Exemple #1
0
    def test_substituter_conditions(self):
        x = Symbol("x")
        y = Symbol("y")
        and_x_x = And(x, x)
        ftype = FunctionType(BOOL, [BOOL])
        f = Symbol("f", ftype)

        # 1. All arguments must be terms
        args_good = {x: y}
        args_bad = {x: f}

        substitute(and_x_x, args_good)
        with self.assertRaisesRegex(TypeError, " substitutions"):
            substitute(and_x_x, args_bad)

        # 2. All arguments belong to the manager of the substituter.
        new_mgr = FormulaManager(get_env())
        new_x = new_mgr.Symbol("x")
        self.assertNotEqual(x, new_x)
        args_1 = {x: new_x}
        args_2 = {new_x: new_x}

        with self.assertRaisesRegex(TypeError, "Formula Manager"):
            substitute(and_x_x, args_1)

        with self.assertRaisesRegex(TypeError, "Formula Manager."):
            substitute(and_x_x, args_2)

        with self.assertRaisesRegex(TypeError, "substitute()"):
            substitute(f, {x: x})
Exemple #2
0
    def test_substituter_conditions(self):
        x = Symbol("x")
        y = Symbol("y")
        and_x_x = And(x, x)
        ftype = FunctionType(BOOL, [BOOL])
        f = Symbol("f", ftype)

        # 1. All arguments must be terms
        args_good = {x:y}
        args_bad = {x:f}

        substitute(and_x_x, args_good)
        with self.assertRaisesRegex(TypeError, " substitutions"):
            substitute(and_x_x, args_bad)

        # 2. All arguments belong to the manager of the substituter.
        new_mgr = FormulaManager(get_env())
        new_x = new_mgr.Symbol("x")
        self.assertNotEqual(x, new_x)
        args_1 = {x: new_x}
        args_2 = {new_x: new_x}

        with self.assertRaisesRegex(TypeError, "Formula Manager" ):
            substitute(and_x_x, args_1)

        with self.assertRaisesRegex(TypeError, "Formula Manager."):
            substitute(and_x_x, args_2)

        with self.assertRaisesRegex(TypeError, "substitute()"):
            substitute(f, {x:x})
Exemple #3
0
    def relax_edge(self, edge):

        u, v = min(edge), max(edge)  # lexicographic order
        ucopy = self.copy_name(u, v)

        assert (edge in self.primal.edges()), f"{edge} not in G"
        assert ((u, v) not in self.relaxations), f"{edge} already relaxed"

        # create a new pysmt var
        old_var = self.primal.nodes()[u]['var']
        new_var = Symbol(ucopy, REAL)

        # copy univariate clauses and potentials for u_c
        new_uniclauses = {
            substitute(c, {old_var: new_var})
            for c in self.primal.nodes()[u]['clauses']
        }
        new_unipotentials = []
        # are these lit in potentials all univariate?
        for lit, w in self.primal.nodes()[u]['potentials']:
            new_unipotentials.append(
                (substitute(lit, {old_var: new_var}), w.subs(u, ucopy)))

        # add the node u_c to the primal graph
        self.primal.G.add_node(ucopy,
                               var=new_var,
                               clauses=new_uniclauses,
                               potentials=new_unipotentials)

        # copy bivariate clauses and potentials for (u_c, v)
        new_biclauses = {
            substitute(c, {old_var: new_var})
            for c in self.primal.edges()[(u, v)]['clauses']
        }
        new_bipotentials = []
        for lit, w in self.primal.edges()[(u, v)]['potentials']:
            new_bipotentials.append(
                (substitute(lit, {old_var: new_var}), w.subs(u, ucopy)))

        self.primal.G.add_edge(ucopy,
                               v,
                               clauses=new_biclauses,
                               potentials=new_bipotentials)

        # store the relaxation (s.t. we can invert it)
        self.relaxations[(u, v)] = {
            'copy_name': ucopy,
            'old_edge': dict(self.primal.edges()[(u, v)]),
            'new_edge': dict(self.primal.edges()[(ucopy, v)])
        }

        if (u, ) not in self.relaxations:
            self.relaxations[(u, )] = {'copies': [ucopy]}
        else:
            self.relaxations[(u, )]['copies'].append(ucopy)

        # finally remove the (u, v) dependency
        self.primal.G.remove_edge(u, v)
