edu.buaa.satla.analysis.core.counterexample.Model.java Source code

Java tutorial

Introduction

Here is the source code for edu.buaa.satla.analysis.core.counterexample.Model.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 edu.buaa.satla.analysis.core.counterexample;

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

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

import org.sosy_lab.common.Appender;
import org.sosy_lab.common.Appenders;
import org.sosy_lab.cpachecker.cfa.model.CFAEdge;
import org.sosy_lab.cpachecker.cpa.arg.ARGPath;
import org.sosy_lab.cpachecker.cpa.arg.ARGState;

import com.google.common.base.Joiner;
import com.google.common.base.Joiner.MapJoiner;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;

import edu.buaa.satla.analysis.core.counterexample.Model.AssignableTerm;

/**
 * This class represents an assignment of concrete values to program variables
 * along a path. Each variable can have several assignments with different
 * SSA indices if it gets re-assigned along the path.
 *
 * The value of each variable can be an arbitrary object, but usually,
 * this is a {@link Number}.
 */
public class Model extends ForwardingMap<AssignableTerm, Object> implements Appender {

    public static enum TermType {
        Boolean, Uninterpreted, Integer, Real, FloatingPoint, Bitvector;
    }

    public static interface AssignableTerm {
        public TermType getType();

        public String getName();
    }

    public static class Constant implements AssignableTerm {

        protected final String name;
        protected final TermType type;

        public Constant(final String name, final TermType type) {
            this.name = name;
            this.type = type;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public TermType getType() {
            return type;
        }

        @Override
        public String toString() {
            return name + " : " + type;
        }

        @Override
        public int hashCode() {
            return 324 + name.hashCode() + type.hashCode();
        }

        @Override
        public boolean equals(final Object other) {
            if (this == other) {
                return true;
            }

            if (other == null) {
                return false;
            }

            if (!getClass().equals(other.getClass())) {
                return false;
            }

            final Constant otherConstant = (Constant) other;

            return name.equals(otherConstant.name) && type.equals(otherConstant.type);
        }

    }

    public static class Variable extends Constant implements AssignableTerm {

        public Variable(final String name, final int ssaIndex, final TermType type) {
            super(name, type);
            this.ssaIndex = ssaIndex;
        }

        public int getSSAIndex() {
            return ssaIndex;
        }

        @Override
        public String toString() {
            return name + "@" + ssaIndex + " : " + type;
        }

        @Override
        public int hashCode() {
            return 324 + name.hashCode() + ssaIndex + type.hashCode();
        }

        @Override
        public boolean equals(final Object other) {
            if (this == other) {
                return true;
            }

            if (other == null) {
                return false;
            }

            if (!getClass().equals(other.getClass())) {
                return false;
            }

            Variable otherVariable = (Variable) other;

            return name.equals(otherVariable.name) && (ssaIndex == otherVariable.ssaIndex)
                    && type.equals(otherVariable.type);
        }

        private final int ssaIndex;
    }

    /**
     * A function call can have a concrete return value.
     * TODO: Describe why handling pointers/references is not needed in this case
     */
    public static class Function implements AssignableTerm {

        private final String mName;
        private final TermType mReturnType;
        private final List<Object> mArguments;
        private int mHashCode;

        public Function(String pName, TermType pReturnType, Object[] pArguments) {
            mName = pName;
            mReturnType = pReturnType;
            mArguments = ImmutableList.copyOf(pArguments);

            mHashCode = 32453 + mName.hashCode() + mReturnType.hashCode();

            for (Object lValue : mArguments) {
                mHashCode += lValue.hashCode();
            }
        }

        @Override
        public String getName() {
            return mName;
        }

        @Override
        public TermType getType() {
            return mReturnType;
        }

        public int getArity() {
            return mArguments.size();
        }

        public Object getArgument(int lArgumentIndex) {
            return mArguments.get(lArgumentIndex);
        }

        @Override
        public String toString() {
            return mName + "(" + Joiner.on(',').join(mArguments) + ") : " + mReturnType;
        }

        @Override
        public int hashCode() {
            return mHashCode;
        }

        @Override
        public boolean equals(Object pOther) {
            if (this == pOther) {
                return true;
            }

            if (pOther == null) {
                return false;
            }

            if (!getClass().equals(pOther.getClass())) {
                return false;
            }

            Function lFunction = (Function) pOther;

            return (lFunction.mName.equals(mName) && lFunction.mReturnType.equals(mReturnType)
                    && lFunction.mArguments.equals(mArguments));
        }
    }

    private final Map<AssignableTerm, Object> mModel;

    private final CFAPathWithAssignments assignments;
    private final Multimap<CFAEdge, AssignableTerm> assignableTermsPerCFAEdge;

    @Override
    protected Map<AssignableTerm, Object> delegate() {
        return mModel;
    }

    public static Model empty() {
        return new Model();
    }

    private Model() {
        mModel = ImmutableMap.of();
        assignments = new CFAPathWithAssignments();
        assignableTermsPerCFAEdge = ImmutableListMultimap.of();
    }

    public Model(Map<AssignableTerm, Object> content) {
        mModel = ImmutableMap.copyOf(content);
        assignments = new CFAPathWithAssignments();
        assignableTermsPerCFAEdge = ImmutableListMultimap.of();
    }

    public Model(Map<AssignableTerm, Object> content, CFAPathWithAssignments pAssignments) {
        mModel = ImmutableMap.copyOf(content);
        assignments = pAssignments;
        assignableTermsPerCFAEdge = ImmutableListMultimap.of();
    }

    public Model(Map<AssignableTerm, Object> content, CFAPathWithAssignments pAssignments,
            Multimap<CFAEdge, AssignableTerm> pAssignableTermsPerCFAEdge) {
        mModel = ImmutableMap.copyOf(content);
        assignments = pAssignments;
        assignableTermsPerCFAEdge = pAssignableTermsPerCFAEdge;
    }

    /**
     * Return a new model that is equal to the current one,
     * but additionally has information about when each variable was assigned.
     * @see Model#getAssignedTermsPerEdge()
     */
    public Model withAssignmentInformation(CFAPathWithAssignments pAssignments) {
        checkState(assignments.isEmpty());
        return new Model(mModel, pAssignments);
    }

    /**
     * Return a new model that is equal to the current one,
     * but additionally has information about when each variable was assigned,
     * and which
     * @see Model#getAssignedTermsPerEdge()
     */
    public Model withAssignmentInformation(CFAPathWithAssignments pAssignments,
            Multimap<CFAEdge, AssignableTerm> pAssignableTermsPerCFAEdge) {
        checkState(assignments.isEmpty());
        return new Model(mModel, pAssignments);
    }

    /**
     * Return a path that indicates which variables where assigned which values at
     * what edge. Note that not every value for every variable is available.
     */
    @Nullable
    public CFAPathWithAssignments getCFAPathWithAssignments() {
        return assignments;
    }

    /**
     * Return a path that indicates which terms were assigned at which edge.
     * Note that it is not guaranteed that this is information is present for
     * all terms, thus <code>this.getAssignedTermsPerEdge().getAllAssignedTerms()</code> may
     * be smaller than <code>this.keySet()</code> (but not larger).
     */
    public Multimap<CFAEdge, AssignableTerm> getAssignedTermsPerEdge() {
        return assignableTermsPerCFAEdge;
    }

    /**
     * Returns a collection of {@link AssignableTerm}} terms that were assigned a the given
     * {@link CFAEdge} edge.
     *
     * @param pEdge All terms that were assigned at this edge are returned-
     * @return A collection of terms assigned at the given edge.
     */
    public Collection<AssignableTerm> getAllAssignedTerms(CFAEdge pEdge) {
        return assignableTermsPerCFAEdge.get(pEdge);
    }

    @Nullable
    public Map<ARGState, CFAEdgeWithAssignments> getExactVariableValues(ARGPath pPath) {

        if (assignments.isEmpty()) {
            return null;
        }

        return assignments.getExactVariableValues(pPath);
    }

    @Nullable
    public CFAPathWithAssignments getExactVariableValuePath(List<CFAEdge> pPath) {

        if (assignments.isEmpty()) {
            return null;
        }

        return assignments.getExactVariableValues(pPath);
    }

    private static final MapJoiner joiner = Joiner.on(System.lineSeparator()).withKeyValueSeparator(": ");

    @Override
    public void appendTo(Appendable output) throws IOException {
        Map<AssignableTerm, Object> sorted = ImmutableSortedMap.copyOf(mModel, Ordering.usingToString());
        joiner.appendTo(output, sorted);
    }

    @Override
    public String toString() {
        return Appenders.toString(this);
    }
}