Beispiel #1
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)
Beispiel #2
0
def scalability_Z3(numberOfBoolVars, numOfRealVars, constraints,
                   max_sensors_under_attack):
    print '\n======================================================='
    print '      TEST Z3'
    print '            #Real Varabiles = ', numOfRealVars
    print '            #Bool Varabiles = ', numberOfBoolVars
    print '            #Bool Constraints = ', len(constraints)
    print '=======================================================\n'

    SMTsolver = z3.Solver()
    bVars = z3.BoolVector('b', numberOfBoolVars)
    rVars = z3.RealVector('y', numOfRealVars)

    #----------------------------------------------------------------------------
    print '--> Z3: FEEDING CONSTRAINTS'
    #----------------------------------------------------------------------------
    for constraint in constraints:
        boolConstraint = constraint['bool']
        convexConstraint = constraint['convex']

        firstVar = boolConstraint[0]
        Q = convexConstraint['Q']
        b = convexConstraint['b']
        c = convexConstraint['c']
        quadConstraint = 0
        for counter1 in range(0, numOfRealVars):
            for counter2 in range(0, numOfRealVars):
                quadConstraint = quadConstraint + rVars[counter1] * rVars[
                    counter2] * Q[counter1, counter2]

        linearConstraint = 0
        for counter1 in range(0, numOfRealVars):
            linearConstraint = linearConstraint + rVars[counter1] * c[counter1]

        #quadConstraint                    = sum([i * j for i,j in zip(rVars,A)] + [-1*b[0]])
        SMTsolver.add(
            z3.Implies(bVars[firstVar], quadConstraint + linearConstraint < b))

    SMTsolver.add(
        sum([BoolVar2Int(bVars[i])
             for i in range(0, numberOfBoolVars)]) == max_sensors_under_attack)
    #----------------------------------------------------------------------------
    print '--> Z3: SEARCHING FOR A SOLUTION'
    #----------------------------------------------------------------------------
    SMTsolver.set("timeout", TIMEOUTE_LIMIT * 1000)
    start = timeit.default_timer()
    SMTsolver.check()
    end = timeit.default_timer()
    time_smt_SMT = end - start

    print('Z3 time = ', time_smt_SMT)
    return time_smt_SMT
Beispiel #3
0
def scalability_Z3(numberOfBoolVars, numOfRealVars, constraints):
    print '\n======================================================='
    print '      TEST Z3'
    print '            #Real Varabiles = ', numOfRealVars
    print '            #Bool Varabiles = ', numberOfBoolVars
    print '            #Bool Constraints = ', len(constraints)
    print '=======================================================\n'

    SMTsolver = z3.Solver()
    bVars = z3.BoolVector('b', numberOfBoolVars)
    rVars = z3.RealVector('y', numOfRealVars)

    #----------------------------------------------------------------------------
    print '--> Z3: FEEDING CONSTRAINTS'
    #----------------------------------------------------------------------------
    for constraint in constraints:
        boolConstraint = constraint['bool']
        positiveVars = [abs(i) - 1 for i in boolConstraint if i > 0]
        negativeVars = [abs(i) - 1 for i in boolConstraint if i < 0]
        Z3Constraint = [bVars[i] for i in positiveVars
                        ] + [NOT(bVars[i]) for i in negativeVars]

        SMTsolver.add(z3.Or(*Z3Constraint))
        convexConstraint = constraint['convex']
        if convexConstraint is not None:
            firstVar = abs(boolConstraint[-1]) - 1
            A = convexConstraint['A']
            b = convexConstraint['b']
            linConst = sum([i * j for i, j in zip(rVars, A)] + [-1 * b[0]])
            SMTsolver.add(z3.Implies(bVars[firstVar], linConst < 0))

    #----------------------------------------------------------------------------
    print '--> Z3: SEARCHING FOR A SOLUTION'
    #----------------------------------------------------------------------------
    SMTsolver.set("timeout", TIMEOUTE_LIMIT * 1000)
    start = timeit.default_timer()
    SMTsolver.check()
    end = timeit.default_timer()
    time_smt_SMT = end - start

    print('Z3 time = ', time_smt_SMT)
    return time_smt_SMT
Beispiel #4
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
	return [z3.BitVec(name + "__" + str(i), bitsCount) for i in range(count)]


def generateFiniteLenFloats(name, count, tp, ctx):
	tp = np.dtype(tp)
	fpSort = floatTypes[tp.itemsize]
	if isinstance(fpSort, tuple):
		fpSort = z3.FPSort(*fpSort)
	return [z3.FP(name + "__" + str(i), fpSort) for i in range(count)]


typesRemapping = {
	np.bool_: lambda name, count, tp, ctx: z3.BoolVector(name, count, ctx),
	bool: lambda name, count, tp, ctx: z3.BoolVector(name, count, ctx),
	int: lambda name, count, tp, ctx: z3.IntVector(name, count, ctx),
	float: lambda name, count, tp, ctx: z3.RealVector(name, count, ctx),
}

floatTypes = {
	1: (4, 4),
	#2: (5, 11),
	2: z3.FloatHalf(),
	#4: (8, 24),
	4: z3.FloatSingle(),
	#8: (11, 53),
	8: z3.FloatDouble(),
	10: (15, 63),
	#16: (15, 111),
	16: z3.FloatQuadruple(),
	32: (19, 237),
}
Beispiel #6
0
    def _init_vars(self):
        assert self.ctx.is_valid()
        assert self.ctx.only_one_input()

        for name, phi in self.ctx.symbols.items():
            self.vars[name] = z3.RealVector(prefix=name, sz=phi.outdim)
Beispiel #7
0
 def RealVector(self, s_str, length):
     return z3.RealVector(s_str, length)