def addOriginSMTConstraints(self): """ Realize to transfer the CCSL constraints into SMT formula. :return: """ cnt = 0 for each in self.newCCSLConstraintList: if each[0] == "<" and len(each) == 3: tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( z3.Implies( history1(i) == history2(i), z3.Not(tick2(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n, history1(x) == history2(x)), # z3.Not(tick2(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 1, history1(x) == history2(x)), z3.Not(tick2(x))))) elif each[0] == "<" and len(each) == 4: tick1 = self.tickDict["t_%s" % (each[1])] delay = each[2] tick2 = self.tickDict["t_%s" % (each[3])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( z3.Implies( history2(i) - history1(i) == delay, z3.Not(tick2(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n, history2(x) - history1(x) == delay), # z3.Not(tick2(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 1, history2(x) - history1(x) == delay), z3.Not(tick2(x))))) elif each[0] == "≤": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add(history1(i) >= history2(i)) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) >= history2(x)))) else: self.solver.add( z3.ForAll( x, z3.Implies(x >= 1, history1(x) >= history2(x)))) elif each[0] == "⊆": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add(z3.Implies(tick1(i), tick2(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n, tick1(x)), # tick2(x)))) else: self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x >= 1, tick1(x)), tick2(x)))) elif each[0] == "#": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add( z3.Or(z3.Not(tick1(i)), z3.Not(tick2(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n), # z3.Or(z3.Not(tick1(x)), z3.Not(tick2(x)))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, z3.Or(z3.Not(tick1(x)), z3.Not(tick2(x)))))) elif each[0] == "+": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add(tick1(i) == z3.Or(tick2(i), tick3(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n), # tick1(x) == z3.Or(tick2(x), tick3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies(x >= 1, tick1(x) == z3.Or(tick2(x), tick3(x))))) elif each[0] == "*": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add( z3.Implies(tick1(i), z3.And(tick2(i), tick3(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n), # tick1(x) == z3.And(tick2(x), tick3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies(x >= 1, tick1(x) == z3.And(tick2(x), tick3(x))))) elif each[0] == "∧": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( history1(i) == z3.If( history2(i) >= history3(i), history2(i), history3(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) == z3.If(history2(x) >= history3(x),history2(x),history3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, history1(x) == z3.If( history2(x) >= history3(x), history2(x), history3(x))))) elif each[0] == "∨": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( history1(i) == z3.If( history2(i) <= history3(i), history2(i), history3(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) == z3.If(history2(x) <= history3(x), history2(x), history3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, history1(x) == z3.If( history2(x) <= history3(x), history2(x), history3(x))))) elif each[0] == "$": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] delay = z3.IntVal(int(each[3])) x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( history1(i) == z3.If( history2(i) >= delay, history2(i) - delay, 0)) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) == z3.If(history2(x) >= delay,history2(x) - delay,0)))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, history1(x) == z3.If( history2(x) >= delay, history2(x) - delay, 0)))) elif each[0] == "on": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[4])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[4])] self.addTickStep(each[1]) self.addTickStep(each[2]) self.addTickStep(each[4]) tickStep1 = self.tickStep["s_%s" % (each[1])] tickStep2 = self.tickStep["s_%s" % (each[2])] tickStep3 = self.tickStep["s_%s" % (each[4])] x = z3.Int("x") if self.bound > 0: for i in range(1, int(each[3]) + 1): self.solver.add(z3.Not(tick1(i))) for i in range(int(each[3]) + 1, self.bound + 1): t = [] for j in range(1, i - int(each[3]) + 1): t.append( z3.And( tick2(j), history3(i) - history3(j) == int(each[3]))) self.solver.add(z3.And(tick3(i), z3.Or(t)) == tick1(i)) self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x > 0, x <= self.n + 1), history2(x) >= history1(x)))) self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x > 0, x <= self.n, tick1(x)), tick3(x)))) # self.solver.add( # z3.ForAll(x, z3.Implies( # z3.And(x > 0, x <= history1(self.bound + 1)), # history3(tickStep2(x)) - history3(tickStep1(x)) == int(each[3]) # ))) # for i in range(self.bound + 1): # self.solver.add(history2(i) >= history1(i)) # for i in range(self.bound): # self.solver.add( # z3.Implies( # tick1(i), tick3(i) # ) # ) # for i in range(self.bound + 1): # self.solver.add( # history3(tickStep1(i)) - history3(tickStep2(i)) == int(each[3]) # ) # self.solver.add(z3.ForAll(x, z3.And( # z3.Implies(z3.And(x >= 1, x <= history1(self.bound + 1),tick2(x)), # tick1(tickStep3(history3(x) + int(each[3]))) # )))) else: self.solver.add( z3.ForAll( x, z3.And( z3.Implies(x >= 1, history2(x) >= history1(x))))) self.solver.add( z3.ForAll( x, z3.And( z3.Implies(z3.And(x >= 1, tick1(x)), tick3(x))))) self.solver.add( z3.ForAll( x, z3.And( z3.Implies(x >= 1, (history3(tickStep1(x)) - history3(tickStep2(x)) == int(each[3])))))) elif each[0] == "∝": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] x = z3.Int("x") left = tick1(x) if is_number(each[3]): k = z3.Int("k_%s" % (cnt)) self.solver.add(k >= 0, k < int(each[3])) right = z3.And(tick2(x), history2(x) >= 0, (history2(x) + k) % z3.IntVal(each[3]) == 0) cnt += 1 # right = z3.And(tick2(x), history2(x) > 0, (history2(x)) % z3.IntVal(each[3]) == 0) else: period = z3.Int("%s" % each[3]) tmp = self.parameter[each[3]] self.printParameter[each[3]] = period k = z3.Int("k_%s" % (cnt)) self.solver.add(k >= 0, k < period) right = z3.And(tick2(x), history2(x) >= 0, (history2(x) + k) % period == 0) self.solver.add(period >= int(tmp[2])) self.solver.add(period <= int(tmp[3])) cnt += 1 if self.bound > 0: self.solver.add( z3.ForAll( x, z3.And( z3.Implies(z3.And(x >= 1, x <= self.n), left == right)))) else: self.solver.add( z3.ForAll(x, z3.And(z3.Implies(x >= 1, left == right)))) elif each[0] == "☇": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[3])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[3])] self.addTickStep(each[1]) self.addTickStep(each[3]) tickStep1 = self.tickStep["s_%s" % (each[1])] tickStep3 = self.tickStep["s_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 2, x <= history3(self.bound + 1)), tick1(tickStep1(x)) == ( history2(tickStep3(x)) - history2(tickStep3(x - 1)) >= 1)))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 2, z3.And( tick1(tickStep1(x)), history2(tickStep3(x)) - history2(tickStep3(x - 1)) >= 1)))) elif each[0] == "==": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x >= 1, x <= self.n), tick1(x) == tick2(x)))) else: self.solver.add( z3.ForAll(x, z3.Implies(x >= 1, tick1(x) == tick2(x)))) elif each[0] == "⋈±": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] self.addTickStep(each[1]) self.addTickStep(each[2]) tickStep1 = self.tickStep["s_%s" % (each[1])] tickStep2 = self.tickStep["s_%s" % (each[2])] lower = int(each[3]) - int(each[4]) upper = int(each[3]) + int(each[4]) x = z3.Int("x") if self.bound > 0: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 1, x <= self.bound + 1, tick1(x)), history1(tickStep2(history2(x) + upper)) - history1( tickStep2(history2(x) + lower)) == 1))) self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 2, x <= history1(self.bound + 1)), z3.And( (history2(tickStep1(x)) - history2(tickStep1(x - 1)) >= lower), (history2(tickStep1(x)) - history2(tickStep1(x - 1)) <= upper))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 2, z3.And( (history2(tickStep1(x)) - history2(tickStep1(x - 1)) >= lower), (history2(tickStep1(x)) - history2(tickStep1(x - 1)) <= upper)))))
def symread_neq(a, b, size=MAX_SYM_READ_SIZE): return z3.Not(symread_eq(a, b, size))
class Z3Context(Context): def __init__(self, *args, **kw): Context.__init__(self, *args, **kw) self.solver = z3.Solver() def __getitem__(self, key): if not isinstance(key, Sort) and key in self.storage: return self.storage[key] elif isinstance(key, Sort): if key.name in self.storage: return self.storage[key.name] val = self.new_from_sort(key) self.storage[key.name] = val return val else: raise ValueError("%s not found! %s. %s." %(key, type(key), self.storage)) def new_from_sort(self, key): if isinstance(key, Bool): key = key.name val = z3.Bool(key) return val elif isinstance(key, Int): key = key.name val = z3.Int(key) return val elif isinstance(key, String): key = key.name val = z3.String(key) return val elif isinstance(key, BitVec): name = key.name size = key.size val = z3.BitVec(name, size) return val raise TypeError("%s not supported!" %type(key)) def s_assert(self, expr): self.solver.assert_exprs(expr.cval(self)) def s_check(self): res = self.solver.check() return res def s_model(self): try: m = self.solver.model() return self.process_model(m) except z3.Z3Exception: return {} def s_push(self): self.solver.push() def s_pop(self): self.solver.pop() def s_reset(self): self.solver.reset() def solve(self, AST): outputs = [] self.s_reset() for node in AST: if isinstance(node, Sort): self.s_assert(node) elif isinstance(node, Let): self.s_assert(node.term) elif isinstance(node, Command): if node.cname == "push": self.s_push() elif node.cname == "pop": self.s_pop() elif node.cname == "check-sat": logger.info("\n-------") outputs.append(self.s_check()) logger.info("Check: %s" % outputs[-1]) elif node.cname == "get-model": outputs.append(self.s_model()) logger.info("Model: %s" % outputs[-1]) else: raise ValueError("Command %s not supported!" %node) return outputs def process_model(self, z3_model): m = {} for v in z3_model: m[v.name()] = self.get_py_value(z3_model.get_interp(v)) return m def get_py_value(self, assignment): if z3.is_ast(assignment): if z3.is_int_value(assignment): return assignment.as_long() if z3.is_bool(assignment): return z3.is_true(assignment) if z3.is_string_value(assignment): try: val = assignment.as_string()[1:-1] # remove quotes val = val.replace("\\x00", "") return str(val) # Z3 throws encoding errors. It can't decode its own solution.. # TODO find a better fix. except UnicodeDecodeError: val = assignment.as_ast() return repr(val) raise ValueError("Unsupported Z3 type! %s" % type(assignment)) return assignment BoolVal = lambda self, x : z3.BoolVal(x) StringVal = lambda self, x : z3.StringVal(x) IntVal = lambda self, x : z3.IntVal(x) BitVecVal = lambda self, val, size : z3.BitVecVal(val, size) And = lambda self, *x : z3.And(x) Or = lambda self, *x : z3.Or(x) Xor = lambda self, *x : reduce(xor, x) Implies = lambda self, x, y : z3.Implies(x, y) Distinct = lambda self, x, y : z3.Distinct(x, y) def Eq(self, x, y): # x = z3.String("x") # x == "test" #throws an error. This is a workaround for now. x = z3.StringVal(x) if isinstance(x,str) else x y = z3.StringVal(y) if isinstance(y,str) else y return eq(x,y) Not = lambda self, x : z3.Not(x) If = lambda self, *x : z3.If(*x) add = lambda self, *x : reduce(add, x) sub = lambda self, *x : reduce(sub, x) if len(x) > 1 else -x[0] mul = lambda self, *x : reduce(mul, x) lt = lambda self, *x : reduce(lt, x) le = lambda self, *x : reduce(le, x) gt = lambda self, *x : reduce(gt, x) ge = lambda self, *x : reduce(ge, x) concat = lambda self, *x : reduce(add, x) length = lambda self, x : z3.Length(x) contains = lambda self, x, y : z3.Contains(x, y) indexof = lambda self, x, y, z=0 : z3.IndexOf(x, y, z) extract = lambda self, x, y, z : z3.Extract(x, y, z) bvadd = add bvsub = sub bvmul = mul bvxor = Xor bvneg = lambda self, x : neg(x) bvnot = lambda self, x : inv(x) bvconcat = lambda self, *x : z3.Concat(*x) bvlshr = lambda self, x, y : z3.LShR(x, y) bvlshl = lambda self, x, y : z3.LShL(x, y) bvuge = lambda self, x, y : z3.UGE(x, y) bvurem = lambda self, x, y : z3.URem(x, y) # TODO Need to define all these with stuff in computation folder FPAbs = lambda self, *x : None FPNeg = lambda self, *x : None FPAdd = lambda self, *x : None FPSub = lambda self, *x : None FPMul = lambda self, *x : None FPDiv = lambda self, *x : None FPFMA = lambda self, *x : None FPRem = lambda self, *x : None FPSqrt = lambda self, *x : None FPRoundToIntegral = lambda self, *x : None FPMin = lambda self, *x : None FPMax = lambda self, *x : None FPLEQ = lambda self, *x : None FPLT = lambda self, *x : None FPGEQ = lambda self, *x : None FPGT = lambda self, *x : None FPEQ = lambda self, *x : None FPIsNormal = lambda self, *x : None FPIsSubNormal = lambda self, *x : None FPIsZero = lambda self, *x : None FPIsInfinite = lambda self, *x : None FPIsNan = lambda self, *x : None FPIsNegative = lambda self, *x : None FPIsPositive = lambda self, *x : None