Exemple #4
0
    def test_substitution_on_quantifiers(self):
        x, y = FreshSymbol(), FreshSymbol()

        # y /\ Forall x. x /\ y.
        f = And(y, ForAll([x], And(x, y)))

        subs = {y: Bool(True)}
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, ForAll([x], x))

        subs = {x: Bool(True)}
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, f)
Exemple #5
0
    def test_substitution_on_quantifiers(self):
        x, y = FreshSymbol(), FreshSymbol()

        # y /\ Forall x. x /\ y.
        f = And(y, ForAll([x], And(x, y)))

        subs = {y: Bool(True)}
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, ForAll([x], x))

        subs = {x: Bool(True)}
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, f)
Exemple #6
0
    def test_subst(self):
        varA = Symbol("At", INT)
        varB = Symbol("Bt", INT)

        f = And(LT(varA, Plus(varB, Int(1))), GT(varA, Minus(varB, Int(1))))
        g = Equals(varA, varB)
        h = Iff(f, g)

        res = substitute(h, subs={varA: varB})

        self.assertEqual(res, h.substitute({varA: varB}))

        res = substitute(h, subs={varA: Int(1)})
        self.assertEqual(res, h.substitute({varA: Int(1)}))
Exemple #7
0
    def test_substitution_on_functions(self):
        i, r = FreshSymbol(INT), FreshSymbol(REAL)
        f = Symbol("f", FunctionType(BOOL, [INT, REAL]))

        phi = Function(f, [Plus(i, Int(1)), Minus(r, Real(2))])

        phi_sub = substitute(phi, {i: Int(0)}).simplify()
        self.assertEqual(phi_sub, Function(f, [Int(1), Minus(r, Real(2))]))

        phi_sub = substitute(phi, {r: Real(0)}).simplify()
        self.assertEqual(phi_sub, Function(f, [Plus(i, Int(1)), Real(-2)]))

        phi_sub = substitute(phi, {r: Real(0), i: Int(0)}).simplify()
        self.assertEqual(phi_sub, Function(f, [Int(1), Real(-2)]))
Exemple #8
0
    def test_substitution_on_functions(self):
        i, r = FreshSymbol(INT), FreshSymbol(REAL)
        f = Symbol("f", FunctionType(BOOL, [INT, REAL]))

        phi = Function(f, [Plus(i, Int(1)), Minus(r, Real(2))])

        phi_sub = substitute(phi, {i: Int(0)}).simplify()
        self.assertEqual(phi_sub, Function(f, [Int(1), Minus(r, Real(2))]))

        phi_sub = substitute(phi, {r: Real(0)}).simplify()
        self.assertEqual(phi_sub, Function(f, [Plus(i, Int(1)), Real(-2)]))

        phi_sub = substitute(phi, {r: Real(0), i: Int(0)}).simplify()
        self.assertEqual(phi_sub, Function(f, [Int(1), Real(-2)]))
Exemple #9
0
    def test_subst(self):
        varA = Symbol("At", INT)
        varB = Symbol("Bt", INT)

        f = And(LT(varA, Plus(varB, Int(1))), GT(varA, Minus(varB, Int(1))))
        g = Equals(varA, varB)
        h = Iff(f, g)

        res = substitute(h, subs={varA: varB})

        self.assertEqual(res, h.substitute({varA: varB}))

        res = substitute(h, subs={varA: Int(1)})
        self.assertEqual(res, h.substitute({varA: Int(1)}))
