You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
7.7 KiB
204 lines
7.7 KiB
package explicit;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.BitSet;
|
|
import java.util.HashMap;
|
|
|
|
import common.StopWatch;
|
|
import explicit.rewards.ConstructRewards;
|
|
import explicit.rewards.Rewards;
|
|
import parser.ast.Expression;
|
|
import parser.ast.ExpressionAccumulation;
|
|
import parser.ast.ExpressionReward;
|
|
import parser.ast.RewardStruct;
|
|
import parser.visitor.ReplaceAccumulationExpressionComplex;
|
|
import parser.visitor.ReplaceAccumulationExpressionSimple;
|
|
import parser.visitor.ASTVisitor;
|
|
import parser.visitor.ReplaceAccumulationBox;
|
|
import prism.PrismException;
|
|
import prism.PrismSettings;
|
|
|
|
public class AccumulationTransformation<M extends ModelExplicit> implements ModelExpressionTransformation<M, M> {
|
|
final protected Expression originalExpression;
|
|
final protected M originalModel;
|
|
final protected BitSet statesOfInterest;
|
|
final protected StateModelChecker mc;
|
|
|
|
protected Expression transformedExpression;
|
|
protected AccumulationProduct<M,?> product;
|
|
|
|
ArrayList<String> initLabels;
|
|
ArrayList<String> runLabels;
|
|
ArrayList<String> goalLabels;
|
|
|
|
public AccumulationTransformation(
|
|
StateModelChecker mc,
|
|
M originalModel, Expression expr,
|
|
BitSet statesOfInterest, boolean forceComplex) throws PrismException{
|
|
super();
|
|
this.originalExpression = expr;
|
|
this.originalModel = originalModel;
|
|
this.mc = mc;
|
|
this.statesOfInterest = statesOfInterest;
|
|
|
|
this.initLabels = new ArrayList<>();
|
|
this.runLabels = new ArrayList<>();
|
|
this.goalLabels = new ArrayList<>();
|
|
|
|
doTransformation(forceComplex);
|
|
}
|
|
|
|
|
|
public AccumulationTransformation(
|
|
StateModelChecker mc,
|
|
M originalModel, Expression expr,
|
|
BitSet statesOfInterest) throws PrismException{
|
|
this(mc, originalModel, expr, statesOfInterest, false);
|
|
}
|
|
|
|
@Override
|
|
public M getOriginalModel() {
|
|
return originalModel;
|
|
}
|
|
@Override
|
|
public Expression getTransformedExpression() {
|
|
return transformedExpression;
|
|
}
|
|
@Override
|
|
public Expression getOriginalExpression() {
|
|
return originalExpression;
|
|
}
|
|
|
|
@Override
|
|
public BitSet getTransformedStatesOfInterest() {
|
|
return product.getTransformedStatesOfInterest();
|
|
}
|
|
|
|
@Override
|
|
public M getTransformedModel() {
|
|
return product.getTransformedModel();
|
|
}
|
|
@Override
|
|
public StateValues projectToOriginalModel(StateValues svTransformedModel)
|
|
throws PrismException {
|
|
return product.projectToOriginalModel(svTransformedModel);
|
|
}
|
|
|
|
protected void doTransformation(boolean forceComplexFlag) throws PrismException {
|
|
StopWatch clock = new StopWatch(mc.getLog());
|
|
|
|
mc.getLog().println("Handling maximal state formulas...");
|
|
transformedExpression = mc.handleMaximalStateFormulas(originalModel, originalExpression);
|
|
|
|
// Get the first ExpressionAccumulation
|
|
mc.getLog().println("Looking for an accumulation formula...");
|
|
|
|
boolean isSingleTrack = true;
|
|
ExpressionAccumulation accexp = transformedExpression.getFirstAccumulationExpressionWithoutTemporal();
|
|
if(accexp == null || mc.getSettings().getBoolean(PrismSettings.ACC_FORCE_MULTI)) {
|
|
isSingleTrack = false;
|
|
accexp = transformedExpression.getFirstAccumulationExpression();
|
|
}
|
|
|
|
mc.getLog().println("... found " + accexp);
|
|
|
|
// Rewrite it, if it is a BOX
|
|
if (accexp.getSymbol().isBox()) {
|
|
ReplaceAccumulationBox replace = new ReplaceAccumulationBox(accexp);
|
|
transformedExpression = (Expression)transformedExpression.accept(replace);
|
|
accexp = transformedExpression.getFirstAccumulationExpression();
|
|
mc.getLog().println("... after unboxing: " + accexp + " (in " + transformedExpression + ")");
|
|
}
|
|
|
|
// Get the rewards
|
|
HashMap<Object, Rewards> rewards = new HashMap<Object, Rewards>();
|
|
|
|
for (int i=0; i < accexp.getFunctions().size(); i++) {
|
|
Object rewardIndex = accexp.getFunctions().get(i).getRewardIndex();
|
|
|
|
RewardStruct rewStruct = ExpressionReward.getRewardStructByIndexObject(rewardIndex, mc.modulesFile, originalModel.getConstantValues());
|
|
ConstructRewards constructRewards = new ConstructRewards();
|
|
constructRewards.allowNegativeRewards();
|
|
|
|
Rewards reward = constructRewards.buildRewardStructure(originalModel, rewStruct, mc.getConstantValues());
|
|
rewards.put(rewardIndex,reward);
|
|
}
|
|
|
|
// Figure out if we need a complex or a simple trafo...
|
|
//boolean isSimple = !accexp.hasFireOn() && accexp.isNullary();
|
|
boolean isSimple = accexp.isNullary();
|
|
boolean isFiltered = accexp.hasRecordSet();
|
|
boolean isPast = accexp.getSymbol().isMinus();
|
|
boolean forceComplex = mc.getSettings().getBoolean(PrismSettings.ACC_FORCE_COMPLEX) || forceComplexFlag;
|
|
boolean forceMulti = mc.getSettings().getBoolean(PrismSettings.ACC_FORCE_MULTI);
|
|
boolean forceUntil = mc.getSettings().getBoolean(PrismSettings.ACC_FORCE_UNTIL);
|
|
|
|
if(forceComplex && isPast) {
|
|
throw new PrismException("Unable to handle <->/[-] with -accforcecomplex. Bailing.");
|
|
}
|
|
|
|
// Build the AccumulationContext
|
|
AccumulationContext ctx = new AccumulationContext(accexp, rewards, mc);
|
|
ctx.singleTrack = isSingleTrack && !forceMulti;
|
|
ctx.simpleMethod = isSimple && !forceComplex;
|
|
ctx.reachConstr = (!isSimple || !isFiltered) && !forceUntil;
|
|
|
|
mc.getLog().print("Context flags: ");
|
|
if(ctx.singleTrack) { mc.getLog().print(" singleTrack "); }
|
|
if(ctx.simpleMethod) { mc.getLog().print(" simpleMethod "); }
|
|
if(ctx.reachConstr) { mc.getLog().print(" reachConstr" ); }
|
|
mc.getLog().println();
|
|
|
|
// Build the product
|
|
clock.start("accumulation product construction");
|
|
if(ctx.accexp.hasRegularExpression()) {
|
|
product = AccumulationProductRegular.generate(originalModel, ctx, statesOfInterest);
|
|
} else if (ctx.accexp.hasBoundExpression()) {
|
|
product = AccumulationProductCounting.generate(originalModel, ctx, statesOfInterest);
|
|
} else {
|
|
throw new PrismException("Accumulation Expression has no valid monitor!");
|
|
}
|
|
clock.stop(product.getTransformedModel().getNumStates() + " states");
|
|
|
|
// Attach labels
|
|
clock.start("attaching labels");
|
|
|
|
if(ctx.simpleMethod) {
|
|
BitSet goodStates = product.getGoalStates(0);
|
|
String goodLabel = ((ModelExplicit)product.getTransformedModel()).addUniqueLabel("goal", goodStates, product.getTransformedModel().getLabels());
|
|
|
|
goalLabels.add(goodLabel);
|
|
} else {
|
|
for(int track=0; track < product.getNumberOfTracks(); track++) {
|
|
BitSet initStates = product.getInitStates(track);
|
|
BitSet runStates = product.getRunStates(track);
|
|
BitSet goalStates = product.getGoalStates(track);
|
|
|
|
String initLabel = ((ModelExplicit)product.getTransformedModel()).addUniqueLabel("init" + track, initStates, product.getTransformedModel().getLabels());
|
|
initLabels.add(initLabel);
|
|
String runLabel = ((ModelExplicit)product.getTransformedModel()).addUniqueLabel("run" + track, runStates, product.getTransformedModel().getLabels());
|
|
runLabels.add(runLabel);
|
|
String goalLabel = ((ModelExplicit)product.getTransformedModel()).addUniqueLabel("goal" + track, goalStates, product.getTransformedModel().getLabels());
|
|
goalLabels.add(goalLabel);
|
|
}
|
|
}
|
|
|
|
clock.stop(initLabels.size() + "/" + runLabels.size() + "/" + goalLabels.size() + " labels");
|
|
|
|
// Transform the expression
|
|
clock.start("replacing formula");
|
|
ASTVisitor replace;
|
|
if(ctx.simpleMethod) {
|
|
replace = new ReplaceAccumulationExpressionSimple(ctx.accexp, goalLabels.get(0), product.getAccumulationLength(), product.getNumberOfTracks(), ctx.reachConstr);
|
|
} else {
|
|
replace = new ReplaceAccumulationExpressionComplex(ctx.accexp, initLabels, runLabels, goalLabels, product.getAccumulationLength(), product.getNumberOfTracks());
|
|
}
|
|
transformedExpression = (Expression)transformedExpression.accept(replace);
|
|
clock.stop("got " + transformedExpression);
|
|
//clock.stop();
|
|
|
|
if(mc.getSettings().getBoolean(PrismSettings.ACC_GENERATE_DOTS)) {
|
|
product.exportToDotFile("DEBUG-product.dot");
|
|
}
|
|
}
|
|
}
|