Пример #1
0
def univariate(n):
    domain = Domain.make([], ["x{}".format(i) for i in range(n)], real_bounds=(-2, 2))
    x_vars = domain.get_symbols()
    support = smt.And(*[x > 0.5 for x in x_vars])
    weight = smt.Times(*[smt.Ite((x > -1) & (x < 1), smt.Ite(x < 0, x + smt.Real(1), -x + smt.Real(1)), smt.Real(0))
                         for x in x_vars])
    return FileDensity(domain, support, weight)
Пример #2
0
    def ast_to_smt(self, node):
        """
        :type node: Node
        """
        def convert_children(number=None):
            if number is not None and len(node.children) != number:
                raise Exception(
                    "The number of children ({}) differed from {}".format(
                        len(node.children), number))
            return [self.ast_to_smt(child) for child in node.children]

        if node.name == "ite":
            return smt.Ite(*convert_children(3))
        elif node.name == "~":
            return smt.Not(*convert_children(1))
        elif node.name == "^":
            return smt.Pow(*convert_children(2))
        elif node.name == "&":
            return smt.And(*convert_children())
        elif node.name == "|":
            return smt.Or(*convert_children())
        elif node.name == "*":
            return smt.Times(*convert_children())
        elif node.name == "+":
            return smt.Plus(*convert_children())
        elif node.name == "-":
            return smt.Minus(*convert_children(2))
        elif node.name == "<=":
            return smt.LE(*convert_children(2))
        elif node.name == ">=":
            return smt.GE(*convert_children(2))
        elif node.name == "<":
            return smt.LT(*convert_children(2))
        elif node.name == ">":
            return smt.GT(*convert_children(2))
        elif node.name == "=":
            return smt.Equals(*convert_children(2))
        elif node.name == "const":
            c_type, c_value = [child.name for child in node.children]
            if c_type == "bool":
                return smt.Bool(bool(c_value))
            elif c_type == "real":
                return smt.Real(float(c_value))
            else:
                raise Exception("Unknown constant type {}".format(c_type))
        elif node.name == "var":
            v_type, v_name = [child.name for child in node.children]
            if v_type == "bool":
                v_smt_type = smt.BOOL
            elif v_type == "real":
                v_smt_type = smt.REAL
            else:
                raise Exception("Unknown variable type {}".format(v_type))
            return smt.Symbol(v_name, v_smt_type)
        else:
            raise RuntimeError("Unrecognized node type '{}'".format(node.name))
Пример #3
0
    def _exp_to_smt(self, expression):
        if isinstance(expression, sympy.Add):
            return smt.Plus([self._exp_to_smt(arg) for arg in expression.args])
        elif isinstance(expression, sympy.Mul):
            return smt.Times(*[self._exp_to_smt(arg) for arg in expression.args])
        elif isinstance(expression, sympy.Symbol):
            return smt.Symbol(str(expression), INT)

        try:
            expression = int(expression)
            return smt.Int(expression)
        except ValueError:
            pass
        raise RuntimeError("Could not parse {} of type {}".format(expression, type(expression)))
Пример #4
0
    def _test_to_smt(self, operator):
        operator = operator.to_canonical()

        # FIXME Integer rounding only applicable if x >= 0

        def to_symbol(s):
            return smt.Symbol(s, typename=smt.types.INT)

        import math
        items = [smt.Times(smt.Int(int(math.floor(v))), to_symbol(k)) for k, v in operator.lhs.items()]
        lhs = smt.Plus([smt.Int(0)] + items)
        rhs = smt.Int(int(math.floor(operator.rhs)))

        assert operator.symbol == "<="

        return smt.LE(lhs, rhs)
Пример #5
0
def generate_click_graph(n):
    def t(c):
        return smt.Ite(c, one, zero)

    sim_n, cl_n, b_n, sim_x_n, b_x_n = "sim", "cl", "b", "sim_x", "b_x"
    domain = Domain.make(
        # Boolean
        ["{}_{}".format(sim_n, i) for i in range(n)] +
        ["{}_{}_{}".format(cl_n, i, j) for i in range(n) for j in (0, 1)] +
        ["{}_{}_{}".format(b_n, i, j) for i in range(n) for j in (0, 1)],
        # Real
        ["{}".format(sim_x_n)] +
        ["{}_{}_{}".format(b_x_n, i, j) for i in range(n) for j in (0, 1)],
        real_bounds=(0, 1))
    sim = [domain.get_symbol("{}_{}".format(sim_n, i)) for i in range(n)]
    cl = [[domain.get_symbol("{}_{}_{}".format(cl_n, i, j)) for j in (0, 1)]
          for i in range(n)]
    b = [[domain.get_symbol("{}_{}_{}".format(b_n, i, j)) for j in (0, 1)]
         for i in range(n)]
    sim_x = domain.get_symbol("{}".format(sim_x_n))
    b_x = [[domain.get_symbol("{}_{}_{}".format(b_x_n, i, j)) for j in (0, 1)]
           for i in range(n)]

    support = smt.And([
        smt.Iff(cl[i][0], b[i][0])
        & smt.Iff(cl[i][1], (sim[i] & b[i][0]) | (~sim[i] & b[i][1]))
        for i in range(n)
    ])

    one = smt.Real(1)
    zero = smt.Real(0)
    w_sim_x = t(sim_x >= 0) * t(sim_x <= 1)
    w_sim = [smt.Ite(s_i, sim_x, 1 - sim_x) for s_i in sim]
    w_b_x = [
        t(b_x[i][j] >= 0) * t(b_x[i][j] <= 1) for i in range(n) for j in (0, 1)
    ]
    w_b = [
        smt.Ite(b[i][j], b_x[i][j], 1 - b_x[i][j]) for i in range(n)
        for j in (0, 1)
    ]

    weight = smt.Times(*([w_sim_x] + w_sim + w_b_x + w_b))
    return Density(domain, support, weight)
