org.sosy_lab.solver.z3.Z3UnsafeFormulaManager.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.solver.z3.Z3UnsafeFormulaManager.java

Source

/*
 *  CPAchecker is a tool for configurable software verification.
 *  This file is part of CPAchecker.
 *
 *  Copyright (C) 2007-2014  Dirk Beyer
 *  All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 *  CPAchecker web page:
 *    http://cpachecker.sosy-lab.org
 */
package org.sosy_lab.solver.z3;

import static com.google.common.base.Preconditions.checkArgument;
import static org.sosy_lab.solver.z3.Z3NativeApi.*;
import static org.sosy_lab.solver.z3.Z3NativeApiConstants.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.sosy_lab.solver.basicimpl.AbstractUnsafeFormulaManager;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.primitives.Longs;

class Z3UnsafeFormulaManager extends AbstractUnsafeFormulaManager<Long, Long, Long> {

    private final Set<Long> uifs = new HashSet<>(); // contains used declarations of UIFs
    private final long z3context;

    Z3UnsafeFormulaManager(Z3FormulaCreator pCreator) {
        super(pCreator);
        this.z3context = pCreator.getEnv();
    }

    private final static Collection<Integer> nonAtomicOpTypes = Sets.newHashSet(Z3_OP_AND, Z3_OP_OR, Z3_OP_IMPLIES,
            Z3_OP_ITE, Z3_OP_NOT);

    @Override
    public boolean isAtom(Long t) {
        int astKind = get_ast_kind(z3context, t);
        switch (astKind) {
        case Z3_APP_AST:
            long decl = get_app_decl(z3context, t);
            return !nonAtomicOpTypes.contains(get_decl_kind(z3context, decl));
        default:
            return true;
        }
    }

    @Override
    public int getArity(Long t) {
        return get_app_num_args(z3context, t);
    }

    @Override
    public Long getArg(Long t, int n) {
        return get_app_arg(z3context, t, n);
    }

    @Override
    public boolean isVariable(Long t) {
        if (isOP(z3context, t, Z3_OP_TRUE) || isOP(z3context, t, Z3_OP_FALSE)) {
            return false;
        }
        int astKind = get_ast_kind(z3context, t);
        return (astKind == Z3_VAR_AST) || ((astKind == Z3_APP_AST) && (getArity(t) == 0));
    }

    @Override
    protected boolean isFreeVariable(Long pT) {
        if (isOP(z3context, pT, Z3_OP_TRUE) || isOP(z3context, pT, Z3_OP_FALSE)) {
            return false;
        }

        int astKind = get_ast_kind(z3context, pT);
        return ((astKind == Z3_APP_AST) && (getArity(pT) == 0));
    }

    @Override
    protected boolean isBoundVariable(Long pT) {
        int astKind = get_ast_kind(z3context, pT);
        return (astKind == Z3_VAR_AST);
    }

    @Override
    public boolean isUF(Long t) {
        return is_app(z3context, t) && uifs.contains(get_app_decl(z3context, t));
    }

    @Override
    public String getName(Long t) {
        int astKind = get_ast_kind(z3context, t);
        if (astKind == Z3_VAR_AST) {
            return "?" + get_index_value(z3context, t);
        } else {
            long funcDecl = get_app_decl(z3context, t);
            long symbol = get_decl_name(z3context, funcDecl);
            switch (get_symbol_kind(z3context, symbol)) {
            case Z3_INT_SYMBOL:
                return Integer.toString(get_symbol_int(z3context, symbol));
            case Z3_STRING_SYMBOL:
                return get_symbol_string(z3context, symbol);
            default:
                throw new AssertionError();
            }
        }
    }

    @Override
    public Long replaceArgs(Long t, List<Long> newArgs) {
        Preconditions.checkState(get_app_num_args(z3context, t) == newArgs.size());
        long[] newParams = Longs.toArray(newArgs);
        // TODO check equality of sort of each oldArg and newArg
        long funcDecl = get_app_decl(z3context, t);
        return mk_app(z3context, funcDecl, newParams);
    }