Exemple #10
0
    def test_substitution_on_quantifiers(self):
        x, y = FreshSymbol(), FreshSymbol()

        # y /\ Forall x. x /\ y.
        f = And(y, ForAll([x], And(x, y)))

        # Symbols within the quantified formula are not free symbols
        # and should not be substituted.
        subs = {y: TRUE()}
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, ForAll([x], x))

        subs = {x: TRUE()}
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, f)
Exemple #11
0
    def get_formula_at_i(self, vars, formula, i, prefix="bmc_"):
        """Change formula replacing every variable var in vars with a variable
        named <prefix>_var_i and every variable var_next with a
        variable named <prefix>_var_j, where j is i+1.

        Example for i = 0, prefix = bmc_

        Input: (v & v_next) | p
        Output: (bmc_v_0 & bmc_v_1) | bmc_p_0
        """
        if i in self.time_memo:
            time_i_map = self.time_memo[i]
        else:
            time_i_map = {}

            Helper.get_new_variables(vars, self.env.formula_manager,
                                     time_i_map, prefix, "_%d" % i)

            app_map = {}
            Helper.get_new_variables(vars, self.env.formula_manager, app_map,
                                     prefix, "_%d" % (i + 1))
            for k, v in app_map.iteritems():
                next_var = Helper.get_next_var(k, self.env.formula_manager)
                time_i_map[next_var] = v
            app_map = None

            self.time_memo[i] = time_i_map

        f_at_i = substitute(formula, time_i_map)
        return f_at_i
Exemple #12
0
    def add_dip_checker(self, dis_boolean, dis_out):
        for d in range(self.unroll_depth + 1):
            c0, c1 = self.attack_formulas.obf_ckt_at_frame(d)
            subs = {}
            c2 = []

            if d > 0:
                dip_out = dis_out[d - 1]
                for i in range(len(self.obf_cir.output_wires)):
                    subs[pystm.Symbol(self.obf_cir.output_wires[i] + '_0@{}'.format(d))] = dip_out[i]
                    subs[pystm.Symbol(self.obf_cir.output_wires[i] + '_1@{}'.format(d))] = dip_out[i]

                dip_boolean = dis_boolean[d - 1]
                for i in range(len(self.obf_cir.input_wires)):
                    subs[pystm.Symbol(self.obf_cir.input_wires[i] + '@{}'.format(d))] = dip_boolean[i]

                for i in range(len(self.obf_cir.next_state_wires)):
                    subs[pystm.Symbol(self.obf_cir.next_state_wires[i] + '_0@{}'.format(d - 1))] = pystm.Symbol(self.obf_cir.next_state_wires[i] + '_0_{}@{}'.format(self.iteration, d - 1))
                    subs[pystm.Symbol(self.obf_cir.next_state_wires[i] + '_1@{}'.format(d - 1))] = pystm.Symbol(self.obf_cir.next_state_wires[i] + '_1_{}@{}'.format(self.iteration, d - 1))
                    subs[pystm.Symbol(self.obf_cir.next_state_wires[i] + '_0@{}'.format(d))] = pystm.Symbol(self.obf_cir.next_state_wires[i] + '_0_{}@{}'.format(self.iteration, d))
                    subs[pystm.Symbol(self.obf_cir.next_state_wires[i] + '_1@{}'.format(d))] = pystm.Symbol(self.obf_cir.next_state_wires[i] + '_1_{}@{}'.format(self.iteration, d))
                    subs[pystm.Symbol(self.obf_cir.state_wires[i] + '_0@{}'.format(d))] = pystm.Symbol(self.obf_cir.state_wires[i] + '_0_{}@{}'.format(self.iteration, d))
                    subs[pystm.Symbol(self.obf_cir.state_wires[i] + '_1@{}'.format(d))] = pystm.Symbol(self.obf_cir.state_wires[i] + '_1_{}@{}'.format(self.iteration, d))
            else:
                for i in range(len(self.obf_cir.next_state_wires)):
                    subs[pystm.Symbol(self.obf_cir.next_state_wires[i] + '_0@{}'.format(d))] = pystm.Symbol(self.obf_cir.next_state_wires[i] + '_0_{}@{}'.format(self.iteration, d))
                    subs[pystm.Symbol(self.obf_cir.next_state_wires[i] + '_1@{}'.format(d))] = pystm.Symbol(self.obf_cir.next_state_wires[i] + '_1_{}@{}'.format(self.iteration, d))

            c = pystm.substitute(pystm.And(c0 + c1 + c2), subs)
            self.solver_obf.add_assertion(c)
            self.solver_key.add_assertion(c)
