def solve_eqts(avs, bvs, c, d): """ solve for c,d in a[i] = c+d*b[i] #[5 = c+d*0, 137 = c + d*44, 59 = c+d*18] => c=5,d=3 sage: c,d = var('c d') sage: rs = solve_eqts([5,137,59],[0,44,18],c,d) sage: rs[c], rs[d] (3, 5) """ if __debug__: assert (isinstance(avs, (tuple, list)) and all(is_scalar(v) and CM.isnum(v) for v in avs)), avs assert (isinstance(bvs, (tuple, list)) and all(is_scalar(v) and CM.isnum(v) for v in bvs)), bvs assert len(avs) == len(bvs) assert is_sage_expr(c), c assert is_sage_expr(d), d eqts = [a == d + c * b for a, b in zip(avs, bvs)] try: sol = solve(eqts, c, d, solution_dict=True) if len(sol) >= 2: print '{} results {} sols {}'.format(eqts, len(sol), sol) return sol[0] except Exception: return None
def strOfExp(p): """ -p^3 => -(p*p*p) n*p^4 => n*(p*p*p*p) ab^3 => (ab*ab*ab) x*y*z^3 => x*y*(z*z*z) """ assert is_sage_expr(p), p def getPow(p): try: oprs = p.operands() except Exception: return [] if p.operator() == sage.all.operator.pow: x, y = oprs pow_s = '*'.join( [str(x) if x.is_symbol() else "({})".format(x)] * int(y)) return [(str(p), '({})'.format(pow_s))] else: return [xy for o in oprs for xy in getPow(o)] s = str(p) if '^' not in s: return s rs = getPow(p) for (x, y) in rs: s = s.replace(x, y) return s
def getConstraints(m, resultAsDict=False): """ Input a model m, returns its set of constraints in either 1) sage dict {x:7,y:10} 1) z3 expr [x==7,y==0] sage: S = z3.Solver() sage: S.add(z3.Int('x') + z3.Int('y') == z3.IntVal('7')) sage: S.check() sat sage: M = S.model() sage: d = getConstraints(M, resultAsDict=True) sage: sorted(d.items(), key=lambda(k,_): str(k)) [(x, 7), (y, 0)] sage: getConstraints(M) [y == 0, x == 7] sage: S.reset() """ assert m is not None, m if resultAsDict: #sage format rs = [(var(str(v())),sage_eval(str(m[v]))) for v in m] rs = dict(rs) assert all(is_sage_expr(x) for x in rs.keys()) assert all(is_sage_real(x) or is_sage_int(x) for x in rs.values()) else: #z3 format rs = [v()==m[v] for v in m] assert all(z3.is_expr(x) for x in rs) return rs
def __str__(self, printStat=False): if is_sage_expr(self.inv): s = Inv.strOfExp(self.inv) else: s = str(self.inv) if printStat: s = "{} {}".format(s, self.stat) return s
def __init__(self, p): """ Ex: x + y >= 0 x^2 + y^2 + 3 == 0 """ if __debug__: assert is_sage_expr(p), p super(InvExp, self).__init__(p)
def __str__(self, printStat=False): if is_sage_expr(self.inv): inv = miscs.elim_denom(self.inv) s = miscs.strOfExp(inv) else: s = str(self.inv) if printStat: s = "{} {}".format(s, self.stat) return s
def infer(self, loc, template, uks, exprs, dtraces, inps): assert isinstance(loc, str), loc assert sageutil.is_sage_expr(template), template assert isinstance(uks, list), uks assert isinstance(exprs, set) and exprs, exprs assert isinstance(dtraces, DTraces) and dtraces, dtraces assert isinstance(inps, Inps) and inps, inps vs = tuple(self.invdecls[loc]) cache = set() eqts = set() #results exprs = list(exprs) newInps = [] curIter = 0 while True: curIter += 1 logger.debug("{}: iter {} infer using {} exprs".format( loc, curIter, len(exprs))) newEqts = Miscs.solveEqts(exprs, uks, template) unchecks = [eqt for eqt in newEqts if eqt not in cache] if not unchecks: logger.debug("{}: no new results -- break".format(loc)) break logger.debug('{}: {} candidates:\n{}'.format( loc, len(newEqts), '\n'.join(map(str, newEqts)))) logger.debug("{}: check {} unchecked ({} candidates)".format( loc, len(unchecks), len(newEqts))) dinvs = DInvs.mk(loc, Invs.mk(map(Inv, unchecks))) dInps, dCexs, dinvs = self.prover.checkRange(dinvs, inps=None) if dInps: newInps.append(dInps) _ = [eqts.add(inv) for inv in dinvs[loc] if not inv.isDisproved] _ = [ cache.add(inv.inv) for inv in dinvs[loc] if inv.stat is not None ] if loc not in dCexs: logger.debug( "{}: no disproved candidates -- break".format(loc)) break cexs = Traces.extract(dCexs[loc], vs) exprs_ = cexs.instantiate(template, None) logger.debug("{}: {} new cex exprs".format(loc, len(exprs_))) exprs.extend(exprs_) return eqts, newInps
def instantiateTemplate(template, sols): """ Instantiate a template with solved coefficient values sage: var('uk_0,uk_1,uk_2,uk_3,uk_4,r14,r15,a,b,y') (uk_0, uk_1, uk_2, uk_3, uk_4, r14, r15, a, b, y) #when sols are in dict form sage: sols = [{uk_0: -2*r14 + 7/3*r15, uk_1: -1/3*r15, uk_4: r14, uk_2: r15, uk_3: -2*r14}] sage: Template(uk_1*a + uk_2*b + uk_3*x + uk_4*y + uk_0 == 0).instantiateSols(sols) [-2*x + y - 2 == 0, -1/3*a + b + 7/3 == 0] # #when sols are not in dict form sage: sols = [[uk_0== -2*r14 + 7/3*r15, uk_1== -1/3*r15, uk_4== r14, uk_2== r15, uk_3== -2*r14]] sage: Template(uk_1*a + uk_2*b + uk_3*x + uk_4*y + uk_0 == 0).instantiateSols(sols) [-2*x + y - 2 == 0, -1/3*a + b + 7/3 == 0] sage: Template(uk_1*a + uk_2*b + uk_3*x + uk_4*y + uk_0 == 0).instantiateSols([]) [] """ assert sageutil.is_sage_expr(template), template if not sols: return [] if len(sols) > 1: logger.warn('instantiateTemplateWithSols: len(sols) = {}'.format( len(sols))) logger.warn(str(sols)) def f_eq(d): if isinstance(d, list): f_ = template for d_ in d: f_ = f_.subs(d_) rhsVals = CM.vset([d_.rhs() for d_ in d]) uk_vars = sageutil.get_vars(rhsVals) else: f_ = template(d) uk_vars = sageutil.get_vars(d.values()) #e.g., r15,r16 ... if not uk_vars: return f_ iM = sage.all.identity_matrix(len(uk_vars)) #standard basis rs = [dict(zip(uk_vars, l)) for l in iM.rows()] rs = [f_(r) for r in rs] return rs sols = sage.all.flatten([f_eq(s) for s in sols]) #remove trivial (tautology) str(x) <=> str(x) sols = [ s for s in sols if not (s.is_relational() and str(s.lhs()) == str(s.rhs())) ] return sols
def __init__(self, p): """ Ex: x + y >= 0 x^2 + y^2 + 3 == 0 """ if __debug__: assert is_sage_expr(p), p super(InvExp,self).__init__(p)
def toZ3(p, is_real): """ Convert a Sage expression to a Z3 expression Initially implements with a dictionary containing variables e.g. {x:Real('x')} but the code is longer and more complicated. This implemention does not require a dictionary pass in. Todo: cache this function sage: toZ3(x*x*x, False) x*x*x """ assert is_sage_expr(p), p def retval(p): if p.is_symbol(): _f = z3.Real if is_real else z3.Int else: _f = z3.RealVal if is_real else z3.IntVal return _f(str(p)) try: oprs = p.operands() except Exception: return retval(p) if is_empty(oprs): return retval(p) else: op = p.operator() #z3 has problem w/ t^c , so use t*t*t.. if op == operator.pow: assert len(oprs) == 2, oprs t, c = oprs t = toZ3(t, is_real) vs = [t] * c z3exp = reduce(operator.mul, vs) else: oprs = [toZ3(o, is_real) for o in oprs] z3exp = reduce(op, oprs) assert z3.is_expr(z3exp), z3exp return z3exp
def instantiate(self, term, nTraces): assert is_sage_expr(term), term assert nTraces is None or nTraces >= 1, nTraces if nTraces is None: exprs = set(term.subs(t) for t in self.mydicts) else: nTracesExtra = nTraces * 5 exprs = set() for i, t in enumerate(self.mydicts): expr = term.subs(t) if expr not in exprs: exprs.add(expr) if len(exprs) >= nTracesExtra: break #instead of doing this, can find out the # 0's in traces #the more 0's , the better exprs = sorted(exprs, key=lambda expr: len(get_vars(expr))) exprs = set(exprs[:nTraces]) return exprs
def get_constraints(m, result_as_dict=False): """ Input a model m, returns its set of constraints in either 1) sage dict {x:7,y:10} 1) z3 expr [x==7,y==0] sage: S = z3.Solver() sage: S.add(z3.Int('x') + z3.Int('y') == z3.IntVal('7')) sage: S.check() sat sage: M = S.model() sage: d = SMT_Z3.get_constraints(M, result_as_dict=True) sage: sorted(d.items(), key=lambda(k,_): str(k)) [(x, 7), (y, 0)] sage: SMT_Z3.get_constraints(M) [y == 0, x == 7] sage: S.reset() """ assert m is not None, m if result_as_dict: #sage format rs = [(var(str(v())),sage_eval(str(m[v]))) for v in m] rs = dict(rs) if __debug__: assert all(is_sage_expr(x) for x in rs.keys()) assert all(is_sage_real(x) or is_sage_int(x) for x in rs.values()) else: #z3 format rs = [v()==m[v] for v in m] if __debug__: assert all(z3.is_expr(x) for x in rs) return rs
def to_z3exp(p, is_real): """ Convert a Sage expression to a Z3 expression Initially implements with a dictionary containing variables e.g. {x:Real('x')} but the code is longer and more complicated. This implemention does not require a dictionary pass in. Todo: cache this function """ assert is_sage_expr(p), p def retval(p): if p.is_symbol(): z3exp = (z3.Real if is_real else z3.Int)(str(p)) else: z3exp = (z3.RealVal if is_real else z3.IntVal)(str(p)) if __debug__: assert z3.is_expr(z3exp), z3exp return z3exp try: oprs = p.operands() except Exception: return retval(p) if is_empty(oprs): return retval(p) else: oprs = [SMT_Z3.to_z3exp(o, is_real) for o in oprs] z3exp = SMT_Z3._reduce(p.operator(),oprs) assert z3.is_expr(z3exp), z3exp return z3exp
def __init__(self, p): if __debug__: assert (is_sage_expr(p) and p.operator() in [operator.le, operator.ge]) super(InvIeq, self).__init__(p)
def __init__(self, p): if __debug__: assert is_sage_expr(p) and p.operator() == operator.eq super(InvEqt, self).__init__(p)
def __init__(self, p): if __debug__: assert (is_sage_expr(p) and p.operator() in [operator.le, operator.ge]) super(InvIeq,self).__init__(p)
def __init__(self, p): if __debug__: assert is_sage_expr(p) and p.operator() == operator.eq super(InvEqt,self).__init__(p)
def myeval(self, term): assert is_sage_expr(term), term return [trace.myeval(term, self.vs) for trace in self]
def myeval(self, term, vs): assert is_sage_expr(term), term return term.subs(self.mydict(vs))
def __init__(self, template): assert sageutil.is_sage_expr(template), template self.template = template