9 changed files with 155 additions and 789 deletions
-
4prism/src/explicit/AccumulationContext.java
-
71prism/src/explicit/AccumulationProduct.java
-
139prism/src/explicit/AccumulationProductComplex.java
-
28prism/src/explicit/AccumulationProductCounting.java
-
28prism/src/explicit/AccumulationProductRegular.java
-
107prism/src/explicit/AccumulationProductSimple.java
-
195prism/src/explicit/AccumulationProductSimpleCounting.java
-
228prism/src/explicit/AccumulationProductSimpleRegular.java
-
144prism/src/explicit/AccumulationTransformation.java
@ -1,139 +0,0 @@ |
|||||
package explicit; |
|
||||
|
|
||||
import java.util.ArrayList; |
|
||||
import java.util.BitSet; |
|
||||
import java.util.Iterator; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
import prism.PrismException; |
|
||||
|
|
||||
import common.Dottable; |
|
||||
|
|
||||
/** |
|
||||
* An AccumulationProduct has ProductStates, where the first component is the |
|
||||
* stateId in the original model, and the second component is the index of an |
|
||||
* AccumulationTracker. |
|
||||
* |
|
||||
* @author Sascha Wunderlich |
|
||||
* |
|
||||
* @param <M> |
|
||||
*/ |
|
||||
|
|
||||
public abstract class AccumulationProductComplex<M extends Model,Component> extends AccumulationProduct<M,Component> implements Dottable |
|
||||
{ |
|
||||
protected final ArrayList<BitSet> initStates; |
|
||||
protected final ArrayList<BitSet> runStates; |
|
||||
protected final ArrayList<BitSet> goalStates; |
|
||||
|
|
||||
public AccumulationProductComplex(M originalModel, AccumulationContext ctx) { |
|
||||
super(originalModel, ctx); |
|
||||
initStates = new ArrayList<>(); |
|
||||
runStates = new ArrayList<>(); |
|
||||
goalStates = new ArrayList<>(); |
|
||||
} |
|
||||
|
|
||||
public final BitSet getInitStates(int track) { |
|
||||
return initStates.get(track); |
|
||||
} |
|
||||
|
|
||||
public final BitSet getRunStates(int track) { |
|
||||
return runStates.get(track); |
|
||||
} |
|
||||
|
|
||||
public final BitSet getGoalStates(int track) { |
|
||||
return goalStates.get(track); |
|
||||
} |
|
||||
|
|
||||
protected void generateTrackInfo(ProductState state, Integer index) throws PrismException { |
|
||||
AccumulationState<Component> accState = accStates.getById(state.getSecondState()); |
|
||||
AccumulationTracker<Component> tracker = accState.getTracker(trackers); |
|
||||
|
|
||||
for(int trackIdx=0; trackIdx<tracker.getTracks().size(); trackIdx++) { |
|
||||
AccumulationTrack<Component> track = tracker.getTracks().get(trackIdx); |
|
||||
|
|
||||
boolean isInitial = trackIdx==accState.lastRestartNr; |
|
||||
boolean isRunning = track != null; |
|
||||
boolean isGoal = accState.getGoodTracks().get(trackIdx); // isGoalTrack(track) |
|
||||
|
|
||||
// Is this an initial |
|
||||
initStates.get(trackIdx).set(index, isInitial); |
|
||||
|
|
||||
// Is this a running track? (Initial tracks are NOT running) |
|
||||
runStates.get(trackIdx).set(index, isRunning && !isInitial); |
|
||||
|
|
||||
// Is this a goal track? |
|
||||
goalStates.get(trackIdx).set(index, isGoal); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected String labelString(Integer stateId) { |
|
||||
StringBuffer result = new StringBuffer(); |
|
||||
|
|
||||
for(int t=0; t<numberOfTracks; t++) { |
|
||||
result.append(" " + t); |
|
||||
if(initStates.get(t).get(stateId)) { result.append("I"); continue; } |
|
||||
if(goalStates.get(t).get(stateId)) { result.append("G"); continue; } |
|
||||
if(runStates.get(t).get(stateId)) { result.append("R"); continue; } |
|
||||
result.append("_"); |
|
||||
} |
|
||||
|
|
||||
return result.toString(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String toDot() { |
|
||||
StringBuffer result = new StringBuffer(); |
|
||||
|
|
||||
result.append("digraph " + originalModel.getModelType() + " {\n"); |
|
||||
|
|
||||
for(int i = 0; i < prod_states.size(); i++) { |
|
||||
ProductState fromState = prod_states.get(i); |
|
||||
AccumulationState<Component> accState = accStates.getById(fromState.getSecondState()); |
|
||||
AccumulationTracker<Component> tracker = accState.getTracker(trackers); |
|
||||
result.append("" |
|
||||
+ i |
|
||||
+ "[shape=box, color=black" |
|
||||
+ " label= < <TABLE BORDER=\"0\">" |
|
||||
+ "<TR>" |
|
||||
+ "<TD>" + i + "=" + fromState + "</TD>" |
|
||||
+ "</TR><TR>" |
|
||||
+ "<TD> " + accState + "</TD>" |
|
||||
+ "</TR><TR>" |
|
||||
+ "<TD> " + labelString(i) + "</TD>" |
|
||||
+ "</TR><TR>" |
|
||||
+ "<TD>\"" + Dottable.quoteForDot(tracker.toString()) + "\"</TD>" |
|
||||
+ "</TR>" |
|
||||
+ " </TABLE> >]\n"); |
|
||||
|
|
||||
switch(productModel.getModelType()) { |
|
||||
case DTMC: |
|
||||
DTMCExplicit castDTMC = (DTMCExplicit)productModel; |
|
||||
Iterator<Map.Entry<Integer, Double>> dtmcIter = castDTMC.getTransitionsIterator(i); |
|
||||
while (dtmcIter.hasNext()) { |
|
||||
Map.Entry<Integer, Double> e = dtmcIter.next(); |
|
||||
result.append(i + " -> " + e.getKey() + " [ label=\""); |
|
||||
result.append(e.getValue() + "\" ];\n"); |
|
||||
} |
|
||||
break; |
|
||||
case MDP: |
|
||||
MDPExplicit castMDP = (MDPExplicit)productModel; |
|
||||
for(int c = 0; c < castMDP.getNumChoices(i); c++) { |
|
||||
Iterator<Map.Entry<Integer, Double>> mdpIter = castMDP.getTransitionsIterator(i, c); |
|
||||
while (mdpIter.hasNext()) { |
|
||||
Map.Entry<Integer, Double> e = mdpIter.next(); |
|
||||
result.append(i + " -> " + e.getKey() + " [ label=\""); |
|
||||
result.append(c + "," + e.getValue() + "\" ];\n"); |
|
||||
} |
|
||||
} |
|
||||
break; |
|
||||
default: |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
result.append("}"); |
|
||||
|
|
||||
return result.toString(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,107 +0,0 @@ |
|||||
package explicit; |
|
||||
|
|
||||
import java.util.BitSet; |
|
||||
import java.util.Iterator; |
|
||||
import java.util.Map; |
|
||||
|
|
||||
import prism.PrismException; |
|
||||
|
|
||||
import common.Dottable; |
|
||||
|
|
||||
/** |
|
||||
* An AccumulationProduct has ProductStates, where the first component is the |
|
||||
* stateId in the original model, and the second component is the index of an |
|
||||
* AccumulationTracker. |
|
||||
* |
|
||||
* @author Sascha Wunderlich |
|
||||
* |
|
||||
* @param <M> |
|
||||
*/ |
|
||||
|
|
||||
public abstract class AccumulationProductSimple<M extends Model,Component> extends AccumulationProduct<M,Component> implements Dottable |
|
||||
{ |
|
||||
protected final BitSet goodStates; |
|
||||
|
|
||||
public AccumulationProductSimple(M originalModel, AccumulationContext ctx) { |
|
||||
super(originalModel, ctx); |
|
||||
goodStates = new BitSet(); |
|
||||
} |
|
||||
|
|
||||
public final BitSet getGoodStates() { |
|
||||
return goodStates; |
|
||||
} |
|
||||
|
|
||||
protected void generateStateInfo(ProductState state, Integer index) throws PrismException { |
|
||||
AccumulationState<Component> accState = accStates.getById(state.getSecondState()); |
|
||||
goodStates.set(index, accState.hasGoodTracks()); |
|
||||
} |
|
||||
|
|
||||
protected String labelString(Integer stateId) { |
|
||||
StringBuffer result = new StringBuffer(); |
|
||||
if(goodStates.get(stateId)) { result.append("G: "); } |
|
||||
|
|
||||
for(int t=0; t<numberOfTracks; t++) { |
|
||||
result.append(" " + t); |
|
||||
if(accStates.getById(prod_states.get(stateId).getSecondState()).getGoodTracks().get(t)) { result.append("+"); continue; } |
|
||||
result.append("_"); |
|
||||
} |
|
||||
|
|
||||
return result.toString(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String toDot() { |
|
||||
StringBuffer result = new StringBuffer(); |
|
||||
|
|
||||
result.append("digraph " + originalModel.getModelType() + " {\n"); |
|
||||
|
|
||||
for(int i = 0; i < prod_states.size(); i++) { |
|
||||
ProductState fromState = prod_states.get(i); |
|
||||
AccumulationState<Component> accState = accStates.getById(fromState.getSecondState()); |
|
||||
AccumulationTracker<Component> tracker = accState.getTracker(trackers); |
|
||||
result.append("" |
|
||||
+ i |
|
||||
+ "[shape=box, color=black" |
|
||||
+ " label= < <TABLE BORDER=\"0\">" |
|
||||
+ "<TR>" |
|
||||
+ "<TD>" + i + "=" + fromState + "</TD>" |
|
||||
+ "</TR><TR>" |
|
||||
+ "<TD> " + accState + "</TD>" |
|
||||
+ "</TR><TR>" |
|
||||
+ "<TD> " + labelString(i) + "</TD>" |
|
||||
+ "</TR><TR>" |
|
||||
+ "<TD>\"" + Dottable.quoteForDot(tracker.toString()) + "\"</TD>" |
|
||||
+ "</TR>" |
|
||||
+ " </TABLE> >]\n"); |
|
||||
|
|
||||
switch(productModel.getModelType()) { |
|
||||
case DTMC: |
|
||||
DTMCExplicit castDTMC = (DTMCExplicit)productModel; |
|
||||
Iterator<Map.Entry<Integer, Double>> dtmcIter = castDTMC.getTransitionsIterator(i); |
|
||||
while (dtmcIter.hasNext()) { |
|
||||
Map.Entry<Integer, Double> e = dtmcIter.next(); |
|
||||
result.append(i + " -> " + e.getKey() + " [ label=\""); |
|
||||
result.append(e.getValue() + "\" ];\n"); |
|
||||
} |
|
||||
break; |
|
||||
case MDP: |
|
||||
MDPExplicit castMDP = (MDPExplicit)productModel; |
|
||||
for(int c = 0; c < castMDP.getNumChoices(i); c++) { |
|
||||
Iterator<Map.Entry<Integer, Double>> mdpIter = castMDP.getTransitionsIterator(i, c); |
|
||||
while (mdpIter.hasNext()) { |
|
||||
Map.Entry<Integer, Double> e = mdpIter.next(); |
|
||||
result.append(i + " -> " + e.getKey() + " [ label=\""); |
|
||||
result.append(c + "," + e.getValue() + "\" ];\n"); |
|
||||
} |
|
||||
} |
|
||||
break; |
|
||||
default: |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
result.append("}"); |
|
||||
|
|
||||
return result.toString(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,195 +0,0 @@ |
|||||
package explicit; |
|
||||
|
|
||||
import java.util.BitSet; |
|
||||
|
|
||||
import explicit.rewards.Rewards; |
|
||||
import prism.IntegerBound; |
|
||||
import prism.PrismException; |
|
||||
|
|
||||
/** |
|
||||
* An AccumulationProduct has ProductStates, where the first component is the |
|
||||
* stateId in the original model, and the second component is the index of an |
|
||||
* AccumulationTracker. |
|
||||
* |
|
||||
* @author Sascha Wunderlich |
|
||||
* |
|
||||
* @param <M> |
|
||||
*/ |
|
||||
|
|
||||
public class AccumulationProductSimpleCounting<M extends Model> extends AccumulationProductSimple<M,Integer> |
|
||||
{ |
|
||||
|
|
||||
public AccumulationProductSimpleCounting(M originalModel, AccumulationContext ctx) { |
|
||||
super(originalModel, ctx); |
|
||||
} |
|
||||
|
|
||||
@SuppressWarnings("unchecked") |
|
||||
public static <T extends Model, R extends Rewards> AccumulationProductSimpleCounting<T> generate(final Model graph, AccumulationContext ctx, BitSet statesOfInterest) throws PrismException { |
|
||||
switch(graph.getModelType()) { |
|
||||
case DTMC: |
|
||||
return (AccumulationProductSimpleCounting<T>)generate((DTMC) graph, ctx, statesOfInterest); |
|
||||
case MDP: |
|
||||
return (AccumulationProductSimpleCounting<T>)generate((MDP) graph, ctx, statesOfInterest); |
|
||||
default: |
|
||||
throw new PrismException("Can't handle accumulation product for " + graph.getModelType()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public static AccumulationProductSimpleCounting<DTMC> generate(final DTMC graph, AccumulationContext ctx, BitSet statesOfInterest) throws PrismException { |
|
||||
final AccumulationProductSimpleCounting<DTMC> result = new AccumulationProductSimpleCounting<DTMC>(graph,ctx); |
|
||||
// Create auxiliary data |
|
||||
result.createAuxData(graph); |
|
||||
|
|
||||
// Build an operator |
|
||||
class AccumulationDTMCProductOperator implements DTMCProductOperator |
|
||||
{ |
|
||||
@Override |
|
||||
public ProductState getInitialState(Integer dtmc_state) |
|
||||
throws PrismException { |
|
||||
int initialAccStateId = result.createInitialStateId(); |
|
||||
return new ProductState(dtmc_state, initialAccStateId); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public ProductState getSuccessor(ProductState from_state, Integer dtmc_to_state) throws PrismException { |
|
||||
// Get the current accumulation state |
|
||||
AccumulationState<Integer> from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
||||
|
|
||||
// Get step weights |
|
||||
double[] weights = ctx.getWeights(from_state.getFirstState()); |
|
||||
|
|
||||
// Update accumulation product state, store it and get its ID. |
|
||||
AccumulationState<Integer> to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, weights); |
|
||||
int to_accproduct_id = result.accStates.findOrAdd(to_accproduct); |
|
||||
|
|
||||
return new ProductState(dtmc_to_state, to_accproduct_id); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void notify(ProductState state, Integer index) |
|
||||
throws PrismException { |
|
||||
result.generateStateInfo(state, index); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void finish() throws PrismException { |
|
||||
// Do nothing |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public DTMC getGraph() { |
|
||||
return graph; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Apply the operator |
|
||||
AccumulationDTMCProductOperator op = new AccumulationDTMCProductOperator(); |
|
||||
ProductWithProductStates.generate(op, result, statesOfInterest); |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
public static AccumulationProductSimpleCounting<MDP> generate(final MDP graph, AccumulationContext ctx, BitSet statesOfInterest) throws PrismException { |
|
||||
// This is basically the same thing as for DTMCs |
|
||||
final AccumulationProductSimpleCounting<MDP> result = new AccumulationProductSimpleCounting<MDP>(graph, ctx); |
|
||||
|
|
||||
// Create auxiliary data |
|
||||
result.createAuxData(graph); |
|
||||
|
|
||||
class AccumulationMDPProductOperator implements MDPProductOperator |
|
||||
{ |
|
||||
|
|
||||
@Override |
|
||||
public ProductState getInitialState(final Integer MDP_state) |
|
||||
throws PrismException { |
|
||||
int initialAccStateId = result.createInitialStateId(); |
|
||||
return new ProductState(MDP_state, initialAccStateId); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public ProductState getSuccessor(final ProductState from_state, final int choice_i, final Integer mdp_to_state) throws PrismException { |
|
||||
// Get the current accumulation state |
|
||||
AccumulationState<Integer> from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
||||
|
|
||||
// Get step weights |
|
||||
// THIS IS DIFFERENT FROM ABOVE! |
|
||||
double[] weights = ctx.getWeights(from_state.getFirstState(), choice_i); |
|
||||
|
|
||||
// Update accumulation product state, store it and get its ID. |
|
||||
AccumulationState<Integer> to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, weights); |
|
||||
int to_accproduct_id = result.accStates.findOrAdd(to_accproduct); |
|
||||
return new ProductState(mdp_to_state, to_accproduct_id); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void notify(final ProductState state, final Integer index) |
|
||||
throws PrismException { |
|
||||
result.generateStateInfo(state, index); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void finish() throws PrismException { |
|
||||
// Do nothing |
|
||||
//mc.getLog().println("."); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public MDP getGraph() { |
|
||||
return graph; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
AccumulationMDPProductOperator op = new AccumulationMDPProductOperator(); |
|
||||
ProductWithProductStates.generate(op, result, statesOfInterest); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected boolean isFinalTrack(final AccumulationTrack<Integer> track) throws PrismException { |
|
||||
boolean isFinal = false; |
|
||||
if ( track != null ) { |
|
||||
Integer step = track.getComponent(); |
|
||||
if ( step > 0 ) { // if the step is 0, we cannot have a goal state. |
|
||||
IntegerBound stepBound = IntegerBound.fromTemporalOperatorBound(ctx.accexp.getBoundExpression(), ctx.mc.getConstantValues(), true); |
|
||||
isFinal = stepBound.isInBounds(step); |
|
||||
} |
|
||||
} |
|
||||
return isFinal; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected Integer getInitialComponent() { |
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected Integer updateComponent(Integer modelFromStateId, final AccumulationTrack<Integer> track) { |
|
||||
int currentStep = track.getComponent(); |
|
||||
|
|
||||
int maxStep = 0; |
|
||||
try { |
|
||||
maxStep = IntegerBound.fromTemporalOperatorBound(ctx.accexp.getBoundExpression(), ctx.mc.getConstantValues(), true).getHighestInteger(); |
|
||||
} catch(PrismException e) { |
|
||||
throw new RuntimeException("..."); |
|
||||
} |
|
||||
|
|
||||
int nextStep = currentStep+1; |
|
||||
if(nextStep > maxStep) { return null; } |
|
||||
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(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,228 +0,0 @@ |
|||||
package explicit; |
|
||||
|
|
||||
import java.util.ArrayList; |
|
||||
import java.util.BitSet; |
|
||||
|
|
||||
import automata.finite.DeterministicFiniteAutomaton; |
|
||||
import automata.finite.EdgeLabel; |
|
||||
import automata.finite.NondeterministicFiniteAutomaton; |
|
||||
import automata.finite.State; |
|
||||
import explicit.rewards.Rewards; |
|
||||
import parser.ast.ExpressionRegular; |
|
||||
import prism.PrismException; |
|
||||
import prism.PrismSettings; |
|
||||
|
|
||||
/** |
|
||||
* An AccumulationProduct has ProductStates, where the first component is the |
|
||||
* stateId in the original model, and the second component is the index of an |
|
||||
* AccumulationTracker. |
|
||||
* |
|
||||
* @author Sascha Wunderlich |
|
||||
* |
|
||||
* @param <M> |
|
||||
*/ |
|
||||
|
|
||||
public class AccumulationProductSimpleRegular<M extends Model> extends AccumulationProductSimple<M,State> |
|
||||
{ |
|
||||
protected DeterministicFiniteAutomaton<String> automaton; |
|
||||
|
|
||||
public AccumulationProductSimpleRegular(M originalModel, AccumulationContext ctx) { |
|
||||
super(originalModel, ctx); |
|
||||
} |
|
||||
|
|
||||
@SuppressWarnings("unchecked") |
|
||||
public static <T extends Model, R extends Rewards> AccumulationProductSimpleRegular<T> generate(final Model graph, AccumulationContext ctx, BitSet statesOfInterest) throws PrismException { |
|
||||
switch(graph.getModelType()) { |
|
||||
case DTMC: |
|
||||
return (AccumulationProductSimpleRegular<T>)generate((DTMC) graph, ctx, statesOfInterest); |
|
||||
case MDP: |
|
||||
return (AccumulationProductSimpleRegular<T>)generate((MDP) graph, ctx, statesOfInterest); |
|
||||
default: |
|
||||
throw new PrismException("Can't handle accumulation product for " + graph.getModelType()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public static AccumulationProductSimpleRegular<DTMC> generate(final DTMC graph, AccumulationContext ctx, BitSet statesOfInterest) throws PrismException { |
|
||||
final AccumulationProductSimpleRegular<DTMC> result = new AccumulationProductSimpleRegular<DTMC>(graph, ctx); |
|
||||
// Create auxiliary data |
|
||||
result.createAuxData(graph); |
|
||||
|
|
||||
// Build an operator |
|
||||
class AccumulationDTMCProductOperator implements DTMCProductOperator |
|
||||
{ |
|
||||
@Override |
|
||||
public ProductState getInitialState(Integer dtmc_state) |
|
||||
throws PrismException { |
|
||||
int initialAccStateId = result.createInitialStateId(); |
|
||||
return new ProductState(dtmc_state, initialAccStateId); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public ProductState getSuccessor(ProductState from_state, |
|
||||
Integer dtmc_to_state) throws PrismException { |
|
||||
// Get the current accumulation state |
|
||||
AccumulationState<State> from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
||||
|
|
||||
// Get step weights |
|
||||
double[] weights = ctx.getWeights(from_state.getFirstState()); |
|
||||
|
|
||||
// Update accumulation product state, store it and get its ID. |
|
||||
AccumulationState<State> to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, weights); |
|
||||
int to_accproduct_id = result.accStates.findOrAdd(to_accproduct); |
|
||||
|
|
||||
return new ProductState(dtmc_to_state, to_accproduct_id); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void notify(ProductState state, Integer index) |
|
||||
throws PrismException { |
|
||||
result.generateStateInfo(state, index); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void finish() throws PrismException { |
|
||||
// Do nothing |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public DTMC getGraph() { |
|
||||
return graph; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Apply the operator |
|
||||
AccumulationDTMCProductOperator op = new AccumulationDTMCProductOperator(); |
|
||||
ProductWithProductStates.generate(op, result, statesOfInterest); |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
public static AccumulationProductSimpleRegular<MDP> generate(final MDP graph, AccumulationContext ctx, BitSet statesOfInterest) throws PrismException { |
|
||||
// This is basically the same thing as for DTMCs |
|
||||
final AccumulationProductSimpleRegular<MDP> result = new AccumulationProductSimpleRegular<MDP>(graph, ctx); |
|
||||
|
|
||||
// Create auxiliary data |
|
||||
result.createAuxData(graph); |
|
||||
|
|
||||
class AccumulationMDPProductOperator implements MDPProductOperator |
|
||||
{ |
|
||||
|
|
||||
@Override |
|
||||
public ProductState getInitialState(final Integer MDP_state) |
|
||||
throws PrismException { |
|
||||
int initialAccStateId = result.createInitialStateId(); |
|
||||
return new ProductState(MDP_state, initialAccStateId); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public ProductState getSuccessor(final ProductState from_state, |
|
||||
final int choice_i, final Integer mdp_to_state) throws PrismException { |
|
||||
// Get the current accumulation state |
|
||||
AccumulationState<State> from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
||||
|
|
||||
// Get step weights |
|
||||
double[] weights = ctx.getWeights(from_state.getFirstState(), choice_i); |
|
||||
|
|
||||
// Update accumulation product state, store it and get its ID. |
|
||||
AccumulationState<State> to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, weights); |
|
||||
int to_accproduct_id = result.accStates.findOrAdd(to_accproduct); |
|
||||
return new ProductState(mdp_to_state, to_accproduct_id); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void notify(final ProductState state, final Integer index) |
|
||||
throws PrismException { |
|
||||
result.generateStateInfo(state, index); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void finish() throws PrismException { |
|
||||
// Do nothing |
|
||||
//mc.getLog().println("."); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public MDP getGraph() { |
|
||||
return graph; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
AccumulationMDPProductOperator op = new AccumulationMDPProductOperator(); |
|
||||
ProductWithProductStates.generate(op, result, statesOfInterest); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected boolean isFinalTrack(AccumulationTrack<State> track) throws PrismException { |
|
||||
boolean isFinal = false; |
|
||||
if ( track != null ) { |
|
||||
isFinal = automaton.isAcceptingState(track.getComponent()); |
|
||||
} |
|
||||
|
|
||||
return isFinal; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected State getInitialComponent() { |
|
||||
return automaton.getInitialState(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected State updateComponent(Integer modelFromStateId, final AccumulationTrack<State> track) { |
|
||||
State currentState = track.getComponent(); |
|
||||
|
|
||||
// Build EdgeLabel from labels. |
|
||||
// labels is a BitSet with labels L0,...,Ln |
|
||||
ArrayList<String> edgeSymbols = new ArrayList<>(); |
|
||||
BitSet edgeValues = new BitSet(); |
|
||||
|
|
||||
for (int i=0; i < labels.size(); i++) { |
|
||||
// Each bitLabel contains one L |
|
||||
edgeSymbols.add(i, "L"+i); |
|
||||
if(labels.get(i).get(modelFromStateId)) { |
|
||||
edgeValues.set(i); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
EdgeLabel<String> edgeLabel = new EdgeLabel<>(edgeSymbols, edgeValues); |
|
||||
|
|
||||
State nextState = automaton.getSuccessor(currentState,edgeLabel); |
|
||||
if(nextState == null) { return null; } |
|
||||
return nextState; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 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 { |
|
||||
// Build labels and DFA |
|
||||
AccumulationModelChecker accMc = new AccumulationModelChecker(); |
|
||||
ExpressionRegular reg = (ExpressionRegular)accMc.checkMaximalStateFormulas((ProbModelChecker) ctx.mc, graph, ctx.accexp.getRegularExpression(), labels); |
|
||||
|
|
||||
// Create and store the actual DFA |
|
||||
NondeterministicFiniteAutomaton<String> nfa = NondeterministicFiniteAutomaton.fromExpressionRegular(reg); |
|
||||
//System.out.println(nfa.toDot()); |
|
||||
|
|
||||
automaton = nfa.determinize(); |
|
||||
automaton.trim(); // This should remove cycles. |
|
||||
|
|
||||
if(ctx.mc.getSettings().getBoolean(PrismSettings.ACC_GENERATE_DOTS)) { |
|
||||
nfa.exportToDotFile("DEBUG-automaton-nfa.dot"); |
|
||||
automaton.exportToDotFile("DEBUG-automaton-dfa.dot"); |
|
||||
} |
|
||||
|
|
||||
if (!automaton.isAcyclic()) { |
|
||||
throw new PrismException("Cannot handle cyclic automata!"); |
|
||||
} |
|
||||
|
|
||||
numberOfTracks = automaton.getLongestPathLength()+1; |
|
||||
numberOfWeights= ctx.rewards.size(); |
|
||||
} |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue