def test_satisfiable_non_symbols(): x, y = symbols('x y') assumptions = Q.zero(x * y) facts = Implies(Q.zero(x * y), Q.zero(x) | Q.zero(y)) query = ~Q.zero(x) & ~Q.zero(y) refutations = [{ Q.zero(x): True, Q.zero(x * y): True }, { Q.zero(y): True, Q.zero(x * y): True }, { Q.zero(x): True, Q.zero(y): True, Q.zero(x * y): True }, { Q.zero(x): True, Q.zero(y): False, Q.zero(x * y): True }, { Q.zero(x): False, Q.zero(y): True, Q.zero(x * y): True }] assert not satisfiable(And(assumptions, facts, query), algorithm='dpll') assert satisfiable(And(assumptions, facts, ~query), algorithm='dpll') in refutations assert not satisfiable(And(assumptions, facts, query), algorithm='dpll2') assert satisfiable(And(assumptions, facts, ~query), algorithm='dpll2') in refutations
def satask(proposition, assumptions=True, context=global_assumptions, use_known_facts=True, iterations=oo): relevant_facts = get_all_relevant_facts(proposition, assumptions, context, use_known_facts=use_known_facts, iterations=iterations) can_be_true = satisfiable( And(proposition, assumptions, relevant_facts, *context)) can_be_false = satisfiable( And(~proposition, assumptions, relevant_facts, *context)) if can_be_true and can_be_false: return None if can_be_true and not can_be_false: return True if not can_be_true and can_be_false: return False if not can_be_true and not can_be_false: # TODO: Run additional checks to see which combination of the # assumptions, global_assumptions, and relevant_facts are # inconsistent. raise ValueError("Inconsistent assumptions")
def test_satisfiable_bool(): from sympy.core.singleton import S assert satisfiable(true) == {true: true} assert satisfiable(S.true) == {true: true} assert satisfiable(false) is False assert satisfiable(S.false) is False
def ask_full_inference(proposition, assumptions): """ Method for inferring properties about objects. """ if not satisfiable(And(known_facts_cnf, assumptions, proposition)): return False if not satisfiable(And(known_facts_cnf, assumptions, Not(proposition))): return True return None
def answer_to_query(query, terms, pred, states): loc = str(query[1]) + '(' + str(query[0][0]) + str(query[0][1]) + ')' query_pred = pred[query[2] + loc] if not satisfiable(terms & query_pred): return 'F' else: for state in states: if state != query[2]: new_pred = pred[state + loc] if satisfiable(terms & new_pred): return '?' return 'T'
def satisfiable(self, solver='dpll'): if solver == 'dpll': sat = satisfiable(self.form, algorithm='dpll') elif solver == 'cdcl': sat = satisfiable(self.form, algorithm='dpll2') res = '' for i in sorted(list(sat.items()), key=lambda x: int(str(x[0])[4:])): res += str(1 * i[1]) print("The formula is solved by the interpretation: ", res) return res
def test_satisfiable_non_symbols(): x, y = symbols('x y') assumptions = Q.zero(x*y) facts = Implies(Q.zero(x*y), Q.zero(x) | Q.zero(y)) query = ~Q.zero(x) & ~Q.zero(y) refutations = [ {Q.zero(x): True, Q.zero(x*y): True}, {Q.zero(y): True, Q.zero(x*y): True}, {Q.zero(x): True, Q.zero(y): True, Q.zero(x*y): True}, {Q.zero(x): True, Q.zero(y): False, Q.zero(x*y): True}, {Q.zero(x): False, Q.zero(y): True, Q.zero(x*y): True}] assert not satisfiable(And(assumptions, facts, query), algorithm='dpll') assert satisfiable(And(assumptions, facts, ~query), algorithm='dpll') in refutations assert not satisfiable(And(assumptions, facts, query), algorithm='dpll2') assert satisfiable(And(assumptions, facts, ~query), algorithm='dpll2') in refutations
def initialize_history(self, initial_condition: boolalg.Boolean) -> ndarray: fluent_history = ndarray(shape=(self.last_time_point, len(self.fluents)), dtype=Fluent) ''' for observation in sorted_observations: for key, value in satisfiable(observation.condition.formula).items(): fluent = Fluent(key.name, value) begin_time = observation.begin_time for i in range(len(fluent_history[begin_time])): if fluent_history[begin_time][i] is None: fluent_history[begin_time][i] = fluent break else: continue ''' for key, value in satisfiable(initial_condition).items(): fluent = Fluent(key.name, value) begin_time = 0 for i in range(len(fluent_history[begin_time])): if fluent_history[begin_time][i] is None: fluent_history[begin_time][i] = fluent break else: continue # Assume inertia law for i in range(fluent_history.shape[0] - 1): for j in range(fluent_history.shape[1]): if fluent_history[i][j] is not None and fluent_history[ i + 1][j] is None: fluent_history[i + 1][j] = deepcopy(fluent_history[i][j]) return fluent_history
def fork_model(self, model: Model, formula: boolalg.Boolean, time: int, duration: int, is_releases_statement: bool = False) -> \ List[Model]: """ Checks all solutions to formula for a given "causes" or "releases" statement and uses satisfiable() and creates a model for each solution holding at time t :param model: The model to be forked, it could be removed from the list of models if :param formula: The sympy boolean formula that must hold at this time :param time: The time at which the action effect given by "formula" must hold in the model :param duration: The duration of action is used for occusion regions :param is_releases_statement: If true, then we keep the model that we want to fork. If false, it means we want to fork based on a CAUSES statement, so we remove the model that was passed in because we only want to have models where formula MUST HOLD :return: The list of new models obtained from solutions of the parameter "formula" """ new_models = [] solutions = satisfiable(formula, all_models=True) for s in solutions: new_model = deepcopy(model) new_model.update_fluent_history(s, time, duration) new_models.append(new_model) if not is_releases_statement and model in self.models: self.models.remove(model) return new_models
def assingn_rule_extensions(rules): for k, rule in rules.items(): h_temp = satisfiable(rule.head, all_models=True) for model in h_temp: new = {} for key in model: new[key] = model[key] rule.headExtension.append(new) b_temp = satisfiable(rule.body, all_models=True) for model in b_temp: new = {} for key in model: new[key] = model[key] rule.bodyExtension.append(new)
def check_for_invalid_initial_state(self): initial_fluents = [] if len(self.sorted_observations) > 0: # assume first observation is the initial description of fluents if not satisfiable(self.sorted_observations[0].condition.formula): for fluent_name, fluent_value in satisfiable( self.sorted_observations[0].condition.formula).items(): initial_fluents.append(fluent_name) if not satisfiable(self.sorted_observations[0].condition.formula): for i in range(1, len(self.sorted_observations)): for fluent_name, fluent_val in satisfiable( self.sorted_observations[i].condition.formula ).items(): if fluent_name not in initial_fluents: self.is_consistent = False
def suggest_new_example(logic, assume_commutative=False): log_eng = LogicEngine() expr = ~log_eng.parse_logic(logic, convert_to_converse=True) if assume_commutative: expr = expr.subs( 'x_1', True) # We want to remove commutativity from consideration modls = satisfiable(expr, all_models=True) results = [] for modl in modls: has = [k.name for k, v in modl.items() if v is True] lacks = [k.name for k, v in modl.items() if v is False] has = map(lambda x: x.replace('x', 'H'), has) lacks = map(lambda x: x.replace('x', 'L'), lacks) terms = list(map(lambda x: x.replace('_', ''), has)) terms.extend(map(lambda x: x.replace('_', ''), lacks)) narrow, _ = ring_search(terms) if len(narrow) > 0: continue terms = mirror_search_terms(terms) narrow, _ = ring_search(terms) if len(narrow) > 0: continue has = [item[1:] for item in terms if item.startswith('H')] lacks = [item[1:] for item in terms if item.startswith('L')] has_readable = [term_to_readable(x) for x in has] lacks_readable = [term_to_readable(x) for x in lacks] qd = QueryDict(mutable=True) qd.setlist('H', has) qd.setlist('L', lacks) results.append((has_readable, lacks_readable, '{}?{}'.format(reverse('results'), qd.urlencode()))) return results
def test_satisfiable_all_models(): from sympy.abc import A, B assert next(satisfiable(False, all_models=True)) is False assert list(satisfiable((A >> ~A) & A , all_models=True)) == [False] assert list(satisfiable(True, all_models=True)) == [{true: true}] models = [{A: True, B: False}, {A: False, B: True}] result = satisfiable(A ^ B, all_models=True) models.remove(next(result)) models.remove(next(result)) raises(StopIteration, lambda: next(result)) assert not models assert list(satisfiable(Equivalent(A, B), all_models=True)) == \ [{A: False, B: False}, {A: True, B: True}] models = [{A: False, B: False}, {A: False, B: True}, {A: True, B: True}] for model in satisfiable(A >> B, all_models=True): models.remove(model) assert not models # This is a santiy test to check that only the required number # of solutions are generated. The expr below has 2**100 - 1 models # which would time out the test if all are generated at once. from sympy import numbered_symbols from sympy.logic.boolalg import Or sym = numbered_symbols() X = [next(sym) for i in range(100)] result = satisfiable(Or(*X), all_models=True) for i in range(10): assert next(result)
def test_satisfiable_all_models(): from sympy.abc import A, B assert next(satisfiable(False, all_models=True)) is False assert list(satisfiable((A >> ~A) & A, all_models=True)) == [False] assert list(satisfiable(True, all_models=True)) == [{true: true}] models = [{A: True, B: False}, {A: False, B: True}] result = satisfiable(A ^ B, all_models=True) models.remove(next(result)) models.remove(next(result)) raises(StopIteration, lambda: next(result)) assert not models assert list(satisfiable(Equivalent(A, B), all_models=True)) == \ [{A: False, B: False}, {A: True, B: True}] models = [{A: False, B: False}, {A: False, B: True}, {A: True, B: True}] for model in satisfiable(A >> B, all_models=True): models.remove(model) assert not models # This is a santiy test to check that only the required number # of solutions are generated. The expr below has 2**100 - 1 models # which would time out the test if all are generated at once. from sympy import numbered_symbols from sympy.logic.boolalg import Or sym = numbered_symbols() X = [next(sym) for i in range(100)] result = satisfiable(Or(*X), all_models=True) for i in range(10): assert next(result)
def apply_logic(self, logic, ring, tentative): """ Evaluate if a Logic is satisfied by a Ring, or if there is a unique model that satisfies it. :param logic: The Logic to apply :param ring: The Ring instance being evaluated :param tentative: A dict of tentative values beyond the cached ones which will be added if they do not cause any conflicts in the end. :return: (dict, bool) The dict of values of symbols for the unique models that satisfies the expression, if it exists. If no new values are needed, this dict may be empty. The bool indicates whether or not all versions of the expression have been exhausted for this ring :exception LogicError, if the values are inconsistent with the Logic This indicates an inconsistency in the values for the Ring, or else an inconsistency of the Logic entries """ log.debug('Applying logic_id={} to ring_id={}'.format(logic.id, ring.id)) exprs = self.logic_to_expr[logic] # the symbolic expression of the logic known_props = cache.get('ring_props:{}'.format(ring.id)) # known values/symbols if known_props is None: self.load_ringproperties(ring) known_props = cache.get('ring_props:{}'.format(ring.id)) ret_dict = {} all_done = 0 for expr in exprs: result = expr.subs(known_props) result = result.subs(tentative) modls = list(satisfiable(result, all_models=True)) if len(modls) > 1: continue # more than one model: nothing to be deduced modl = modls[0] # if no models exist, we get False (python primitive False) if modl is False: raise LogicError('Logic error encountered while processing {} with {}:{}' .format(ring, logic.id, logic)) # If no symbols remain, the model will look like {True, True} where the # second true is the python primitive, and the first True is a sympy True if len(modl) == 1: check, _ = list(modl.items())[0] if isinstance(check, BooleanTrue): all_done += 1 # Nothing learned, but should note success continue # at this point, it should be a dict full of symbol:boolean keyvalues, # the unique thing that satisfies the expression ret_dict = self.merge_if_possible(ret_dict, modl) all_done += 1 # notes that we found the only model that can work if all_done > 2: log.error('This should not happen. Logics only evaluate one or two expressions...') # right hand side will only be true if all expressions were satisfied return ret_dict, all_done == len(exprs)
def parse_initial_fluents(self, scenario: Scenario): fluents = [] for observation in scenario.observations: if observation.begin_time == 0: for key, value in satisfiable( observation.condition.formula).items(): fluents.append(Fluent(key.name, value)) break return fluents
def check_for_contradictory_domain_desc(self): #action_dict = dict() # Maps action name -> Conditions joined by and action_dict = defaultdict(list) for i in range(len(self.domain_desc.statements)): statement = self.domain_desc.statements[i] # print(statement) # join action with its causes/releases effect if isinstance(statement, Causes): # if statement.action not in action_dict: #action_dict[statement.action] = statement.effect.formula # action_dict[statement.action] = statement action_dict[statement.action].append(statement) # action_dict[statement.action] = And(action_dict[statement.action], statement.effect.formula) for action_name, action_statement in action_dict.items(): n = len(action_statement) for j in range(n - 1): count = 0 for i in range(0, n - 1 - j): if not satisfiable( And(action_statement[i].effect.formula, And(action_statement[i + 1].effect.formula))): if action_statement[i].agent == action_statement[ i + 1].agent: if action_statement[ i].condition is True and action_statement[ i + 1].condition is True: print('action_effect:', action_statement, 'is not satisfiable') self.is_consistent = False break elif action_statement[ i].condition is True and action_statement[ i + 1].condition is not True: pass elif action_statement[ i].condition is not True and action_statement[ i + 1].condition is True: pass elif action_statement[ i].condition.formula == action_statement[ i + 1].condition.formula: print('action_effect:', action_statement, 'is not satisfiable') self.is_consistent = False break #if not satisfiable(action_statement): #print('action_effect:', action_statement, 'is not satisfiable') #self.is_consistent = False #break # Uncomment the below if we want to remove actions with unsatisfiable preconditions # I don't think we have to care about this case '''
def test_minisat22_satisfiable(): A, B, C = symbols('A,B,C') minisat22_satisfiable = lambda expr: satisfiable(expr, algorithm="minisat22") assert minisat22_satisfiable(A & ~A) is False assert minisat22_satisfiable(A & ~B) == {A: True, B: False} assert minisat22_satisfiable(A | B) in ({ A: True }, { B: False }, { A: False, B: True }, { A: True, B: True }, { A: True, B: False }) assert minisat22_satisfiable((~A | B) & (~B | A)) in ({ A: True, B: True }, { A: False, B: False }) assert minisat22_satisfiable((A | B) & (~B | C)) in ({ A: True, B: False, C: True }, { A: True, B: True, C: True }, { A: False, B: True, C: True }, { A: True, B: False, C: False }) assert minisat22_satisfiable(A & B & C) == {A: True, B: True, C: True} assert minisat22_satisfiable((A | B) & (A >> B)) in ({ B: True, A: False }, { B: True, A: True }) assert minisat22_satisfiable(Equivalent(A, B) & A) == {A: True, B: True} assert minisat22_satisfiable(Equivalent(A, B) & ~A) == {A: False, B: False}
def check_satisfiability(prop, _prop, factbase): sat_true = factbase.copy() sat_false = factbase.copy() sat_true.add_from_cnf(prop) sat_false.add_from_cnf(_prop) can_be_true = satisfiable(sat_true) can_be_false = satisfiable(sat_false) if can_be_true and can_be_false: return None if can_be_true and not can_be_false: return True if not can_be_true and can_be_false: return False if not can_be_true and not can_be_false: # TODO: Run additional checks to see which combination of the # assumptions, global_assumptions, and relevant_facts are # inconsistent. raise ValueError("Inconsistent assumptions")
def satask(proposition, assumptions=True, context=global_assumptions, use_known_facts=True, iterations=oo): relevant_facts = get_all_relevant_facts( proposition, assumptions, context, use_known_facts=use_known_facts, iterations=iterations ) can_be_true = satisfiable(And(proposition, assumptions, relevant_facts, *context)) can_be_false = satisfiable(And(~proposition, assumptions, relevant_facts, *context)) if can_be_true and can_be_false: return None if can_be_true and not can_be_false: return True if not can_be_true and can_be_false: return False if not can_be_true and not can_be_false: # TODO: Run additional checks to see which combination of the # assumptions, global_assumptions, and relevant_facts are # inconsistent. raise ValueError("Inconsistent assumptions")
def unsatisfied_deps(self): configuration = satisfiable(self.expr) if not configuration: return False # If configuration is 'True', return none. if configuration.get(True, False): return [] deps = [] for k in configuration: idx = int(k.name) deps.append((idx, self.symbols[idx][0], configuration[k])) deps.sort(key=lambda x: x[0], reverse=True) return deps
def assign_extensions(formula, worlds, propositions): extension = [] if str(formula).isspace() or len(str(formula)) == 0 or str( formula ) == "TRUE": #if the formula is empty it will be treated as a toutology #print("Check Empty\n") for w in worlds.values(): extension.append(w.state) return extension if str(formula) == "FALSE": return extension else: props_in_formula = set() #store propositions found in the formula for char in str(formula): add = Symbol(char) props_in_formula.add(add) props_not_in_form = propositions.difference( props_in_formula ) #Determine which propositions are missing from the rule's body supplement = Symbol('') #print("formula: %s " % (formula)) form_cnf = to_cnf(formula) for p in props_not_in_form: supplement = Or( p, Not(p)) #Loop aguments (P | ~P) for each P not found in body form_cnf = And(form_cnf, supplement) #print("__form_cnf: %s \n" % (form_cnf)) form_SAT = satisfiable( form_cnf, all_models=True ) #The sympy SAT solver is applied to the augmented formula form_SAT_list = list( form_SAT ) #the ouput of satisfiable() is an itterator object so we turn it into a list if (len(form_SAT_list) == 1 and form_SAT_list[0] == False): #check to handle inconsistencies extension = [] return extension else: for state in form_SAT_list: #We now turn each state in which the body is true into a dictionary so that new = {} #they may be directly compared with each world state for key, value in state.items(): new[key] = value if new not in extension: extension.append(new) return extension
def initialize( rules, propositions, pro): # Calls a sequence of functions that calculate the SE models formulas = formula_translation(rules) crules = rule_compliment(rules, propositions) _rules = construct_program(crules, "A") _formulas = formula_translation(_rules) comIorg = get_com_org_imp(propositions) condition = create_condition(formulas, _formulas, comIorg) #print("condition______________________________________________________________") #print(condition) YY = satisfiable(condition, all_models=True) listYY = list(YY) print("\n") model = get_Models(listYY) return model
def entailment_0(a, b, rules, constraints): first = "~" + a + "|" + b second = "~" + a + "|" + "~" + b first = prepare_for_SAT(first) second = prepare_for_SAT(second) expression = And(first, second) for k, v in rules.items(): frule = rule_conditional_formula(v) frule = prepare_for_SAT(frule) expression = And(expression, frule) for k, v in constraints.items(): restriction = prepare_for_SAT(v.item) expression = And(expression, restriction) expression = And(expression, Not(b)) print(expression) if satisfiable(expression) == False: return True else: return False
def run(): global step current = exit isExplored = [] isExplored.append(exit) start = 0 while (step < MAX_STEP and start < len(isExplored)): newPath = bfs(current, isExplored[start]) home = bfs(isExplored[start], exit) if (2 * len(newPath) + len(home) + step <= MAX_STEP): for i in newPath: path.append(i) step = step + len(newPath) else: home = bfs(current, exit) for i in home: path.append(i) step = step + len(home) break current = isExplored[start] addToKB(current) tmp = satisfiable(KB) for i in tmp: x = str(i)[1] y = str(i)[2] if ('P' in str(i)): assign[x + y][0] = 1 if tmp[Symbol(str(i))] else 0 if ('W' in str(i)): assign[x + y][1] = 1 if tmp[Symbol(str(i))] else 0 if (assign[x + y] == [0, 0] and not [int(x, 10), int(y, 10)] in isExplored): isExplored.append([int(x, 10), int(y, 10)]) if start < len(isExplored): start = start + 1 calculateScore(current) if start == len(isExplored): home = bfs(current, exit) print(home) for i in home: path.append(i) step = step + len(home)
def check_for_contradictory_domain_desc(self): action_dict = dict() # Maps action name -> Conditions joined by and for i in range(len(self.domain_desc.statements)): statement = self.domain_desc.statements[i] # print(statement) # join action with its causes/releases effect if isinstance(statement, (Causes, Releases)): if statement.action not in action_dict: action_dict[statement.action] = statement.effect.formula action_dict[statement.action] = And( action_dict[statement.action], statement.effect.formula) for action_name, action_cond in action_dict.items(): if not satisfiable(action_cond): # print('action_cond:', action_cond, 'is not satisfiable') self.is_consistent = False break # Uncomment the below if we want to remove actions with unsatisfiable preconditions # I don't think we have to care about this case '''
def check_tolerance(item, sub_rules, constraints): expression = item print(expression) for sub in sub_rules.values(): print("Other: %s" % (sub.item)) other = rule_conditional_formula(sub) print("other before: %s" % (other)) other = prepare_for_SAT(other) print("Other after: %s" % (other)) expression = And(expression, other) for c in constraints.values(): restriction = prepare_for_SAT(c.item) print(restriction) expression = And(expression, restriction) print("expression: %s" % (expression)) if satisfiable(expression): print("true") return True else: print("false") return False
def equals(self, other): """ Returns if the given formulas have the same truth table. For two formulas to be equal they must have the same literals. Examples ======== >>> from sympy.abc import A, B, C >>> from sympy.logic.boolalg import And, Or, Not >>> (A >> B).equals(~B >> ~A) True >>> Not(And(A, B, C)).equals(And(Not(A), Not(B), Not(C))) False >>> Not(And(A, Not(A))).equals(Or(B, Not(B))) False """ from sympy.logic.inference import satisfiable return self.atoms() == other.atoms() and \ not satisfiable(Not(Equivalent(self, other)))
def isSAT(expr): vars = getVars(expr) # a list of all variables used as strings symbs = symbols(" ".join(vars)) # variables converted to sympy symbols if not isinstance( symbs, tuple ): # if only one result is returned, make sure it is still in a list format symbs = [symbs] symbolOf = {} for varNr in range( len(vars) ): # generate a mapping from string variables to sympy symbols symbolOf[vars[varNr]] = symbs[varNr] newexpr = buildExpr( expr, symbolOf ) # build sympy expression using the expression and the symbol mapping cnf = to_cnf(newexpr) # convert the expression to cnf return satisfiable( cnf) != False # return whether or not the expression is satisfiable
def check_tolerance(item, sub_rules, constraints): # Check if a given rule (item) is tolerated by the remaining subset of rules. expression = item #print(expression) for sub in sub_rules.values(): # print("Other: %s" % (sub.item)) other = rule_conditional_formula(sub) #print("other before: %s" % (other)) other = prepare_for_SAT(other) #print ("Other after: %s" % (other)) expression = And(expression, other) for c in constraints.values(): restriction = prepare_for_SAT(c.item) # print(restriction) expression = And(expression, restriction) #print("expression: %s" % (expression)) if satisfiable(expression): # print("true") return True else: # print("false") return False
def initialize_history(self, scenario: Scenario) -> ndarray: fluent_history = ndarray(shape=(self.last_time_point, len(self.fluents)), dtype=Fluent) sorted_observations = sorted(scenario.observations, key=lambda obs: obs.begin_time) assert len(sorted_observations) > 0 ''' for observation in sorted_observations: for key, value in satisfiable(observation.condition.formula).items(): fluent = Fluent(key.name, value) begin_time = observation.begin_time for i in range(len(fluent_history[begin_time])): if fluent_history[begin_time][i] is None: fluent_history[begin_time][i] = fluent break else: continue ''' for key, value in satisfiable( sorted_observations[0].condition.formula).items(): fluent = Fluent(key.name, value) begin_time = sorted_observations[0].begin_time for i in range(len(fluent_history[begin_time])): if fluent_history[begin_time][i] is None: fluent_history[begin_time][i] = fluent break else: continue # Assume inertia law for i in range(fluent_history.shape[0] - 1): for j in range(fluent_history.shape[1]): if fluent_history[i][j] is not None and fluent_history[ i + 1][j] is None: fluent_history[i + 1][j] = deepcopy(fluent_history[i][j]) return fluent_history
def assign_head_extensions(rules, worlds, propositions): for r, rule in rules.items(): props_in_head = set( ) #The process above is repeated for the rule's head for char in str(rule.head): if (char.isalpha()): add = Symbol(char) props_in_head.add(add) #print(props_in_head) props_not_in_head = propositions.difference(props_in_head) supplement = Symbol('') _head = to_cnf(rule.head) for p in props_not_in_head: supplement = Or(p, Not(p)) _head = And(_head, supplement) head_it_sat = satisfiable(_head, all_models=True) head_sat_list = list(head_it_sat) if (len(head_sat_list) == 1 and head_sat_list[0] == False): continue for state in head_sat_list: new = {} for key, value in state.items(): new[key] = value rule.headExtension.append(new)
def equals(self, other): """ Returns if the given formulas have the same truth table. For two formulas to be equal they must have the same literals. Examples ======== >>> from sympy.abc import A, B, C >>> from sympy.logic.boolalg import And, Or, Not >>> (A >> B).equals(~B >> ~A) True >>> Not(And(A, B, C)).equals(And(Not(A), Not(B), Not(C))) False >>> Not(And(A, Not(A))).equals(Or(B, Not(B))) False """ from sympy.logic.inference import satisfiable from sympy.core.relational import Relational if self.has(Relational) or other.has(Relational): raise NotImplementedError('handling of relationals') return self.atoms() == other.atoms() and \ not satisfiable(Not(Equivalent(self, other)))
def ask(proposition, assumptions=True, context=global_assumptions): """ Method for inferring properties about objects. **Syntax** * ask(proposition) * ask(proposition, assumptions) where ``proposition`` is any boolean expression Examples ======== >>> from sympy import ask, Q, pi >>> from sympy.abc import x, y >>> ask(Q.rational(pi)) False >>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) True >>> ask(Q.prime(x*y), Q.integer(x) & Q.integer(y)) False **Remarks** Relations in assumptions are not implemented (yet), so the following will not give a meaningful result. >>> ask(Q.positive(x), Q.is_true(x > 0)) # doctest: +SKIP It is however a work in progress. """ if not isinstance(proposition, (BooleanFunction, AppliedPredicate, bool)): raise TypeError("proposition must be a valid logical expression") if not isinstance(assumptions, (BooleanFunction, AppliedPredicate, bool)): raise TypeError("assumptions must be a valid logical expression") if isinstance(proposition, AppliedPredicate): key, expr = proposition.func, sympify(proposition.arg) else: key, expr = Q.is_true, sympify(proposition) assumptions = And(assumptions, And(*context)) local_facts = _extract_facts(assumptions, expr) if local_facts is not None and satisfiable(And(local_facts, known_facts_cnf)) is False: raise ValueError("inconsistent assumptions %s" % assumptions) # direct resolution method, no logic res = key(expr)._eval_ask(assumptions) if res is not None: return res if assumptions is True: return if local_facts in (None, True): return # See if there's a straight-forward conclusion we can make for the inference if local_facts.is_Atom: if key in known_facts_dict[local_facts]: return True if Not(key) in known_facts_dict[local_facts]: return False elif local_facts.func is And and all(k in known_facts_dict for k in local_facts.args): for assum in local_facts.args: if assum.is_Atom: if key in known_facts_dict[assum]: return True if Not(key) in known_facts_dict[assum]: return False elif assum.func is Not and assum.args[0].is_Atom: if key in known_facts_dict[assum]: return False if Not(key) in known_facts_dict[assum]: return True elif (isinstance(key, Predicate) and local_facts.func is Not and local_facts.args[0].is_Atom): if local_facts.args[0] in known_facts_dict[key]: return False # Failing all else, we do a full logical inference return ask_full_inference(key, local_facts, known_facts_cnf)
def test_satisfiable_bool(): assert satisfiable(True) == {} assert satisfiable(False) == False
if (i == "AND") or (i == "&&") or (i == "and") or (i == "∧"): tokenized_input.append("&") continue # or if (i == "OR") or (i == "||") or (i == "or") or (i == "∨"): tokenized_input.append("|") continue # not if (i == "NOT") or (i == "not") or (i == "!") or (i == "¬"): tokenized_input.append("~") continue # XOR if (i == "XOR") or (i == "xor") or (i == "^"): tokenized_input.append("^") continue tokenized_input.append(i) print("Tokenized: " + str(tokenized_input)) string = " ".join(tokenized_input) print("string: " + string) sym = sympify(str(string), convert_xor=False) sat = satisfiable(sym, all_models=True) for x in sat: # print all possibilities print(x)
def test_satisfiable_1(): """We prove expr entails alpha proving expr & ~B is unsatisfiable""" A, B, C = symbols('ABC') assert satisfiable(A & (A >> B) & ~B) == False
def ask(expr, key, assumptions=True, context=global_assumptions, disable_preprocessing=False): """ Method for inferring properties about objects. **Syntax** * ask(expression, key) * ask(expression, key, assumptions) where expression is any SymPy expression **Examples** >>> from sympy import ask, Q, Assume, pi >>> from sympy.abc import x, y >>> ask(pi, Q.rational) False >>> ask(x*y, Q.even, Assume(x, Q.even) & Assume(y, Q.integer)) True >>> ask(x*y, Q.prime, Assume(x, Q.integer) & Assume(y, Q.integer)) False **Remarks** Relations in assumptions are not implemented (yet), so the following will not give a meaningful result. >> ask(x, positive=True, Assume(x>0)) It is however a work in progress and should be available before the official release """ expr = sympify(expr) if type(key) is not Predicate: key = getattr(Q, str(key)) assumptions = And(assumptions, And(*context)) # direct resolution method, no logic if not disable_preprocessing: res = eval_predicate(key, expr, assumptions) if res is not None: return res if assumptions is True: return if not expr.is_Atom: return assumptions = eliminate_assume(assumptions, expr) if assumptions is None or assumptions is True: return # See if there's a straight-forward conclusion we can make for the inference if not disable_preprocessing: if assumptions.is_Atom: if key in known_facts_dict[assumptions]: return True if Not(key) in known_facts_dict[assumptions]: return False elif assumptions.func is And: for assum in assumptions.args: if assum.is_Atom: if key in known_facts_dict[assum]: return True if Not(key) in known_facts_dict[assum]: return False elif assum.func is Not and assum.args[0].is_Atom: if key in known_facts_dict[assum]: return False if Not(key) in known_facts_dict[assum]: return True elif assumptions.func is Not and assumptions.args[0].is_Atom: if assumptions.args[0] in known_facts_dict[key]: return False # Failing all else, we do a full logical inference # If it's not consistent with the assumptions, then it can't be true if not satisfiable(And(known_facts_cnf, assumptions, key)): return False # If the negation is unsatisfiable, it is entailed if not satisfiable(And(known_facts_cnf, assumptions, Not(key))): return True # Otherwise, we don't have enough information to conclude one way or the other return None
def test_satisfiable(): A, B, C = symbols('A,B,C') assert satisfiable(A & (A >> B) & ~B) is False
def test_satisfiable(): A, B, C = symbols("A,B,C") assert satisfiable(A & (A >> B) & ~B) == False
def eval(variable, expr): if satisfiable(expr) == False: return false return Exist(variable, expr, evaluate=False)