org.sosy_lab.cpachecker.cpa.constraints.refiner.precision.ConstraintBasedConstraintsPrecision.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.cpa.constraints.refiner.precision.ConstraintBasedConstraintsPrecision.java

Source

/*
 * CPAchecker is a tool for configurable software verification.
 *  This file is part of CPAchecker.
 *
 *  Copyright (C) 2007-2015  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.cpa.constraints.refiner.precision;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

import org.sosy_lab.cpachecker.cfa.model.CFANode;
import org.sosy_lab.cpachecker.cpa.constraints.constraint.Constraint;
import org.sosy_lab.cpachecker.cpa.value.symbolic.util.SymbolicValues;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

/**
 * ConstraintsPrecision that uses the code constraints represent.
 *
 * <p>Example:
 * A ConstraintBasedConstraintsPrecision contains for location <code>N12</code> the precision
 * <code>'a > 5'</code>. The ConstraintsState to adjust at this location is
 * <code>'s1(a) > 5, s3(b) > 5'</code>.
 * After precision adjustment, the ConstraintsState only consists of <code>'s1(a) > 5'</code>.
 * </p>
 */
class ConstraintBasedConstraintsPrecision implements ConstraintsPrecision {

    private final static ConstraintBasedConstraintsPrecision EMPTY = new ConstraintBasedConstraintsPrecision();

    private Multimap<CFANode, Constraint> trackedLocally;
    private Multimap<String, Constraint> trackedInFunction;
    private Set<Constraint> trackedGlobally;

    public static ConstraintsPrecision getEmptyPrecision() {
        return EMPTY;
    }

    /**
     * Creates a new <code>ConstraintBasedConstraintsPrecision</code> with the given constraints as precision.
     */
    private ConstraintBasedConstraintsPrecision(final ConstraintBasedConstraintsPrecision pPrecision) {
        checkNotNull(pPrecision);

        trackedLocally = pPrecision.trackedLocally;
        trackedInFunction = pPrecision.trackedInFunction;
        trackedGlobally = pPrecision.trackedGlobally;
    }

    private ConstraintBasedConstraintsPrecision(final Multimap<CFANode, Constraint> pTrackedLocally,
            final Multimap<String, Constraint> pTrackedInFunction, final Set<Constraint> pTrackedGlobally) {
        trackedLocally = pTrackedLocally;
        trackedInFunction = pTrackedInFunction;
        trackedGlobally = pTrackedGlobally;
    }

    private ConstraintBasedConstraintsPrecision() {
        trackedLocally = HashMultimap.create();
        trackedInFunction = HashMultimap.create();
        trackedGlobally = new HashSet<>();
    }