Пример #6
0
 def affine(self, a):
     """ return some positive rescaling of the affine expression
     s.t. the rescaled expression has integer coefficients
     safe, since positive rescaling preserves
     all of a >= 0, a > 0, and a == 0 """
     # find the lcm of the offset denominator
     # and all coefficient denominators
     mult = a.offset.denominator
     for t in a.terms:
         mult = _lcm(mult, t.coeff.denominator)
     # now, we can produce an integral affine equation,
     # by rescaling through with `mult`
     a = a * Fraction(mult)
     # Finally, convert this to an SMT formula
     assert a.offset.denominator == 1
     f = SMT.Int(a.offset.numerator)
     for t in a.terms:
         assert t.coeff.denominator == 1
         sym = self._ctxt.get(t.var)
         assert sym is not None, f"expected variable name '{t.var}'"
         term = SMT.Times(SMT.Int(t.coeff.numerator), sym)
         f = SMT.Plus(f, term)
     return f
Пример #7
0
 def walk_times(self, args):
     return smt.Times(*self.walk_smt_multiple(args))
Пример #8
0
                   SMT.GT(variables[i + 2], SMT.Int(0))),
            SMT.Equals(variables[i + 1], SMT.Int(1))))

solver = SMT.Solver(name="z3")
print("constraints:")
for c in constraints:
    print(c)
    solver.add_assertion(c)

# add equations

# 24727*a_1 + 75235*b_1 + 50508*c_1 = 75235*a_2 + 125743*b_2 + 176251*c_2
solver.add_assertion(
    SMT.Equals(
        SMT.Plus(
            SMT.Plus(SMT.Times(SMT.Int(125743), variables[4]),
                     SMT.Times(SMT.Int(75235), variables[3])),
            SMT.Times(SMT.Int(176251), variables[5])),
        SMT.Plus(
            SMT.Plus(SMT.Times(SMT.Int(75235), variables[1]),
                     SMT.Times(SMT.Int(24727), variables[0])),
            SMT.Times(SMT.Int(50508), variables[2]))))

