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 mOr(*args): ''' Similar to mAnd ''' args = list(args) newArgs = [] while (args): i = args.pop() if isinstance(i, SMTLib.SMT_Or): #print(i) for j in i.children(): #print(j) args.append(j) continue if i: if isinstance(i, SMTLib.SMT_BoolConst): if str(i) == "False": continue else: return SMTLib.SMT_BoolConst(True) newArgs.append(i) if len(newArgs) == 0: return SMTLib.SMT_BoolConst(False) elif len(newArgs) == 1: return newArgs[0] else: return SMTLib.SMT_Or(*newArgs)
def flattenInstances(instances): ''' sets the new polarities to corresponding ternary values ''' for (sort, index) in instances.keys(): final_expr = mOr(SMTLib.SMT_BoolConst(False)) (l, h, _) = sort.instanceRanges[index] (exprs, pols) = instances[(sort, index)] final_polarity = Common.DEFINITELY_OFF all_on = True for i in range(l, h + 1): currExpr = exprs.get(i) currPol = pols.get(i) if not (i in pols.keys()) or currPol == Common.DEFINITELY_OFF: all_on = False continue elif currPol == Common.UNKNOWN: all_on = False final_polarity = Common.UNKNOWN final_expr = mOr(final_expr, currExpr) else: final_polarity = Common.UNKNOWN final_expr = mOr(final_expr, currExpr) if all_on: final_polarity = Common.DEFINITELY_ON final_expr = SMTLib.SMT_BoolConst(True) instances[(sort, index)] = (final_expr, final_polarity) return instances
def mAnd(*args): ''' Short for MaybeAnd. Helper Function to simplify formulas passed to Z3, but mostly to make debugging output more comprehensible. Only applies the And function if there are actually multiple arguments. ''' args = list(args) newArgs = [] while (args): i = args.pop() if isinstance(i, SMTLib.SMT_And): for j in i.children(): args.append(j) continue if i: if str(i) == "True": continue if str(i) == "False": return SMTLib.SMT_BoolConst(False) newArgs.append(i) if len(newArgs) == 0: return SMTLib.SMT_BoolConst(True) elif len(newArgs) == 1: return newArgs[0] else: return SMTLib.SMT_And(*newArgs)
def joinWithClafer(left, right): newInstances = {} leftInstances = left.getInstances(nonsupered=True) rightInstances = right.getInstances(nonsupered=True) for (lsort, lindex) in leftInstances.keys(): (lexpr, lpolarity) = leftInstances[(lsort, lindex)] if lpolarity == Common.DEFINITELY_OFF: continue for (rsort, rindex) in rightInstances.keys(): (_rexpr, rpolarity) = rightInstances[(rsort, rindex)] if rpolarity == Common.DEFINITELY_OFF: continue noMatch = False while not (rsort in lsort.fields): if not lsort.superSort: noMatch = True break (lsort, lindex) = joinWithSuper(lsort, lindex) if noMatch: continue (lower, upper, _) = rsort.instanceRanges[rindex] (new_rexpr, new_rpol) = newInstances.get((rsort, rindex), ({}, {})) new_rpol[lindex] = lpolarity new_rexpr[lindex] = mAnd( lexpr, SMTLib.SMT_EQ(rsort.instances[rindex], SMTLib.SMT_IntConst(lindex))) if lower <= lindex and lindex <= upper: newInstances[(rsort, rindex)] = (new_rexpr, new_rpol) newInstances = flattenInstances(newInstances) return ExprArg(newInstances, nonsupered=True)
def joinWithParent(arg): instances = arg.getInstances(nonsupered=True) newInstances = {} for (sort, index) in instances.keys(): (expr, pol) = instances[(sort, index)] if pol == Common.DEFINITELY_OFF: continue (lower, upper, _) = sort.instanceRanges[index] for i in range(lower, min(sort.parentInstances, upper + 1)): (old_expr, old_pol) = newInstances.get( (sort.parent, i), (SMTLib.SMT_BoolConst(False), Common.DEFINITELY_OFF)) if pol == Common.DEFINITELY_ON and lower == upper: new_pol = Common.DEFINITELY_ON new_expr = SMTLib.SMT_BoolConst(True) else: new_pol = Common.aggregate_polarity(old_pol, Common.UNKNOWN) new_expr = mOr( old_expr, mAnd( expr, SMTLib.SMT_EQ(sort.instances[index], SMTLib.SMT_IntConst(i)))) newInstances[(sort.parent, i)] = (new_expr, new_pol) return ExprArg(newInstances, nonsupered=True)
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 ConstraintNotDominatedByX(self, model): """ Creates a constraint preventing search in dominated regions. """ DisjunctionOrLessMetrics = list() for i in range(len(self.metrics_variables)): if self.metrics_objective_direction[i] == Common.METRICS_MAXIMIZE: DisjunctionOrLessMetrics.append( SMTLib.SMT_GT( self.metrics_variables[i], SMTLib.SMT_IntConst( Common.evalForNum( model, self.metrics_variables[i].convert( self.cfr.solver.converter)))) ) #model[self.metrics_variables[i]]) else: DisjunctionOrLessMetrics.append( SMTLib.SMT_LT( self.metrics_variables[i], SMTLib.SMT_IntConst( Common.evalForNum( model, self.metrics_variables[i].convert( self.cfr.solver.converter)))) ) #model[self.metrics_variables[i]]) return SMTLib.SMT_Or(*DisjunctionOrLessMetrics)
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 interpretUnsatCore(cfr, bool_id): cid = bool_id.split("_", 1)[1] SMTLib.toStr(cfr.low_level_unsat_core_trackers[bool_id]) if cid.startswith("BC"): bc = cfr.unsat_map[bool_id] retString = "[ " + bc.element.toString(1) + " ]" return retString else: claferSort = cfr.cfr_sorts.get(cid) return interpretClaferSort(claferSort)
def ConstraintMustDominatesX(self, model): """ Returns a constraint that a new instance has to be better than the instance represented by model in at least one dimension, and better or equal in all the other ones. """ dominationDisjunction = [] i = 0 for dominatedByMetric in self.metrics_variables: dominationConjunction = [] j = 0 if self.metrics_objective_direction[i] == Common.METRICS_MAXIMIZE: dominationConjunction.append( SMTLib.SMT_GT( dominatedByMetric, SMTLib.SMT_IntConst( Common.evalForNum( model, dominatedByMetric.convert( self.cfr.solver.converter))))) else: dominationConjunction.append( SMTLib.SMT_LT( dominatedByMetric, SMTLib.SMT_IntConst( Common.evalForNum( model, dominatedByMetric.convert( self.cfr.solver.converter))))) for AtLeastEqualInOtherMetric in self.metrics_variables: if j != i: if self.metrics_objective_direction[ j] == Common.METRICS_MAXIMIZE: dominationConjunction.append( SMTLib.SMT_GE( AtLeastEqualInOtherMetric, SMTLib.SMT_IntConst( Common.evalForNum( model, AtLeastEqualInOtherMetric.convert( self.cfr.solver.converter))))) else: dominationConjunction.append( SMTLib.SMT_LE( AtLeastEqualInOtherMetric, SMTLib.SMT_IntConst( Common.evalForNum( model, AtLeastEqualInOtherMetric.convert( self.cfr.solver.converter))))) j = 1 + j i = 1 + i dominationDisjunction.append( SMTLib.SMT_And(*dominationConjunction)) constraintDominateX = SMTLib.SMT_Or(*dominationDisjunction) return constraintDominateX
def compute_int_set(instances): cons = [] for index in range(len(instances)): (i, c) = instances[index] cons.append( mAnd( c, *[ mOr(SMTLib.createNot(jc), SMTLib.SMT_NE(j, i)) for (j, jc) in instances[0:index] ])) return cons
def isOff(self, index): ''' Returns a Boolean Constraint stating whether or not the instance at the given index is *off*. An instance is off if it is set to self.parentInstances. ''' try: return SMTLib.SMT_EQ(self.instances[index], SMTLib.SMT_IntConst(self.parentInstances)) except: return SMTLib.SMT_EQ(index, SMTLib.SMT_IntConst(self.parentInstances))
def ConstraintEqualToX(self, model): """ Returns a Constraint that a new instance, can't be dominated by the instance represented by model. (it can't be worst in any objective). """ EqualMetrics = list() for i in range(len(self.metrics_variables)): EqualMetrics.append( SMTLib.SMT_EQ( self.metrics_variables[i], Common.evalForNum(model, self.metrics_variables[i]))) return SMTLib.SMT_And(EqualMetrics)
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 isOn(self, index): ''' index is either an int or SMT-Int Returns a Boolean Constraint stating whether or not the instance at the given index is *on*. An instance is on if it is not set to self.parentInstances. ''' try: return SMTLib.SMT_NE(self.instances[index], SMTLib.SMT_IntConst(self.parentInstances)) except: return SMTLib.SMT_NE(index, SMTLib.SMT_IntConst(self.parentInstances))
def op_un_minus(arg): ''' :param arg: :type arg: :class:`~ExprArg` :returns: :class:`~IntArg` Negates arg. ''' assert isinstance(arg, IntArg) val = arg.getInts() val = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e,c) in val] val_sum = SMTLib.createSum(val) return IntArg(SMTLib.createNeg(val_sum))
def debug_print(self): constraints = [ self.instance_constraints, self.card_constraints, self.group_card_constraints, self.inheritance_constraints, self.ref_constraints ] for i in range(len(constraints)): print("CONSTRAINT TYPE: " + str(i)) for j in constraints[i]: SMTLib.toStr(j) print("")
def op_sum(arg): ''' :param arg: :type arg: :class:`~ExprArg` :returns: :class:`~IntArg` Computes the sum of all integer instances in arg. May not match the semantics of the Alloy backend. ''' assert isinstance(arg, ExprArg) sum_list = [] for (e, c) in arg.getInts(): sum_list.append(SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0))) return IntArg(SMTLib.createSum(sum_list))
def op_un_minus(arg): ''' :param arg: :type arg: :class:`~ExprArg` :returns: :class:`~IntArg` Negates arg. ''' assert isinstance(arg, IntArg) val = arg.getInts() val = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e, c) in val] val_sum = SMTLib.createSum(val) return IntArg(SMTLib.createNeg(val_sum))
def op_sum(arg): ''' :param arg: :type arg: :class:`~ExprArg` :returns: :class:`~IntArg` Computes the sum of all integer instances in arg. May not match the semantics of the Alloy backend. ''' assert isinstance(arg, ExprArg) sum_list = [] for (e,c) in arg.getInts(): sum_list.append(SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0))) return IntArg(SMTLib.createSum(sum_list))
def goalVisit(self, element): bracketedConstraintsVisitor = CreateBracketedConstraints.CreateBracketedConstraints(self.cfr) op = element.exp.iExp[0].operation if op == "min": op = Common.METRICS_MINIMIZE else: op = Common.METRICS_MAXIMIZE expr = bracketedConstraintsVisitor.objectiveVisit(element.exp.iExp[0].elements[0]) if isinstance(expr[0], JoinArg): #TODO cache stuff here too (pass cfr into computeJoin if caching expr = operations.Join.computeJoin(expr) valueList = [SMTLib.createIf(c, i, SMTLib.SMT_IntConst(0)) for (i,c) in expr.getInts()] self.cfr.objectives.append((op, SMTLib.createSum(valueList)))
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 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 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 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 goalVisit(self, element): bracketedConstraintsVisitor = CreateBracketedConstraints.CreateBracketedConstraints( self.cfr) op = element.exp.iExp[0].operation if op == "min": op = Common.METRICS_MINIMIZE else: op = Common.METRICS_MAXIMIZE expr = bracketedConstraintsVisitor.objectiveVisit( element.exp.iExp[0].elements[0]) if isinstance(expr[0], JoinArg): #TODO cache stuff here too (pass cfr into computeJoin if caching expr = operations.Join.computeJoin(expr) valueList = [ SMTLib.createIf(c, i, SMTLib.SMT_IntConst(0)) for (i, c) in expr.getInts() ] self.cfr.objectives.append((op, SMTLib.createSum(valueList)))
def op_le(left,right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~BoolArg` Invariant: left and right have exactly one int Ensures that the left <= right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) lval = left.getInts() lval = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e,c) in lval] rval = right.getInts() rval = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e,c) in rval] lsum = SMTLib.createSum(lval) rsum = SMTLib.createSum(rval) return BoolArg(SMTLib.SMT_LE(lsum, rsum))
def op_mul(left,right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~IntArg` Returns left * right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) lval = left.getInts() lval = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e,c) in lval] lval = SMTLib.createSum(lval) rval = right.getInts() rval = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e,c) in rval] rval = SMTLib.createSum(rval) return IntArg(SMTLib.SMT_Times(lval, rval))
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 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 addBasedOnPolarity(self, sort, index, expr): #DOES NOT SUPER polarity = sort.known_polarity(index) if polarity == Common.DEFINITELY_ON: self.clafers[(sort, index)] = (SMTLib.SMT_BoolConst(True), polarity) elif polarity == Common.UNKNOWN: self.clafers[(sort, index)] = (expr, polarity) else: #if definitely off, do not add return
def op_not(arg): ''' :param arg: :type arg: :class:`~ExprArg` :returns: :class:`~IntArg` Boolean negation of arg. ''' assert isinstance(arg, ExprArg) val = arg.getBool() return BoolArg(SMTLib.createNot(val))
def op_div(left,right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~IntArg` Returns left / right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) lval = left.getInts() lval = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e,c) in lval] lval = SMTLib.createSum(lval) rval = right.getInts() rval = [SMTLib.createIf(c, e, SMTLib.SMT_IntConst(0)) for (e,c) in rval] rval = SMTLib.createSum(rval) return IntArg(SMTLib.SMT_Divide(lval, rval) if((not isinstance(lval, SMTLib.SMT_IntConst)) or (not isinstance(rval, SMTLib.SMT_IntConst))) else SMTLib.SMT_IntDivide(lval, rval))
def int_set_in(leftIntSort, rightIntSort): (left_sort, left_mask) = leftIntSort (right_sort, right_mask) = rightIntSort cond = [] for i in left_mask.keys(): constraint = SMTLib.SMT_Or( SMTLib.SMT_EQ(left_sort.cardinalityMask.get(i), SMTLib.SMT_IntConst(0)), SMTLib.SMT_Or(*[ SMTLib.SMT_And( SMTLib.SMT_EQ(right_sort.cardinalityMask.get(j), SMTLib.SMT_IntConst(1)), SMTLib.SMT_EQ(right_mask.get(j), left_mask.get(i))) for j in right_mask.keys() ])) cond.append(constraint) return (SMTLib.SMT_And(*cond))
def getInstances(self, nonsupered=False): if nonsupered or self.hasBeenSupered: return self.clafers else: newClafers = {} for (sort, index) in self.clafers.keys(): (expr, polarity) = self.clafers[(sort, index)] if polarity == Common.DEFINITELY_OFF: continue key = (sort.highestSuperSort, sort.indexInHighestSuper + index) if polarity == Common.DEFINITELY_ON: newClafers[key] = (SMTLib.SMT_BoolConst(True), Common.DEFINITELY_ON) continue (currEntry, currPolarity) = newClafers.get( key, (SMTLib.SMT_BoolConst(False), Common.DEFINITELY_OFF)) currEntry = mOr(currEntry, expr) newClafers[key] = (currEntry, Common.aggregate_polarity( currPolarity, polarity)) self.clafers = newClafers self.hasBeenSupered = True return self.clafers
def joinWithClaferRef(arg): instances = arg.getInstances(nonsupered=True) newArg = ExprArg(nonsupered=True) for (sort, index) in instances.keys(): (expr, pol) = instances[(sort, index)] while not sort.refSort: (sort, index) = joinWithSuper(sort, index) if isinstance(sort.refSort, PrimitiveType): joinWithPrimitive(newArg, sort, index, expr, pol) else: for i in range(sort.refSort.numInstances): (prev_expr, _) = newArg.getInstances(nonsupered=True).get( (sort.refSort, i), (SMTLib.SMT_BoolConst(False), Common.DEFINITELY_OFF)) newArg.getInstances(nonsupered=True)[(sort.refSort, i)] = (mOr( prev_expr, mAnd( expr, SMTLib.SMT_EQ( sort.refs[index], SMTLib.SMT_IntConst(i)))), Common.UNKNOWN) return newArg
def op_nin(left, right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~ExprArg` Ensures that left is not a subset of right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) expr = op_in(left, right) return BoolArg(SMTLib.createNot(expr.pop_value()))
def op_nin(left,right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~ExprArg` Ensures that left is not a subset of right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) expr = op_in(left,right) return BoolArg(SMTLib.createNot(expr.pop_value()))
def initialize(self): (_, upper) = self.element.glCard self.numInstances = upper.value self.instances = SMTLib.SMT_IntVector( self.element.uid, self.numInstances, bits=self.getBits(self.parentInstances + 1)) #gets the upper card bound of the parent clafer if not self.parentStack: self.parent = None self.parentInstances = 1 else: self.parent = self.parentStack[-1] self.parentInstances = self.parent.numInstances
def op_ne(left,right): ''' :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) expr = op_eq(left, right) b = expr.getBool() return BoolArg(SMTLib.createNot(b))
def getArithValue(vals): return SMTLib.createSum(vals)
def compute_int_set(instances): cons = [] for index in range(len(instances)): (i,c) = instances[index] cons.append(mAnd(c, *[mOr(SMTLib.createNot(jc), SMTLib.SMT_NE(j,i)) for (j, jc) in instances[0:index]])) return cons
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))
def isOff(self, arg): ''' Returns a Boolean Constraint stating whether or not the instance at the given index is *off*. ''' return SMTLib.createNot(self.isOn(arg))
def quant_no(exprs, ifConstraints): condList = getQuantifierConditionList(exprs) if ifConstraints: condList = [mAnd(i, j) for i,j in zip(ifConstraints, condList)] return SMTLib.createNot(mOr(*condList))
def debug_print(self): print("GENERIC CONSTRAINT") for i in self.constraints: SMTLib.toStr(i) print("")