{"url":"/dataset/huawei-uk-university-challenge-competition","name":"Huawei-UK-University-Challenge-Competition-2021","full_name":"Huawei UK University Challenge Competition 2021 - TASK2","description_markdown":"<h1>Huawei University Challenge Competition 2021</h1>\r\n<h1>Data Science for Indoor positioning</h1>\r\n\r\n## 2.2 Full Mall Graph Clustering\r\n\r\n### Train\r\n\r\nThe sample training data for this problem is a set of 106981 fingerprints (`task2_train_fingerprints.json`) and some edges between them. We have provided files that indicate three different edge types, all of which should be treated differently. \r\n\r\n`task2_train_steps.csv` indicates edges that connect subsequent steps within a trajectory. These edges should be highly trusted as they indicate a certainty that two fingerprints were recorded from the same floor.\r\n\r\n`task2_train_elevations.csv` indicate the opposite of the steps. These elevations indicate that the fingerprints are almost definitely from a different floor. You can thus extrapolate that if fingerprint $N$ from trajectory $n$ is on a different floor to fingerprint $M$ from trajectory $m$, then all other fingerprints in both trajectories $m$ and $n$ must also be on seperate floors.\r\n\r\n`task2_train_estimated_wifi_distances.csv` are the pre-computed distances that we have calculated using our own distance metric. This metric is imperfect and as such we know that many of these edges will be incorrect (i.e. they will connect two floors together). We suggest that initially you use the edges in this file to construct your initial graph and compute some solution. However, if you get a high score on task1 then you might consider computing your own wifi distances to build a graph.\r\n\r\nYour graph can be at one of two levels of detail, either trajectory level or fingerprint level, you can choose what representation you want to use, but ultimately we want to know the **trajectory clusters**. Trajectory level would have every node as a trajectory and edges between nodes would occur if fingerprints in their trajectories had high similiraty. Fingerprint level would have each fingerprint as a node. You can lookup the trajectory id of the fingerprint using the `task2_train_lookup.json` to convert between representations. \r\n\r\nTo help you debug and train your solution we have provided a ground truth for some of the trajectories in `task2_train_GT.json`. In this file the keys are the trajectory ids (the same as in `task2_train_lookup.json`) and the values are the real floor id of the building.\r\n\r\n### Test\r\n\r\nThe test set is the exact same format as the training set (for a seperate building, we weren't going to make it that easy ;) ) but we haven't included the equivalent ground truth file. This will be withheld to allow us to score your solution.\r\n\r\nPoints to consider\r\n- When doing this on real data we do not know the exact number of floors to expect, so your model will need to decide this for itself as well. For this data, do not expect to find more than 20 floors or less than 3 floors.\r\n- Sometimes in balcony areas the similarity between fingerprints on different floors can be deceivingly high. In these cases it may be wise to try to rely on the graph information rather than the individual similarity (e.g. what is the similarity of the other neighbour nodes to this candidate other-floor node?)\r\n- To the best of our knowledge there are no outlier fingerprints in the data that do not belong to the building. Every fingerprint belongs to a floor\r\n\r\n\r\n\r\n## 2.3 Loading the data\r\n\r\nIn this section we will provide some example code to open the files and construct both types of graph.\r\n\r\n\r\n```python\r\nimport os\r\nimport json\r\nimport csv\r\nimport networkx as nx\r\nfrom tqdm import tqdm\r\n\r\npath_to_data = \"task2_for_participants/train\"\r\n\r\nwith open(os.path.join(path_to_data,\"task2_train_estimated_wifi_distances.csv\")) as f:\r\n    wifi = []\r\n    reader = csv.DictReader(f)\r\n    for line in tqdm(reader):\r\n        wifi.append([line['id1'],line['id2'],float(line['estimated_distance'])])\r\n        \r\nwith open(os.path.join(path_to_data,\"task2_train_elevations.csv\")) as f:\r\n    elevs = []\r\n    reader = csv.DictReader(f)\r\n    for line in tqdm(reader):\r\n        elevs.append([line['id1'],line['id2']])        \r\n\r\nwith open(os.path.join(path_to_data,\"task2_train_steps.csv\")) as f:\r\n    steps = []\r\n    reader = csv.DictReader(f)\r\n    for line in tqdm(reader):\r\n        steps.append([line['id1'],line['id2'],float(line['displacement'])]) \r\n        \r\nfp_lookup_path = os.path.join(path_to_data,\"task2_train_lookup.json\")\r\ngt_path = os.path.join(path_to_data,\"task2_train_GT.json\")\r\n\r\nwith open(fp_lookup_path) as f:\r\n    fp_lookup = json.load(f)\r\n\r\nwith open(gt_path) as f:\r\n    gt = json.load(f)\r\n   \r\n```\r\n\r\n### Fingerprint graph\r\nThis is one way to construct the fingerprint-level graph, where each node in the graph is a fingerprint. We have added edge weights that correspond to the estimated/true distances from the wifi and pdr edges respectively. We have also added elevation edges to indicate this relationship. You might want to explicitly enforce that there are *none* of these edges (or any valid elevation edge between trajectories) when developing your solution. \r\n\r\n\r\n```python\r\nG = nx.Graph()\r\n\r\nfor id1,id2,dist in tqdm(steps):\r\n    G.add_edge(id1, id2, ty = \"s\", weight=dist)\r\n    \r\nfor id1,id2,dist in tqdm(wifi):\r\n    G.add_edge(id1, id2, ty = \"w\", weight=dist)\r\n    \r\nfor id1,id2 in tqdm(elevs):\r\n    G.add_edge(id1, id2, ty = \"e\")\r\n```\r\n\r\n### Trajectory graph\r\nThe trajectory graph is arguably not as simple as you need to think of a way to represent many wifi connections between trajectories. In the example graph below we just take the mean distance as a weight, but is this really the best representation?\r\n\r\n\r\n```python\r\nB = nx.Graph()\r\n\r\n# Get all the trajectory ids from the lookup\r\nvalid_nodes = set(fp_lookup.values())\r\n\r\nfor node in valid_nodes:\r\n    B.add_node(node)\r\n\r\n# Either add an edge or append the distance to the edge data\r\nfor id1,id2,dist in tqdm(wifi):\r\n    if not B.has_edge(fp_lookup[str(id1)], fp_lookup[str(id2)]):\r\n        \r\n        B.add_edge(fp_lookup[str(id1)], \r\n                   fp_lookup[str(id2)], \r\n                   ty = \"w\", weight=[dist])\r\n    else:\r\n        B[fp_lookup[str(id1)]][fp_lookup[str(id2)]]['weight'].append(dist)\r\n        \r\n# Compute the mean edge weight\r\nfor edge in B.edges(data=True):\r\n    B[edge[0]][edge[1]]['weight'] = sum(B[edge[0]][edge[1]]['weight'])/len(B[edge[0]][edge[1]]['weight'])\r\n        \r\n# If you have made a wifi connection between trajectories with an elev, delete the edge\r\nfor id1,id2 in tqdm(elevs):\r\n    if B.has_edge(fp_lookup[str(id1)], fp_lookup[str(id2)]):\r\n        B.remove_edge(fp_lookup[str(id1)], \r\n                      fp_lookup[str(id2)])\r\n```","description_withheld":null,"homepage":"https://github.com/kahramankostas/IPIN2025/tree/main/task2_for_participants","introduced_date":null,"introduced_date_note":null,"introduced_by":null,"license":null,"modalities":[{"name":"Graphs","url":"/datasets/modality/graphs"}],"tasks":[],"languages":[{"name":"English","url":"/datasets/language/english"}],"variants":["Huawei-UK-University-Challenge-Competition-2021"],"data_loaders":[{"repo":"https://github.com/kahramankostas/ipin2025","url":"https://github.com/kahramankostas/ipin2025","frameworks":[]}],"num_papers_in_archive":0,"source":{"archive":"pwc-archive (Hugging Face), CC BY-SA 4.0","snapshot":"2025-07-28"},"benchmarks":[],"papers_with_a_benchmark_row":[],"syntology_totals":{"read_at":"2026-09-25T09:33:49+00:00","papers_with_samples":0,"samples_harvested":0,"samples_ran":0,"samples_unverified":0,"pointer_only_for_licence":0,"papers_with_no_sample_that_ran":0,"note":"the per-paper counts above, summed; not a rate"},"papers_note":"The archive never published its papers-using-dataset list; these are papers with a leaderboard row on this dataset's benchmarks."}