def test_4nodes(self): # Graph with 4 nodes, one cycle # # x1---X3 # \ / # x2---x4 domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) x4 = Variable('x4', domain) variables = [x1, x2, x3, x4] def binary_func(x, y): return x + y r1 = NAryFunctionRelation(binary_func, [x1, x2], name='r1') r2 = NAryFunctionRelation(binary_func, [x1, x3], name='r2') r3 = NAryFunctionRelation(binary_func, [x2, x3], name='r3') r4 = NAryFunctionRelation(binary_func, [x2, x4], name='r4') relations = [r1, r2, r3, r4] root = _generate_dfs_tree(variables, relations, root=x1) _filter_relation_to_lowest_node(root) check_tree(root) self.assertEqual(root.variable, x1) self.assertEqual(root.parent, None) self.assertEqual(len(root.children), 1) self.assertEqual(len(root.relations), 0)
def test_3nodes_tree_cycle(self): domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) variables = [x1, x2, x3] r1 = NAryFunctionRelation(lambda x, y: x + y, [x1, x2], name='r1') r2 = NAryFunctionRelation(lambda x, y: x + y, [x1, x3], name='r2') r3 = NAryFunctionRelation(lambda x, y: x + y, [x2, x3], name='r3') relations = [r1, r2, r3] dcop = DCOP('test', 'min') dcop.add_constraint(r1) dcop.add_constraint(r2) dcop.add_constraint(r3) cg = build_computation_graph(dcop) self.assertEqual(len(cg.nodes), len(variables)) self.assertEqual(len(cg.roots), 1) # All variables have the same number of neighbors, they could all be # root self.assertIn(cg.roots[0].variable, [x1, x2, x3]) self.assertEqual(cg.roots[0].parent, None) root = _generate_dfs_tree(variables, relations, root=x1) self.assertEqual(root.variable, x1) self.assertEqual(root.parent, None)
def test_3nodes_tree_cycle(self): domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) variables = [x1, x2, x3] r1 = NAryFunctionRelation(lambda x, y: x + y, [x1, x2], name='r1') r2 = NAryFunctionRelation(lambda x, y: x + y, [x1, x3], name='r2') r3 = NAryFunctionRelation(lambda x, y: x + y, [x2, x3], name='r3') relations = [r1, r2, r3] root = _generate_dfs_tree(variables, relations, root=x1) self.assertEqual(root.variable, x1) self.assertEqual(root.parent, None) self.assertEqual(len(root.children), 1) c1 = root.children[0] self.assertIn(c1.variable, [x2, x3]) self.assertEqual(len(root.pseudo_children), 1) self.assertEqual(root.pseudo_parents, []) self.assertEqual(c1.parent, root) self.assertEqual(len(c1.children), 1) c2 = c1.children[0] self.assertEqual(c2.children, []) self.assertEqual(c2.pseudo_children, []) self.assertEqual(c2.pseudo_parents, [root]) check_tree(root)
def test_diameter_simple(self): l1 = Variable('l1', []) l2 = Variable('l2', []) l3 = Variable('l3', []) r1 = NAryFunctionRelation(lambda x, y: 0, [l1, l2], name='r1') r2 = NAryFunctionRelation(lambda x, y: 0, [l2, l3], name='r2') d = graph_diameter([l1, l2, l3], [r1, r2]) self.assertEqual(len(d), 1) self.assertEqual(d[0], 2)
def test_diameter_simple2(self): l1 = Variable('l1', []) l2 = Variable('l2', []) l3 = Variable('l3', []) r1 = NAryFunctionRelation(lambda x, y: 0, [l1, l2], name='r1') r2 = NAryFunctionRelation(lambda x, y: 0, [l2, l3], name='r2') r3 = NAryFunctionRelation(lambda x, y: 0, [l1, l3], name='r3') d = graph_diameter([l1, l2, l3], [r1, r2, r3]) self.assertListEqual(d, [1])
def test_count_cycle_none(self): domain = list(range(10)) l1 = Variable('l1', domain) l2 = Variable('l2', domain) l3 = Variable('l3', domain) r1 = NAryFunctionRelation(lambda x, y: 0, [l1, l2], name='r1') r2 = NAryFunctionRelation(lambda x, y: 0, [l2, l3], name='r2') n = cycles_count([l1, l2, l3], [r1, r2]) self.assertEqual(n, 0)
def test_convert_graph_simple(self): domain = list(range(10)) l1 = Variable('l1', domain) l2 = Variable('l2', domain) l3 = Variable('l3', domain) r1 = NAryFunctionRelation(lambda x, y: 0, [l1, l2], name='r1') r2 = NAryFunctionRelation(lambda x, y: 0, [l2, l3], name='r2') r3 = NAryFunctionRelation(lambda x, y: 0, [l1, l3], name='r3') graph = as_networkx_graph([l1, l2, l3], [r1, r2, r3]) print(graph.edges()) print(graph.nodes()) self.assertEqual(len(graph.nodes()), 3) self.assertEqual(len(graph.edges()), 3)
def create_computation_hosted_constraint(computation_name: str, bin_vars: Dict[Tuple, BinaryVariable])\ -> Constraint: """ Create a constraints that the computation names `computation_name` is hosted exactly once on a set of n candidate agents. The constraints is an hard constraint that return an 'high enough' (10 000) value when it is not satisfied. :param computation_name: the name of the computation :param bin_vars: a dictionary { (comp_name, agt_name) -> BinaryVariable } containing the n binary variables x_i^m, one for each of the n candidate agents a_m the computation x_i could be hosted on :return: a constraint object """ def hosted(**kwargs): # kwargs will be a map {bin_var_name -> value} giving the binary # value for each of the n candidate agent the computation could be # hosted on s = sum([v for v in kwargs.values()]) return 0 if s == 1 else 10000 constraint = NAryFunctionRelation( hosted, list(bin_vars.values()), name='{}_hosted'.format(computation_name)) return constraint
def test_2nodes_tree(self): domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) variables = [x1, x2] r1 = NAryFunctionRelation(lambda x, y: x + y, [x1, x2], name='r1') relations = [r1] root = _generate_dfs_tree(variables, relations, root=x1) self.assertEqual(root.variable, x1) self.assertEqual(root.parent, None) self.assertEqual(len(root.children), 1) self.assertEqual(len(root.relations), 1) node = root.children[0] self.assertEqual(node.variable, x2) self.assertEqual(root.pseudo_children, []) self.assertEqual(root.pseudo_parents, []) self.assertEqual(node.parent, root) self.assertEqual(node.children, []) self.assertEqual(node.pseudo_children, []) self.assertEqual(node.pseudo_parents, []) self.assertEqual(node.relations, [r1]) check_tree(root)
def test_root(self): domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) variables = [x1, x2, x3] r1 = NAryFunctionRelation(lambda x, y: x + y, [x1, x2], name='r1') r2 = NAryFunctionRelation(lambda x, y: x - y, [x2, x3], name='r2') relations = [r1, r2] tree_root = _generate_dfs_tree(variables, relations, x1) self.assertEqual(tree_root.variable, x1) tree_root = _generate_dfs_tree(variables, relations) self.assertIn(tree_root.variable, variables)
def test_3nodes_tree_cycle_3ary_rel_bottom(self): # A graph with 3 variables and a single 3-ary relation. domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) variables = [x1, x2, x3] r1 = NAryFunctionRelation(lambda x, y, z: x + y + z, [x1, x2, x3], name='r1') relations = [r1] root = _generate_dfs_tree(variables, relations, root=x1) _filter_relation_to_lowest_node(root) self.assertEqual(root.variable, x1) self.assertEqual(root.parent, None) self.assertEqual(len(root.children), 1) self.assertEqual(len(root.relations), 0) c1 = root.children[0] self.assertIn(c1.variable, [x2, x3]) self.assertEqual(len(root.pseudo_children), 1) self.assertEqual(root.pseudo_parents, []) self.assertEqual(c1.parent, root) self.assertEqual(len(c1.children), 1) c2 = c1.children[0] self.assertEqual(c2.children, []) self.assertEqual(c2.pseudo_children, []) self.assertEqual(c2.pseudo_parents, [root]) self.assertEqual(len(c1.relations) + len(c2.relations), 1) check_tree(root)
def test_diameter_simple3(self): l1 = Variable('l1', []) l2 = Variable('l2', []) l3 = Variable('l3', []) r1 = NAryFunctionRelation(lambda x, y: 0, [l1, l2], name='r1') g = as_networkx_graph([l1, l2, l3], [r1]) d = graph_diameter([l1, l2, l3], [r1]) self.assertListEqual(sorted(d), [0, 1])
def test_count_cycle_clique(self): domain = list(range(10)) l1 = Variable('l1', domain) l2 = Variable('l2', domain) l3 = Variable('l3', domain) l4 = Variable('l4', domain) r1 = NAryFunctionRelation(lambda x, y, z, w: 0, [l1, l2, l3, l4], name='r1') n = cycles_count([l1, l2, l3, l4], [r1]) self.assertEqual(n, 3)
def test_visit_tree(self): domain = ['a', 'b', 'c'] x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) x4 = Variable('x4', domain) variables = [x1, x2, x3, x4] binary_func = lambda x, y: x + y r1 = NAryFunctionRelation(binary_func, [x1, x2], name='r1') r2 = NAryFunctionRelation(binary_func, [x1, x3], name='r2') r3 = NAryFunctionRelation(binary_func, [x2, x3], name='r3') r4 = NAryFunctionRelation(binary_func, [x2, x4], name='r4') relations = [r1, r2, r3, r4] root = _generate_dfs_tree(variables, relations, root=x1) for node in _visit_tree(root): self.assertIn(node.variable, variables) variables.remove(node.variable) self.assertEqual(len(variables), 0)
def test_convert_graph(self): domain = list(range(10)) l1 = Variable('l1', domain) l2 = Variable('l2', domain) l3 = Variable('l3', domain) l4 = Variable('l4', domain) # 4-ary relation : iot defines a clique with l1, l2, l3, l4 r1 = NAryFunctionRelation(lambda x, y: 0, [l1, l2, l3, l4], name='r1') graph = as_networkx_graph([l1, l2, l3], [r1]) print(graph.edges()) print(graph.nodes()) self.assertEqual(len(graph.nodes()), 4) self.assertEqual(len(graph.edges()), 6)
def create_agent_capacity_constraint(agt_name: str, remaining_capacity, footprint_func: Callable[[str], float], bin_vars: Dict[Tuple, BinaryVariable]) \ -> Constraint: """ Create a constraints that ensure that an agent a_m does not exceeds its capacity when hosting some candidates computations x_i \in X_c. The constraints is an hard constraint that return an 'high enough' (10 000) value when it is not satisfied. Parameters ---------- agt_name: str the name of the agent a_m for which we are creating the constraint remaining_capacity the remaining capacity of a_m before hosting any candidate computation from X_c. footprint_func: function a function that gives the footprint for a computation, given its name. bin_vars: a dictionary { (comp_name, agt_name) -> BinaryVariable } containing the k binary variable x_i^m, one for each of the k candidate computations x_i that could be hosted on the agent a_m. Returns ------- a Constraint object """ # Reversed lookup table: which (agt, computation) a variable is about: var_lookup = {v.name: k for k, v in bin_vars.items()} def capacity(**kwargs): # kwargs will be a name {v_name : value} # where v_name is x_{}_{} orphaned_footprint = 0 for v_name in kwargs: comp, _ = var_lookup[v_name] orphaned_footprint += kwargs[v_name] * footprint_func(comp) repair_capa = remaining_capacity - orphaned_footprint return 0 if repair_capa >= 0 else 10000 constraint = NAryFunctionRelation(capacity, list(bin_vars.values()), name=agt_name + '_capacity') return constraint
def test_find_neighbors_relations(self): domain = ['a', 'b', 'c'] n1 = _BuildingNode(Variable('x1', domain)) n2 = _BuildingNode(Variable('x2', domain)) n3 = _BuildingNode(Variable('x3', domain)) nodes = [n1, n2, n3] r1 = NAryFunctionRelation(lambda x, y: x + y, [n1.variable, n2.variable], name='r1') relations = [r1] self.assertEqual(_find_neighbors_relations(n1, relations, nodes), ([n2], [r1])) self.assertEqual(_find_neighbors_relations(n2, relations, nodes), ([n1], [r1])) self.assertEqual(_find_neighbors_relations(n3, relations, nodes), ([], []))
def test_3var_1rel(self): domain = list(range(10)) l1 = Variable('l1', domain) l2 = Variable('l2', domain) l3 = Variable('l3', domain) rel = NAryFunctionRelation(lambda x, y, z: 0, [l1, l2, l3], name='rel') nodes = as_bipartite_graph([l1, l2, l3], [rel]) self.assertEqual(len(nodes), 4) var_nodes = [n for n in nodes if n.type == 'VARIABLE'] rel_nodes = [n for n in nodes if n.type == 'CONSTRAINT'] self.assertEqual(len(var_nodes), 3) self.assertEqual(len(rel_nodes), 1) self.assertEqual(len(rel_nodes[0].neighbors), 3) self.assertIn(var_nodes[0], rel_nodes[0].neighbors) self.assertIn(var_nodes[1], rel_nodes[0].neighbors) self.assertIn(var_nodes[2], rel_nodes[0].neighbors)
def create_agent_hosting_constraint(agt_name: str, hosting_func: Callable[[str], float], bin_vars: Dict[Tuple, BinaryVariable]) \ -> Constraint: """ Create a constraints that returns the hosting costs for agent a_m `agt_name` when hosting some candidates computations x_i \in X_c. The constraints is an soft constraint that should be minimized. Parameters ---------- agt_name: str the name of the agent a_m. hosting_func: Callable a function that gives the hosting costs for a computation x_i on a_m, given the name of x_i. bin_vars: dictionary { (comp_name, agt_name) -> BinaryVariable } containing the k binary variable x_i^m, one for each of the k candidate computations x_i that could be hosted on the agent a_m. Returns ------- a Constraint object """ # Reversed lookup table: which (agt, computation) a variable is about: var_lookup = {v.name: k for k, v in bin_vars.items()} def hosting_cost(**kwargs): cost = 0 for v_name in kwargs: comp, _ = var_lookup[v_name] cost += kwargs[v_name] * hosting_func(comp) return cost constraint = NAryFunctionRelation(hosting_cost, list(bin_vars.values()), name=agt_name + '_hosting') return constraint
def dmaxsum_external_variable(): domain = VariableDomain('colors', 'color', ['R', 'G', 'B']) # RW Variables v1 = VariableNoisyCostFunc('v1', domain, prefer_color('R')) v2 = VariableNoisyCostFunc('v2', domain, prefer_color('B')) v3 = VariableNoisyCostFunc('v3', domain, prefer_color('B')) v4 = VariableNoisyCostFunc('v4', domain, prefer_color('R')) # External Variable domain_e = VariableDomain('boolean', 'abstract', [False, True]) e1 = ExternalVariable('e1', domain_e, False) def r1(v1_, v2_, v3_): if v1_ != v2_ and v2_ != v3_ and v1_ != v3_: return 0 return 100 condition = NAryFunctionRelation(lambda x: x, [e1], name='r1_cond') relation_if_true = NAryFunctionRelation(r1, [v1, v2, v3], name='r1') r1 = ConditionalRelation(condition, relation_if_true) def r2(v2_, v4_): if v2_ != v4_: return 0 return 100 r2 = NAryFunctionRelation(r2, [v2, v4], name='r2') def r3(v3_, v4_): if v3_ != v4_: return 0 return 100 r3 = NAryFunctionRelation(r3, [v3, v4], name='r3') r1_computation = DynamicFactorComputation(r1, name='r1') r2_computation = DynamicFactorComputation(r2) r3_computation = DynamicFactorComputation(r3) e1_computation = ExternalVariableComputation(e1) # MUST only consider current relation when building computation objects !! # When a relation uses external variable, these must be sliced out. current_r1 = r1.slice({e1.name: e1.value}) relations = [current_r1, r2, r3] v1_computation = \ DynamicFactorVariableComputation( v1, [r.name for r in find_dependent_relations(v1, relations)]) v2_computation = \ DynamicFactorVariableComputation( v2, [r.name for r in find_dependent_relations(v2, relations)]) v3_computation = \ DynamicFactorVariableComputation( v3, [r.name for r in find_dependent_relations(v3, relations)]) v4_computation = \ DynamicFactorVariableComputation( v4, [r.name for r in find_dependent_relations(v4, relations)]) # Prepare the agents comm = InProcessCommunicationLayer() a1 = Agent('a1', comm) a1.add_computation(v1_computation) a1.add_computation(r1_computation) a2 = Agent('a2', comm) a2.add_computation(v2_computation) a1.add_computation(r2_computation) a3 = Agent('a3', comm) a3.add_computation(v3_computation) a3.add_computation(v4_computation) a3.add_computation(r3_computation) a4 = Agent('a4', comm) a4.add_computation(e1_computation) agents = [a1, a2, a3, a4] runner = AgentsRunner(agents) runner.run_agents() # Now change a factor function every two seconds fail = False for i in range(5): time.sleep(2) current_value = e1_computation.current_value print('### Iteration {} - function {}'.format(i, current_value)) print(runner.status_string()) results = runner.variable_values() if current_value: c = r1(filter_assignment_dict(results, r1.dimensions)) + \ r2(filter_assignment_dict(results, r2.dimensions)) + \ r3(filter_assignment_dict(results, r3.dimensions)) if c != 0: print('Error on results for {} : \nGot {} !'.format( current_value, results)) fail = True break else: c = r2(filter_assignment_dict(results, r2.dimensions)) + \ r3(filter_assignment_dict(results, r3.dimensions)) if c != 0: print('Error on results for {} : \nGot {} !'.format( current_value, results)) fail = True break new_val = not current_value print('## Changing e1 value to {}'.format(new_val)) e1_computation.change_value(new_val) print('Finished, stopping agents') runner.request_stop_agents(wait_for_stop=True) if fail: print('Failed !') return 1 else: print('Success !') return 0
def dmaxsum_graphcoloring(): v1 = VariableNoisyCostFunc('v1', d, prefer_color('R')) v2 = VariableNoisyCostFunc('v2', d, prefer_color('G')) v3 = VariableNoisyCostFunc('v3', d, prefer_color('B')) v4 = VariableNoisyCostFunc('v4', d, prefer_color('R')) def r1(v1_, v2_, v3_): if v1_ != v2_ and v2_ != v3_ and v1_ != v3_: return 0 return 100 r1 = NAryFunctionRelation(r1, [v1, v2, v3], name='r1') def r1_2(v1_, v2_, v4_): if v1_ != v2_ and v2_ != v4_ and v1_ != v4_: return 0 return 100 r1_2 = NAryFunctionRelation(r1_2, [v1, v2, v4], name='r1_2') def r2(v2_, v4_): if v2_ != v4_: return 0 return 100 r2 = NAryFunctionRelation(r2, [v2, v4], name='r2') def r3(v3_, v4_): if v3_ != v4_: return 0 return 100 r3 = NAryFunctionRelation(r3, [v3, v4], name='r3') relations = [r1, r2, r3] r1_computation = DynamicFactorComputation(r1, name='r1') r2_computation = DynamicFactorComputation(r2) r3_computation = DynamicFactorComputation(r3) v1_computation = \ DynamicFactorVariableComputation( v1, [r.name for r in find_dependent_relations(v1, relations)]) v2_computation = \ DynamicFactorVariableComputation( v2, [r.name for r in find_dependent_relations(v2, relations)]) v3_computation = \ DynamicFactorVariableComputation( v3, [r.name for r in find_dependent_relations(v3, relations)]) v4_computation = \ DynamicFactorVariableComputation( v4, [r.name for r in find_dependent_relations(v4, relations)]) # Prepare the agents comm = InProcessCommunicationLayer() a1 = Agent('a1', comm) a1.add_computation(v1_computation) a1.add_computation(r1_computation) a2 = Agent('a2', comm) a2.add_computation(v2_computation) a1.add_computation(r2_computation) a3 = Agent('a3', comm) a3.add_computation(v3_computation) a3.add_computation(v4_computation) a3.add_computation(r3_computation) # Expected results to check for success expected_results = { 'r1': { 'v1': 'R', 'v2': 'G', 'v3': 'B', 'v4': 'R' }, 'r1_2': { 'v1': 'B', 'v2': 'G', 'v3': 'B', 'v4': 'R' } } r1_fcts = [r1, r1_2] agents = [a1, a2, a3] for a in agents: a.start() # Now change a factor function every two seconds r1_fct, iteration, fail = 0, 0, False for _ in range(5): iteration += 1 time.sleep(2) print('### Iteration {} - function {}'.format(iteration, r1_fcts[r1_fct].name)) print(runner.status_string()) results = runner.variable_values() if not results == expected_results[r1_fcts[r1_fct].name]: print('Error on results for {} : \nGot {} instead of {} !'.format( r1_fcts[r1_fct].name, results, expected_results[r1_fcts[r1_fct].name])) fail = True break r1_fct = (r1_fct + 1) % 2 print('## Changing to function {}'.format(r1_fcts[r1_fct].name)) r1_computation.change_factor_function(r1_fcts[r1_fct]) print('Finished, stopping agents') runner.request_stop_agents(wait_for_stop=True) if fail: print('Failed !') return 1 else: print('Success !') return 0
def create_agent_comp_comm_constraint( agt_name: str, candidate_name: str, candidate_info: Tuple[List[str], Dict[str, str], Dict[str, List[str]]], comm: Callable[[str, str, str], float], bin_vars: Dict[Tuple, BinaryVariable]) \ -> Constraint: """ Create a constraints that returns the communication costs for agent a_m `agt_name` when hosting a candidate computations x_i \in X_c. The constraints is an soft constraint that should be minimized. Parameters ---------- agt_name: str candidate_info: comm: Callable function (comp_name, neigh_comp, neigh_agt) -> float that returns the communication cost between the computation comp_name hosted on the current agt_name agent and it's neighbor computation neigh_comp hosted on neigh_agt. bin_vars: Dict[Tuple, BinaryVariable] a dict containing one binary variable for each par (x_i, a_m) where x_i is a candidate computation or a neighbor of a candidate computation and a_m is an agent that can host x_i. Returns ------- A Constraint object """ agts, fixed_neighbors, candidate_neighbors = candidate_info def host_cost(**kwargs): """ Parameters ---------- kwargs : dict assignment for the variables the comm constraints depends on, given as a dict { variable name -> variable value} Returns ------- """ candidate_cost = 0.0 locally_hosted = bin_vars[(candidate_name, agt_name)].name for v in fixed_neighbors: v_agt = fixed_neighbors[v] candidate_cost += kwargs[locally_hosted] * \ comm(candidate_name, v, v_agt) for v in candidate_neighbors: cost_v = 0.0 for v_agt in candidate_neighbors[v]: arg_name = bin_vars[(v, v_agt)].name cost_v += kwargs[arg_name] * comm(candidate_name, v, v_agt) candidate_cost += kwargs[locally_hosted] * cost_v return candidate_cost scope = [bin_vars[(candidate_name, agt_name)]] for v in candidate_neighbors: for v_agt in candidate_neighbors[v]: scope.append(bin_vars[(v, v_agt)]) constraint = NAryFunctionRelation(host_cost, scope, name='comm_' + agt_name + '_' + candidate_name) return constraint
class TestsConstraintViolation(unittest.TestCase): domain = list(range(2)) x1 = Variable('x1', domain) x2 = Variable('x2', domain) x3 = Variable('x3', domain) phi = UnaryFunctionRelation('phi', Variable('x1', domain), lambda x: x) phi_n_ary = NAryFunctionRelation( lambda x1_, x2_, x3_: 2 if x1_ == x2_ else (1 if x1_ == x3_ else 0), [x1, x2, x3]) def NZ_violation_unary(self): g = GdbaComputation(self.x1, [self.phi], comp_def=MagicMock()) g._neighbors_values['x2'] = 1 g._neighbors_values['x3'] = 2 c = g.__constraints__[0] self.assertEqual(g._is_violated(c, 0), False) self.assertEqual(g._is_violated(c, 1), True) self.assertEqual(g._is_violated(c, 2), True) def NZ_violation_n_ary(self): g = GdbaComputation(self.x1, [self.phi_n_ary], comp_def=MagicMock()) g._neighbors_values['x2'] = 1 g._neighbors_values['x3'] = 2 c = g.__constraints__[0] self.assertEqual(g._is_violated(c, 0), False) self.assertEqual(g._is_violated(c, 1), True) self.assertEqual(g._is_violated(c, 2), True) def NM_violation_unary(self): g = GdbaComputation(self.x1, [self.phi], comp_def=MagicMock()) g._neighbors_values['x2'] = 1 g._neighbors_values['x3'] = 2 g._violation_mode = 'NM' c = g.__constraints__[0] self.assertEqual(g._is_violated(c, 0), False) self.assertEqual(g._is_violated(c, 1), True) self.assertEqual(g._is_violated(c, 2), True) def NM_violation_n_ary(self): g = GdbaComputation(self.x1, [self.phi_n_ary], comp_def=MagicMock()) g._neighbors_values['x2'] = 1 g._neighbors_values['x3'] = 2 g._violation_mode = 'NM' c = g.__constraints__[0] self.assertEqual(g._is_violated(c, 0), False) self.assertEqual(g._is_violated(c, 1), True) self.assertEqual(g._is_violated(c, 2), True) def MX_violation_unary(self): g = GdbaComputation(self.x1, [self.phi], comp_def=MagicMock()) g._neighbors_values['x2'] = 1 g._neighbors_values['x3'] = 2 g._violation_mode = 'MX' c = g.__constraints__[0] self.assertEqual(g._is_violated(c, 0), False) self.assertEqual(g._is_violated(c, 1), False) self.assertEqual(g._is_violated(c, 2), True) def MX_violation_n_ary(self): g = GdbaComputation(self.x1, [self.phi_n_ary], comp_def=MagicMock()) g._neighbors_values['x2'] = 1 g._neighbors_values['x3'] = 2 g._violation_mode = 'MX' c = g.__constraints__[0] self.assertEqual(g._is_violated(c, 0), False) self.assertEqual(g._is_violated(c, 1), True) self.assertEqual(g._is_violated(c, 2), False)