    @Override
    public Long replaceArgsAndName(Long t, String pNewName, List<Long> newArgs) {
        if (isVariable(t)) {
            checkArgument(newArgs.isEmpty());
            long sort = get_sort(z3context, t);
            return getFormulaCreator().makeVariable(sort, pNewName);

        } else if (isUF(t)) {
            int n = get_app_num_args(z3context, t);
            long[] sorts = new long[n];
            for (int i = 0; i < sorts.length; i++) {
                long arg = get_app_arg(z3context, t, i);
                inc_ref(z3context, arg);
                sorts[i] = get_sort(z3context, arg);
                inc_ref(z3context, sorts[i]);
                dec_ref(z3context, arg);
            }
            long symbol = mk_string_symbol(z3context, pNewName);
            long retSort = get_sort(z3context, t);
            long newFunc = mk_func_decl(z3context, symbol, sorts, retSort);
            inc_ref(z3context, newFunc);

            //      creator.getSmtLogger().logDeclaration(newFunc, retSort, sorts); // TODO necessary???

            long uif = createUIFCallImpl(newFunc, Longs.toArray(newArgs));

            for (int i = 0; i < sorts.length; i++) {
                dec_ref(z3context, sorts[i]);
            }
            return uif;

        } else {
            throw new IllegalArgumentException(
                    "Cannot replace name '" + pNewName + "' in term '" + ast_to_string(z3context, t) + "'.");
        }
    }

    @Override
    protected List<Long> splitNumeralEqualityIfPossible(Long pF) {
        if (isOP(z3context, pF, Z3_OP_EQ) && get_app_num_args(z3context, pF) == 2) {
            long arg0 = getArg(pF, 0);
            inc_ref(z3context, arg0);
            long arg1 = getArg(pF, 1);
            inc_ref(z3context, arg1);

            try {
                long sortKind = get_sort_kind(z3context, get_sort(z3context, arg0));
                assert sortKind == get_sort_kind(z3context, get_sort(z3context, arg1));
                if (sortKind == Z3_BV_SORT) {

                    long out1 = mk_bvule(z3context, arg0, arg1);
                    inc_ref(z3context, out1);
                    long out2 = mk_bvuge(z3context, arg0, arg1);
                    inc_ref(z3context, out2);

                    return ImmutableList.of(out1, out2);
                } else if (sortKind == Z3_INT_SORT || sortKind == Z3_REAL_SORT) {

                    long out1 = mk_le(z3context, arg0, arg1);
                    inc_ref(z3context, out1);
                    long out2 = mk_ge(z3context, arg0, arg1);
                    inc_ref(z3context, out2);
                    return ImmutableList.of(out1, out2);
                }
            } finally {
                dec_ref(z3context, arg0);
                dec_ref(z3context, arg1);
            }
        }
        return ImmutableList.of(pF);
    }

    public long createUIFCallImpl(long pNewFunc, long[] args) {
        long ufc = mk_app(z3context, pNewFunc, args);
        uifs.add(pNewFunc);
        return ufc;
    }

    @Override
    public boolean isNumber(Long t) {
        return is_numeral_ast(z3context, t);
    }

    @Override
    protected Long substitute(Long t, List<Long> changeFrom, List<Long> changeTo) {
        int size = changeFrom.size();
        Preconditions.checkState(size == changeTo.size());
        return Z3NativeApi.substitute(z3context, t, size, Longs.toArray(changeFrom), Longs.toArray(changeTo));
    }

    @Override
    protected Long simplify(Long pF) {
        return Z3NativeApi.simplify(z3context, pF);
    }

    @Override
    protected boolean isQuantification(Long pT) {
        return Z3_QUANTIFIER_AST == get_ast_kind(z3context, pT);
    }

    @Override
    protected Long getQuantifiedBody(Long pT) {
        return get_quantifier_body(z3context, pT);
    }

    @Override
    protected Long replaceQuantifiedBody(Long pF, Long pBody) {
        boolean isForall = is_quantifier_forall(z3context, pF);
        int boundCount = get_quantifier_num_bound(z3context, pF);
        ArrayList<Long> boundVars = Lists.newArrayList();

        for (int b = 0; b < boundCount; b++) {
            long varName = get_quantifier_bound_name(z3context, pF, b);
            long varSort = get_quantifier_bound_sort(z3context, pF, b);
            long var = mk_const(z3context, varName, varSort);
            boundVars.add(var);
            inc_ref(z3context, var);
        }

        if (isForall) {
            return Z3NativeApi.mk_forall_const(z3context, 0, boundVars.size(), Longs.toArray(boundVars), 0,
                    Longs.toArray(Collections.<Long>emptyList()), pBody);
        } else {
            return Z3NativeApi.mk_exists_const(z3context, 0, boundVars.size(), Longs.toArray(boundVars), 0,
                    Longs.toArray(Collections.<Long>emptyList()), pBody);

        }
    }

}