Exemple #13
0
    def resize_bvs(self, formula):
        """ Resize the bitvector variables wrt to the maximum domain size """
        subs_map = {}
        for (fvar, max_value) in self.fvars_maxval.iteritems():
            old_enc_var = self.fvars2encvars.lookup_a(fvar)
            bv_size = self.get_size(max_value+1)
            new_enc_var = FreshSymbol(BVType(bv_size))

            self.fvars2encvars.add(fvar, new_enc_var)

            val2val = self.fvars2values[fvar]

            for i in range(max_value + 1):
                old_value = BV(i, SymbolicGrounding.MAX_BV)
                new_value = BV(i, bv_size)

                fval = val2val.lookup_b(old_value)
                val2val.add(fval, new_value)

                old_f = Equals(old_enc_var,  old_value)
                new_f = Equals(new_enc_var,  new_value)
                subs_map[old_f] = new_f

        formula = substitute(formula, subs_map)
        return formula
Exemple #14
0
def clause_to_intervals(clause: FNode, sender_symbol: FNode,
                        test_point: float):
    """
    turn clause into a list of  intervals,
    where there are at most two intervals
    :param clause: OR FNode or a single atom
    :param sender_symbol:
    :param test_point: an initiation value for recipient variable
    :return: list of tuples of form [lower, upper]
    """
    upper_bounds, lower_bounds, recipient_atoms = categorize_bounds(
        clause, sender_symbol)
    if recipient_atoms:
        parent_symbol = list(get_real_variables(recipient_atoms[0]))
        for atom in recipient_atoms:
            bound = simplify(
                substitute(atom, {parent_symbol[0]: Real(test_point)}))
            if bound.is_true():
                return []

    num_uppers = [initiate_bound(upper, test_point) for upper in upper_bounds]
    num_lowers = [initiate_bound(lower, test_point) for lower in lower_bounds]
    if not num_uppers and not num_lowers:
        return []
    if not num_uppers:
        return [[min(num_lowers), float('inf')]]
    if not num_lowers:
        return [[float('-inf'), max(num_uppers)]]

    max_upper, min_lower = max(num_uppers), min(num_lowers)
    if max_upper < min_lower:
        return [[float('-inf'), max_upper], [min_lower, float('inf')]]
    else:
        return []
Exemple #15
0
    def get_next_formula(self, vars, formula):
        """Given a formula returns the same formula where all the variables
        in vars are renamed to var_next"""
        next_map = {}
        Helper.get_new_variables(vars, self.env.formula_manager, next_map, "", "_next")

        next_formula = substitute(formula, next_map)
        return next_formula
