def test_connect(self): # TEST - undefined connections return None g = world.Graph(3) g.finalize() self.assertEqual(g.cost(0, 1), None) # TEST - defined connections are bidirectional g = world.Graph(3) g.connect(0, 1, 10) g.finalize() self.assertEqual(g.cost(0, 1), 10) self.assertEqual(g.cost(1, 0), 10)
def test_pathgen(self): g = world.Graph(4) g.connect(0, 1, 5) g.connect(1, 2, 5) g.connect(2, 3, 5) g.connect(3, 0, 5) g.connect(1, 3, 5) g.finalize() # TEST - permutation path generation works as intended expected_paths = [ [1, 0, 2, 3], [1, 0, 3, 2], [1, 2, 0, 3], [1, 2, 3, 0], [1, 3, 2, 0], [1, 3, 0, 2] ] permute_paths = g.permute_paths(1) self.assertCountEqual(permute_paths, expected_paths) # TEST - world correctly computes lengths of paths in list form c = g.path_cost([0, 1, 2, 3]) self.assertEqual(c, 15) c = g.path_cost([0, 3, 2, 1]) self.assertEqual(c, 15) c = g.path_cost([0, 2, 1]) self.assertEqual(c, 15)
def test(self): g = world.Graph(6) g.finalize() e0 = world.Event("box", [0, 1, 2], 0.5) e1 = world.Event("box", [3], 0.3) e2 = world.Event("box", [4, 5], 0.2) d0 = world.Distribution([e0, e1, e2]) e3 = world.Event("plant", [2, 4], 0.5) e4 = world.Event("plant", [1, 3], 0.5) d1 = world.Distribution([e3, e4]) e5 = world.Event("robot", [1], 1.0) d2 = world.Distribution([e5]) w = world.World(g, [d0, d1, d2]) w.finalize() # TEST - world returns the correct probabilities of object occurrence self.assertEqual(w.objs, ["box", "plant", "robot"]) self.assertEqual(w.prob_obj("box", 0), 0.5) self.assertEqual(w.prob_obj("box", 5), 0.2) self.assertEqual(w.prob_obj("plant", 2), 0.5) self.assertEqual(w.prob_obj("plant", 0), 0.0) self.assertEqual(w.prob_obj("robot", 0), 0.0) self.assertEqual(w.prob_obj("robot", 1), 1.0) # TEST - world returns the correct potential objects to find at a loc self.assertEqual(w.pot_objs_at(0), ["box"]) self.assertEqual(w.pot_objs_at(2), ["box", "plant"]) self.assertEqual(w.pot_objs_at(1), ["box", "plant", "robot"]) # TEST - populated world contains the specified objects box_count = 0 plant_count = 0 robot_count = 0 w.populate() for loc in w.graph.nodes: objs = w.objs_at(loc) for obj in objs: if obj == "box": self.assertTrue(loc < 6) box_count += 1 elif obj == "plant": self.assertTrue(1 <= loc <= 4) plant_count += 1 elif obj == "robot": self.assertTrue(loc == 1) robot_count += 1 else: self.assertTrue(False) self.assertTrue(box_count >= 1) self.assertTrue(plant_count == 2) self.assertTrue(robot_count == 1)
def test_finalize(self): g = world.Graph(5) g.connect(0, 1, 5) g.connect(1, 2, 5) g.connect(1, 3, 5) g.finalize() # TEST - connection mapping is created correctly self.assertEqual(g.conns[1], [0, 2, 3]) self.assertEqual(g.conns[3], [1]) self.assertEqual(g.conns[4], [])
def test_dijkstra(self): g = world.Graph(4) g.connect(0, 1, 2) g.connect(1, 2, 2) g.connect(2, 3, 2) g.connect(0, 3, 100) g.finalize() # TEST - Dijkstra's works as intended path = g.find_shortest_path(0, 3) self.assertEqual(path.nodes, [0, 1, 2, 3]) self.assertEqual(path.cost, 6)
def test(self): g = world.Graph(6) g.finalize() e0 = world.Event("box", [0], 0.5) e1 = world.Event("box", [1], 0.3) e2 = world.Event("box", [2], 0.2) d0 = world.Distribution([e0, e1, e2]) e3 = world.Event("plant", [3], 0.5) e4 = world.Event("plant", [4], 0.5) d1 = world.Distribution([e3, e4]) w = world.World(g, [d0, d1]) w.finalize() a = world.ArrangementSpace(w) # TEST - arrangement space returns the correct event probabilities self.assertEqual(a.prob_obj("box", 0), 0.5) self.assertEqual(a.prob_obj("box", 1), 0.3) self.assertEqual(a.prob_obj("box", 2), 0.2) self.assertEqual(a.prob_obj("box", 3), 0.0) self.assertEqual(a.prob_obj("plant", 3), 0.5) self.assertEqual(a.pot_objs_at(0), ["box"]) self.assertEqual(a.pot_objs_at(3), ["plant"]) self.assertEqual(a.pot_objs_at(5), []) # TEST - observations update the arrangement space accordingly a.observe("box", 0, False) self.assertEqual(a.prob_obj("box", 0), 0) self.assertEqual(a.prob_obj("box", 1), 0.6) self.assertEqual(a.prob_obj("box", 2), 0.4) self.assertEqual(a.prob_obj("box", 3), 0.0) self.assertEqual(a.pot_objs_at(0), []) a.observe("plant", 3, True) self.assertEqual(a.prob_obj("plant", 3), 1.0) self.assertEqual(a.prob_obj("plant", 4), 0.0) self.assertEqual(a.pot_objs_at(3), ["plant"]) self.assertEqual(a.pot_objs_at(4), []) a.observe("box", 1, False) self.assertEqual(a.prob_obj("box", 1), 0.0) self.assertEqual(a.prob_obj("box", 2), 1.0) self.assertEqual(a.pot_objs_at(1), []) self.assertEqual(a.pot_objs_at(2), ["box"])
def test_placement(self): g = world.Graph(4) g.finalize() e0 = world.Event("box", [0], 0.6) e1 = world.Event("box", [1], 0.3) e2 = world.Event("box", [2], 0.1) distr = world.Distribution([e0, e1, e2]) # TEST - objs are distributed with approx. the expected probabilities placements = [0] * len(g.nodes) n = 1000 for i in range(n): locs = distr.place().locs placements[locs[0]] += 1 self.assertTrue(util.approx(placements[0] / n, e0.prob, 0.1)) self.assertTrue(util.approx(placements[1] / n, e1.prob, 0.1)) self.assertTrue(util.approx(placements[2] / n, e2.prob, 0.1)) self.assertTrue(placements[3] == 0)
def parse_world(fname): """Parses a scavenger hunt world from a datfile. Parameters ---------- fname : str source file name Returns ------- world.World finalized scavenger hunt world list of str scavenger hunt str start location name """ src = open(fname, "r") sec = None start_loc = None conns = [] # 3-tuples (from, to, cost) nodes = {} # User-specified loc names -> integer IDs node_count = 0 distrs = [] hunt = [] for line in src.readlines(): # Blank lines and comments line = line.strip() if len(line) == 0 or line[0] == '#': continue # Section header line if line[0] == '[': sec = line[1:line.find(']')] continue # Map section if sec == "map": args = line.split() assert len(args) == 3 n_from, n_to = args[0], args[1] # Parse for starting location if '*' in n_from: n_from = n_from.replace('*', '') if start_loc is None: start_loc = n_from elif '*' in n_to: n_to = n_to.replace('*', '') if start_loc is None: start_loc = n_to cost = float(args[2]) if n_from not in nodes: nodes[n_from] = node_count node_count += 1 if n_to not in nodes: nodes[n_to] = node_count node_count += 1 conns.append((n_from, n_to, cost)) # Distribution section elif sec == "distr": args = line.split() assert len(args) > 2 obj = args[0] events = [] ind = 1 if obj not in hunt: hunt.append(obj) while ind < len(args): locs = [] prob_ind = ind while args[prob_ind] in nodes: locs.append(nodes[args[prob_ind]]) prob_ind += 1 prob_arg = args[prob_ind] if '/' in prob_arg: frac = prob_arg.split('/') prob = float(frac[0]) / float(frac[1]) else: prob = float(prob_arg) events.append(world.Event(obj, locs, prob)) ind = prob_ind + 1 distrs.append(world.Distribution(events)) else: assert False src.close() # Build graph g = world.Graph(node_count) for conn in conns: id_from, id_to, cost = nodes[conn[0]], nodes[conn[1]], conn[2] g.connect(id_from, id_to, cost) g.name_ids[conn[0]] = id_from g.name_ids[conn[1]] = id_to g.finalize() # Build world w = world.World(g, distrs) w.finalize() return w, hunt, start_loc