Пример #1
0
    def query(self, *query, **kwargs):
        if 'max_solutions' in kwargs:
            max_solutions = kwargs['max_solutions']
        else:
            max_solutions = -1

        body_atms = [x.as_muz() for x in query]
        self._solver.query(*body_atms)

        ans = self._solver.get_answer()

        query_vars = [x.get_variables() for x in query]
        query_vars = reduce(lambda x, y: x + [v for v in y if v not in x],
                            query_vars, [])

        if is_false(ans):
            # no solution
            return []
        elif not (is_and(ans) or is_or(ans)):
            # single solution, value of a single variable
            val = int(ans.children()[1].as_long())
            #varb = query.get_variables()[0]
            varb = query_vars[0]
            return [{varb: c_id_to_const(val, varb.get_type())}]
        elif is_or(ans) and not (is_and(ans.children()[0])
                                 or is_or(ans.children()[0])):
            # multiple solutions of single variable
            vals = [int(x.children()[1].as_long()) for x in ans.children()]
            #varbs = query.get_variables()[0]
            varbs = query_vars[0]
            varbs = [varbs] * len(vals)
            return [{
                k: c_id_to_const(v, varbs[0].get_type())
            } for k, v in zip(varbs, vals)]
        elif is_and(ans):
            # single solution of more than 1 variable
            ans = [int(x.children()[1].as_long()) for x in ans.children()]
            ans = [ans]
        elif is_or(ans):
            # multiple solutions of more than 1 variable
            ans = ans.children()
            ans = [[int(y.children()[1].as_long()) for y in x.children()]
                   for x in ans]
        else:
            raise Exception(f"don't know how to parse {ans}")

        tmp_args = [v for x in query for v in x.get_variables()]
        args = reduce(lambda x, y: x + [y] if y not in x else x, tmp_args, [])

        answer = [
            dict([(v, c_id_to_const(c,
                                    v.get_type().name))
                  for v, c in zip(args, x)]) for x in ans
        ]

        if max_solutions > 0:
            return answer[:max_solutions]
        else:
            return answer
Пример #2
0
def elim_bool_ite(exp):
    if z3.is_quantifier(exp):
        (qvars, matrix) = strip_qblock(exp)
        matrix = elim_bool_ite(matrix)
        if exp.is_forall():
            e = z3.ForAll(qvars, matrix)
        else:
            e = z3.Exists(qvars, matrix)
        return e
    if not z3.is_bool(exp): return exp
    if z3.is_true(exp) or z3.is_false(exp): return exp
    assert z3.is_app(exp)
    decl = exp.decl()
    args = map(elim_bool_ite, exp.children())
    # need to worry about And and Or because they can take >2 args and
    # decl(*args) doesn't seem to work with the py interface
    if z3.is_and(exp):
        return z3.And(*args)
    elif z3.is_or(exp):
        return z3.Or(*args)
    elif is_ite(exp):
        impl1 = z3.Implies(args[0], args[1])
        impl2 = z3.Implies(z3.Not(args[0]), args[2])
        return z3.And(impl1, impl2)
    else:
        return decl(*args)
Пример #3
0
def transformNonBooleanLazyEvaluations(var):
    if z3.is_or(var):
        # in this case it needs to be the first child since we are using it as a first child when coercing any expression to bool
        left = var.children()[0].children()[0]
        if len(var.children()[1].children()) == 0:
            if str(var.children()[1]) == 'False':
                return left
            else:

                raise Exception('Why would the lazy side of the or be a truthy value?')
        else:
            right = var.children()[1].children()[0]
        sub = z3.String('__ignore({}||{})'.format(str(left), str(right)))

        GLOBAL_CONSTRAINTS.append(z3.Or(left == sub, right == sub))
        return sub

    if z3.is_and(var):
        # FIXME what about the first child
        # in this case it needs to be the first child since we are using it as a first child when coercing any expression to bool
        right = var.children()[1].children()[0]
        # this is by construction the not null of the first
        GLOBAL_CONSTRAINTS.append(var.children()[0])

        return right

    return var
Пример #4
0
def coerceTypesIfPossible(var, other_var):
    if z3.is_or(other_var) and not z3.is_bool(var):
        other_var = transformNonBooleanLazyEvaluations(other_var)
    if z3.is_or(var) and not z3.is_bool(other_var):
        var = transformNonBooleanLazyEvaluations(var)

    if z3.is_and(other_var) and not z3.is_bool(var):
        other_var = transformNonBooleanLazyEvaluations(other_var)
    if z3.is_and(var) and not z3.is_bool(other_var):
        var = transformNonBooleanLazyEvaluations(var)
    if var.decl().kind() == z3.Z3_OP_UNINTERPRETED:
        if z3.is_bool(other_var) and not z3.is_bool(var):
            infered_types[str(var)] = 'boolean'
            return z3.Bool(str(var)), other_var
        if z3.is_string(other_var) and not z3.is_string(var):
            if other_var.as_string() == '':
                # we probably dont want to coerce in this specific case as this is merely a non empty check
                if z3.is_bool(var):
                    return var, z3.BoolVal(False)
                if z3.is_int(var):
                    return var, z3.IntVal(0)
            else:
                infered_types[str(var)] = 'string'
                return z3.String(str(var)), other_var
        if z3.is_int(other_var) and not z3.is_int(var):
            infered_types[str(var)] = 'number'
            return z3.Int(str(var)), other_var
    elif var.decl().kind() == z3.Z3_OP_UNINTERPRETED:
        if z3.is_bool(var):
            infered_types[str(var)] = 'boolean'
        if z3.is_string(var):
            infered_types[str(var)] = 'string'
        if z3.is_int(var):
            infered_types[str(var)] = 'number'
    else:
        # this means that it is non-interpreted and we need to coerce other var to the type of var
        if z3.is_string(var) and z3.is_int_value(other_var):
            other_var = z3.StringVal(str(other_var))
        if z3.is_arith(var) and z3.is_string(other_var):
            other_var = z3.IntVal(int(other_var.as_string()))

    return var, other_var
