def test_comp_creation_with_factory_method():
    d = Domain("d", "", ["R", "G"])
    v1 = Variable("v1", d)
    v2 = Variable("v2", d)
    c1 = constraint_from_str("c1", "10 if v1 == v2 else 0", [v1, v2])
    graph = build_computation_graph(None, constraints=[c1], variables=[v1, v2])

    comp_node = graph.computation("c1")
    algo_def = AlgorithmDef.build_with_default_param("maxsum")
    comp_def = ComputationDef(comp_node, algo_def)

    comp = build_computation(comp_def)
    assert comp is not None
    assert comp.name == "c1"
    assert comp.factor == c1

    comp_node = graph.computation("v1")
    algo_def = AlgorithmDef.build_with_default_param("maxsum")
    comp_def = ComputationDef(comp_node, algo_def)

    comp = build_computation(comp_def)
    assert comp is not None
    assert comp.name == "v1"
    assert comp.variable.name == "v1"
    assert comp.factors == ["c1"]
    def test_current_local_cost_3_ary(self):
        x1 = Variable("x1", list(range(2)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", [1])

        @AsNAryFunctionRelation(x1, x2, x3)
        def phi(x1_, x2_, x3_):
            return x1_ + x2_ + x3_

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.__value__ = 1
        computation._neighbors_values["x2"] = 0
        computation._neighbors_values["x3"] = 1

        computation2 = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation2.__value__ = 0
        computation2._neighbors_values["x2"] = 0
        computation2._neighbors_values["x3"] = 1
        self.assertEqual(computation._current_local_cost(), 2)
        self.assertEqual(computation2._current_local_cost(), 1)
示例#3
0
def test_algo_def():

    a = AlgorithmDef("maxsum", {"stability": 0.01}, "min")

    assert a.algo == "maxsum"
    assert a.mode == "min"
    assert "stability" in a.param_names()
    assert a.param_value("stability") == 0.01
    def test_enter_offer_state(self):
        x1 = Variable("x1", list(range(2)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", list(range(2)))

        @AsNAryFunctionRelation(x1, x2, x3)
        def phi(x1_, x2_, x3_):
            return x1_ + x2_ + x3_

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi]),
                AlgorithmDef.build_with_default_param("mgm2", mode="max"),
            ))
        computation.message_sender = DummySender()

        computation._postponed_msg["offer"] = [
            ("x2", Mgm2OfferMessage({(1, 1): 5}, is_offering=True), 1)
        ]

        computation._enter_state("offer")

        self.assertEqual(computation._state, "offer")
        self.assertEqual(computation._postponed_msg["offer"], [])
        self.assertEqual(computation._offers,
                         [("x2", Mgm2OfferMessage({(1, 1): 5}, True))])
    def test_compute_offers_max_mode(self):
        x1 = Variable("x1", list(range(2)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", list(range(2)))

        @AsNAryFunctionRelation(x1, x2, x3)
        def phi(x1_, x2_, x3_):
            if x1_ == x3_:
                return 2
            elif x1_ == x2_:
                return 1
            return 0

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi]),
                AlgorithmDef.build_with_default_param("mgm2", mode="max"),
            ))

        computation._neighbors_values = {"x2": 0, "x3": 0}
        computation._partner = x2
        computation.__value__ = 1
        computation.__cost__ = 0
        offers = computation._compute_offers_to_send()

        self.assertEqual(offers, {(0, 0): -2, (0, 1): -2, (1, 1): -1})
