def op_card(arg): ''' :param arg: :type left: :class:`~arg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~IntArg` Returns the number of instances that are *on* in arg. ''' assert isinstance(arg, ExprArg) instances = [] matches = getSetInstancePairs(arg) known_card = 0 if arg.getInts(): card_cons = compute_int_set(arg.getInts()) for i in card_cons: if isinstance(i, SMTLib.SMT_BoolConst): if i.value: known_card = known_card + 1 else: instances.append( SMTLib.SMT_If(i, SMTLib.SMT_IntConst(1), SMTLib.SMT_IntConst(0))) for (instance, _) in matches.values(): (expr, polarity) = instance if polarity == Common.DEFINITELY_ON: known_card = known_card + 1 else: instances.append( SMTLib.SMT_If(expr, SMTLib.SMT_IntConst(1), SMTLib.SMT_IntConst(0))) instances.append(SMTLib.SMT_IntConst(known_card)) return IntArg(SMTLib.createSum(instances))
def op_difference(left, right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~ExprArg` Computes the set difference (left - - right) ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) if left.getInts() or right.getInts(): sys.exit("FIXME ints diff") matches = getSetInstancePairs(left, right) newInstances = {} for (sort, index) in matches.keys(): key = (sort, index) ((lexpr, lpol), (rexpr, rpol)) = matches[(sort, index)] if rpol == Common.DEFINITELY_ON or lpol == Common.DEFINITELY_OFF: #cases (-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1) continue elif rpol == Common.DEFINITELY_OFF: #cases (0 , -1), (1, -1) newInstances[key] = (lexpr, lpol) else: #rpol is unknown, lpol is unknown or on => new_pol is UNKNOWN #cases (0, 0), (1, 0) #if right is not on, then left, else sort.isOff new_expr = SMTLib.SMT_If(SMTLib.createNot(rexpr), lexpr, sort.parentInstances) newInstances[key] = (new_expr, Common.UNKNOWN) return ExprArg(newInstances)
def putIfNotMatched(sort, mask, index, value, matches): ''' Used to make sure you don't add duplicate elements to a set i.e. a sub and super. Needed by union, intersection, and difference. ''' if not matches: mask.put(index, value) else: cond = [] for i in matches: (leftIsSub, transform, (match_sort, match_mask)) = i if leftIsSub: if match_mask.get(index + transform): cond.append( match_sort.isOff(match_mask.get(index + transform))) else: if match_mask.get(index - transform): cond.append( match_sort.isOff(match_mask.get(index - transform))) if not cond: mask.put(index, value) else: mask.put( index, SMTLib.SMT_If(mAnd(*cond), value, SMTLib.SMT_IntConst(sort.parentInstances)))
def quant_one(exprs, ifConstraints): ''' There's probably a better way to do this. ''' condList = getQuantifierConditionList(exprs) if ifConstraints: condList = [mAnd(i, j) for i, j in zip(ifConstraints, condList)] exprList = [] for i in range(len(condList)): exprList.append( SMTLib.SMT_If(condList[i], SMTLib.SMT_IntConst(1), SMTLib.SMT_IntConst(0))) return SMTLib.SMT_EQ(SMTLib.createSum(*exprList), SMTLib.SMT_IntConst(1))
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 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 max2(l, r): ''' returns the min of two integers ''' return SMTLib.SMT_If(SMTLib.SMT_LE(l, r), r, l)