    /**
     * Returns whether the given <code>Constraint</code> is tracked by this precision.
     */
    @Override
    public boolean isTracked(final Constraint pConstraint, final CFANode pLocation) {
        for (Constraint c : trackedLocally.get(pLocation)) {
            if (SymbolicValues.representSameCCodeExpression(c, pConstraint)) {
                return true;
            }
        }

        for (Constraint c : trackedInFunction.get(pLocation.getFunctionName())) {
            if (SymbolicValues.representSameCCodeExpression(c, pConstraint)) {
                return true;
            }
        }

        for (Constraint c : trackedGlobally) {
            if (SymbolicValues.representSameCCodeExpression(c, pConstraint)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Joins this precision with the given one.
     * The join of two precisions is their union.
     *
     * @param pOther the precision to join with this precision
     * @return the join of both precisions
     */
    @Override
    public ConstraintBasedConstraintsPrecision join(final ConstraintsPrecision pOther) {
        assert pOther instanceof ConstraintBasedConstraintsPrecision;

        ConstraintBasedConstraintsPrecision other = (ConstraintBasedConstraintsPrecision) pOther;
        Multimap<CFANode, Constraint> joinedLocal = HashMultimap.create(trackedLocally);
        Multimap<String, Constraint> joinedFunctionwise = HashMultimap.create(trackedInFunction);
        Set<Constraint> joinedGlobal = new HashSet<>(trackedGlobally);

        addNewLocalConstraints(joinedLocal, other.trackedLocally);
        addNewFunctionConstraints(joinedFunctionwise, other.trackedInFunction);
        addNewGlobalConstraints(joinedGlobal, other.trackedGlobally);

        return new ConstraintBasedConstraintsPrecision(joinedLocal, joinedFunctionwise, joinedGlobal);
    }

    private void addNewLocalConstraints(Multimap<CFANode, Constraint> pMapToAddTo,
            Multimap<CFANode, Constraint> pNewConstraints) {
        for (Entry<CFANode, Constraint> entry : pNewConstraints.entries()) {
            CFANode loc = entry.getKey();
            Constraint constraint = entry.getValue();

            if (!constraintWithSameMeaningExists(loc, constraint, pMapToAddTo)) {
                pMapToAddTo.put(loc, constraint);
            }
        }
    }

    private void addNewFunctionConstraints(Multimap<String, Constraint> pMapToAddTo,
            Multimap<String, Constraint> pNewConstraints) {
        for (Entry<String, Constraint> entry : pNewConstraints.entries()) {
            String function = entry.getKey();
            Constraint constraint = entry.getValue();

            if (!constraintWithSameMeaningExists(function, constraint, pMapToAddTo)) {
                pMapToAddTo.put(function, constraint);
            }
        }
    }

    private void addNewGlobalConstraints(Set<Constraint> pSetToAddTo, Set<Constraint> pNewConstraints) {
        for (Constraint c : pNewConstraints) {
            if (!constraintWithSameMeaningExists(c, pNewConstraints)) {
                pSetToAddTo.add(c);
            }
        }
    }

    private boolean constraintWithSameMeaningExists(final CFANode pLoc, final Constraint pConstraint,
            final Multimap<CFANode, Constraint> pTrackedConstraints) {

        if (pTrackedConstraints.containsKey(pLoc)) {
            final Collection<Constraint> constraintsOnLocation = pTrackedConstraints.get(pLoc);

            for (Constraint c : constraintsOnLocation) {
                if (SymbolicValues.representSameCCodeExpression(c, pConstraint)) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean constraintWithSameMeaningExists(final String pFunctionName, final Constraint pConstraint,
            final Multimap<String, Constraint> pTrackedConstraints) {

        if (pTrackedConstraints.containsKey(pFunctionName)) {
            final Collection<Constraint> constraintsOnLocation = pTrackedConstraints.get(pFunctionName);

            for (Constraint c : constraintsOnLocation) {
                if (SymbolicValues.representSameCCodeExpression(c, pConstraint)) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean constraintWithSameMeaningExists(final Constraint pConstraint,
            final Set<Constraint> pTrackedConstraints) {

        for (Constraint c : pTrackedConstraints) {
            if (SymbolicValues.representSameCCodeExpression(c, pConstraint)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public ConstraintBasedConstraintsPrecision withIncrement(final Increment pIncrement) {
        ConstraintBasedConstraintsPrecision newPrecision = new ConstraintBasedConstraintsPrecision(this);

        newPrecision.trackedGlobally.addAll(pIncrement.getTrackedGlobally());
        newPrecision.trackedInFunction.putAll(pIncrement.getTrackedInFunction());
        newPrecision.trackedLocally.putAll(pIncrement.getTrackedLocally());

        return newPrecision;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        ConstraintBasedConstraintsPrecision that = (ConstraintBasedConstraintsPrecision) o;

        return Objects.equals(trackedLocally, that.trackedLocally);
    }

    @Override
    public int hashCode() {
        return Objects.hash(trackedLocally);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("ConstraintBasedConstraintsPrecision[");

        sb.append("\nLocally tracked: {");
        if (!trackedLocally.keySet().isEmpty()) {
            List<CFANode> nodes = new ArrayList<>(trackedLocally.keySet());
            Collections.sort(nodes); // we always want the same node order

            sb.append("\n");
            for (CFANode n : nodes) {
                sb.append("\t").append(n).append(" -> ");

                // unfortunately, constraints aren't comparable, so we won't have a deterministic order.
                for (Constraint c : trackedLocally.get(n)) {
                    sb.append(c.getRepresentation()).append(", ");
                }

                sb.append("\n");
            }
        }
        sb.append("} -> size: ").append(trackedLocally.size());

        sb.append("\nFunctionwise tracked: {");
        if (!trackedInFunction.keySet().isEmpty()) {
            List<String> functions = new ArrayList<>(trackedInFunction.keySet());
            Collections.sort(functions); // we always want the same function order

            sb.append("\n");
            for (String f : functions) {
                sb.append("\t").append(f).append(" -> ");

                for (Constraint c : trackedInFunction.get(f)) {
                    sb.append(c.getRepresentation()).append(", ");
                }

                sb.append("\n");
            }
        }
        sb.append("} -> size: ").append(trackedInFunction.size());

        sb.append("\nGlobally tracked: {");
        for (Constraint c : trackedGlobally) {
            sb.append(c).append(", ");
        }
        sb.append("} -> size: ").append(trackedGlobally.size());

        return sb.toString();
    }

}