Exemple #16
0
    def __init__(self, oracle_cir, obf_cir):
        self.orcl_cir = oracle_cir
        self.obf_cir = obf_cir
        self.key_subs = [{}, {}]

        orcl_wires = self.orcl_cir.wire_objs
        obf_wires = self.obf_cir.wire_objs

        # generate solver formulas
        self.gen_wire_formulas(self.orcl_cir)
        self.gen_wire_formulas(self.obf_cir)

        # create key substitution dictionary
        for w in self.obf_cir.key_wires:
            self.key_subs[0][Symbol(w)] = Symbol(w + '_0')
            self.key_subs[1][Symbol(w)] = Symbol(w + '_1')

        # generate formulas for two copies of obfuscated circuit
        ckt1 = []
        ckt2 = []
        for w in self.obf_cir.output_wires:
            ckt1.append(substitute(obf_wires[w].formula, self.key_subs[0]))
            ckt2.append(substitute(obf_wires[w].formula, self.key_subs[1]))
        output_xors = []
        for i in range(len(self.obf_cir.output_wires)):
            output_xors.append(Xor(ckt1[i], ckt2[i]))
        self.dip_gen_ckt = Or(output_xors)

        # key inequality circuit
        key_symbols1 = []
        key_symbols2 = []
        for w in self.obf_cir.key_wires:
            key_symbols1.append(Symbol(w + '_0'))
            key_symbols2.append(Symbol(w + '_1'))

        output_xors = []
        for i in range(len(key_symbols1)):
            output_xors.append(Xor(key_symbols1[i], key_symbols2[i]))
        self.key_inequality_ckt = Or(output_xors)

        # dip checker circuit
        self.dip_chk1 = []
        self.dip_chk2 = []
        for w in self.obf_cir.output_wires:
            self.dip_chk1.append(substitute(obf_wires[w].formula, self.key_subs[0]))
            self.dip_chk2.append(substitute(obf_wires[w].formula, self.key_subs[1]))
Exemple #17
0
    def test_substitution_complex(self):
        x, y = FreshSymbol(REAL), FreshSymbol(REAL)
        # y = 0 /\ (Forall x. x > 3 /\ y < 2)
        f = And(Equals(y, Real(0)), ForAll([x], And(GT(x, Real(3)), LT(y, Real(2)))))

        subs = {y: Real(0), ForAll([x], And(GT(x, Real(3)), LT(y, Real(2)))): TRUE()}
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, TRUE())
Exemple #18
0
    def test_substitution_term(self):
        x, y = FreshSymbol(REAL), FreshSymbol(REAL)

        # y = 0 /\ Forall x. x > 3
        f = And(Equals(y, Real(0)), ForAll([x], GT(x, Real(3))))

        subs = {GT(x, Real(3)): TRUE()}
        f_subs = substitute(f, subs)
        # Since 'x' is quantified, we cannot replace the term
        # therefore the substitution does not yield any result.
        self.assertEqual(f_subs, f)
Exemple #19
0
    def test_substitution_term(self):
        x, y = FreshSymbol(REAL), FreshSymbol(REAL)

        # y = 0 /\ Forall x. x > 3
        f = And(Equals(y, Real(0)), ForAll([x], GT(x, Real(3))))

        subs = {GT(x, Real(3)): TRUE()}
        f_subs = substitute(f, subs)
        # Since 'x' is quantified, we cannot replace the term
        # therefore the substitution does not yield any result.
        self.assertEqual(f_subs, f)
Exemple #20
0
    def test_substitution_complex(self):
        x, y = FreshSymbol(REAL), FreshSymbol(REAL)
        # y = 0 /\ (Forall x. x > 3 /\ y < 2)
        f = And(Equals(y, Real(0)),
                ForAll([x], And(GT(x, Real(3)), LT(y, Real(2)))))

        subs = {
            y: Real(0),
            ForAll([x], And(GT(x, Real(3)), LT(y, Real(2)))): TRUE()
        }
        f_subs = substitute(f, subs).simplify()
        self.assertEqual(f_subs, TRUE())
Exemple #21
0
def initiate_bound(bound: FNode, initiation: float) -> float:
    """
    initiate an atom with only one variable with value initiation
    :param bound: FNode atom
    :param initiation: initiation of variable, type float
    :return: initiated bound, type float
    """
    real_variables = list(get_real_variables(bound))
    assert len(real_variables) < 2
    if real_variables:
        # print(real_variables[0], Real(initiation))
        bound = simplify(
            substitute(bound, {real_variables[0]: Real(initiation)}))
    return float(bound.constant_value())
