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_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 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 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 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 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_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 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_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 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_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 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 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_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 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 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 getArithValue(vals): return SMTLib.createSum(vals)