|
|
|
@ -76,6 +76,154 @@ public class ForwardsReach |
|
|
|
*/ |
|
|
|
public ReachabilityGraph buildForwardsGraph(PTA pta, BitSet targetLocs, Constraint targetConstraint) |
|
|
|
throws PrismException |
|
|
|
{ |
|
|
|
boolean formats10 = true; |
|
|
|
|
|
|
|
if (formats10) |
|
|
|
return buildForwardsGraphFormats10(pta, targetLocs, targetConstraint); |
|
|
|
else |
|
|
|
return buildForwardsGraphFormats09(pta, targetLocs, targetConstraint); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Implementation of {@link #buildForwardsGraph} using FORMATS'10 definition. |
|
|
|
*/ |
|
|
|
private ReachabilityGraph buildForwardsGraphFormats10(PTA pta, BitSet targetLocs, Constraint targetConstraint) |
|
|
|
throws PrismException |
|
|
|
{ |
|
|
|
Zone z; |
|
|
|
LocZone init, lz, lz2; |
|
|
|
LinkedList<LocZone> X; |
|
|
|
IndexedSet<LocZone> Yset; |
|
|
|
//LocZoneSetOld Zset; |
|
|
|
ReachabilityGraph graph; |
|
|
|
int src, dest, count; |
|
|
|
long timer, timerProgress; |
|
|
|
boolean progressDisplayed; |
|
|
|
|
|
|
|
// Store target info |
|
|
|
this.targetLocs = targetLocs; |
|
|
|
this.targetConstraint = targetConstraint; |
|
|
|
|
|
|
|
// Starting reachability... |
|
|
|
mainLog.println("\nBuilding forwards reachability graph..."); |
|
|
|
timer = timerProgress = System.currentTimeMillis(); |
|
|
|
progressDisplayed = false; |
|
|
|
|
|
|
|
// Re-compute max clock constraint value if required |
|
|
|
if (targetConstraint != null) |
|
|
|
pta.recomputeMaxClockConstraint(targetConstraint); |
|
|
|
|
|
|
|
// Initialise data structures |
|
|
|
graph = new ReachabilityGraph(pta); |
|
|
|
Yset = new IndexedSet<LocZone>(); |
|
|
|
X = new LinkedList<LocZone>(); |
|
|
|
target = new BitSet(); |
|
|
|
|
|
|
|
// Build initial symbolic state (NB: assume initial location = 0) |
|
|
|
z = DBM.createZero(pta); |
|
|
|
init = new LocZone(0, z); |
|
|
|
|
|
|
|
// Reachability loop |
|
|
|
Yset.add(init); |
|
|
|
X.add(init); |
|
|
|
src = -1; |
|
|
|
// While there are unexplored symbolic states (in X)... |
|
|
|
while (!X.isEmpty()) { |
|
|
|
// Pick next state to explore |
|
|
|
// X is a list containing states in order found |
|
|
|
// (so we know index of lz is src+1) |
|
|
|
lz = X.removeFirst(); |
|
|
|
src++; |
|
|
|
// Compute timed post for this zone (NB: do this before checking if target) |
|
|
|
lz = lz.deepCopy(); |
|
|
|
lz.tPost(pta); |
|
|
|
// Is this a target state? |
|
|
|
if (targetLocs.get(lz.loc) && (targetConstraint == null || lz.zone.isSatisfied(targetConstraint))) { |
|
|
|
target.set(src); |
|
|
|
// Add null for this state (no need to store info) |
|
|
|
graph.addState(); |
|
|
|
continue; |
|
|
|
} |
|
|
|
// Otherwise, explore this symbolic state |
|
|
|
// First, check there is at least one transition |
|
|
|
// (don't want deadlocks in non-target states) |
|
|
|
if (pta.getTransitions(lz.loc).size() == 0) { |
|
|
|
throw new PrismException("PTA deadlocks in location \"" + pta.getLocationNameString(lz.loc) + "\""); |
|
|
|
} |
|
|
|
// Add current state to reachability graph |
|
|
|
graph.addState(); |
|
|
|
// For each outgoing transition... |
|
|
|
for (Transition transition : pta.getTransitions(lz.loc)) { |
|
|
|
int[] dests = new int[transition.getNumEdges()]; |
|
|
|
boolean enabled = false; |
|
|
|
boolean unenabled = false; |
|
|
|
count = 0; |
|
|
|
for (Edge edge : transition.getEdges()) { |
|
|
|
// Do "discrete post" for this edge |
|
|
|
lz2 = lz.deepCopy(); |
|
|
|
lz2.dPost(edge); |
|
|
|
// If non-empty, create edge, also adding state to X if new |
|
|
|
if (!lz2.zone.isEmpty()) { |
|
|
|
if (Yset.add(lz2)) { |
|
|
|
X.add(lz2); |
|
|
|
} |
|
|
|
dest = Yset.getIndexOfLastAdd(); |
|
|
|
enabled = true; |
|
|
|
dests[count] = dest; |
|
|
|
} else { |
|
|
|
unenabled = true; |
|
|
|
dests[count] = -1; |
|
|
|
} |
|
|
|
count++; |
|
|
|
} |
|
|
|
if (enabled) { |
|
|
|
if (unenabled) |
|
|
|
throw new PrismException("Badly formed PTA: state " + src); |
|
|
|
graph.addTransition(src, transition, dests, null); |
|
|
|
} |
|
|
|
} |
|
|
|
// Print some progress info occasionally |
|
|
|
if (System.currentTimeMillis() - timerProgress > 3000) { |
|
|
|
if (!progressDisplayed) { |
|
|
|
mainLog.print("Number of states so far:"); |
|
|
|
progressDisplayed = true; |
|
|
|
} |
|
|
|
mainLog.print(" " + Yset.size()); |
|
|
|
mainLog.flush(); |
|
|
|
timerProgress = System.currentTimeMillis(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Tidy up progress display |
|
|
|
if (progressDisplayed) |
|
|
|
mainLog.println(" " + Yset.size()); |
|
|
|
|
|
|
|
// Convert state set to ArrayList and store |
|
|
|
graph.states = Yset.toArrayList(); |
|
|
|
|
|
|
|
// Always have a single initial state 0 after this construction |
|
|
|
initialStates = new ArrayList<Integer>(); |
|
|
|
initialStates.add(0); |
|
|
|
|
|
|
|
// Reachability complete |
|
|
|
timer = System.currentTimeMillis() - timer; |
|
|
|
mainLog.println("Graph constructed in " + (timer / 1000.0) + " secs."); |
|
|
|
mainLog.print("Graph: " + graph.states.size() + " symbolic states"); |
|
|
|
mainLog.println("), " + target.cardinality() + " target states"); |
|
|
|
|
|
|
|
// Print a warning if there are no target states |
|
|
|
if (target.cardinality() == 0) |
|
|
|
mainLog.println("Warning: There are no target states."); |
|
|
|
|
|
|
|
return graph; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Implementation of {@link #buildForwardsGraph} using FORMATS'09 definition. |
|
|
|
*/ |
|
|
|
private ReachabilityGraph buildForwardsGraphFormats09(PTA pta, BitSet targetLocs, Constraint targetConstraint) |
|
|
|
throws PrismException |
|
|
|
{ |
|
|
|
Zone z; |
|
|
|
LocZone init, lz, lz2; |
|
|
|
|