org.sosy_lab.cpachecker.pcc.strategy.BackwardTargetsReachedSetStrategy.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.pcc.strategy.BackwardTargetsReachedSetStrategy.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.pcc.strategy;

import com.google.common.collect.Maps;

import org.sosy_lab.common.ShutdownNotifier;
import org.sosy_lab.common.configuration.Configuration;
import org.sosy_lab.common.configuration.InvalidConfigurationException;
import org.sosy_lab.common.configuration.Option;
import org.sosy_lab.common.configuration.Options;
import org.sosy_lab.common.log.LogManager;
import org.sosy_lab.cpachecker.core.algorithm.CPAAlgorithm;
import org.sosy_lab.cpachecker.core.algorithm.pcc.AlgorithmWithPropertyCheck;
import org.sosy_lab.cpachecker.core.interfaces.AbstractState;
import org.sosy_lab.cpachecker.core.interfaces.Precision;
import org.sosy_lab.cpachecker.core.interfaces.Statistics;
import org.sosy_lab.cpachecker.core.interfaces.StatisticsProvider;
import org.sosy_lab.cpachecker.core.reachedset.ReachedSet;
import org.sosy_lab.cpachecker.core.reachedset.UnmodifiableReachedSet;
import org.sosy_lab.cpachecker.cpa.PropertyChecker.PropertyCheckerCPA;
import org.sosy_lab.cpachecker.cpa.arg.ARGState;
import org.sosy_lab.cpachecker.exceptions.CPAException;
import org.sosy_lab.cpachecker.util.Pair;

import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import javax.annotation.Nullable;

@Options(prefix = "pcc.backwardtargets")
public class BackwardTargetsReachedSetStrategy extends SequentialReadStrategy implements StatisticsProvider {

    private final @Nullable AlgorithmWithPropertyCheck algorithm;
    private AbstractState[] backwardTargets;

    @Option(secure = true, description = "Enable to store ARG states instead of abstract states wrapped by ARG state")
    private boolean certificateStatesAsARGStates = false;

    public BackwardTargetsReachedSetStrategy(final Configuration pConfig, final LogManager pLogger,
            final ShutdownNotifier pShutdownNotifier, final @Nullable PropertyCheckerCPA pCpa)
            throws InvalidConfigurationException {
        super(pConfig, pLogger);
        pConfig.inject(this);
        algorithm = pCpa == null ? null
                : new AlgorithmWithPropertyCheck(CPAAlgorithm.create(pCpa, pLogger, pConfig, pShutdownNotifier),
                        pLogger, pCpa);
    }

    @Override
    public void constructInternalProofRepresentation(final UnmodifiableReachedSet pReached)
            throws InvalidConfigurationException {
        try {
            backwardTargets = detectBackwardTargets((ARGState) pReached.getFirstState(), pReached.size());
        } catch (ClassCastException e) {
            throw new InvalidConfigurationException("Require ARG states, as top level abstract states.");
        }
    }

    private AbstractState[] detectBackwardTargets(final ARGState rootNode, final int size) {
        // DFS to detect circles (backward targets)
        Collection<AbstractState> statesToStore = new HashSet<>();
        Map<ARGState, Pair<Integer, Integer>> exploreTimes = Maps.newHashMapWithExpectedSize(size);
        Deque<Pair<ARGState, Iterator<ARGState>>> toVisit = new ArrayDeque<>();

        int time = 0;
        exploreTimes.put(rootNode, Pair.of(time++, Integer.MAX_VALUE));
        toVisit.add(Pair.of(rootNode, rootNode.getChildren().iterator()));
        Pair<ARGState, Iterator<ARGState>> top;
        Pair<Integer, Integer> exploreTime;
        ARGState uncoveredChild;

        while (!toVisit.isEmpty()) {
            top = toVisit.peek();

            if (!top.getSecond().hasNext()) {
                exploreTimes.put(top.getFirst(), Pair.of(exploreTimes.get(top.getFirst()).getFirst(), time++));
                toVisit.pop();
                continue;
            }

            uncoveredChild = replaceByCoveringState(top.getSecond().next());
            if (exploreTimes.containsKey(uncoveredChild)) {
                exploreTime = exploreTimes.get(uncoveredChild);
                if (exploreTime.getFirst() < time && exploreTime.getSecond() > time) {
                    if (certificateStatesAsARGStates) {
                        statesToStore.add(uncoveredChild);
                    } else {
                        statesToStore.add(uncoveredChild.getWrappedState());
                    }
                }
            } else {
                toVisit.push(Pair.of(uncoveredChild, uncoveredChild.getChildren().iterator()));
                exploreTimes.put(uncoveredChild, Pair.of(time++, Integer.MAX_VALUE));
            }
        }

        return statesToStore.toArray(new AbstractState[statesToStore.size()]);
    }

    private ARGState replaceByCoveringState(final ARGState pState) {
        ARGState result = pState;
        while (result.isCovered()) {
            result = result.getCoveringState();
        }
        return result;
    }

    @Override
    public boolean checkCertificate(final ReachedSet pReachedSet) throws CPAException, InterruptedException {
        // get initial precision
        Precision initPrec = pReachedSet.getPrecision(pReachedSet.getFirstState());

        // add certificate states to reached set
        for (AbstractState backwardTarget : backwardTargets) {
            pReachedSet.add(backwardTarget, initPrec);
        }

        // recompute deleted part with CPAalgorithm and check property with property checking algorithm
        return algorithm.run(pReachedSet).isSound();
    }

    @Override
    protected Object getProofToWrite(final UnmodifiableReachedSet pReached) throws InvalidConfigurationException {
        constructInternalProofRepresentation(pReached);
        return backwardTargets;
    }

    @Override
    protected void prepareForChecking(final Object pReadObject) throws InvalidConfigurationException {
        backwardTargets = (AbstractState[]) pReadObject;
        this.stats.proofSize = backwardTargets.length;
    }

    @Override
    public void collectStatistics(Collection<Statistics> statsCollection) {
        super.collectStatistics(statsCollection);
        if (algorithm != null) {
            algorithm.collectStatistics(statsCollection);
        }
    }

}