def op_implies(left, right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~BoolArg` Ensure that if instance *i* of left is on, so is instance *i* of right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) #clafer-set equality case if left.getInts(): sys.exit("FIXME Implies") if isinstance(left, BoolArg) and isinstance(right, BoolArg): return BoolArg(SMTLib.SMT_Implies(left.getBool(), right.getBool())) cond = [] matches = getSetInstancePairs(left, right) for ((lexpr, lpol), (rexpr, rpol)) in matches.values(): if lpol == Common.DEFINITELY_OFF or rpol == Common.DEFINITELY_ON: continue elif lpol == Common.DEFINITELY_ON: cond.append(rexpr) else: #lpol is unknown and rpol is off or unknown #almost the same as op_difference below cond.append(SMTLib.SMT_Implies(lexpr, rexpr)) return BoolArg(mAnd(*cond))
def addGroupCardConstraints(self): self.upperGCard = self.element.gcard.interval[1].value self.lowerGCard = self.element.gcard.interval[0].value if (len(self.fields) == 0 and ((not self.superSort) or self.superSort.fields == 0)): return #lower bounds if not self.fields: return # front end is broken if self.lowerGCard == 0 and self.upperGCard == -1: return for i in range(self.numInstances): bigSumm = SMTLib.SMT_IntConst(0) for j in self.fields: bigSumm = SMTLib.SMT_Plus(bigSumm, j.summs[i]) #**** LEAVE THIS CODE **** #don't include inherited fields for now #if self.superSort: # for j in self.superSort.fields: # print("found " + str(j)) # bigSumm = bigSumm + j.summs[i + self.indexInSuper] if self.lowerGCard != 0: self.constraints.addGroupCardConstraint( SMTLib.SMT_Implies( self.isOn(i), SMTLib.SMT_GE(bigSumm, SMTLib.SMT_IntConst(self.lowerGCard)))) if self.upperGCard != -1: self.constraints.addGroupCardConstraint( SMTLib.SMT_Implies( self.isOn(i), SMTLib.SMT_LE(bigSumm, SMTLib.SMT_IntConst(self.upperGCard))))
def addSubSortConstraints(self, sub): #the super cannot exist without the sub, and vice-versa for i in range(sub.numInstances): self.constraints.addInheritanceConstraint( SMTLib.SMT_And( SMTLib.SMT_Implies(self.isOn(i + sub.indexInSuper), sub.isOn(i)), SMTLib.SMT_Implies(sub.isOn(i), self.isOn(i + sub.indexInSuper))))
def createCardinalityConstraints(self): if not self.cfr.isUsed(self.element): return self.summs = [[] for i in range(self.parentInstances + 1)] for i in range(self.numInstances): (lower, upper, _) = self.getInstanceRange(i) for j in range(lower, upper + 1): self.summs[j].append( SMTLib.SMT_If( SMTLib.SMT_EQ(self.instances[i], SMTLib.SMT_IntConst(j)), SMTLib.SMT_IntConst(1), SMTLib.SMT_IntConst(0))) for i in range(len(self.summs)): if self.summs[i]: self.summs[i] = SMTLib.createSum(*[self.summs[i]]) else: self.summs[i] = SMTLib.SMT_IntConst(0) for i in range(self.parentInstances): if self.parent: self.constraints.addCardConstraint( SMTLib.SMT_Implies( self.parent.isOn(i), SMTLib.SMT_GE( self.summs[i], SMTLib.SMT_IntConst(self.lowerCardConstraint)))) if self.upperCardConstraint != -1: self.constraints.addCardConstraint( SMTLib.SMT_Implies( self.parent.isOn(i), SMTLib.SMT_LE( self.summs[i], SMTLib.SMT_IntConst( self.upperCardConstraint)))) else: self.constraints.addCardConstraint( SMTLib.SMT_GE( self.summs[i], SMTLib.SMT_IntConst(self.lowerCardConstraint))) if self.upperCardConstraint != -1: self.constraints.addCardConstraint( SMTLib.SMT_LE( self.summs[i], SMTLib.SMT_IntConst(self.upperCardConstraint)))
def quant_all(exprs, ifConstraints): if ifConstraints: cond = mAnd(*[ SMTLib.SMT_Implies(i, j[0].getBool()) for i, j in zip(ifConstraints, exprs) ]) else: cond = mAnd(*[i[0].getBool() for i in exprs]) return cond
def assertConstraint(self, constraint, cfr): if Common.FLAG: SMTLib.toStr(constraint) if Options.PRODUCE_UNSAT_CORE: p = cfr.solver.convert(SMTLib.SMT_Bool("bool" + str(Common.getConstraintUID()) + "_" + str(self.assertID))) cfr.unsat_core_trackers.append(p) cfr.low_level_unsat_core_trackers[str(p)] = constraint cfr.unsat_map[str(p)] = self cfr.solver.add(SMTLib.SMT_Implies(p, constraint, unsat_core_implies=True)) else: cfr.solver.add(constraint)
def endProcessing(self, addToZ3=True): if not self.stack: return self.value = self.stack.pop() expr = self.value if (self.claferStack): thisClafer = self.claferStack[-1] for i in range(thisClafer.numInstances): if thisClafer.numInstances == len(expr): self.addConstraint( SMTLib.SMT_Implies( thisClafer.isOn(thisClafer.instances[i]), expr[i].getBool())) #hack for now else: self.addConstraint( SMTLib.SMT_Implies( thisClafer.isOn(thisClafer.instances[i]), expr[0].getBool())) else: for i in expr: self.addConstraint(i.getBool()) if addToZ3: self.cfr.smt_bracketed_constraints.append(self)
def createInstancesConstraintsAndFunctions(self): for i in range(self.numInstances): (lower, upper, extraAbsenceConstraint) = self.instanceRanges[i] #lower == upper case (simpler) if lower == upper: constraint = SMTLib.SMT_EQ(self.instances[i], SMTLib.SMT_IntConst(upper)) if extraAbsenceConstraint: self.constraints.addInstanceConstraint( SMTLib.SMT_Or(self.isOff(i), constraint)) else: #TODO self.instances[i] = SMTLib.SMT_IntConst(lower) self.constraints.addInstanceConstraint(constraint) else: #parent pointer is >= lower self.constraints.addInstanceConstraint( SMTLib.SMT_GE(self.instances[i], SMTLib.SMT_IntConst(lower))) constraint = SMTLib.SMT_LE(self.instances[i], SMTLib.SMT_IntConst(upper)) if extraAbsenceConstraint: #parent pointer is <= upper , or equal to parentInstances self.constraints.addInstanceConstraint( SMTLib.SMT_Or(self.isOff(i), constraint)) else: #parent pointer is <= upper self.constraints.addInstanceConstraint(constraint) #sorted parent pointers (only consider things that are not part of an abstract) if not self.beneathAnAbstract: if i != self.numInstances - 1: self.constraints.addInstanceConstraint( SMTLib.SMT_LE(self.instances[i], self.instances[i + 1])) if not self.parent: return #if the parent is not live, then no child can point to it for i in range(self.parent.numInstances): for j in range(self.numInstances): self.constraints.addInstanceConstraint( SMTLib.SMT_Implies( self.parent.isOff(i), SMTLib.SMT_NE(self.instances[j], SMTLib.SMT_IntConst(i))), self.parent.known_polarity(i, local=True) != Common.DEFINITELY_ON)
def addRefConstraints(self): if not self.refSort: return elif isinstance(self.refSort, PrimitiveType) and self.refSort.type == "real": self.refs = SMTLib.SMT_RealVector(self.element.uid + "_ref", self.numInstances) elif isinstance(self.refSort, PrimitiveType): self.refs = SMTLib.SMT_IntVector(self.element.uid + "_ref", self.numInstances) else: self.refs = SMTLib.SMT_IntVector( self.element.uid + "_ref", self.numInstances, bits=self.getBits(self.refSort.parentInstances + 1)) if not isinstance(self.refSort, PrimitiveType): for i in range(self.numInstances): #refs pointer is >= 0 self.constraints.addRefConstraint( SMTLib.SMT_GE(self.refs[i], SMTLib.SMT_IntConst(0))) #ref pointer is <= upper card of ref parent self.constraints.addRefConstraint( SMTLib.SMT_LE( self.refs[i], SMTLib.SMT_IntConst(self.refSort.numInstances))) #if integer refs, zero out refs that do not have live parents, #if clafer refs, set equal to ref.parentInstances if not live #reference symmetry breaking if not self.element.isAbstract: for i in range(self.numInstances - 1): for j in range(i + 1, self.numInstances): if isinstance(self.refSort, PrimitiveType): self.constraints.addRefConstraint( SMTLib.SMT_Implies( SMTLib.SMT_EQ(self.instances[i], self.instances[j]), SMTLib.SMT_LE(self.refs[i], self.refs[j]))) else: self.constraints.addRefConstraint( SMTLib.SMT_Implies( mAnd( SMTLib.SMT_NE( self.refs[i], SMTLib.SMT_IntConst( self.refSort.numInstances)), SMTLib.SMT_EQ(self.instances[i], self.instances[j])), SMTLib.SMT_LE(self.refs[i], self.refs[j]))) for i in range(self.numInstances): if isinstance(self.refSort, PrimitiveType): if self.refSort == "integer": self.constraints.addRefConstraint( SMTLib.SMT_Implies( self.isOff(i), SMTLib.SMT_EQ(self.refs[i], SMTLib.SMT_IntConst(0))), self.known_polarity(i, local=True) != Common.DEFINITELY_ON) elif self.refSort == "string": if Options.STRING_CONSTRAINTS: self.constraints.addRefConstraint( SMTLib.SMT_Implies( self.isOff(i), SMTLib.SMT_EQ(self.refs[i], self.cfr.EMPTYSTRING)), self.known_polarity(i, local=True) != Common.DEFINITELY_ON) else: self.constraints.addRefConstraint( SMTLib.SMT_Implies( self.isOff(i), SMTLib.SMT_EQ(self.refs[i], SMTLib.SMT_IntConst(0))), self.known_polarity(i, local=True) != Common.DEFINITELY_ON) else: self.constraints.addRefConstraint( SMTLib.SMT_Implies( self.isOff(i), SMTLib.SMT_EQ(self.refs[i], SMTLib.SMT_IntConst(0))), self.known_polarity(i, local=True) != Common.DEFINITELY_ON) else: if self.known_polarity(i, local=True) != Common.DEFINITELY_ON: self.constraints.addRefConstraint( SMTLib.SMT_If( self.isOff(i), SMTLib.SMT_EQ( self.refs[i], SMTLib.SMT_IntConst( self.refSort.numInstances)), SMTLib.SMT_NE( self.refs[i], SMTLib.SMT_IntConst( self.refSort.numInstances)))) else: self.constraints.addRefConstraint( SMTLib.SMT_NE( self.refs[i], SMTLib.SMT_IntConst(self.refSort.numInstances))) #if refsort.full does not exist, create it if not self.refSort.full: self.refSort.full = lambda x: mOr(*[ SMTLib.SMT_And( SMTLib.SMT_EQ(x, SMTLib.SMT_IntConst(i)), self.refSort.isOn(i)) for i in range(self.refSort.numInstances) ]) #the clafer that the reference points to must be "on" self.constraints.addRefConstraint( SMTLib.SMT_Implies( SMTLib.SMT_NE( self.refs[i], SMTLib.SMT_IntConst(self.refSort.numInstances)), self.refSort.full(self.refs[i])))
def op_eq(left, right, cacheJoins=False, bc=None): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~BoolArg` Ensures that the left = right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) if cacheJoins and bc: #TODO CLEAN left_key = None right_key = None keys = [] #asil allocation speedup, if both sides are sets, we can perform expression substitution in other constraints #bc is the bracketed constraint to put the cache for i in [left, right]: if isinstance(i, JoinArg): newkeys = Common.computeCacheKeys(i.flattenJoin()) #print(tuple(key)) keys = keys + newkeys #need to return all keys during the progress of join, add flag? #get the all keys all_keys = i.checkIfJoinIsComputed(nonsupered=True, getAllKeys=True) #print(keys) #print(all_keys) keys = keys + all_keys #sys.exit() #print() #print("GGGG right" + str(right.__class__)) #print(right.clafers) if len(left.clafers) != len(right.clafers): minJoinVal = left.clafers if len(left.clafers) < len( right.clafers) else right.clafers for i in keys: #TODO make more robust (e.g. if multiple equalities exist for the same join key, aggregate expressions bc.cache[i] = ExprArg(minJoinVal) #print(i) #print(minJoinVal) #print(str(len(minJoinVal)) + " " + str(len(left.clafers)) + " " + str(len(right.clafers))) #print(str(len(left.clafers)) + " " + str(len(right.clafers))) cond = [] #int equality case lints = [(e, c) for (e, c) in left.getInts() if str(c) != "False"] rints = [(e, c) for (e, c) in right.getInts() if str(c) != "False"] if lints or rints: for (e, c) in lints: #exists r in R s.t. e == r expr = mOr(*[mAnd(rc, SMTLib.SMT_EQ(e, r)) for (r, rc) in rints]) if str(c) != "True": expr = SMTLib.SMT_Implies(c, expr) cond.append(expr) for (e, c) in rints: #exists l in L s.t. e == l expr = mOr(*[mAnd(lc, SMTLib.SMT_EQ(e, l)) for (l, lc) in lints]) if str(c) != "True": expr = SMTLib.SMT_Implies(c, expr) cond.append(expr) #clafer-set equality case matches = getSetInstancePairs(left, right) for ((lexpr, lpol), (rexpr, rpol)) in matches.values(): if lpol == Common.DEFINITELY_OFF and rpol == Common.DEFINITELY_OFF: continue elif lpol == Common.DEFINITELY_OFF: cond.append(SMTLib.createNot(rexpr)) elif rpol == Common.DEFINITELY_OFF: cond.append(SMTLib.createNot(lexpr)) else: cond.append(SMTLib.SMT_Implies(lexpr, rexpr)) cond.append(SMTLib.SMT_Implies(rexpr, lexpr)) return BoolArg(mAnd(*cond))