Пример #5
0
def formula2dimacs(z3_formula,
                   output_filename,
                   append_to_file=False,
                   verbose=False):
    seen_literals = {}
    number_of_clauses = 0

    clauses = []
    if append_to_file:
        if not os.path.isfile(output_filename):
            print('{} does not exist! Exiting...')
            exit(1)

    cnf_clauses = []
    # Z3 expressions can be applications, quantifiers and bounded/free variables
    # FIXME
    for expr in z3_formula:
        if z3.is_quantifier(expr):
            print('Expecting {} to be OR, got quantifier in CNF!'.format(expr))
            return

        #print(expr)
        if z3.is_or(expr):
            or_clause = ''.join(
                [translate2(lit, seen_literals) for lit in expr.children()])
            cnf_clauses.append(or_clause)
        else:
            lit = translate2(expr, seen_literals)
            cnf_clauses.append(lit)

    if not append_to_file:
        with open(output_filename, 'w') as f:
            f.write('p cnf {} {}\n'.format(len(seen_literals),
                                           len(cnf_clauses)))
            for clause in cnf_clauses:
                f.write('{}0\n'.format(clause))
    else:
        (num_vars, num_clauses) = parse_dimacs_header(output_filename)
        with open(output_filename, 'r') as from_file:
            tmp_path = output_filename + ".tmp"
            with open(tmp_path, 'w') as tmp_file:
                tmp_file.write('p cnf {} {}\n'.format(
                    num_vars + len(seen_literals),
                    num_clauses + len(cnf_clauses)))
                line = from_file.readline()
                for line in from_file.readlines():
                    tmp_file.write(line)

                for clause in cnf_clauses:
                    tmp_file.write('{}0\n'.format(clause))

            os.rename(tmp_path, output_filename)
    def toCnf(self):
        #t = Then('simplify','nnf')
        #subgoal = t(simplify(self._kb))
        #self._logger.writeToLog("subgoal",subgoal)
        cnf = z3.simplify(self._toCnf(self._kb))
        cnflist = []
        if z3.is_and(cnf):
            for i in cnf.children():
                tmp = []
                if z3.is_or(i):
                    for ii in i.children():
                        if z3.is_const(ii) or z3.is_not(ii) and z3.is_const(
                                ii.children()[0]):
                            tmp.append(ii)
                        else:
                            self._logger.writeToLog("Wrongly formulated CNF")
                            raise Exception
                elif z3.is_not(i) and z3.is_const(i.children()[0]):
                    tmp.append(i)
                elif z3.is_const(i):
                    tmp.append(i)
                else:
                    self._logger.writeToLog("Wonrgly formulated CNF")
                cnflist.append(tmp)
        elif z3.is_or(cnf):
            tmp = []
            for i in cnf.children():
                if z3.is_const(i) or z3.is_not(i) and z3.is_const(
                        i.children()[0]):
                    tmp.append(i)
                else:
                    self._logger.writeToLog("Wonrgly formulated CNF")
            cnflist.append(tmp)

        self._logger.writeToLog(
            "Full Propositional KB in CNF: {}".format(cnflist))
        return cnflist
 def _parseSmt2String(self, formula):
     try:
         if z3.is_or(formula):
             return z3.Or(self._parseSmt2String(formula.children()))
         elif z3.is_and(formula):
             return z3.And(self._parseSmt2String(formula.children()))
         elif isinstance(formula, list):  # and len(formula) > 1:
             tmp = []
             for elem in formula:
                 tmp.append(self._parseSmt2String(elem))
             return tmp
         elif z3.is_not(formula):
             return z3.Not(self._parseSmt2String(formula.children()[0]))
         else:
             return self._abstraction(formula)
     except:
         self._logger.writeToLog(
             "Some Error Occured parsing formula: {}".format(formula))
         raise Exception
Пример #8
0
 def mk_app(self, f, args):
     if z3.is_eq(f):
         return args[0] == args[1]
     elif z3.is_and(f):
         return And(*args)
     elif z3.is_or(f):
         return Or(*args)
     elif z3.is_not(f):
         return Not(*args)
     elif z3.is_add(f):
         return reduce(operator.add, args[1:], args[0])
     elif z3.is_mul(f):
         return reduce(operator.mul, args[1:], args[0])
     elif z3.is_sub(f):
         return args[0] - args[1]
     elif z3.is_div(f):
         return args[0] / args[1]
     elif z3.is_lt(f):
         return args[0] < args[1]
     elif z3.is_le(f):
         return args[0] <= args[1]
     elif z3.is_gt(f):
         return args[0] > args[1]
     elif z3.is_ge(f):
         return args[0] >= args[1]
     elif z3.is_to_real(f):    # TODO: ignore coercions?
         return args[0]
     elif z3.is_to_int(f):
         return args[0]
     elif f.name() == '=>':
         return implies(args[0], args[1])
     else:
         dom_types = [self.mk_sort(f.domain(i))\
                      for i in range(0, f.arity())]
         cod_type = self.mk_sort(f.range())
         dom_types.reverse()
         fun_type = reduce((lambda X, Y: type_arrow(Y, X)), \
                           dom_types, cod_type)
         func = self.mk_fun(f)
         return func(*args)
