def test_computation_memory_two_constraints(): v1 = Variable("v1", list(range(10))) v2 = Variable("v2", list(range(10))) v3 = Variable("v3", list(range(10))) v4 = Variable("v4", list(range(10))) c1 = constraint_from_str("c1", " v1 == v2", [v1, v2]) c2 = constraint_from_str("c2", " v1 == v3", [v1, v3]) c3 = constraint_from_str("c3", " v1 == v4", [v1, v4]) v1_node = VariableComputationNode(v1, [c1, c2, c3]) # here, we have 3 edges , one for each constraint assert mgm2.computation_memory(v1_node) == mgm2.UNIT_SIZE * 3 * 2
def three_variables_pb(): # a very simple problem with 3 variables x1 = Variable("x1", ["R", "B"]) x2 = Variable("x2", ["R", "B"]) x3 = Variable("x3", ["R", "B"]) diff_x1_x2 = constraint_from_str("c1", "1 if x1 == x2 else 0", [x1, x2]) diff_x1_x3 = constraint_from_str("c2", "1 if x1 == x3 else 0", [x1, x3]) # build the pseudo-tree for this problem g = build_computation_graph(None, constraints=[diff_x1_x2, diff_x1_x3], variables=[x1, x2, x3]) return g
def test_communication_load(): v1 = Variable('v1', list(range(10))) v2 = Variable('v2', list(range(10))) v3 = Variable('v3', list(range(10))) v4 = Variable('v4', list(range(10))) c1 = constraint_from_str('c1', ' v1 == v2', [v1, v2]) c2 = constraint_from_str('c2', ' v1 == v3', [v1, v3]) c3 = constraint_from_str('c3', ' v1 == v4', [v1, v4]) v1_node = VariableComputationNode(v1, [c1, c2, c3]) assert mgm2.UNIT_SIZE * 10 * 10 * 3 + mgm2.HEADER_SIZE \ == mgm2.communication_load(v1_node, 'v2')
def test_computation_memory_two_constraints(): v1 = Variable('v1', list(range(10))) v2 = Variable('v2', list(range(10))) v3 = Variable('v3', list(range(10))) v4 = Variable('v4', list(range(10))) c1 = constraint_from_str('c1', ' v1 == v2', [v1, v2]) c2 = constraint_from_str('c2', ' v1 == v3', [v1, v3]) c3 = constraint_from_str('c3', ' v1 == v4', [v1, v4]) v1_node = VariableComputationNode(v1, [c1, c2, c3]) # here, we have 3 edges , one for each constraint assert dsa.computation_memory(v1_node) == dsa.UNIT_SIZE * 3
def test_communication_load(): v1 = Variable("v1", list(range(10))) v2 = Variable("v2", list(range(10))) v3 = Variable("v3", list(range(10))) v4 = Variable("v4", list(range(10))) c1 = constraint_from_str("c1", " v1 == v2", [v1, v2]) c2 = constraint_from_str("c2", " v1 == v3", [v1, v3]) c3 = constraint_from_str("c3", " v1 == v4", [v1, v4]) v1_node = VariableComputationNode(v1, [c1, c2, c3]) assert mgm2.UNIT_SIZE * 10 * 10 * 3 + mgm2.HEADER_SIZE == mgm2.communication_load( v1_node, "v2")
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 build_models(light_domain, lights, max_model_size, model_count): # Models: for each model # * one constraint depends on 2 =< k =<max_model_size lights # * one variable , # Example: # function: 0 if 0.7 * l_d1 + 0.5 * l_d2 + 0.3 * l_lv3 == mv_desk else # 1000 # function: '0 if 10 * abs(m0 - ( 0.2 * l1 + 0.5 * l2 + 0.8 * l3 )) < 3 else 1000' models = {} models_var = {} for j in range(model_count): model_var = Variable("m{}".format(j), domain=light_domain) models_var[model_var.name] = model_var model_size = randint(2, max_model_size) model_lights = () light_expression_parts = [] for k, model_light in enumerate(sample(list(lights), model_size)): impact = randint(1, 7) / 10 light_expression_parts.append(" {} * {}".format(model_light, impact)) # model_lights.append((model_light, impact)) # model_light. light_expression = " + ".join(light_expression_parts) model_expression = f"0 if 10* abs({model_var.name} - ({light_expression})) < 5 else 10000 ".format( light_expression, model_var.name ) model = constraint_from_str( "c_m{}".format(j), expression=model_expression, all_variables=list(lights.values()) + [model_var], ) models[model.name] = model return models_var, models
def test_create_ok(self): d1 = Domain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) f1 = constraint_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, [f1]) cf1 = FactorComputationNode(f1) cg = ComputationsFactorGraph([cv1], [cf1])
def test_build_graph_from_variables_constraints(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) c1 = constraint_from_str('c1', 'v1 * 0.5 + v2 - v3', [v1, v2, v3]) graph = build_computation_graph(variables=[v1, v2, v3], constraints=[c1])
def generate_unary_intentional_constraint(variable: Variable, un_range: float): value = random.uniform(-un_range, un_range) constraint = constraint_from_str( name=f"cu_{variable.name}", expression=f" -{value} if {variable.name} == 1 else {value}", all_variables=[variable], ) return constraint
def build_pb(): # A toy problem with 5 variables and 5 constraints. # The objective here is to have a problem that is simple enough to be solved # manually and used in test, but that is representative enough to be meaningful. v_a = Variable("vA", ["R", "G"]) v_b = Variable("vB", ["R", "G"]) v_c = Variable("vC", ["R", "G"]) v_d = Variable("vD", ["R", "G"]) c1 = constraint_from_str( "c1", "{('R', 'G'): 8, " " ('R', 'R'): 5, " " ('G', 'G'): 3, " " ('G', 'R'): 20 " "}[(vA, vB)]", [v_a, v_b], ) c2 = constraint_from_str( "c2", "{('R', 'G'): 10, " " ('R', 'R'): 5, " " ('G', 'G'): 3, " " ('G', 'R'): 20 " "}[(vA, vC)]", [v_a, v_c], ) c3 = constraint_from_str( "c3", "{('R', 'G'): 4, " " ('R', 'R'): 5, " " ('G', 'G'): 3, " " ('G', 'R'): 3 " "}[(vB, vC)]", [v_b, v_c], ) c4 = constraint_from_str( "c4", "{('R', 'G'): 8, " " ('R', 'R'): 3, " " ('G', 'G'): 3, " " ('G', 'R'): 10 " "}[(vB, vD)]", [v_b, v_d], ) return [v_a, v_b, v_c, v_d], [c1, c2, c3, c4]
def test_computation_memory_one_constraint(): v1 = Variable("v1", list(range(10))) v2 = Variable("v2", list(range(10))) v3 = Variable("v3", list(range(10))) c1 = constraint_from_str("c1", " v1 + v2 == v3", [v1, v2, v3]) v1_node = VariableComputationNode(v1, [c1]) # here, we have an hyper-edges with 3 vertices assert mgm2.computation_memory(v1_node) == mgm2.UNIT_SIZE * 2 * 2
def test_create_node_with_custom_name(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) c1 = constraint_from_str('c1', 'v1 * 0.5', [v1]) n1 = VariableComputationNode(v1, [c1], name='foo') assert v1 == n1.variable assert n1.name == 'foo'
def test_computation_memory_one_constraint(): v1 = Variable('v1', list(range(10))) v2 = Variable('v2', list(range(10))) v3 = Variable('v3', list(range(10))) c1 = constraint_from_str('c1', ' v1 + v2 == v3', [v1, v2, v3]) v1_node = VariableComputationNode(v1, [c1]) # here, we have an hyper-edges with 3 vertices assert dsa.computation_memory(v1_node) == dsa.UNIT_SIZE * 2
def test_raise_when_duplicate_computation_name(self): d1 = Domain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) # here we create a relation with the same name as the variable f1 = constraint_from_str('v1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1) self.assertRaises(KeyError, ComputationsFactorGraph, [cv1], [cf1])
def test_compute_factor_cost_at_start(): 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]) obtained = factor_costs_for_var(c1, v1, {}, "min") assert obtained["R"] == 0 assert obtained["G"] == 0 assert len(obtained) == 2
def test_create_node_no_neigbors(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) c1 = constraint_from_str('c1', 'v1 * 0.5', [v1]) n1 = VariableComputationNode(v1, [c1]) assert v1 == n1.variable assert c1 in n1.constraints assert len(n1.links) == 1 # link to our-self assert not n1.neighbors
def test_var_node_simple_repr(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) c1 = constraint_from_str('c1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, [c1]) r = simple_repr(cv1) cv1_obtained = from_repr(r) assert cv1 == cv1_obtained
def test_create_node_with_binary_constraint(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) v2 = Variable('v2', d) c1 = constraint_from_str('c1', 'v1 * 0.5 - v2', [v1, v2]) n1 = VariableComputationNode(v1, [c1]) assert v1 == n1.variable assert c1 in n1.constraints assert list(n1.links)[0].has_node('v2') assert 'v2' in n1.neighbors
def generate_binary_intentional_constraint( variable1: Variable, variable2: Variable, bin_range: float ) -> Constraint: value = random.uniform(-bin_range, bin_range) constraint = constraint_from_str( name=f"cb_{variable1.name}_{variable2.name}", expression=f"{value} if {variable1.name} == {variable2.name} else -{value}", all_variables=[variable1, variable2], ) return constraint
def __add__(self, info: Tuple[str, str, List[Variable]]): """Convenience notation for adding a constraint to te dcop. Parameters ---------- info: a tuple name, expr_str, variables name is the name of the constraint, as a string expr_str is a python expression as a string, that return the value of the constraint. names used in this expression must be names of variables given in te third element of the tuple. variable can be an iterable of variable object or a dictionary of {name: variables} Returns ------- DCOP the dcop itself, in order to be able to use the += notation. Raises ------ ValueError If a domain or variable with the same name, but not the same definition, already exist for this dcop. Notes ----- Variable(s) and domain(s) involved in the constraint are automatically added to the dcop. See Also -------- add_constraint Examples -------- >>> dcop = DCOP('test') >>> v1 = Variable('v1', range(10) ) >>> dcop += 'c1', '2 if v1 > 5 else 10 ', [v1] >>> dcop.constraints['c1'](8) 2 >>> dcop.constraints['c1'](1) 10 """ (name, expr_str, variables) = info if hasattr(variables, 'values'): variables = variables.values() c = constraint_from_str(name, expr_str, variables) self.add_constraint(c) return self
def test_variablenode_simple_repr(): d1 = Domain('d1', '', [1, 2, 3, 5]) v1 = Variable('v1', d1) f1 = constraint_from_str('f1', 'v1 * 0.5', [v1]) cv1 = VariableComputationNode(v1, ['f1']) cf1 = FactorComputationNode(f1, ) r = simple_repr(cv1) obtained = from_repr(r) assert obtained == cv1 assert cv1.variable == obtained.variable
def test_dcop_add_constraint_is_enough(): dcop = DCOP() d = VariableDomain('test', 'test', values=range(10)) v1 = Variable('v1', d) v2 = Variable('v2', d) c1 = constraint_from_str('c1', '0 if v1 != v2 else 1000', [v1, v2]) dcop.add_constraint(c1) assert dcop.constraints == {'c1': c1} assert dcop.variables == {'v1': v1, 'v2': v2} assert dcop.domains == {'test': d}
def test_graph_density(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) c1 = constraint_from_str('c1', 'v1 * 0.5 + v2 - v3', [v1, v2, v3]) dcop = DCOP('dcop_test', 'min') dcop.add_constraint(c1) graph = build_computation_graph(dcop) density = graph.density() assert density == 1 / 3
def setUp(self): variables = list( create_variables('v', ['1', '2', '3'], Domain('d', '', [1, 2])).values()) all_diff = constraint_from_str('all_diff', 'v1 + v2 + v3 ', variables) v1, v2, v3 = variables c1 = VariableComputationNode(v1, [all_diff]) c2 = VariableComputationNode(v2, [all_diff]) c3 = VariableComputationNode(v3, [all_diff]) nodes = [c1, c2, c3] # links = [ConstraintLink('all_diff', ['c1', 'c2', 'c3'])] self.cg = ComputationConstraintsHyperGraph(nodes) self.agents = [AgentDef('a1'), AgentDef('a2'), AgentDef('a3')]
def build_lights(light_count, light_domain): # Lights : cost function & variable lights = {} lights_cost = {} for i in range(light_count): light = Variable("l{}".format(i), domain=light_domain) lights[light.name] = light efficiency = randint(0, 90) / 100 cost = constraint_from_str( "c_l{}".format(i), expression="{} * {}".format(light.name, efficiency), all_variables=[light], ) lights_cost[cost.name] = cost return lights, lights_cost
def test_no_neighbors(): x1 = Variable("x1", list(range(10))) cost_x1 = constraint_from_str('cost_x1', 'x1 *2 ', [x1]) computation = Mgm2Computation(x1, [cost_x1], mode='max', comp_def=MagicMock()) computation.value_selection = MagicMock() computation.finished = MagicMock() vals, cost = computation._compute_best_value() assert cost == 18 assert set(vals) == {9} computation.on_start() computation.value_selection.assert_called_once_with(9, 18) computation.finished.assert_called_once_with()
def test_link_simple_repr(): d = Domain('d', 'test', [1, 2, 3]) v1 = Variable('v1', d) v2 = Variable('v2', d) v3 = Variable('v3', d) c1 = constraint_from_str('c1', 'v1 * 0.5 + v2 - v3', [v1, v2, v3]) cv1 = VariableComputationNode(v1, [c1]) cv2 = VariableComputationNode(v2, [c1]) cv3 = VariableComputationNode(v3, [c1]) link = ConstraintLink(c1.name, ['c1', 'c2', 'c3']) r = simple_repr(link) link_obtained = from_repr(r) assert link == link_obtained
def test_problem_with_non_binary_constraints_raises_exception(): d = Domain("values", "", [1, 0]) v1 = Variable("v1", d) v2 = Variable("v2", d) v3 = Variable("v3", d) c1 = constraint_from_str("c1", "v1 + v2 + v3 <= 2", [v1, v2, v3]) g = build_computation_graph(None, constraints=[c1], variables=[v1, v2, v3]) with pytest.raises(ComputationException) as comp_exc: get_computation_instance(g, "v1") assert f" with arity {3}" in str(comp_exc.value) with pytest.raises(ComputationException) as comp_exc: get_computation_instance(g, "v3") assert f" with arity {3}" in str(comp_exc.value) with pytest.raises(ComputationException) as comp_exc: get_computation_instance(g, "v2") assert f" with arity {3}" in str(comp_exc.value)
def test_no_neighbors(): x1 = Variable("x1", list(range(10))) cost_x1 = constraint_from_str("cost_x1", "x1 *2 ", [x1]) computation = Mgm2Computation( ComputationDef( VariableComputationNode(x1, [cost_x1]), AlgorithmDef.build_with_default_param("mgm2", mode="max"), )) computation.value_selection = MagicMock() computation.finished = MagicMock() vals, cost = computation._compute_best_value() assert cost == 18 assert set(vals) == {9} computation.on_start() computation.value_selection.assert_called_once_with(9, 18) computation.finished.assert_called_once_with()