org.sosy_lab.cpachecker.util.predicates.z3.Z3InterpolatingProver.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.util.predicates.z3.Z3InterpolatingProver.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.cpachecker.util.predicates.z3;

import static org.sosy_lab.cpachecker.util.predicates.z3.Z3NativeApi.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.sosy_lab.cpachecker.core.counterexample.Model;
import org.sosy_lab.cpachecker.util.predicates.interfaces.BooleanFormula;
import org.sosy_lab.cpachecker.util.predicates.interfaces.InterpolatingProverEnvironment;
import org.sosy_lab.cpachecker.util.predicates.z3.Z3NativeApi.PointerToLong;
import org.sosy_lab.cpachecker.util.predicates.z3.Z3NativeApiConstants.Z3_LBOOL;

import com.google.common.base.Preconditions;
import com.google.common.primitives.Longs;

class Z3InterpolatingProver implements InterpolatingProverEnvironment<Long> {

    private final Z3FormulaManager mgr;
    private long z3context;
    private long z3solver;
    private final Z3SmtLogger smtLogger;
    private int level = 0;
    private List<Long> assertedFormulas = new LinkedList<>();

    Z3InterpolatingProver(Z3FormulaManager mgr) {
        this.mgr = mgr;
        this.z3context = mgr.getEnvironment();
        this.z3solver = mk_solver(z3context);
        solver_inc_ref(z3context, z3solver);
        this.smtLogger = mgr.getSmtLogger();
    }

    @Override
    public Long push(BooleanFormula f) {
        level++;

        long e = Z3FormulaManager.getZ3Expr(f);
        solver_push(z3context, z3solver);

        if (mgr.simplifyFormulas) {
            e = simplify(z3context, e);
            inc_ref(z3context, e);
        }

        solver_assert(z3context, z3solver, e);
        assertedFormulas.add(e);

        smtLogger.logPush(1);
        smtLogger.logInterpolationAssert(e);

        return e;
    }

    @Override
    public void pop() {
        level--;

        assertedFormulas.remove(assertedFormulas.size() - 1); // remove last
        solver_pop(z3context, z3solver, 1);

        smtLogger.logPop(1);
    }

    @Override
    public boolean isUnsat() {
        Preconditions.checkState(z3context != 0);
        Preconditions.checkState(z3solver != 0);
        int result = solver_check(z3context, z3solver);

        smtLogger.logCheck();

        Preconditions.checkState(result != Z3_LBOOL.Z3_L_UNDEF.status);
        return result == Z3_LBOOL.Z3_L_FALSE.status;
    }

    @Override
    public BooleanFormula getInterpolant(List<Long> formulasOfA) {

        // calc difference: formulasOfB := assertedFormulas - formulasOfA
        List<Long> formulasOfB = new ArrayList<>();
        for (long af : assertedFormulas) {
            if (!formulasOfA.contains(af)) {
                formulasOfB.add(af);
            }
        }

        // build 2 groups:  (and A1 A2 A3...) , (and B1 B2 B3...)
        assert formulasOfA.size() != 0;
        assert formulasOfB.size() != 0;
        long[] groupA = Longs.toArray(formulasOfA);
        long[] groupB = Longs.toArray(formulasOfB);
        long fA = mk_and(z3context, groupA);
        inc_ref(z3context, fA);
        long fB = mk_and(z3context, groupB);
        inc_ref(z3context, fB);

        // 2 groups -> 1 interpolant
        long[] itps = new long[1];
        itps[0] = 1; // initialize with value != 0

        PointerToLong labels = new PointerToLong();
        PointerToLong model = new PointerToLong();

        // next lines are not needed due to a direct implementation in the C-code.
        //    long options = mk_params(z3context);
        //    inc_ref(z3context, options);
        //    int[] parents = new int[0]; // this line is not working
        long[] theory = new long[0]; // do we need a theory?

        long[] interpolationFormulas = new long[] { fA, fB };

        smtLogger.logInterpolation(formulasOfA, formulasOfB, fA, fB);

        // get interpolant of groups
        int isSat = interpolateSeq(z3context, interpolationFormulas, itps, model, labels, 0, theory);

        assert isSat != Z3_LBOOL.Z3_L_TRUE.status;
        BooleanFormula f = mgr.encapsulateBooleanFormula(itps[0]);

        // cleanup
        dec_ref(z3context, fA);
        dec_ref(z3context, fB);

        return f;
    }

    @Override
    public List<BooleanFormula> getSeqInterpolants(List<Set<Long>> partitionedFormulas) {

        final long[] interpolationFormulas = new long[partitionedFormulas.size()];

        for (int i = 0; i < interpolationFormulas.length; i++) {
            long partition = mk_and(z3context, Longs.toArray(partitionedFormulas.get(i)));
            inc_ref(z3context, partition);
            interpolationFormulas[i] = partition;
        }

        // n groups -> n-1 interpolants
        final long[] itps = new long[interpolationFormulas.length - 1];
        Arrays.fill(itps, 1); // initialize with value != 0

        PointerToLong labels = new PointerToLong();
        PointerToLong model = new PointerToLong();

        // next lines are not needed due to a direct implementation in the C-code.
        //    long options = mk_params(z3context);
        //    inc_ref(z3context, options);
        //    int[] parents = new int[0]; // this line is not working
        long[] theory = new long[0]; // do we need a theory?

        smtLogger.logSeqInterpolation(interpolationFormulas);

        // get interpolant of groups
        int isSat = interpolateSeq(z3context, interpolationFormulas, itps, model, labels, 0, theory);

        assert isSat != Z3_LBOOL.Z3_L_TRUE.status;

        final List<BooleanFormula> result = new ArrayList<>();
        for (long itp : itps) {
            result.add(mgr.encapsulateBooleanFormula(itp));
        }

        // cleanup
        for (long partition : interpolationFormulas) {
            dec_ref(z3context, partition);
        }

        return result;
    }

    @Override
    public Model getModel() {
        return Z3Model.createZ3Model(mgr, z3context, z3solver);
    }

    @Override
    public void close() {
        Preconditions.checkState(z3context != 0);
        Preconditions.checkState(z3solver != 0);

        while (level > 0) { // TODO do we need this?
            pop();
        }

        assertedFormulas = null;
        //TODO solver_reset(z3context, z3solver);
        solver_dec_ref(z3context, z3solver);
        z3context = 0;
        z3solver = 0;
    }
}