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_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 divide_biggest_ranges_in_two(z3inst, module, num_split): initial_num_split = num_split pairs = [] for i in z3inst.cfr_sorts.values(): glCardRange = i.numInstances - i.element.glCard[0].value + 1 if glCardRange > 1: pairs.append((i, glCardRange)) pairs.append((i, glCardRange)) pairs.reverse() constraints = [True] try: while num_split != 1: num_split = num_split // 2 (currSort, currRange) = pairs.pop(0) left1 = API.createCard( API.createArg(currSort.element.uid, currSort)) right1 = API.createInteger(currSort.element.glCard[0].value + (currRange // 2)) bc1 = CreateBracketedConstraints.CreateBracketedConstraints( z3inst, True) constraint1 = bc1.generatedConstraintVisit( API.createLT(left1, right1)) left2 = API.createCard( API.createArg(currSort.element.uid, currSort)) right2 = API.createInteger(currSort.element.glCard[0].value + (currRange // 2)) bc2 = CreateBracketedConstraints.CreateBracketedConstraints( z3inst, True) constraint2 = bc2.generatedConstraintVisit( API.createLE(right2, left2)) newConstraints = [] for i in constraints: newConstraints.append(mAnd(i, constraint1)) for i in constraints: newConstraints.append(mAnd(i, constraint2)) constraints = newConstraints except: return safe_raise_heuristic_failure_exception( "divide_biggest_ranges_in_two#" + str(initial_num_split) + "failed.") if num_split != 1: return safe_raise_heuristic_failure_exception( "divide_biggest_ranges_in_two#" + str(initial_num_split) + "failed.") return constraints sys.exit( "INCOMPLETE: need to figure out what to do when run out of splits")
def createAllLocalsCombinations(self, localDecls, exprArg, isDisjunct, isSymmetric): instances = exprArg.getInstances() my_range = list(instances.keys()) integer_combinations = itertools.permutations(my_range, len(localDecls)) localInstances = [] ifConstraints = [] for i in integer_combinations: list_of_ints = list(i) set_of_ints = set(list_of_ints) if isDisjunct and (len(set_of_ints) != len(list_of_ints)): continue ifList = [] locallocalInstances = [] for (sort, index) in list_of_ints: localExprArg = ExprArg(instances={}, nonsupered=True) (e, p) = exprArg.getInstances()[(sort, index)] localExprArg.add((sort, index), (e, p)) ifList.append(e) locallocalInstances.append(localExprArg) localInstances.append(locallocalInstances) ifConstraints.append(mAnd(*ifList)) return (localInstances, ifConstraints)
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 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 createAllLocalsCombinations(self, localDecls, exprArg, isDisjunct, isSymmetric): instances = exprArg.getInstances() my_range = list(instances.keys()) integer_combinations = itertools.permutations(my_range, len(localDecls)) localInstances = [] ifConstraints = [] for i in integer_combinations: list_of_ints = list(i) set_of_ints = set(list_of_ints) if isDisjunct and (len(set_of_ints) != len(list_of_ints)): continue ifList = [] locallocalInstances = [] for (sort,index) in list_of_ints: localExprArg = ExprArg(instances={}, nonsupered=True) (e,p) = exprArg.getInstances()[(sort,index)] localExprArg.add((sort,index),(e,p)) ifList.append(e) locallocalInstances.append(localExprArg) localInstances.append(locallocalInstances) ifConstraints.append(mAnd(*ifList)) return (localInstances, ifConstraints)
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 op_intersection(left,right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~ExprArg` Computes the set intersection (left & right) ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) if left.getInts() or right.getInts(): sys.exit("FIXME ints intersection") 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_OFF or lpol == Common.DEFINITELY_OFF: continue else: new_expr = mAnd(lexpr,rexpr) newInstances[key] = (new_expr, Common.aggregate_polarity(lpol, rpol)) return ExprArg(newInstances)
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 op_intersection(left, right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~ExprArg` Computes the set intersection (left & right) ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) if left.getInts() or right.getInts(): sys.exit("FIXME ints intersection") 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_OFF or lpol == Common.DEFINITELY_OFF: continue else: new_expr = mAnd(lexpr, rexpr) newInstances[key] = (new_expr, Common.aggregate_polarity(lpol, rpol)) return ExprArg(newInstances)
def optional_clafer_toggle(z3inst, module, num_split, order="random"): ''' only considers clafers with card = [0,1], AND numInstances = 1 num_split must be a power of 2 ''' assert (Common.is_power2(num_split)) initial_num_split = num_split opts = [] for i in z3inst.cfr_sorts: claferSort = z3inst.cfr_sorts[i] lowerCard = claferSort.lowerCardConstraint upperCard = claferSort.upperCardConstraint if lowerCard == 0 and upperCard == 1 and claferSort.numInstances == 1 and not claferSort.element.isAbstract: opts.append(claferSort) if order == "random": random.shuffle(opts) else: pairs = [] for i in opts: pairs.append((i, len(i.parentStack))) pairs.sort(key=operator.itemgetter(1)) if order == "top": pairs.reverse() opts = [i for (i, _) in pairs] constraints = [True] try: while num_split != 1: num_split = num_split // 2 currSort = opts.pop(0) newConstraints = [] for i in constraints: newConstraints.append(mAnd(i, currSort.instances[0] == 0)) for i in constraints: newConstraints.append(mAnd(i, currSort.instances[0] == 1)) constraints = newConstraints except: return safe_raise_heuristic_failure_exception( order + "_optional_clafer_toggle#" + str(initial_num_split) + " failed.") if num_split != 1: return safe_raise_heuristic_failure_exception( order + "_optional_clafer_toggle#" + str(initial_num_split) + " failed.") return constraints
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 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 optional_clafer_toggle(z3inst, module, num_split, order="random"): ''' only considers clafers with card = [0,1], AND numInstances = 1 num_split must be a power of 2 ''' assert(Common.is_power2(num_split)) initial_num_split = num_split opts = [] for i in z3inst.cfr_sorts: claferSort = z3inst.cfr_sorts[i] lowerCard = claferSort.lowerCardConstraint upperCard = claferSort.upperCardConstraint if lowerCard == 0 and upperCard == 1 and claferSort.numInstances == 1 and not claferSort.element.isAbstract: opts.append(claferSort) if order == "random": random.shuffle(opts) else: pairs = [] for i in opts: pairs.append((i, len(i.parentStack))) pairs.sort(key=operator.itemgetter(1)) if order == "top": pairs.reverse() opts = [i for (i, _) in pairs] constraints = [True] try: while num_split != 1: num_split = num_split // 2 currSort = opts.pop(0) newConstraints = [] for i in constraints: newConstraints.append(mAnd(i, currSort.instances[0] == 0)) for i in constraints: newConstraints.append(mAnd(i, currSort.instances[0] == 1)) constraints = newConstraints except: return safe_raise_heuristic_failure_exception(order + "_optional_clafer_toggle#" + str(initial_num_split) + " failed.") if num_split != 1: return safe_raise_heuristic_failure_exception(order + "_optional_clafer_toggle#" + str(initial_num_split) + " failed.") return constraints
def divide_biggest_ranges_in_two(z3inst, module, num_split): initial_num_split = num_split pairs = [] for i in z3inst.cfr_sorts.values(): glCardRange = i.numInstances - i.element.glCard[0].value + 1 if glCardRange > 1: pairs.append((i, glCardRange)) pairs.append((i, glCardRange)) pairs.reverse() constraints = [True] try: while num_split != 1: num_split = num_split // 2 (currSort,currRange) = pairs.pop(0) left1 = API.createCard(API.createArg(currSort.element.uid, currSort)) right1 = API.createInteger(currSort.element.glCard[0].value + (currRange//2)) bc1 = CreateBracketedConstraints.CreateBracketedConstraints(z3inst, True) constraint1 = bc1.generatedConstraintVisit(API.createLT(left1, right1)) left2 = API.createCard(API.createArg(currSort.element.uid, currSort)) right2 = API.createInteger(currSort.element.glCard[0].value + (currRange//2)) bc2 = CreateBracketedConstraints.CreateBracketedConstraints(z3inst, True) constraint2 = bc2.generatedConstraintVisit(API.createLE(right2, left2)) newConstraints = [] for i in constraints: newConstraints.append(mAnd(i, constraint1)) for i in constraints: newConstraints.append(mAnd(i, constraint2)) constraints = newConstraints except: return safe_raise_heuristic_failure_exception("divide_biggest_ranges_in_two#" + str(initial_num_split) + "failed.") if num_split != 1: return safe_raise_heuristic_failure_exception("divide_biggest_ranges_in_two#" + str(initial_num_split) + "failed.") return constraints sys.exit("INCOMPLETE: need to figure out what to do when run out of splits")
def op_equivalence(left,right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~BoolArg` Ensures that an element of left is *on* iff it is *on* in right. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) return BoolArg(mAnd(op_implies(left, right).getBool(), op_implies(right,left).getBool()))
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 op_and(left,right): ''' :param left: :type left: :class:`~ExprArg` :param right: :type right: :class:`~ExprArg` :returns: :class:`~BoolArg` Computes the boolean conjunction of the left and right instances. ''' assert isinstance(left, ExprArg) assert isinstance(right, ExprArg) lval = left.getBool() rval = right.getBool() return BoolArg(mAnd(lval, rval))
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 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 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 quant_some(exprs, ifConstraints): condList = getQuantifierConditionList(exprs) if ifConstraints: condList = [mAnd(i, j) for i,j in zip(ifConstraints, condList)] return mOr(*condList)
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 quant_some(exprs, ifConstraints): condList = getQuantifierConditionList(exprs) if ifConstraints: condList = [mAnd(i, j) for i, j in zip(ifConstraints, condList)] return mOr(*condList)
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 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))
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))