|
|
|
@ -10,6 +10,7 @@ import automata.finite.NondeterministicFiniteAutomaton; |
|
|
|
import automata.finite.State; |
|
|
|
import explicit.rewards.MCRewards; |
|
|
|
import explicit.rewards.MDPRewards; |
|
|
|
import explicit.rewards.Rewards; |
|
|
|
import parser.ast.AccumulationFactor; |
|
|
|
import parser.ast.ExpressionAccumulation; |
|
|
|
import parser.ast.ExpressionRegular; |
|
|
|
@ -37,7 +38,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
public static AccumulationProductRegular<DTMC> generate(final DTMC graph, final ExpressionAccumulation accexp, final Vector<MCRewards> rewards, final ProbModelChecker mc, BitSet statesOfInterest) throws PrismException { |
|
|
|
final AccumulationProductRegular<DTMC> result = new AccumulationProductRegular<DTMC>(graph); |
|
|
|
// Create auxiliary data |
|
|
|
result.createAuxData(graph, accexp, mc); |
|
|
|
result.createAuxData(graph, accexp, rewards, mc); |
|
|
|
|
|
|
|
// Build an operator |
|
|
|
class AccumulationDTMCProductOperator implements DTMCProductOperator |
|
|
|
@ -53,7 +54,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
public ProductState getSuccessor(ProductState from_state, |
|
|
|
Integer dtmc_to_state) throws PrismException { |
|
|
|
// Get the current accumulation state |
|
|
|
AccumulationState from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
|
|
AccumulationState<State> from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
|
|
|
|
|
|
// Get step weights |
|
|
|
double[] weights = new double[rewards.size()]; |
|
|
|
@ -63,7 +64,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
} |
|
|
|
|
|
|
|
// Update accumulation product state, store it and get its ID. |
|
|
|
AccumulationState to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, accexp, weights, mc); |
|
|
|
AccumulationState<State> to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, accexp, weights, mc); |
|
|
|
int to_accproduct_id = result.accStates.findOrAdd(to_accproduct); |
|
|
|
|
|
|
|
return new ProductState(dtmc_to_state, to_accproduct_id); |
|
|
|
@ -72,7 +73,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
@Override |
|
|
|
public void notify(ProductState state, Integer index) |
|
|
|
throws PrismException { |
|
|
|
AccumulationState accState = result.accStates.getById(state.getSecondState()); |
|
|
|
AccumulationState<State> accState = result.accStates.getById(state.getSecondState()); |
|
|
|
if (result.isGoodAccState(accState, accexp, mc)) { |
|
|
|
result.goodStates.set(index); |
|
|
|
} |
|
|
|
@ -101,7 +102,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
final AccumulationProductRegular<MDP> result = new AccumulationProductRegular<MDP>(graph); |
|
|
|
|
|
|
|
// Create auxiliary data |
|
|
|
result.createAuxData(graph, accexp, mc); |
|
|
|
result.createAuxData(graph, accexp, rewards, mc); |
|
|
|
|
|
|
|
class AccumulationMDPProductOperator implements MDPProductOperator |
|
|
|
{ |
|
|
|
@ -117,7 +118,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
public ProductState getSuccessor(ProductState from_state, |
|
|
|
int choice_i, Integer mdp_to_state) throws PrismException { |
|
|
|
// Get the current accumulation state |
|
|
|
AccumulationState from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
|
|
AccumulationState<State> from_accstate = result.accStates.getById(from_state.getSecondState()); |
|
|
|
|
|
|
|
// Get step weights |
|
|
|
// THIS IS DIFFERENT FROM ABOVE! |
|
|
|
@ -130,7 +131,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
} |
|
|
|
|
|
|
|
// Update accumulation product state, store it and get its ID. |
|
|
|
AccumulationState to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, accexp, weights, mc); |
|
|
|
AccumulationState<State> to_accproduct = result.updateAccumulationState(from_state.getFirstState(), from_accstate, accexp, weights, mc); |
|
|
|
int to_accproduct_id = result.accStates.findOrAdd(to_accproduct); |
|
|
|
|
|
|
|
return new ProductState(mdp_to_state, to_accproduct_id); |
|
|
|
@ -139,7 +140,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
@Override |
|
|
|
public void notify(ProductState state, Integer index) |
|
|
|
throws PrismException { |
|
|
|
AccumulationState accState = result.accStates.getById(state.getSecondState()); |
|
|
|
AccumulationState<State> accState = result.accStates.getById(state.getSecondState()); |
|
|
|
if (result.isGoodAccState(accState, accexp, mc)) { |
|
|
|
result.goodStates.set(index); |
|
|
|
} |
|
|
|
@ -171,14 +172,14 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
return isFinal; |
|
|
|
} |
|
|
|
|
|
|
|
private boolean isGoodAccState(AccumulationState state, ExpressionAccumulation accexp, ProbModelChecker mc) throws PrismException { |
|
|
|
//TODO: fill me! |
|
|
|
return false; |
|
|
|
private boolean isGoodAccState(AccumulationState<State> state, ExpressionAccumulation accexp, ProbModelChecker mc) throws PrismException { |
|
|
|
return state.hasGoodTrack(); |
|
|
|
} |
|
|
|
|
|
|
|
private boolean isGoodTrack(AccumulationTrack<State> track, ExpressionAccumulation accexp, ProbModelChecker mc) throws PrismException { |
|
|
|
//System.out.println("Checking " + track + " for goodness..."); |
|
|
|
mc.getLog().println("Checking " + track + " for goodness..."); |
|
|
|
// Only final tracks can be good |
|
|
|
mc.getLog().println("Final? " + isFinalTrack(track,accexp,mc)); |
|
|
|
if (!isFinalTrack(track,accexp,mc)) { return false; } |
|
|
|
boolean isGood = false; |
|
|
|
|
|
|
|
@ -214,13 +215,13 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
throw new RuntimeException("Oh boy!"); |
|
|
|
} |
|
|
|
|
|
|
|
//System.out.println("Good? " + isGood); |
|
|
|
mc.getLog().println("Good? " + lhs + rhs + " : " + isGood); |
|
|
|
|
|
|
|
return isGood; |
|
|
|
} |
|
|
|
|
|
|
|
private AccumulationState updateAccumulationState(final int modelFromStateId, |
|
|
|
final AccumulationState accstate, final ExpressionAccumulation accexp, |
|
|
|
private AccumulationState<State> updateAccumulationState(final int modelFromStateId, |
|
|
|
final AccumulationState<State> accstate, final ExpressionAccumulation accexp, |
|
|
|
final double[] weights, final ProbModelChecker mc) throws PrismException { |
|
|
|
// We have the current accumulation state, the current model id and the accumulation expression. |
|
|
|
|
|
|
|
@ -268,7 +269,7 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
|
|
|
|
int newTrackerId = trackers.findOrAdd(newTracker); |
|
|
|
|
|
|
|
return new AccumulationState(newTrackerId, newLastRestartNr, numberOfTracks, newGoodTracks); |
|
|
|
return new AccumulationState<State>(newTrackerId, newLastRestartNr, numberOfTracks, newGoodTracks); |
|
|
|
} |
|
|
|
private AccumulationTrack<State> updateTrackRegular(Integer modelFromStateId, AccumulationTrack<State> track, ExpressionAccumulation accexp, double[] weights, StateModelChecker mc) { |
|
|
|
State currentState = track.getComponent(); |
|
|
|
@ -313,15 +314,25 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
BitSet initialGoodTracks = new BitSet(); |
|
|
|
|
|
|
|
// Generate the initial track and product state |
|
|
|
AccumulationTracker<State> initialTracker = new AccumulationTracker<>(numberOfTracks, numberOfRewards, initialState); |
|
|
|
AccumulationTracker<State> initialTracker = new AccumulationTracker<State>(numberOfTracks, numberOfRewards, initialState); |
|
|
|
int initialTrackerId = trackers.findOrAdd(initialTracker); |
|
|
|
AccumulationState initialAccState = new AccumulationState(initialTrackerId, initialActiveTrack, numberOfTracks, initialGoodTracks); |
|
|
|
AccumulationState<State> initialAccState = new AccumulationState<State>(initialTrackerId, initialActiveTrack, numberOfTracks, initialGoodTracks); |
|
|
|
int initialAccStateId = accStates.findOrAdd(initialAccState); |
|
|
|
|
|
|
|
return initialAccStateId; |
|
|
|
} |
|
|
|
|
|
|
|
public void createAuxData(final Model graph, final ExpressionAccumulation accexp, final ProbModelChecker mc) throws PrismException { |
|
|
|
/** |
|
|
|
* Populates fields: |
|
|
|
* - automaton with a trimmed deterministic finite automaton and |
|
|
|
* - numberOfTracks with the length of its longest path. |
|
|
|
* |
|
|
|
* @param graph |
|
|
|
* @param accexp |
|
|
|
* @param mc |
|
|
|
* @throws PrismException |
|
|
|
*/ |
|
|
|
public void createAuxData(final Model graph, final ExpressionAccumulation accexp, final Vector<? extends Rewards> rewards, final ProbModelChecker mc) throws PrismException { |
|
|
|
mc.getLog().println(" [AP] generating aux data for " + graph + "\n and " + accexp); |
|
|
|
// Build labels and DFA |
|
|
|
AccumulationModelChecker accMc = new AccumulationModelChecker(); |
|
|
|
@ -334,12 +345,15 @@ public class AccumulationProductRegular<M extends Model> extends AccumulationPro |
|
|
|
automaton = nfa.determinize(); |
|
|
|
automaton.trim(); // This should remove cycles. |
|
|
|
|
|
|
|
System.out.println(nfa.toDot()); |
|
|
|
nfa.exportToDotFile("DEBUG-automaton-nfa.dot"); |
|
|
|
|
|
|
|
if (!automaton.isAcyclic()) { |
|
|
|
throw new PrismException("Cannot handle cyclic automata!"); |
|
|
|
} |
|
|
|
|
|
|
|
numberOfTracks = automaton.getLongestPathLength(); |
|
|
|
numberOfTracks = automaton.getLongestPathLength()+1; |
|
|
|
mc.getLog().println(" [AP] tracks: " + numberOfTracks); |
|
|
|
numberOfWeights= rewards.size(); |
|
|
|
mc.getLog().println(" [AP] weights: " + numberOfWeights); |
|
|
|
} |
|
|
|
} |