org.sosy_lab.cpachecker.util.AbstractStates.java Source code

Java tutorial

Introduction

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

import static com.google.common.base.Predicates.*;
import static com.google.common.collect.FluentIterable.from;

import java.util.Set;

import org.sosy_lab.cpachecker.cfa.model.CFANode;
import org.sosy_lab.cpachecker.core.defaults.AbstractSingleWrapperState;
import org.sosy_lab.cpachecker.core.interfaces.AbstractState;
import org.sosy_lab.cpachecker.core.interfaces.AbstractStateWithLocation;
import org.sosy_lab.cpachecker.core.interfaces.AbstractWrapperState;
import org.sosy_lab.cpachecker.core.interfaces.FormulaReportingState;
import org.sosy_lab.cpachecker.core.interfaces.Targetable;
import org.sosy_lab.cpachecker.core.reachedset.LocationMappedReachedSet;
import org.sosy_lab.cpachecker.util.predicates.interfaces.BooleanFormula;
import org.sosy_lab.cpachecker.util.predicates.interfaces.BooleanFormulaManager;
import org.sosy_lab.cpachecker.util.predicates.interfaces.view.FormulaManagerView;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.TreeTraverser;

/**
 * Helper class that provides several useful methods for handling AbstractStates.
 */
public final class AbstractStates {

    private AbstractStates() {
    }

    /**
     * Retrieve one of the wrapped abstract states by type. If the hierarchy of
     * (wrapped) abstract states has several levels, this method searches through
     * them recursively.
     *
     * The type does not need to match exactly, the returned state has just to
     * be a sub-type of the type passed as argument.
     *
     * If you want to get all wrapped states with this type,
     * use <code>asIterable(pState).filter(pType)</code>.
     *
     * @param <T> The type of the wrapped state.
     * @param pState An abstract state
     * @param pType The class object of the type of the wrapped state.
     * @return An instance of an state with type T or null if there is none.
     */
    public static <T extends AbstractState> T extractStateByType(AbstractState pState, Class<T> pType) {
        if (pType.isInstance(pState)) {
            return pType.cast(pState);

        } else if (pState instanceof AbstractSingleWrapperState) {
            AbstractState wrapped = ((AbstractSingleWrapperState) pState).getWrappedState();
            return extractStateByType(wrapped, pType);

        } else if (pState instanceof AbstractWrapperState) {
            for (AbstractState wrapped : ((AbstractWrapperState) pState).getWrappedStates()) {
                T result = extractStateByType(wrapped, pType);
                if (result != null) {
                    return result;
                }
            }
        }

        return null;
    }

    /**
     * Applies {@link #extractStateByType(AbstractState, Class)} to all states
     * of a given {@link Iterable}.
     * There is one state in the output for every state in the input
     * that has a wrapped state with a matching type, in the same order.
     * Input states without a matching wrapped state are silently ignored.
     *
     * If you want to get all wrapped states with the given type,
     * even if a single state in the input has several of them,
     * use <code>asFlatIterable(states).filter(pType)</code>.   *
     *
     * @param states an <code>Iterable</code> over all the states
     *        <code>extractStateByType(AbstractState, Class)</code>
     *        should be applied on
     * @param pType the type to use in each call of
     *        <code>extractStateByType(AbstractState, Class)</code>
     *
     * @return an <code>Iterable</code> over all the returned states
     *         without <code>null</code> values
     */
    public static <T extends AbstractState> FluentIterable<T> projectToType(Iterable<AbstractState> states,
            Class<T> pType) {
        return from(states).transform(toState(pType)).filter(notNull());
    }

    public static CFANode extractLocation(AbstractState pState) {
        AbstractStateWithLocation e = extractStateByType(pState, AbstractStateWithLocation.class);
        return e == null ? null : e.getLocationNode();
    }

    public static final Function<AbstractState, CFANode> EXTRACT_LOCATION = new Function<AbstractState, CFANode>() {
        @Override
        public CFANode apply(AbstractState pArg0) {
            return extractLocation(pArg0);
        }
    };

    public static Iterable<AbstractState> filterLocation(Iterable<AbstractState> pStates, CFANode pLoc) {
        if (pStates instanceof LocationMappedReachedSet) {
            // only do this for LocationMappedReachedSet, not for all ReachedSet,
            // because this method is imprecise for the rest
            return ((LocationMappedReachedSet) pStates).getReached(pLoc);
        }

        Predicate<AbstractState> statesWithRightLocation = Predicates.compose(equalTo(pLoc), EXTRACT_LOCATION);
        return FluentIterable.from(pStates).filter(statesWithRightLocation);
    }

