def get_truth_assignment(self, symbol): """ get one set of truth assignment that makes the symbol true :param symbol: logical expression which controls the transition :return: a set of truth assignment enables the symbol """ # empty symbol if symbol == '(1)': return '1' # non-empty symbol else: exp = symbol.replace('||', '|').replace('&&', '&').replace('!', '~') # add extra constraints: a single robot can reside in at most one region robot_region = self.robot2region(exp) for robot, region in robot_region.items(): mutual_execlusion = list(combinations(region, 2)) # single label in the symbol if not mutual_execlusion: continue for i in range(len(mutual_execlusion)): mutual_execlusion[i] = '(~(' + ' & '.join( list(mutual_execlusion[i])) + '))' exp = exp + '&' + ' & '.join(mutual_execlusion) # find one truth assignment that makes symbol true using function satisfiable truth = satisfiable(sympify(exp), algorithm="dpll") try: truth_table = dict() for key, value in truth.items(): truth_table[key.name] = value except AttributeError: return False else: return truth_table
def DelInfesEdge(self, robot): """ Delete infeasible edge :param buchi_graph: buchi automaton :param robot: # robot """ TobeDel = [] # print(self.buchi_graph.number_of_edges()) i = 0 for edge in self.buchi_graph.edges(): i = i+1 # print(i) b_label = self.buchi_graph.edges[edge]['label'] # multiple labels if ') && (' in b_label: TobeDel.append(edge) continue if b_label != '(1)': exp = b_label.replace('||', '|').replace('&&', '&').replace('!', '~') truth = satisfiable(exp, algorithm="dpll") truth_table = dict() for key, value in truth.items(): truth_table[key.name] = value if not truth_table: TobeDel.append(edge) else: self.buchi_graph.edges[edge]['truth'] = truth_table else: self.buchi_graph.edges[edge]['truth'] = '1' for edge in TobeDel: self.buchi_graph.remove_edge(edge[0], edge[1])
def add_transition(self, transition: TransitionType) -> None: """ Add a transition, i.e. a tuple (source, guard, destination). :param transition: the transition to add. :return: None :raise ValueError: if the source state does not exist. :raise ValueError: if the dest state does not exist. """ state1, guard, state2 = transition assert state1 in self.states assert state2 in self.states if isinstance(guard, str): guard = simplify(parse_expr(guard)) other_guard = self._transition_function.get(state1, {}).get(state2, None) if other_guard is None: super().add_transition((state1, guard, state2)) else: outgoing_guards = self._transition_function.get(state1, {}).values() ors = sympy.Or(*outgoing_guards) all_outgoing_guards = sympy.And(ors, guard) if sympy.satisfiable(all_outgoing_guards) is False: super().add_transition((state1, guard, state2)) else: raise ValueError("Transition is not deterministic.")
def inclusion(subtask_lib, subtask_new, tree, end2path): """ whether subtask_lib is included in subtask_new :param subtask_lib: :param subtask_new: :return: """ # trick # no need to build subtree for those who doesn't have self-loop and edge label != 1 []<> ( <>) if subtask_new[1].label == to_dnf( '0') and subtask_new[0].x != subtask_new[1].x: return 'zero' condition = not satisfiable( And(subtask_lib[1].label, Not(subtask_new[1].label))) if subtask_lib[0].x == subtask_new[0].x and subtask_lib[ 1].x == subtask_new[1].x: condition = condition or good_execution( end2path[(subtask_lib[0], subtask_lib[1])], subtask_new[1].label, tree) if condition: return 'forward' elif subtask_lib[0].x == subtask_new[1].x and subtask_lib[ 1].x == subtask_new[0].x: condition = condition or good_execution( end2path[(subtask_lib[0], subtask_lib[1])], subtask_new[1].label, tree) if condition: return 'backward' return ''
def rsolve(self): A = self.INITA.copy() B = self.INITB.copy() C = self.INITC.copy() D = self.INITD.copy() eq = And(*[~(A[i] ^ self.a[i]) & ~(B[i] ^ self.b[i]) & ~(C[i] ^ self.c[i]) & ~(D[i] ^ self.d[i]) for i in range(32)]) print("Equation:",eq) return satisfiable(eq)
def determinize(self) -> "SymbolicDFA": """Do determinize.""" macro_initial_state = frozenset([self._initial_state ]) # type: FrozenSet[int] stack = [macro_initial_state] visited = {macro_initial_state} macro_accepting_states = ( {macro_initial_state} if macro_initial_state.intersection(self.accepting_states) != set() else set()) # type: Set[FrozenSet[int]] moves = set() # given an iterable of transitions (i.e. triples (source, guard, destination)), # get the guard def getguard(x): return map(operator.itemgetter(1), x) # given ... (as before) # get the target def gettarget(x): return map(operator.itemgetter(2), x) while len(stack) > 0: macro_source = stack.pop() transitions = set([ (source, guard, dest) for source in macro_source for dest, guard in self._transition_function.get(source, {}).items() ]) for transitions_subset in map(frozenset, iter_powerset(transitions)): if len(transitions_subset) == 0: continue transitions_subset_negated = transitions.difference( transitions_subset) phi_positive = And(*getguard(transitions_subset)) phi_negative = And( *map(Not, getguard(transitions_subset_negated))) phi = phi_positive & phi_negative if sympy.satisfiable(phi) is not False: macro_dest = frozenset( gettarget(transitions_subset)) # type: FrozenSet[int] moves.add((macro_source, phi, macro_dest)) if macro_dest not in visited: visited.add(macro_dest) stack.append(macro_dest) if macro_dest.intersection( self.accepting_states) != set(): macro_accepting_states.add(macro_dest) return self._from_transitions(visited, macro_initial_state, set(macro_accepting_states), moves)
def greatest_fixpoint_condition(el: Tuple[int, int], current_set: Set): """Condition to say whether the pair must be removed from the bisimulation relation.""" # unpack the two states s_source, t_source = el for (s_dest, s_guard) in dfa._transition_function.get(s_source, {}).items(): for (t_dest, t_guard) in dfa._transition_function.get(t_source, {}).items(): if (t_dest != s_dest and (s_dest, t_dest) not in current_set and satisfiable(And(s_guard, t_guard)) is not False): return True
def satsolver_main(): prop = open('/home/wrick/Documents/logia/prop', 'r').readline().strip() # of the form -- Proposition name : forall p q r :Prop, expression. expr = prop.split(',')[-1].strip('.').strip() # expression without leading space or trailing . varnames = prop.split(':')[1].strip()[7:].replace(' ', ',') # store the names of the variables as a string, split with ',' varlist = list(symbols(varnames)) # create and store the symbols themselves in a list --- ERROR!!! symbols is not iterable try: models = [] sat = satisfiable(expr, all_models = True) while True: models.append(next(sat)) except StopIteration: pass return(models)
def inclusion(subtask_lib, subtask_new): """ whether subtask_lib is included in subtask_new :param subtask_lib: :param subtask_new: :return: """ # if Equivalent(subtask_lib[0].label, subtask_new[0].label): # print(subtask_lib[0].label, subtask_new[0].label) # A included in B <=> does no exist a truth assignment such that (A & not B) is true if not satisfiable(And(subtask_lib[0].label, Not(subtask_new[0].label))): if subtask_lib[0].x == subtask_new[0].x and subtask_lib[1].x == subtask_new[1].x: return 'forward' elif subtask_lib[0].x == subtask_new[1].x and subtask_lib[1].x == subtask_new[0].x: return 'backward' return ''
def is_complete(self) -> bool: """ Check whether the automaton is complete. :return: True if the automaton is complete, False otherwise. """ # all the state must have an outgoing transition. if not all(state in self._transition_function.keys() for state in self.states): return False for source in self._transition_function: guards = self._transition_function[source].values() negated_guards = Not(Or(*guards)) if satisfiable(negated_guards): return False return True
def target(exp, regions): """ find the target location :param label: word :return: target location/region """ target = [] if exp != to_dnf('1'): # a set of target points for dnf in exp.args or [exp]: truth_table = satisfiable(dnf, algorithm="dpll") # find the target point with true value for key, value in truth_table.items(): if value: des = key.name.split('_')[0] target.append(regions[des]) return target
def models_with_all_atoms(formula, atoms): """Takes a formula and a set of atoms (that do not necessarily appear in the formula), and returns a set of *models* of the formula, where each model is represented by a *dictionary* that maps each atom to a Boolean value, where atoms are drawn from the set of atoms that appear in ``formula`` *and* the set of atoms represented by ``atoms``. Parameters ---------- formula : A Sympy formula. atoms : A set of Sympy atoms. Example ------- >>> p,q,r = [eb.parse_formula(letter) for letter in "pqr"] >>> f = p | q >>> eb.models_with_all_atoms(f, {p,q}) [{p: True, q: True}, {p: True, q: False}, {p: False, q: True}] >>> eb.models_with_all_atoms(f, {p,q,r}) [{p: True, q: True, r: True}, {p: True, q: True, r: False}, {p: True, q: False, r: True}, {p: True, q: False, r: False}, {p: False, q: True, r: True}, {p: False, q: True, r: False}] """ if formula == True: return [model for model in tablize(atoms)] original_models = [model for model in satisfiable(formula, all_models=True)] extra_atoms = atoms - formula.atoms() if not extra_atoms: return original_models else: models_all_atoms = [] for model in original_models: models_all_atoms += [updated_model for updated_model in tablize(extra_atoms, model)] return models_all_atoms
def inclusion(subtask_lib, subtask_new, tree, end2path): """ whether subtask_lib is included in subtask_new :param subtask_lib: :param subtask_new: :return: """ # if Equivalent(subtask_lib[0].label, subtask_new[0].label): # print(subtask_lib[0].label, subtask_new[0].label) # A included in B <=> does no exist a truth assignment such that (A & not B) is true # if not satisfiable(And(subtask_lib[0].label, Not(subtask_new[0].label))): # if subtask_lib[0].x == subtask_new[0].x and subtask_lib[1].x == subtask_new[1].x: # return 'forward' # elif subtask_lib[0].x == subtask_new[1].x and subtask_lib[1].x == subtask_new[0].x: # return 'backward' # # return '' # if subtask_new[0].label == to_dnf('0'): # return 'zero' condition = not satisfiable( And(subtask_lib[0].label, Not(subtask_new[0].label))) if subtask_lib[0].x == subtask_new[0].x and subtask_lib[ 1].x == subtask_new[1].x: condition = condition or good_execution( end2path[(subtask_lib[0], subtask_lib[1])], subtask_new[0].label, tree) if condition: return 'forward' elif subtask_lib[0].x == subtask_new[1].x and subtask_lib[ 1].x == subtask_new[0].x: condition = condition or good_execution( end2path[(subtask_lib[0], subtask_lib[1])], subtask_new[0].label, tree) if condition: return 'backward' return ''
def complete(self) -> "SymbolicAutomaton": """Complete the automaton.""" states = set(self.states) initial_state = self.initial_state final_states = self.accepting_states transitions = set() sink_state = None for source in states: transitions_from_source = self._transition_function.get(source, {}) transitions.update( set( map(lambda x: (source, x[1], x[0]), transitions_from_source.items()))) guards = transitions_from_source.values() guards_negation = simplify(Not(Or(*guards))) if satisfiable(guards_negation) is not False: sink_state = len(states) if sink_state is None else sink_state transitions.add((source, guards_negation, sink_state)) if sink_state is not None: states.add(sink_state) transitions.add((sink_state, BooleanTrue(), sink_state)) return SymbolicAutomaton._from_transitions(states, initial_state, final_states, transitions)
from sympy import pprint, satisfiable, to_cnf, simplify import networkx as nx import equibel as eb def print_formulas(G): for node in G.nodes(): print("Node {}:".format(node)) pprint(G.formula_conj(node)) #pprint(simplify(G.formula_conj(node))) #pprint(to_cnf(G.formula_conj(node), simplify=True)) print("\n") if __name__ == '__main__': G = eb.path_graph(5) G.add_formula(2, '(x1 & ~x4) | (x4 & ~x1) | ~x5') G.add_formula(3, 'x4 | ~x2 | ~x3') G.add_formula(4, '~x3 & (x4 | ~x5) & (x5 | ~x4)') print_formulas(G) G, num_iterations = eb.iterate_steady(G) print_formulas(G) print(G.formula_conj(0)) for model in satisfiable(G.formula_conj(0), all_models=True): print(model) print("Num iterations = {}".format(num_iterations))
def _make_transition(marco_q: FrozenSet[FrozenSet[PLAtomic]], i: PropositionalInterpretation): new_macrostate = set() for q in marco_q: # delta function applied to every formula in the macro state Q delta_formulas = [cast(Delta, f.s).delta(i) for f in q] # find atomics -> so also ldlf formulas # replace atomic with custom object # convert to sympy # find the list of atoms, which are "true" atoms # (i.e. propositional atoms) or LDLf formulas atomics = [s for subf in delta_formulas for s in find_atomics(subf)] atom2id = {v: str(k) for k, v in enumerate(atomics)} # type: Dict[PLAtomic, str] id2atom = {v: k for k, v in atom2id.items()} # type: Dict[str, PLAtomic] # build a map from formula to a "freezed" propositional Atomic Formula formula2atomic_formulas = { f: PLAtomic(atom2id[f]) if f != PLTrue() and f != PLFalse() # and not isinstance(f, PLAtomic) else f for f in atomics } # the final list of Propositional Atomic Formulas, # one for each formula in the original macro state Q transformed_delta_formulas = [ _transform_delta(f, formula2atomic_formulas) for f in delta_formulas ] # the empty conjunction stands for true if len(transformed_delta_formulas) == 0: conjunctions = PLTrue() elif len(transformed_delta_formulas) == 1: conjunctions = transformed_delta_formulas[0] else: conjunctions = PLAnd(transformed_delta_formulas) # type: ignore # the model in this case is the smallest set of symbols # s.t. the conjunction of "freezed" atomic formula is true. # alphabet = frozenset(symbol2formula) # models = frozenset(conjunctions.minimal_models(alphabet)) formula = to_sympy(conjunctions, replace=atom2id) # type: ignore all_models = list(sympy.satisfiable(formula, all_models=True)) if len(all_models) == 1 and all_models[0] == BooleanFalse(): models = [] # type: List[Set[str]] elif len(all_models) == 1 and all_models[0] == {True: True}: models = [set()] else: models = list( map(lambda x: {k for k, v in x.items() if v is True}, all_models)) for min_model in models: q_prime = frozenset({id2atom[s] for s in map(str, min_model)}) new_macrostate.add(q_prime) return frozenset(new_macrostate)
from sympy import pprint, simplify, satisfiable import equibel as eb if __name__ == '__main__': formula = eb.random_formula(num_atoms=6, num_connectives=10) pprint(formula) for model in satisfiable(formula, all_models=True): print(model) simplified = simplify(formula) pprint(simplified)
# Build the solution to part A. part_a_conjuncts = [] for pigeon in xrange(1, 5): term1 = And(P[pigeon][1], Not(P[pigeon][2]), Not(P[pigeon][3])) term2 = And(Not(P[pigeon][1]), (P[pigeon][2]), Not(P[pigeon][3])) term3 = And(Not(P[pigeon][1]), Not(P[pigeon][2]), (P[pigeon][3])) # Build the conjunction of the disjuncts. part_a_conjuncts.append(Or(term1, term2, term3)) # Build part A using conjuncts. part_a = And(part_a_conjuncts[0], part_a_conjuncts[1], part_a_conjuncts[2], part_a_conjuncts[3]) print "PartA is satisfiable with the assignment:" print str(satisfiable(part_a)) + "\n\n\n" # Build part B. part_b = False for hole in xrange(1, 4): part_b = Or(part_b, And(P[1][hole], P[2][hole])) part_b = Or(part_b, And(P[1][hole], P[3][hole])) part_b = Or(part_b, And(P[1][hole], P[4][hole])) part_b = Or(part_b, And(P[2][hole], P[3][hole])) part_b = Or(part_b, And(P[2][hole], P[4][hole])) part_b = Or(part_b, And(P[3][hole], P[4][hole])) print "PartB is satisfiable with the assignment:" print str(satisfiable(part_b)) + "\n\n\n" # Pigeon Hole Principle php = And(part_a, part_b)
rightSide = functools.reduce(lambda x,y:x^y, [False]+InitialWallaceWeights('n',n,'k',n,i,toAddToRightSide,rightSideLeftOvers)).subs(rightSideKnowns).subs(substitutes) rightSideLeftOvers = [rightSideTerm.subs(rightSideKnowns).subs(substitutes) for rightSideTerm in rightSideLeftOvers] # replacing n digits if shouldSubN: rightSide = rightSide.subs(n_Subs) rightSideLeftOvers = [rightSideTerm.subs(n_Subs) for rightSideTerm in rightSideLeftOvers] toAddToLeftSide = leftSideLeftOvers toAddToRightSide = rightSideLeftOvers equations.append((leftSide,rightSide)) # adding new term to equalitis for new k newKkey = 'k{}'.format(len(equations)-1) if newKkey in D: substitutes[D[newKkey]] = equations[-1][0]^sympy.simplify_logic(equations[-1][1]^D[newKkey]) else: satEquation = sympy.Equivalent(equations[-1][0],sympy.simplify_logic(equations[-1][1])) & satEquation print((bcolors.HEADER+"w:{:>2}"+bcolors.ENDC+" {:>"+str(math.floor(shutil.get_terminal_size((80,20))[0]/2)-2-3)+"}").format(i,sympy.pretty(equations[-1][0]))+bcolors.OKGREEN+" = "+bcolors.ENDC+sympy.pretty(equations[-1][1])) i += 1 #print("number of terms in CNF for satisfiability: {}".format(len(to_cnf(satEquation.args)))) if shouldSubN & shouldSolve: print("=======Sat Equation=======") simplifiedSat = sympy.simplify_logic(satEquation) print(simplifiedSat) print("=Satisfiability solutions=") allModels = list(sympy.satisfiable(simplifiedSat,all_models=True)) print(", ".join(map(str,[2*functools.reduce(lambda x,y:2*x+y, [0]+[int(model[D[x]]) for x in ["a{}".format(i+1) for i in reversed(range(n-1))]])+1 for model in allModels])))
def is_sat(formula, gt): return satisfiable(formula.subs(gt)) != False
# Tekijöihin jakoa: # In[186]: poly = x**4 - 3*x**2 + 1 # In[188]: from sympy import factor factor(poly) # In[189]: factor(poly,modulus=5) # Boolean lausekkeita # In[191]: from sympy import satisfiable satisfiable(x & y)
def solve_problem_no_teams(kb, kb_symbols, data_q, undefined, queries, num_of_observations, row_num, col_num, possible_states): answer = {} change = True police_num, medic_num= 0, 0 kb_symbols = spreader(kb_symbols, undefined, kb, row_num, col_num, data_q, possible_states, police_num) while change: undefined_copy = undefined.copy() undefined_copy.reverse() for und in undefined_copy: isS = is_S(und, row_num, col_num, num_of_observations) kb_S = sympy.And(~isS, kb_symbols) kb_S_cnf = sympy.to_cnf(kb_S) res = sympy.satisfiable(kb_S_cnf) if not res: new_S = und + '_S' data_q.append(new_S) kb.append(new_S) undefined.remove(und) new_S = sympy.symbols(new_S) kb_symbols = sympy.And(kb_symbols, new_S) no_H = und + '_H' data_q.append('~' + no_H) no_H = sympy.symbols(no_H) kb_symbols = sympy.And(kb_symbols, ~no_H) no_U = und + '_U' if '~' + no_U not in data_q: data_q.append('~' + no_U) no_U = sympy.symbols(no_U) kb_symbols = sympy.And(kb_symbols, ~no_U) else: isH = is_H(und, row_num, col_num, police_num, medic_num, num_of_observations) kb_H = sympy.And(~isH, kb_symbols) kb_H_cnf = sympy.to_cnf(kb_H) res = sympy.satisfiable(kb_H_cnf) if not res: new_H = und + '_H' data_q.append(new_H) kb.append(new_H) undefined.remove(und) new_H = sympy.symbols(new_H) kb_symbols = sympy.And(kb_symbols, new_H) no_S = und + '_S' data_q.append('~' + no_S) no_S = sympy.symbols(no_S) kb_symbols = sympy.And(kb_symbols, ~no_S) no_U = und + '_U' if '~' + no_U not in data_q: data_q.append('~' + no_U) no_U = sympy.symbols(no_U) kb_symbols = sympy.And(kb_symbols, ~no_U) kb_symbols = spreader(kb_symbols, undefined, kb, row_num, col_num, data_q, possible_states, police_num) if set(undefined_copy) == set(undefined): change = False for quer in queries: place, number, s = quer i, j = place q = '{}_{}_{}_{}'.format(i, j, number, s) if q in data_q: answer[quer] = 'T' elif '~' + q in data_q: answer[quer] = 'F' else: answer[quer] = '?' return answer
def solve(self, H): A,B,C,D = self.HtoABCD(H) eq = And(*[~(A[i] ^ self.a[i]) & ~(B[i] ^ self.b[i]) & ~(C[i] ^ self.c[i]) & ~(D[i] ^ self.d[i]) for i in range(32)]) print("Equation:",eq) return satisfiable(eq)