# 75235*a_2 + 125743*b_2 + 176251*c_2 = 125743*a_3 + 301994*b_3 + 16785921*c
solver.add_assertion(
    SMT.Equals(
        SMT.Plus(
            SMT.Plus(SMT.Times(SMT.Int(301994), variables[7]),
                     SMT.Times(SMT.Int(125743), variables[6])),
            SMT.Times(SMT.Int(16785921), variables[8])),
        SMT.Plus(
Пример #9
0
    def __getExpressionTree(symbolicExpression):
        # TODO LATER: take into account bitwise shift operations
        args = []
        castType = None
        if len(symbolicExpression.args) > 0:
            for symbolicArg in symbolicExpression.args:
                arg, type = Solver.__getExpressionTree(symbolicArg)
                args.append(arg)
                if castType is None:
                    castType = type
                else:
                    if castType.literal == 'Integer':
                        if type.literal == 'Real':
                            castType = type
                    # TODO LATER: consider other possible castings
            if castType.literal == 'Real':
                for i in range(len(args)):
                    args[i] = pysmt.ToReal(args[i])

        if isinstance(symbolicExpression, sympy.Not):
            if castType.literal == 'Integer':
                return pysmt.Equals(args[0], pysmt.Int(0)), Type('Bool')
            elif castType.literal == 'Real':
                return pysmt.Equals(args[0], pysmt.Real(0)), Type('Bool')
            elif castType.literal == 'Bool':
                return pysmt.Not(args[0]), Type('Bool')
            else: # castType.literal == 'BitVector'
                return pysmt.BVNot(args[0]), Type('BitVector')
        elif isinstance(symbolicExpression, sympy.Lt):
            return pysmt.LT(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Gt):
            return pysmt.GT(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Ge):
            return pysmt.GE(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Le):
            return pysmt.LE(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Eq):
            return pysmt.Equals(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.Ne):
            return pysmt.NotEquals(args[0], args[1]), Type('Bool')
        elif isinstance(symbolicExpression, sympy.And):
            if castType.literal == 'Bool':
                return pysmt.And(args[0], args[1]), Type('Bool')
            else: # type.literal == 'BitVector'
                return pysmt.BVAnd(args[0], args[1]), castType
        elif isinstance(symbolicExpression, sympy.Or):
            if castType.literal == 'Bool':
                return pysmt.Or(args[0], args[1]), Type('Bool')
            else:  # type.literal == 'BitVector'
                return pysmt.BVOr(args[0], args[1]), castType
        elif isinstance(symbolicExpression, sympy.Xor):
            return pysmt.BVXor(args[0], args[1]), castType
        elif isinstance(symbolicExpression, sympy.Add):
            return pysmt.Plus(args), castType
        elif isinstance(symbolicExpression, sympy.Mul):
            return pysmt.Times(args), castType
        elif isinstance(symbolicExpression, sympy.Pow):
            return pysmt.Pow(args[0], args[1]), castType
        # TODO LATER: deal with missing modulo operator from pysmt
        else:
            if isinstance(symbolicExpression, sympy.Symbol):
                symbolType = Variable.symbolTypes[symbolicExpression.name]
                literal = symbolType.getTypeForSolver()
                designator = symbolType.designatorExpr1
                type = Type(literal, designator)
                return Solver.__encodeTerminal(symbolicExpression, type), type
            elif isinstance(symbolicExpression, sympy.Integer):
                type = Type('Integer')
                return Solver.__encodeTerminal(symbolicExpression, type), type
            elif isinstance(symbolicExpression, sympy.Rational):
                type = Type('Real')
                return Solver.__encodeTerminal(symbolicExpression, type), type
            elif isinstance(symbolicExpression, sympy.Float):
                type = Type('Real')
                return Solver.__encodeTerminal(symbolicExpression, type), type
            else:
                type = Type('Real')
                return Solver.__encodeTerminal(symbolicExpression, type), type
Пример #10
0
    def initialize(self, mdp, colors, hole_options, reward_name, okay_states,
                   target_states, threshold, relation):
        logger.warning("This approach has been tested sparsely.")
        prob0E, prob1A = stormpy.compute_prob01min_states(
            mdp, okay_states, target_states)
        sink_states = ~okay_states

        assert len(mdp.initial_states) == 1
        self.state_vars = [
            smt.Symbol("p_{}".format(i), smt.REAL)
            for i in range(mdp.nr_states)
        ]
        self.state_prob1_vars = [
            smt.Symbol("asure_{}".format(i)) for i in range(mdp.nr_states)
        ]
        self.state_probpos_vars = [
            smt.Symbol("x_{}".format(i)) for i in range(mdp.nr_states)
        ]
        self.state_order_vars = [
            smt.Symbol("r_{}".format(i), smt.REAL)
            for i in range(mdp.nr_states)
        ]
        self.option_vars = dict()
        for h, opts in hole_options.items():
            self.option_vars[h] = {
                index: smt.Symbol("h_{}_{}".format(h, opt))
                for index, opt in enumerate(opts)
            }
        self.transition_system = []
        logger.debug("Obtain rewards if necessary")

        rewards = mdp.reward_models[reward_name] if reward_name else None
        if rewards:
            assert not rewards.has_transition_rewards
            state_rewards = rewards.has_state_rewards
            action_rewards = rewards.has_state_action_rewards
            logger.debug(
                "Model has state rewards: {}, has state/action rewards {}".
                format(state_rewards, action_rewards))

            self.transition_system.append(
                self.state_prob1_vars[mdp.initial_states[0]])

        threshold_inequality, action_constraint_inequality = self._to_smt_relation(
            relation)  # TODO or GE
        self.transition_system.append(
            threshold_inequality(self.state_vars[mdp.initial_states[0]],
                                 smt.Real(float(threshold))))

        state_order_domain_constraint = smt.And([
            smt.And(smt.GE(var, smt.Real(0)), smt.LE(var, smt.Real(1)))
            for var in self.state_order_vars
        ])
        self.transition_system.append(state_order_domain_constraint)
        #TODO how to ensure that prob is zero if there is no path.

        select_parameter_value_constraints = []
        for h, opts in self.option_vars.items():
            select_parameter_value_constraints.append(
                smt.Or(ov for ov in opts.values()))
            for i, opt1 in enumerate(opts.values()):
                for opt2 in list(opts.values())[i + 1:]:
                    select_parameter_value_constraints.append(
                        smt.Not(smt.And(opt1, opt2)))
        #logger.debug("Consistency: {}".format(smt.And(select_parameter_value_constraints)))
        self.transition_system.append(
            smt.And(select_parameter_value_constraints))

        for state in mdp.states:
            if sink_states.get(state.id):
                assert rewards is None
                self.transition_system.append(
                    smt.Equals(self.state_vars[state.id], smt.REAL(0)))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                self.transition_system.append(
                    smt.Not(self.state_prob1_vars[state.id]))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                self.transition_system.append(
                    smt.Equals(self.state_order_vars[state.id], smt.Real(0)))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
            elif target_states.get(state.id):
                self.transition_system.append(
                    smt.Equals(self.state_order_vars[state.id], smt.Real(1)))
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                self.transition_system.append(self.state_prob1_vars[state.id])
                #logger.debug("Constraint: {}".format(self.transition_system[-1]))

                if rewards is None:
                    self.transition_system.append(
                        smt.Equals(self.state_vars[state.id], smt.Real(1)))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                else:
                    self.transition_system.append(
                        self.state_probpos_vars[state.id])
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    self.transition_system.append(
                        smt.Equals(self.state_vars[state.id], smt.Real(0)))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
            else:
                state_in_prob1A = False
                state_in_prob0E = False
                if prob0E.get(state.id):
                    state_in_prob0E = True
                else:
                    self.transition_system.append(
                        smt.Equals(self.state_order_vars[state.id],
                                   smt.Real(1)))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    self.transition_system.append(
                        self.state_probpos_vars[state.id])
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                if rewards and not state_in_prob0E:
                    if prob1A.get(state.id):
                        self.transition_system.append(
                            self.state_prob1_vars[state.id])
                        logger.debug("Constraint: {}".format(
                            self.transition_system[-1]))
                        state_in_prob1A = True

                for action in state.actions:
                    action_index = mdp.nondeterministic_choice_indices[
                        state.id] + action.id
                    #logger.debug("Action index: {}".format(action_index))
                    precondition = smt.And([
                        self.option_vars[hole][list(option)[0]] for hole,
                        option in colors.get(action_index, dict()).items()
                    ])
                    reward_value = None
                    if rewards:
                        reward_const = (rewards.get_state_reward(
                            state.id) if state_rewards else 0.0) + (
                                rewards.get_state_action_reward(action_index)
                                if action_rewards else 0.0)
                        reward_value = smt.Real(reward_const)
                    act_constraint = action_constraint_inequality(
                        self.state_vars[state.id],
                        smt.Plus([
                            smt.Times(smt.Real(t.value()), self.
                                      state_vars[t.column])
                            for t in action.transitions
                        ] + [reward_value] if reward_value else []))
                    full_act_constraint = act_constraint
                    if state_in_prob0E:
                        if not rewards:
                            full_act_constraint = smt.And(
                                smt.Implies(self.state_probpos_vars[state.id],
                                            act_constraint),
                                smt.Implies(
                                    smt.Not(self.state_probpos_vars),
                                    smt.Equals(self.state_vars[state.id],
                                               smt.Real(0))))
                        self.transition_system.append(
                            smt.Implies(
                                precondition,
                                smt.Iff(
                                    self.state_probpos_vars[state.id],
                                    smt.Or([
                                        smt.And(
                                            self.state_probpos_vars[t.column],
                                            smt.LT(
                                                self.state_order_vars[
                                                    state.id],
                                                self.state_order_vars[
                                                    t.column]))
                                        for t in action.transitions
                                    ]))))
                        #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    if rewards and not state_in_prob1A:
                        # prob_one(state) <-> probpos AND for all succ prob_one(succ)
                        self.transition_system.append(
                            smt.Implies(
                                precondition,
                                smt.Iff(
                                    self.state_prob1_vars[state.id],
                                    smt.And([
                                        self.state_prob1_vars[t.column]
                                        for t in action.transitions
                                    ] + [self.state_probpos_vars[state.id]]))))
                        #logger.debug("Constraint: {}".format(self.transition_system[-1]))
                    self.transition_system.append(
                        smt.Implies(precondition, full_act_constraint))
                    #logger.debug("Constraint: {}".format(self.transition_system[-1]))

        if rewards:
            self.transition_system.append(
                smt.And([smt.GE(sv, smt.Real(0)) for sv in self.state_vars]))
        else:
            self.transition_system.append(
                smt.And([
                    smt.And(smt.GE(sv, smt.Real(0)), smt.LE(sv, smt.Real(1)))
                    for sv in self.state_vars
                ]))

        #print(self.transition_system)
        formula = smt.And(self.transition_system)
        logger.info("Start SMT solver")
        model = smt.get_model(formula)

        if model:
            logger.info("SAT: Found {}".format(model))
        else:
            logger.info("UNSAT.")