    public static FluentIterable<AbstractState> filterLocations(Iterable<AbstractState> pStates,
            Set<CFANode> pLocs) {
        if (pStates instanceof LocationMappedReachedSet) {
            // only do this for LocationMappedReachedSet, not for all ReachedSet,
            // because this method is imprecise for the rest
            final LocationMappedReachedSet states = (LocationMappedReachedSet) pStates;
            return from(pLocs).transformAndConcat(new Function<CFANode, Iterable<AbstractState>>() {
                @Override
                public Iterable<AbstractState> apply(CFANode location) {
                    return states.getReached(location);
                }
            });
        }

        Predicate<AbstractState> statesWithRightLocation = Predicates.compose(in(pLocs), EXTRACT_LOCATION);
        return from(pStates).filter(statesWithRightLocation);
    }

    public static boolean isTargetState(AbstractState as) {
        return (as instanceof Targetable) && ((Targetable) as).isTarget();
    }

    public static final Predicate<AbstractState> IS_TARGET_STATE = new Predicate<AbstractState>() {
        @Override
        public boolean apply(AbstractState pArg0) {
            return isTargetState(pArg0);
        }
    };

    /**
     * Returns a {@link Function} object for {@link #extractStateByType(AbstractState, Class)}.
     *
     * @param pType the type to use in the call of
     *        <code>extractStateByType(AbstractState, Class)</code> for parameter
     *        <code>Class</code>
     *
     * @return a <code>Function</code> for
     *        <code>extractStateByType(AbstractState, Class)</code> using the given
     *        type
     */
    public static <T extends AbstractState> Function<AbstractState, T> toState(final Class<T> pType) {

        return new Function<AbstractState, T>() {
            @Override
            public T apply(AbstractState as) {
                return extractStateByType(as, pType);
            }
        };
    }

    /**
     * Creates a {@link FluentIterable} that enumerates all the <code>AbstractStates</code>
     * contained in a given state pre-order. The root state itself is included, the states
     * are unwrapped recursively.
     *
     * <p><b>Example</b>: State A wraps states B and C. State B wraps states D and E.<br />
     *             The resulting tree (see below) is traversed pre-order.
     * <pre>
     *                  A
     *                 / \
     *                B   C
     *               / \
     *              D   E
     * </pre>
     * The returned <code>FluentIterable</code> iterates over the items in the following
     * order : A, B, D, E, C.
     * </p>
     *
     * @param as the root state
     *
     * @return a <code>FluentIterable</code> over the given root state and all states
     *         that are wrapped in it, recursively
     */
    public static FluentIterable<AbstractState> asIterable(final AbstractState as) {

        return new TreeTraverser<AbstractState>() {

            @Override
            public Iterable<AbstractState> children(AbstractState state) {
                if (state instanceof AbstractSingleWrapperState) {
                    AbstractState wrapped = ((AbstractSingleWrapperState) state).getWrappedState();
                    return ImmutableList.of(wrapped);

                } else if (state instanceof AbstractWrapperState) {
                    return ((AbstractWrapperState) state).getWrappedStates();
                }

                return ImmutableList.of();
            }
        }.preOrderTraversal(as);
    }

    private static final Function<AbstractState, Iterable<AbstractState>> AS_ITERABLE = new Function<AbstractState, Iterable<AbstractState>>() {
        @Override
        public Iterable<AbstractState> apply(AbstractState pState) {
            return asIterable(pState);
        }
    };

    /**
     * Apply {@link #asIterable(AbstractState)} to several abstract states at once
     * and provide an iterable for all resulting component abstract states.
     * There is no distinction from which state in the input iterable
     * a state in the output iterable results,
     * and there is no guaranteed order.
     */
    public static FluentIterable<AbstractState> asFlatIterable(final Iterable<AbstractState> pStates) {
        return from(pStates).transformAndConcat(AS_ITERABLE);
    }

    /**
     * Returns a predicate representing states represented by
     * the given abstract state, according to reported
     * formulas
     */
    public static BooleanFormula extractReportedFormulas(FormulaManagerView manager, AbstractState state) {
        BooleanFormulaManager bfmgr = manager.getBooleanFormulaManager();
        BooleanFormula result = bfmgr.makeBoolean(true);

        // traverse through all the sub-states contained in this state
        for (FormulaReportingState s : asIterable(state).filter(FormulaReportingState.class)) {

            result = bfmgr.and(result, s.getFormulaApproximation(manager));
        }

        return result;
    }
}