def __init__(self, left_space, right_space, is_affine):
        """
        Construct to pull back the `right_space`. Bool `is_affine` states if the given space represents
        an affine space, in which case the returned points will always have the last coordinate 1.
        """
        assert(len(left_space[0]) == len(right_space[0]))

        # Fields
        self.affine = is_affine
        self.r_space = right_space[:]
        self.l_space = left_space[:]
        self.rd = len(right_space)
        self.ld = len(left_space)
        self.n = len(right_space[0])
        self.rr = min(self.rd, pb_nbasis_r)
        self.lr = min(self.ld, pb_nbasis_l)
        self.k = (factorial(self.rd) // (factorial(self.rr) * factorial(self.rd-self.rr))) * \
                 (factorial(self.ld) // (factorial(self.lr) * factorial(self.ld-self.lr)))

        # Set up solver
        self.solver = z3.SolverFor("LRA")
        self.z3_rc = [ z3.Real('rc_%d'%i) for i in range(self.rd) ]        # Coefficients in right_space
        self.z3_lc = [ z3.Real('lc_%d'%i) for i in range(self.ld) ]        # Coefficients in left

        # Set up combination iterator
        self.subb_cmb = itr.product(itr.combinations(zip(self.z3_lc, self.l_space), self.lr),
                                    itr.combinations(zip(self.z3_rc, self.r_space), self.rr))
        self.sbn = 0

        # Number of queries we have done. By this, we signal that we have not done any queries yet
        self.qn = pb_nqueries
Пример #2
0
 def make_solver(self) -> z3.Solver:
     solver = z3.SolverFor("HORN")
     solver.set("engine", "spacer")
     # allow quantified variables in pobs
     solver.set("spacer.ground_pobs", False)
     # enable quantified generalization
     solver.set("spacer.q3.use_qgen", True)
     for p in self.get_proof_rule():
         solver.add(p.as_z3())
     return solver
Пример #3
0
    def __init__(self, environment, logic, **options):
        IncrementalTrackingSolver.__init__(self,
                                           environment=environment,
                                           logic=logic,
                                           **options)
        self.z3 = z3.SolverFor(str(logic))
        self.options(self)
        self.declarations = set()
        self.converter = Z3Converter(environment, z3_ctx=self.z3.ctx)
        self.mgr = environment.formula_manager

        self._name_cnt = 0
        return
Пример #4
0
def checkSat(consts, logic="None"):
    z3Consts = [z3Obj(c) for c in consts]
    if logic != "None":
        solver = z3.SolverFor(logic)
    else:
        solver = z3.Solver()

    target_z3_simplify = z3.simplify(z3.And(*z3Consts))
    solver.add(target_z3_simplify)
    solver.set("timeout", 9000000)  #timeout : 150 min
    with open("thermoLinear.smt2", 'w') as fle:
        print(solver.to_smt2(), file=fle)
    return (solver.check(), sizeAst(z3.And(*z3Consts)))
Пример #5
0
    def __init__(self, json_file, pipeline, test_case_writer, solve_again):
        self.test_case_builder = TestCaseBuilder(json_file, pipeline)
        self.test_case_writer = test_case_writer
        self.solve_again = solve_again

        self.solver = z3.SolverFor('QF_UFBV')

        # Each item in list corresponds to an added path and a solver increment.
        # path_data is a data structure containing whatever is needed by the
        # child class' build_test_case implementation.
        self.paths_data = []  # [ (path_id, path_data), ... ]

        # Constraints added with each path
        self.constraint_lists = []  # [ [constraint, ...], ...]
Пример #6
0
    def __init__(self, environment, logic, **options):
        IncrementalTrackingSolver.__init__(self,
                                           environment=environment,
                                           logic=logic,
                                           **options)
        # LBYL to avoid a possible segmentation fault caused by z3.SolverFor
        # See issue #465 (https://github.com/pysmt/pysmt/issues/465)
        if str(logic) in Z3Solver.SOLVERFOR_LOGIC_NAMES:
            self.z3 = z3.SolverFor(str(logic))
        else:
            self.z3 = z3.Solver()
        self.options(self)
        self.declarations = set()
        self.converter = Z3Converter(environment, z3_ctx=self.z3.ctx)
        self.mgr = environment.formula_manager

        self._name_cnt = 0
        return
Пример #7
0
 def is_satisfied(self, command: 'Command', state_before: State,
                  state_after: State, environment: Environment,
                  config: Configuration) -> bool:
     """
     Determines whether this specification is satisfied by a given
     before and after state in a particular context (i.e, command
     arguments, configuration and environment).
     """
     logger.debug("Checking for command: %s", command.name)  # FIXME
     ctx = z3.Context()
     solver = z3.SolverFor("QF_NRA", ctx=ctx)
     smt, decls = self._prepare_query(ctx, command, state_before,
                                      state_after)
     expr = self.get_expression(decls, state_before)
     smt.extend(expr)
     logger.info("SMT: {}".format(smt))
     solver.add(smt)
     logger.debug("Z3 result: {}".format(str(solver.check())))
     return solver.check() == z3.sat
Пример #8
0
    def __init__(self, environment, logic, **options):
        IncrementalTrackingSolver.__init__(self,
                                           environment=environment,
                                           logic=logic,
                                           **options)
        try:
            self.z3 = z3.SolverFor(str(logic))
        except z3.Z3Exception:
            self.z3 = z3.Solver()
        except z3.z3types.Z3Exception:
            self.z3 = z3.Solver()
        self.options(self)
        self.declarations = set()
        self.converter = Z3Converter(environment, z3_ctx=self.z3.ctx)
        self.mgr = environment.formula_manager

        self._name_cnt = 0
        
        self.qf = False
        return
Пример #9
0
    def test_hardtanh(self):
        """
        This test is a mild sanity check; don't take too seriously
        """
        y = z3.RealVector("y", 2)
        x = z3.RealVector("x", 2)
        constraints = lantern.encode_hardtanh(x, y)

        s = z3.SolverFor("QF_LRA")

        s.add(constraints)

        # x_0 = -2 => y_0 = -1
        s.add(x[0] == -2)
        s.add(x[1] == y[0])
        self.assertTrue(s.check() == z3.sat)

        # should fail, since y_1 is constrained to -1
        s.add(y[1] == 0)
        self.assertTrue(s.check() == z3.unsat)
Пример #10
0
def main():
    base = 100
    expected = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99]
    expected = base2integer(expected, 100)
    expected = integer2base(expected, base)
    size = len(expected)
    bits = 2 * (int(math.log(base, 2)) + 1) + 1

    va = create_bit_vector('a', size, bits)
    vb = create_bit_vector('b', size, bits)

    expected = left_pad_with_zeros(expected, 2 * len(expected))
    print(str(expected))

    z3.set_option("parallel.enable", True)
    # 6 Threads ran on AMD Phenom II X6
    z3.set_option("parallel.threads.max", 6)
    s = z3.SolverFor("QF_BV")

    multiply(s, base, va, vb, expected)

    time1 = datetime.now()
    if s.check() == z3.sat:
        print("sat")
        m = s.model()
        print(str(m))

        f1 = vector_to_number(m, va, base)
        f2 = vector_to_number(m, vb, base)
        print("Factor 1 = " + str(f1))
        print("Factor 2 = " + str(f2))
        print("The number (Factor 1 * Factor 2) " + str(f1 * f2))
    else:
        print("unsat")
        print(base2integer(expected, base))
        print(str(s.unsat_core()))

    time2 = datetime.now()

    print("Base " + str(base))
    print("Elapsed " + str(time2 - time1))
Пример #11
0
    def is_satisfiable(self, command: 'Command', state: State,
                       environment: Environment) -> bool:
        """
        Determines whether this specification is satisifiable in a given
        context (i.e., command, state, environment, configuration).

        Parameters:
            command: the parameters supplied to the command.
            state: the state of the system immediately prior to executing the
                command.
            environment: the state of the environment immediately prior to
                executing the command.

        Returns:
            True if satisfiable, false if not.
        """
        ctx = z3.Context()
        s = z3.SolverFor("QF_NRA", ctx=ctx)
        decls = self.get_declarations(ctx, command, state)
        smt = Expression.values_to_smt('_', state, decls)
        smt.extend(self.get_expression(decls, state))
        s.add(smt)
        return s.check() == z3.sat
def push_forward_relu(left_space):
    """
    Finds an linear subspace to the right of relu so that any vector in `left_space` left space
    goes to it. Returns a basis of the space as a list of vecors. `left_space` must be a list of
    linearly indpenedent vectors giving a basis of the left space.
    """
    
    d = len(left_space)
    n = len(left_space[0])
    
    # Set up z3.
    solver = z3.SolverFor("LRA")
    z3_coeffs = [ z3.Real("c_%d"%i) for i in range(d) ]

    # Calculate the tie-classes of the relus
    tie_class_reps = [0]
    tie_class_vals = list(range(n))
    for i in range(1, n):
        print("Classifying ", i, end='\r', flush=True)    # DEBUG
        solver.push()
        solver.add( 0 >= z3.Sum([ c*l[i] for c, l in zip(z3_coeffs, left_space) ]) )
        cls = -1
        for rep in tie_class_reps:
            solver.push()
            solver.add( 0 < z3.Sum([ c*l[rep] for c, l in zip(z3_coeffs, left_space) ]) )
            if solver.check() == z3.unsat:
                cls = rep
                solver.pop()
                break
            solver.pop()
        if cls == -1:
            tie_class_reps.append(i)
        else:
            tie_class_vals[i] = cls
        solver.pop()
    print()


    fb_basis = []

    # If there are completely positive points in the left space, then those points exist in the
    # right space
    solver.reset()
    solver.push()
    h_cp = False
    for i in range(n):
        solver.add( 0 <= z3.Sum([ c*l[i] for c, l in zip(z3_coeffs, left_space) ]) )
    print("Checking completely positive points") #DEBUG
    if solver.check() == z3.sat:
        print("Completely positive points exist") #DEBUG
        fb_basis = deepcopy(left_space)
        h_cp = True 
    solver.pop()

    # Now, for each tie-class, we add basis generating that tie class
    for rep, i in zip(tie_class_reps, range(len(tie_class_reps))):
        for b, j in zip(left_space, range(len(left_space))):
            print("Adding basis %d for tie-class %d"%(j, i), end='\r', flush=True)    #DEBUG
            b_ = [ c if rv == rep else 0 for c, rv in zip(b, tie_class_vals) ]
            if np.linalg.matrix_rank(np.asarray(fb_basis + [b_])) > len(fb_basis):
                fb_basis.append(b_)
                print("\nAdding basis")
    print()

    return fb_basis, tie_class_reps, tie_class_vals, h_cp
def perm_check(weights, biases, perm, prc_eq):
    """
    Check if DNN given by the `weights` and `biases` is invariant under the given `perm`utation. The
    other arguments are:
    prc_eq          -   A set of linear equalities giving a precondition on the input. Specified as
                        a list of rows, each row [a1, a2, ... an, b] specifies the equation a1.x1 +
                        a2.x2 + ... an.xn = b.
    """

    # Numbers
    inp_dim = len(weights[0])
    out_dim = len(biases[-1])
    num_lyrs = len(weights)

    # Generate basis representing permutation constraint in the larger space
    in_basis = []
    if(len(prc_eq) > 0):
        # Convert the constraints into a basis for a precondition space
        prc_a = np.matrix([ r[:-1] for r in prc_eq])
        prc_b = np.asarray([r[-1] for r in prc_eq])
        prc_eq_krn = np.transpose(sp.null_space(prc_a)).tolist()
        prc_eq_s0, _, _, _ = sp.lstsq(prc_a, prc_b)
        prc_eq_s0 = prc_eq_s0.tolist()
        
        if len(prc_eq_krn) <= 0:
            # The equations determine exactly one input, and so we just check if that is a cex
            if check_cex(weights, biases, perm, prc_eq, prc_eq_s0):
                return False, prc_eq_s0
            return True, []
        
        in_basis = [ r + [r[p] for p in perm] + [0] for r in prc_eq_krn] + \
                    [ prc_eq_s0 + [prc_eq_s0[p] for p in perm] + [1] ]
    else:
        for i in range(inp_dim):
            b = [0]*(inp_dim*2)
            b[i] = 1
            b[perm[i] + inp_dim] = -1
            in_basis.append(b + [0])
        in_basis.append((inp_dim*2)*[0] + [1])
    prc_space = [ r[:] for r in in_basis ]


    

    ## ABSTRACTION


    # Represent affine transforms as matrices in a larger space
     # Joint weight matrix
    jlt_mat = [ np.matrix([r + [0]*len(w[0]) for r in w] + [[0]*len(w[0]) + r for r in w]) 
                                            for w,b in zip(weights,biases) ]
    # Joint affine transform
    jat_mat = [ np.matrix([r + [0]*len(w[0]) + [0] for r in w] + 
                        [[0]*len(w[0]) + r + [0] for r in w] + [b + b + [1]])
                                            for w,b in zip(weights,biases) ]
    # Kernels of joint weight matrices
    jlt_krn = [ np.transpose(sp.null_space(np.transpose(dm))) for dm in jlt_mat]


    # Track interpolants
    pre_lin_ints = []           # Interpolants
    post_lin_ints = []          # Interpolants after going through linear transform
    tc_reps = []                # Representatives of tie classes
    tc_vals = []                # Values of each tie class
    has_cp = []                 # Weather the push forward of the interpolant has the complete space
                                # of the previous layer

    # Linear inclusion loop
    for w, b, lm, curr_lyr in zip(weights, biases, jat_mat, range(num_lyrs)):
        print('Kernel check for layer ', curr_lyr)
        l = len(w[0])

        # Find image of in_basis under space. Ensure generated out_basis is linearly independent
        out_basis = []
        for b in in_basis:
            ob = (np.array(b) @ lm).tolist()[0]
            _r = np.linalg.matrix_rank(np.asarray(out_basis + [ob]))
            if _r > len(out_basis):
                out_basis.append(ob)

        # Check linear inclusion by finding subbasis of input basis that does not go to 0
        eq_basis = lm @ np.matrix([[0]*i + [+1] + [0]*(l-i-1) for i in range(l)] + 
                                  [[0]*i + [-1] + [0]*(l-i-1) for i in range(l)] +
                                  [[0]*l])

        if np.allclose(np.matrix(in_basis) @ eq_basis, 0):
            print('Verified at layer via linear inclusion ', curr_lyr)
            return True, [] 
        else:
            print('Linear inclusion failed at layer ', curr_lyr)

            # The basis containing the space at this layer where no CEX can ever be found
            spr_basis = np.transpose(sp.null_space(np.transpose(eq_basis))).tolist()

            # Backtracking pullback for cex
            suc, cex = pull_back_cex_explore(weights, biases, inp_dim, perm, prc_eq, prc_space,
                                            tc_reps, tc_vals, has_cp, curr_lyr, spr_basis)

            if suc:
                return False, cex 
                pass

        # Save these interpolants, and get next ones
        print('Looking for affine interpolant for next layer')
        pre_lin_ints.append(in_basis)
        post_lin_ints.append(out_basis)
        in_basis, tc_r, tc_v, h_cp = push_forward_relu(out_basis) 
        tc_reps.append(tc_r)
        tc_vals.append(tc_v)
        has_cp.append(h_cp)


    
    
    ## REFINEMENT

    # Set up solver and vars
    refined_solver = z3.SolverFor("LRA")
    # Stores the values going into each layer's transform in reverse order. First member stores
    # output.
    lyr_vars =  [[ z3.Real('lyr_%d_%d'%(num_lyrs, nn)) for nn in range(out_dim) ]]
    lyr_vars_p = [[ z3.Real('lyr_p_%d_%d'%(num_lyrs, nn)) for nn in range(out_dim) ]]
    for v, v_ in zip(lyr_vars[-1], lyr_vars_p[-1]):
        refined_solver.add(z3.Not(v == v_))

    # Refinement Loop
    for itp, w, b, i in zip(reversed(pre_lin_ints), reversed(weights), reversed(biases),
                            reversed(range(num_lyrs))):
        print("Refining layer %d"%i)

        # Encode layers
        lyr_vars.append([ z3.Real('lyr_%d_%d'%(i, nn)) for nn in range(len(w)) ])
        lyr_vars_p.append([ z3.Real('lyr_p_%d_%d'%(i, nn)) for nn in range(len(w)) ])
        lyr_out = encode_dnn.encode_network([w], [b], lyr_vars[-1])
        lyr_out_p = encode_dnn.encode_network([w], [b], lyr_vars_p[-1])
        for le, lep, lv, lvp in zip(lyr_out, lyr_out_p, lyr_vars[-2], lyr_vars_p[-2]):
            refined_solver.add(le == lv)
            refined_solver.add(lep == lvp)

        # Perform refined check
        refined_solver.push()
        
        # Cefficient to each basis in interpolant
        itp_cffs = [ z3.Real('cf_%d'%i) for i in range(len(itp)) ]
        # Encode that input is in inetrpolant, 
        for j in range(len(w)):
            refined_solver.add( lyr_vars[-1][j] == z3.Sum([ ic * it[j] for ic, it in 
                                                                    zip(itp_cffs, itp) ]))
            refined_solver.add( lyr_vars_p[-1][j] == z3.Sum([ ic * it[len(w) + j] for ic, it in 
                                                                    zip(itp_cffs, itp) ]))
        refined_solver.add( 1 == z3.Sum([ ic * it[-1] for ic, it in zip(itp_cffs, itp) ]))


        if refined_solver.check() == z3.unsat:
            print("Verified via refinement at layer %d")
            return True, []
        else:
            print('Found potential cex, attempting pullback....', end='')

            mdl = refined_solver.model()
            # The cex is a single point in the joint affine space at the begining of the current
            # layer, and that can be represented by the follwing line 
            cex_basis = [   list(map(mdl.eval, lyr_vars[-1])) + 
                            list(map(mdl.eval, lyr_vars_p[-1])) ]
            cex_basis[0] = [ v.numerator_as_long()/v.denominator_as_long() for v in cex_basis[0]]\
                            + [1]
            
            suc, cex = refined_pull_back_cex_explore(weights, biases, inp_dim, prc_space, perm, prc_eq,
                                            jlt_mat, jlt_krn, post_lin_ints, i, cex_basis)
            if suc:
                return False, cex
    
            
    assert(False) #We should never reach here
Пример #14
0
def stability_search1(phi, xsys, m):
    """ Attempts to find a max-affine Lyapunov function
        that proves global stability of an AMN:
        
        Dynamical system: x(t+1) = phi(x(t))
        Lyapunov function: V(x) = max(Ax+b),
                           A (m-by-n) and b (m)
        
        A and b are recalculated again at every E-solve step
        x should be a ref to the input variable to phi
    """
    n = phi.outdim
    assert n == xsys.outdim
    assert m >= 1

    # 0. Initialize
    print 'Initializing stability_search1'
    MAX_ITER = 50

    # init counterexample set
    Xc = list()
    #Xc.append(np.ones((n,)))
    # go around the Linf 1-ball
    for xcpoint in itertools.product([-1, 1], repeat=n):
        Xc.append(np.array(xcpoint))

    # init SMT solver
    esolver = z3.SolverFor('QF_LRA')
    fsolver = z3.SolverFor('QF_LRA')

    enc = amnet.smt.SmtEncoder(phi, solver=fsolver)
    enc.init_tree()

    print enc

    for iter in range(MAX_ITER):

        # 1. E-solve
        esolver.push()

        Avar = [z3.RealVector('A' + str(i), n) for i in range(m)]
        bvar = z3.RealVector('b', m)

        print 'iter=%s: Xc=%s' % (iter, Xc)
        print 'Avar=%s' % Avar
        print 'bvar=%s' % bvar

        esolver.add(_maxN_z3(bvar) == 0)

        for k, xk in enumerate(Xc):
            # point value
            xk_next = phi.eval(xk)

            # Lyapunov max expressions
            Vk_terms = [
                z3.Sum([Avar[i][j] * xk[j] for j in range(n)]) + bvar[i]
                for i in range(m)
            ]
            Vk_next_terms = [
                z3.Sum([Avar[i][j] * xk_next[j] for j in range(n)]) + bvar[i]
                for i in range(m)
            ]
            Vk_expr = _maxN_z3(Vk_terms)
            Vk_next_expr = _maxN_z3(Vk_next_terms)

            # Lyapunov function constraints for counterexample xk
            Vk = z3.Real('v' + str(k))
            Vk_next = z3.Real('v' + str(k) + '_next')
            esolver.add(Vk == Vk_expr)
            esolver.add(Vk_next == Vk_next_expr)

            # nonnegativity/decrement of V
            if all(xk == 0):
                esolver.add(Vk == 0)
            else:
                # CONDITIONING: impose minimum decay rate
                esolver.add(Vk > 0)
                esolver.add(Vk_next > 0)
                esolver.add(Vk_next < 0.99 * Vk)

            # CONDITIONING: impose upper bound on b
            esolver.add(_normL1_z3(bvar) <= 10)
            esolver.add(_maxN_z3(bvar) == 0)

            #esolver.add([bvar[i] == 0 for i in range(m)])

            # CONDITIONING: impose normalization on A
            for i in range(m):
                esolver.add(_normL1_z3(Avar[i]) <= 10)

        if _DEBUG_SMT2:
            filename = 'log/esolver_%s.smt2' % iter
            file = open(filename, 'w')
            print 'Writing %s...' % filename,
            file.write('(set-logic QF_LRA)\n')
            file.write(esolver.to_smt2())
            file.write('(get-model)')
            print 'done!'
            file.close()

        # find a candidate Lyapunov function
        if esolver.check() == z3.sat:
            print 'iter=%s: Found new Lyapunov Function' % iter
            #print 'esolver=%s' % esolver
            model = esolver.model()
            A_cand = np.array([[mfp(model, Avar[i][j]) for j in range(n)]
                               for i in range(m)])
            b_cand = np.array([mfp(model, bvar[i]) for i in range(m)])
            print "V(x)=max(Ax+b):"
            print "A=" + str(A_cand)
            print "b=" + str(b_cand)
        else:
            print 'iter=%s: Stability unknown, exiting' % iter

            esolver.pop()
            return None

        esolver.pop()

        # 2. F-solve
        # find counterexample for candidate Lyapunov function

        fsolver.push()

        # z3 symbol for input to phi
        x = enc.get_symbol(xsys)

        # encode Vx
        Vx_terms = [
            z3.Sum([A_cand[i][j] * x[j] for j in range(n)]) + b_cand[i]
            for i in range(m)
        ]
        Vx_expr = _maxN_z3(Vx_terms)
        Vx = z3.Real('vx')
        fsolver.add(Vx == Vx_expr)

        # z3 symbol for phi(x)
        x_next = enc.get_symbol(phi)

        # encode Vx_next
        Vx_next_terms = [
            z3.Sum([A_cand[i][j] * x_next[j] for j in range(n)]) + b_cand[i]
            for i in range(m)
        ]
        Vx_next_expr = _maxN_z3(Vx_next_terms)
        Vx_next = z3.Real('vx_next')
        fsolver.add(Vx_next == Vx_next_expr)

        # encode failure to decrement
        fsolver.add(z3.Not(x == 0))
        fsolver.add(z3.Not(z3.And(Vx > 0, Vx_next - Vx < 0)))

        # CONDITIONING: only care about small counterexamples
        fsolver.add(_normL1_z3(x) <= 5)
        fsolver.add(_normL1_z3(x) >= 0.5)

        if _DEBUG_SMT2:
            filename = 'log/fsolver_%s.smt2' % iter
            file = open(filename, 'w')
            print 'Writing %s...' % filename,
            file.write('(set-logic QF_LRA)\n')
            file.write(fsolver.to_smt2())
            file.write('(get-model)\n')
            print 'done!'
            file.close()

        # look for a counterexample
        if fsolver.check() == z3.sat:
            print 'iter=%s: Found new Counterexample' % iter
            #print 'fsolver=%s' % fsolver
            fmodel = fsolver.model()
            xc = np.array([mfp(fmodel, x[j]) for j in range(n)])
            Xc.append(xc)
        else:
            print 'iter=%s: No Counterexample found' % iter
            print 'Lyapunov function found'

            print "V(x)=max(Ax+b):"
            print "A=" + str(A_cand)
            print "b=" + str(b_cand)

            fsolver.pop()
            return (A_cand, b_cand)

        fsolver.pop()

    # max iterations reached
    print 'Max iterations reached'
    return None
Пример #15
0
def walk_block(node, prev_g=None, cond=True):
    g = z3.Goal()
    g.add(cond)
    if prev_g is not None:
        for e in prev_g:
            if isinstance(e, z3.Goal):
                g.add(e.as_expr())
            else:
                g.add(e)

    if isinstance(node, pycp.c_ast.Compound):
        if node.block_items is not None:
            for e in node.block_items:
                g_next = walk_block(e, g)
                g = g_next
    elif isinstance(node, pycp.c_ast.Decl):
        if "int" in node.type.type.names:
            ts[node.name] = 0
            vars[node.name] = z3.BitVec("%s!!%d" % (node.name, ts[node.name]),
                                        32)
    elif isinstance(node, pycp.c_ast.FuncCall):
        if node.name.name == "__ASSUME":
            for e_exp in node.args.exprs:
                g.add(gen_smt_expr(e_exp))
        elif node.name.name == "__ASSERT":
            assertions = z3.Goal()
            for e_exp in node.args.exprs:
                assertions.add(gen_smt_expr(e_exp))
            print("solving..")
            print("SP:", g.as_expr())
            print("assert:", assertions)

            fml = z3.And(g.as_expr(), z3.Not(assertions.as_expr()))

            s = z3.SolverFor('bv')
            s.add(fml)

            under_approx_info = {}
            for e in vars:
                under_approx_info[e] = [1, z3.Bool('%s!!switch' % e)]

            while (1):
                s.push()
                switches = []
                for e in vars:
                    if under_approx_info[e][0] <= 30:
                        s.add(
                            z3.Implies(
                                under_approx_info[e][1],
                                z3.Extract(30, under_approx_info[e][0],
                                           vars[e]) == 0))
                        switches.append(under_approx_info[e][1])

                if len(switches) == 0:
                    status = s.check()
                    s.pop()
                    break

                # print(s)
                status = s.check(switches)
                s.pop()
                if status == z3.unsat:
                    u_core = s.unsat_core()
                    # print(u_core)
                    if len(u_core) == 0:
                        break
                    e_bool = random.choice(u_core)
                    var_st = str(e_bool)[:-8]
                    # print(var_st)
                    under_approx_info[var_st][0] += 1
                elif status == z3.sat:
                    break
                else:
                    break

            if status == z3.sat:
                # print(s)
                model = s.model()
                print("program is unsafe.\nlisting an unsafe assignments..")
                for e in vars:
                    print(e, ':', model[vars[e]].as_signed_long())
            elif status == z3.unsat:
                print("program is safe.")
            elif status == z3.unknown:
                print("unknown")
        else:
            print("found a func call")
    elif isinstance(node, pycp.c_ast.Assignment):
        rexp = gen_smt_expr(node.rvalue)
        ts[node.lvalue.name] += 1
        old_ = vars[node.lvalue.name]
        if z3.is_bv(vars[node.lvalue.name]):
            curr_ = z3.BitVec(
                '%s!!%d' % (node.lvalue.name, ts[node.lvalue.name]), 32)
        vars[node.lvalue.name] = curr_
        if node.op == "=":
            g.add(curr_ == rexp)
        elif node.op == "+=":
            g.add(curr_ == (old_ + rexp))
        elif node.op == "-=":
            g.add(curr_ == (old_ - rexp))
        elif node.op == "*=":
            g.add(curr_ == (old_ * rexp))
        elif node.op == "%=":
            g.add(curr_ == (old_ % rexp))
        g_ = z3.Goal()
        g_.add(z3.Exists(old_, g.as_expr()))
        g_ = t_qe(g_)
        if not z3.is_quantifier(g_.as_expr()):
            print("q eliminated: %s" % old_)
            g = g_
        # g = z3.Goal()
        # g = g.simplify()
    elif isinstance(node, pycp.c_ast.If):
        cond_exp = gen_smt_expr(node.cond)
        vars_ = {}
        for e in vars:
            vars_[e] = vars[e]
        if node.iftrue is not None:
            true_expr = walk_block(node.iftrue, g, cond_exp).as_expr()
        else:
            true_expr = z3.And(cond_exp, g.as_expr())
        vars_t = {}
        for e in vars:
            vars_t[e] = vars[e]
            vars[e] = vars_[e]
        if node.iffalse is not None:
            false_expr = walk_block(node.iffalse, g,
                                    z3.Not(cond_exp)).as_expr()
        else:
            false_expr = z3.And(z3.Not(cond_exp), g.as_expr())
        g_t = z3.Goal()
        g_f = z3.Goal()
        g_t.add(true_expr)
        g_f.add(false_expr)
        for e in vars:
            if not vars[e].eq(vars_t[e]):
                ts[e] += 1
                new_ = z3.BitVec('%s!!%s' % (e, ts[e]), 32)
                g_t.add(new_ == vars_t[e])
                g_f.add(new_ == vars[e])
                vars[e] = new_
        g = z3.Goal()
        g.add(z3.Or(g_t.as_expr(), g_f.as_expr()))
        # print(g)
        g = t(g)  # g.simplify()
    else:
        return prev_g
    # print(g.as_expr(), "\n")
    return g
Пример #16
0
def is_false(cond):
    s = z3.SolverFor("QF_ABV")
    s.add(cond)
    return s.check() == z3.unsat
Пример #17
0
def main():
    """Lantern demo"""

    # Initialize a PyTorch network
    # Lantern currently supports: Linear, ReLU, Hardtanh, Dropout, Identity
    net = nn.Sequential(nn.Linear(2, 5), nn.ReLU(), nn.Linear(5, 1), nn.ReLU())

    print("A PyTorch network:")
    print(net)
    print()

    # Normally, we would train this network to compute some function. However,
    # for this demo, we'll just use the initialized weights.
    print("Network parameters:")
    print(list(net.parameters()))
    print()

    # lantern.as_z3(model) returns a triple of z3 constraints, input variables,
    # and output variables that directly correspond to the behavior of the
    # given PyTorch network. By default, latnern assumes Real-sorted variables.
    constraints, in_vars, out_vars = lantern.as_z3(net)

    print("Z3 constraints, input variables, output variables (Real-sorted):")
    print(constraints)
    print(in_vars)
    print(out_vars)
    print()

    # The 'payoff' is that we can prove theorems about our network with z3.
    # Trivially, we can ask for a satisfying assignment of variables
    print("A satisfying assignment to the variables in this network:")
    z3.solve(constraints)
    print()

    # However, we can run the network "backwards"; e.g. what is an *input* that
    # causes the network to output the value 0 (if such an input exists)?
    constraints.append(out_vars[0] == 0)
    print("An assignment such that the output variable is 0:")
    z3.solve(constraints)
    print()

    # To more precisely represent the underlying computations, consider using
    # an appropriate floating-point sort; PyTorch defaults to single precision.
    # To speed up satisfiability computations, models can be 'rounded', which
    # truncates the mantissa of every PyTorch model parameter. Note that the
    # exponent part remains the same (11 bits) so that the result can be
    # returned as a Python float. Here, we truncate to 10 bits (half precision).
    rounded_net = lantern.round_model(net, 10)
    constraints, in_vars, out_vars = lantern.as_z3(rounded_net,
                                                   sort=z3.FPSort(11, 10))
    print("Z3 constraints, input, output (FPSort(11, 10)):")
    print(constraints)
    print(in_vars)
    print(out_vars)
    print()

    # We add the constraint that the output must be 0.0, and solve using a
    # solver for FloatingPoint theory.
    print("An assignment such that the output variable is 0.0:")
    constraints.append(out_vars[0] == 0.0)
    z3.solve_using(z3.SolverFor("QF_FP"), *constraints)
    print()

    # Note that the constraints, and variables are all 'ordinary' Z3Py objects.
    print("Happy hacking!")
Пример #18
0
def get_solver():
    z3.set_param('rewriter.blast_select_store', True)
    return z3.SolverFor('QF_ABV')