def test_gen_clause(self): """ Ensures the clause generation method creates the correct tree structure. """ eq = Equation('({1})') # Non-sub clause check rslt = eq._generate_clause('{1}.{2}.{3}') assert type(rslt) is AndNode # Check the node types assert type(rslt._lhs_child) is VariableNode assert type(rslt._rhs_child) is AndNode vec = {'{1}': True, '{2}': True, '{3}': True} assert rslt.evaluate(vec) # Check some evaluations. vec = {'{1}': False, '{2}': True, '{3}': True} self.assertFalse(rslt.evaluate(vec)) vec = {'{1}': True, '{2}': True, '{3}': False} self.assertFalse(rslt.evaluate(vec)) vec = {'{1}': False, '{2}': False, '{3}': True} self.assertFalse(rslt.evaluate(vec)) # With inversion? rslt = eq._generate_clause('¬{1}+{2}') assert type(rslt) is OrNode # Check the node types assert type(rslt._lhs_child) is InversionNode assert type(rslt._rhs_child) is VariableNode vec = {'{1}': True, '{2}': True} self.assertTrue(rslt.evaluate(vec)) # Check some evaluations. vec = {'{1}': True, '{2}': False} self.assertFalse(rslt.evaluate(vec))
def test_str_validation(self): """ Ensures the string validation method validates strings correctly. """ test_cases = self.gen_validation_cases() eq = Equation('({1})') for case in test_cases: self.assertTrue( eq._validate_string(case['str']) == case['exp'], case)
def test_evaluate(self, val): """ Ensures the evaluate class tests response for a False. """ nde = Equation('({1})') rtn_val = [True, True, True] nde.get_clause_evaluation = MagicMock(return_value=rtn_val) self.assertTrue(nde.evaluate({})) rtn_val = [True, False, True] nde.get_clause_evaluation = MagicMock(return_value=rtn_val) self.assertFalse(nde.evaluate({}))
def test_clausal_evaluation(self): """ Tests the evaluation of a selection of clauses. """ eq = Equation('({1})') # Equation object to test. fke_clause_true = Mock() # Fake clause to return true fke_clause_true.evaluate = MagicMock(return_value=True) fke_clause_false = Mock() # Fake clause to return false fke_clause_false.evaluate = MagicMock(return_value=False) eq._clauses = [fke_clause_true, fke_clause_false, fke_clause_true] res = eq.get_clause_evaluation({}) assert (res[0] and (not res[1]) and res[2]) eq._clauses = [fke_clause_true, fke_clause_true, fke_clause_true] res = eq.get_clause_evaluation({}) assert (res[0] and res[1] and res[2]) eq._clauses = [fke_clause_false, fke_clause_false, fke_clause_false] res = eq.get_clause_evaluation({}) assert not (res[0] or res[1] or res[2])
def _generate_equation(self, clique_size): """ Generates a boolean equation and variable set based on the parameters. """ # Generate string equivalent bln_eq_str = "" var_set = [] vertex_combinations = combinations( self._graph.get_vertices(), clique_size) # Get all combinations of vertices for combination in vertex_combinations: # Generate clause and inverse clause clause_one = "" clause_two = "" for edge in self._graph.get_edges( ): # Get all edges in this combination if (edge.get_origin() in combination) and (edge.get_target() in combination): edge_id = str( edge.get_id()) # Found an edge in this combination var_id = "{" + edge_id + "}" clause_one = clause_one + "+¬" + var_id + "" clause_two = clause_two + "+" + var_id + "" # Format clause clause_one = "(" + clause_one[ 1:] + ")" # The substring removes the first redundant "AND" symbol clause_two = "(" + clause_two[1:] + ")" # Add clause to equation bln_eq_str = bln_eq_str + "." + clause_one + "." + clause_two # Generate variables list for edge in self._graph.get_edges(): var_id = "{" + str(edge.get_id()) + "}" var_set.append(var_id) # Format Equation bln_eq_str = bln_eq_str[1:] # Removes redundant AND symbol # Generate equation object return (Equation(bln_eq_str), var_set)
def _test_method(self, method, no_trials, test_cases): """ Tests the given method with x trials on all test cases provided. """ results = [] for test_case in test_cases: test_case_aes = 0 test_case_sr = 0 trial_count = 0 while trial_count < no_trials: trial_res = self._do_trial(method(), Equation(test_case['Equation']), test_case['NumVars']) # Do the trial if trial_res['Success']: # Only add information if it was successful test_case_sr = test_case_sr + 1 test_case_aes = test_case_aes + trial_res['Evaluations'] trial_count = trial_count + 1 try: test_case_aes = test_case_aes / test_case_sr # Divide by the number of successes except ZeroDivisionError: test_case_aes = 0 test_case_sr = test_case_sr / no_trials # No. Successful trials / percentage results.append({ "AES": test_case_aes, "SR": test_case_sr }) return results
def test_gen_clause_list(self, gen_clause): """ Ensures the method generates the set of clauses. """ gen_clause.return_value = "Fake3lause" # Fake the generation of a clause node. eq = Equation('({1})') eq._unparsed_equation = '(1234).(1234).(9876)' # Setup some fake clauses expected_calls = [call('1234'), call('1234'), call('9876')] eq.generate_clauses() eq._generate_clause.assert_has_calls(expected_calls) eq._clauses = [] # Reset clauses eq._unparsed_equation = '(1234)' # Setup a fake clause expected_calls = [call('1234')] eq.generate_clauses() eq._generate_clause.assert_has_calls(expected_calls) eq._clauses = [] # Reset clauses eq._unparsed_equation = '' # Setup no fake clauses expected_calls = [] eq.generate_clauses() eq._generate_clause.assert_has_calls(expected_calls)