Пример #9
0
 def mk_app(self, f, args):
     if z3.is_eq(f):
         return args[0] == args[1]
     elif z3.is_and(f):
         return And(*args)
     elif z3.is_or(f):
         return Or(*args)
     elif z3.is_not(f):
         return Not(*args)
     elif z3.is_add(f):
         return reduce(operator.add, args[1:], args[0])
     elif z3.is_mul(f):
         return reduce(operator.mul, args[1:], args[0])
     elif z3.is_sub(f):
         return args[0] - args[1]
     elif z3.is_div(f):
         return args[0] / args[1]
     elif z3.is_lt(f):
         return args[0] < args[1]
     elif z3.is_le(f):
         return args[0] <= args[1]
     elif z3.is_gt(f):
         return args[0] > args[1]
     elif z3.is_ge(f):
         return args[0] >= args[1]
     elif z3.is_to_real(f):    # TODO: ignore coercions?
         return args[0]
     elif z3.is_to_int(f):
         return args[0]
     elif f.name() == '=>':
         return implies(args[0], args[1])
     else:
         dom_types = [self.mk_sort(f.domain(i))\
                      for i in range(0, f.arity())]
         cod_type = self.mk_sort(f.range())
         dom_types.reverse()
         fun_type = reduce((lambda X, Y: type_arrow(Y, X)), \
                           dom_types, cod_type)
         func = self.mk_fun(f)
         return func(*args)
Пример #10
0
    def _toCnf(self, formula):
        if z3.is_or(formula):
            tmp = []
            ground = []
            for i in formula.children():
                tmp.append(self._toCnf(i))
            for i in tmp:
                if z3.is_and(i):
                    ground.append(i.children())
                elif z3.is_const(i):
                    ground.append([i])
                elif z3.is_not(i) and z3.is_const(i.children()[0]):
                    ground.append([i])
                elif z3.is_or(i) and all(
                        z3.is_const(elem)
                        or z3.is_not(elem) and z3.is_const(elem.children()[0])
                        for elem in i.children()):
                    for j in i.children():
                        ground.append([j])
                else:
                    self._logger.writeToLog("is_or, {},{}".format(formula, i))
                    raise Exception
            result = []
            self._logger.writeToLog("CROSS: {}".format(ground))
            for i in itertools.product(*ground):
                self._logger.writeToLog('Writing to rsults: {},{}'.format(
                    i, list(i)))
                result.append(z3.Or(i))
            self._logger.writeToLog('Resutl: {}'.format(result))
            result = z3.And(result)
            self._logger.writeToLog('ResutAnd: {}'.format(result))
            resultS = z3.simplify(result)
            self._logger.writeToLog("Result simplified: {}".format(resultS))
            return resultS

        elif z3.is_and(formula):
            tmp = []
            ground = []
            for i in formula.children():
                tmp.append(self._toCnf(i))
            for i in tmp:
                if z3.is_and(i):
                    ground.extend(i.children())
                elif z3.is_const(i):
                    ground.append(i)
                elif z3.is_not(i) and z3.is_const(i.children()[0]):
                    ground.append(i)
                elif z3.is_or(i) and all(
                        z3.is_const(elem)
                        or z3.is_not(elem) and z3.is_const(elem.children()[0])
                        for elem in i.children()):
                    ground.append(i)

                # SHoueld be ----> (1 v 2) and 3 --> (1 and 3 or 2 and 3) not just adding them to the and statement.... right ?
                else:
                    self._logger.error("is_and, {}, {}".format(formula, i))
                    raise Exception
            return z3.simplify(z3.And(ground))
        elif z3.is_not(formula):
            if z3.is_const(formula.children()[0]):
                return formula
            elif z3.is_not(formula.children()[0]):
                return self._toCnf(formula.children()[0])
            elif z3.is_and(formula.children()[0]):
                return self._toCnf(
                    z3.Or([
                        z3.Not(elem)
                        for elem in formula.children()[0].children()
                    ]))
            elif z3.is_or(formula.children()[0]):
                return self._toCnf(
                    z3.And([
                        z3.Not(elem)
                        for elem in formula.children()[0].children()
                    ]))
            else:
                self._logger.writeToLog("is_not({}) problem".formula(formula))
                raise Exception
        elif z3.is_const(formula):
            return formula
        else:
            self._logger.writeToLog("is_nothing problem", formula)
Пример #11
0
def get_disjuncts (exp) :
  assert z3.is_bool (exp)
  if z3.is_or (exp) : return exp.children ()
  else : return [exp]