def test_build_computation_max_mode():
    v1 = Variable('v1', [0, 1, 2, 3, 4])
    n1 = VariableComputationNode(v1, [])
    comp_def = ComputationDef(
        n1, AlgorithmDef.build_with_default_param('dsa', mode='max'))
    c = DsaComputation(comp_def)
    assert c.mode == 'max'
    def test_gain_not_all_received(self):
        x1 = Variable("x1", list(range(3)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", list(range(2)))

        @AsNAryFunctionRelation(x1, x2)
        def phi(x1_, x2_):
            if x1_ == x2_:
                return 1
            return 0

        @AsNAryFunctionRelation(x1, x3)
        def psi(x1_, x3_):
            if x1_ == x3_:
                return 8
            return 0

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi, psi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.message_sender = DummySender()

        computation._state = "gain"
        computation.on_gain_msg("x2", Mgm2GainMessage(5), 1)

        self.assertEqual(computation._neighbors_gains, {"x2": 5})
def test_select_and_send_random_value_when_starting():
    # When starting, a DSA computation select a random value and send it to
    # all neighbors
    v1 = Variable('v1', [0, 1, 2, 3, 4])
    v2 = Variable('v2', [0, 1, 2, 3, 4])
    v3 = Variable('v3', [0, 1, 2, 3, 4])

    @AsNAryFunctionRelation(v1, v2, v3)
    def c1(v1_, v2_, v3_):
        return abs(v1_ - v2_ + v3_)

    node = VariableComputationNode(v1, [c1])
    comp_def = ComputationDef(node,
                              AlgorithmDef.build_with_default_param('dsa'))

    computation = DsaComputation(comp_def=comp_def)
    message_sender = MagicMock()
    computation.message_sender = message_sender

    computation.start()

    assert computation.current_value in v1.domain
    expected_message = DsaMessage(computation.current_value)
    print("message_sender.mock_calls", message_sender.mock_calls)
    message_sender.assert_has_calls([
        call('v1', 'v2', expected_message, None, None),
        call('v1', 'v3', expected_message, None, None)
    ],
                                    any_order=True)
    def test_go_reject_no_postponed_value_message(self):
        x1 = Variable("x1", list(range(3)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", list(range(2)))

        @AsNAryFunctionRelation(x1, x2)
        def phi(x1_, x2_):
            if x1_ == x2_:
                return 1
            return 0

        @AsNAryFunctionRelation(x1, x3)
        def psi(x1_, x3_):
            if x1_ == x3_:
                return 8
            return 0

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi, psi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.message_sender = DummySender()

        computation._neighbors_values = {"x2": 1, "x3": 1}
        computation.__value__ = 1
        computation._potential_value = 0
        computation._state = "go?"
        # from Response message or accepted offer

        computation._handle_go_message("x3", Mgm2GoMessage(False))

        self.assertEqual(computation._state, "value")
        self.assertEqual(computation.__value__, 1)
        self.test_clear_agent()
def test_receive_one_neighbor_dcop_computation():

    comp_def = ComputationDef(ComputationNode("test", neighbors=["bar"]),
                              AlgorithmDef("fake", {}))
    c = SynchDcopC("test", comp_def)
    c.on_new_cycle = MagicMock()
    c.start()

    # First cycle, c receives a message from its single neighbor,
    # on_cycle_message must be called.
    msg1 = FooMsg(1)
    # This is automatically done when sending from a Synchronous Computation:
    msg1.cycle_id = 0
    c.on_message("bar", msg1, 42)
    assert c.cycle_count == 1
    c.on_new_cycle.assert_any_call({"bar": (msg1, 42)}, 0)

    # Second cycle, c receives a message from its single neighbor,
    # on_cycle_message must be called again.
    c.on_new_cycle.reset_mock()
    msg2 = FooMsg(2)
    msg2.cycle_id = 1
    c.on_message("bar", msg2, 43)
    c.on_new_cycle.assert_any_call({"bar": (msg2, 43)}, 1)
    assert c.cycle_count == 2
示例#11
0
def test_building_algodef_with_provided_and_default_params():

    a = AlgorithmDef.build_with_default_param("dsa", {"variant": "B"},
                                              mode="max")

    assert a.params["variant"] == "B"  # provided param
    assert a.params["probability"] == 0.7  # default param
    assert a.algo == "dsa"
    assert a.mode == "max"
示例#12
0
def test_from_repr():

    a = AlgorithmDef("maxsum", {"stability": 0.01}, "min")

    r = simple_repr(a)
    a2 = from_repr(r)

    assert a == a2
    assert a2.param_value("stability") == 0.01
def test_repr_dsa_class():
    variable = Variable('a', [0, 1, 2, 3, 4])
    c1 = UnaryFunctionRelation('c1', variable, lambda x: abs(x - 2))

    computation = DsaComputation(
        ComputationDef(VariableComputationNode(variable, [c1]),
                       AlgorithmDef.build_with_default_param('dsa')))

    assert repr(computation) == "dsa.DsaComputation(a)"
示例#14
0
def test_simple_repr():

    a = AlgorithmDef("maxsum", {"stability": 0.01}, "min")

    r = simple_repr(a)

    assert r["algo"] == "maxsum"
    assert r["mode"] == "min"
    assert r["params"]["stability"] == 0.01
def test_build_computation_default_params():
    v1 = Variable('v1', [0, 1, 2, 3, 4])
    n1 = VariableComputationNode(v1, [])
    comp_def = ComputationDef(n1, AlgorithmDef.build_with_default_param('dsa'))
    c = DsaComputation(comp_def)
    assert c.mode == 'min'
    assert c.variant == 'B'
    assert c.stop_cycle == 0
    assert c.probability == 0.7
def test_1_unary_constraint_means_no_neighbors():
    variable = Variable('a', [0, 1, 2, 3, 4])
    c1 = UnaryFunctionRelation('c1', variable, lambda x: abs(x - 2))

    node = VariableComputationNode(variable, [c1])
    comp_def = ComputationDef(node,
                              AlgorithmDef.build_with_default_param('dsa'))

    computation = DsaComputation(comp_def=comp_def)
    assert len(computation.neighbors) == 0
    def test_go_accept_with_postponed_value_message(self):
        x1 = Variable("x1", list(range(3)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", list(range(2)))

        @AsNAryFunctionRelation(x1, x2)
        def phi(x1_, x2_):
            if x1_ == x2_:
                return 1
            return 0

        @AsNAryFunctionRelation(x1, x3)
        def psi(x1_, x3_):
            if x1_ == x3_:
                return 8
            return 0

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi, psi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.message_sender = DummySender()

        computation._neighbors_values = {"x2": 1, "x3": 1}
        computation.__value__ = 1
        computation.__cost__ = 9
        computation._state = "go?"
        computation._postponed_msg["value"] = [("x2", Mgm2ValueMessage(1), 1)]
        # from Response message or accepted offer
        computation._potential_gain = 10
        computation._potential_value = 0

        computation.on_go_msg("x3", Mgm2GoMessage(True), 1)
        # Common tests
        self.assertEqual(computation._state, "value")
        self.assertEqual(computation._potential_gain, 0)
        self.assertIsNone(computation._potential_value)
        self.assertEqual(computation._neighbors_values, {"x2": 1})
        self.assertEqual(computation._neighbors_gains, dict())
        self.assertEqual(computation._offers, [])
        self.assertIsNone(computation._partner)
        self.assertEqual(computation.__nb_received_offers__, 0)
        self.assertFalse(computation._committed)
        self.assertFalse(computation._is_offerer)
        self.assertFalse(computation._can_move)

        # If cannot move
        self.assertEqual(computation.current_value, 1)
        # If can move
        computation._can_move = True
        computation._state = "go?"
        computation._potential_value = 0
        computation.on_go_msg("x3", Mgm2GoMessage(True), 1)
        self.assertEqual(computation.current_value, 0)
def get_computation_instance(graph, name):

    # Get the computation node for x1
    comp_node = graph.computation(name)

    # Create the ComputationDef and computation instance
    algo_def = AlgorithmDef.build_with_default_param("ncbb")
    comp_def = ComputationDef(comp_node, algo_def)
    comp = NcbbAlgo(comp_def)
    comp._msg_sender = MagicMock()

    return comp
def test_fallback_memory_footprint_from_classic_import():
    # use dsatuto as is has no computation_memory function defined
    import pydcop.algorithms.dsatuto as dsa_module

    v1 = Variable("v1", [1, 2])
    comp_def = ComputationDef(
        VariableComputationNode(v1, []),
        AlgorithmDef.build_with_default_param("dsatuto"),
    )
    comp = dsa_module.DsaTutoComputation(comp_def)

    assert comp.footprint() == 1
    def test_clear_agent(self):
        x1 = Variable("x1", list(range(3)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", list(range(2)))

        @AsNAryFunctionRelation(x1, x2)
        def phi(x1_, x2_):
            if x1_ == x2_:
                return 1
            return 0

        @AsNAryFunctionRelation(x1, x3)
        def psi(x1_, x3_):
            if x1_ == x3_:
                return 8
            return 0

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi, psi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.message_sender = DummySender()

        computation._neighbors_values = {"x2": 1, "x3": 1}
        computation.__value__ = 1
        computation.__nb_received_offers__ = 2
        computation._partner = x3
        computation._state = "go?"
        computation._potential_gain = 10
        computation._potential_value = 10
        computation._neighbors_values = {"x2": 1, "x3": 0}
        computation._neighbors_gains = {"x2": 5, "x3": 1}
        computation._offers = [(1, 1, "x2")]
        computation._committed = True
        computation._is_offerer = True
        computation._can_move = True

        computation._clear_agent()

        self.assertEqual(computation._potential_gain, 0)
        self.assertEqual(computation._neighbors_values, dict())
        self.assertEqual(computation._neighbors_gains, dict())
        self.assertEqual(computation._offers, [])
        self.assertIsNone(computation._partner)
        self.assertEqual(computation.__nb_received_offers__, 0)
        self.assertFalse(computation._committed)
        self.assertFalse(computation._is_offerer)
        self.assertFalse(computation._can_move)
        self.assertIsNone(computation._potential_value)
        self.assertIsNotNone(computation.current_value)
    def test_best_unary(self):
        x = Variable("x", list(range(5)))
        phi = UnaryFunctionRelation("phi", x, lambda x_: 1
                                    if x_ in [0, 2, 3] else 0)

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x, [phi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.__value__ = 0
        bests, best = computation._compute_best_value()

        self.assertEqual(best, 0)
        self.assertEqual(bests, [1, 4])
def test_3ary_constraint_2_neighbors():
    v1 = Variable('v1', [0, 1, 2, 3, 4])
    v2 = Variable('v2', [0, 1, 2, 3, 4])
    v3 = Variable('v3', [0, 1, 2, 3, 4])

    @AsNAryFunctionRelation(v1, v2, v3)
    def c1(v1_, v2_, v3_):
        return abs(v1_ - v2_ + v3_)

    node = VariableComputationNode(v1, [c1])
    comp_def = ComputationDef(node,
                              AlgorithmDef.build_with_default_param('dsa'))

    computation = DsaComputation(comp_def=comp_def)
    assert len(computation.neighbors) == 2
def test_cycle_id_is_added_when_using_post_to_all_neighbors_dcop_computation():

    comp_def = ComputationDef(
        ComputationNode("test", neighbors=["bar", "yup"]),
        AlgorithmDef("fake", {}))
    c = SynchDcopC("test", comp_def)
    c.start()

    c.post_to_all_neighbors(FooMsg(1))

    expected = FooMsg(1)
    expected.cycle_id = 0

    c.message_sender.assert_any_call("test", "yup", expected, None, None)
    c.message_sender.assert_any_call("test", "bar", expected, None, None)
    def test_value_all_neighbors_received(self):
        x1 = Variable("x1", list(range(2)))
        x2 = Variable("x2", list(range(2)))

        @AsNAryFunctionRelation(x1, x2)
        def phi(x1_, x2_):
            return x1_ + x2_

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.message_sender = DummySender()
        computation._state = "value"
        computation.__value__ = 1
        computation.on_value_msg("x2", Mgm2ValueMessage(0), 1)

        self.assertEqual(computation._state, "offer")
        self.assertEqual(computation._neighbors_values["x2"], 0)
        self.assertEqual(computation._potential_gain, 1)
        self.assertEqual(computation._potential_value, 0)

        computation2 = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi]),
                AlgorithmDef.build_with_default_param("mgm2", mode="max"),
            ))
        computation2.message_sender = DummySender()
        computation2._state = "value"
        computation2.__value__ = 1
        computation2.on_value_msg("x2", Mgm2ValueMessage(0), 1)
        self.assertEqual(computation2._state, "offer")
        self.assertEqual(computation2._neighbors_values["x2"], 0)
        self.assertEqual(computation2._potential_gain, 0)
        self.assertEqual(computation2._potential_value, 1)
def test_memory_footprint_from_classic_import():
    # use maxsum as is has a computation_memory function defined
    import pydcop.algorithms.amaxsum as maxsum_module
    from pydcop.computations_graph.factor_graph import (
        VariableComputationNode as FGVariableComputationNode, )

    v1 = Variable("v1", [1, 2])
    comp_def = ComputationDef(
        FGVariableComputationNode(v1, []),
        AlgorithmDef.build_with_default_param("amaxsum"),
    )
    comp = maxsum_module.MaxSumVariableComputation(comp_def=comp_def)

    # The variable has no neighbors : footprint is 0
    assert comp.footprint() == 0
    def test_current_local_cost_unary(self):
        x = Variable("x", list(range(5)))
        #        x2 = Variable('x2', list(range(5)))

        #        @AsNAryFunctionRelation(x, x2)
        #       def phi(x1_):
        #          return x1_
        phi = UnaryFunctionRelation("phi", x, lambda x_: 1
                                    if x_ in [0, 2, 3] else 0)
        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x, [phi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation.__value__ = 0
        computation2 = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x, [phi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        computation2.__value__ = 1

        self.assertEqual(computation._current_local_cost(), 1)
        self.assertEqual(computation2._current_local_cost(), 0)
    def test_find_best_offer_max_mode_one_offerer(self):
        x1 = Variable("x1", list(range(2)))
        x2 = Variable("x2", list(range(2)))
        x3 = Variable("x3", list(range(2)))
        x4 = Variable("x4", list(range(2)))

        @AsNAryFunctionRelation(x1, x2, x3)
        def phi(x1_, x2_, x3_):
            if x1_ == x3_:
                return 2
            elif x1_ == x2_:
                return 1
            return 0

        @AsNAryFunctionRelation(x1, x4)
        def psi(x1_, x4_):
            if x1_ == x4_:
                return 1
            return 0

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi, psi]),
                AlgorithmDef.build_with_default_param("mgm2", mode="max"),
            ))

        computation._neighbors_values = {"x2": 0, "x3": 1, "x4": 1}
        computation.__value__ = 0
        computation.__cost__ = 1

        bests, best_gain = computation._find_best_offer([("x2", {
            (0, 0): -1,
            (0, 1): -5,
            (1, 0): -3
        })])
        # global gain: -1 -5 -5

        bests2, best_gain2 = computation._find_best_offer([("x2", {
            (0, 0): -1,
            (0, 1): -5,
            (1, 0): -6
        })])
        # global gain: -1 -5 -5

        self.assertEqual(bests, [(0, 1, "x2")])
        self.assertEqual(best_gain, -5)
        self.assertEqual(set(bests2), {(0, 1, "x2"), (1, 0, "x2")})
        self.assertEqual(best_gain2, -5)
def test_footprint_on_computation_object():
    v1 = Variable('v1', [0, 1, 2, 3, 4])
    v2 = Variable('v2', [0, 1, 2, 3, 4])
    c1 = relation_from_str('c1', '0 if v1 == v2 else  1', [v1, v2])
    n1 = VariableComputationNode(v1, [c1])
    n2 = VariableComputationNode(v2, [c1])
    comp_def = ComputationDef(
        n1, AlgorithmDef.build_with_default_param('dsa', mode='min'))
    c = DsaComputation(comp_def)

    # Must fix unit size otherwise the tests fails when we change the default
    # value
    dsa.UNIT_SIZE = 1

    footprint = c.footprint()
    assert footprint == 1
def test_build_computation_with_params():
    v1 = Variable('v1', [0, 1, 2, 3, 4])
    n1 = VariableComputationNode(v1, [])
    comp_def = ComputationDef(
        n1,
        AlgorithmDef.build_with_default_param('dsa',
                                              mode='max',
                                              params={
                                                  'variant': 'C',
                                                  'stop_cycle': 10,
                                                  'probability': 0.5
                                              }))
    c = DsaComputation(comp_def)
    assert c.mode == 'max'
    assert c.variant == 'C'
    assert c.stop_cycle == 10
    assert c.probability == 0.5
    def test_binary_func(self):
        x1 = Variable("x1", list(range(2)))
        x2 = Variable("x2", list(range(2)))

        @AsNAryFunctionRelation(x1, x2)
        def phi(x1_, x2_):
            return x1_ + x2_

        computation = Mgm2Computation(
            ComputationDef(
                VariableComputationNode(x1, [phi]),
                AlgorithmDef.build_with_default_param("mgm2"),
            ))
        self.assertEqual(computation._compute_cost(**{"x1": 0, "x2": 0}), 0)
        self.assertEqual(computation._compute_cost(**{"x1": 0, "x2": 1}), 1)
        self.assertEqual(computation._compute_cost(**{"x1": 1, "x2": 0}), 1)
        self.assertEqual(computation._compute_cost(**{"x1": 1, "x2": 1}), 2)