/**
*
*/
package bixie.checker.inconsistency_checker;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Set;
import java.util.LinkedHashSet;
import org.joogie.cfgPlugin.Util.Dag;
import ap.parser.IFormula;
import bixie.checker.report.Report;
import bixie.checker.transition_relation.TransitionRelation;
import bixie.prover.Prover;
import bixie.prover.ProverExpr;
import bixie.prover.ProverResult;
import bixie.prover.princess.PrincessProver;
import bixie.util.Log;
import boogie.controlflow.AbstractControlFlowFactory;
import boogie.controlflow.BasicBlock;
import boogie.controlflow.CfgAxiom;
import boogie.controlflow.CfgProcedure;
import boogie.controlflow.util.PartialBlockOrderNode;
/**
* @author schaef Inconsistent code detection algorithm that uses an abstract
* graph to find paths with a sat solver, and then an smt solver to
* check if the transition relation of the path is feasible. If not, it
* learns a conflict that can prune paths in the abstract graph.
*
* While this approach is less efficient on small procedures compared to
* the GreedyCfgChecker, it is orders of magnitude more efficient on
* large procedures.
*
* This algorithm is described in the paper: - Conflict-Directed Graph
* Coverage (NFM'15)
*/
public class CdcChecker extends AbstractChecker {
TransitionRelation transitionRelation;
LinkedHashSet<PartialBlockOrderNode> knownInfeasibleNodes = new LinkedHashSet<PartialBlockOrderNode>();
// TODO: keep track of everything that has been proved infeasible
// to make sure that we don't do the same work twice.
Set<Set<BasicBlock>> infeasibleSubprograms = new LinkedHashSet<Set<BasicBlock>>();
Set<Set<BasicBlock>> learnedConflicts = new LinkedHashSet<Set<BasicBlock>>();
/**
* @param cff
* @param p
*/
public CdcChecker(AbstractControlFlowFactory cff, CfgProcedure p) {
super(cff, p);
}
/*
* (non-Javadoc)
*
* @see
* bixie.checker.infeasiblecode.AbstractInfeasibleCodeDetection#checkSat(org
* .gravy.prover.Prover,
* bixie.checker.verificationcondition.CfgTransitionRelation)
*/
@Override
public Report runAnalysis(Prover prover) {
TransitionRelation tr = new TransitionRelation(this.procedure, cff,
prover);
return runAnalysisFromIntermediateResult(prover, tr,
new LinkedHashSet<BasicBlock>(), new LinkedHashSet<BasicBlock>());
}
public Report runAnalysisFromIntermediateResult(Prover prover,
TransitionRelation tr, Set<BasicBlock> alreadyCovered,
Set<BasicBlock> firstRoundResult) {
this.prover = prover;
this.transitionRelation = tr;
/*
* before adding anything, push a frame on the prover stack so that we
* can clean up easily.
*/
prover.push();
/* add the verification condition to the prover stack */
for (Entry<CfgAxiom, ProverExpr> entry : tr.getPreludeAxioms()
.entrySet()) {
prover.addAssertion(entry.getValue());
}
prover.addAssertion(tr.getRequires());
prover.addAssertion(tr.getEnsures());
Set<BasicBlock> coveredBlocks = new LinkedHashSet<BasicBlock>();
if (firstRoundResult.isEmpty()) {
Log.debug("Round1 " + this.transitionRelation.getProcedureName());
/*
* Cover all feasible path in the procedure while the assertion flag
* is set.
*/
prover.push();
prover.addAssertion(prover
.mkNot(this.transitionRelation.assertionFlag));
coveredBlocks.addAll(computeJodCover(prover, tr, alreadyCovered));
this.feasibleBlocks = new LinkedHashSet<BasicBlock>(coveredBlocks);
/* pop the assertion flag. */
prover.pop();
} else {
//not that alreadyCovered may contain more blocks than
//firstRoundResult
coveredBlocks = new LinkedHashSet<BasicBlock>(alreadyCovered);
this.feasibleBlocks = new LinkedHashSet<BasicBlock>(firstRoundResult);
}
Log.debug("Round2 " + this.transitionRelation.getProcedureName());
// TODO: reset the known infeasible node...?
knownInfeasibleNodes.clear();
learnedConflicts.clear();
infeasibleSubprograms.clear();
/*
* Now cover all paths that are feasible if the assertion flag is not
* set.
*/
coveredBlocks.addAll(computeJodCover(prover, tr, coveredBlocks));
/*
* algorithm is done, pop the verification condition from the prover
* stack.
*/
prover.pop();
/* 'unreachable' is the set of all blocks minus the set coveredBlocks. */
LinkedHashSet<BasicBlock> unreachable = new LinkedHashSet<BasicBlock>(tr
.getReachabilityVariables().keySet());
unreachable.removeAll(coveredBlocks);
/*
* All blocks that are covered in the second round - that is, the blocks
* that are in coveredBlocks but not in feasibleBlocks - are potentially
* dangerous, because their inconsistency contains an assertion.
*/
LinkedHashSet<BasicBlock> dangerous = new LinkedHashSet<BasicBlock>(coveredBlocks);
dangerous.removeAll(this.feasibleBlocks);
Report report = new Report(tr);
report.reportInconsistentCode(0, dangerous);
report.reportInconsistentCode(1, unreachable);
return report;
}
public Collection<BasicBlock> computeJodCover(Prover prover,
TransitionRelation tr, Set<BasicBlock> alreadyCovered) {
Set<BasicBlock> coveredBlocks = new LinkedHashSet<BasicBlock>(
alreadyCovered);
PartialBlockOrderNode poRoot = tr.getHasseDiagram().getRoot();
coveredBlocks.addAll(findFeasibleBlocks2(prover, tr, poRoot,
new LinkedHashSet<BasicBlock>(alreadyCovered)));
return coveredBlocks;
}
/**
* Check subprogram
*
* @param prover
* @param tr
* @param node
* @return
*/
private Set<BasicBlock> findFeasibleBlocks2(Prover prover,
TransitionRelation tr, PartialBlockOrderNode node,
Set<BasicBlock> alreadyCovered) {
if (node.getSuccessors().size() > 0) {
boolean allChildrenInfeasible = true;
Set<BasicBlock> result = new LinkedHashSet<BasicBlock>();
for (PartialBlockOrderNode child : node.getSuccessors()) {
Set<BasicBlock> res = findFeasibleBlocks2(prover, tr, child,
alreadyCovered);
result.addAll(res);
if (!res.isEmpty())
allChildrenInfeasible = false;
// check if we have proved this node to be infeasible
if (knownInfeasibleNodes.contains(node))
return new LinkedHashSet<BasicBlock>();
}
if (allChildrenInfeasible)
knownInfeasibleNodes.add(node);
return result;
} else {
// Log.debug("Step 3 A");
LinkedHashSet<BasicBlock> result = new LinkedHashSet<BasicBlock>(alreadyCovered);
if (alreadyCovered.containsAll(node.getElements()))
return result;
result.addAll(tryToFindConflictInPO(prover, tr, node, 0));
return result;
}
}
/**
* returns all nodes that occur on paths through b
*
* @param b
* @return
*/
private Set<BasicBlock> getSubprogContaining(BasicBlock b) {
Set<BasicBlock> knownInfeasibleBlocks = getKnownInfeasibleBlocks();
LinkedList<BasicBlock> todo = new LinkedList<BasicBlock>();
LinkedHashSet<BasicBlock> done = new LinkedHashSet<BasicBlock>();
todo.add(b);
while (!todo.isEmpty()) {
BasicBlock current = todo.pop();
done.add(current);
for (BasicBlock x : current.getPredecessors()) {
if (!todo.contains(x) && !done.contains(x)
&& !knownInfeasibleBlocks.contains(x)) {
todo.add(x);
}
}
}
// now the other direction
todo.add(b);
while (!todo.isEmpty()) {
BasicBlock current = todo.pop();
done.add(current);
for (BasicBlock x : current.getSuccessors()) {
if (!todo.contains(x) && !done.contains(x)
&& !knownInfeasibleBlocks.contains(x)) {
todo.add(x);
}
}
}
return done;
}
// private Set<BasicBlock> getSubgraphContainingAll(Set<BasicBlock> nodes,
// Set<BasicBlock> blocks) {
// LinkedList<BasicBlock> todo = new LinkedList<BasicBlock>(blocks);
// LinkedHashSet<BasicBlock> done = new LinkedHashSet<BasicBlock>();
// while (!todo.isEmpty()) {
// BasicBlock current = todo.pop();
// Set<BasicBlock> subprog = getSubgraphContaining(nodes, current);
// done.addAll(subprog);
// }
// return done;
// }
private Set<BasicBlock> getKnownInfeasibleBlocks() {
Set<BasicBlock> infeasibleBlocks = new LinkedHashSet<BasicBlock>();
// for (PartialBlockOrderNode po : this.knownInfeasibleNodes) {
// infeasibleBlocks.addAll(po.getElements());
// }
return infeasibleBlocks;
}
private ProverExpr mkDisjunction(TransitionRelation tr,
Collection<BasicBlock> blocks) {
ProverExpr next;
if (blocks.size() == 0) {
next = prover.mkLiteral(true);
} else if (blocks.size() == 1) {
next = tr.getReachabilityVariables().get(blocks.iterator().next());
} else {
ProverExpr[] disj = new ProverExpr[blocks.size()];
int i = 0;
for (BasicBlock n : blocks) {
disj[i++] = tr.getReachabilityVariables().get(n);
}
next = prover.mkOr(disj);
}
return next;
}
/**
* Get a complete and feasible path from the model produced by princes.
*
* @param prover
* @param tr
* @param necessaryNodes
* one of these nodes needs to be in the path
* @return
*/
private LinkedHashSet<BasicBlock> getPathFromModel(Prover prover,
TransitionRelation tr, Set<BasicBlock> allBlocks,
Set<BasicBlock> necessaryNodes) {
// Blocks selected by the model
LinkedHashSet<BasicBlock> enabledBlocks = new LinkedHashSet<BasicBlock>();
for (BasicBlock b : allBlocks) {
final ProverExpr pe = tr.getReachabilityVariables().get(b);
if (prover.evaluate(pe).getBooleanLiteralValue()) {
enabledBlocks.add(b);
}
}
for (BasicBlock block : necessaryNodes) {
if (enabledBlocks.contains(block)) {
// Get the path from block to the exit
LinkedList<BasicBlock> blockToExit = new LinkedList<BasicBlock>();
BasicBlock current = block;
while (current != null) {
blockToExit.add(current);
BasicBlock _current = null;
for (BasicBlock next : current.getSuccessors()) {
if (enabledBlocks.contains(next)) {
_current = next;
break;
}
}
current = _current;
}
if (blockToExit != null) {
// Get the path from root to the block
LinkedList<BasicBlock> rootToBlock = new LinkedList<BasicBlock>();
current = block;
while (current != null) {
blockToExit.add(current);
BasicBlock _current = null;
for (BasicBlock next : current.getPredecessors()) {
if (enabledBlocks.contains(next)) {
_current = next;
break;
}
}
current = _current;
}
if (rootToBlock != null) {
// We got a full path
LinkedHashSet<BasicBlock> result = new LinkedHashSet<BasicBlock>();
result.addAll(rootToBlock);
result.addAll(blockToExit);
return result;
}
}
}
}
// Screwed
// toDot("path_error.dot", new LinkedHashSet<BasicBlock>(allBlocks),
// new LinkedHashSet<BasicBlock>(enabledBlocks),
// new LinkedHashSet<BasicBlock>(necessaryNodes));
throw new RuntimeException("Could not find a path");
}
/*
* private void makeColors(PartialBlockOrderNode node, int startColor, int
* endColor, HashMap<PartialBlockOrderNode, Integer> node2color) {
*
* int range = (endColor - startColor) / 2; int midcolor = startColor +
* range;
*
* node2color.put(node, midcolor);
*
* int previous_color = startColor; int colordelta = (int) ((1.0) /
* ((double) node.getSuccessors().size()) * range);
*
* for (PartialBlockOrderNode child : node.getSuccessors()) {
* makeColors(child, previous_color, previous_color + colordelta,
* node2color); previous_color += colordelta; }
*
* }
*
* public void toDot(String filename, TransitionRelation tr) { HasseDiagram
* hd = tr.getHasseDiagram(); // LinkedHashSet<PartialBlockOrderNode> poNodes =
* getPoNodes(hd.getRoot()); HashMap<PartialBlockOrderNode, Integer>
* node2color = new HashMap<PartialBlockOrderNode, Integer>();
*
* makeColors(hd.getRoot(), 0x101010, 0xffffff, node2color); // int i=1; //
* for (PartialBlockOrderNode node : poNodes) { // double color =
* ((double)(i++))/((double)poNodes.size()+1) * // ((double)0xffffff); //
* node2color.put(node, (int)color ); // }
*
* try (PrintWriter pw = new PrintWriter(new OutputStreamWriter( new
* FileOutputStream(filename), "UTF-8"))) { pw.println("digraph dot {");
* LinkedList<BasicBlock> todo = new LinkedList<BasicBlock>();
* LinkedHashSet<BasicBlock> done = new LinkedHashSet<BasicBlock>();
* todo.add(tr.getProcedure().getRootNode()); StringBuffer sb = new
* StringBuffer(); while (!todo.isEmpty()) { BasicBlock current =
* todo.pop(); done.add(current); // for (BasicBlock prev :
* current.getPredecessors()) { // pw.println(" \""+ current.getLabel() //
* +"\" -> \""+prev.getLabel()+"\" [style=dotted]"); // if
* (!todo.contains(prev) && !done.contains(prev)) { // todo.add(prev); // }
* // // } for (BasicBlock next : current.getSuccessors()) { sb.append(" \""
* + current.getLabel() + "\" -> \"" + next.getLabel() + "\" \n"); if
* (!todo.contains(next) && !done.contains(next)) { todo.add(next); } } }
*
* for (BasicBlock b : done) { StringBuilder sb_ = new StringBuilder();
* sb_.append(Integer.toHexString(node2color.get(hd.findNode(b)))); while
* (sb_.length() < 6) { sb_.insert(0, '0'); // pad with leading zero if
* needed } String colorHex = sb_.toString(); pw.println("\"" + b.getLabel()
* + "\" " + "[label=\"" + b.getLabel() + "\",style=filled, fillcolor=\"#" +
* colorHex + "\"];\n"); } pw.println(sb.toString());
*
* pw.println("}"); pw.close(); } catch (IOException e) {
* e.printStackTrace(); } }
*
* public void hasseToDot(String filename, TransitionRelation tr) {
* HasseDiagram hd = tr.getHasseDiagram();
*
* try (PrintWriter pw = new PrintWriter(new OutputStreamWriter( new
* FileOutputStream(filename), "UTF-8"))) { pw.println("digraph dot {");
* LinkedList<PartialBlockOrderNode> todo = new
* LinkedList<PartialBlockOrderNode>(); LinkedHashSet<PartialBlockOrderNode> done
* = new LinkedHashSet<PartialBlockOrderNode>(); todo.add(hd.getRoot());
* StringBuffer sb = new StringBuffer(); while (!todo.isEmpty()) {
* PartialBlockOrderNode current = todo.pop(); done.add(current); // for
* (BasicBlock prev : current.getPredecessors()) { // pw.println(" \""+
* current.getLabel() // +"\" -> \""+prev.getLabel()+"\" [style=dotted]");
* // if (!todo.contains(prev) && !done.contains(prev)) { // todo.add(prev);
* // } // // } for (PartialBlockOrderNode next : current.getSuccessors()) {
* sb.append(" \"" + current.hashCode() + "\" -> \"" + next.hashCode() +
* "\" \n"); if (!todo.contains(next) && !done.contains(next)) {
* todo.add(next); } } }
*
* for (PartialBlockOrderNode node : done) { StringBuilder _sb = new
* StringBuilder(); for (BasicBlock b : node.getElements()) {
* _sb.append(b.getLabel() + "\n"); }
*
* pw.println("\"" + node.hashCode() + "\" " + "[label=\"" + _sb.toString()
* + "\"];\n"); } pw.println(sb.toString());
*
* pw.println("}"); pw.close(); } catch (IOException e) {
* e.printStackTrace(); } }
*/
/*
* ---------------------------- Plan B --------------------------------
*/
private Set<BasicBlock> tryToFindConflictInPO(Prover prover,
TransitionRelation tr, PartialBlockOrderNode node, int timeout) {
// pick any
learnedConflicts.clear();
BasicBlock current = node.getElements().iterator().next();
try {
// find the first one cheap.
Set<BasicBlock> path = up(current, current,
new LinkedHashSet<BasicBlock>());
while (path != null) {
Log.debug("Searching Path ... ");
if (checkPath(current, path)) {
return path;
}
path = findNextPath(current);
}
Log.debug("DONE Searching Path ... ");
} catch (InfeasibleException e) {
this.knownInfeasibleNodes.add(node);
Log.debug("YEAH");
}
return new LinkedHashSet<BasicBlock>();
}
private Set<BasicBlock> up(BasicBlock b, BasicBlock source,
Set<BasicBlock> path) throws InfeasibleException {
Set<BasicBlock> path_ = new LinkedHashSet<BasicBlock>(path);
path_.add(b);
if (isInLearnedConflicts(path_))
return null;
if (b != this.procedure.getRootNode()) {
for (BasicBlock x : b.getPredecessors()) {
Set<BasicBlock> result = up(x, source, path_);
if (result != null)
return result;
}
} else {
Set<BasicBlock> result = down(source, source, path_);
if (result != null)
return result;
}
return null;
}
private Set<BasicBlock> down(BasicBlock b, BasicBlock source,
Set<BasicBlock> path) throws InfeasibleException {
Set<BasicBlock> path_ = new LinkedHashSet<BasicBlock>(path);
path_.add(b);
if (isInLearnedConflicts(path_))
return null;
if (b != this.procedure.getExitNode()) {
for (BasicBlock x : b.getSuccessors()) {
Set<BasicBlock> result = down(x, source, path_);
if (result != null)
return result;
}
} else {
// ignore paths that are already known conflicts.
if (isInLearnedConflicts(path_))
return null;
return path_;
}
return null;
}
private boolean isInLearnedConflicts(Set<BasicBlock> path) {
for (Set<BasicBlock> conflict : learnedConflicts) {
if (conflict.size() > 0 && path.size() > conflict.size()
&& path.containsAll(conflict)) {
return true;
}
}
return false;
}
@SuppressWarnings("serial")
public static class InfeasibleException extends Exception {
}
/**
* Checks the feasibility of Path. If feasible, returns True.
* Otherwise Y
* @param source
* @param path
* @return
* @throws InfeasibleException
*/
private boolean checkPath(BasicBlock source, Set<BasicBlock> path)
throws InfeasibleException {
Log.debug("checking path");
prover.push();
for (BasicBlock b : path) {
prover.addAssertion(this.transitionRelation.blockTransitionReleations
.get(b));
}
ProverResult res = prover.checkSat(true);
prover.pop();
if (res == ProverResult.Sat) {
return true;
} else if (res == ProverResult.Unsat) {
Set<BasicBlock> core = computePseudoUnsatCore(path);
learnedConflicts.add(new LinkedHashSet<BasicBlock>(core));
if (path.size() == core.size()) {
Log.debug("nothing could be removed");
return false;
}
Set<BasicBlock> inevitableBlocks = findNodeThatMustBePassed(this.transitionRelation
.getHasseDiagram().findNode(source));
if (inevitableBlocks.containsAll(core)) {
Log.debug("FOUND CONFLICT! DONE");
markSmallestSubtreeInfeasible(core);
throw new InfeasibleException();
} else {
Log.debug("nothing learned. Looking for next path.");
}
} else {
throw new RuntimeException("PROVER FAILED");
}
return false;
}
/**
* TODO: @Philipp, this gets stuck for some examples :(
*
* @param path
*/
boolean allowHackedTimeouts = true;
private Set<BasicBlock> computePseudoUnsatCore(Set<BasicBlock> path) {
Set<BasicBlock> core = new LinkedHashSet<BasicBlock>(path);
LinkedList<BasicBlock> todo = new LinkedList<BasicBlock>(path);
while (!todo.isEmpty()) {
BasicBlock current = todo.pop();
core.remove(current);
prover.push();
for (BasicBlock b : core) {
prover.addAssertion(this.transitionRelation.blockTransitionReleations
.get(b));
}
ProverResult res = ProverResult.Unknown;
if (!allowHackedTimeouts) {
res = prover.checkSat(true);
} else {
prover.checkSat(false);
res = prover.getResult(200);
if (res == ProverResult.Running) {
// the coverage algorithm could not make progress within the
// given time limit. Falling back to the new algorithms.
Log.debug("\tComputing Unsat Core took too long and got killed.");
prover.stop();
res = ProverResult.Unknown;
}
}
prover.pop();
if (res != ProverResult.Unsat) {
core.add(current); // then we needed this one
}
}
return core;
}
private Set<BasicBlock> findNodeThatMustBePassed(PartialBlockOrderNode node) {
if (node == null)
return new LinkedHashSet<BasicBlock>();
Set<BasicBlock> result = findNodeThatMustBePassed(node.getParent());
result.addAll(node.getElements());
return result;
}
private void markSmallestSubtreeInfeasible(Set<BasicBlock> unsatCore) {
PartialBlockOrderNode lowest = this.transitionRelation
.getHasseDiagram().getRoot();
for (BasicBlock b : unsatCore) {
PartialBlockOrderNode current = this.transitionRelation
.getHasseDiagram().findNode(b);
if (isAbove(current, lowest)) {
lowest = current;
}
}
LinkedList<PartialBlockOrderNode> todo = new LinkedList<PartialBlockOrderNode>();
todo.add(lowest);
while (!todo.isEmpty()) {
PartialBlockOrderNode current = todo.pop();
this.knownInfeasibleNodes.add(current);
todo.addAll(current.getSuccessors());
}
}
private boolean isAbove(PartialBlockOrderNode child,
PartialBlockOrderNode parent) {
PartialBlockOrderNode node = child;
while (node != null) {
if (node == parent)
return true;
node = node.getParent();
}
return false;
}
/*
* ================ stuff to find path with sat solver =====================
*/
/**
* Use the solver to find a path through 'current' in the abstract model
* that has not yet been covered.
*
* @param current
* The block that must be contained on the path.
* @return The set of all blocks on that path.
*/
private Set<BasicBlock> findNextPath(BasicBlock current) {
Log.debug("Finding next path");
Set<BasicBlock> blocks = this.getSubprogContaining(current);
prover.push();
// assert this subprogram.
// assertAbstractaPath(blocks);
assertAbstractaPathCfGTheory(blocks);
prover.addAssertion(transitionRelation.getReachabilityVariables().get(
current));
// block all learned conflicts
Log.debug("Asserting " + this.learnedConflicts.size() + " conflicts");
for (Set<BasicBlock> conflict : this.learnedConflicts) {
ProverExpr[] conj = new ProverExpr[conflict.size()];
int i = 0;
for (BasicBlock b : conflict) {
conj[i++] = this.transitionRelation.getReachabilityVariables()
.get(b);
}
prover.addAssertion(prover.mkNot(prover.mkAnd(conj)));
}
Log.debug("Checking for path.");
ProverResult res = prover.checkSat(true);
if (res == ProverResult.Sat) {
LinkedHashSet<BasicBlock> necessaryNodes = new LinkedHashSet<BasicBlock>();
necessaryNodes.add(current);
Set<BasicBlock> path = this.getPathFromModel(prover,
transitionRelation, blocks, necessaryNodes);
prover.pop();
Log.debug("Found one.");
return path;
} else if (res == ProverResult.Unsat) {
prover.pop();
// otherwise, we can remove it.
} else {
throw new RuntimeException("PROVER FAILED");
}
Log.debug("Found NONE.");
return null;
}
/**
*
* @param blocks
*/
private void assertAbstractaPathCfGTheory(Set<BasicBlock> blocks) {
LinkedHashMap<ProverExpr, ProverExpr> ineffFlags = new LinkedHashMap<ProverExpr, ProverExpr>();
for (BasicBlock block : blocks) {
ProverExpr v = transitionRelation.getReachabilityVariables().get(
block);
ineffFlags.put(v, prover.mkVariable("" + v + "_flag",
prover.getBooleanType()));
}
Dag<IFormula> vcdag = transitionRelation.getProverDAG();
LinkedList<ProverExpr> remainingBlockVars = new LinkedList<ProverExpr>();
LinkedList<ProverExpr> remainingIneffFlags = new LinkedList<ProverExpr>();
for (Entry<ProverExpr, ProverExpr> entry : ineffFlags.entrySet()) {
remainingBlockVars.add(entry.getKey());
remainingIneffFlags.add(entry.getValue());
}
((PrincessProver) prover).setupCFGPlugin(vcdag, remainingBlockVars,
remainingIneffFlags, 1);
// Encode each block
for (BasicBlock block : blocks) {
// Get the successors of the block
LinkedList<BasicBlock> successors = new LinkedList<BasicBlock>();
for (BasicBlock succ : block.getSuccessors()) {
if (blocks.contains(succ)) {
successors.add(succ);
}
}
// Construct the disjunction of the successors
// Make the assertion
ProverExpr assertion = prover.mkImplies(transitionRelation
.getReachabilityVariables().get(block),
mkDisjunction(transitionRelation, successors));
// Assert it
prover.addAssertion(assertion);
}
prover.addAssertion(transitionRelation.getReachabilityVariables().get(
transitionRelation.getProcedure().getRootNode()));
prover.addAssertion(transitionRelation.getReachabilityVariables().get(
transitionRelation.getProcedure().getExitNode()));
// Log.debug("Entries "+count);
}
}