Exemple #1
0
    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)
Exemple #2
0
    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)
Exemple #3
0
    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)
Exemple #4
0
    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], [])
Exemple #5
0
    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)
Exemple #6
0
    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"])
Exemple #7
0
    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