Пример #12
0
def writeQDIMACS(filename, constraint, quantifiers, bitmap=None):
    # filename: String
    # constraints: list of BV constraints
    # quantifiers: list of tuples (['a','e','max','count'], list of vars)

    assert_consistent_quantifiers(quantifiers)

    log('Bit blasting')
    bitmap = {}

    for q in quantifiers:
        bitvecs = filter(is_bv, q[1])
        localBitmap, localBitmapConstraints = create_bitmap(bitvecs)
        bitmap.update(localBitmap)
        constraint = And(localBitmapConstraints, constraint)
        newQuantifiedVars = filter(lambda v: not is_bv(v), q[1])
        for (_, boolvar) in localBitmap.iteritems():
            newQuantifiedVars.append(boolvar)
        q[1] = newQuantifiedVars

    g = Goal()
    g.add(constraint)
    matrix = []
    t = Then('simplify', 'bit-blast', 'tseitin-cnf')
    subgoal = t(g)
    # print(subgoal[0][0].children()[1].children()[0] == bitmap())
    assert len(subgoal) == 1

    # print('Printing quantifier')
    # print(quantifiers)
    # print('Printing goal')
    # print(g)
    # exit()

    max_var = 0
    var_mapping = {}  # maps to qdimacs variables

    textFile = open(filename, "w")

    log('Creating and writing symbol table')
    textFile.write('c Symbol table for bitvectors\n')
    symbol_table = []
    for ((bv, i), boolvar) in bitmap.iteritems():
        max_var += 1
        var_mapping[boolvar.get_id()] = max_var
        # symbol_table.append('c ' + str(boolvar) + ' --> ' + str(max_var))
        textFile.write('c ' + str(boolvar) + ' --> ' + str(max_var) + '\n')

    log('Reserving variable names for quantified variables')
    for i, q in enumerate(quantifiers):
        for var in q[1]:
            if var.get_id() not in var_mapping:
                max_var += 1
                var_mapping[var.get_id()] = max_var

    # minTseitin = max_var + 1
    Tseitin_vars = []

    log('Generating clauses ... (this may take a while)')
    clause_num = 0
    for c in subgoal[0]:
        clause_num += 1
        if clause_num % 10000 == 0:
            log('  {} clauses'.format(clause_num))
        if is_or(c):
            clause = ''
            for l in c.children():  # literals
                max_var, lit_str = encode_literal(var_mapping, Tseitin_vars,
                                                  max_var, l)
                clause += lit_str
            matrix.append(clause)
        elif is_const(c) or is_not(c):
            max_var, lit_str = encode_literal(var_mapping, Tseitin_vars,
                                              max_var, c)
            matrix.append(lit_str)
        else:
            log('Error: Unknown element ' + str(c))
            assert false
    matrix.append('')
    log('  Generated ' + str(clause_num) + ' clauses')

    log('Writing header')
    textFile.write('p cnf {} {}\n'.format(max_var, clause_num))

    # Extending quantifiers by innermost existential if necessary
    if quantifiers[-1][0] == 'a' and len(
            Tseitin_vars) > 0:  #  max_var + 1 - minTseitin > 0
        quantifiers.append(['e', []])  # empty existential

    log('Writing quantifiers')
    for i, q in enumerate(quantifiers):
        textFile.write(q[0])
        for v in q[1]:
            # try:
            v_id = v.get_id()
            textFile.write(' ' + str(var_mapping[v_id]))
            # except Exception as ex:
            #     log(' Error when writing var {} to file ({})'.format(str(v), str(ex)))
            #
            #     template = "An exception of type {0} occurred. Arguments:\n{1!r}"
            #     message = template.format(type(ex).__name__, ex.args)
            #     print message
            #
            #     exit()

        if i == len(quantifiers) - 1:
            log('Adding {} Tseitin variables'.format(len(Tseitin_vars)))
            for varID in Tseitin_vars:
                textFile.write(' ' + str(varID))

            # for varID in range(minTseitin,max_var+1):
#                 # log('Adding var {}'.format(varID))
#                 textFile.write(' '+str(varID))
#                 # quantifiers[-1][1].append(varID)
# log('  OK (added {} Tseitin vars)'.format(len(range(minTseitin,max_var+1))))

        textFile.write(' 0\n')

    log('Writing clauses')
    textFile.write('0\n'.join(matrix))
    textFile.close()

    return var_mapping
