def CreateKB(kb, clauses): while clauses: clause, clauses = Clause.NextClause(clauses) clause_type = Clause.Categorize(clause) if clause_type == 'fact': fact = Fact.ParseFact(clause) kb.AddFact(fact) elif clause_type == 'rule': if ';' in clause: idx = clause.index(':-') temp_clause = clause[idx + 2:].rstrip('.') conclusion = clause[0:idx] conditions_raw = temp_clause.split(';') conditions = [] for condition in conditions_raw: temp = condition.strip() temp = temp[1:len(temp) - 1] conditions.append(temp) rules = [] for condition in conditions: rule_str = conclusion + ':-' + condition + '.' rules.append(rule_str) for clause in rules: rule = Rule.ParseRule(clause) kb.AddRule(rule) elif ';' not in clause: rule = Rule.ParseRule(clause) kb.AddRule(rule)
def __help_fun(c1, c2, sos_new, sos_stage, clauses, clause_to_number, steps): # TODO refactor if c1 == c2: return [False, steps] for resolvent in Clause.pl_resolve(c1, c2): if resolvent and Clause.cnf_tautology(resolvent): continue if Clause.simplify_sets_by_clause_for_subsets( resolvent, sos_new, sos_stage, clauses): break if resolvent not in clause_to_number: n1 = clause_to_number[c1] n2 = clause_to_number[c2] n1, n2 = (n2, n1) if (n1 > n2) else (n1, n2) steps += "{}. {} ({}, {})\n".format( Resolution.clause_counter, Clause.clause_to_string(resolvent) if resolvent else "NIL", n1, n2) clause_to_number[resolvent] = Resolution.clause_counter Resolution.clause_counter += 1 sos_new.add(resolvent) if not resolvent: return tuple([True, steps]) return [False, steps]
def loadClauses(self, clausesNode): for item in clausesNode.findall("clause") : clause = Clause(self) id = item.get("id") clause.loadXML(item) self.clauses[id] = clause order = clausesNode.find('order').text clausesOrder = [] if (order is not None) : clausesOrder = order.split(';') for clauseID in clausesOrder : self.clausesOrder.append(self.getName() + ":" + clauseID)
def test_assign(self: TestClause): clause = Clause([-6, 5, -4, 3, -2, 1]) a1 = Assignment(set([1, 2, 3, 4, 5, 6])) a1.add_assignment(0, 6, 1, None) clause.assign(a1) self.assertEqual(clause.get_state(a1), (Clause.UNRESOLVED, 5, 1)) self.assertEqual(clause.get_assigned_vars(a1), [6]) a1.add_assignment(1, 5, 0, None) a1.add_assignment(2, 4, 1, None) a1.add_assignment(2, 1, 0, None) clause.assign(a1) self.assertEqual(clause.get_state(a1), (Clause.UNRESOLVED, 3, 2)) self.assertEqual(clause.get_assigned_vars(a1), [6, 5, 4, 1])
def _add_base_clause(self: Formula, clause: List[int]) -> None: """Add a clause to the formula, only during initialization. """ clause_object = Clause(clause) self.formula.append(clause_object) head_var, tail_var = clause_object.get_head_tail_var() if head_var not in self.variable_clauses: self.variable_clauses[head_var] = set() self.variable_clauses[head_var].add(clause_object) if tail_var not in self.variable_clauses: self.variable_clauses[tail_var] = set() self.variable_clauses[tail_var].add(clause_object) if len(clause) == 1: self.unit_clauses.add(clause_object)
def __init__(self, clause_list, model): self.clauses = [ Clause(cl, model, _id) for (_id, cl) in enumerate(clause_list, 0) ] self.learnt_clauses = [] self.watched_var_dict = self._make_dict() self._make_dict()
def from_cnf_lines(lines): ''' This maybe not be the canonical cnf format (e.g. http://people.sc.fsu.edu/~jburkardt/data/cnf/cnf.html ) I am not allowing multi-line clauses because that is f*****g retarded. :param lines: :return: ''' p = Problem() varcount = 0 for line in lines: line = line.strip() #trim if line == "": continue elif "c" == line[0].lower(): p.addComment(line) elif "p" == line[0].lower(): #p {problem type} {varcount} {clausecount} _, problem_type, varcount, clausecount = line.split() else: numbers = [int(s) for s in line.split()] c = Clause.fromCnfArray(numbers) p.add(c) #TODO: !!!!! normalize, and fix varcount #TODO: useful exception handling? return p
def start(self, description=None, **options): super(SCryptoMinisatEngine, self).start(description, **options) self.start_time = time.time() if not self.cnf: vars = sorted(self.description.get_variables(), key=lambda x: not x.name.startswith("AB")) self.vars = TwoWayDict( dict((i, v.name) for i, v in enumerate(vars))) self.ab_vars = [ i for i, n in self.vars.iteritems() if n.startswith("AB") ] # add clauses for the input/output variables which are constrained self.core_map = {} self.clauses = [] for s in self.description.get_sentences(): self.clauses.extend(self.sentence_interpreters[type(s)]( self, s, self.vars)) for v in self.description.get_variables(): if v.value is not None: self.clauses.append(Clause([Literal(v.name, v.value)])) for c in self.clauses: self.cnf += "\n" + to_dimacs_clause(c, self.vars) self.stats['cnf_clauses'] = len(self.clauses) self.max_out = max(self.ab_vars) + 1 return self.solve()
def read_from_file(cls, filepath): """ Create an instance of Sentences from an input file. This file format is given by the professor for this class. Args: filepath <str>: the filepath to the input file. Returns: <sentences.Sentences>: an instance of the Sentences class with the given clauses in the input file. """ clauses = [] f = open(filepath) # First read in the clauses for line in f: clause = [] if line[0] == '0': break else: line = line.strip().split(' ') for l in line: clause.append(Atom(l)) clauses.append(Clause(clause)) # Then read in the rest of the input file for the translation rest_of_input = [] for line in f: rest_of_input.append(line) return cls(clauses, rest_of_input)
def start(self, description=None, **options): super(PicoSatEngine, self).start(description, **options) if not self.cnf: self.vars = TwoWayDict( dict((i, v.name) for i, v in enumerate(self.description.get_variables()))) # add clauses for the input/output variables which are constrained sentences = self.description.get_sentences() for v in self.description.get_variables(): if v.value is not None: sentences.append(Clause([Literal(v.name, v.value)])) self.core_map = {} self.clauses = self.interpret_sentences(sentences) self.cnf = "p cnf %d %d" % (max(self.vars.keys()) + 1, len(self.clauses)) for c in self.clauses: self.cnf += "\n" + to_dimacs_clause(c, self.vars) # print self.cnf p = PicoSatWrapper() p.start(self.cnf, calculate_unsat_core=True) # print "\n".join(outlines) self.result = self.parse_output(p.outlines, self.vars, p.get_core_file_name()) return self.result
def load_facts(filepath) -> List: _clauses = [] with open(filepath, "r+") as file: for line in file.read().splitlines(): if line.startswith("#") or not line.strip(): continue _clauses.extend(Clause.parse_to_clauses(line.strip())) return _clauses
def __init__(self, facts: Set, debug: bool): self._knowledge = facts self._debug = debug if debug: print("Resolution system constructed with knowledge:") for clause in facts: print("> " + Clause.clause_to_string(clause))
def autocnf_from_file(filepath): output = [] with open(filepath, "r+") as file: for line in file.read().splitlines(): if line.startswith("#") or not line.strip(): continue cnf_format = Node(line.lower()).evaluate() output.append(Clause.clauses_to_string(cnf_format)) return "\n".join(output)
def add_clause(self: Formula, clause: List[int]) -> None: """Add a clause to the formula after initialization. :param clause: a list of `Literal`s that are contained in the clause; each variable must appear in `clause` at most once. `clause` cannot contain literals in variables not already present in the representation. """ clause_object = Clause(clause) clause_object.assign(self.assignment) self.formula.append(clause_object) # update mutation history and state history old_head_var, old_tail_var = clause_object.get_head_tail_var() was_valid = False was_unsat = len(clause) == 0 for d in range(0, self.decision_level + 1): clause_object.assign_decision_level(self.assignment, d) state, head_var, tail_var = clause_object.get_state( self.assignment.get_assignment_at_level(d)) if head_var != old_head_var or tail_var != old_tail_var: self.mutation_history[d].add(clause_object) # can actually be commented out since we never make # decisions while the formila is valid or unsat was_valid = was_valid or state == Clause.SATISFIED was_unsat = was_unsat or state == Clause.UNSATISFIED if self.state_history[d] == Formula.SATISFIED and not was_valid: self.state_history[d] = Formula.UNRESOLVED if was_unsat: self.state_history[d] = Formula.UNSATISFIED # update current state state, head_var, tail_var = clause_object.get_state(self.assignment) if state == Clause.UNRESOLVED or state == Clause.UNIT: if head_var not in self.variable_clauses: self.variable_clauses[head_var] = set() self.variable_clauses[head_var].add(clause_object) if tail_var not in self.variable_clauses: self.variable_clauses[tail_var] = set() self.variable_clauses[tail_var].add(clause_object) # update unit clauses if state == Clause.UNIT: self.unit_clauses.add(clause_object) # update unsat clauses if state == Clause.UNSATISFIED: self.unsat_clauses.add(clause_object)
def evaluate(self): # return self._evaluate() result_clean = set() for clause in self._evaluate(): if not Clause.cnf_tautology(clause) and clause != frozenset(): result_clean.add(clause) if not result_clean: return {frozenset()} else: return result_clean
def parseCommand(line: str): parts = line.strip().rsplit(maxsplit=1) if len(parts) != 2: raise ValueError( 'Given command "{}" is not of valid format.'.format(line)) command = parts[1] clauses = Clause.parse_to_clauses(parts[0]) if len(clauses) != 1: raise ValueError("Given command clause must be in CNF!") return tuple([clauses.pop(), command])
def executeCommand(self, command): if command[1] == "?": print(self.query(command[0])) elif command[1] == "-": removed = self.remove_from_knowledge(command[0]) if self._debug: if not removed: print(Clause.clause_to_string(command[0]), "already removed") else: print("removed", Clause.clause_to_string(command[0])) elif command[1] == "+": added = self.add_to_knowledge(command[0]) if self._debug: if not added: print(Clause.clause_to_string(command[0]), "already added") else: print("added", Clause.clause_to_string(command[0])) else: raise ValueError( 'Command "' + str(command[1]) + '" is not recognized. Command found in:', str(command))
def check_deduction(facts, goal_clause, debug: bool = False) -> (str, str): output = "" (prove_true, steps_true) = Resolution.refute_by_resolution_proof( facts, {goal_clause}) if debug: output += steps_true + "\n\n" if prove_true: check_result = "true" return tuple([ check_result, output + Clause.clause_to_string(goal_clause) + " is " + check_result ]) (prove_false, steps_false) = Resolution.refute_by_resolution_proof( facts, Clause.cnf_negated({goal_clause})) if debug: output += steps_false + "\n\n" check_result = "false" if prove_false else "unknown" return tuple([ check_result, output + Clause.clause_to_string(goal_clause) + " is " + check_result ])
def create_yices_code(self): code = [] for v in self.description.get_variables(): self.vars[v.name] = self.next_var self.next_var += 1 if v.value is not None: code.append( self.to_dimacs_clause( Clause([Literal(v.name, v.value)], weight=self.MAX_WEIGHT + 1), self.vars)) for s in self.description.get_sentences(): for c in self.sentence_interpreters[type(s)](self, s, None): code.append(self.to_dimacs_clause(c, self.vars)) return len(code), "\n".join(code)
def setClause(self): title = unicode(self.ui.titleEdit.text()) parent = unicode(self.ui.parentBox.currentText()) self.clause = Clause() self.clause.setTitle(title) self.clause.setType(self.project.getTIM().getType(unicode(self.ui.typeBox.currentText()))) self.document = self.project.getDocument(unicode(self.ui.documentBox.currentText())) self.document.addClause(self.clause) if (parent != "Sem Clausula Pai") : parentClause = self.clausesList[unicode(self.ui.parentBox.currentText())] link = Link() link.addChild(self.clause.getID()) link.addParent(parentClause) link.consolidateLink(self.project) self.openElementSignal.emit("clause:" + self.clause.getID())
def from_str(klass, string): """ Creates a mapping from a string Parameters ---------- string : str String of the form `target<=clause` Returns ------- caspo.core.mapping.Mapping Created object instance """ if "<=" not in string: raise ValueError("Cannot parse the given string to a mapping") target,clause_str = string.split('<=') return klass(Clause.from_str(clause_str), target)
def read_input(file): cnf = [] f = open(file, "r") clause_id = 0 for line in f: if len(line) < 3: continue if line[0] in ["c", "p", "%"]: continue # props = strip(line)[:-1].split() # get rid of the trailing 0 props = (line[:-2] ).split() # for lines, last character is newline character. clause = Clause(clause_id, props) cnf.append(clause) clause_id += 1 return Form(cnf)
def resolve(self, clause1, clause2): # Store that these two clauses have been resolved self.resolvedClauses.append(set([clause1, clause2])) # Get the resolution of the two clauses newClauseLiterals = self.getResolution(clause1, clause2) # Create a new Clause object newClause = Clause(' '.join(newClauseLiterals), len(self.clauses) + 1) self.clauses.append(newClause) printedClause = ' '.join(newClauseLiterals) if len( newClause.literals) > 0 else 'False' # Print the resolution info self.printLine(newClause.id, printedClause, True, clause1.id, clause2.id) return len(newClause.literals) == 0
def start(self, description=None, **options): super(YicesCnEngine, self).start(description, **options) if not self.cnf: vars = sorted(self.description.get_variables(), key=lambda x: not x.name.startswith("AB")) self.vars = TwoWayDict( dict((i, v.name) for i, v in enumerate(vars))) self.ab_vars = [ i for i, n in self.vars.iteritems() if n.startswith("AB") ] sentences = self.description.get_sentences() for v in self.description.get_variables(): if v.value is not None: sentences.append(Clause([Literal(v.name, v.value)])) self.core_map = {} self.clauses = self.interpret_sentences(sentences) for c in self.clauses: self.cnf += "\n" + self.to_dimacs_clause(c, self.vars) self.stats['cnf_clauses'] = len(self.clauses) self.construct_cardinality_network(**options) self.stats['num_rules'] = self.stats.get( 'cnf_clauses', 0) + self.stats.get('net_clauses', 0) + 1 self.stats['num_vars'] = max(self.cn.vars) # cnf = "p cnf %d %d\n" % (self.stats['num_vars'], self.stats['num_rules']) + self.cnf + self.cnf_cn cnf = self.cnf + self.cnf_cn cnf += "\n\n-%d 0\n" % self.cn.vars[options.get('max_card', 1)] p = SimpleYicesWrapper() p.start( SimpleDescription(cnf, self.stats['num_vars'], self.stats['num_rules'])) self.result = self.parse_output(p.outlines, self.vars, self.ab_vars) return self.result
def resolution(kb, alpha): steps = [] entail = False alpha.negate() clauses = set(kb.clauses) clauses.add(alpha) while True: new_clauses = set() for (ci, cj) in itertools.combinations(sorted(clauses), 2): resolvents, contradict = Clause.resolve(ci, cj) new_clauses.update(resolvents) entail |= contradict generated_clauses = sorted(new_clauses.difference(clauses)) steps.append(generated_clauses) clauses.update(new_clauses) if entail: return True, steps if not generated_clauses: return False, steps
def generate(self): num_of_var = self.num_of_var + self.get_variation(self.num_of_var) num_of_clause = self.num_of_clause + self.get_variation( self.num_of_clause) clause_list = list() for i in range(num_of_clause): num_of_var_per_clause = self.num_of_var_per_clause + self.get_variation( self.num_of_var_per_clause) var_list = list() for j in range(num_of_var_per_clause): signal = 1 if rd() > 0.5: signal = -1 var_str = str(int(signal * round(num_of_var * rd() + 1))) var = Variable(var_str) var_list.append(var) clause = Clause(var_list) clause_list.append(clause) cnf = Cnf(clause_list) return cnf
def checkSpaces(self, project): project = Project() doc2Clause = project.getDocument2ClausesDict() windows = [] orphans = [] for documentName in doc2Clause: document = project.getDocument(documentName) for clauseId in doc2Clause[documentName]: clause = document.getClause(clauseId) clause = Clause() clauseType = clause.getType() parentsNeeded = {} childrenNeeded = {} possibleChildren = clauseType.getPossibleChildrenList() for child in possibleChildren: childrenNeeded[child] = clauseType.getChildMinCard(child) childLinks = clause.getChildClausesList() for childId in childLinks: child = clause.getChildLinkClause(childId) childTypeName = child.getType().getName() if child.getType().getName() in clauseType.getPossibleChildrenList(): childrenNeeded[childTypeName] -= 1 for need in childrenNeeded.keys(): if childrenNeeded[need] > 0 : windows.append(clauseId, need) possibleParents = clauseType.getPossibleParentsList() for parent in possibleParents: parentsNeeded[parent] = clauseType.getParentMinCard(parent) for parent in possibleParents: parentsNeeded[parent] = clauseType.getParentMinCard(parent) parentLinks = clause.getParentClausesList() for parentId in parentLinks: parent = clause.getParentLinkClause(parentId) parentTypeName = parent.getType().getName() if parent.getType().getName() in clauseType.getPossibleParentsList(): parentsNeeded[parentTypeName] -= 1 for need in parentsNeeded.keys(): if parentsNeeded[need] > 0 : windows.append(clauseId, need) return (windows, orphans)
def _evaluate(self): left_cnf = self.left.evaluate() if isinstance(self.left, Node) else self.left if self.left_negated: left_cnf = Clause.cnf_negated(left_cnf) if self.right is None: return left_cnf right_cnf = self.right.evaluate() if isinstance(self.right, Node) else self.right if self.right_negated: right_cnf = Clause.cnf_negated(right_cnf) if self.operator == "v": return Clause.disjunctionOperator(left_cnf, right_cnf) elif self.operator == "&": return Clause.conjunctionOperator(left_cnf, right_cnf) elif self.operator == "=": return Clause.equalityOperator(left_cnf, right_cnf) elif self.operator == ">": return Clause.implicationOperator(left_cnf, right_cnf) else: raise ValueError("Invalid operator! '{}'".format(self.operator))
def declare(kb, list_clause_str): for clause_str in list_clause_str: clause = Clause.parse_clause(clause_str) clause.flatten() kb.add(clause)
def make_singleton_clause(l): return Clause(-1, [l])
from knowledge_base import KnowledgeBase from clause import Clause from resolution import resolution # Edit input and output file here test_case = input().strip() inp_file = 'test/' + test_case + '.txt' outp_file = 'test/' + test_case + '_out.txt' kb = KnowledgeBase() with open(inp_file, 'r') as f: alpha = Clause.parse_clause(f.readline()) num_clauses = f.readline() clauses = f.readlines() KnowledgeBase.declare(kb, clauses) f.close() print('Done reading from', inp_file) entail, new_clauses = resolution(kb, alpha) with open(outp_file, 'w') as f: for clauses in new_clauses: f.write('{}\n'.format(len(clauses))) for clause in clauses: f.write('{}\n'.format(clause)) f.write('{}'.format('YES' if entail else 'NO')) print('Done writing to', outp_file)
def addClause(self, clauseText): self.clauses.append(Clause(clauseText, len(self.clauses) + 1))
class NewClauseDialog(QDialog): openElementSignal = pyqtSignal(str) def __init__(self, parent, project, document=None, parentClause=None): super(NewClauseDialog, self).__init__(parent) self.project = project self.document = document self.ui = Ui_NewClauseDialog.Ui_NewClauseDialog() self.ui.setupUi(self) documentList = self.project.getDocumentsList() self.ui.documentBox.addItems(documentList) if (self.document is not None): self.ui.documentBox.setCurrentIndex(self.ui.documentBox.findText(self.document.getName())) if (parentClause is not None): type = parentClause.getType() typeList = type.getPossibleChildrenList() else : typeList = self.project.getTIM().getTypesList() self.ui.typeBox.addItems(typeList) currentType = self.ui.typeBox.currentText() self.updateParentClauses() if (parentClause is not None): parentClauseName = parentClause.getDocument().getName() + ": " + parentClause.getTitle() self.ui.parentBox.setCurrentIndex(self.ui.parentBox.findText(parentClauseName)) self.accepted.connect(self.setClause) self.ui.typeBox.currentIndexChanged.connect(self.updateParentClauses) def updateParentClauses(self): currentType = self.ui.typeBox.currentText() self.clausesList = {} self.ui.parentBox.clear() clausesDict = self.project.getAllClauses() type = self.project.getTIM().getType(unicode(currentType)) parentTypeList = self.project.getTIM().getPossibleParentsList(type) for clauseID in clausesDict.keys(): clause = clausesDict[clauseID] if self.isType(clause, parentTypeList): self.clausesList[(clause.getDocument().getName() + ": " + clause.getTitle())] = clauseID self.ui.parentBox.addItems(self.clausesList.keys()) if currentType in self.project.getTIM().getRootsList() : self.ui.parentBox.insertItem(0, "Sem Clausula Pai" ) if (unicode(self.ui.parentBox.currentText()) is ""): self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) else: self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) def isType(self, clause, typeList): if (clause.getType().getName() in typeList) : return True else : return False def setClause(self): title = unicode(self.ui.titleEdit.text()) parent = unicode(self.ui.parentBox.currentText()) self.clause = Clause() self.clause.setTitle(title) self.clause.setType(self.project.getTIM().getType(unicode(self.ui.typeBox.currentText()))) self.document = self.project.getDocument(unicode(self.ui.documentBox.currentText())) self.document.addClause(self.clause) if (parent != "Sem Clausula Pai") : parentClause = self.clausesList[unicode(self.ui.parentBox.currentText())] link = Link() link.addChild(self.clause.getID()) link.addParent(parentClause) link.consolidateLink(self.project) self.openElementSignal.emit("clause:" + self.clause.getID())
def test_backtrack(self: TestClause): clause = Clause([-6, 5, -4, 3, -2, 1]) a1 = Assignment(set([1, 2, 3, 4, 5, 6])) a1.add_assignment(0, 5, 0, None) a1.add_assignment(1, 3, 0, None) clause.assign(a1) a1.add_assignment(1, 6, 1, None) a1.add_assignment(1, 4, 1, None) a1.add_assignment(2, 1, 0, None) a1.add_assignment(2, 2, 1, None) clause.assign(a1) self.assertEqual(clause.get_state(a1), (Clause.UNSATISFIED, 1, 1)) self.assertEqual(clause.get_assigned_vars(a1), [6, 5, 4, 3, 2, 1]) clause.backtrack(1) a1.backtrack(1) self.assertEqual(clause.get_state(a1), (Clause.UNRESOLVED, 2, 1)) self.assertEqual(clause.get_assigned_vars(a1), [6, 5, 4, 3]) clause.backtrack(0) a1.backtrack(0) self.assertEqual(clause.get_state(a1), (Clause.UNRESOLVED, 6, 1)) self.assertEqual(clause.get_assigned_vars(a1), [5])
def test_init(self: TestClause): clause = Clause([-6, 5, -4, 3, -2, 1]) self.assertEqual(clause.get_head_tail_var(), (6, 1))