def antecedents(self, ids, ruleNum): if ids == "all": for Id, c in enumerate(self.db): if c is not None: # this is inconsitent now as we get (Id, c) for # "all" but the constraint directly if a list of # ids is provided. I don' have time to fix this # now and probably nobody (also not future me) # will notice as you ever only want the Ids if you # don't know them already. yield (Id, c) else: for i in ids: if i >= len(self.db): raise InvalidProof("Rule %i is trying to access constraint "\ "(constraintId %i), which is not derived, yet."\ %(ruleNum, i)) elif i <= -len(self.db): raise InvalidProof("Rule %i is trying to access invalid id "\ "(constraintId %i)."\ %(ruleNum, len(self.db) + i)) constraint = self.db[i] if constraint is None: raise InvalidProof("Rule %i is trying to access constraint "\ "(constraintId %i), that was marked as safe to delete."\ %(ruleNum, i)) yield constraint
def check(self, context): order = OrderContext.setup(context).activeDefinition leftSet = set(order.leftVars) rightSet = set(order.rightVars) sizes = {len(leftSet), len(rightSet), len(order.leftVars), len(order.rightVars)} if len(sizes) != 1: raise InvalidProof("Number of variables specified in left and right did not match.") if not leftSet.isdisjoint(rightSet): raise InvalidProof("Variables specified in left and right are not disjoint.")
def compute(self, antecedents, context=None): antecedents = list(antecedents) stack = list() antecedentIt = iter(antecedents) it = iter(self.instructions) ins = next(it, None) while ins is not None: if isinstance(ins, int): stack.append(next(antecedentIt).copy()) if isinstance(ins, tuple): what = ins[0] if what == "l": lit = ins[1] stack.append(context.ineqFactory.litAxiom(lit)) else: assert (False) elif ins == "+": second = stack.pop() first = stack.pop() stack.append(first.add(second)) elif ins == "*": constraint = stack.pop() factor = next(it) if factor < 0: raise InvalidProof("Multiplication by negative number.") stack.append(constraint.multiply(factor)) elif ins == "d": constraint = stack.pop() divisor = next(it) if divisor <= 0: raise InvalidProof("Division by non positive number.") stack.append(constraint.divide(divisor)) elif ins == "s": constraint = stack.pop() stack.append(constraint.saturate()) elif ins == "w": nxt = next(it, None) assert (nxt[0] == "l") lit = nxt[1] if lit < 0: logging.warn("Weakening step ignores sign of literals.") lit = abs(lit) constraint = stack.pop() stack.append(constraint.weaken(lit)) ins = next(it, None) assert len(stack) == 1 stack[0].contract() return stack
def compute(self, antecedents, context): # context for sub verifier svContext = verifier.Context() svContext.newIneqFactory = context.newIneqFactory svContext.ineqFactory = svContext.newIneqFactory() svContext.newPropEngine = context.newPropEngine svContext.propEngine = svContext.newPropEngine() svContext.ruleCount = getattr(context, "ruleCount", 0) self._newParseContext = ParseContext(svContext) self.onEnterSubVerifier(context, svContext) try: verify = verifier.Verifier( context = svContext, settings = context.verifierSettings) verify(context.rules) except StopSubVerifier: self.exitSubVerifier(context, svContext) svContext.propEngine = None svContext.ineqFactory = None else: raise InvalidProof("Subproof not finished.") return []
def __call__(self, rules): self.db = list() self.result = VerificationResult() self.result.requireUnsat = self.settings.requireUnsat if self.settings.trace: print() print("=== begin trace ===") if self.settings.progressBar: self.start_time = time.time() for ruleNum, rule in enumerate(itertools.chain([DummyRule()], rules)): try: self.handleRule(ruleNum, rule) except InvalidProof as e: e.lineInFile = rule.lineInFile raise e self.result.usesAssumptions = getattr(self.context, "usesAssumptions", False) self.result.containsContradiction = getattr(self.context, "containsContradiction", False) if self.settings.requireUnsat and not self.result.containsContradiction: raise InvalidProof("Proof does not contain contradiction!") if self.settings.trace: print("=== end trace ===") print() return self.result
def __call__(self): while self.subgoals: nxtGoalId, nxtGoal = self.subgoals.popleft() ## for performance reasons the following two checks are ## done directly when the effected constraints are computed # # if self.selfImplication(nxtGoalId, nxtGoal): # continue asRhs = nxtGoal.getAsRightHand() if asRhs is None: asLhs = nxtGoal.getAsLeftHand() with TemporaryAttach(self.propEngine) as temporary: for c in asLhs: if c is not None: temporary.attach(c) if self.rupImplication( nxtGoalId, self.context.ineqFactory.fromTerms([], 1)): continue else: nxtGoal = asRhs.copy() if nxtGoal.isTrivial(): if self.verbose: print( " automatically proved %s, constraint is trivial." % (str(nxtGoalId))) continue if not self.triedRUP and self.rupImplication( None, self.context.ineqFactory.fromTerms([], 1)): self.wasRUP = True break self.triedRUP = True if self.rupImplication(nxtGoalId, nxtGoal): continue # implication checks are stronger if we plug in propagated literals asmnt = self.getPropagatedAssignment().get() nxtGoal = nxtGoal.substitute(asmnt) # this is already checked when the effected constraints # are computed. However, due to caching it could be that # new constraints were added since then. if self.inDB(nxtGoalId, nxtGoal): continue if self.dbImplication(nxtGoalId, nxtGoal): continue raise InvalidProof("Could not proof proof goal %s automatically." % (str(nxtGoalId)))
def antecedents(self, ids, ruleNum): if ids == "all": for c in self.db: if c is not None: yield c else: for i in ids: if i >= len(self.db): raise InvalidProof("Rule %i is trying to access constraint "\ "(constraintId %i), which is not derived, yet."\ %(ruleNum, i)) constraint = self.db[i] if constraint is None: raise InvalidProof("Rule %i is trying to access constraint "\ "(constraintId %i), that was marked as save to delete."\ %(ruleNum, i)) yield constraint
def pop(self, checkSubgoals=True): oldContext = self.infos.pop() for callback in oldContext.callbacks: callback(self.context, oldContext) if checkSubgoals and len(oldContext.subgoals) > 0: for Id, subgoal in oldContext.subgoals.items(): raise InvalidProof( "Open subgoal not proven: %s: %s" % (str(Id), subgoal.toString(self.context.ineqFactory))) return oldContext
def parse(cls, words, ineqFactory, forbidden=[]): result = cls() try: nxt = next(words) except StopIteration: return result while nxt != ";": frm = ineqFactory.lit2int(nxt) if frm < 0: raise ValueError("Substitution should only" "map variables, not negated literals.") if frm in forbidden: raise InvalidProof("Substitution contains forbidden variable.") try: nxt = next(words) if nxt == "→" or nxt == "->": nxt = next(words) except StopIteration: raise ValueError("Substitution is missing" "a value for the last variable.") if nxt == "0": to = False elif nxt == "1": to = True else: to = ineqFactory.lit2int(nxt) result.map(frm, to) try: nxt = next(words) if nxt == ",": nxt = next(words) except StopIteration: break return result
def check(self): if not self.transitivity.isProven: raise InvalidProof("Proof did not show transitivity of order.")
def check(self, context): if not self.order.transitivity.isProven: raise InvalidProof("Transitivity proof is missing.")
def compute(self, antecedents, context): if self.found: raise InvalidProof("Constraint should be deleted.") return []
def check(self, context): if not getattr(context, "containsContradiction", False): raise InvalidProof("Sub proof did not show contradiction.") context.containsContradiction = False
def handleRule(self, ruleNum, rule): self.checked_rules += 1 if self.settings.progressBar: printProgressBar(ruleNum, self.context.ruleCount, self.start_time, length=50) didPrint = False antecedents = self.antecedents(rule.antecedentIDs(), ruleNum) constraints = rule.compute(antecedents, self.context) for constraint in constraints: if constraint is None: continue constraintId = len(self.db) constraint = self.attach(constraint, constraintId) if self.settings.trace and ruleNum > 0: didPrint = True self.print( " ConstraintId ${cid}%(line)03d${reset}: ${ienq}%(ineq)s${reset}" % { "line": constraintId, "ineq": self.context.ineqFactory.toString(constraint) }) if self.settings.proofGraph is not None and ruleNum > 0: ids = rule.antecedentIDs() if ids == "all": ids = (i for (i, c) in enumerate(self.db) if c is not None and i > 0) f = self.settings.proofGraph print("%(ineq)s ; %(line)d = %(antecedents)s" % { "line": constraintId, "ineq": self.context.ineqFactory.toString(constraint), "antecedents": " ".join(map(str, ids)) }, file=f) self.db.append(constraint) # Delete rule expects delete to happen after compute! deletedConstraints = [ i for i in rule.deleteConstraints() if self.db[i] is not None ] if self.settings.trace and len(deletedConstraints) > 0: didPrint = True print(" ConstraintId - : deleting %(ineq)s" % {"ineq": ", ".join(map(str, deletedConstraints))}) deleted = dict() for i in deletedConstraints: ineq = self.db[i] if ineq is None: continue self.db[i] = None wasLastReference = self.detach(ineq, i) if wasLastReference and ineq.isCoreConstraint: if self.settings.isCheckDeletionOn: if not ineq.rupCheck(self.context.propEngine, True): raise InvalidProof( "Could not verify deletion of core constraint %s", self.context.ineqFactory.toString(ineq)) else: orderContext = getattr(self.context, "orderContext", None) if orderContext is not None and len( orderContext.activeOrder.vars) > 0: if not ineq.rupCheck(self.context.propEngine, True): raise InvalidProof( "Could not verify deletion of core constraint while order was loaded." ) deleted[id(ineq)] = ineq # clean up references, to not get spicious warnings constraint = None antecedents = None for ineq in deleted.values(): refcount = sys.getrefcount(ineq) attachCount = self.context.propEngine.attachCount(ineq) if (attachCount == 0 and refcount > 4): # todo: refcount should be at-most 3, except for # constraints that apear in the formula or in dominance proofs. #logging.warning print("Internal Warning: refcount of " "deleted constraint too large (is %i), memory will " "not be freed." % (refcount)) print(self.context.ineqFactory.toString(ineq))
def compute(self, antecedents, context): try: return [context.formula[self._axiomId - 1]] except IndexError as e: raise InvalidProof("Trying to load non existing axiom.")
def compute(self, antecedents, context=None): if (len(context.formula) != self._numConstraints): raise InvalidProof("Wrong number of constraints") return context.formula