Пример #13
0
    def _back_single_term(self, expr, args):
        assert z3.is_expr(expr)

        if z3.is_quantifier(expr):
            raise NotImplementedError(
                "Quantified back conversion is currently not supported")

        res = None
        if z3.is_and(expr):
            res = self.mgr.And(args)
        elif z3.is_or(expr):
            res = self.mgr.Or(args)
        elif z3.is_add(expr):
            res = self.mgr.Plus(args)
        elif z3.is_div(expr):
            res = self.mgr.Div(args[0], args[1])
        elif z3.is_eq(expr):
            if self._get_type(args[0]).is_bool_type():
                res = self.mgr.Iff(args[0], args[1])
            else:
                res = self.mgr.Equals(args[0], args[1])
        elif z3.is_iff(expr):
            res = self.mgr.Iff(args[0], args[1])
        elif z3.is_xor(expr):
            res = self.mgr.Xor(args[0], args[1])
        elif z3.is_false(expr):
            res = self.mgr.FALSE()
        elif z3.is_true(expr):
            res = self.mgr.TRUE()
        elif z3.is_gt(expr):
            res = self.mgr.GT(args[0], args[1])
        elif z3.is_ge(expr):
            res = self.mgr.GE(args[0], args[1])
        elif z3.is_lt(expr):
            res = self.mgr.LT(args[0], args[1])
        elif z3.is_le(expr):
            res = self.mgr.LE(args[0], args[1])
        elif z3.is_mul(expr):
            res = self.mgr.Times(args[0], args[1])
        elif z3.is_uminus(expr):
            tp = self._get_type(args[0])
            if tp.is_real_type():
                minus_one = self.mgr.Real(-1)
            else:
                assert tp.is_int_type()
                minus_one = self.mgr.Int(-1)
            res = self.mgr.Times(args[0], minus_one)
        elif z3.is_sub(expr):
            res = self.mgr.Minus(args[0], args[1])
        elif z3.is_not(expr):
            res = self.mgr.Not(args[0])
        elif z3.is_implies(expr):
            res = self.mgr.Implies(args[0], args[1])
        elif z3.is_quantifier(expr):
            raise NotImplementedError
        elif z3.is_const(expr):
            if z3.is_rational_value(expr):
                n = expr.numerator_as_long()
                d = expr.denominator_as_long()
                f = Fraction(n, d)
                res = self.mgr.Real(f)
            elif z3.is_int_value(expr):
                n = expr.as_long()
                res = self.mgr.Int(n)
            elif z3.is_bv_value(expr):
                n = expr.as_long()
                w = expr.size()
                res = self.mgr.BV(n, w)
            else:
                # it must be a symbol
                res = self.mgr.get_symbol(str(expr))
        elif z3.is_ite(expr):
            res = self.mgr.Ite(args[0], args[1], args[2])
        elif z3.is_function(expr):
            res = self.mgr.Function(self.mgr.get_symbol(expr.decl().name()), args)
        elif z3.is_to_real(expr):
            res = self.mgr.ToReal(args[0])
        elif z3.is_bv_and(expr):
            res = self.mgr.BVAnd(args[0], args[1])
        elif z3.is_bv_or(expr):
            res = self.mgr.BVOr(args[0], args[1])
        elif z3.is_bv_xor(expr):
            res = self.mgr.BVXor(args[0], args[1])
        elif z3.is_bv_not(expr):
            res = self.mgr.BVNot(args[0])
        elif z3.is_bv_neg(expr):
            res = self.mgr.BVNeg(args[0])
        elif z3.is_bv_concat(expr):
            res = self.mgr.BVConcat(args[0], args[1])
        elif z3.is_bv_ult(expr):
            res = self.mgr.BVULT(args[0], args[1])
        elif z3.is_bv_uleq(expr):
            res = self.mgr.BVULE(args[0], args[1])
        elif z3.is_bv_slt(expr):
            res = self.mgr.BVSLT(args[0], args[1])
        elif z3.is_bv_sleq(expr):
            res = self.mgr.BVSLE(args[0], args[1])
        elif z3.is_bv_ugt(expr):
            res = self.mgr.BVUGT(args[0], args[1])
        elif z3.is_bv_ugeq(expr):
            res = self.mgr.BVUGE(args[0], args[1])
        elif z3.is_bv_sgt(expr):
            res = self.mgr.BVSGT(args[0], args[1])
        elif z3.is_bv_sgeq(expr):
            res = self.mgr.BVSGE(args[0], args[1])
        elif z3.is_bv_extract(expr):
            end = z3.get_payload(expr, 0)
            start = z3.get_payload(expr, 1)
            res = self.mgr.BVExtract(args[0], start, end)
        elif z3.is_bv_add(expr):
            res = self.mgr.BVAdd(args[0], args[1])
        elif z3.is_bv_mul(expr):
            res = self.mgr.BVMul(args[0], args[1])
        elif z3.is_bv_udiv(expr):
            res = self.mgr.BVUDiv(args[0], args[1])
        elif z3.is_bv_sdiv(expr):
            res = self.mgr.BVSDiv(args[0], args[1])
        elif z3.is_bv_urem(expr):
            res = self.mgr.BVURem(args[0], args[1])
        elif z3.is_bv_srem(expr):
            res = self.mgr.BVSRem(args[0], args[1])
        elif z3.is_bv_lshl(expr):
            res = self.mgr.BVLShl(args[0], args[1])
        elif z3.is_bv_lshr(expr):
            res = self.mgr.BVLShr(args[0], args[1])
        elif z3.is_bv_ashr(expr):
            res = self.mgr.BVAShr(args[0], args[1])
        elif z3.is_bv_sub(expr):
            res = self.mgr.BVSub(args[0], args[1])
        elif z3.is_bv_rol(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVRol(args[0], amount)
        elif z3.is_bv_ror(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVRor(args[0], amount)
        elif z3.is_bv_ext_rol(expr):
            amount = args[1].bv_unsigned_value()
            res = self.mgr.BVRol(args[0], amount)
        elif z3.is_bv_ext_ror(expr):
            amount = args[1].bv_unsigned_value()
            res = self.mgr.BVRor(args[0], amount)
        elif z3.is_bv_sext(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVSExt(args[0], amount)
        elif z3.is_bv_zext(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVZExt(args[0], amount)

        if res is None:
            raise ConvertExpressionError(message=("Unsupported expression: %s" %
                                                   str(expr)),
                                         expression=expr)
        return res
Пример #14
0
    def back(self, expr):
        assert z3.is_expr(expr)

        if askey(expr) in self.backconversion:
            return self.backconversion[askey(expr)]

        if z3.is_quantifier(expr):
            raise NotImplementedError(
                "Quantified back conversion is currently not supported")

        args = [self.back(x) for x in expr.children()]
        res = None
        if z3.is_and(expr):
            res = self.mgr.And(args)

        elif z3.is_or(expr):
            res = self.mgr.Or(args)

        elif z3.is_add(expr):
            res = self.mgr.Plus(args)

        elif z3.is_div(expr):
            res = self.mgr.Div(args[0], args[1])

        elif z3.is_eq(expr):
            if self._get_type(args[0]) == types.BOOL:
                res = self.mgr.Iff(args[0], args[1])
            else:
                res = self.mgr.Equals(args[0], args[1])

        elif z3.is_false(expr):
            res = self.mgr.FALSE()

        elif z3.is_true(expr):
            res = self.mgr.TRUE()

        elif z3.is_gt(expr):
            res = self.mgr.GT(args[0], args[1])

        elif z3.is_ge(expr):
            res = self.mgr.GE(args[0], args[1])

        elif z3.is_lt(expr):
            res = self.mgr.LT(args[0], args[1])

        elif z3.is_le(expr):
            res = self.mgr.LE(args[0], args[1])

        elif z3.is_mul(expr):
            res = self.mgr.Times(args[0], args[1])

        elif z3.is_sub(expr):
            res = self.mgr.Minus(args[0], args[1])

        elif z3.is_not(expr):
            res = self.mgr.Not(args[0])

        elif z3.is_quantifier(expr):
            if expr.is_forall():
                pass
            else:
                pass
            raise NotImplementedError

        elif z3.is_const(expr):
            if z3.is_rational_value(expr):
                n = expr.numerator_as_long()
                d = expr.denominator_as_long()
                f = Fraction(n, d)
                res = self.mgr.Real(f)
            elif z3.is_int_value(expr):
                n = expr.as_long()
                res = self.mgr.Int(n)
            else:
                # it must be a symbol
                res = self.mgr.get_symbol(str(expr))

        elif z3.is_ite(expr):
            res = self.mgr.Ite(args[0], args[1], args[2])

        else:
            raise TypeError("Unsupported expression:", expr)

        if res is None:
            raise TypeError("Unsupported expression:", expr)

        self.backconversion[askey(expr)] = res

        return res
Пример #15
0
Файл: z3.py Проект: 0Chuzz/pysmt
    def _back_single_term(self, expr, args, model=None):
        assert z3.is_expr(expr)

        if z3.is_quantifier(expr):
            raise NotImplementedError(
                "Quantified back conversion is currently not supported")

        res = None
        if z3.is_and(expr):
            res = self.mgr.And(args)
        elif z3.is_or(expr):
            res = self.mgr.Or(args)
        elif z3.is_add(expr):
            res = self.mgr.Plus(args)
        elif z3.is_div(expr):
            res = self.mgr.Div(args[0], args[1])
        elif z3.is_eq(expr):
            if self._get_type(args[0]).is_bool_type():
                res = self.mgr.Iff(args[0], args[1])
            else:
                res = self.mgr.Equals(args[0], args[1])
        elif z3.is_iff(expr):
            res = self.mgr.Iff(args[0], args[1])
        elif z3.is_xor(expr):
            res = self.mgr.Xor(args[0], args[1])
        elif z3.is_false(expr):
            res = self.mgr.FALSE()
        elif z3.is_true(expr):
            res = self.mgr.TRUE()
        elif z3.is_gt(expr):
            res = self.mgr.GT(args[0], args[1])
        elif z3.is_ge(expr):
            res = self.mgr.GE(args[0], args[1])
        elif z3.is_lt(expr):
            res = self.mgr.LT(args[0], args[1])
        elif z3.is_le(expr):
            res = self.mgr.LE(args[0], args[1])
        elif z3.is_mul(expr):
            res = self.mgr.Times(args[0], args[1])
        elif z3.is_uminus(expr):
            tp = self._get_type(args[0])
            if tp.is_real_type():
                minus_one = self.mgr.Real(-1)
            else:
                assert tp.is_int_type()
                minus_one = self.mgr.Int(-1)
            res = self.mgr.Times(args[0], minus_one)
        elif z3.is_sub(expr):
            res = self.mgr.Minus(args[0], args[1])
        elif z3.is_not(expr):
            res = self.mgr.Not(args[0])
        elif z3.is_implies(expr):
            res = self.mgr.Implies(args[0], args[1])
        elif z3.is_quantifier(expr):
            raise NotImplementedError
        elif z3.is_const(expr):
            if z3.is_rational_value(expr):
                n = expr.numerator_as_long()
                d = expr.denominator_as_long()
                f = Fraction(n, d)
                res = self.mgr.Real(f)
            elif z3.is_int_value(expr):
                n = expr.as_long()
                res = self.mgr.Int(n)
            elif z3.is_bv_value(expr):
                n = expr.as_long()
                w = expr.size()
                res = self.mgr.BV(n, w)
            elif z3.is_as_array(expr):
                if model is None:
                    raise NotImplementedError("As-array expressions cannot be" \
                                              " handled as they are not " \
                                              "self-contained")
                else:
                    interp_decl = z3.get_as_array_func(expr)
                    interp = model[interp_decl]
                    default = self.back(interp.else_value(), model=model)
                    assign = {}
                    for i in xrange(interp.num_entries()):
                        e = interp.entry(i)
                        assert e.num_args() == 1
                        idx = self.back(e.arg_value(0), model=model)
                        val = self.back(e.value(), model=model)
                        assign[idx] = val
                    arr_type = self._z3_to_type(expr.sort())
                    res = self.mgr.Array(arr_type.index_type, default, assign)
            elif z3.is_algebraic_value(expr):
                # Algebraic value
                return self.mgr._Algebraic(Numeral(expr))
            else:
                # it must be a symbol
                res = self.mgr.get_symbol(str(expr))
        elif z3.is_ite(expr):
            res = self.mgr.Ite(args[0], args[1], args[2])
        elif z3.is_function(expr):
            res = self.mgr.Function(self.mgr.get_symbol(expr.decl().name()), args)
        elif z3.is_to_real(expr):
            res = self.mgr.ToReal(args[0])
        elif z3.is_bv_and(expr):
            res = self.mgr.BVAnd(args[0], args[1])
        elif z3.is_bv_or(expr):
            res = self.mgr.BVOr(args[0], args[1])
        elif z3.is_bv_xor(expr):
            res = self.mgr.BVXor(args[0], args[1])
        elif z3.is_bv_not(expr):
            res = self.mgr.BVNot(args[0])
        elif z3.is_bv_neg(expr):
            res = self.mgr.BVNeg(args[0])
        elif z3.is_bv_concat(expr):
            res = self.mgr.BVConcat(args[0], args[1])
        elif z3.is_bv_ult(expr):
            res = self.mgr.BVULT(args[0], args[1])
        elif z3.is_bv_uleq(expr):
            res = self.mgr.BVULE(args[0], args[1])
        elif z3.is_bv_slt(expr):
            res = self.mgr.BVSLT(args[0], args[1])
        elif z3.is_bv_sleq(expr):
            res = self.mgr.BVSLE(args[0], args[1])
        elif z3.is_bv_ugt(expr):
            res = self.mgr.BVUGT(args[0], args[1])
        elif z3.is_bv_ugeq(expr):
            res = self.mgr.BVUGE(args[0], args[1])
        elif z3.is_bv_sgt(expr):
            res = self.mgr.BVSGT(args[0], args[1])
        elif z3.is_bv_sgeq(expr):
            res = self.mgr.BVSGE(args[0], args[1])
        elif z3.is_bv_extract(expr):
            end = z3.get_payload(expr, 0)
            start = z3.get_payload(expr, 1)
            res = self.mgr.BVExtract(args[0], start, end)
        elif z3.is_bv_add(expr):
            res = self.mgr.BVAdd(args[0], args[1])
        elif z3.is_bv_mul(expr):
            res = self.mgr.BVMul(args[0], args[1])
        elif z3.is_bv_udiv(expr):
            res = self.mgr.BVUDiv(args[0], args[1])
        elif z3.is_bv_sdiv(expr):
            res = self.mgr.BVSDiv(args[0], args[1])
        elif z3.is_bv_urem(expr):
            res = self.mgr.BVURem(args[0], args[1])
        elif z3.is_bv_srem(expr):
            res = self.mgr.BVSRem(args[0], args[1])
        elif z3.is_bv_lshl(expr):
            res = self.mgr.BVLShl(args[0], args[1])
        elif z3.is_bv_lshr(expr):
            res = self.mgr.BVLShr(args[0], args[1])
        elif z3.is_bv_ashr(expr):
            res = self.mgr.BVAShr(args[0], args[1])
        elif z3.is_bv_sub(expr):
            res = self.mgr.BVSub(args[0], args[1])
        elif z3.is_bv_rol(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVRol(args[0], amount)
        elif z3.is_bv_ror(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVRor(args[0], amount)
        elif z3.is_bv_ext_rol(expr):
            amount = args[1].bv_unsigned_value()
            res = self.mgr.BVRol(args[0], amount)
        elif z3.is_bv_ext_ror(expr):
            amount = args[1].bv_unsigned_value()
            res = self.mgr.BVRor(args[0], amount)
        elif z3.is_bv_sext(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVSExt(args[0], amount)
        elif z3.is_bv_zext(expr):
            amount = z3.get_payload(expr, 0)
            res = self.mgr.BVZExt(args[0], amount)
        elif z3.is_array_select(expr):
            res = self.mgr.Select(args[0], args[1])
        elif z3.is_array_store(expr):
            res = self.mgr.Store(args[0], args[1], args[2])
        elif z3.is_const_array(expr):
            arr_ty = self._z3_to_type(expr.sort())
            k = args[0]
            res = self.mgr.Array(arr_ty.index_type, k)
        elif z3.is_power(expr):
            res = self.mgr.Pow(args[0], args[1])
        if res is None:
            raise ConvertExpressionError(message=("Unsupported expression: %s" %
                                                   str(expr)),
                                         expression=expr)
        return res
Пример #16
0
    def _back_single_term(self, expr, args, model=None):
        assert z3.is_expr(expr)

        if z3.is_quantifier(expr):
            raise NotImplementedError(
                "Quantified back conversion is currently not supported")

        assert not len(args) > 2 or \
            (z3.is_and(expr) or z3.is_or(expr) or
             z3.is_add(expr) or z3.is_mul(expr) or
             (len(args) == 3 and (z3.is_ite(expr) or z3.is_array_store(expr)))),\
            "Unexpected n-ary term: %s" % expr

        res = None
        try:
            decl = z3.Z3_get_app_decl(expr.ctx_ref(), expr.as_ast())
            kind = z3.Z3_get_decl_kind(expr.ctx.ref(), decl)
            # Try to get the back-conversion function for the given Kind
            fun = self._back_fun[kind]
            return fun(args, expr)
        except KeyError as ex:
            pass

        if z3.is_const(expr):
            # Const or Symbol
            if z3.is_rational_value(expr):
                n = expr.numerator_as_long()
                d = expr.denominator_as_long()
                f = Fraction(n, d)
                return self.mgr.Real(f)
            elif z3.is_int_value(expr):
                n = expr.as_long()
                return self.mgr.Int(n)
            elif z3.is_bv_value(expr):
                n = expr.as_long()
                w = expr.size()
                return self.mgr.BV(n, w)
            elif z3.is_as_array(expr):
                if model is None:
                    raise NotImplementedError("As-array expressions cannot be" \
                                              " handled as they are not " \
                                              "self-contained")
                else:
                    interp_decl = z3.get_as_array_func(expr)
                    interp = model[interp_decl]
                    default = self.back(interp.else_value(), model=model)
                    assign = {}
                    for i in xrange(interp.num_entries()):
                        e = interp.entry(i)
                        assert e.num_args() == 1
                        idx = self.back(e.arg_value(0), model=model)
                        val = self.back(e.value(), model=model)
                        assign[idx] = val
                    arr_type = self._z3_to_type(expr.sort())
                    return self.mgr.Array(arr_type.index_type, default, assign)
            elif z3.is_algebraic_value(expr):
                # Algebraic value
                return self.mgr._Algebraic(Numeral(expr))
            else:
                # it must be a symbol
                try:
                    return self.mgr.get_symbol(str(expr))
                except UndefinedSymbolError:
                    import warnings
                    symb_type = self._z3_to_type(expr.sort())
                    warnings.warn("Defining new symbol: %s" % str(expr))
                    return self.mgr.FreshSymbol(symb_type,
                                                template="__z3_%d")
        elif z3.is_function(expr):
            # This needs to be after we try to convert regular Symbols
            fsymbol = self.mgr.get_symbol(expr.decl().name())
            return self.mgr.Function(fsymbol, args)

        # If we reach this point, we did not manage to translate the expression
        raise ConvertExpressionError(message=("Unsupported expression: %s" %
                                              (str(expr))),
                                     expression=expr)
Пример #17
0
    def _back_single_term(self, expr, args, model=None):
        assert z3.is_expr(expr)

        if z3.is_quantifier(expr):
            raise NotImplementedError(
                "Quantified back conversion is currently not supported")

        assert not len(args) > 2 or \
            (z3.is_and(expr) or z3.is_or(expr) or
             z3.is_add(expr) or z3.is_mul(expr) or
             (len(args) == 3 and (z3.is_ite(expr) or z3.is_array_store(expr)))),\
            "Unexpected n-ary term: %s" % expr

        res = None
        try:
            decl = z3.Z3_get_app_decl(expr.ctx_ref(), expr.as_ast())
            kind = z3.Z3_get_decl_kind(expr.ctx.ref(), decl)
            # Try to get the back-conversion function for the given Kind
            fun = self._back_fun[kind]
            return fun(args, expr)
        except KeyError as ex:
            pass

        if z3.is_const(expr):
            # Const or Symbol
            if z3.is_rational_value(expr):
                n = expr.numerator_as_long()
                d = expr.denominator_as_long()
                f = Fraction(n, d)
                return self.mgr.Real(f)
            elif z3.is_int_value(expr):
                n = expr.as_long()
                return self.mgr.Int(n)
            elif z3.is_bv_value(expr):
                n = expr.as_long()
                w = expr.size()
                return self.mgr.BV(n, w)
            elif z3.is_as_array(expr):
                if model is None:
                    raise NotImplementedError("As-array expressions cannot be" \
                                              " handled as they are not " \
                                              "self-contained")
                else:
                    interp_decl = z3.get_as_array_func(expr)
                    interp = model[interp_decl]
                    default = self.back(interp.else_value(), model=model)
                    assign = {}
                    for i in xrange(interp.num_entries()):
                        e = interp.entry(i)
                        assert e.num_args() == 1
                        idx = self.back(e.arg_value(0), model=model)
                        val = self.back(e.value(), model=model)
                        assign[idx] = val
                    arr_type = self._z3_to_type(expr.sort())
                    return self.mgr.Array(arr_type.index_type, default, assign)
            elif z3.is_algebraic_value(expr):
                # Algebraic value
                return self.mgr._Algebraic(Numeral(expr))
            else:
                # it must be a symbol
                try:
                    return self.mgr.get_symbol(str(expr))
                except UndefinedSymbolError:
                    import warnings
                    symb_type = self._z3_to_type(expr.sort())
                    warnings.warn("Defining new symbol: %s" % str(expr))
                    return self.mgr.FreshSymbol(symb_type, template="__z3_%d")
        elif z3.is_function(expr):
            # This needs to be after we try to convert regular Symbols
            fsymbol = self.mgr.get_symbol(expr.decl().name())
            return self.mgr.Function(fsymbol, args)

        # If we reach this point, we did not manage to translate the expression
        raise ConvertExpressionError(message=("Unsupported expression: %s" %
                                              (str(expr))),
                                     expression=expr)
Пример #18
0
def translate2dimacs(z3_formula,
                     start_var,
                     output_filename,
                     append_to_file=False,
                     overlap_vars=0,
                     indep_set=0,
                     verbose=False):
    """Write a z3 formula to a DIMACS output format.

    Parameters:
    - start_var: Offset the auxiliary variables by start_var
    """
    seen_literals = {}

    cnf_clauses = []
    start = time.time()
    # Z3 expressions can be applications, quantifiers and bounded/free variables
    for expr in z3_formula:
        if z3.is_quantifier(expr):
            print('Expecting {} to be OR, got quantifier in CNF!'.format(expr))
            return
        if z3.is_or(expr):
            # for lit in expr.children():
            # or_clause += translate(start_var, lit, seen_literals)
            or_clause = ''.join([
                translate(start_var, lit, seen_literals)
                for lit in expr.children()
            ])
            cnf_clauses.append(or_clause)
        else:
            lit = translate(start_var, expr, seen_literals)
            if verbose:
                print('{} not OR. translated to {}'.format(expr, lit))
            cnf_clauses.append(lit)

    number_of_clauses = len(cnf_clauses)
    end = time.time()
    if verbose:
        print('SEEN LITERALS {}'.format(seen_literals))

    print('Iterating took {} sec'.format(end - start))

    if not append_to_file:
        with open(output_filename, 'w') as f:
            f.write('p cnf {} {}\n'.format(
                len(seen_literals) + start_var, number_of_clauses))
            if indep_set > 0:
                f.write('{}\n'.format(count_header(indep_set)))
            curr = 0
            prev = 0
            for curr, clause in enumerate(cnf_clauses):
                curr += 1
                # flush every 32K elements -- this 32k is an approx.
                if curr % 99991 == 0:
                    f.write('0\n'.join(cnf_clauses[prev:curr]))
                    f.write('0\n')
                    prev = curr
            #f.write('0\n'.join(cnf_clauses))
            f.write('0\n'.join(cnf_clauses[prev:curr]))
            f.write('0\n')
    else:
        (num_vars, num_clauses) = parse_dimacs_header(output_filename)
        with open(output_filename, 'r') as from_file:
            tmp_path = output_filename + '.tmp'
            with open(tmp_path, 'w') as tmp_file:
                number_of_clauses += num_clauses
                tmp_file.write('p cnf {} {}\n'.format(
                    num_vars + start_var + len(seen_literals) - overlap_vars,
                    number_of_clauses))

                if indep_set > 0:
                    tmp_file.write('{}\n'.format(count_header(indep_set)))

                line = from_file.readline()
                start = time.time()
                shutil.copyfileobj(from_file, tmp_file)
                end = time.time()
                logger.debug('shutil.copyfileobj took {} sec'.format(end -
                                                                     start))
                curr = 0
                prev = 0
                if len(cnf_clauses) < 99991:
                    tmp_file.write('0\n'.join(cnf_clauses))
                    tmp_file.write('0\n')
                else:
                    for curr, clause in enumerate(cnf_clauses):
                        curr += 1
                        # flush every 100K elements -- this 32k is an approx.
                        if curr % 99991 == 0:
                            tmp_file.write('0\n'.join(cnf_clauses[prev:curr]))
                            tmp_file.write('0\n')
                            prev = curr
                    tmp_file.write('0\n'.join(cnf_clauses[prev:curr]))
                    tmp_file.write('0\n')

                #tmp_file.write('0\n'.join(cnf_clauses))
            os.rename(tmp_path, output_filename)

    return len(seen_literals), number_of_clauses