Exemple #22
0
    def test_substitution_complex(self):
        x, y = Symbol("x", REAL), Symbol("y", REAL)
        # y = 0 /\ (Forall x. x > 3 /\ y < 2)
        f = And(Equals(y, Real(0)),
                ForAll([x], And(GT(x, Real(3)), LT(y, Real(2)))))

        subs = {
            y: Real(0),
            ForAll([x], And(GT(x, Real(3)), LT(y, Real(2)))): TRUE()
        }
        f_subs = substitute(f, subs).simplify()
        if self.env.SubstituterClass == MGSubstituter:
            self.assertEqual(f_subs, TRUE())
        else:
            # In the MSS the y=0 substitution is performed first,
            # therefore, the overall quantified expression does not
            # match the one defined in the substitution map.
            # See test_substitution_complex_mss for a positive example.
            self.assertEqual(f_subs, ForAll([x], GT(x, Real(3))))
Exemple #23
0
    def compensating_potentials(self, n_comp_lits):
        winit = lambda x: safeexp(self.rand_gen.random())
        comp_pots = {}
        init_w = 1
        for k in self.relaxations:
            if len(k) == 1:
                continue
            x, y = k
            xc = self.relaxations[(x,y)]['copy_name']
            var_x = self.primal.nodes()[x]['var']
            var_xc = self.primal.nodes()[xc]['var']
            
            if x not in comp_pots:
                # REM model for 'x'
                rem = MP2WMI(self.primal.get_univariate_formula(x), Real(1),
                             n_processes=self.n_processes)

                # sampling compensating potentials for 'x'
                # original = [[self.sample_comp_literal(var_x), winit(None)]
                #             for _ in range(n_comp_lits)]
                # try uniform weights
                original = [[self.sample_comp_literal(var_x), init_w]
                            for _ in range(n_comp_lits)]
                print(f"%%%%%%% var {x} compensating literals:")
                for lit, w in original:
                    print(f"%%%%%%% {lit}")
                comp_pots[x] = (rem, original, {})
            else:
                original = comp_pots[x][1]

            # using the same comp lits for the copies of 'x'
            # comp_pots[x][2][xc] = [
            #     [substitute(lit, {var_x: var_xc}), winit(None)]
            #     for lit, _ in original]
            comp_pots[x][2][xc] = [
                [substitute(lit, {var_x: var_xc}), init_w]
                for lit, _ in original]

        return comp_pots
Exemple #24
0
    def comb_attack(self):
        # dis generator
        solver_name = 'btor'
        solver_obf = Solver(name=solver_name)
        solver_key = Solver(name=solver_name)
        solver_oracle = Solver(name=solver_name)
        attack_formulas = FormulaGenerator(self.oracle_cir, self.obf_cir)

        f = attack_formulas.dip_gen_ckt
        # f = simplify(f)
        solver_obf.add_assertion(f)

        f = attack_formulas.key_inequality_ckt
        # f = simplify(f)
        solver_obf.add_assertion(f)

        iteration = 0
        while 1:
            # query dip generator
            if solver_obf.solve():
                dip_formula = []
                dip_boolean = []
                for l in self.obf_cir.input_wires:
                    t = Symbol(l)
                    if solver_obf.get_py_value(t):
                        dip_formula.append(t)
                        dip_boolean.append(TRUE())
                    else:
                        dip_formula.append(Not(t))
                        dip_boolean.append(FALSE())
                logging.info(dip_formula)

                # query oracle
                dip_out = []
                for l in self.oracle_cir.output_wires:
                    t = self.oracle_cir.wire_objs[l].formula
                    solver_oracle.reset_assertions()
                    solver_oracle.add_assertion(t)
                    if solver_oracle.solve(dip_formula):
                        dip_out.append(TRUE())
                    else:
                        dip_out.append(FALSE())
                logging.info(dip_out)

                # add dip checker
                f = []
                for i in range(len(attack_formulas.dip_chk1)):
                    f.append(And(Iff(dip_out[i], attack_formulas.dip_chk1[i]),
                                 Iff(dip_out[i], attack_formulas.dip_chk2[i])))
                f = And(f)

                subs = {}
                for i in range(len(self.obf_cir.input_wires)):
                    subs[Symbol(self.obf_cir.input_wires[i])] = dip_boolean[i]

                # f = simplify(f)
                f = substitute(f, subs)
                solver_obf.add_assertion(f)
                solver_key.add_assertion(f)

                iteration += 1
                logging.warning('iteration: {}'.format(iteration))
            else:
                logging.warning('print keys')
                if solver_key.solve():
                    key = ''
                    for i in range(len(self.obf_cir.key_wires)):
                        k = 'keyinput{}_0'.format(i)
                        if solver_key.get_py_value(Symbol(k)):
                            key += '1'
                        else:
                            key += '0'
                    print("key=%s" % key)
                else:
                    logging.critical('key solver returned UNSAT')
                return
