Browse Source

accumulation: deduplicate product code

accumulation
Sascha Wunderlich 7 years ago
parent
commit
28f49ddc16
  1. 100
      prism/src/explicit/AccumulationProduct.java
  2. 119
      prism/src/explicit/AccumulationProductComplex.java
  3. 10
      prism/src/explicit/AccumulationProductComplexCounting.java
  4. 110
      prism/src/explicit/AccumulationProductSimple.java
  5. 20
      prism/src/explicit/AccumulationState.java

100
prism/src/explicit/AccumulationProduct.java

@ -5,6 +5,7 @@ import java.util.BitSet;
import java.util.Iterator;
import java.util.Map;
import parser.ast.AccumulationFactor;
import parser.ast.Expression;
import prism.IntegerBound;
import prism.PrismException;
@ -67,6 +68,90 @@ public abstract class AccumulationProduct<M extends Model,Component> extends Pro
protected abstract Component updateComponent(Integer modelFromStateId, final AccumulationTrack<Component> track);
protected final AccumulationTrack<Component> updateTrack(Integer modelFromStateId, final AccumulationTrack<Component> track, final double[] weights) {
Component nextComponent = updateComponent(modelFromStateId, track);
// If we are done, return null-Track
if (nextComponent == null) { return null; }
// Otherwise, we update the weights and increase the step.
double[] newweights = new double[weights.length];
for (int i = 0; i < weights.length; i++) {
newweights[i] = weights[i] + track.getWeights()[i];
}
return new AccumulationTrack<Component>(newweights, nextComponent);
}
protected final AccumulationState<Component> updateAccumulationState(final int modelFromStateId, final AccumulationState<Component> accstate, final double[] weights) throws PrismException {
// If we are in singleTrack mode and the last restart is the numberOfTracks, we can stop...
if(ctx.singleTrack && (accstate.lastRestartNr == numberOfTracks-1)) { return accstate; }
// Check if we even need to fire here.
if(ctx.accexp.hasFireOn()) {
boolean stutter = true;
for(Expression f : ctx.accexp.getFireOn()) {
if(ctx.mc.checkExpression(originalModel, f, null).getBitSet().get(modelFromStateId)) {
//mc.getLog().println("f:" + f);
stutter = false;
break;
}
}
// If this is a stutter action, we can return the same accstate. Copies are made on modification.
if(stutter) { return accstate; }
}
// ...otherwise proceed.
// Get the old tracker and tracks.
AccumulationTracker<Component> oldTracker = accstate.getTracker(trackers);
ArrayList<AccumulationTrack<Component>> oldTracks = oldTracker.getTracks();
// This restart will be...
int newLastRestartNr = accstate.getNextRestartNr();
//mc.getLog().print(newLastRestartNr);
// Build the new tracks and determine their goodness;
ArrayList<AccumulationTrack<Component>> newTracks = new ArrayList<>();
BitSet newGoodTracks = (BitSet)accstate.getGoodTracks().clone();
int trackNr = 0;
for(AccumulationTrack<Component> oldTrack : oldTracks) {
AccumulationTrack<Component> newTrack;
// restart or advance
if(trackNr == newLastRestartNr && !ctx.singleTrack) {
// If we have a restart, we produce an initial track and let it advance.
// The goodness is cleared.
AccumulationTrack<Component> freshTrack = new AccumulationTrack<Component>(numberOfWeights, getInitialComponent());
//newTrack = updateTrack(modelFromStateId, freshTrack, accexp, weights, mc);
newTrack = freshTrack;
newGoodTracks.clear(trackNr);
} else if (oldTrack == null || (ctx.singleTrack && trackNr>0)) {
// If the old track is undefined, the new track is as well.
// Goodness stays!
newTrack = null;
} else {
// Otherwise, the track is defined and advances.
// If it is not good yet, we check it.
assert oldTrack != null;
newTrack = updateTrack(modelFromStateId, oldTrack, weights);
if(!newGoodTracks.get(trackNr)) {
newGoodTracks.set(trackNr, isGoalTrack(newTrack));
}
}
newTracks.add(newTrack);
trackNr++;
}
//Create a new tracker with the right tracks and add it to storage.
AccumulationTracker<Component> newTracker = new AccumulationTracker<>(newTracks);
int newTrackerId = trackers.findOrAdd(newTracker);
return new AccumulationState<>(newTrackerId, newLastRestartNr, numberOfTracks, newGoodTracks);
}
/**
* Creates the initial state for the accumulation part of this of this accumulation product. Returns its ID.
*
@ -74,7 +159,20 @@ public abstract class AccumulationProduct<M extends Model,Component> extends Pro
* where the first restart is the first (0th) track.
* @return
*/
protected abstract int createInitialStateId();
protected final int createInitialStateId() {
Component initialComponent = getInitialComponent();
// The initial active track is the first one, all tracks are non-good by default
int initialActiveTrack = 0;
// Generate the initial track and product state
AccumulationTracker<Component> initialTracker = new AccumulationTracker<Component>(numberOfTracks, numberOfWeights, initialComponent);
int initialTrackerId = trackers.findOrAdd(initialTracker);
AccumulationState<Component> initialAccState = new AccumulationState<Component>(initialTrackerId, initialActiveTrack, numberOfTracks);
int initialAccStateId = accStates.findOrAdd(initialAccState);
return initialAccStateId;
}
protected boolean isGoalTrack(AccumulationTrack<Component> track) throws PrismException {
return isFinalTrack(track) && constraintHolds(track);

119
prism/src/explicit/AccumulationProductComplex.java

@ -5,7 +5,6 @@ import java.util.BitSet;
import java.util.Iterator;
import java.util.Map;
import parser.ast.Expression;
import prism.PrismException;
import common.Dottable;
@ -45,21 +44,6 @@ public abstract class AccumulationProductComplex<M extends Model,Component> exte
return goalStates.get(track);
}
protected final int createInitialStateId() {
Component initialComponent = getInitialComponent();
// The initial active track is the first one, all tracks are non-good by default
int initialActiveTrack = 0;
// Generate the initial track and product state
AccumulationTracker<Component> initialTracker = new AccumulationTracker<Component>(numberOfTracks, numberOfWeights, initialComponent);
int initialTrackerId = trackers.findOrAdd(initialTracker);
AccumulationState<Component> initialAccState = new AccumulationState<Component>(initialTrackerId, initialActiveTrack, numberOfTracks, false);
int initialAccStateId = accStates.findOrAdd(initialAccState);
return initialAccStateId;
}
protected void generateTrackInfo(ProductState state, Integer index) throws PrismException {
AccumulationState<Component> accState = accStates.getById(state.getSecondState());
AccumulationTracker<Component> tracker = accState.getTracker(trackers);
@ -69,7 +53,7 @@ public abstract class AccumulationProductComplex<M extends Model,Component> exte
boolean isInitial = trackIdx==accState.lastRestartNr;
boolean isRunning = track != null;
boolean isGoal = isGoalTrack(track);
boolean isGoal = accState.getGoodTracks().get(trackIdx); // isGoalTrack(track)
// Is this an initial
initStates.get(trackIdx).set(index, isInitial);
@ -82,106 +66,7 @@ public abstract class AccumulationProductComplex<M extends Model,Component> exte
}
}
/** Updates a single AccumulationTrack. Used in updateAccumulationState.
*
* Uses updateComponent to get the next Component, accumulates the current weights
* and makes a new track.
* @param modelFromStateId
* @param track
* @param accexp
* @param weights
* @param mc
* @return
*/
protected final AccumulationTrack<Component> updateTrack(Integer modelFromStateId, final AccumulationTrack<Component> track, final double[] weights) {
Component nextComponent = updateComponent(modelFromStateId, track);
// If we are done, return null-Track
if (nextComponent == null) { return null; }
// Otherwise, we update the weights and increase the step.
double[] newweights = new double[weights.length];
for (int i = 0; i < weights.length; i++) {
newweights[i] = weights[i] + track.getWeights()[i];
}
return new AccumulationTrack<Component>(newweights, nextComponent);
}
/** Generates a new accumulation state from an old one.
*
* To do so, it reads the necessary information from the model and its rewards
* and updates all tracks and their goodness accordingly.
* @param modelFromStateId
* @param accstate
* @param accexp
* @param weights
* @param mc
* @return
* @throws PrismException
*/
protected final AccumulationState<Component> updateAccumulationState(final int modelFromStateId, final AccumulationState<Component> accstate, final double[] weights) throws PrismException {
// If we are in singleTrack mode and the last restart is the numberOfTracks, we can stop...
if(ctx.singleTrack && (accstate.lastRestartNr == numberOfTracks-1)) { return accstate; }
// Check if we even need to fire here.
if(ctx.accexp.hasFireOn()) {
boolean stutter = true;
for(Expression f : ctx.accexp.getFireOn()) {
if(ctx.mc.checkExpression(originalModel, f, null).getBitSet().get(modelFromStateId)) {
//mc.getLog().println("f:" + f);
stutter = false;
break;
}
}
// If this is a stutter action, we can return the same accstate. Copies are made on modification.
if(stutter) { return accstate; }
}
// ...otherwise proceed.
// Get the old tracker and tracks.
AccumulationTracker<Component> oldTracker = accstate.getTracker(trackers);
ArrayList<AccumulationTrack<Component>> oldTracks = oldTracker.getTracks();
// This restart will be...
int newLastRestartNr = accstate.getNextRestartNr();
//mc.getLog().print(newLastRestartNr);
// Build the new tracks and determine their goodness;
ArrayList<AccumulationTrack<Component>> newTracks = new ArrayList<>();
int trackNr = 0;
for(AccumulationTrack<Component> oldTrack : oldTracks) {
AccumulationTrack<Component> newTrack;
// restart or advance
if(trackNr == newLastRestartNr && !ctx.singleTrack) {
// If we have a restart, we produce an initial track and let it advance.
AccumulationTrack<Component> freshTrack = new AccumulationTrack<Component>(numberOfWeights, getInitialComponent());
//newTrack = updateTrack(modelFromStateId, freshTrack, accexp, weights, mc);
newTrack = freshTrack;
} else if (oldTrack == null || (ctx.singleTrack && trackNr>0)) {
// If the old track is undefined, the new track is as well.
newTrack = null;
} else {
// Otherwise, the track is defined and advances.
assert oldTrack != null;
newTrack = updateTrack(modelFromStateId, oldTrack, weights);
}
newTracks.add(newTrack);
trackNr++;
}
//Create a new tracker with the right tracks and add it to storage.
AccumulationTracker<Component> newTracker = new AccumulationTracker<>(newTracks);
int newTrackerId = trackers.findOrAdd(newTracker);
return new AccumulationState<>(newTrackerId, newLastRestartNr, numberOfTracks);
}
@Override
protected String labelString(Integer stateId) {
StringBuffer result = new StringBuffer();

10
prism/src/explicit/AccumulationProductComplexCounting.java

@ -178,16 +178,6 @@ public class AccumulationProductComplexCounting<M extends Model> extends Accumul
return nextStep;
}
/**
* Populates fields:
* - numberOfTracks with the highest relevant integer plus one, and
* - numberOfWeights with the size of the reward vector.
* @param graph
* @param accexp
* @param rewards
* @param mc
* @throws PrismException
*/
protected void createAuxData(final Model graph) throws PrismException {
numberOfTracks = IntegerBound.fromTemporalOperatorBound(ctx.accexp.getBoundExpression(), ctx.mc.getConstantValues(), true).getHighestInteger()+1;
numberOfWeights = ctx.rewards.size();

110
prism/src/explicit/AccumulationProductSimple.java

@ -1,6 +1,5 @@
package explicit;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Iterator;
import java.util.Map;
@ -32,120 +31,11 @@ public abstract class AccumulationProductSimple<M extends Model,Component> exten
return goodStates;
}
protected final int createInitialStateId() {
Component initialComponent = getInitialComponent();
// The initial active track is the first one, all tracks are non-good by default
int initialActiveTrack = 0;
// Generate the initial track and product state
AccumulationTracker<Component> initialTracker = new AccumulationTracker<Component>(numberOfTracks, numberOfWeights, initialComponent);
int initialTrackerId = trackers.findOrAdd(initialTracker);
AccumulationState<Component> initialAccState = new AccumulationState<Component>(initialTrackerId, initialActiveTrack, numberOfTracks, true);
int initialAccStateId = accStates.findOrAdd(initialAccState);
return initialAccStateId;
}
protected void generateStateInfo(ProductState state, Integer index) throws PrismException {
AccumulationState<Component> accState = accStates.getById(state.getSecondState());
goodStates.set(index, accState.hasGoodTracks());
}
/** Updates a single AccumulationTrack. Used in updateAccumulationState.
*
* Uses updateComponent to get the next Component, accumulates the current weights
* and makes a new track.
* @param modelFromStateId
* @param track
* @param accexp
* @param weights
* @param mc
* @return
*/
protected final AccumulationTrack<Component> updateTrack(Integer modelFromStateId, final AccumulationTrack<Component> track, final double[] weights) {
Component nextComponent = updateComponent(modelFromStateId, track);
// If we are done, return null-Track
if (nextComponent == null) { return null; }
// Otherwise, we update the weights and increase the step.
double[] newweights = new double[weights.length];
for (int i = 0; i < weights.length; i++) {
newweights[i] = weights[i] + track.getWeights()[i];
}
return new AccumulationTrack<Component>(newweights, nextComponent);
}
/** Generates a new accumulation state from an old one.
*
* To do so, it reads the necessary information from the model and its rewards
* and updates all tracks and their goodness accordingly.
* @param modelFromStateId
* @param accstate
* @param accexp
* @param weights
* @param mc
* @return
* @throws PrismException
*/
protected final AccumulationState<Component> updateAccumulationState(final int modelFromStateId, final AccumulationState<Component> accstate, final double[] weights) throws PrismException {
// If we are in singleTrack mode and the last restart is the numberOfTracks, we can stop...
if(ctx.singleTrack && (accstate.lastRestartNr == numberOfTracks-1)) { return accstate; }
// Get the old tracker and tracks.
AccumulationTracker<Component> oldTracker = accstate.getTracker(trackers);
ArrayList<AccumulationTrack<Component>> oldTracks = oldTracker.getTracks();
// This restart will be...
int newLastRestartNr = accstate.getNextRestartNr();
//mc.getLog().print(newLastRestartNr);
// Build the new tracks and determine their goodness;
ArrayList<AccumulationTrack<Component>> newTracks = new ArrayList<>();
BitSet newGoodTracks = (BitSet)accstate.getGoodTracks().clone();
int trackNr = 0;
for(AccumulationTrack<Component> oldTrack : oldTracks) {
AccumulationTrack<Component> newTrack;
// restart or advance
if(trackNr == newLastRestartNr && !ctx.singleTrack) {
// If we have a restart, we produce an initial track and let it advance.
// The goodness is cleared.
AccumulationTrack<Component> freshTrack = new AccumulationTrack<Component>(numberOfWeights, getInitialComponent());
//newTrack = updateTrack(modelFromStateId, freshTrack, accexp, weights, mc);
newTrack = freshTrack;
newGoodTracks.clear(trackNr);
} else if (oldTrack == null || (ctx.singleTrack && trackNr>0)) {
// If the old track is undefined, the new track is as well.
// Goodness stays!
newTrack = null;
} else {
// Otherwise, the track is defined and advances.
// If it is not good yet, we check it.
assert oldTrack != null;
newTrack = updateTrack(modelFromStateId, oldTrack, weights);
if(!newGoodTracks.get(trackNr)) {
newGoodTracks.set(trackNr, isGoalTrack(newTrack));
}
}
newTracks.add(newTrack);
trackNr++;
}
//Create a new tracker with the right tracks and add it to storage.
AccumulationTracker<Component> newTracker = new AccumulationTracker<>(newTracks);
int newTrackerId = trackers.findOrAdd(newTracker);
//Create the new AccState and its Goodness
AccumulationState<Component> newAccState = new AccumulationState<>(newTrackerId, newLastRestartNr, numberOfTracks, newGoodTracks);
return newAccState;
}
protected String labelString(Integer stateId) {
StringBuffer result = new StringBuffer();
if(goodStates.get(stateId)) { result.append("G: "); }

20
prism/src/explicit/AccumulationState.java

@ -12,28 +12,24 @@ import java.util.Objects;
*
*/
public class AccumulationState<Component> {
final int trackerId;
protected final int trackerId;
int lastRestartNr;
int numberOfTracks;
protected int lastRestartNr;
protected int numberOfTracks;
BitSet goodTracks;
public AccumulationState(int trackerId, int lastRestartNr, int numberOfTracks) {
this(trackerId, lastRestartNr, numberOfTracks, false);
}
protected BitSet goodTracks;
public AccumulationState(int trackerId, int lastRestartNr, int numberOfTracks, BitSet goodTracks) {
this(trackerId, lastRestartNr, numberOfTracks);
this.goodTracks = goodTracks;
}
public AccumulationState(int trackerId, int lastRestartNr, int numberOfTracks, boolean withGoodTracks) {
public AccumulationState(int trackerId, int lastRestartNr, int numberOfTracks) {
super();
if(withGoodTracks) { goodTracks = new BitSet(numberOfTracks); }
this.trackerId = trackerId;
this.lastRestartNr = lastRestartNr;
this.trackerId = trackerId;
this.lastRestartNr = lastRestartNr;
this.numberOfTracks = numberOfTracks;
this.goodTracks = new BitSet();
}
public int getTrackerId() {

Loading…
Cancel
Save