Exemple #25
0
    def _compute_WMI_PA(self, formula, weights):
        """Computes WMI using the Predicate Abstraction (PA) algorithm.
        
        Args:
            formula (FNode): The formula on whick to compute WMI.
            weights (Weight): The corresponding weight.
            
        Returns:
            real: The final volume of the integral computed by summing up all the integrals' results.
            int: The number of problems that have been computed.
        
        """
        problems = []
        boolean_variables = get_boolean_variables(formula)
        if len(boolean_variables) == 0:
            # Enumerate partial TA over theory atoms
            lab_formula, pa_vars, labels = self.label_formula(formula, formula.get_atoms())
            # Predicate abstraction on LRA atoms with minimal models
            for assignments in self._compute_WMI_PA_no_boolean(lab_formula, pa_vars, labels):
                problem = self._create_problem(assignments, weights)
                problems.append(problem)
        else:
            solver = Solver(name="msat")
            converter = solver.converter
            solver.add_assertion(formula)
            boolean_models = []
            # perform AllSAT on the Boolean variables
            mathsat.msat_all_sat(
                solver.msat_env(),
                [converter.convert(v) for v in boolean_variables],
                lambda model : WMI._callback(model, converter, boolean_models))

            logger.debug("n_boolean_models: {}".format(len(boolean_models)))
            # for each boolean assignment mu^A of F        
            for model in boolean_models:
                atom_assignments = {}
                boolean_assignments = WMI._get_assignments(model)
                atom_assignments.update(boolean_assignments)
                subs = {k : Bool(v) for k, v in boolean_assignments.items()}
                f_next = formula
                # iteratively simplify F[A<-mu^A], getting (possibily part.) mu^LRA
                while True:            
                    f_before = f_next
                    f_next = simplify(substitute(f_before, subs))
                    lra_assignments, over = WMI._parse_lra_formula(f_next)
                    subs = {k : Bool(v) for k, v in lra_assignments.items()}
                    atom_assignments.update(lra_assignments)
                    if over or lra_assignments == {}:
                        break
                if not over:
                    # predicate abstraction on LRA atoms with minimal models
                    lab_formula, pa_vars, labels = self.label_formula(f_next, f_next.get_atoms())
                    expressions = []
                    for k, v in atom_assignments.items():
                        if k.is_theory_relation():
                            if v:
                                expressions.append(k)
                            else:
                                expressions.append(Not(k))
                                                
                    lab_formula = And([lab_formula] + expressions)
                    for assignments in self._compute_WMI_PA_no_boolean(lab_formula, pa_vars, labels, atom_assignments):
                        problem = self._create_problem(assignments, weights)
                        problems.append(problem)
                else:
                    # integrate over mu^A & mu^LRA
                    problem = self._create_problem(atom_assignments, weights)
                    problems.append(problem)

        results, cached = self.integrator.integrate_batch(problems, self.cache)
        volume = fsum(results)
        return volume, len(problems)-cached, cached
Exemple #26
0
def substitution_to_argument_tuple(pysmt_program_variables: List, sub: Dict):
    return tuple([substitute(var, sub) for var in pysmt_program_variables])
Exemple #27
0
def apply_substitution_to_argument_tuple(argument, sub):
    return tuple([substitute(arg, sub) for arg in argument])