From 56d17c40a4ac8d13646213fa58e91a2adbd76bab Mon Sep 17 00:00:00 2001 From: Dave Parker Date: Sun, 7 Feb 2021 11:57:09 +0000 Subject: [PATCH 01/11] MDP solution via linear programming (reach probs/rewards) for explicit engine. Uses the built-in lpsolve library. Not particularly efficient, but a useful reference. --- .../mdps/reach/mdp_simple.nm.props.args | 1 + .../mdps/rewards/rewpoliter.nm.props.args | 1 + prism-tests/pmc/lec13and14mdp.nm | 5 + prism-tests/pmc/lec13and14mdp.nm.props | 5 + prism/src/explicit/MDPModelChecker.java | 273 +++++++++++++++++- 5 files changed, 278 insertions(+), 7 deletions(-) diff --git a/prism-tests/functionality/verify/mdps/reach/mdp_simple.nm.props.args b/prism-tests/functionality/verify/mdps/reach/mdp_simple.nm.props.args index fecd1a44ec..eef11583d8 100644 --- a/prism-tests/functionality/verify/mdps/reach/mdp_simple.nm.props.args +++ b/prism-tests/functionality/verify/mdps/reach/mdp_simple.nm.props.args @@ -5,6 +5,7 @@ -ex -gs -ex -politer -ex -modpoliter +-ex -lp -s -ii -m -ii -h -ii diff --git a/prism-tests/functionality/verify/mdps/rewards/rewpoliter.nm.props.args b/prism-tests/functionality/verify/mdps/rewards/rewpoliter.nm.props.args index a07d393efe..8ac1eeed3b 100644 --- a/prism-tests/functionality/verify/mdps/rewards/rewpoliter.nm.props.args +++ b/prism-tests/functionality/verify/mdps/rewards/rewpoliter.nm.props.args @@ -4,3 +4,4 @@ -valiter -h -valiter -ex -gs -ex +-gs -lp diff --git a/prism-tests/pmc/lec13and14mdp.nm b/prism-tests/pmc/lec13and14mdp.nm index 3a450e896a..92180962c4 100644 --- a/prism-tests/pmc/lec13and14mdp.nm +++ b/prism-tests/pmc/lec13and14mdp.nm @@ -16,3 +16,8 @@ s:[0..3]; endmodule label "a" = s=2; + +rewards + [] true : 0.6; + true : 0.4; +endrewards diff --git a/prism-tests/pmc/lec13and14mdp.nm.props b/prism-tests/pmc/lec13and14mdp.nm.props index 39c31250a9..a7ce9916ea 100644 --- a/prism-tests/pmc/lec13and14mdp.nm.props +++ b/prism-tests/pmc/lec13and14mdp.nm.props @@ -12,3 +12,8 @@ filter(forall, P<0.1 [ F "a" ] <=> false); // RESULT: true filter(forall, P>0 [ F "a" ] <=> (s=0|s=1|s=2)); + + // RESULT: 5/3 + Rmin=? [ F "a" ]; + // RESULT: Infinity + Rmax=? [ F "a" ]; diff --git a/prism/src/explicit/MDPModelChecker.java b/prism/src/explicit/MDPModelChecker.java index 8226c19b06..d3b1ab5394 100644 --- a/prism/src/explicit/MDPModelChecker.java +++ b/prism/src/explicit/MDPModelChecker.java @@ -48,8 +48,12 @@ import explicit.rewards.MDPRewards; import explicit.rewards.Rewards; import io.ModelExportOptions; +import lpsolve.LpSolve; +import lpsolve.LpSolveException; import parser.ast.Expression; import parser.type.TypeDouble; +import prism.Accuracy; +import prism.Accuracy.AccuracyLevel; import prism.AccuracyFactory; import prism.OptionsIntervalIteration; import prism.Prism; @@ -318,12 +322,6 @@ public ModelCheckerResult computeReachProbs(MDP mdp, BitSet remain, BitS boolean doPmaxQuotient = this.doPmaxQuotient; - // Switch to a supported method, if necessary - if (mdpSolnMethod == MDPSolnMethod.LINEAR_PROGRAMMING) { - mdpSolnMethod = MDPSolnMethod.GAUSS_SEIDEL; - mainLog.printWarning("Switching to MDP solution method \"" + mdpSolnMethod.fullName() + "\""); - } - // Check for some unsupported combinations if (mdpSolnMethod == MDPSolnMethod.VALUE_ITERATION && valIterDir == ValIterDir.ABOVE) { if (!(precomp && prob0)) @@ -353,6 +351,14 @@ public ModelCheckerResult computeReachProbs(MDP mdp, BitSet remain, BitS throw new PrismException("Policy iteration methods cannot be passed 'known' values for some states"); } } + if (mdpSolnMethod == MDPSolnMethod.LINEAR_PROGRAMMING) { + if (!(precomp && prob0)) { + throw new PrismNotSupportedException("Prob0 precomputation must be enabled for linear programming"); + } + if (!min && genStrat) { + throw new PrismNotSupportedException("Currently, explicit engine does not support strategy generation for linear programming and Rmax"); + } + } if (doPmaxQuotient && min) { // for Pmin, don't do quotient @@ -532,6 +538,9 @@ protected ModelCheckerResult computeReachProbsNumeric(MDP mdp, MDPSolnMe } res = computeReachProbsModPolIter(mdp, no, yes, min, strat); break; + case LINEAR_PROGRAMMING: + res = computeReachProbsLP(mdp, no, yes, min, strat); + break; default: throw new PrismException("Unknown MDP solution method " + mdpSolnMethod.fullName()); } @@ -1186,6 +1195,121 @@ protected ModelCheckerResult computeReachProbsModPolIter(MDP mdp, BitSet return res; } + /** + * Compute reachability probabilities using linear programming. + * @param mdp: The MDP + * @param no: Probability 0 states + * @param yes: Probability 1 states + * @param min: Min or max probabilities (true=min, false=max) + * @param strat Storage for (memoryless) strategy choice indices (ignored if null) + */ + protected ModelCheckerResult computeReachProbsLP(MDP mdp, BitSet no, BitSet yes, boolean min, int[] strat) throws PrismException + { + double[] soln = null; + long timer; + + // Start solution + timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (" + (min ? "min" : "max") + ")..."); + + // Store num states + int n = mdp.getNumStates(); + + // Determine set of states actually need to perform computation for + BitSet unknown = new BitSet(); + unknown.set(0, n); + unknown.andNot(yes); + unknown.andNot(no); + + try { + // Initialise LP solver + LpSolve solver = LpSolve.makeLp(0, n); + solver.setVerbose(lpsolve.LpSolve.CRITICAL); + solver.setAddRowmode(true); + // Set up arrays for passing LP to solver + double[] row = new double[n + 1]; + int[] colno = new int[n + 1]; + // Set objective function + if (min) { + solver.setMaxim(); + } else { + solver.setMinim(); + } + for (int s : new IterableBitSet(unknown)) { + row[s + 1] = 1.0; + } + solver.setObjFn(row); + // Add constraints + for (int s = 0; s < n; s++) { + solver.setBounds(s + 1, 0, 1); + if (yes.get(s)) { + row[0] = 1.0; + colno[0] = s + 1; + solver.addConstraintex(1, row, colno, LpSolve.EQ, 1.0); + } else if (no.get(s)) { + row[0] = 1.0; + colno[0] = s + 1; + solver.addConstraintex(1, row, colno, LpSolve.EQ, 0.0); + } else { + int numChoices = mdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + int count = 0; + row[count] = 1.0; + colno[count] = s + 1; + count++; + Iterator> iter = mdp.getTransitionsIterator(s, i); + while (iter.hasNext()) { + Map.Entry e = iter.next(); + int t = e.getKey(); + double p = e.getValue(); + if (t == s) { + row[0] -= p; + } else { + row[count] = -p; + colno[count] = t + 1; + count++; + } + } + solver.addConstraintex(count, row, colno, min ? LpSolve.LE : LpSolve.GE, 0.0); + } + } + } + // Solve LP + solver.setAddRowmode(false); + //solver.printLp(); + int lpRes = solver.solve(); + if (lpRes == lpsolve.LpSolve.OPTIMAL) { + soln = solver.getPtrVariables(); + } else { + throw new PrismException("Error solving LP" + (lpRes == lpsolve.LpSolve.INFEASIBLE ? " (infeasible)" : "")); + } + // Clean up + solver.deleteLp(); + } catch (LpSolveException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + + // We do an extra iteration of VI (using GS since we have just one solution vector) + // If strategy generation was requested (strat != null), this takes care of it + // (NB: that only works reliably for min - max needs more work - but this is disallowed earlier) + // It also has the side-effect of sometimes fixing small round-off errors from LP + mdp.mvMultGSMinMax(soln, min, unknown, false, true, strat); + + // Finished solution + timer = System.currentTimeMillis() - timer; + mainLog.print("Linear programming"); + mainLog.println(" took " + timer / 1000.0 + " seconds."); + + // Return results + // (Note we don't add the strategy - the one passed in is already there + // and might have some existing choices stored for other states). + ModelCheckerResult res = new ModelCheckerResult(); + res.soln = soln; + res.accuracy = new Accuracy(AccuracyLevel.EXACT_FLOATING_POINT); + res.timeTaken = timer / 1000.0; + return res; + } + /** * Construct strategy information for min/max reachability probabilities. * (More precisely, list of indices of choices resulting in min/max.) @@ -2075,7 +2199,7 @@ public ModelCheckerResult computeReachRewards(MDP mdp, MDPRewards mdp, MDPRewards mdp, MDPRewa } res = computeReachRewardsPolIter(mdp, mdpRewards, target, inf, min, strat); break; + case LINEAR_PROGRAMMING: + res = computeReachRewardsLP(mdp, mdpRewards, target, inf, min, strat); + break; default: throw new PrismException("Unknown MDP solution method " + method.fullName()); } @@ -2627,6 +2762,130 @@ protected ModelCheckerResult computeReachRewardsPolIter(MDP mdp, MDPRewa return res; } + /** + * Compute expected reachability rewards using linear programming. + * @param mdp: The MDP + * @param mdpRewards The rewards + * @param target Target states + * @param inf States for which reward is infinite + * @param min: Min or max probabilities (true=min, false=max) + * @param strat Storage for (memoryless) strategy choice indices (ignored if null) + */ + protected ModelCheckerResult computeReachRewardsLP(MDP mdp, MDPRewards mdpRewards, BitSet target, BitSet inf, boolean min, int strat[]) throws PrismException + { + double[] soln = null; + long timer; + + // Start solution + timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (" + (min ? "min" : "max") + ")..."); + + // Store num states + int n = mdp.getNumStates(); + + // Determine set of states actually need to perform computation for + BitSet unknown = new BitSet(); + unknown.set(0, n); + unknown.andNot(target); + unknown.andNot(inf); + + try { + // Initialise LP solver + LpSolve solver = LpSolve.makeLp(0, n); + solver.setVerbose(lpsolve.LpSolve.CRITICAL); + solver.setAddRowmode(true); + // Set up arrays for passing LP to solver + double[] row = new double[n + 1]; + int[] colno = new int[n + 1]; + // Set objective function + if (min) { + solver.setMaxim(); + } else { + solver.setMinim(); + } + for (int s : new IterableBitSet(unknown)) { + row[s + 1] = 1.0; + } + solver.setObjFn(row); + // Add constraints + for (int s = 0; s < n; s++) { + solver.setBounds(s + 1, 0, Double.POSITIVE_INFINITY); + if (!unknown.get(s)) { + row[0] = 1.0; + colno[0] = s + 1; + solver.addConstraintex(1, row, colno, LpSolve.EQ, 0.0); + } else { + int numChoices = mdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + int count = 0; + row[count] = 1.0; + colno[count] = s + 1; + count++; + boolean toInf = false; + Iterator> iter = mdp.getTransitionsIterator(s, i); + while (iter.hasNext()) { + Map.Entry e = iter.next(); + int t = e.getKey(); + double p = e.getValue(); + if (t == s) { + row[0] -= p; + } else { + row[count] = -p; + colno[count] = t + 1; + count++; + } + toInf = toInf || inf.get(t); + } + // We ignore choices that may lead to an inf states + // (inf states are not handled by the LP so given value 0) + if (!toInf) { + double rew = mdpRewards.getStateReward(s) + mdpRewards.getTransitionReward(s, i); + solver.addConstraintex(count, row, colno, min ? LpSolve.LE : LpSolve.GE, rew); + } + } + } + } + // Solve LP + solver.setAddRowmode(false); + //solver.printLp(); + int lpRes = solver.solve(); + if (lpRes == lpsolve.LpSolve.OPTIMAL) { + soln = solver.getPtrVariables(); + } else { + throw new PrismException("Error solving LP" + (lpRes == lpsolve.LpSolve.INFEASIBLE ? " (infeasible)" : "")); + } + // Clean up + solver.deleteLp(); + } catch (LpSolveException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + + // Set value for states with infinite rewards + for (int s : new IterableBitSet(inf)) { + soln[s] = Double.POSITIVE_INFINITY; + } + + // We do an extra iteration of VI (using GS since we have just one solution vector) + // If strategy generation was requested (strat != null), this takes care of it + // (NB: that only works reliably for min - max needs more work - but this is disallowed earlier) + // It also has the side-effect of sometimes fixing small round-off errors from LP + mdp.mvMultRewGSMinMax(soln, mdpRewards, min, unknown, false, true, strat); + + // Finished solution + timer = System.currentTimeMillis() - timer; + mainLog.print("Linear programming"); + mainLog.println(" took " + timer / 1000.0 + " seconds."); + + // Return results + // (Note we don't add the strategy - the one passed in is already there + // and might have some existing choices stored for other states). + ModelCheckerResult res = new ModelCheckerResult(); + res.soln = soln; + res.accuracy = new Accuracy(AccuracyLevel.EXACT_FLOATING_POINT); + res.timeTaken = timer / 1000.0; + return res; + } + /** * Construct strategy information for min/max expected reachability. * (More precisely, list of indices of choices resulting in min/max.) From f5bd3169aee66a5005b0a7c26fdcd7792a773a84 Mon Sep 17 00:00:00 2001 From: Dave Parker Date: Thu, 20 May 2021 09:51:18 +0100 Subject: [PATCH 02/11] Add code to use Gurobi for MDP probabilistic reachability in explicit engine. Gurobi is made the default (over lpsolve) for now. Test e.g. with: prism ../prism-tests/functionality/verify/mdps/reach/mdp_simple.nm ../prism-tests/functionality/verify/mdps/reach/mdp_simple.nm.props -ex -lp -test This requires the Gurobi libraries to be copied into lib, e.g.: cp /Library/gurobi1201/macos_universal2/lib/gurobi.jar lib cp /Library/gurobi1201/macos_universal2/lib/*lib lib --- .classpath | 1 + prism/src/explicit/MDPModelChecker.java | 158 +++++++++++++++++++++--- 2 files changed, 140 insertions(+), 19 deletions(-) diff --git a/.classpath b/.classpath index 06fd0b5d77..da69d8471d 100644 --- a/.classpath +++ b/.classpath @@ -15,5 +15,6 @@ + diff --git a/prism/src/explicit/MDPModelChecker.java b/prism/src/explicit/MDPModelChecker.java index d3b1ab5394..9586e8bac1 100644 --- a/prism/src/explicit/MDPModelChecker.java +++ b/prism/src/explicit/MDPModelChecker.java @@ -36,6 +36,12 @@ import acceptance.AcceptanceReach; import acceptance.AcceptanceType; +import com.gurobi.gurobi.GRB; +import com.gurobi.gurobi.GRBEnv; +import com.gurobi.gurobi.GRBException; +import com.gurobi.gurobi.GRBLinExpr; +import com.gurobi.gurobi.GRBModel; +import com.gurobi.gurobi.GRBVar; import common.IntSet; import common.IterableBitSet; import common.IterableStateSet; @@ -76,6 +82,10 @@ */ public class MDPModelChecker extends ProbModelChecker { + public enum LPSolver { LPSOLVE, GUROBI } + + protected LPSolver lpSolver = LPSolver.GUROBI; + /** * Create a new MDPModelChecker, inherit basic state from parent (unless null). */ @@ -1221,6 +1231,48 @@ protected ModelCheckerResult computeReachProbsLP(MDP mdp, BitSet no, Bit unknown.andNot(yes); unknown.andNot(no); + switch (lpSolver) { + case LPSOLVE: + soln = solveReachProbsLPWithLPSolve(mdp, no, yes, unknown, min, strat); + break; + case GUROBI: + soln = solveReachProbsLPWithGurobi(mdp, no, yes, unknown, min, strat); + break; + } + + // We do an extra iteration of VI (using GS since we have just one solution vector) + // If strategy generation was requested (strat != null), this takes care of it + // (NB: that only works reliably for min - max needs more work - but this is disallowed earlier) + // It also has the side-effect of sometimes fixing small round-off errors from LP + mdp.mvMultGSMinMax(soln, min, unknown, false, true, strat); + + // Finished solution + timer = System.currentTimeMillis() - timer; + mainLog.print("Linear programming"); + mainLog.println(" took " + timer / 1000.0 + " seconds."); + + // Return results + // (Note we don't add the strategy - the one passed in is already there + // and might have some existing choices stored for other states). + ModelCheckerResult res = new ModelCheckerResult(); + res.soln = soln; + res.accuracy = new Accuracy(AccuracyLevel.EXACT_FLOATING_POINT); + res.timeTaken = timer / 1000.0; + return res; + } + + /** + * Solve the linear program for reachability probabilities with LPSolve. + * @param mdp: The MDP + * @param no: Probability 0 states + * @param yes: Probability 1 states + * @param min: Min or max probabilities (true=min, false=max) + * @param strat Storage for (memoryless) strategy choice indices (ignored if null) + */ + protected double[] solveReachProbsLPWithLPSolve(MDP mdp, BitSet no, BitSet yes, BitSet unknown, boolean min, int strat[]) throws PrismException + { + double[] soln = null; + int n = mdp.getNumStates(); try { // Initialise LP solver LpSolve solver = LpSolve.makeLp(0, n); @@ -1285,29 +1337,97 @@ protected ModelCheckerResult computeReachProbsLP(MDP mdp, BitSet no, Bit } // Clean up solver.deleteLp(); + // Return solution + return soln; } catch (LpSolveException e) { throw new PrismException("Error solving LP: " +e.getMessage()); } + } - // We do an extra iteration of VI (using GS since we have just one solution vector) - // If strategy generation was requested (strat != null), this takes care of it - // (NB: that only works reliably for min - max needs more work - but this is disallowed earlier) - // It also has the side-effect of sometimes fixing small round-off errors from LP - mdp.mvMultGSMinMax(soln, min, unknown, false, true, strat); - - // Finished solution - timer = System.currentTimeMillis() - timer; - mainLog.print("Linear programming"); - mainLog.println(" took " + timer / 1000.0 + " seconds."); - - // Return results - // (Note we don't add the strategy - the one passed in is already there - // and might have some existing choices stored for other states). - ModelCheckerResult res = new ModelCheckerResult(); - res.soln = soln; - res.accuracy = new Accuracy(AccuracyLevel.EXACT_FLOATING_POINT); - res.timeTaken = timer / 1000.0; - return res; + /** + * Solve the linear program for reachability probabilities with Gurobi. + * @param mdp: The MDP + * @param no: Probability 0 states + * @param yes: Probability 1 states + * @param min: Min or max probabilities (true=min, false=max) + * @param strat Storage for (memoryless) strategy choice indices (ignored if null) + */ + protected double[] solveReachProbsLPWithGurobi(MDP mdp, BitSet no, BitSet yes, BitSet unknown, boolean min, int strat[]) throws PrismException + { + double[] soln = null; + int n = mdp.getNumStates(); + try { + // Initialise LP solver + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + GRBModel model = new GRBModel(env); + // Set up LP variables + objective function + GRBVar xVars[] = new GRBVar[n]; + for (int s = 0; s < n; s++) { + xVars[s] = model.addVar(0.0, 1.0, unknown.get(s) ? 1.0 : 0.0, GRB.CONTINUOUS, "x" + s); + } + model.set(GRB.IntAttr.ModelSense, min ? -1 : 1); + // Set up arrays for passing LP to solver + double row[] = new double[n + 1]; + int colno[] = new int[n + 1]; + // Add constraints + int counter = 0; + for (int s = 0; s < n; s++) { + if (yes.get(s)) { + GRBLinExpr expr = new GRBLinExpr(); + expr.addTerm(1.0, xVars[s]); + model.addConstr(expr, GRB.EQUAL, 1.0, "c" + counter++); + } else if (no.get(s)) { + GRBLinExpr expr = new GRBLinExpr(); + expr.addTerm(1.0, xVars[s]); + model.addConstr(expr, GRB.EQUAL, 0.0, "c" + counter++); + } else { + int numChoices = mdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + int count = 0; + row[count] = 1.0; + colno[count] = s + 1; + count++; + Iterator> iter = mdp.getTransitionsIterator(s, i); + while (iter.hasNext()) { + Map.Entry e = iter.next(); + int t = e.getKey(); + double p = e.getValue(); + if (t == s) { + row[0] -= p; + } else { + row[count] = -p; + colno[count] = t + 1; + count++; + } + } + GRBLinExpr expr = new GRBLinExpr(); + for (int j = 0; j < count; j++) { + expr.addTerm(row[j], xVars[colno[j] - 1]); + } + model.addConstr(expr, min ? GRB.LESS_EQUAL : GRB.GREATER_EQUAL, 0.0, "c" + counter++); + } + } + } + // Solve LP + //model.write("gurobi.lp"); + model.optimize(); + if (model.get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL) { + soln = new double[n]; + for (int s = 0; s < n; s++) { + soln[s] = xVars[s].get(GRB.DoubleAttr.X); + } + } else { + throw new PrismException("Error solving LP" + (model.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE ? " (infeasible)" : "")); + } + // Clean up + model.dispose(); + env.dispose(); + // Return solution + return soln; + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } } /** From b3944beee1a3510bf1981c0fe8d226ffc7307eaf Mon Sep 17 00:00:00 2001 From: Dave Parker Date: Thu, 20 May 2021 09:51:33 +0100 Subject: [PATCH 03/11] WIP permissive --- prism/src/explicit/MDPModelChecker.java | 252 +++++++ prism/src/explicit/ProbModelChecker.java | 51 +- prism/src/parser/PrismParser.java | 687 +++++++++--------- prism/src/parser/PrismParser.jj | 4 + prism/src/parser/ast/ExpressionStrategy.java | 34 + .../src/symbolic/comp/NondetModelChecker.java | 6 +- prism/tests/robot.nm | 32 + 7 files changed, 732 insertions(+), 334 deletions(-) create mode 100644 prism/tests/robot.nm diff --git a/prism/src/explicit/MDPModelChecker.java b/prism/src/explicit/MDPModelChecker.java index 9586e8bac1..2d6ef1b2d0 100644 --- a/prism/src/explicit/MDPModelChecker.java +++ b/prism/src/explicit/MDPModelChecker.java @@ -768,6 +768,96 @@ public BitSet prob1(MDP mdp, BitSet remain, BitSet target, boolean min, int s return u; } + /** + * Zero total rewards precomputation algorithm, i.e., determine the states of an MDP + * from which the min/max expected total cumulative rewards is zero. + * @param mdp The MDP + * @param mdpRewards The rewards + * @param min Min or max rewards (true=min, false=max) + */ + public BitSet rewTot0(MDP mdp, MDPRewards mdpRewards, boolean min) + { + int n, iters; + BitSet v, soln; + boolean v_done; + long timer; + + // Start precomputation + timer = System.currentTimeMillis(); + if (!silentPrecomputations) + mainLog.println("Starting RewTot0 (" + (min ? "min" : "max") + ")..."); + + // Initialise vectors + n = mdp.getNumStates(); + v = new BitSet(n); + soln = new BitSet(n); + + // Fixed point loop + iters = 0; + v_done = false; + // Least fixed point - start from 0 + v.clear(); + soln.clear(); + while (!v_done) { + iters++; + rewTot0step(mdp, mdpRewards, v, min, soln); + // Check termination (inner) + v_done = soln.equals(v); + // v = soln + v.clear(); + v.or(soln); + } + + // Negate + v.flip(0, n); + + // Finished precomputation + timer = System.currentTimeMillis() - timer; + if (!silentPrecomputations) { + mainLog.print("RewTot0 (" + (min ? "min" : "max") + ")"); + mainLog.println(" took " + iters + " iterations and " + timer / 1000.0 + " seconds."); + } + + return v; + } + + /** + * Perform a single step of zero total rewards precomputation algorithm, + * i.e., set bit i of {@code result} iff, there is a positive (state or transition) + * reward or, for some/all choices, there is a transition to a state in {@code u}. + * @param mdp The MDP + * @param mdpRewards The rewards + * @param u Set of states {@code u} + * @param forall For-all or there-exists (true=for-all, false=there-exists) + * @param result Store results here + */ + private void rewTot0step(final MDP mdp, final MDPRewards mdpRewards, final BitSet u, final boolean forall, BitSet result) + { + int n = mdp.getNumStates(); + for (int s = 0; s < n; s++) { + if (mdpRewards.getStateReward(s) > 0) { + result.set(s); + continue; + } + boolean b1 = forall; // there exists or for all + for (int choice = 0, numChoices = mdp.getNumChoices(s); choice < numChoices; choice++) { + boolean b2 = mdpRewards.getTransitionReward(s, choice) > 0 || mdp.someSuccessorsInSet(s, choice, u); + if (forall) { + if (!b2) { + b1 = false; + break; + } + } else { + if (b2) { + b1 = true; + break; + } + } + } + result.set(s, b1); + } + } + /** * Compute reachability probabilities using value iteration. * Optionally, store optimal (memoryless) strategy info. @@ -3023,6 +3113,168 @@ public List expReachStrategy(MDP mdp, MDPRewards mdpRew return mdp.mvMultRewMinMaxSingleChoices(state, lastSoln, mdpRewards, min, val); } + /** + * Compute a multi-strategy for... + * @param mdp: The MDP + * @param mdpRewards The rewards + * @param bound Reward bound + */ + public ModelCheckerResult computeMultiStrategy(MDP mdp, MDPRewards mdpRewards, double bound) throws PrismException + { + boolean min = true; + double[] soln = null; + + // Start solution + long timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (" + (min ? "min" : "max") + ")..."); + + // Store MDP info + int n = mdp.getNumStates(); + int sInit = mdp.getFirstInitialState(); + // Find states where max expected total reward is 0 + BitSet maxRew0 = rewTot0(mdp, mdpRewards, false); + + try { + // Initialise MILP solver + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + GRBModel model = new GRBModel(env); + // Set up MILP variables (real) + GRBVar xVars[] = new GRBVar[n]; + for (int s = 0; s < n; s++) { + xVars[s] = model.addVar(0.0, maxRew0.get(s) ? 0.0 : GRB.INFINITY, 0.0, GRB.CONTINUOUS, "x" + s); + } + // Set up MILP variables (binary) + GRBVar yaVars[][] = new GRBVar[n][]; + for (int s = 0; s < n; s++) { + int nc = mdp.getNumChoices(s); + yaVars[s] = new GRBVar[nc]; + for (int j = 0; j < nc; j++) { + yaVars[s][j] = model.addVar(0.0, 1.0, 0.0, GRB.BINARY, "y" + s + "_" + j + mdp.getAction(s, j)); + } + } + + double scale = 100.0; + + // Set up objective function + GRBLinExpr exprObj = new GRBLinExpr(); + exprObj.addTerm(-1.0, xVars[sInit]); + //double rhs = 0.0; + for (int s = 0; s < n; s++) { + int nc = mdp.getNumChoices(s); + for (int j = 0; j < nc; j++) { + double phi_s_j = 1.0 * scale; + exprObj.addTerm(-phi_s_j, yaVars[s][j]); + //rhs -= phi_s_j; + } + } + model.setObjective(exprObj, GRB.MINIMIZE); + + // Set up arrays for passing MILP to solver + double row[] = new double[n + 1]; + int colno[] = new int[n + 1]; + // Add constraints + int counter = 0; + double b = bound; + GRBLinExpr expr = new GRBLinExpr(); + expr.addTerm(1.0, xVars[sInit]); + model.addConstr(expr, GRB.GREATER_EQUAL, b, "c" + counter++); + for (int s = 0; s < n; s++) { + expr = new GRBLinExpr(); + int nc = mdp.getNumChoices(s); + for (int j = 0; j < nc; j++) { + expr.addTerm(1.0, yaVars[s][j]); + } + model.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "c" + counter++); + } + for (int s = 0; s < n; s++) { + int numChoices = mdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + int count = 0; + row[count] = 1.0; + colno[count] = s + 1; + count++; + Iterator> iter = mdp.getTransitionsIterator(s, i); + while (iter.hasNext()) { + Map.Entry e = iter.next(); + int t = e.getKey(); + double p = e.getValue(); + if (t == s) { + row[0] -= p; + } else { + row[count] = -p; + colno[count] = t + 1; + count++; + } + } + // TODO state rewards? + double r = mdpRewards.getTransitionReward(s, i); + expr = new GRBLinExpr(); + for (int j = 0; j < count; j++) { + expr.addTerm(row[j], xVars[colno[j] - 1]); + } + expr.addTerm(scale, yaVars[s][i]); + model.addConstr(expr, GRB.LESS_EQUAL, r + scale, "c" + counter++); + } + } + // Solve MILP + model.write("gurobi.lp"); + model.optimize(); + if (model.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { +// model.computeIIS(); +// System.out.println("\nThe following constraint(s) " + "cannot be satisfied:"); +// for (GRBConstr c : model.getConstrs()) { +// if (c.get(GRB.IntAttr.IISConstr) == 1) { +// System.out.println(c.get(GRB.StringAttr.ConstrName)); +// } +// } + throw new PrismException("Error solving LP: " + "infeasible"); + } + if (model.get(GRB.IntAttr.Status) == GRB.Status.UNBOUNDED) { + throw new PrismException("Error solving LP: " + "unbounded"); + } + if (model.get(GRB.IntAttr.Status) != GRB.Status.OPTIMAL) { + throw new PrismException("Error solving LP: " + "non-optimal " + model.get(GRB.IntAttr.Status)); + } + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(xVars[s].get(GRB.StringAttr.VarName) + " = "+xVars[s].get(GRB.DoubleAttr.X)); + soln[s] = xVars[s].get(GRB.DoubleAttr.X); + } + for (int s = 0; s < n; s++) { + int numChoices = mdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + System.out.println(yaVars[s][i].get(GRB.StringAttr.VarName) + " = " + yaVars[s][i].get(GRB.DoubleAttr.X)); + } + } + // Print multi-strategy + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = mdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + if (yaVars[s][i].get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + mdp.getAction(s, i)); + } + } + mainLog.println(); + } + + // Clean up + model.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + + + // Return results + ModelCheckerResult res = new ModelCheckerResult(); +// res.accuracy = AccuracyFactory.boundedNumericalIterations(); + res.soln = soln; +// res.timeTaken = timer / 1000.0; + return res; + } + /** * Restrict a (memoryless) strategy for an MDP, stored as an integer array of choice indices, * to the states of the MDP that are reachable under that strategy. diff --git a/prism/src/explicit/ProbModelChecker.java b/prism/src/explicit/ProbModelChecker.java index 5439a43b02..987c161d44 100644 --- a/prism/src/explicit/ProbModelChecker.java +++ b/prism/src/explicit/ProbModelChecker.java @@ -52,6 +52,7 @@ import prism.AccuracyFactory; import prism.Evaluator; import prism.IntegerBound; +import prism.ModelType; import prism.OpRelOpBound; import prism.Prism; import prism.PrismComponent; @@ -588,8 +589,12 @@ protected StateValues checkExpressionStrategy(Model model, ExpressionStrategy } Expression exprSub = exprs.get(0); // Pass onto relevant method: + // Multi-strategy + if ("multi".equals(expr.getModifier())) { + return checkExpressionMultiStrategy(model, expr, forAll, coalition, statesOfInterest); + } // P operator - if (exprSub instanceof ExpressionProb) { + else if (exprSub instanceof ExpressionProb) { return checkExpressionProb(model, (ExpressionProb) exprSub, forAll, coalition, statesOfInterest); } // R operator @@ -602,6 +607,50 @@ else if (exprSub instanceof ExpressionReward) { } } + /** + * Model check a <<>> operator requesting a multi-strategy + * @param statesOfInterest the states of interest, see checkExpression() + */ + protected StateValues checkExpressionMultiStrategy(Model model, ExpressionStrategy expr, boolean forAll, Coalition coalition, BitSet statesOfInterest) throws PrismException + { + // Only support "exists" (<<>>) currently + if (forAll) { + throw new PrismException("Multi-strategies not supported for " + expr.getOperatorString()); + } + // Only support R[C] currently + Expression exprSub = expr.getOperands().get(0); + if (!(exprSub instanceof ExpressionReward)) { + throw new PrismException("Multi-strategy synthesis only supports R[C] properties currently"); + } + ExpressionReward exprRew = (ExpressionReward) exprSub; + if (!(exprRew.getExpression() instanceof ExpressionTemporal)) { + throw new PrismException("Multi-strategy synthesis only supports R[C] properties currently"); + } + ExpressionTemporal exprTemp = (ExpressionTemporal) exprRew.getExpression(); + if (!(exprTemp.getOperator() == ExpressionTemporal.R_C) && !exprTemp.hasBounds()) { + throw new PrismException("Multi-strategy synthesis only supports R[C] properties currently"); + } + + // Get info from R operator + OpRelOpBound opInfo = exprRew.getRelopBoundInfo(constantValues); + MinMax minMax = opInfo.getMinMax(model.getModelType(), false); + + // Build rewards + int r = exprRew.getRewardStructIndexByIndexObject(rewardGen, constantValues); + mainLog.println("Building reward structure..."); + Rewards modelRewards = constructRewards(model, r); + + // Only support MDPs + if (model.getModelType() != ModelType.MDP) { + throw new PrismNotSupportedException("Multi-strategy synthesis not supported for " + model.getModelType() + "s"); + } + + ModelCheckerResult res = ((MDPModelChecker) this).computeMultiStrategy((MDP) model, (MDPRewards) modelRewards, opInfo.getBound()); + + result.setStrategy(res.strat); + return StateValues.createFromDoubleArrayResult(res, model); + } + /** * Model check a P operator expression and return the values for the statesOfInterest. * @param statesOfInterest the states of interest, see checkExpression() diff --git a/prism/src/parser/PrismParser.java b/prism/src/parser/PrismParser.java index 85735651b8..8aa8be380b 100644 --- a/prism/src/parser/PrismParser.java +++ b/prism/src/parser/PrismParser.java @@ -3704,6 +3704,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression // (Property) expression: ATL strategy operators <<>> and [[]] static final public Expression ExpressionStrategy(boolean prop, boolean pathprop) throws ParseException {ExpressionStrategy ret; + ExpressionIdent modifier = null; Expression expr; Token begin = null; if (!prop) {if (true) throw generateParseException();} @@ -3728,6 +3729,17 @@ static class ExpressionPair { public Expression expr1 = null; public Expression throw new ParseException(); } switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { + case LBRACE:{ + jj_consume_token(LBRACE); + modifier = IdentifierExpression(); + jj_consume_token(RBRACE); + break; + } + default: + jj_la1[95] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { case PMAXMAX: case PMAXMIN: case PMAX: @@ -3764,7 +3776,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[95] = jj_gen; + jj_la1[96] = jj_gen; jj_consume_token(-1); throw new ParseException(); } @@ -3777,11 +3789,12 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[96] = jj_gen; + jj_la1[97] = jj_gen; jj_consume_token(-1); throw new ParseException(); } -ret.setPosition(begin, getToken(0)); +ret.setModifier(modifier == null ? null : modifier.getName()); + ret.setPosition(begin, getToken(0)); {if ("" != null) return ret;} throw new Error("Missing return statement in function"); } @@ -3797,7 +3810,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[99] = jj_gen; + jj_la1[100] = jj_gen; switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { case REG_INT: case REG_IDENT:{ @@ -3811,7 +3824,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[97] = jj_gen; + jj_la1[98] = jj_gen; break label_28; } jj_consume_token(COMMA); @@ -3821,7 +3834,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[98] = jj_gen; + jj_la1[99] = jj_gen; ; } exprStrat.setCoalition(coalition); @@ -3841,7 +3854,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[100] = jj_gen; + jj_la1[101] = jj_gen; jj_consume_token(-1); throw new ParseException(); } @@ -3868,7 +3881,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[101] = jj_gen; + jj_la1[102] = jj_gen; jj_consume_token(-1); throw new ParseException(); } @@ -3919,7 +3932,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[102] = jj_gen; + jj_la1[103] = jj_gen; jj_consume_token(-1); throw new ParseException(); } @@ -3932,7 +3945,7 @@ static class ExpressionPair { public Expression expr1 = null; public Expression break; } default: - jj_la1[103] = jj_gen; + jj_la1[104] = jj_gen; ; } jj_consume_token(RPARENTH); @@ -3981,7 +3994,7 @@ String Identifier() throws ParseException { break; } default: - jj_la1[104] = jj_gen; + jj_la1[105] = jj_gen; jj_consume_token(-1); throw new ParseException(); } @@ -4018,7 +4031,7 @@ int EqNeq() throws ParseException { break; } default: - jj_la1[105] = jj_gen; + jj_la1[106] = jj_gen; jj_consume_token(-1); throw new ParseException(); } @@ -4050,7 +4063,7 @@ int LtGt() throws ParseException { break; } default: - jj_la1[106] = jj_gen; + jj_la1[107] = jj_gen; jj_consume_token(-1); throw new ParseException(); } @@ -4076,7 +4089,7 @@ int LtGt() throws ParseException { break; } default: - jj_la1[107] = jj_gen; + jj_la1[108] = jj_gen; ; } jj_consume_token(0); @@ -4233,22 +4246,6 @@ static private boolean jj_2_18(int xla) finally { jj_save(17, xla); } } - static private boolean jj_3R_ExpressionStrategy_1905_9_153() - { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_ExpressionStrategy_1908_10_184()) { - jj_scanpos = xsp; - if (jj_3R_ExpressionStrategy_1909_11_185()) return true; - } - xsp = jj_scanpos; - if (jj_3R_ExpressionStrategy_1912_9_186()) { - jj_scanpos = xsp; - if (jj_3R_ExpressionStrategy_1914_11_187()) return true; - } - return false; - } - static private boolean jj_3R_ExpressionFuncMinMax_1518_11_161() { if (jj_scan_token(MIN)) return true; @@ -4272,9 +4269,9 @@ static private boolean jj_3R_ExpressionFuncMinMax_1518_9_146() static private boolean jj_3R_SystemHideRename_1131_11_81() { if (jj_scan_token(LBRACE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(RENAME)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; Token xsp; while (true) { xsp = jj_scanpos; @@ -4299,7 +4296,7 @@ static private boolean jj_3_4() return false; } - static private boolean jj_3R_RewardIndex_1815_87_242() + static private boolean jj_3R_RewardIndex_1815_87_243() { if (jj_3R_Expression_1177_9_38()) return true; return false; @@ -4316,7 +4313,7 @@ static private boolean jj_3R_SystemHideRename_1125_9_80() { if (jj_scan_token(DIVIDE)) return true; if (jj_scan_token(LBRACE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; Token xsp; while (true) { xsp = jj_scanpos; @@ -4365,7 +4362,7 @@ static private boolean jj_3_8() static private boolean jj_3R_ExpressionFuncOrIdent_1503_9_145() { - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_ExpressionFuncOrIdent_1505_11_160()) jj_scanpos = xsp; @@ -4398,19 +4395,19 @@ static private boolean jj_3_10() static private boolean jj_3R_ExpressionBasic_1481_17_143() { - if (jj_3R_ExpressionFilter_1977_9_155()) return true; + if (jj_3R_ExpressionFilter_1981_9_155()) return true; return false; } static private boolean jj_3R_ExpressionBasic_1479_17_142() { - if (jj_3R_ExpressionLabel_1959_9_154()) return true; + if (jj_3R_ExpressionLabel_1963_9_154()) return true; return false; } static private boolean jj_3R_ExpressionBasic_1477_17_141() { - if (jj_3R_ExpressionStrategy_1905_9_153()) return true; + if (jj_3R_ExpressionStrategy_1906_9_153()) return true; return false; } @@ -4433,7 +4430,7 @@ static private boolean jj_3R_SystemParallel_1096_11_59() { if (jj_scan_token(OR)) return true; if (jj_scan_token(LBRACKET)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; Token xsp; while (true) { xsp = jj_scanpos; @@ -4491,7 +4488,7 @@ static private boolean jj_3R_ExpressionBasic_1464_17_135() return false; } - static private boolean jj_3R_ExpressionRewardContents_1852_11_222() + static private boolean jj_3R_ExpressionRewardContents_1852_11_223() { if (jj_3R_Expression_1177_9_38()) return true; return false; @@ -4509,7 +4506,7 @@ static private boolean jj_3_17() return false; } - static private boolean jj_3R_ExpressionRewardContents_1849_11_221() + static private boolean jj_3R_ExpressionRewardContents_1849_11_222() { if (jj_scan_token(I)) return true; if (jj_scan_token(EQ)) return true; @@ -4529,13 +4526,13 @@ static private boolean jj_3_16() return false; } - static private boolean jj_3R_ExpressionRewardContents_1848_11_220() + static private boolean jj_3R_ExpressionRewardContents_1848_11_221() { if (jj_scan_token(C)) return true; return false; } - static private boolean jj_3R_ExpressionRewardContents_1847_11_219() + static private boolean jj_3R_ExpressionRewardContents_1847_11_220() { if (jj_scan_token(C)) return true; if (jj_scan_token(LE)) return true; @@ -4561,7 +4558,7 @@ static private boolean jj_3R_ExpressionBasic_1456_17_131() return false; } - static private boolean jj_3R_ExpressionRewardContents_1844_11_218() + static private boolean jj_3R_ExpressionRewardContents_1844_11_219() { if (jj_scan_token(S)) return true; return false; @@ -4573,16 +4570,16 @@ static private boolean jj_3R_ExpressionReward_1786_69_183() return false; } - static private boolean jj_3R_ExpressionRewardContents_1843_9_217() + static private boolean jj_3R_ExpressionRewardContents_1843_9_218() { if (jj_3R_ExpressionSS_1714_9_33()) return true; return false; } - static private boolean jj_3R_RewardIndex_1817_33_245() + static private boolean jj_3R_RewardIndex_1817_33_246() { if (jj_scan_token(DQUOTE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(DQUOTE)) return true; return false; } @@ -4591,17 +4588,17 @@ static private boolean jj_3R_ExpressionRewardContents_1840_9_182() { Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionRewardContents_1843_9_217()) { + if (jj_3R_ExpressionRewardContents_1843_9_218()) { jj_scanpos = xsp; - if (jj_3R_ExpressionRewardContents_1844_11_218()) { + if (jj_3R_ExpressionRewardContents_1844_11_219()) { jj_scanpos = xsp; - if (jj_3R_ExpressionRewardContents_1847_11_219()) { + if (jj_3R_ExpressionRewardContents_1847_11_220()) { jj_scanpos = xsp; - if (jj_3R_ExpressionRewardContents_1848_11_220()) { + if (jj_3R_ExpressionRewardContents_1848_11_221()) { jj_scanpos = xsp; - if (jj_3R_ExpressionRewardContents_1849_11_221()) { + if (jj_3R_ExpressionRewardContents_1849_11_222()) { jj_scanpos = xsp; - if (jj_3R_ExpressionRewardContents_1852_11_222()) return true; + if (jj_3R_ExpressionRewardContents_1852_11_223()) return true; } } } @@ -4684,10 +4681,10 @@ static private boolean jj_3R_ExpressionUnaryMinus_1440_17_128() return false; } - static private boolean jj_3R_RewardIndex_1815_22_241() + static private boolean jj_3R_RewardIndex_1815_22_242() { if (jj_scan_token(DQUOTE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(DQUOTE)) return true; return false; } @@ -4701,7 +4698,7 @@ static private boolean jj_3R_ExpressionPlusMinus_1392_62_123() static private boolean jj_3_2() { if (jj_scan_token(DQUOTE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(DQUOTE)) return true; if (jj_scan_token(COLON)) return true; return false; @@ -4718,15 +4715,15 @@ static private boolean jj_3R_ExpressionUnaryMinus_1439_9_124() return false; } - static private boolean jj_3R_RewardIndex_1817_11_243() + static private boolean jj_3R_RewardIndex_1817_11_244() { if (jj_scan_token(DIVIDE)) return true; if (jj_scan_token(LBRACE)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_RewardIndex_1817_33_245()) { + if (jj_3R_RewardIndex_1817_33_246()) { jj_scanpos = xsp; - if (jj_3R_RewardIndex_1817_101_246()) return true; + if (jj_3R_RewardIndex_1817_101_247()) return true; } if (jj_scan_token(RBRACE)) return true; return false; @@ -4739,18 +4736,18 @@ static private boolean jj_3R_ExpressionPower_1426_17_125() return false; } - static private boolean jj_3R_RewardIndex_1815_9_232() + static private boolean jj_3R_RewardIndex_1815_9_233() { if (jj_scan_token(LBRACE)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_RewardIndex_1815_22_241()) { + if (jj_3R_RewardIndex_1815_22_242()) { jj_scanpos = xsp; - if (jj_3R_RewardIndex_1815_87_242()) return true; + if (jj_3R_RewardIndex_1815_87_243()) return true; } if (jj_scan_token(RBRACE)) return true; xsp = jj_scanpos; - if (jj_3R_RewardIndex_1817_11_243()) jj_scanpos = xsp; + if (jj_3R_RewardIndex_1817_11_244()) jj_scanpos = xsp; return false; } @@ -4801,7 +4798,7 @@ static private boolean jj_3R_ExpressionTimesDivide_1409_17_121() static private boolean jj_3_7() { if (jj_scan_token(DQUOTE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(DQUOTE)) return true; if (jj_3R_SystemDefn_1034_9_31()) return true; return false; @@ -4818,7 +4815,7 @@ static private boolean jj_3R_ExpressionTimesDivide_1407_9_116() return false; } - static private boolean jj_3R_ExpressionReward_1771_26_238() + static private boolean jj_3R_ExpressionReward_1771_26_239() { if (jj_scan_token(MAX)) return true; if (jj_scan_token(EQ)) return true; @@ -4826,7 +4823,7 @@ static private boolean jj_3R_ExpressionReward_1771_26_238() return false; } - static private boolean jj_3R_ExpressionReward_1770_26_237() + static private boolean jj_3R_ExpressionReward_1770_26_238() { if (jj_scan_token(MIN)) return true; if (jj_scan_token(EQ)) return true; @@ -4834,7 +4831,7 @@ static private boolean jj_3R_ExpressionReward_1770_26_237() return false; } - static private boolean jj_3R_ExpressionReward_1769_26_236() + static private boolean jj_3R_ExpressionReward_1769_26_237() { if (jj_scan_token(EQ)) return true; if (jj_scan_token(QMARK)) return true; @@ -4855,7 +4852,7 @@ static private boolean jj_3R_ExpressionPlusMinus_1392_19_122() return false; } - static private boolean jj_3R_ExpressionReward_1767_26_235() + static private boolean jj_3R_ExpressionReward_1767_26_236() { if (jj_scan_token(MAX)) return true; if (jj_scan_token(EQ)) return true; @@ -4863,7 +4860,7 @@ static private boolean jj_3R_ExpressionReward_1767_26_235() return false; } - static private boolean jj_3R_ExpressionReward_1776_17_216() + static private boolean jj_3R_ExpressionReward_1776_17_217() { if (jj_scan_token(MAXMAX)) return true; if (jj_scan_token(EQ)) return true; @@ -4879,7 +4876,7 @@ static private boolean jj_3R_ExpressionReward_1783_10_180() return false; } - static private boolean jj_3R_ExpressionReward_1766_26_234() + static private boolean jj_3R_ExpressionReward_1766_26_235() { if (jj_scan_token(MIN)) return true; if (jj_scan_token(EQ)) return true; @@ -4887,7 +4884,7 @@ static private boolean jj_3R_ExpressionReward_1766_26_234() return false; } - static private boolean jj_3R_ExpressionReward_1775_17_215() + static private boolean jj_3R_ExpressionReward_1775_17_216() { if (jj_scan_token(MAXMIN)) return true; if (jj_scan_token(EQ)) return true; @@ -4915,14 +4912,14 @@ static private boolean jj_3R_ExpressionPlusMinus_1392_17_117() return false; } - static private boolean jj_3R_ExpressionReward_1765_26_233() + static private boolean jj_3R_ExpressionReward_1765_26_234() { if (jj_scan_token(EQ)) return true; if (jj_scan_token(QMARK)) return true; return false; } - static private boolean jj_3R_ExpressionReward_1774_17_214() + static private boolean jj_3R_ExpressionReward_1774_17_215() { if (jj_scan_token(MINMAX)) return true; if (jj_scan_token(EQ)) return true; @@ -4938,7 +4935,7 @@ static private boolean jj_3R_ExpressionReward_1781_10_178() return false; } - static private boolean jj_3R_ExpressionReward_1773_17_213() + static private boolean jj_3R_ExpressionReward_1773_17_214() { if (jj_scan_token(MINMIN)) return true; if (jj_scan_token(EQ)) return true; @@ -4962,31 +4959,31 @@ static private boolean jj_3R_ExpressionReward_1779_10_176() return false; } - static private boolean jj_3R_ExpressionReward_1769_17_212() + static private boolean jj_3R_ExpressionReward_1769_17_213() { if (jj_scan_token(MAX)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionReward_1769_26_236()) { + if (jj_3R_ExpressionReward_1769_26_237()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1770_26_237()) { + if (jj_3R_ExpressionReward_1770_26_238()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1771_26_238()) return true; + if (jj_3R_ExpressionReward_1771_26_239()) return true; } } return false; } - static private boolean jj_3R_ExpressionReward_1765_17_211() + static private boolean jj_3R_ExpressionReward_1765_17_212() { if (jj_scan_token(MIN)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionReward_1765_26_233()) { + if (jj_3R_ExpressionReward_1765_26_234()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1766_26_234()) { + if (jj_3R_ExpressionReward_1766_26_235()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1767_26_235()) return true; + if (jj_3R_ExpressionReward_1767_26_236()) return true; } } return false; @@ -5003,30 +5000,30 @@ static private boolean jj_3R_ExpressionPlusMinus_1390_9_113() return false; } - static private boolean jj_3R_ExpressionReward_1764_17_210() + static private boolean jj_3R_ExpressionReward_1764_17_211() { if (jj_scan_token(EQ)) return true; if (jj_scan_token(QMARK)) return true; return false; } - static private boolean jj_3R_ExpressionReward_1763_18_209() + static private boolean jj_3R_ExpressionReward_1763_18_210() { - if (jj_3R_LtGt_2065_9_45()) return true; + if (jj_3R_LtGt_2069_9_45()) return true; if (jj_3R_Expression_1177_9_38()) return true; return false; } - static private boolean jj_3R_ExpressionReward_1762_18_208() + static private boolean jj_3R_ExpressionReward_1762_18_209() { - if (jj_3R_RewardIndex_1815_9_232()) return true; + if (jj_3R_RewardIndex_1815_9_233()) return true; return false; } - static private boolean jj_3R_ExpressionReward_1761_19_207() + static private boolean jj_3R_ExpressionReward_1761_19_208() { if (jj_scan_token(LPARENTH)) return true; - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; if (jj_scan_token(RPARENTH)) return true; return false; } @@ -5042,25 +5039,25 @@ static private boolean jj_3R_ExpressionReward_1760_10_175() if (jj_scan_token(R)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionReward_1761_19_207()) jj_scanpos = xsp; + if (jj_3R_ExpressionReward_1761_19_208()) jj_scanpos = xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionReward_1762_18_208()) jj_scanpos = xsp; + if (jj_3R_ExpressionReward_1762_18_209()) jj_scanpos = xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionReward_1763_18_209()) { + if (jj_3R_ExpressionReward_1763_18_210()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1764_17_210()) { + if (jj_3R_ExpressionReward_1764_17_211()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1765_17_211()) { + if (jj_3R_ExpressionReward_1765_17_212()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1769_17_212()) { + if (jj_3R_ExpressionReward_1769_17_213()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1773_17_213()) { + if (jj_3R_ExpressionReward_1773_17_214()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1774_17_214()) { + if (jj_3R_ExpressionReward_1774_17_215()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1775_17_215()) { + if (jj_3R_ExpressionReward_1775_17_216()) { jj_scanpos = xsp; - if (jj_3R_ExpressionReward_1776_17_216()) return true; + if (jj_3R_ExpressionReward_1776_17_217()) return true; } } } @@ -5104,7 +5101,7 @@ static private boolean jj_3R_ExpressionReward_1758_9_150() static private boolean jj_3R_ExpressionRelop_1370_11_114() { - if (jj_3R_LtGt_2065_9_45()) return true; + if (jj_3R_LtGt_2069_9_45()) return true; if (jj_3R_ExpressionPlusMinus_1390_9_113()) return true; return false; } @@ -5122,7 +5119,7 @@ static private boolean jj_3R_ExpressionRelop_1369_9_111() static private boolean jj_3R_ExpressionEquality_1356_11_112() { - if (jj_3R_EqNeq_2055_9_115()) return true; + if (jj_3R_EqNeq_2059_9_115()) return true; if (jj_3R_ExpressionRelop_1369_9_111()) return true; return false; } @@ -5141,7 +5138,7 @@ static private boolean jj_3R_ExpressionEquality_1355_9_110() static private boolean jj_3_1() { if (jj_scan_token(MODULE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(EQ)) return true; return false; } @@ -5193,7 +5190,7 @@ static private boolean jj_3R_ExpressionSS_1719_17_37() static private boolean jj_3R_ExpressionSS_1717_19_44() { if (jj_scan_token(LPARENTH)) return true; - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; if (jj_scan_token(RPARENTH)) return true; return false; } @@ -5209,7 +5206,7 @@ static private boolean jj_3R_ExpressionSS_1717_17_36() Token xsp; xsp = jj_scanpos; if (jj_3R_ExpressionSS_1717_19_44()) jj_scanpos = xsp; - if (jj_3R_LtGt_2065_9_45()) return true; + if (jj_3R_LtGt_2069_9_45()) return true; if (jj_3R_Expression_1177_9_38()) return true; return false; } @@ -5329,105 +5326,105 @@ static private boolean jj_3R_Filter_1690_9_47() return false; } - static private boolean jj_3R_ExpressionIff_1300_11_103() - { - if (jj_scan_token(IFF)) return true; - if (jj_3R_ExpressionOr_1312_9_102()) return true; - return false; - } - - static private boolean jj_3R_LtGt_2068_9_54() + static private boolean jj_3R_LtGt_2072_9_54() { if (jj_scan_token(LE)) return true; return false; } - static private boolean jj_3R_LtGt_2067_9_53() + static private boolean jj_3R_LtGt_2071_9_53() { if (jj_scan_token(GE)) return true; return false; } - static private boolean jj_3R_LtGt_2066_9_52() + static private boolean jj_3R_LtGt_2070_9_52() { if (jj_scan_token(LT)) return true; return false; } - static private boolean jj_3R_ExpressionIff_1299_9_92() - { - if (jj_3R_ExpressionOr_1312_9_102()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_ExpressionIff_1300_11_103()) { jj_scanpos = xsp; break; } - } - return false; - } - - static private boolean jj_3R_LtGt_2065_9_51() + static private boolean jj_3R_LtGt_2069_9_51() { if (jj_scan_token(GT)) return true; return false; } - static private boolean jj_3R_LtGt_2065_9_45() + static private boolean jj_3R_LtGt_2069_9_45() { Token xsp; xsp = jj_scanpos; - if (jj_3R_LtGt_2065_9_51()) { + if (jj_3R_LtGt_2069_9_51()) { jj_scanpos = xsp; - if (jj_3R_LtGt_2066_9_52()) { + if (jj_3R_LtGt_2070_9_52()) { jj_scanpos = xsp; - if (jj_3R_LtGt_2067_9_53()) { + if (jj_3R_LtGt_2071_9_53()) { jj_scanpos = xsp; - if (jj_3R_LtGt_2068_9_54()) return true; + if (jj_3R_LtGt_2072_9_54()) return true; } } } return false; } - static private boolean jj_3R_UpdateElement_910_9_40() + static private boolean jj_3R_ExpressionIff_1300_11_103() { - if (jj_scan_token(LPARENTH)) return true; - if (jj_3R_IdentifierPrime_2037_9_48()) return true; - if (jj_scan_token(EQ)) return true; - if (jj_3R_Expression_1177_9_38()) return true; - if (jj_scan_token(RPARENTH)) return true; + if (jj_scan_token(IFF)) return true; + if (jj_3R_ExpressionOr_1312_9_102()) return true; + return false; + } + + static private boolean jj_3R_ExpressionIff_1299_9_92() + { + if (jj_3R_ExpressionOr_1312_9_102()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_ExpressionIff_1300_11_103()) { jj_scanpos = xsp; break; } + } return false; } - static private boolean jj_3R_EqNeq_2056_9_119() + static private boolean jj_3R_EqNeq_2060_9_119() { if (jj_scan_token(NE)) return true; return false; } - static private boolean jj_3R_ExpressionImplies_1287_11_93() + static private boolean jj_3R_UpdateElement_910_9_40() { - if (jj_scan_token(IMPLIES)) return true; - if (jj_3R_ExpressionImplies_1286_9_82()) return true; + if (jj_scan_token(LPARENTH)) return true; + if (jj_3R_IdentifierPrime_2041_9_48()) return true; + if (jj_scan_token(EQ)) return true; + if (jj_3R_Expression_1177_9_38()) return true; + if (jj_scan_token(RPARENTH)) return true; return false; } - static private boolean jj_3R_EqNeq_2055_9_115() + static private boolean jj_3R_EqNeq_2059_9_115() { Token xsp; xsp = jj_scanpos; - if (jj_3R_EqNeq_2055_9_118()) { + if (jj_3R_EqNeq_2059_9_118()) { jj_scanpos = xsp; - if (jj_3R_EqNeq_2056_9_119()) return true; + if (jj_3R_EqNeq_2060_9_119()) return true; } return false; } - static private boolean jj_3R_EqNeq_2055_9_118() + static private boolean jj_3R_EqNeq_2059_9_118() { if (jj_scan_token(EQ)) return true; return false; } + static private boolean jj_3R_ExpressionImplies_1287_11_93() + { + if (jj_scan_token(IMPLIES)) return true; + if (jj_3R_ExpressionImplies_1286_9_82()) return true; + return false; + } + static private boolean jj_3R_ExpressionImplies_1286_9_82() { if (jj_3R_ExpressionIff_1299_9_92()) return true; @@ -5448,7 +5445,7 @@ static private boolean jj_3R_Update_897_10_34() return false; } - static private boolean jj_3R_ExpressionProb_1646_26_231() + static private boolean jj_3R_ExpressionProb_1646_26_232() { if (jj_scan_token(MAX)) return true; if (jj_scan_token(EQ)) return true; @@ -5465,7 +5462,7 @@ static private boolean jj_3R_ExpressionITE_1272_17_83() return false; } - static private boolean jj_3R_ExpressionProb_1645_26_230() + static private boolean jj_3R_ExpressionProb_1645_26_231() { if (jj_scan_token(MIN)) return true; if (jj_scan_token(EQ)) return true; @@ -5473,7 +5470,7 @@ static private boolean jj_3R_ExpressionProb_1645_26_230() return false; } - static private boolean jj_3R_ExpressionProb_1644_26_229() + static private boolean jj_3R_ExpressionProb_1644_26_230() { if (jj_scan_token(EQ)) return true; if (jj_scan_token(QMARK)) return true; @@ -5501,12 +5498,12 @@ static private boolean jj_3R_ExpressionProb_1659_10_173() static private boolean jj_3_14() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; if (jj_scan_token(LPARENTH)) return true; return false; } - static private boolean jj_3R_ExpressionProb_1642_26_228() + static private boolean jj_3R_ExpressionProb_1642_26_229() { if (jj_scan_token(MAX)) return true; if (jj_scan_token(EQ)) return true; @@ -5514,7 +5511,7 @@ static private boolean jj_3R_ExpressionProb_1642_26_228() return false; } - static private boolean jj_3R_ExpressionProb_1651_17_206() + static private boolean jj_3R_ExpressionProb_1651_17_207() { if (jj_scan_token(MAXMAX)) return true; if (jj_scan_token(EQ)) return true; @@ -5532,12 +5529,12 @@ static private boolean jj_3R_ExpressionProb_1658_10_172() static private boolean jj_3_13() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; if (jj_scan_token(LPARENTH)) return true; return false; } - static private boolean jj_3R_ExpressionProb_1641_26_227() + static private boolean jj_3R_ExpressionProb_1641_26_228() { if (jj_scan_token(MIN)) return true; if (jj_scan_token(EQ)) return true; @@ -5545,7 +5542,7 @@ static private boolean jj_3R_ExpressionProb_1641_26_227() return false; } - static private boolean jj_3R_ExpressionProb_1650_17_205() + static private boolean jj_3R_ExpressionProb_1650_17_206() { if (jj_scan_token(MAXMIN)) return true; if (jj_scan_token(EQ)) return true; @@ -5563,19 +5560,25 @@ static private boolean jj_3R_ExpressionProb_1657_10_171() static private boolean jj_3_12() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; if (jj_scan_token(LPARENTH)) return true; return false; } - static private boolean jj_3R_ExpressionProb_1640_26_226() + static private boolean jj_3R_IdentifierPrime_2041_9_48() + { + if (jj_scan_token(REG_IDENTPRIME)) return true; + return false; + } + + static private boolean jj_3R_ExpressionProb_1640_26_227() { if (jj_scan_token(EQ)) return true; if (jj_scan_token(QMARK)) return true; return false; } - static private boolean jj_3R_ExpressionProb_1649_17_204() + static private boolean jj_3R_ExpressionProb_1649_17_205() { if (jj_scan_token(MINMAX)) return true; if (jj_scan_token(EQ)) return true; @@ -5593,12 +5596,12 @@ static private boolean jj_3R_ExpressionProb_1656_10_170() static private boolean jj_3_11() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; if (jj_scan_token(LPARENTH)) return true; return false; } - static private boolean jj_3R_ExpressionProb_1648_17_203() + static private boolean jj_3R_ExpressionProb_1648_17_204() { if (jj_scan_token(MINMIN)) return true; if (jj_scan_token(EQ)) return true; @@ -5622,17 +5625,17 @@ static private boolean jj_3R_ExpressionProb_1654_10_168() return false; } - static private boolean jj_3R_ExpressionProb_1638_25_199() + static private boolean jj_3R_ExpressionProb_1638_25_200() { - if (jj_3R_LtGt_2065_9_45()) return true; + if (jj_3R_LtGt_2069_9_45()) return true; if (jj_3R_Expression_1177_9_38()) return true; return false; } - static private boolean jj_3R_ExpressionProb_1637_26_198() + static private boolean jj_3R_ExpressionProb_1637_26_199() { if (jj_scan_token(LPARENTH)) return true; - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; if (jj_scan_token(RPARENTH)) return true; return false; } @@ -5643,12 +5646,6 @@ static private boolean jj_3_5() return false; } - static private boolean jj_3R_IdentifierPrime_2037_9_48() - { - if (jj_scan_token(REG_IDENTPRIME)) return true; - return false; - } - static private boolean jj_3R_ExpressionITE_1270_9_75() { if (jj_3R_ExpressionImplies_1286_9_82()) return true; @@ -5658,43 +5655,49 @@ static private boolean jj_3R_ExpressionITE_1270_9_75() return false; } - static private boolean jj_3R_ExpressionProb_1644_17_202() + static private boolean jj_3R_ExpressionProb_1644_17_203() { if (jj_scan_token(MAX)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionProb_1644_26_229()) { + if (jj_3R_ExpressionProb_1644_26_230()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1645_26_230()) { + if (jj_3R_ExpressionProb_1645_26_231()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1646_26_231()) return true; + if (jj_3R_ExpressionProb_1646_26_232()) return true; } } return false; } + static private boolean jj_3R_ExpressionFilter_1987_56_195() + { + if (jj_scan_token(OR)) return true; + return false; + } + static private boolean jj_3R_TimeBound_1256_20_100() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; return false; } static private boolean jj_3R_TimeBound_1255_20_98() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; return false; } - static private boolean jj_3R_ExpressionProb_1640_17_201() + static private boolean jj_3R_ExpressionProb_1640_17_202() { if (jj_scan_token(MIN)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionProb_1640_26_226()) { + if (jj_3R_ExpressionProb_1640_26_227()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1641_26_227()) { + if (jj_3R_ExpressionProb_1641_26_228()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1642_26_228()) return true; + if (jj_3R_ExpressionProb_1642_26_229()) return true; } } return false; @@ -5702,26 +5705,20 @@ static private boolean jj_3R_ExpressionProb_1640_17_201() static private boolean jj_3R_TimeBound_1254_20_96() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; return false; } - static private boolean jj_3R_ExpressionProb_1639_17_200() + static private boolean jj_3R_ExpressionProb_1639_17_201() { if (jj_scan_token(EQ)) return true; if (jj_scan_token(QMARK)) return true; return false; } - static private boolean jj_3R_ExpressionFilter_1983_56_194() - { - if (jj_scan_token(OR)) return true; - return false; - } - static private boolean jj_3R_TimeBound_1253_20_94() { - if (jj_3R_IdentifierExpression_2015_9_32()) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; return false; } @@ -5783,23 +5780,23 @@ static private boolean jj_3R_ExpressionProb_1637_10_167() if (jj_scan_token(P)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionProb_1637_26_198()) jj_scanpos = xsp; + if (jj_3R_ExpressionProb_1637_26_199()) jj_scanpos = xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionProb_1638_25_199()) { + if (jj_3R_ExpressionProb_1638_25_200()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1639_17_200()) { + if (jj_3R_ExpressionProb_1639_17_201()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1640_17_201()) { + if (jj_3R_ExpressionProb_1640_17_202()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1644_17_202()) { + if (jj_3R_ExpressionProb_1644_17_203()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1648_17_203()) { + if (jj_3R_ExpressionProb_1648_17_204()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1649_17_204()) { + if (jj_3R_ExpressionProb_1649_17_205()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1650_17_205()) { + if (jj_3R_ExpressionProb_1650_17_206()) { jj_scanpos = xsp; - if (jj_3R_ExpressionProb_1651_17_206()) return true; + if (jj_3R_ExpressionProb_1651_17_207()) return true; } } } @@ -5845,6 +5842,12 @@ static private boolean jj_3R_TimeBound_1253_9_76() return false; } + static private boolean jj_3R_IdentifierExpression_2019_9_32() + { + if (jj_3R_Identifier_2008_9_29()) return true; + return false; + } + static private boolean jj_3R_ExpressionProb_1635_9_149() { Token xsp; @@ -5876,15 +5879,21 @@ static private boolean jj_3R_ExpressionProb_1635_9_149() return false; } - static private boolean jj_3R_IdentifierExpression_2015_9_32() + static private boolean jj_3R_ExpressionTemporalUnary_1240_17_61() { - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_ExpressionITE_1270_9_75()) return true; return false; } - static private boolean jj_3R_ExpressionTemporalUnary_1240_17_61() + static private boolean jj_3R_ExpressionFilter_1987_34_194() { - if (jj_3R_ExpressionITE_1270_9_75()) return true; + if (jj_scan_token(AND)) return true; + return false; + } + + static private boolean jj_3R_ExpressionFilter_1986_35_192() + { + if (jj_scan_token(MAX)) return true; return false; } @@ -5912,15 +5921,9 @@ static private boolean jj_3R_ExpressionTemporalUnary_1233_19_71() return false; } - static private boolean jj_3R_ExpressionFilter_1983_34_193() + static private boolean jj_3R_Identifier_2008_9_29() { - if (jj_scan_token(AND)) return true; - return false; - } - - static private boolean jj_3R_ExpressionFilter_1982_35_191() - { - if (jj_scan_token(MAX)) return true; + if (jj_scan_token(REG_IDENT)) return true; return false; } @@ -5941,13 +5944,7 @@ static private boolean jj_3R_ExpressionTemporalUnary_1231_17_60() return false; } - static private boolean jj_3R_Identifier_2004_9_29() - { - if (jj_scan_token(REG_IDENT)) return true; - return false; - } - - static private boolean jj_3R_ExpressionLabel_1961_47_189() + static private boolean jj_3R_ExpressionLabel_1965_47_190() { if (jj_scan_token(INIT)) return true; return false; @@ -5964,13 +5961,20 @@ static private boolean jj_3R_ExpressionTemporalUnary_1229_9_55() return false; } + static private boolean jj_3R_ExpressionFilter_1992_11_197() + { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_Expression_1177_9_38()) return true; + return false; + } + static private boolean jj_3R_ExpressionTemporalBinary_1215_19_65() { if (jj_3R_TimeBound_1253_9_76()) return true; return false; } - static private boolean jj_3R_ExpressionFuncArgs_1544_72_197() + static private boolean jj_3R_ExpressionFuncArgs_1544_72_198() { if (jj_scan_token(COMMA)) return true; if (jj_3R_Expression_1177_9_38()) return true; @@ -5979,8 +5983,7 @@ static private boolean jj_3R_ExpressionFuncArgs_1544_72_197() static private boolean jj_3R_ExpressionFilter_1988_11_196() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_Expression_1177_9_38()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; return false; } @@ -5990,39 +5993,39 @@ static private boolean jj_3R_ExpressionTemporalBinary_1214_19_64() return false; } - static private boolean jj_3R_ExpressionFuncOldStyle_1532_83_166() + static private boolean jj_3R_ExpressionFilter_1987_11_193() { - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_scan_token(PLUS)) return true; return false; } - static private boolean jj_3R_ExpressionTemporalBinary_1213_19_63() + static private boolean jj_3R_ExpressionFuncOldStyle_1532_83_166() { - if (jj_scan_token(W)) return true; + if (jj_3R_Identifier_2008_9_29()) return true; return false; } - static private boolean jj_3R_ExpressionTemporalBinary_1212_19_62() + static private boolean jj_3R_ExpressionTemporalBinary_1213_19_63() { - if (jj_scan_token(U)) return true; + if (jj_scan_token(W)) return true; return false; } - static private boolean jj_3R_ExpressionFilter_1984_11_195() + static private boolean jj_3R_ExpressionFilter_1986_11_191() { - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_scan_token(MIN)) return true; return false; } - static private boolean jj_3R_ExpressionFilter_1983_11_192() + static private boolean jj_3R_ExpressionTemporalBinary_1212_19_62() { - if (jj_scan_token(PLUS)) return true; + if (jj_scan_token(U)) return true; return false; } - static private boolean jj_3R_ExpressionFilter_1982_11_190() + static private boolean jj_3R_ExpressionLabel_1965_30_189() { - if (jj_scan_token(MIN)) return true; + if (jj_3R_Identifier_2008_9_29()) return true; return false; } @@ -6043,29 +6046,23 @@ static private boolean jj_3R_ExpressionTemporalBinary_1210_17_56() return false; } - static private boolean jj_3R_ExpressionLabel_1961_30_188() - { - if (jj_3R_Identifier_2004_9_29()) return true; - return false; - } - - static private boolean jj_3R_ExpressionFilter_1977_9_155() + static private boolean jj_3R_ExpressionFilter_1981_9_155() { if (jj_scan_token(FILTER)) return true; if (jj_scan_token(LPARENTH)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionFilter_1982_11_190()) { + if (jj_3R_ExpressionFilter_1986_11_191()) { jj_scanpos = xsp; - if (jj_3R_ExpressionFilter_1982_35_191()) { + if (jj_3R_ExpressionFilter_1986_35_192()) { jj_scanpos = xsp; - if (jj_3R_ExpressionFilter_1983_11_192()) { + if (jj_3R_ExpressionFilter_1987_11_193()) { jj_scanpos = xsp; - if (jj_3R_ExpressionFilter_1983_34_193()) { + if (jj_3R_ExpressionFilter_1987_34_194()) { jj_scanpos = xsp; - if (jj_3R_ExpressionFilter_1983_56_194()) { + if (jj_3R_ExpressionFilter_1987_56_195()) { jj_scanpos = xsp; - if (jj_3R_ExpressionFilter_1984_11_195()) return true; + if (jj_3R_ExpressionFilter_1988_11_196()) return true; } } } @@ -6074,7 +6071,7 @@ static private boolean jj_3R_ExpressionFilter_1977_9_155() if (jj_scan_token(COMMA)) return true; if (jj_3R_Expression_1177_9_38()) return true; xsp = jj_scanpos; - if (jj_3R_ExpressionFilter_1988_11_196()) jj_scanpos = xsp; + if (jj_3R_ExpressionFilter_1992_11_197()) jj_scanpos = xsp; if (jj_scan_token(RPARENTH)) return true; return false; } @@ -6105,7 +6102,7 @@ static private boolean jj_3R_ExpressionFuncOldStyle_1532_60_165() static private boolean jj_3R_SystemHideRename_1127_81_90() { if (jj_scan_token(COMMA)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; return false; } @@ -6115,26 +6112,26 @@ static private boolean jj_3R_ExpressionLiteral_1581_9_159() return false; } - static private boolean jj_3R_ExpressionLiteral_1579_9_158() - { - if (jj_scan_token(TRUE)) return true; - return false; - } - - static private boolean jj_3R_ExpressionLabel_1959_9_154() + static private boolean jj_3R_ExpressionLabel_1963_9_154() { if (jj_scan_token(DQUOTE)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_ExpressionLabel_1961_30_188()) { + if (jj_3R_ExpressionLabel_1965_30_189()) { jj_scanpos = xsp; - if (jj_3R_ExpressionLabel_1961_47_189()) return true; + if (jj_3R_ExpressionLabel_1965_47_190()) return true; } if (jj_scan_token(DQUOTE)) return true; return false; } - static private boolean jj_3R_ExpressionStrategy_1912_51_225() + static private boolean jj_3R_ExpressionLiteral_1579_9_158() + { + if (jj_scan_token(TRUE)) return true; + return false; + } + + static private boolean jj_3R_ExpressionStrategy_1915_51_226() { if (jj_3R_ExpressionReward_1758_9_150()) return true; return false; @@ -6146,7 +6143,7 @@ static private boolean jj_3R_ExpressionLiteral_1568_9_157() return false; } - static private boolean jj_3R_ExpressionStrategyCoalitionPlayer_1945_9_247() + static private boolean jj_3R_ExpressionStrategyCoalitionPlayer_1949_9_248() { Token xsp; xsp = jj_scanpos; @@ -6169,12 +6166,38 @@ static private boolean jj_3R_Expression_1177_9_38() return false; } + static private boolean jj_3R_ExpressionStrategyCoalition_1938_11_249() + { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_ExpressionStrategyCoalitionPlayer_1949_9_248()) return true; + return false; + } + + static private boolean jj_3R_ExpressionStrategyCoalition_1937_11_245() + { + if (jj_3R_ExpressionStrategyCoalitionPlayer_1949_9_248()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_ExpressionStrategyCoalition_1938_11_249()) { jj_scanpos = xsp; break; } + } + return false; + } + static private boolean jj_3R_ExpressionLiteral_1555_9_156() { if (jj_scan_token(REG_INT)) return true; return false; } + static private boolean jj_3R_ExpressionStrategyCoalition_1937_9_241() + { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_ExpressionStrategyCoalition_1937_11_245()) jj_scanpos = xsp; + return false; + } + static private boolean jj_3R_ExpressionLiteral_1554_9_144() { Token xsp; @@ -6192,20 +6215,19 @@ static private boolean jj_3R_ExpressionLiteral_1554_9_144() return false; } - static private boolean jj_3R_ExpressionStrategyCoalition_1934_11_248() + static private boolean jj_3R_ExpressionStrategyCoalition_1935_9_240() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_ExpressionStrategyCoalitionPlayer_1945_9_247()) return true; + if (jj_scan_token(TIMES)) return true; return false; } - static private boolean jj_3R_ExpressionStrategyCoalition_1933_11_244() + static private boolean jj_3R_ExpressionStrategyCoalition_1935_9_224() { - if (jj_3R_ExpressionStrategyCoalitionPlayer_1945_9_247()) return true; Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_ExpressionStrategyCoalition_1934_11_248()) { jj_scanpos = xsp; break; } + xsp = jj_scanpos; + if (jj_3R_ExpressionStrategyCoalition_1935_9_240()) { + jj_scanpos = xsp; + if (jj_3R_ExpressionStrategyCoalition_1937_9_241()) return true; } return false; } @@ -6216,38 +6238,13 @@ static private boolean jj_3R_ExpressionFuncMinMax_1518_42_162() return false; } - static private boolean jj_3R_ExpressionStrategyCoalition_1933_9_240() - { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_ExpressionStrategyCoalition_1933_11_244()) jj_scanpos = xsp; - return false; - } - - static private boolean jj_3R_ExpressionStrategyCoalition_1931_9_239() - { - if (jj_scan_token(TIMES)) return true; - return false; - } - - static private boolean jj_3R_ExpressionStrategyCoalition_1931_9_223() - { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_ExpressionStrategyCoalition_1931_9_239()) { - jj_scanpos = xsp; - if (jj_3R_ExpressionStrategyCoalition_1933_9_240()) return true; - } - return false; - } - static private boolean jj_3R_ExpressionFuncArgs_1544_9_163() { if (jj_3R_Expression_1177_9_38()) return true; Token xsp; while (true) { xsp = jj_scanpos; - if (jj_3R_ExpressionFuncArgs_1544_72_197()) { jj_scanpos = xsp; break; } + if (jj_3R_ExpressionFuncArgs_1544_72_198()) { jj_scanpos = xsp; break; } } return false; } @@ -6263,27 +6260,33 @@ static private boolean jj_3R_SystemAtomic_1157_10_79() static private boolean jj_3R_SystemAtomic_1155_10_78() { if (jj_scan_token(DQUOTE)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(DQUOTE)) return true; return false; } + static private boolean jj_3R_ExpressionStrategy_1917_11_188() + { + if (jj_3R_ExpressionParenth_1594_9_148()) return true; + return false; + } + static private boolean jj_3R_SystemAtomic_1153_9_77() { - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; return false; } static private boolean jj_3R_SystemParallel_1097_65_70() { if (jj_scan_token(COMMA)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; return false; } - static private boolean jj_3R_ExpressionStrategy_1914_11_187() + static private boolean jj_3R_ExpressionStrategy_1915_11_225() { - if (jj_3R_ExpressionParenth_1594_9_148()) return true; + if (jj_3R_ExpressionProb_1635_9_149()) return true; return false; } @@ -6301,6 +6304,17 @@ static private boolean jj_3R_SystemAtomic_1150_9_68() return false; } + static private boolean jj_3R_ExpressionStrategy_1915_9_187() + { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_ExpressionStrategy_1915_11_225()) { + jj_scanpos = xsp; + if (jj_3R_ExpressionStrategy_1915_51_226()) return true; + } + return false; + } + static private boolean jj_3R_ExpressionFuncOldStyle_1532_9_147() { if (jj_scan_token(FUNC)) return true; @@ -6320,54 +6334,45 @@ static private boolean jj_3R_ExpressionFuncOldStyle_1532_9_147() return false; } - static private boolean jj_3R_ExpressionStrategy_1912_11_224() + static private boolean jj_3R_ExpressionStrategy_1912_11_186() { - if (jj_3R_ExpressionProb_1635_9_149()) return true; + if (jj_scan_token(LBRACE)) return true; + if (jj_3R_IdentifierExpression_2019_9_32()) return true; + if (jj_scan_token(RBRACE)) return true; return false; } - static private boolean jj_3R_ExpressionStrategy_1912_9_186() + static private boolean jj_3R_ExpressionStrategy_1910_11_185() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_ExpressionStrategy_1912_11_224()) { - jj_scanpos = xsp; - if (jj_3R_ExpressionStrategy_1912_51_225()) return true; - } + if (jj_scan_token(DLBRACKET)) return true; + if (jj_3R_ExpressionStrategyCoalition_1935_9_224()) return true; + if (jj_scan_token(DRBRACKET)) return true; return false; } - static private boolean jj_3R_ExpressionStrategy_1909_11_185() + static private boolean jj_3R_ExpressionStrategy_1909_10_184() { - if (jj_scan_token(DLBRACKET)) return true; - if (jj_3R_ExpressionStrategyCoalition_1931_9_223()) return true; - if (jj_scan_token(DRBRACKET)) return true; + if (jj_scan_token(DLT)) return true; + if (jj_3R_ExpressionStrategyCoalition_1935_9_224()) return true; + if (jj_scan_token(DGT)) return true; return false; } static private boolean jj_3R_SystemHideRename_1134_19_91() { if (jj_scan_token(COMMA)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; if (jj_scan_token(RENAME)) return true; - if (jj_3R_Identifier_2004_9_29()) return true; + if (jj_3R_Identifier_2008_9_29()) return true; return false; } - static private boolean jj_3R_RewardIndex_1817_101_246() + static private boolean jj_3R_RewardIndex_1817_101_247() { if (jj_3R_Expression_1177_9_38()) return true; return false; } - static private boolean jj_3R_ExpressionStrategy_1908_10_184() - { - if (jj_scan_token(DLT)) return true; - if (jj_3R_ExpressionStrategyCoalition_1931_9_223()) return true; - if (jj_scan_token(DGT)) return true; - return false; - } - static private boolean jj_3_9() { if (jj_scan_token(OR)) return true; @@ -6376,6 +6381,24 @@ static private boolean jj_3_9() return false; } + static private boolean jj_3R_ExpressionStrategy_1906_9_153() + { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_ExpressionStrategy_1909_10_184()) { + jj_scanpos = xsp; + if (jj_3R_ExpressionStrategy_1910_11_185()) return true; + } + xsp = jj_scanpos; + if (jj_3R_ExpressionStrategy_1912_11_186()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_ExpressionStrategy_1915_9_187()) { + jj_scanpos = xsp; + if (jj_3R_ExpressionStrategy_1917_11_188()) return true; + } + return false; + } + static private boolean jj_initialized_once = false; /** Generated Token Manager. */ static public PrismParserTokenManager token_source; @@ -6388,7 +6411,7 @@ static private boolean jj_3_9() static private Token jj_scanpos, jj_lastpos; static private int jj_la; static private int jj_gen; - static final private int[] jj_la1 = new int[108]; + static final private int[] jj_la1 = new int[109]; static private int[] jj_la1_0; static private int[] jj_la1_1; static private int[] jj_la1_2; @@ -6400,16 +6423,16 @@ static private boolean jj_3_9() jj_la1_init_3(); } private static void jj_la1_init_0() { - jj_la1_0 = new int[] {0x228804c0,0x208804c0,0x2000000,0x20340848,0x0,0x20340848,0x20340848,0x0,0x20340848,0x400,0x0,0x80,0x480,0x10000210,0x10000210,0x0,0x40,0x0,0x2000000,0x10000030,0x0,0x4000000,0x0,0x0,0x0,0x1740808,0x1740808,0x0,0x0,0x0,0x1740808,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1400000,0x0,0x1740808,0x1740808,0x1740808,0x1740808,0x1740808,0x0,0x0,0x0,0x0,0x0,0x0,0x340808,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x340808,0x340808,0x0,0x0,0x0,0x0,0x40000,0x0,0x0,0x0,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc0000000,0x0,0x0,0x1740808,0x1740808,0x0,0x0,0x9740908,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,}; + jj_la1_0 = new int[] {0x228804c0,0x208804c0,0x2000000,0x20340848,0x0,0x20340848,0x20340848,0x0,0x20340848,0x400,0x0,0x80,0x480,0x10000210,0x10000210,0x0,0x40,0x0,0x2000000,0x10000030,0x0,0x4000000,0x0,0x0,0x0,0x1740808,0x1740808,0x0,0x0,0x0,0x1740808,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1400000,0x0,0x1740808,0x1740808,0x1740808,0x1740808,0x1740808,0x0,0x0,0x0,0x0,0x0,0x0,0x340808,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x340808,0x340808,0x0,0x0,0x0,0x0,0x40000,0x0,0x0,0x0,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc0000000,0x0,0x0,0x1740808,0x1740808,0x0,0x0,0x9740908,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,}; } private static void jj_la1_init_1() { - jj_la1_1 = new int[] {0xfe03a2,0x7e0082,0x800320,0xff51fc11,0x0,0xff51fc11,0xff51fc11,0x0,0xff51fc11,0x80000,0x82,0x0,0x2e0082,0x0,0x0,0x500000,0x500000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff01fc51,0xff01fc51,0x0,0x0,0x0,0xff01fc51,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000000,0x0,0x40000000,0x40,0x0,0xff01fc51,0xff01fc51,0xff01fc51,0xff01fc51,0xff01fc51,0x0,0x0,0x0,0x0,0x0,0x0,0xff01fc11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff01fc11,0xff01fc11,0x0,0x11,0x11,0x0,0x0,0x0,0x11,0x11,0x1d,0x1fc00,0x0,0x0,0x11,0x0,0x0,0x0,0x0,0x0,0x11,0x11,0x1d,0x7f000000,0x0,0xff01fc51,0xff01fc51,0x0,0x80000000,0xff01fc51,0x0,0x7f01fc00,0x7f01fc00,0x0,0x0,0x0,0x0,0x0,0x11,0x0,0x11,0x0,0x0,0x0,}; + jj_la1_1 = new int[] {0xfe03a2,0x7e0082,0x800320,0xff51fc11,0x0,0xff51fc11,0xff51fc11,0x0,0xff51fc11,0x80000,0x82,0x0,0x2e0082,0x0,0x0,0x500000,0x500000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff01fc51,0xff01fc51,0x0,0x0,0x0,0xff01fc51,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000000,0x0,0x40000000,0x40,0x0,0xff01fc51,0xff01fc51,0xff01fc51,0xff01fc51,0xff01fc51,0x0,0x0,0x0,0x0,0x0,0x0,0xff01fc11,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff01fc11,0xff01fc11,0x0,0x11,0x11,0x0,0x0,0x0,0x11,0x11,0x1d,0x1fc00,0x0,0x0,0x11,0x0,0x0,0x0,0x0,0x0,0x11,0x11,0x1d,0x7f000000,0x0,0xff01fc51,0xff01fc51,0x0,0x80000000,0xff01fc51,0x0,0x0,0x7f01fc00,0x7f01fc00,0x0,0x0,0x0,0x0,0x0,0x11,0x0,0x11,0x0,0x0,0x0,}; } private static void jj_la1_init_2() { - jj_la1_2 = new int[] {0x3,0x1,0x2,0x8088024,0x1000,0x8088024,0x8088024,0x1000,0x8088024,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x800000,0x0,0x20000,0x0,0x0,0x20000,0x0,0x80000000,0x80a8024,0x80a8024,0x40,0x8004,0x2000,0x80a8024,0x0,0x20000,0x2000,0x2000,0x200000,0x2000,0x2000,0x200000,0x8000,0x18,0x66820000,0x18,0x0,0x66820000,0x8088024,0x8088024,0x8088024,0x8088024,0x8088024,0x66820000,0x0,0x100,0x200,0x80,0x40,0x8088024,0x1800000,0x66000000,0x80000000,0x80000000,0x0,0x0,0x0,0x8088004,0x8088004,0x8000,0x0,0x0,0x2000,0x4,0x8000,0x800000,0x800000,0x66800000,0x0,0x200000,0x200000,0x0,0x8000,0x66808000,0x200000,0x8000,0x200000,0x800000,0x800000,0x66800000,0x0,0x200000,0x8088024,0x8088024,0x0,0x0,0x8088024,0x8080000,0x0,0x8000,0x2000,0x0,0x0,0x0,0x0,0x800000c0,0x2000,0x0,0x1800000,0x66000000,0x800,}; + jj_la1_2 = new int[] {0x3,0x1,0x2,0x8088024,0x1000,0x8088024,0x8088024,0x1000,0x8088024,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x800000,0x0,0x20000,0x0,0x0,0x20000,0x0,0x80000000,0x80a8024,0x80a8024,0x40,0x8004,0x2000,0x80a8024,0x0,0x20000,0x2000,0x2000,0x200000,0x2000,0x2000,0x200000,0x8000,0x18,0x66820000,0x18,0x0,0x66820000,0x8088024,0x8088024,0x8088024,0x8088024,0x8088024,0x66820000,0x0,0x100,0x200,0x80,0x40,0x8088024,0x1800000,0x66000000,0x80000000,0x80000000,0x0,0x0,0x0,0x8088004,0x8088004,0x8000,0x0,0x0,0x2000,0x4,0x8000,0x800000,0x800000,0x66800000,0x0,0x200000,0x200000,0x0,0x8000,0x66808000,0x200000,0x8000,0x200000,0x800000,0x800000,0x66800000,0x0,0x200000,0x8088024,0x8088024,0x0,0x0,0x8088024,0x8080000,0x200000,0x0,0x8000,0x2000,0x0,0x0,0x0,0x0,0x800000c0,0x2000,0x0,0x1800000,0x66000000,0x800,}; } private static void jj_la1_init_3() { - jj_la1_3 = new int[] {0x0,0x0,0x0,0xb81,0x0,0xb81,0xb81,0x0,0xb81,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x800,0x0,0xb81,0xb81,0x0,0x0,0x0,0xb81,0x800,0x0,0x0,0x0,0x4,0x0,0x0,0x4,0x880,0x0,0x0,0x0,0x0,0x0,0xb81,0xb81,0xb81,0xb81,0xb81,0x0,0x40,0x0,0x0,0x0,0x0,0xb81,0x0,0x0,0x1,0x1,0x6,0x6,0x8,0xb81,0xb80,0x0,0x0,0x800,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb81,0xb81,0x4,0x0,0xb81,0x0,0x0,0x0,0x0,0x900,0x2,0x900,0x800,0x800,0x0,0x800,0x0,0x0,0x0,}; + jj_la1_3 = new int[] {0x0,0x0,0x0,0xb81,0x0,0xb81,0xb81,0x0,0xb81,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x800,0x0,0xb81,0xb81,0x0,0x0,0x0,0xb81,0x800,0x0,0x0,0x0,0x4,0x0,0x0,0x4,0x880,0x0,0x0,0x0,0x0,0x0,0xb81,0xb81,0xb81,0xb81,0xb81,0x0,0x40,0x0,0x0,0x0,0x0,0xb81,0x0,0x0,0x1,0x1,0x6,0x6,0x8,0xb81,0xb80,0x0,0x0,0x800,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb81,0xb81,0x4,0x0,0xb81,0x0,0x0,0x0,0x0,0x0,0x900,0x2,0x900,0x800,0x800,0x0,0x800,0x0,0x0,0x0,}; } static final private JJCalls[] jj_2_rtns = new JJCalls[18]; static private boolean jj_rescan = false; @@ -6433,7 +6456,7 @@ public PrismParser(java.io.InputStream stream, String encoding) { token = new Token(); jj_ntk = -1; jj_gen = 0; - for (int i = 0; i < 108; i++) jj_la1[i] = -1; + for (int i = 0; i < 109; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } @@ -6448,7 +6471,7 @@ static public void ReInit(java.io.InputStream stream, String encoding) { token = new Token(); jj_ntk = -1; jj_gen = 0; - for (int i = 0; i < 108; i++) jj_la1[i] = -1; + for (int i = 0; i < 109; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } @@ -6466,7 +6489,7 @@ public PrismParser(java.io.Reader stream) { token = new Token(); jj_ntk = -1; jj_gen = 0; - for (int i = 0; i < 108; i++) jj_la1[i] = -1; + for (int i = 0; i < 109; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } @@ -6485,7 +6508,7 @@ static public void ReInit(java.io.Reader stream) { token = new Token(); jj_ntk = -1; jj_gen = 0; - for (int i = 0; i < 108; i++) jj_la1[i] = -1; + for (int i = 0; i < 109; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } @@ -6502,7 +6525,7 @@ public PrismParser(PrismParserTokenManager tm) { token = new Token(); jj_ntk = -1; jj_gen = 0; - for (int i = 0; i < 108; i++) jj_la1[i] = -1; + for (int i = 0; i < 109; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } @@ -6512,7 +6535,7 @@ public void ReInit(PrismParserTokenManager tm) { token = new Token(); jj_ntk = -1; jj_gen = 0; - for (int i = 0; i < 108; i++) jj_la1[i] = -1; + for (int i = 0; i < 109; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } @@ -6648,7 +6671,7 @@ static public ParseException generateParseException() { la1tokens[jj_kind] = true; jj_kind = -1; } - for (int i = 0; i < 108; i++) { + for (int i = 0; i < 109; i++) { if (jj_la1[i] == jj_gen) { for (int j = 0; j < 32; j++) { if ((jj_la1_0[i] & (1<> or [[...]] (( begin = { ret = new ExpressionStrategy(true); } ExpressionStrategyCoalition(ret) ) | (begin = { ret = new ExpressionStrategy(false); } ExpressionStrategyCoalition(ret) )) + // Optional modifier + ( modifier = IdentifierExpression() )? // Child expression ( ( expr = ExpressionProb(prop, pathprop) | expr = ExpressionReward(prop, pathprop) ) @@ -1915,6 +1918,7 @@ Expression ExpressionStrategy(boolean prop, boolean pathprop) : { ret.addOperand(expr); } )) { + ret.setModifier(modifier == null ? null : modifier.getName()); ret.setPosition(begin, getToken(0)); return ret; } diff --git a/prism/src/parser/ast/ExpressionStrategy.java b/prism/src/parser/ast/ExpressionStrategy.java index 4afca9cfba..1a313c90af 100644 --- a/prism/src/parser/ast/ExpressionStrategy.java +++ b/prism/src/parser/ast/ExpressionStrategy.java @@ -46,6 +46,9 @@ public class ExpressionStrategy extends Expression /** Coalition info (for game models) */ protected Coalition coalition = new Coalition(); + /** Optional "modifier" to specify variants */ + protected String modifier = null; + /** Child expression(s) */ protected ArrayList operands = new ArrayList(); @@ -87,6 +90,14 @@ public void setCoalition(List coalition) this.coalition.setPlayers(coalition); } + /** + * Set the (optional) "modifier" for this operator. + */ + public void setModifier(String modifier) + { + this.modifier = modifier; + } + public void setSingleOperand(Expression expression) { operands.clear(); @@ -139,6 +150,22 @@ public boolean hasSingleOperand() return singleOperand; } + /** + * Get the (optional) "modifier" for this operator. + */ + public String getModifier() + { + return modifier; + } + + /** + * Get a string representing the modifier as a suffix for the operator. + */ + public String getModifierString() + { + return modifier == null ? "" : "{" + modifier + "}"; + } + public int getNumOperands() { return operands.size(); @@ -223,6 +250,7 @@ public String toString() s += (thereExists ? "<<" : "[["); s += coalition; s += (thereExists ? ">> " : "]] "); + s += getModifierString(); if (singleOperand) { s += operands.get(0); } else { @@ -246,6 +274,7 @@ public int hashCode() final int prime = 31; int result = 1; result = prime * result + ((coalition == null) ? 0 : coalition.hashCode()); + result = prime * result + ((modifier == null) ? 0 : modifier.hashCode()); result = prime * result + ((operands == null) ? 0 : operands.hashCode()); result = prime * result + (singleOperand ? 1231 : 1237); result = prime * result + (thereExists ? 1231 : 1237); @@ -267,6 +296,11 @@ public boolean equals(Object obj) return false; } else if (!coalition.equals(other.coalition)) return false; + if (modifier == null) { + if (other.modifier != null) + return false; + } else if (!modifier.equals(other.modifier)) + return false; if (operands == null) { if (other.operands != null) return false; diff --git a/prism/src/symbolic/comp/NondetModelChecker.java b/prism/src/symbolic/comp/NondetModelChecker.java index 62a6b0c7e7..eae5c501e9 100644 --- a/prism/src/symbolic/comp/NondetModelChecker.java +++ b/prism/src/symbolic/comp/NondetModelChecker.java @@ -231,7 +231,11 @@ protected StateValues checkExpressionStrategy(ExpressionStrategy expr, JDDNode s coalition = null; } - // Process operand(s) + // Multi-strategies not supported + if ("multi".equals(expr.getModifier())) { + throw new PrismNotSupportedException("Multi-strategy synthesis not supported by this engine"); + } + List exprs = expr.getOperands(); // Pass onto relevant method: // Single P operator diff --git a/prism/tests/robot.nm b/prism/tests/robot.nm new file mode 100644 index 0000000000..eb517c8c02 --- /dev/null +++ b/prism/tests/robot.nm @@ -0,0 +1,32 @@ +mdp + +module M + +s:[0..5]; + +[east] s=0 -> 0.6:(s'=1) + 0.4:(s'=0); +[south] s=0 -> 0.8:(s'=3) + 0.1:(s'=1) + 0.1:(s'=4); +[east] s=1 -> 1:(s'=2); +[south] s=1 -> 0.5:(s'=4) + 0.5:(s'=2); +[stuck] s=2 -> 1:(s'=2); +[stuck] s=3 -> 1:(s'=3); +[east] s=4 -> 1:(s'=5); +[west] s=4 -> 0.6:(s'=3) + 0.4:(s'=4); +[north] s=5 -> 0.9:(s'=2) + 0.1:(s'=5); +[west] s=5 -> 1:(s'=4); + +endmodule + +label "hazard" = s=1; +label "goal1" = s=5; +label "goal2" = s=2|s=3; + +rewards "time" + +[north] s!=5 : 1; +[east] s!=5 : 1; +[south] s!=5 : 1; +[west] s!=5 : 1; +[stuck] s!=5 : 1; + +endrewards From ff4f107e1ba7f189115ffcaab45a5919c742fd54 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Thu, 8 May 2025 16:19:39 -0400 Subject: [PATCH 04/11] MDP multi strat resolved --- prism/src/explicit/IMDPModelChecker.java | 37 ++++ prism/src/explicit/MDPModelChecker.java | 223 +++++++++++++---------- prism/src/explicit/ProbModelChecker.java | 13 +- prism/src/strat/MDStrategyArray.java | 6 +- prism/src/strat/Strategy.java | 1 + 5 files changed, 183 insertions(+), 97 deletions(-) diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index 8f148fd184..eed4d334b0 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -27,6 +27,8 @@ package explicit; import java.util.BitSet; +import java.util.Iterator; +import java.util.Map; import java.util.PrimitiveIterator; import acceptance.AcceptanceReach; @@ -47,6 +49,15 @@ import strat.MDStrategyArray; import strat.Strategy; +import com.gurobi.gurobi.GRB; +import com.gurobi.gurobi.GRBEnv; +import com.gurobi.gurobi.GRBException; +import com.gurobi.gurobi.GRBLinExpr; +import com.gurobi.gurobi.GRBModel; +import com.gurobi.gurobi.GRBVar; +import lpsolve.LpSolve; +import lpsolve.LpSolveException; + /** * Explicit-state model checker for interval Markov decision prcoesses (IMDPs). */ @@ -591,6 +602,32 @@ public ModelCheckerResult computeReachRewards(IMDP imdp, MDPRewards mdp, MDPRewards mdpRewards, double bound) throws PrismException + { + boolean min = true; + double[] soln = null; + + // Start solution + long timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (" + (min ? "min" : "max") + ")..."); + + System.out.println("yucky"); + + // Return results + ModelCheckerResult res = new ModelCheckerResult(); +// res.accuracy = AccuracyFactory.boundedNumericalIterations(); + res.soln = soln; +// res.timeTaken = timer / 1000.0; + return res; + } /** * Simple test program. diff --git a/prism/src/explicit/MDPModelChecker.java b/prism/src/explicit/MDPModelChecker.java index 2d6ef1b2d0..403a1f2f46 100644 --- a/prism/src/explicit/MDPModelChecker.java +++ b/prism/src/explicit/MDPModelChecker.java @@ -26,13 +26,16 @@ package explicit; +import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.PrimitiveIterator; +import java.util.TreeMap; import acceptance.AcceptanceReach; import acceptance.AcceptanceType; @@ -73,9 +76,11 @@ import prism.PrismUtils; import strat.FMDStrategyProduct; import strat.FMDStrategyStep; +import strat.MDPMultiStrat; import strat.MDStrategy; import strat.MDStrategyArray; import strat.Strategy; +import strat.MDPMultiStrat; /** * Explicit-state model checker for Markov decision processes (MDPs). @@ -3133,144 +3138,172 @@ public ModelCheckerResult computeMultiStrategy(MDP mdp, MDPRewards v; + Map eta; + + // Value-function + v = new HashMap<>(); + for (int s = 0; s (); + for (int s = 0; s = 1.0, deter == 1.0) + for (int s = 0; s < n; s++){ + GRBLinExpr expr = new GRBLinExpr(); + int numChoices = mdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s + "-" + c; + expr.addTerm(1.0, eta.get(sc)); } - model.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "c" + counter++); + m.addConstr(expr,GRB.GREATER_EQUAL, 1.0, null); } - for (int s = 0; s < n; s++) { + + // Bellman constraint + for (int s = 0; s < n; s ++){ int numChoices = mdp.getNumChoices(s); - for (int i = 0; i < numChoices; i++) { - int count = 0; - row[count] = 1.0; - colno[count] = s + 1; - count++; - Iterator> iter = mdp.getTransitionsIterator(s, i); - while (iter.hasNext()) { + for (int c = 0; c < numChoices; c++){ + GRBLinExpr expr = new GRBLinExpr(); + double reward = mdpRewards.getTransitionReward(s, c); + Iterator> iter = mdp.getTransitionsIterator(s, c); + expr.addConstant(reward); + GRBLinExpr ins = new GRBLinExpr(); + while (iter.hasNext()){ Map.Entry e = iter.next(); int t = e.getKey(); - double p = e.getValue(); - if (t == s) { - row[0] -= p; - } else { - row[count] = -p; - colno[count] = t + 1; - count++; - } + Double transition_val = e.getValue(); + ins.addTerm(transition_val, v.get(t)); } - // TODO state rewards? - double r = mdpRewards.getTransitionReward(s, i); - expr = new GRBLinExpr(); - for (int j = 0; j < count; j++) { - expr.addTerm(row[j], xVars[colno[j] - 1]); + expr.add(ins); + String sc = s +"-"+c; + if (min == true){ + expr.addConstant(-BIG); + expr.addTerm(+BIG,eta.get(sc)); + } else { + expr.addConstant(+BIG); + expr.addTerm(-BIG,eta.get(sc)); } - expr.addTerm(scale, yaVars[s][i]); - model.addConstr(expr, GRB.LESS_EQUAL, r + scale, "c" + counter++); - } + m.addConstr(v.get(s),GRB.GREATER_EQUAL,expr,"bell-"+sc); + } } - // Solve MILP - model.write("gurobi.lp"); - model.optimize(); - if (model.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { -// model.computeIIS(); -// System.out.println("\nThe following constraint(s) " + "cannot be satisfied:"); -// for (GRBConstr c : model.getConstrs()) { -// if (c.get(GRB.IntAttr.IISConstr) == 1) { -// System.out.println(c.get(GRB.StringAttr.ConstrName)); -// } -// } - throw new PrismException("Error solving LP: " + "infeasible"); - } - if (model.get(GRB.IntAttr.Status) == GRB.Status.UNBOUNDED) { - throw new PrismException("Error solving LP: " + "unbounded"); - } - if (model.get(GRB.IntAttr.Status) != GRB.Status.OPTIMAL) { - throw new PrismException("Error solving LP: " + "non-optimal " + model.get(GRB.IntAttr.Status)); + + // Bound for v[0]; + if (min == true){ + m.addConstr(v.get(sInit), GRB.LESS_EQUAL, bound, "multi-bound"); + } else { + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); } - soln = new double[n]; + m.update(); + + // Objective + GRBLinExpr pen = new GRBLinExpr(); + for (int s = 0; s < n; s++){ + int numChoices = mdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + + // set the model’s objective to pen, minimize it + m.setObjective(pen, GRB.MINIMIZE); + + // now optimize + m.optimize(); + + // build a map from state → list of allowed choices + Map> allowed = new TreeMap<>(); for (int s = 0; s < n; s++) { - System.out.println(xVars[s].get(GRB.StringAttr.VarName) + " = "+xVars[s].get(GRB.DoubleAttr.X)); - soln[s] = xVars[s].get(GRB.DoubleAttr.X); + allowed.put(s, new ArrayList<>()); } + for (int s = 0; s < n; s++) { int numChoices = mdp.getNumChoices(s); - for (int i = 0; i < numChoices; i++) { - System.out.println(yaVars[s][i].get(GRB.StringAttr.VarName) + " = " + yaVars[s][i].get(GRB.DoubleAttr.X)); + int[] tempC = new int[numChoices]; + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBVar var = eta.get(sc); + if (var.get(GRB.DoubleAttr.X) > 0.5) { + // eta[s,c] = 1 in the solution → choice c is allowed in state s + allowed.get(s).add(c); + tempC[c] = c; + } } + choices[s] = tempC; + } + + // now print + System.out.println("Multi‑strategy:"); + for (int s = 0; s < n; s++) { + List c = allowed.get(s); + if (s == 10) continue; + System.out.println(" state " + s + ": allow " + c); } - // Print multi-strategy + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + if (min==true){ + mainLog.println("Multi Strategy to Obtain at most " + bound); + } else { + mainLog.println("Multi Strategy to Obtain at least " + bound); + } + + mainLog.println("Multi Strategy to Obtain " + bound); for (int s = 0; s < n; s++) { mainLog.print(s + ":"); int numChoices = mdp.getNumChoices(s); for (int i = 0; i < numChoices; i++) { - if (yaVars[s][i].get(GRB.DoubleAttr.X) > 0) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { mainLog.print(" " + mdp.getAction(s, i)); } } mainLog.println(); } - // Clean up - model.dispose(); + m.dispose(); env.dispose(); - } catch (GRBException e) { + } catch (GRBException e) { throw new PrismException("Error solving LP: " +e.getMessage()); } - + + //soln[0] = 0; // Return results ModelCheckerResult res = new ModelCheckerResult(); // res.accuracy = AccuracyFactory.boundedNumericalIterations(); + res.soln = soln; + //res.strat = new MDPMultiStrat<>(mdp, choices); // res.timeTaken = timer / 1000.0; return res; } diff --git a/prism/src/explicit/ProbModelChecker.java b/prism/src/explicit/ProbModelChecker.java index 987c161d44..c05addcf4b 100644 --- a/prism/src/explicit/ProbModelChecker.java +++ b/prism/src/explicit/ProbModelChecker.java @@ -641,11 +641,22 @@ protected StateValues checkExpressionMultiStrategy(Model model, ExpressionStrate Rewards modelRewards = constructRewards(model, r); // Only support MDPs + ModelCheckerResult res = null; + switch (model.getModelType()) { + case MDP: + res = ((MDPModelChecker) this).computeMultiStrategy((MDP) model, (MDPRewards) modelRewards, opInfo.getBound()); + break; + case IMDP: + res = ((IMDPModelChecker) this).computeMultiStrategy((IMDP) model, (MDPRewards) modelRewards, opInfo.getBound()); + break; + default: + throw new PrismNotSupportedException("Cannot model check " + expr + " for " + model.getModelType() + "s"); + } if (model.getModelType() != ModelType.MDP) { throw new PrismNotSupportedException("Multi-strategy synthesis not supported for " + model.getModelType() + "s"); } - ModelCheckerResult res = ((MDPModelChecker) this).computeMultiStrategy((MDP) model, (MDPRewards) modelRewards, opInfo.getBound()); + //ModelCheckerResult res = ((MDPModelChecker) this).computeMultiStrategy((MDP) model, (MDPRewards) modelRewards, opInfo.getBound()); result.setStrategy(res.strat); return StateValues.createFromDoubleArrayResult(res, model); diff --git a/prism/src/strat/MDStrategyArray.java b/prism/src/strat/MDStrategyArray.java index 7966e8bc97..3721f2ecc3 100644 --- a/prism/src/strat/MDStrategyArray.java +++ b/prism/src/strat/MDStrategyArray.java @@ -56,7 +56,7 @@ public MDStrategyArray(NondetModel model, int choices[]) super(model); this.choices = choices; } - + @Override public Object getChoiceAction(int s, int m) { @@ -69,6 +69,10 @@ public int getChoiceIndex(int s, int m) { return choices[s]; } + public int[] getChoiceIndexMulti(int s, int m) + { + return null; + } @Override public UndefinedReason whyUndefined(int s, int m) diff --git a/prism/src/strat/Strategy.java b/prism/src/strat/Strategy.java index ec66d47996..3dfb7cbcc0 100644 --- a/prism/src/strat/Strategy.java +++ b/prism/src/strat/Strategy.java @@ -99,6 +99,7 @@ public default Object sampleChoiceAction(int s, int m, RandomNumberGenerator rng * Pass an arbitrary value (e.g. -1) for m if memory is not relevant. */ public int getChoiceIndex(int s, int m); + public int[] getChoiceIndexMulti(int s, int m); /** * Is a choice defined by the strategy in the state index s From 0c2a04134110b9093394f80aa8917be3f7586317 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Thu, 8 May 2025 22:39:05 -0400 Subject: [PATCH 05/11] optimistic add --- prism/src/explicit/IMDPModelChecker.java | 359 ++++++++++++++++++++++- prism/src/explicit/ProbModelChecker.java | 6 +- 2 files changed, 360 insertions(+), 5 deletions(-) diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index eed4d334b0..f514163a1f 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -26,10 +26,14 @@ package explicit; +import java.util.ArrayList; import java.util.BitSet; +import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.PrimitiveIterator; +import java.util.TreeMap; import acceptance.AcceptanceReach; import common.IntSet; @@ -53,6 +57,7 @@ import com.gurobi.gurobi.GRBEnv; import com.gurobi.gurobi.GRBException; import com.gurobi.gurobi.GRBLinExpr; +import com.gurobi.gurobi.GRBQuadExpr; import com.gurobi.gurobi.GRBModel; import com.gurobi.gurobi.GRBVar; import lpsolve.LpSolve; @@ -610,16 +615,366 @@ public ModelCheckerResult computeReachRewards(IMDP imdp, MDPRewards mdp, MDPRewards mdpRewards, double bound) throws PrismException + public ModelCheckerResult computeMultiStrategy(IMDP imdp, MDPRewards mdpRewards, double bound) throws PrismException { boolean min = true; + boolean robust = false; double[] soln = null; // Start solution long timer = System.currentTimeMillis(); mainLog.println("Starting linear programming (" + (min ? "min" : "max") + ")..."); - System.out.println("yucky"); + int n = imdp.getNumStates(); + int sInit = imdp.getFirstInitialState(); + // Find states where max expected total reward is 0 + int[] target = new int[1]; + target[0]=10; + double BIG = 1000.0; + if (robust==true){ + mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); + try { + // Initialise MILP solver + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + GRBModel m = new GRBModel(env); + Map v; + Map eta, lam; + Map> uplus, umin; + + // Value-function + v = new HashMap<>(); + for (int s = 0; s (); + lam = new HashMap<>(); + uplus = new HashMap<>(); + umin = new HashMap<>(); + for (int s = 0; s ()); + umin.put(sc, new HashMap<>()); + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc + "->" + t; + GRBVar up = m.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,"umin["+key+"]"); + uplus.get(sc).put(t, up); + umin.get(sc).put(t, um); + GRBLinExpr allowed = new GRBLinExpr(); + allowed.addTerm(BIG, eta.get(sc)); + m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); + m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); + m.addConstr(uplus.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uPlusHigh-"+sc+"-"+t); + m.addConstr(umin.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uMinHigh-"+sc+"-"+t); + GRBLinExpr dualExpr = new GRBLinExpr(); + dualExpr.addTerm(1.0, lam.get(sc)); + dualExpr.addTerm(1.0, uplus.get(sc).get(t)); + dualExpr.addTerm(-1.0, umin.get(sc).get(t)); + m.addConstr(dualExpr, GRB.GREATER_EQUAL, v.get(t), "dualFeas_"+sc+"_"+t); + System.out.println(transition_val); + } + } + } + + // Action per state Constraint (multi >= 1.0, deter == 1.0) + for (int s = 0; s < n; s++){ + GRBLinExpr expr = new GRBLinExpr(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s + "-" + c; + expr.addTerm(1.0, eta.get(sc)); + } + m.addConstr(expr,GRB.GREATER_EQUAL, 1.0, null); + } + + //Pre-bell + Map phi = new HashMap<>(); + for (int s = 0; s < n; s++) { + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); + GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); + phi.put(sc, phiVar); + + // 1) φ ≤ λ + m.addConstr(phiVar, GRB.LESS_EQUAL, lamVar, "philem1-" + sc); + + // 2) φ ≤ BIG * η → build RHS as a LinExpr + GRBLinExpr rhs2 = new GRBLinExpr(); + rhs2.addTerm(BIG, etaVar); + m.addConstr(phiVar, GRB.LESS_EQUAL, rhs2, "philem2-" + sc); + + // 3) φ ≥ λ − BIG*(1−η) + GRBLinExpr c3 = new GRBLinExpr(); + c3.addTerm(1.0, phiVar); + c3.addTerm(-1.0, lamVar); + c3.addConstant(BIG); + c3.addTerm(-BIG, etaVar); + m.addConstr(c3, GRB.GREATER_EQUAL, 0.0, "philem3-" + sc); + } + } + m.update(); + + + // Bellman constraint + for (int s = 0; s < n; s++) { + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBLinExpr expr = new GRBLinExpr(); + expr.addConstant(mdpRewards.getTransitionReward(s,c)); + + // add phi = λ·η + expr.addTerm(1.0, phi.get(sc)); + + // add ∑[hi·uplus – lo·umin] + GRBLinExpr ins = new GRBLinExpr(); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); + ins.addTerm( hi, uplus.get(sc).get(t) ); + ins.addTerm(-lo, umin .get(sc).get(t) ); + } + expr.add(ins); + + // add big‑M disable term + if (min) { + expr.addConstant(-BIG); + expr.addTerm( BIG, eta.get(sc) ); + } else { + expr.addConstant(+BIG); + expr.addTerm(-BIG, eta.get(sc) ); + } + + // post v[s] ≥ expr + m.addConstr( v.get(s), GRB.GREATER_EQUAL, expr, "bell-"+sc ); + } + } + + // Bound for v[0]; + if (min == true){ + m.addConstr(v.get(sInit), GRB.LESS_EQUAL, bound, "multi-bound"); + } else { + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); + } + m.update(); + + // Objective + GRBLinExpr pen = new GRBLinExpr(); + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + // set the model’s objective to pen, minimize it + m.setObjective(pen, GRB.MINIMIZE); + + // now optimize + m.optimize(); + + System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + if (min==true){ + mainLog.println("Multi Strategy to Obtain at most under worst assumption of adversary " + bound); + } else { + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + } + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + + // Clean up + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } else { + + + // Multi-strategy under best assumption + mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); + try { + // create environment & model + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + GRBModel m = new GRBModel(env); + + // --- 1) Value‐function vars v[s] --- + Map v = new HashMap<>(); + for (int s = 0; s < n; s++) { + v.put(s, m.addVar(0.0,GRB.INFINITY, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); + } + for (int t : target) { + m.addConstr(v.get(t), GRB.EQUAL, 0.0, "v-target-"+t); + } + + // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- + Map eta = new HashMap<>(); + Map> delta = new HashMap<>(); + + for (int s = 0; s < n; s++) { + int numC = imdp.getNumChoices(s); + for (int c = 0; c < numC; c++) { + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); + delta.put(sc, new HashMap<>()); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc+"->"+t; + GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); + delta.get(sc).put(t, up); + GRBLinExpr allowedUp = new GRBLinExpr(); + GRBLinExpr allowedLow = new GRBLinExpr(); + allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); + allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); + m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); + m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); + } + GRBLinExpr norm = new GRBLinExpr(); + for (int t : delta.get(sc).keySet()) + norm.addTerm(1.0, delta.get(sc).get(t)); + m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); + } + } + + // --- 3) Action‐selection: sum η ≥ 1 at each state --- + for (int s = 0; s < n; s++) { + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + + // 3g) Bellman + for (int s = 0; s < n; s++) { + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBQuadExpr rhs = new GRBQuadExpr(); + rhs.addConstant(mdpRewards.getTransitionReward(s,c)); + + Iterator>> it = imdp.getTransitionsIterator(s,c); + GRBQuadExpr qexpr = new GRBQuadExpr(); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); + } + + rhs.add(qexpr); + + // add big‑M disable term + if (min) { + rhs.addConstant(-BIG); + rhs.addTerm(BIG,eta.get(sc)); + } else { + rhs.addConstant(+BIG); + rhs.addTerm(-BIG, eta.get(sc) ); + } + + // post v[s] ≥ expr + m.addQConstr(v.get(s), GRB.GREATER_EQUAL, rhs, "bell-"+sc ); + } + } + m.addConstr(v.get(0), GRB.LESS_EQUAL, bound, "prefBound"); + m.update(); + + // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) + GRBLinExpr pen = new GRBLinExpr(); + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + // set the model’s objective to pen, minimize it + m.setObjective(pen, GRB.MINIMIZE); + + + m.optimize(); + System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + if (min==true){ + mainLog.println("Multi Strategy to Obtain at most under worst assumption of adversary " + bound); + } else { + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + } + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } + // Return results ModelCheckerResult res = new ModelCheckerResult(); diff --git a/prism/src/explicit/ProbModelChecker.java b/prism/src/explicit/ProbModelChecker.java index c05addcf4b..a8514e12bc 100644 --- a/prism/src/explicit/ProbModelChecker.java +++ b/prism/src/explicit/ProbModelChecker.java @@ -565,8 +565,8 @@ else if (expr instanceof ExpressionSS) { protected StateValues checkExpressionStrategy(Model model, ExpressionStrategy expr, BitSet statesOfInterest) throws PrismException { // Only support <<>>/[[]] for MDPs right now - if (!(this instanceof MDPModelChecker)) - throw new PrismNotSupportedException("The " + expr.getOperatorString() + " operator is only supported for MDPs currently"); + //if (!(this instanceof MDPModelChecker)) + // throw new PrismNotSupportedException("The " + expr.getOperatorString() + " operator is only supported for MDPs currently"); // Will we be quantifying universally or existentially over strategies/adversaries? boolean forAll = !expr.isThereExists(); @@ -652,7 +652,7 @@ protected StateValues checkExpressionMultiStrategy(Model model, ExpressionStrate default: throw new PrismNotSupportedException("Cannot model check " + expr + " for " + model.getModelType() + "s"); } - if (model.getModelType() != ModelType.MDP) { + if (model.getModelType() != ModelType.MDP && model.getModelType() != ModelType.IMDP ) { throw new PrismNotSupportedException("Multi-strategy synthesis not supported for " + model.getModelType() + "s"); } From 091d20ccdf2ff1cd410b2b4a6b868c672ac22060 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Mon, 9 Jun 2025 11:45:00 -0400 Subject: [PATCH 06/11] Update closed bound --- ac-imdp.prism | 54 + bg-imdp.prism | 28 + chain-imdp-reverse.prism | 23 + chain-imdp.prism | 22 + drone-imdp.prism | 66 + example.prism | 32 + firewire-imdp.prism | 79 ++ prism-examples/imdps/simple/robot.prism | 2 +- prism/src/explicit/IMDPModelChecker.java | 1519 +++++++++++++++++++++- prism/src/strat/Strategy.java | 2 +- robot-imdp.prism | 286 ++++ sav-imdp.prism | 61 + test-imdp.prism | 0 tiny-imdp.prism | 22 + 14 files changed, 2129 insertions(+), 67 deletions(-) create mode 100644 ac-imdp.prism create mode 100644 bg-imdp.prism create mode 100644 chain-imdp-reverse.prism create mode 100644 chain-imdp.prism create mode 100644 drone-imdp.prism create mode 100644 example.prism create mode 100644 firewire-imdp.prism create mode 100644 robot-imdp.prism create mode 100644 sav-imdp.prism create mode 100644 test-imdp.prism create mode 100644 tiny-imdp.prism diff --git a/ac-imdp.prism b/ac-imdp.prism new file mode 100644 index 0000000000..1d9b7bc836 --- /dev/null +++ b/ac-imdp.prism @@ -0,0 +1,54 @@ +mdp + + +const int maxX = 10;//10; +const int maxY = 5;//4; +const double r=0.8; //= 0.820795462532;// = 0.5; // pilot response factor +const double e1 = 0.1; +const double p=0.3;// = 0.19; // prob of adversary moving up or down, ensure 2p <= 1 +const double e2=0.05; + + +formula xclose = (x-ax >= 0 & x-ax < 3) | (ax-x >= 0 & ax-x < 3); +formula yclose = (y-ay >= 0 & y-ay < 2) | (ay-y >= 0 & ay-y < 2); +formula collision = xclose & yclose; + +module aircraft + + x : [0..maxX] init 0; + y : [0..maxY] init 1; + + + [down] x < maxX -> [r-e1,r+e1] : (y'=max(y-1,0)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [up] x < maxX -> [r-e1,r+e1] : (y'=min(y+1,maxY)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [stay] x < maxX -> (y'=y) & (x'=x+1); + + [down] x = maxX -> true; + [up] x = maxX -> true; + [stay] x = maxX -> true; + +endmodule + + +module adversary + + ax : [0..maxX] init maxX; + ay : [0..maxY] init 1; + + [up] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + 1-2*p : (ay'=ay) & (ax'=ax-1); + [down] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + 1-2*p : (ay'=ay) & (ax'=ax-1); + [stay] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + 1-2*p : (ay'=ay) & (ax'=ax-1); + [up] ax = 0 -> true; + [down] ax = 0 -> true; + [stay] ax = 0 -> true; + +endmodule + +rewards + [up] true : 1; + [down] true : 1; + [stay] true : 1; +endrewards + +label "goal" = x=maxX; +label "Crash" = collision; \ No newline at end of file diff --git a/bg-imdp.prism b/bg-imdp.prism new file mode 100644 index 0000000000..d79af7db0e --- /dev/null +++ b/bg-imdp.prism @@ -0,0 +1,28 @@ +mdp + + +const int n = 8; +const double p=0.5; +const double e=0.1; +module bet + + money : [0..(n+1)*10] init 10; + steps : [0..n+1] init 0; // +1 for terminal state + + [bet0] steps < n & money >= 0 -> 1 : (money'=money) & (steps'=steps+1); + [bet1] steps < n & money >= 1 & money <= n*10 -> [p-e,p+e] : (money'=money+1) & (steps'=steps+1) + [1-p-e,1-p+e] : (money'=money-1) & (steps'=steps+1); + [bet2] steps < n & money >= 2 & money <= n*10 -> [p-e,p+e] : (money'=money+2) & (steps'=steps+1) + [1-p-e,1-p+e] : (money'=money-2) & (steps'=steps+1); + [bet5] steps < n & money >= 5 & money <= n*10 -> [p-e,p+e] : (money'=money+5) & (steps'=steps+1) + [1-p-e,1-p+e] : (money'=money-5) & (steps'=steps+1); + [bet10] steps < n & money >=10 & money <= n*10 -> [p-e,p+e] : (money'=money+10) & (steps'=steps+1) + [1-p-e,1-p+e] : (money'=money-10) & (steps'=steps+1); + + [end] steps = n -> 1: (steps'=n+1); + [stop] steps = n+1 -> 1: true; + +endmodule + +rewards + [] steps < n : money; + [end] true : money; +endrewards + +label "goal" = steps = n+1; \ No newline at end of file diff --git a/chain-imdp-reverse.prism b/chain-imdp-reverse.prism new file mode 100644 index 0000000000..6a92122993 --- /dev/null +++ b/chain-imdp-reverse.prism @@ -0,0 +1,23 @@ +mdp + +const double p=0.4; +const double uncertainty=0.05; +const int H = 6; +const double m=200.0; + +module chain + + s : [0..H] init 0; + + [a] true -> [p-uncertainty, p+uncertainty]: (s'=min(s+1,H)) + [1-p-uncertainty,1-p+uncertainty]: (s'=0); + [b] true -> [1-p-uncertainty, 1-p+uncertainty] : (s'=min(s+1,H)) + [p-uncertainty, p+uncertainty] : (s'=0); + [end] (s=H) -> true; + +endmodule + +rewards + [a] true : 1; + [b] true : 1; +endrewards + +label "goal" = s=H; \ No newline at end of file diff --git a/chain-imdp.prism b/chain-imdp.prism new file mode 100644 index 0000000000..1e1ac5a978 --- /dev/null +++ b/chain-imdp.prism @@ -0,0 +1,22 @@ +mdp + +const double p=0.4; +const double uncertainty=0.05; +const int H = 6; + +module chain + + s : [0..H] init 0; + + [a] true -> [p-uncertainty, p+uncertainty]: (s'=min(s+1,H)) + [1-p-uncertainty,1-p+uncertainty]: (s'=0); + [b] true -> [1-p-uncertainty, 1-p+uncertainty] : (s'=min(s+1,H)) + [p-uncertainty, p+uncertainty] : (s'=0); + [end] (s=H) -> true; + +endmodule + +rewards + [a] true : 1; + [b] true : 1; +endrewards + +label "goal" = s=H; \ No newline at end of file diff --git a/drone-imdp.prism b/drone-imdp.prism new file mode 100644 index 0000000000..d91232dcf1 --- /dev/null +++ b/drone-imdp.prism @@ -0,0 +1,66 @@ +mdp + +// Environment Dimensions +const int MAXX = 8; +const int MAXY = 8; +const int MAXZ = 8; + +// Disturbance Probability Parameter +const double p=0.2; // must be less than 1/3 +const double e=0.05; + +// Regions + +// Target Region +formula target = x > MAXX - 2 & y < 2 & z > MAXZ - 2; + +// Obstacle Regions +formula crash = obstacle1 | obstacle2 | obstacle3 | obstacle4; +formula obstacle1 = x >= 3 & x <= 4 & z >= 1 & z <= 2; +formula obstacle2 = x >= 3 & x <= 4 & y >= 1 & y <= 2; +formula obstacle3 = x >= 3 & x <= 4 & y >= 3 & y <= 5; +formula obstacle4 = x >= 3 & x <= 4 & z >= 7 & z <= 8; + +module drone + x : [1..MAXX] init 1; + y : [1..MAXY] init 1; + z : [1..MAXZ] init 1; + + [front] true -> [1 - 3 * p-e,1 - 3 * p+e]: (x' = min(x + 1, MAXX)) + + [p-e,p+e] : (x' = min(x + 1, MAXX)) & (y' = max(y - 1,1)) + + [p-e,p+e] : (x' = min(x + 1, MAXX)) & (y' = min(y + 1, MAXY)) + + [p-e,p+e] : (x' = x) & (y' = max(y - 2, 1)); + + [back] true ->[1 - 3 * p-e,1 - 3 * p+e]: (x' = max(x - 1, 1)) + + [p-e,p+e] : (x' = max(x - 1, 1)) & (y' = max(y - 1,1)) + + [p-e,p+e] : (x' = max(x - 1, 1)) & (y' = min(y + 1, MAXY)) + + [p-e,p+e] : (x' = x) & (y' = max(y - 2, 1)); + + [right] true -> [1 - 2 * p-e,1-2*p+e]: (y' = min(y + 1, MAXY)) + + [p-e,p+e]: (y' = min(y + 2, MAXY)) + + [p-e,p+e]: (y' = max(y - 1, 1)); + + [left] true -> [1 - 2 * p-e,1-2*p+e]: (y' = max(y - 1, 1)) + + [p-e,p+e]: (y' = max(y - 2, 1)) + + [p-e,p+e]: (y' = min(y + 1, MAXY)); + + [up] true -> [1 - 3 * p-e,1 - 3 * p+e]: (z' = min(z + 1, MAXZ)) + + [p-e,p+e] : (z' = min(z + 1, MAXZ)) & (y' = max(y - 1,1)) + + [p-e,p+e] : (z' = min(z + 1, MAXZ)) & (y' = min(y + 1, MAXY)) + + [p-e,p+e] : (z' = z) & (y' = max(y - 2, 1)); + + [down] true ->[1 - 3 * p-e,1 - 3 * p+e]: (z' = max(z - 1,1)) + + [p-e,p+e] : (z' = max(z - 1,1)) & (y' = max(y - 1,1)) + + [p-e,p+e] : (z' = max(z - 1,1)) & (y' = min(y + 1, MAXY)) + + [p-e,p+e] : (z' = z) & (y' = max(y - 2, 1)); + [done] target -> 1:true; + [cry] crash -> 1:true; + +endmodule + +rewards + [] true : 1; +endrewards + +label "goal" = target; +label "Crash" = crash; \ No newline at end of file diff --git a/example.prism b/example.prism new file mode 100644 index 0000000000..126160f47a --- /dev/null +++ b/example.prism @@ -0,0 +1,32 @@ +mdp + +const double e = 0.05; + +module finiteMaxReward + // States 0..4: 0 = initial, 3,4 = target + s : [0..4] init 0; + + // From state 0: two ways to proceed + [goA] s=0 -> [0.5-e,0.5+e] : (s'=1) + [0.5-e,0.5+e] : (s'=2); + [goB] s=0 -> [0.5-e,0.5+e] : (s'=2) + [0.5-e,0.5+e] : (s'=4); + + // From state 1: one step to target + [step] s=1 -> 1.0 : (s'=3); + + // From state 2: one step to target + [step] s=2 -> 1.0 : (s'=4); + + // Target is absorbing (no outgoing transitions) + [end] s=3 -> (s'=3); + [end] s=4 -> (s'=4); +endmodule + +rewards "finiteReward" + // You get reward once, then the chain moves you toward the target. + [goA] s=0 : 5; // higher reward for choosing A + [goB] s=0 : 2; // smaller reward for choosing B + [step] s=1 : 3; // reward for stepping from 1→3 + [step] s=2 : 1; // reward for stepping from 2→3 +endrewards + +label "goal" = (s=3 | s=4); \ No newline at end of file diff --git a/firewire-imdp.prism b/firewire-imdp.prism new file mode 100644 index 0000000000..cf123296d0 --- /dev/null +++ b/firewire-imdp.prism @@ -0,0 +1,79 @@ +// integer semantics version of abstract firewire protocol +// gxn 23/05/2001 + +mdp + +// wire delay +const int delay=1; + +// probability of choosing fast and slow +const double fast=0.5; +const double slow = 1-fast; +const double e = 0.05; + +// largest constant the clock of the system is compared to +const int kx = 167; + +module abstract_firewire + + // clock + x : [0..kx+1]; + + // local state + s : [0..9]; + // 0 -start_start + // 1 -fast_start + // 2 -start_fast + // 3 -start_slow + // 4 -slow_start + // 5 -fast_fast + // 6 -fast_slow + // 7 -slow_fast + // 8 -slow_slow + // 9 -done + + // initial state + [time] s=0 & x (x'=min(x+1,kx+1)); + [round1] s=0 -> [fast-e,fast+e] : (s'=1) + [slow-e,slow+e] : (s'=4); + [round2] s=0 -> [fast-e,fast+e] : (s'=2) + [slow-e,slow+e] : (s'=3); + // fast_start + [time] s=1 & x (x'=min(x+1,kx+1)); + [tfs] s=1 -> fast : (s'=5) & (x'=0) + slow : (s'=6) & (x'=0); + // start_fast + [time] s=2 & x (x'=min(x+1,kx+1)); + [tsf] s=2 -> [fast-e,fast+e] : (s'=5) & (x'=0) + [slow-e,slow+e] : (s'=7) & (x'=0); + // start_slow + [time] s=3 & x (x'=min(x+1,kx+1)); + [tss] s=3 -> fast : (s'=6) & (x'=0) + [slow-e,slow+e] : (s'=8) & (x'=0); + // slow_start + [time] s=4 & x (x'=min(x+1,kx+1)); + [tsls] s=4 -> [fast-e,fast+e] : (s'=7) & (x'=0) +[slow-e,slow+e]: (s'=8) & (x'=0); + // fast_fast + [time] s=5 & (x<85) -> (x'=min(x+1,kx+1)); + [tff] s=5 & (x>=76) -> (s'=0) & (x'=0); + [tff2] s=5 & (x>=76-delay) -> (s'=9) & (x'=0); + // fast_slow + [time] s=6 & x<167 -> (x'=min(x+1,kx+1)); + [tfs] s=6 & x>=159-delay -> (s'=9) & (x'=0); + // slow_fast + [time] s=7 & x<167 -> (x'=min(x+1,kx+1)); + [tsf] s=7 & x>=159-delay -> (s'=9) & (x'=0); + // slow_slow + [time] s=8 & x<167 -> (x'=min(x+1,kx+1)); + [tss] s=8 & x>=159 -> (s'=0) & (x'=0); + [tss] s=8 & x>=159-delay -> (s'=9) & (x'=0); + // done + [done] s=9 -> 1:(s'=s); + +endmodule + +//reward structures +// time +rewards + [time] true : 1; +endrewards +// number of rounds +//rewards "rounds" +// [round] true : 1; +//endrewards +label "goal" = (s=9); \ No newline at end of file diff --git a/prism-examples/imdps/simple/robot.prism b/prism-examples/imdps/simple/robot.prism index 0b83688342..fac1136603 100644 --- a/prism-examples/imdps/simple/robot.prism +++ b/prism-examples/imdps/simple/robot.prism @@ -1,6 +1,6 @@ mdp -const double delta; +const double delta=0.2; const double p = 0.5-delta; const double q = 0.5+delta; diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index f514163a1f..95c28cea6b 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -60,6 +60,7 @@ import com.gurobi.gurobi.GRBQuadExpr; import com.gurobi.gurobi.GRBModel; import com.gurobi.gurobi.GRBVar; +import com.gurobi.gurobi.GRBConstr; import lpsolve.LpSolve; import lpsolve.LpSolveException; @@ -617,20 +618,67 @@ public ModelCheckerResult computeReachRewards(IMDP imdp, MDPRewards imdp, MDPRewards mdpRewards, double bound) throws PrismException { - boolean min = true; - boolean robust = false; + boolean value =false; + boolean min = false; + boolean robust = true; + if (value){ + if (min){ + return computeMultiStrategyValueMin(imdp, mdpRewards, bound, robust); + } else { + return computeMultiStrategyValueMax(imdp, mdpRewards, bound, robust); + } + + } else { + if (min){ + return computeMultiStrategyProbMax(imdp, mdpRewards, bound, robust); + } else { + return computeMultiStrategyProbMax(imdp, mdpRewards, bound, robust); + } + + } + } + + /** + * Compute permissive strategy that satisfy a specified bound -> Rmin >= bound. + * i.e. compute the probability of being in a state in {@code target} in the next step. + * @param imdp The IMDP + * @param mdpRewards Target states + * @param bound limitation bound + * @param robust true -> robust or false -> optimistic + */ + + public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException + { double[] soln = null; // Start solution long timer = System.currentTimeMillis(); - mainLog.println("Starting linear programming (" + (min ? "min" : "max") + ")..."); + mainLog.println("Starting linear programming (min)..."); int n = imdp.getNumStates(); + System.out.println(n); int sInit = imdp.getFirstInitialState(); - // Find states where max expected total reward is 0 - int[] target = new int[1]; - target[0]=10; - double BIG = 1000.0; + + double BIG = 10000.0; + System.out.println(imdp.getLabelStates("goal")); + BitSet targetS = imdp.getLabelStates("goal"); + System.out.println(imdp.getInitialStates()); + IntSet targetStates = IntSet.asIntSet(targetS); + PrimitiveIterator.OfInt states = targetStates.iterator(); + int numTarget = 0; + while(states.hasNext()){ + final int s = states.nextInt(); + numTarget += 1; + } + int[] target = new int[numTarget]; + states = targetStates.iterator(); + int counter = 0; + while(states.hasNext()){ + final int s = states.nextInt(); + target[counter] = s; + counter += 1; + } + System.out.println(target[0]); if (robust==true){ mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); try { @@ -645,7 +693,7 @@ public ModelCheckerResult computeMultiStrategy(IMDP imdp, MDPRewards(); for (int s = 0; s imdp, MDPRewards= 1.0, deter == 1.0) - for (int s = 0; s < n; s++){ + for (int s = 0; s < n; s++) { GRBLinExpr expr = new GRBLinExpr(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String sc = s + "-" + c; - expr.addTerm(1.0, eta.get(sc)); - } - m.addConstr(expr,GRB.GREATER_EQUAL, 1.0, null); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); } //Pre-bell Map phi = new HashMap<>(); + for (int s = 0; s < n; s++) { for (int c = 0; c < imdp.getNumChoices(s); c++) { String sc = s + "-" + c; @@ -710,14 +755,6 @@ public ModelCheckerResult computeMultiStrategy(IMDP imdp, MDPRewards imdp, MDPRewards imdp, MDPRewards>> it = imdp.getTransitionsIterator(s,c); while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); - ins.addTerm( hi, uplus.get(sc).get(t) ); - ins.addTerm(-lo, umin .get(sc).get(t) ); + Map.Entry> e = it.next(); + int t = e.getKey(); + double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); + ins.addTerm( hi, uplus.get(sc).get(t) ); + ins.addTerm(-lo, umin .get(sc).get(t) ); } expr.add(ins); - // add big‑M disable term - if (min) { + expr.addConstant(-BIG); expr.addTerm( BIG, eta.get(sc) ); - } else { - expr.addConstant(+BIG); - expr.addTerm(-BIG, eta.get(sc) ); - } + // post v[s] ≥ expr + m.addConstr( v.get(s), GRB.GREATER_EQUAL, expr, "bell-"+sc ); + } } // Bound for v[0]; - if (min == true){ - m.addConstr(v.get(sInit), GRB.LESS_EQUAL, bound, "multi-bound"); - } else { - m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); - } + + m.addConstr(v.get(sInit), GRB.LESS_EQUAL, bound, "multi-bound"); m.update(); // Objective @@ -784,14 +819,18 @@ public ModelCheckerResult computeMultiStrategy(IMDP imdp, MDPRewards imdp, MDPRewards imdp, MDPRewards v = new HashMap<>(); for (int s = 0; s < n; s++) { v.put(s, m.addVar(0.0,GRB.INFINITY, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); } - for (int t : target) { - m.addConstr(v.get(t), GRB.EQUAL, 0.0, "v-target-"+t); + for (int i = 0; i < numTarget; i++) { + m.addConstr(v.get(target[i]), GRB.EQUAL, 0.0, "v-target-"+target[i]); } + m.update(); // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- Map eta = new HashMap<>(); @@ -908,23 +947,23 @@ public ModelCheckerResult computeMultiStrategy(IMDP imdp, MDPRewards imdp, MDPRewards imdp, MDPRewards Rmax <= bound. + * i.e. compute the probability of being in a state in {@code target} in the next step. + * @param imdp The IMDP + * @param mdpRewards Target states + * @param bound limitation bound + * @param robust true -> robust or false -> optimistic + */ + public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException + { + double[] soln = null; + + // Start solution + long timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (min)..."); + + int n = imdp.getNumStates(); + System.out.println(n); + int sInit = imdp.getFirstInitialState(); + //double BIG = 1000.00; + double BIG =bound + 0.1; + System.out.println(imdp.getLabelStates("goal")); + BitSet targetS = imdp.getLabelStates("goal"); + System.out.println(imdp.getInitialStates()); + IntSet targetStates = IntSet.asIntSet(targetS); + PrimitiveIterator.OfInt states = targetStates.iterator(); + int numTarget = 0; + while(states.hasNext()){ + final int s = states.nextInt(); + numTarget += 1; + } + int[] target = new int[numTarget]; + states = targetStates.iterator(); + int counter = 0; + while(states.hasNext()){ + final int s = states.nextInt(); + target[counter] = s; + counter += 1; + } + System.out.println(target[0]); + if (robust==true){ + mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); + try { + // Initialise MILP solver + GRBEnv env = new GRBEnv("gurobi.log"); + //env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit + //env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + //env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + env.set(GRB.IntParam.MIPFocus, 2); + env.set(GRB.DoubleParam.MIPGap,1e-2); + GRBModel m = new GRBModel(env); + Map v; + Map eta, lam; + Map> uplus, umin; + + // Value-function + v = new HashMap<>(); + for (int s = 0; s (); + lam = new HashMap<>(); + uplus = new HashMap<>(); + umin = new HashMap<>(); + for (int s = 0; s ()); + umin.put(sc, new HashMap<>()); + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc + "->" + t; + GRBVar up = m.addVar(0,BIG,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,BIG,0,GRB.CONTINUOUS,"umin["+key+"]"); + uplus.get(sc).put(t, up); + umin.get(sc).put(t, um); + /* GRBLinExpr allowed = new GRBLinExpr(); + allowed.addTerm(BIG, eta.get(sc));*/ + m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); + m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); + // if ηₛₐ == 1 then uplusₛₐₜ == 0 + GRBLinExpr linP = new GRBLinExpr(); + linP.addTerm(1.0, uplus.get(sc).get(t)); + GRBLinExpr linM = new GRBLinExpr(); + linM.addTerm(1.0, umin.get(sc).get(t)); + m.addGenConstrIndicator(eta.get(sc),1,linP,GRB.EQUAL,0.0,"ind_uplus-"+sc+"-"+t); + // similarly for umin: + m.addGenConstrIndicator(eta.get(sc),1,linM,GRB.EQUAL,0.0,"ind_umin-"+sc+"-"+t); + /* m.addConstr(uplus.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uPlusHigh-"+sc+"-"+t); + m.addConstr(umin.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uMinHigh-"+sc+"-"+t); */ + GRBLinExpr dualExpr = new GRBLinExpr(); + dualExpr.addTerm(1.0, lam.get(sc)); + dualExpr.addTerm(-1.0, uplus.get(sc).get(t)); + dualExpr.addTerm(+1.0, umin.get(sc).get(t)); + m.addConstr(dualExpr, GRB.LESS_EQUAL, v.get(t), "dualFeas_"+sc+"_"+t); + } + } + } + + // Action per state Constraint (multi >= 1.0, deter == 1.0) + for (int s = 0; s < n; s++) { + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + //Pre-bell + Map phi = new HashMap<>(); + for (int s = 0; s < n; s++) { + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); + GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); + phi.put(sc, phiVar); + + // 3) φ <= λ + BIG*(1−η) + GRBLinExpr c3 = new GRBLinExpr(); + c3.addTerm(1.0, phiVar); + c3.addTerm(-1.0, lamVar); + c3.addConstant(-BIG); + c3.addTerm(+BIG, etaVar); + m.addConstr(c3, GRB.LESS_EQUAL, 0.0, "philem3-" + sc); + } + } + + + m.update(); + + + // Bellman constraint + for (int s = 0; s < n; s++) { + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBLinExpr expr = new GRBLinExpr(); + expr.addConstant(mdpRewards.getTransitionReward(s,c)); + + // add phi = λ·η + expr.addTerm(1.0, phi.get(sc)); + + // add ∑[hi·uplus – lo·umin] + GRBLinExpr ins = new GRBLinExpr(); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); + ins.addTerm(-hi, uplus.get(sc).get(t) ); + ins.addTerm(+lo, umin .get(sc).get(t) ); + } + expr.add(ins); + expr.addConstant(+BIG); + expr.addTerm(-BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + m.addConstr( v.get(s), GRB.LESS_EQUAL, expr, "bell-"+sc ); + + + } + } + // Bound for v[0]; + + /* m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); + + m.update(); + double eps = 0.01; + GRBLinExpr tieB = new GRBLinExpr(); + for (int s = 0; s 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + + // Clean up + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } else { + + System.out.println("Hi"); + // Multi-strategy under best assumption + mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); + + try { + // create environment & model + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit + env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + env.set(GRB.DoubleParam.MIPGap,1e-2); + GRBModel m = new GRBModel(env); + m.set(GRB.IntParam.NonConvex, 2); + + // --- 1) Value‐function vars v[s] --- + Map v = new HashMap<>(); + for (int s = 0; s < n; s++) { + v.put(s, m.addVar(0.0,BIG, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); + } + for (int i = 0; i < numTarget; i++) { + m.addConstr(v.get(target[i]), GRB.EQUAL, 0.0, "v-target-"+target[i]); + } + m.update(); + + // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- + Map eta = new HashMap<>(); + Map> delta = new HashMap<>(); + + for (int s = 0; s < n; s++) { + int numC = imdp.getNumChoices(s); + for (int c = 0; c < numC; c++) { + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); + delta.put(sc, new HashMap<>()); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc+"->"+t; + GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); + delta.get(sc).put(t, up); + GRBLinExpr allowedUp = new GRBLinExpr(); + GRBLinExpr allowedLow = new GRBLinExpr(); + allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); + allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); + m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); + m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); + } + GRBLinExpr norm = new GRBLinExpr(); + for (int t : delta.get(sc).keySet()) + norm.addTerm(1.0, delta.get(sc).get(t)); + m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); + } + } + + // --- 3) Action‐selection: sum η ≥ 1 at each state --- + for (int s = 0; s < n; s++) { + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + + // 3g) Bellman + for (int s = 0; s < n; s++) { + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBQuadExpr rhs = new GRBQuadExpr(); + rhs.addConstant(mdpRewards.getTransitionReward(s,c)); + + Iterator>> it = imdp.getTransitionsIterator(s,c); + GRBQuadExpr qexpr = new GRBQuadExpr(); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); + } + + rhs.add(qexpr); + + // add big‑M disable term + rhs.addConstant(+BIG); + rhs.addTerm(-BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + + m.addQConstr(v.get(s), GRB.LESS_EQUAL, rhs, "bell-"+sc ); + + + } + } + + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "prefBound"); + + + m.update(); + + // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) + GRBLinExpr pen = new GRBLinExpr(); + + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + + // set the model’s objective to pen, minimize it + + m.setObjective(pen, GRB.MINIMIZE); + /* GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MAXIMIZE); */ + int numVars = m.get(GRB.IntAttr.NumVars); + int numConstr = m.get(GRB.IntAttr.NumConstrs); + int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types + int numContVars = numVars - numIntVars; + mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + + + m.optimize(); + //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { + System.out.println("Model infeasible—computing IIS..."); + m.computeIIS(); + for (GRBConstr c : m.getConstrs()) { + if (c.get(GRB.IntAttr.IISConstr) == 1) { + System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); + } + } + // Optionally write the IIS to a file: + m.write("model.IIS"); + } + int status = m.get(GRB.IntAttr.Status); + System.out.println("Gurobi Status = " + status); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } + long time = (System.currentTimeMillis() - timer); + mainLog.println("It took "+time + " milli-seconds to finish synthesize the permissive strategy"); + + // Return results + ModelCheckerResult res = new ModelCheckerResult(); +// res.accuracy = AccuracyFactory.boundedNumericalIterations(); + res.soln = soln; +// res.timeTaken = timer / 1000.0; + return res; + } + + public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException + { + double[] soln = null; + + // Start solution + long timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (min)..."); + + int n = imdp.getNumStates(); + System.out.println(n); + int sInit = imdp.getFirstInitialState(); + double BIG = 1.0; + BitSet no = imdp.getLabelStates("Crash"); + BitSet targetS = imdp.getLabelStates("goal"); + System.out.println(targetS); + no.andNot(targetS); + //targetS.andNot(no); + BitSet everything = new BitSet(); + everything.set(0, n); + //everything.andNot(no); + IntSet targetStates = IntSet.asIntSet(targetS); + IntSet eS = IntSet.asIntSet(everything); + PrimitiveIterator.OfInt Tstates = targetStates.iterator(); + int numTarget = 0; + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + numTarget += 1; + } + int[] target = new int[numTarget]; + Tstates = targetStates.iterator(); + int counter = 0; + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + target[counter] = s; + counter += 1; + } + PrimitiveIterator.OfInt states = eS.iterator(); + IntSet nStates = IntSet.asIntSet(no); + PrimitiveIterator.OfInt ns = nStates.iterator(); + System.out.println(no); + if (robust==true){ + mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); + try { + // Initialise MILP solver + GRBEnv env = new GRBEnv("gurobi.log"); + //env.set(GRB.DoubleParam.TimeLimit, 10800.0); // 60-second limit + /* env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + env.set(GRB.IntParam.MIRCuts, 2); + env.set(GRB.IntParam.CoverCuts, 2); + env.set(GRB.IntParam.FlowCoverCuts,2); + env.set(GRB.IntParam.GUBCoverCuts, 2); + env.set(GRB.IntParam.ImpliedCuts, 2); */ + GRBModel m = new GRBModel(env); + Map v; + Map eta, lam; + Map> uplus, umin; + + // Value-function + v = new HashMap<>(); + for (int s = 0; s (); + lam = new HashMap<>(); + uplus = new HashMap<>(); + umin = new HashMap<>(); + states = eS.iterator(); + while(states.hasNext()){ + final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); + lam.put(sc, m.addVar(-BIG,BIG,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + uplus.put(sc, new HashMap<>()); + umin.put(sc, new HashMap<>()); + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc + "->" + t; + GRBVar up = m.addVar(0,BIG,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,BIG,0,GRB.CONTINUOUS,"umin["+key+"]"); + uplus.get(sc).put(t, up); + umin.get(sc).put(t, um); + GRBLinExpr allowed = new GRBLinExpr(); + allowed.addTerm(BIG, eta.get(sc)); + m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); + m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); + m.addConstr(uplus.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uPlusHigh-"+sc+"-"+t); + m.addConstr(umin.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uMinHigh-"+sc+"-"+t); + GRBLinExpr dualExpr = new GRBLinExpr(); + dualExpr.addTerm(1.0, lam.get(sc)); + dualExpr.addTerm(-1.0, uplus.get(sc).get(t)); + dualExpr.addTerm(+1.0, umin.get(sc).get(t)); + m.addConstr(dualExpr, GRB.LESS_EQUAL, v.get(t), "dualFeas_"+sc+"_"+t); + } + } + } + + // Action per state Constraint (multi >= 1.0, deter == 1.0) + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + //Pre-bell + Map phi = new HashMap<>(); + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); + GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); + phi.put(sc, phiVar); + + // 3) φ <= λ + BIG*(1−η) + GRBLinExpr c3 = new GRBLinExpr(); + c3.addTerm(1.0, phiVar); + c3.addTerm(-1.0, lamVar); + c3.addConstant(-BIG); + c3.addTerm(+BIG, etaVar); + m.addConstr(c3, GRB.LESS_EQUAL, 0.0, "philem3-" + sc); + } + } + + + m.update(); + + + // Bellman constraint + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBLinExpr expr = new GRBLinExpr(); + //expr.addConstant(mdpRewards.getTransitionReward(s,c)); + + // add phi = λ·η + expr.addTerm(1.0, phi.get(sc)); + + // add ∑[hi·uplus – lo·umin] + GRBLinExpr ins = new GRBLinExpr(); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); + ins.addTerm(-hi, uplus.get(sc).get(t) ); + ins.addTerm(+lo, umin .get(sc).get(t) ); + } + expr.add(ins); + + expr.addConstant(+BIG); + expr.addTerm(-BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + m.addConstr( v.get(s), GRB.LESS_EQUAL, expr, "bell-"+sc ); + + + } + } + + // Bound for v[0]; + + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); + + m.update(); + + // Objective + GRBLinExpr pen = new GRBLinExpr(); + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + m.setObjective(pen, GRB.MINIMIZE); + // set the model’s objective to pen, minimize it + /* GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MAXIMIZE); */ + + // now optimize + m.optimize(); + + System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + + // Clean up + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } else { + + + // Multi-strategy under best assumption + mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); + + try { + // create environment & model + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit + env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + GRBModel m = new GRBModel(env); + + + // --- 1) Value‐function vars v[s] --- + Map v = new HashMap<>(); + for (int s = 0; s < n; s++) { + v.put(s, m.addVar(0.0,1.0, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); + } + /* for (int i = 0; i < numTarget; i++) { + m.addConstr(v.get(target[i]), GRB.EQUAL, 1.0, "v-target-"+target[i]); + } */ + Tstates = targetStates.iterator(); + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + m.addConstr(v.get(s),GRB.EQUAL,1.0,"v-target"); + } + + while(ns.hasNext()){ + final int s = ns.nextInt(); + v.put(s, m.addVar(0.0, 1.0, 0, GRB.CONTINUOUS, "mu["+s+"]")); + m.addConstr(v.get(s),GRB.EQUAL,0.0,"v-no"); + } + m.update(); + + // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- + Map eta = new HashMap<>(); + Map> delta = new HashMap<>(); + + states = eS.iterator(); + while(states.hasNext()){ + final int s = states.nextInt(); + int numC = imdp.getNumChoices(s); + for (int c = 0; c < numC; c++) { + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); + delta.put(sc, new HashMap<>()); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc+"->"+t; + GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); + delta.get(sc).put(t, up); + GRBLinExpr allowedUp = new GRBLinExpr(); + GRBLinExpr allowedLow = new GRBLinExpr(); + allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); + allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); + m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); + m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); + } + GRBLinExpr norm = new GRBLinExpr(); + for (int t : delta.get(sc).keySet()) + norm.addTerm(1.0, delta.get(sc).get(t)); + m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); + } + } + + // --- 3) Action‐selection: sum η ≥ 1 at each state --- + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + + // 3g) Bellman + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBQuadExpr rhs = new GRBQuadExpr(); + //rhs.addConstant(mdpRewards.getTransitionReward(s,c)); + + Iterator>> it = imdp.getTransitionsIterator(s,c); + GRBQuadExpr qexpr = new GRBQuadExpr(); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); + } + + rhs.add(qexpr); + + // add big‑M disable term + rhs.addConstant(+BIG); + rhs.addTerm(-BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + + m.addQConstr(v.get(s), GRB.LESS_EQUAL, rhs, "bell-"+sc ); + + + } + } + + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "prefBound"); + + + m.update(); + + // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) + GRBLinExpr pen = new GRBLinExpr(); + + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + + // set the model’s objective to pen, minimize it + + m.setObjective(pen, GRB.MINIMIZE); + /* GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MAXIMIZE); */ + + + + m.optimize(); + //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { + System.out.println("Model infeasible—computing IIS..."); + m.computeIIS(); + for (GRBConstr c : m.getConstrs()) { + if (c.get(GRB.IntAttr.IISConstr) == 1) { + System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); + } + } + // Optionally write the IIS to a file: + m.write("model.IIS"); + } + int status = m.get(GRB.IntAttr.Status); + System.out.println("Gurobi Status = " + status); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } + long time = (System.currentTimeMillis() - timer); + mainLog.println("It took "+time + " milli-seconds to finish synthesize the permissive strategy"); + + // Return results + ModelCheckerResult res = new ModelCheckerResult(); +// res.accuracy = AccuracyFactory.boundedNumericalIterations(); + res.soln = soln; +// res.timeTaken = timer / 1000.0; + return res; + } + + public ModelCheckerResult computeMultiStrategyProbMin(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException + { + double[] soln = null; + + // Start solution + long timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (min)..."); + + int n = imdp.getNumStates(); + System.out.println(n); + int sInit = imdp.getFirstInitialState(); + double BIG = 1.00; + BitSet no = imdp.getLabelStates("Crash"); + BitSet targetS = imdp.getLabelStates("goal"); + System.out.println(targetS); + no.andNot(targetS); + //targetS.andNot(no); + BitSet everything = new BitSet(); + everything.set(0, n); + //everything.andNot(no); + IntSet targetStates = IntSet.asIntSet(targetS); + IntSet eS = IntSet.asIntSet(everything); + PrimitiveIterator.OfInt Tstates = targetStates.iterator(); + int numTarget = 0; + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + numTarget += 1; + } + int[] target = new int[numTarget]; + Tstates = targetStates.iterator(); + int counter = 0; + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + target[counter] = s; + counter += 1; + } + PrimitiveIterator.OfInt states = eS.iterator(); + IntSet nStates = IntSet.asIntSet(no); + PrimitiveIterator.OfInt ns = nStates.iterator(); + System.out.println(no); + if (robust==true){ + mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); + try { + // Initialise MILP solver + GRBEnv env = new GRBEnv("gurobi.log"); + //env.set(GRB.DoubleParam.TimeLimit, 10800.0); // 60-second limit + env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + env.set(GRB.IntParam.MIRCuts, 2); + env.set(GRB.IntParam.CoverCuts, 2); + env.set(GRB.IntParam.FlowCoverCuts,2); + env.set(GRB.IntParam.GUBCoverCuts, 2); + env.set(GRB.IntParam.ImpliedCuts, 2); + GRBModel m = new GRBModel(env); + Map v; + Map eta, lam; + Map> uplus, umin; + + // Value-function + v = new HashMap<>(); + for (int s = 0; s (); + lam = new HashMap<>(); + uplus = new HashMap<>(); + umin = new HashMap<>(); + states = eS.iterator(); + while(states.hasNext()){ + final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); + lam.put(sc, m.addVar(-1.0,1.0,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + uplus.put(sc, new HashMap<>()); + umin.put(sc, new HashMap<>()); + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc + "->" + t; + GRBVar up = m.addVar(0,1.0,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,1.0,0,GRB.CONTINUOUS,"umin["+key+"]"); + uplus.get(sc).put(t, up); + umin.get(sc).put(t, um); + GRBLinExpr allowed = new GRBLinExpr(); + allowed.addTerm(BIG, eta.get(sc)); + m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); + m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); + m.addConstr(uplus.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uPlusHigh-"+sc+"-"+t); + m.addConstr(umin.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uMinHigh-"+sc+"-"+t); + GRBLinExpr dualExpr = new GRBLinExpr(); + dualExpr.addTerm(1.0, lam.get(sc)); + dualExpr.addTerm(1.0, uplus.get(sc).get(t)); + dualExpr.addTerm(-1.0, umin.get(sc).get(t)); + m.addConstr(dualExpr, GRB.GREATER_EQUAL, v.get(t), "dualFeas_"+sc+"_"+t); + } + } + } + + // Action per state Constraint (multi >= 1.0, deter == 1.0) + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + //Pre-bell + Map phi = new HashMap<>(); + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); + GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); + phi.put(sc, phiVar); + + // 3) φ >= λ - BIG*(1−η) + GRBLinExpr c3 = new GRBLinExpr(); + c3.addTerm(1.0, phiVar); + c3.addTerm(-1.0, lamVar); + c3.addConstant(-BIG); + c3.addTerm(+BIG, etaVar); + m.addConstr(c3, GRB.GREATER_EQUAL, 0.0, "philem3-" + sc); + } + } + + + m.update(); + + + // Bellman constraint + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBLinExpr expr = new GRBLinExpr(); + //expr.addConstant(mdpRewards.getTransitionReward(s,c)); + + // add phi = λ·η + expr.addTerm(1.0, phi.get(sc)); + + // add ∑[hi·uplus – lo·umin] + GRBLinExpr ins = new GRBLinExpr(); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); + ins.addTerm(+hi, uplus.get(sc).get(t) ); + ins.addTerm(-lo, umin .get(sc).get(t) ); + } + expr.add(ins); + + expr.addConstant(-BIG); + expr.addTerm(+BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + m.addConstr( v.get(s), GRB.GREATER_EQUAL, expr, "bell-"+sc ); + + + } + } + + // Bound for v[0]; + + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); + + m.update(); + + // Objective + GRBLinExpr pen = new GRBLinExpr(); + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + m.setObjective(pen, GRB.MINIMIZE); + // set the model’s objective to pen, minimize it + /* GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MAXIMIZE); */ + + // now optimize + m.optimize(); + + System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + + // Clean up + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } else { + + + // Multi-strategy under best assumption + mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); + + try { + // create environment & model + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit + env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + GRBModel m = new GRBModel(env); + + + // --- 1) Value‐function vars v[s] --- + Map v = new HashMap<>(); + for (int s = 0; s < n; s++) { + v.put(s, m.addVar(0.0,1.0, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); + } + /* for (int i = 0; i < numTarget; i++) { + m.addConstr(v.get(target[i]), GRB.EQUAL, 1.0, "v-target-"+target[i]); + } */ + Tstates = targetStates.iterator(); + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + m.addConstr(v.get(s),GRB.EQUAL,1.0,"v-target"); + } + + while(ns.hasNext()){ + final int s = ns.nextInt(); + v.put(s, m.addVar(0.0, 1.0, 0, GRB.CONTINUOUS, "mu["+s+"]")); + m.addConstr(v.get(s),GRB.EQUAL,0.0,"v-no"); + } + m.update(); + + // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- + Map eta = new HashMap<>(); + Map> delta = new HashMap<>(); + + states = eS.iterator(); + while(states.hasNext()){ + final int s = states.nextInt(); + int numC = imdp.getNumChoices(s); + for (int c = 0; c < numC; c++) { + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); + delta.put(sc, new HashMap<>()); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc+"->"+t; + GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); + delta.get(sc).put(t, up); + GRBLinExpr allowedUp = new GRBLinExpr(); + GRBLinExpr allowedLow = new GRBLinExpr(); + allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); + allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); + m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); + m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); + } + GRBLinExpr norm = new GRBLinExpr(); + for (int t : delta.get(sc).keySet()) + norm.addTerm(1.0, delta.get(sc).get(t)); + m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); + } + } + + // --- 3) Action‐selection: sum η ≥ 1 at each state --- + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + + // 3g) Bellman + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBQuadExpr rhs = new GRBQuadExpr(); + //rhs.addConstant(mdpRewards.getTransitionReward(s,c)); + + Iterator>> it = imdp.getTransitionsIterator(s,c); + GRBQuadExpr qexpr = new GRBQuadExpr(); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); + } + + rhs.add(qexpr); + + // add big‑M disable term + rhs.addConstant(-BIG); + rhs.addTerm(BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + + m.addQConstr(v.get(s), GRB.GREATER_EQUAL, rhs, "bell-"+sc ); + + + } + } + + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "prefBound"); + + + m.update(); + + // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) + GRBLinExpr pen = new GRBLinExpr(); + + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + + // set the model’s objective to pen, minimize it + + m.setObjective(pen, GRB.MINIMIZE); + /* GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MAXIMIZE); */ + + + + m.optimize(); + //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { + System.out.println("Model infeasible—computing IIS..."); + m.computeIIS(); + for (GRBConstr c : m.getConstrs()) { + if (c.get(GRB.IntAttr.IISConstr) == 1) { + System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); + } + } + // Optionally write the IIS to a file: + m.write("model.IIS"); + } + int status = m.get(GRB.IntAttr.Status); + System.out.println("Gurobi Status = " + status); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } + long time = (System.currentTimeMillis() - timer); + mainLog.println("It took "+time + " milli-seconds to finish synthesize the permissive strategy"); // Return results ModelCheckerResult res = new ModelCheckerResult(); diff --git a/prism/src/strat/Strategy.java b/prism/src/strat/Strategy.java index 3dfb7cbcc0..271f3499c5 100644 --- a/prism/src/strat/Strategy.java +++ b/prism/src/strat/Strategy.java @@ -99,7 +99,7 @@ public default Object sampleChoiceAction(int s, int m, RandomNumberGenerator rng * Pass an arbitrary value (e.g. -1) for m if memory is not relevant. */ public int getChoiceIndex(int s, int m); - public int[] getChoiceIndexMulti(int s, int m); + //public int[] getChoiceIndexMulti(int s, int m); /** * Is a choice defined by the strategy in the state index s diff --git a/robot-imdp.prism b/robot-imdp.prism new file mode 100644 index 0000000000..3322e4349c --- /dev/null +++ b/robot-imdp.prism @@ -0,0 +1,286 @@ +mdp + +// operator parameters +const double p=0.5; // probability of increasing workload due to other uncertain tasks +const double accu_load1; // accuracy at the low workload level (real numbers between 0 and 1) +const double accu_load2; // accuracy at the high workload level (real numbers between 0 and 1) +const double fd; // accuracy discount due to fatigue (real numbers between 0 and 1) +const int COUNTER; // fatigue threshold (integers, e.g, 10) +const double risky2; // at w2: probability of choosing a risky route +const double risky6; // at w6: probability of choosing a risky route + +global stop : bool init false; // done visiting all waypoints +formula roz = (r=8) | (w=3&a=1) | (w=3&a=2) | (w=5&a=2); // restricted operating zones + + +// OPERATOR MODEL +module operator + + k:[0..100] init 0; // fatigue level measured by completetd tasks + t:[0..2] init 0; // workload level + s:[0..2] init 0; // status of image processing, 0: init, 1: good, 2: bad + c:[0..3] init 0; // choices at the check point + + // image processing, the workload may increase due to other unknown tasks + [image] !stop & t=0 & s=0 -> (1-p):(t'=1) & (s'=0) + p:(t'=2) & (s'=0); + // not fatigue, workload level 1 + [process] !stop & t=1 & s=0 & k<=COUNTER -> accu_load1:(s'=1)&(k'=k+1) + (1-accu_load1):(s'=2)&(k'=k+1); + // fatigue, workload level 1 + [process] !stop & t=1 & s=0 & k>COUNTER -> accu_load1*fd:(s'=1) + (1-accu_load1*fd):(s'=2); + // not fatigue, workload level 2 + [process] !stop & t=2 & s=0 & k<=COUNTER -> accu_load2:(s'=1)&(k'=k+1) + (1-accu_load2):(s'=2)&(k'=k+1); + // fatigue, workload level 2 + [process] !stop & t=2 & s=0 & k>COUNTER -> accu_load2*fd:(s'=1) + (1-accu_load2*fd):(s'=2); + + // image analysis is bad, UAV need to wait at the waypoint and take another image + [wait] !stop & s=2 -> (t'=0) & (s'=0); + + // if image analysis is good, UAV can continue flying + // at check points, operator may suggest route for the UAV + + // w2 -> r5 (c=0) |r6 (c=1) |r7 (c=2)|r9 (c=3) + [go] !stop & s=1 & w=2 -> risky2:(c'=2) & (t'=0) & (s'=0) + (1-risky2)/3:(c'=3) & (t'=0) & (s'=0) + +(1-risky2)/3:(c'=1) & (t'=0) & (s'=0) + (1-risky2)/3:(c'=0) & (t'=0) & (s'=0); + + // w5 -> r3 (c=0)| r4 (c=1)| w4 (c=2) + [go] !stop & s=1 & w=5 -> 1/3:(c'=2) & (t'=0) & (s'=0) + 1/3:(c'=1) & (t'=0) & (s'=0) + + 1/3:(c'=0) & (t'=0) & (s'=0); + + // w6 -> r2 (c=0)| r3 (c=1) |r8 (c=2) + [go] !stop & s=1 & w=6 -> risky6:(c'=2) & (t'=0) & (s'=0) + (1-risky6)/2:(c'=1) & (t'=0) & (s'=0) + + (1-risky6)/2:(c'=0) & (t'=0) & (s'=0); + + // at non-check-points, UAV has full autonomy to choose flying route + [go] !stop & s=1 & (w!=2 & w!=5 & w!=6) -> (t'=0) & (s'=0); + + // operator stops + [] !stop & w1 & w2 & w6 -> (stop'=true); + [operator_stop] stop -> true; + +endmodule + + +// UAV MODEL +module UAV + // UAV positions: + // inside a waypoint: w!=0, a=0, r=0 + // fly through certain angle of a waypoint: w!=0, a!=0, r=0 + // fly through a road point: w=0, a=0, r!=0 + w:[0..6] init 1; // waypoint + a:[0..8] init 0; // angle points + r:[0..9] init 0; // road points + send: bool init true; + in: bool init true; + // flag that a waypoint has been visited + w1: bool init true; + w2: bool init false; + w3: bool init false; + w4: bool init false; + w5: bool init false; + w6: bool init false; + + // at any waypoint: + // send image to human operator for analysis + [image] w!=0 & a=0 & r=0 & send -> (send'=false); + // wait at the waypoint and send another image + [wait] !send -> (send'=true); + // fly into a waypoint and take an image + [camera] w=1 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w1'=true); + [camera] w=2 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w2'=true); + [camera] w=3 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w3'=true); + [camera] w=4 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w4'=true); + [camera] w=5 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w5'=true); + [camera] w=6 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w6'=true); + // fly out of the waypoint via any angle point + [go] w!=0 & a=0 & r=0 -> 1/8:(a'=1) & (in'=false) + + 1/8:(a'=2) & (in'=false) + + 1/8:(a'=3) & (in'=false) + + 1/8:(a'=4) & (in'=false) + + 1/8:(a'=5) & (in'=false) + + 1/8:(a'=6) & (in'=false) + + 1/8:(a'=7) & (in'=false) + + 1/8:(a'=8) & (in'=false); + + + // UAV flying plans (based on the road map) + // check points: receiving commands from the operator + // w2 -> r5 |r6 |r7 |r9 + [fly] c=0 & w=2 & (a!=0) & r=0 & !in -> (r'=5); + [fly] c=1 & w=2 & (a!=0) & r=0 & !in -> (r'=6); + [fly] c=2 & w=2 & (a!=0) & r=0 & !in -> (r'=7); + [fly] c=3 & w=2 & (a!=0) & r=0 & !in -> (r'=9); + // w5 -> r3 | r4 | w4 (at any angle point) + [fly] c=0 & w=5 & (a!=0) & r=0 & !in -> (r'=3); + [fly] c=1 & w=5 & (a!=0) & r=0 & !in -> (r'=4); + [fly] c=2 & w=5 & (a!=0) & r=0 & !in -> 1/8:(w'=4) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=8) & (r'=0) & (in'=true); + // w6 -> r2 | r3 |r8 + [fly] c=0 & w=6 & (a!=0) & r=0 & !in -> (r'=2); + [fly] c=1 & w=6 & (a!=0) & r=0 & !in -> (r'=3); + [fly] c=2 & w=6 & (a!=0) & r=0 & !in -> (r'=8); + + // non check points: fly autonomy + // w1 -> r1 | r9 + [fly] w=1 & (a!=0) & r=0 & !in -> (r'=1); + [fly] w=1 & (a!=0) & r=0 & !in -> (r'=9); + // w3 -> r6 | w4 (any angle point) + [fly] w=3 & (a!=0) & r=0 & !in -> (r'=6); + [fly] w=3 & (a!=0) & r=0 & !in -> 1/8:(w'=4) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=8) & (r'=0) & (in'=true); + + // w4 -> w3 | w5 + [fly] w=4 & (a!=0) & r=0 & !in -> 1/8:(w'=3) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=8) & (r'=0) & (in'=true); + + [fly] w=4 & (a!=0) & r=0 & !in -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); + // r1 -> r2 | w1 + [fly] r=1 -> (r'=2); + [fly] r=1 -> 1/8:(w'=1) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=8) & (r'=0) & (in'=true); + // r2 -> r1 | w6 + [fly] r=2 -> (r'=1); + [fly] r=2 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); + // r3 -> w5 | w6 + [fly] r=3 -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); + + [fly] r=3 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); + // r4 -> r5 | w5 + [fly] r=4 -> (r'=5); + [fly] r=4 -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); + // r5 -> r4 | w2 + [fly] r=5 -> (r'=4); + [fly] r=5 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + // r6 -> w2 | w3 + [fly] r=6 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + + [fly] r=6 -> 1/8:(w'=3) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=8) & (r'=0) & (in'=true); + // r7 -> w2 | r8 + [fly] r=7 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + [fly] r=7 -> (r'=8); + // r8 -> w6 | r7 + [fly] r=8 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); + [fly] r=8 -> (r'=7); + // r9 -> w1 | w2 + [fly] r=9 -> 1/8:(w'=1) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=8) & (r'=0) & (in'=true); + + [fly] r=9 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + +endmodule + + +rewards "time" // flight time + [wait] true: 10; + [fly] true: 60; +endrewards + +rewards "ROZ" // ROZ occupancy + [fly] roz : 1; +endrewards \ No newline at end of file diff --git a/sav-imdp.prism b/sav-imdp.prism new file mode 100644 index 0000000000..d3d72a23b2 --- /dev/null +++ b/sav-imdp.prism @@ -0,0 +1,61 @@ +// GRID WORLD MODEL OF A SEMIAUTONOMOUS EXPLORING ROBOT +// Sebastian Junges, RWTH Aachen University +// As described in +// Junges, Jansen, Dehnert, Topcu, Katoen: +// Safety Constrained Reinforcement Learning +// Proc. of TACAS’16 + +mdp + +//PARAMETERS +//The difference of the reliability of the channels between the worst and at the best position +const double pLDiff=0.7; +const double pHDiff=0.1; +const double u=0.1; +//Scaling factor for the minimum reliability of the channels +const double pL=0.2; +const double pH=0.3; + +//CONSTANTS +//The minimum reliablities +const double pLMin=pL*(1-pLDiff); +const double pHMin= pH*(1-pHDiff); + +// Grid size +const int Xsize = 6; +const int Ysize = 6; +// Number of tries before an error +const int MAXTRIES = 2; +// Ball within the robot has to move. +const int B = 2; + + +formula T = (xLoc = Xsize & yLoc = Ysize); + + +module robot + xLoc : [1..Ysize] init 1; + yLoc : [1..Xsize] init 1; + unreported : [0..B] init 0; + hasSendNow : bool init false; + tries : [0..MAXTRIES] init 0; + + [up] xLoc < Xsize & !T & hasSendNow -> 1:(xLoc'=xLoc+1) & (unreported' = 0) & (hasSendNow'=false); + [up] xLoc < Xsize & !T & !hasSendNow -> 1:(xLoc'=xLoc+1) & (unreported'=min(unreported+1, B)); + [right] yLoc < Ysize & !T & hasSendNow -> 1:(yLoc'=yLoc+1) & (unreported' = 0)& (hasSendNow'=false); + [right] yLoc < Ysize & !T & !hasSendNow -> 1:(yLoc'=yLoc+1) & (unreported'=min(unreported+1,B)); + [sendL] !hasSendNow & !T & tries < MAXTRIES -> [pLMin + pLDiff * xLoc/Xsize-u,pLMin + pLDiff * xLoc/Xsize+u]:(hasSendNow'=true) & (tries'=0) + [1 - pLMin - pLDiff * xLoc/Xsize-u,1 - pLMin - pLDiff * xLoc/Xsize+u]: (tries'=tries+1); + [sendH] !hasSendNow & !T & tries < MAXTRIES -> [pHMin + pHDiff * yLoc/Ysize-u,pHMin + pHDiff * yLoc/Ysize+u]:(hasSendNow'=true) & (tries'=0) + [1 - pHMin - pHDiff * yLoc/Ysize-u,1 - pHMin - pHDiff * yLoc/Ysize+u]: (tries'=tries+1); + [done] T -> 1:true; +endmodule + +rewards + [up] true: 0.03; + [right] true: 0.03; + [sendL] true: max(10, min(11 + xLoc - yLoc, 20)); + [sendH] true: min(13 + xLoc + yLoc, 24); +endrewards + + +label "goal" = T; +label "Crash" = unreported=B; \ No newline at end of file diff --git a/test-imdp.prism b/test-imdp.prism new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tiny-imdp.prism b/tiny-imdp.prism new file mode 100644 index 0000000000..87a4b1b410 --- /dev/null +++ b/tiny-imdp.prism @@ -0,0 +1,22 @@ +mdp + +const double p = 0.8; +const double u=0.1; + +module chain + + s : [0..2] init 0; + + [a] s=0 -> [p-u,p+u] : (s'=1) + [1-p-u,1-p+u] : (s'=2); + [b] s=0 -> 1 : (s'=2); + [c] s=1 -> 1 : (s'=2); + +endmodule + +rewards + [a] true : 0; + [b] true : 10; + [c] true : 19; +endrewards + +label "goal" = s=2; \ No newline at end of file From ebe2cda86d5b6cc8ece48447837e31d3feba6f79 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Mon, 23 Jun 2025 01:35:50 -0400 Subject: [PATCH 07/11] new update - lambda bound --- chain-imdp.prism | 2 +- hav-imdp.prism | 284 +++++++ kobe-log-robust+opt.txt | 71 ++ prism/src/explicit/IMDPModelChecker.java | 952 +++++++++++++++++++++-- prism/src/explicit/trigger.java | 60 ++ 5 files changed, 1322 insertions(+), 47 deletions(-) create mode 100644 hav-imdp.prism create mode 100644 kobe-log-robust+opt.txt create mode 100644 prism/src/explicit/trigger.java diff --git a/chain-imdp.prism b/chain-imdp.prism index 1e1ac5a978..79e40aa773 100644 --- a/chain-imdp.prism +++ b/chain-imdp.prism @@ -2,7 +2,7 @@ mdp const double p=0.4; const double uncertainty=0.05; -const int H = 6; +const int H = 13; module chain diff --git a/hav-imdp.prism b/hav-imdp.prism new file mode 100644 index 0000000000..7f0883766c --- /dev/null +++ b/hav-imdp.prism @@ -0,0 +1,284 @@ +mdp + +// operator parameters +const double p=0.5; // probability of increasing workload due to other uncertain tasks +const double accu_load1=0.2; // accuracy at the low workload level (real numbers between 0 and 1) +const double accu_load2=0.3; // accuracy at the high workload level (real numbers between 0 and 1) +const double fd=0.3; // accuracy discount due to fatigue (real numbers between 0 and 1) +const int COUNTER=1; // fatigue threshold (integers, e.g, 10) +const double risky2=0.25; // at w2: probability of choosing a risky route +const double risky6=0.25; // at w6: probability of choosing a risky route + +global stop : bool init false; // done visiting all waypoints +formula roz = (r=8) | (w=3&a=1) | (w=3&a=2) | (w=5&a=2); // restricted operating zones + + +// OPERATOR MODEL +module operator + + k:[0..100] init 0; // fatigue level measured by completetd tasks + t:[0..2] init 0; // workload level + s:[0..2] init 0; // status of image processing, 0: init, 1: good, 2: bad + c:[0..3] init 0; // choices at the check point + + // image processing, the workload may increase due to other unknown tasks + [image] !stop & t=0 & s=0 -> [1-p-0.05,1-p+0.05]:(t'=1) & (s'=0) + [p-0.05,p+0.05]:(t'=2) & (s'=0); + // not fatigue, workload level 1 + [process] !stop & t=1 & s=0 & k<=COUNTER -> accu_load1:(s'=1)&(k'=k+1) + (1-accu_load1):(s'=2)&(k'=k+1); + // fatigue, workload level 1 + [process] !stop & t=1 & s=0 & k>COUNTER -> accu_load1*fd:(s'=1) + (1-accu_load1*fd):(s'=2); + // not fatigue, workload level 2 + [process] !stop & t=2 & s=0 & k<=COUNTER -> accu_load2:(s'=1)&(k'=k+1) + (1-accu_load2):(s'=2)&(k'=k+1); + // fatigue, workload level 2 + [process] !stop & t=2 & s=0 & k>COUNTER -> accu_load2*fd:(s'=1) + (1-accu_load2*fd):(s'=2); + + // image analysis is bad, UAV need to wait at the waypoint and take another image + [wait] !stop & s=2 -> (t'=0) & (s'=0); + + // if image analysis is good, UAV can continue flying + // at check points, operator may suggest route for the UAV + + // w2 -> r5 (c=0) |r6 (c=1) |r7 (c=2)|r9 (c=3) + [go] !stop & s=1 & w=2 -> risky2:(c'=2) & (t'=0) & (s'=0) + (1-risky2)/3:(c'=3) & (t'=0) & (s'=0) + +(1-risky2)/3:(c'=1) & (t'=0) & (s'=0) + (1-risky2)/3:(c'=0) & (t'=0) & (s'=0); + + // w5 -> r3 (c=0)| r4 (c=1)| w4 (c=2) + [go] !stop & s=1 & w=5 -> 1/3:(c'=2) & (t'=0) & (s'=0) + 1/3:(c'=1) & (t'=0) & (s'=0) + + 1/3:(c'=0) & (t'=0) & (s'=0); + + // w6 -> r2 (c=0)| r3 (c=1) |r8 (c=2) + [go] !stop & s=1 & w=6 -> risky6:(c'=2) & (t'=0) & (s'=0) + (1-risky6)/2:(c'=1) & (t'=0) & (s'=0) + + (1-risky6)/2:(c'=0) & (t'=0) & (s'=0); + + // at non-check-points, UAV has full autonomy to choose flying route + [go] !stop & s=1 & (w!=2 & w!=5 & w!=6) -> (t'=0) & (s'=0); + + // operator stops + [] !stop & w1 & w2 & w6 -> (stop'=true); + [operator_stop] stop -> true; + +endmodule + + +// UAV MODEL +module UAV + // UAV positions: + // inside a waypoint: w!=0, a=0, r=0 + // fly through certain angle of a waypoint: w!=0, a!=0, r=0 + // fly through a road point: w=0, a=0, r!=0 + w:[0..6] init 1; // waypoint + a:[0..8] init 0; // angle points + r:[0..9] init 0; // road points + send: bool init true; + in: bool init true; + // flag that a waypoint has been visited + w1: bool init true; + w2: bool init false; + w3: bool init false; + w4: bool init false; + w5: bool init false; + w6: bool init false; + + // at any waypoint: + // send image to human operator for analysis + [image] w!=0 & a=0 & r=0 & send -> (send'=false); + // wait at the waypoint and send another image + [wait] !send -> (send'=true); + // fly into a waypoint and take an image + [camera] w=1 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w1'=true); + [camera] w=2 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w2'=true); + [camera] w=3 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w3'=true); + [camera] w=4 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w4'=true); + [camera] w=5 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w5'=true); + [camera] w=6 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w6'=true); + // fly out of the waypoint via any angle point + [go] w!=0 & a=0 & r=0 -> 1/8:(a'=1) & (in'=false) + + 1/8:(a'=2) & (in'=false) + + 1/8:(a'=3) & (in'=false) + + 1/8:(a'=4) & (in'=false) + + 1/8:(a'=5) & (in'=false) + + 1/8:(a'=6) & (in'=false) + + 1/8:(a'=7) & (in'=false) + + 1/8:(a'=8) & (in'=false); + + + // UAV flying plans (based on the road map) + // check points: receiving commands from the operator + // w2 -> r5 |r6 |r7 |r9 + [fly] c=0 & w=2 & (a!=0) & r=0 & !in -> (r'=5); + [fly] c=1 & w=2 & (a!=0) & r=0 & !in -> (r'=6); + [fly] c=2 & w=2 & (a!=0) & r=0 & !in -> (r'=7); + [fly] c=3 & w=2 & (a!=0) & r=0 & !in -> (r'=9); + // w5 -> r3 | r4 | w4 (at any angle point) + [fly] c=0 & w=5 & (a!=0) & r=0 & !in -> (r'=3); + [fly] c=1 & w=5 & (a!=0) & r=0 & !in -> (r'=4); + [fly] c=2 & w=5 & (a!=0) & r=0 & !in -> 1/8:(w'=4) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=8) & (r'=0) & (in'=true); + // w6 -> r2 | r3 |r8 + [fly] c=0 & w=6 & (a!=0) & r=0 & !in -> (r'=2); + [fly] c=1 & w=6 & (a!=0) & r=0 & !in -> (r'=3); + [fly] c=2 & w=6 & (a!=0) & r=0 & !in -> (r'=8); + + // non check points: fly autonomy + // w1 -> r1 | r9 + [fly] w=1 & (a!=0) & r=0 & !in -> (r'=1); + [fly] w=1 & (a!=0) & r=0 & !in -> (r'=9); + // w3 -> r6 | w4 (any angle point) + [fly] w=3 & (a!=0) & r=0 & !in -> (r'=6); + [fly] w=3 & (a!=0) & r=0 & !in -> 1/8:(w'=4) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=4) & (a'=8) & (r'=0) & (in'=true); + + // w4 -> w3 | w5 + [fly] w=4 & (a!=0) & r=0 & !in -> 1/8:(w'=3) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=8) & (r'=0) & (in'=true); + + [fly] w=4 & (a!=0) & r=0 & !in -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); + // r1 -> r2 | w1 + [fly] r=1 -> (r'=2); + [fly] r=1 -> 1/8:(w'=1) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=8) & (r'=0) & (in'=true); + // r2 -> r1 | w6 + [fly] r=2 -> (r'=1); + [fly] r=2 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); + // r3 -> w5 | w6 + [fly] r=3 -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); + + [fly] r=3 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); + // r4 -> r5 | w5 + [fly] r=4 -> (r'=5); + [fly] r=4 -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); + // r5 -> r4 | w2 + [fly] r=5 -> (r'=4); + [fly] r=5 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + // r6 -> w2 | w3 + [fly] r=6 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + + [fly] r=6 -> 1/8:(w'=3) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=3) & (a'=8) & (r'=0) & (in'=true); + // r7 -> w2 | r8 + [fly] r=7 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + [fly] r=7 -> (r'=8); + // r8 -> w6 | r7 + [fly] r=8 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); + [fly] r=8 -> (r'=7); + // r9 -> w1 | w2 + [fly] r=9 -> 1/8:(w'=1) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=1) & (a'=8) & (r'=0) & (in'=true); + + [fly] r=9 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) + + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); + +endmodule + + +rewards // flight time + [wait] true: 10; + [fly] true: 60; +endrewards + +label "goal" = (w1&w2&w6); \ No newline at end of file diff --git a/kobe-log-robust+opt.txt b/kobe-log-robust+opt.txt new file mode 100644 index 0000000000..4469398645 --- /dev/null +++ b/kobe-log-robust+opt.txt @@ -0,0 +1,71 @@ +PRISM +===== + +Version: 4.8.1.dev +Date: Tue Jun 10 23:10:06 EDT 2025 +Hostname: Khangs-MacBook-Pro.local +Memory limits: cudd=1g, java(heap)=1g +Command line: prism kobe-imdp.prism -pf '<<*>>{multi}R>5.2[C]' -mainlog log.txt + +Parsing PRISM model file "kobe-imdp.prism"... + +Type: IMDP +Modules: robot +Variables: s +Labels: "goal" +Rewards: 1 + +1 property: +(1) <<*>> {multi}R>5.2 [ C ] + +--------------------------------------------------------------------- + +Model checking: <<*>> {multi}R>5.2 [ C ] + +Warning: Switching to explicit engine to allow model checking of interval model. + +Building model (engine:explicit)... + +Computing reachable states... 11 states +Reachable states exploration and model construction done in 0.007 secs. +Sorting reachable states list... + +Time for model construction: 0.021 seconds. + +Type: IMDP +States: 11 (1 initial) +Transitions: 29 +Choices: 15 +Max/avg: 2/1.36 +Building reward structure... +Starting linear programming (min)... +Calcualting multi Strategy under the assumption of worst transition per objective: +Continuous Variables = 99, Integer Variables = 15, Constraints = 188 +Multi Strategy to Obtain at most under worst assumption of adversary 5.2 +0: south +1: south +2: south east +3: south east +4: south +5: east +6: east +7: east +8: east +9: north +10: stop +It took 41 milli-seconds to finish synthesize the permissive strategy + +java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.Boolean (java.lang.Double and java.lang.Boolean are in module java.base of loader 'bootstrap') + at parser.ast.ExpressionFilter.applyForAll(ExpressionFilter.java:391) + at parser.ast.ExpressionFilter.apply(ExpressionFilter.java:226) + at explicit.StateModelChecker.checkExpressionFilter(StateModelChecker.java:1194) + at explicit.StateModelChecker.checkExpression(StateModelChecker.java:674) + at explicit.NonProbModelChecker.checkExpression(NonProbModelChecker.java:78) + at explicit.ProbModelChecker.checkExpression(ProbModelChecker.java:555) + at explicit.StateModelChecker.check(StateModelChecker.java:589) + at prism.Prism.modelCheck(Prism.java:3317) + at prism.PrismCL.run(PrismCL.java:441) + at prism.PrismCL.go(PrismCL.java:246) + at prism.PrismCL.main(PrismCL.java:3098) + +Error: Caught unhandled exception, aborting.... diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index 95c28cea6b..5289b3d7a5 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -26,13 +26,18 @@ package explicit; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.BitSet; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.PrimitiveIterator; +import java.util.Queue; +import java.util.Set; import java.util.TreeMap; import acceptance.AcceptanceReach; @@ -64,6 +69,9 @@ import lpsolve.LpSolve; import lpsolve.LpSolveException; +import explicit.trigger.*; + + /** * Explicit-state model checker for interval Markov decision prcoesses (IMDPs). */ @@ -620,7 +628,7 @@ public ModelCheckerResult computeMultiStrategy(IMDP imdp, MDPRewards imdp, MDPRew counter += 1; } System.out.println(target[0]); + //compute predecessor + Map> predecessor = new HashMap<>(); + //cstates = eS.iterator(); + for(int s = 0; s < n; s++){ + //final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String key = s + "-" + c; + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + if (predecessor.containsKey(t) == false){ + predecessor.computeIfAbsent(t, k -> new ArrayList<>()).add(key); + } else { + List l = predecessor.computeIfAbsent(t,k -> new ArrayList<>()); + if (!l.contains(key)){ + l.add(key); + } + } + } + } + } + String fakeKey = sInit + "-DUMMY"; + predecessor.computeIfAbsent(sInit, __ -> new ArrayList<>()).add(fakeKey); if (robust==true){ mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); try { // Initialise MILP solver GRBEnv env = new GRBEnv("gurobi.log"); - env.set(GRB.IntParam.OutputFlag, 0); + env.set(GRB.IntParam.OutputFlag, 1); GRBModel m = new GRBModel(env); Map v; Map eta, lam; @@ -744,6 +778,50 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); } + /* fakeKey = sInit + "-DUMMY"; + GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); + eta.put(fakeKey, etaDummy); + for(int s =0; s preds = predecessor.get(s); + if (preds == null || preds.isEmpty()) + continue; + GRBLinExpr lhs1 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs1.addTerm(1.0, eta.get(s + "-" + a)); + } + // RHS = c * sum of eta over all predecessors (t–*) + GRBLinExpr rhs1 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs1.addTerm(BIG, eta.get(predKey)); + } + m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); + + // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} + GRBLinExpr lhs2 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs2.addTerm(BIG, eta.get(s + "-" + a)); + } + GRBLinExpr rhs2 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs2.addTerm(1.0, eta.get(predKey)); + } + m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); + } + + GRBLinExpr seed = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(sInit); a++) { + seed.addTerm(1.0, eta.get(sInit + "-" + a)); + } + m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); */ //Pre-bell Map phi = new HashMap<>(); @@ -827,9 +905,23 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types int numContVars = numVars - numIntVars; mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); // now optimize + m.setObjective(pen, GRB.MINIMIZE); + m.setCallback(new trigger(m, 3600)); + m.optimize(); - + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { + System.out.println("Model infeasible—computing IIS..."); + m.computeIIS(); + for (GRBConstr c : m.getConstrs()) { + if (c.get(GRB.IntAttr.IISConstr) == 1) { + System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); + } + } + // Optionally write the IIS to a file: + m.write("model.IIS"); + } System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); soln = new double[n]; @@ -849,9 +941,12 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew for (int s = 0; s < n; s++) { mainLog.print(s + ":"); int numChoices = imdp.getNumChoices(s); + System.out.println(numChoices); for (int i = 0; i < numChoices; i++) { String sc = s +"-"+i; + System.out.println(eta.get(sc).get(GRB.DoubleAttr.X)); if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); } } @@ -873,9 +968,9 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew try { // create environment & model GRBEnv env = new GRBEnv("gurobi.log"); - env.set(GRB.IntParam.OutputFlag, 0); + env.set(GRB.IntParam.OutputFlag, 1); GRBModel m = new GRBModel(env); - m.set(GRB.IntParam.NonConvex, 2); + //m.set(GRB.IntParam.NonConvex, 2); // --- 1) Value‐function vars v[s] --- Map v = new HashMap<>(); @@ -920,13 +1015,57 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } // --- 3) Action‐selection: sum η ≥ 1 at each state --- - for (int s = 0; s < n; s++) { + /* for (int s = 0; s < n; s++) { GRBLinExpr expr = new GRBLinExpr(); for (int c = 0; c < imdp.getNumChoices(s); c++) expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } */ + fakeKey = sInit + "-DUMMY"; + GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); + eta.put(fakeKey, etaDummy); + for(int s =0; s preds = predecessor.get(s); + if (preds == null || preds.isEmpty()) + continue; + GRBLinExpr lhs1 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs1.addTerm(1.0, eta.get(s + "-" + a)); + } + // RHS = c * sum of eta over all predecessors (t–*) + GRBLinExpr rhs1 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs1.addTerm(BIG, eta.get(predKey)); + } + m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); + + // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} + GRBLinExpr lhs2 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs2.addTerm(BIG, eta.get(s + "-" + a)); + } + GRBLinExpr rhs2 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs2.addTerm(1.0, eta.get(predKey)); + } + m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); } + GRBLinExpr seed = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(sInit); a++) { + seed.addTerm(1.0, eta.get(sInit + "-" + a)); + } + m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); + // 3g) Bellman for (int s = 0; s < n; s++) { @@ -984,7 +1123,8 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types int numContVars = numVars - numIntVars; mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); - + System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + m.setCallback(new trigger(m, 3600)); m.optimize(); //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { @@ -1065,7 +1205,7 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew System.out.println(n); int sInit = imdp.getFirstInitialState(); //double BIG = 1000.00; - double BIG =bound + 0.1; + double BIG =100.000; System.out.println(imdp.getLabelStates("goal")); BitSet targetS = imdp.getLabelStates("goal"); System.out.println(imdp.getInitialStates()); @@ -1085,6 +1225,63 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew counter += 1; } System.out.println(target[0]); + //Map> predecessor = new HashMap<>(); + Map> predecessor = new HashMap<>(); + //cstates = eS.iterator(); + for(int s = 0; s < n; s++){ + //final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String key = s + "-" + c; + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + if (predecessor.containsKey(t) == false){ + predecessor.computeIfAbsent(t, k -> new ArrayList<>()).add(key); + } else { + List l = predecessor.computeIfAbsent(t,k -> new ArrayList<>()); + if (!l.contains(key)){ + l.add(key); + } + } + } + } + } + String fakeKey = sInit + "-DUMMY"; + predecessor.computeIfAbsent(sInit, __ -> new ArrayList<>()).add(fakeKey); + + BitSet reachable = new BitSet(n); + Queue q = new ArrayDeque<>(); + reachable.set(sInit); + q.add(sInit); + + for (int s = 0; s < n; s++) + System.out.println(imdp.isSuccessor(sInit, s)); + + while (!q.isEmpty()) { + int s = q.remove(); + for (int c = 0; c < imdp.getNumChoices(s); c++) { + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + int t = it.next().getKey(); + if (!reachable.get(t)) { + reachable.set(t); + q.add(t); + } + } + } + } + + System.out.println(reachable); + + // collect into a List for convenient looping + List reachStates = new ArrayList<>(); + for (int s = 0; s < n; s++) { + if (reachable.get(s)); + } + if (robust==true){ mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); try { @@ -1093,9 +1290,12 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew //env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit //env.set(GRB.IntParam.Threads, 0); // (optional) use all cores //env.set(GRB.IntParam.OutputFlag, 1); + /* env.set(GRB.IntParam.Cuts, 2); + + env.set(GRB.DoubleParam.MIPGap,1e-2); */ + //env.set(GRB.IntParam.MIPFocus, 2); env.set(GRB.IntParam.Cuts, 2); - env.set(GRB.IntParam.MIPFocus, 2); - env.set(GRB.DoubleParam.MIPGap,1e-2); + env.set(GRB.DoubleParam.MIPGap,1e-1); GRBModel m = new GRBModel(env); Map v; Map eta, lam; @@ -1121,6 +1321,12 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew String sc = s + "-" + c; eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); lam.put(sc, m.addVar(-BIG,BIG,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + GRBLinExpr lamAU = new GRBLinExpr(); + lamAU.addTerm(BIG, eta.get(sc)); + GRBLinExpr lamAD = new GRBLinExpr(); + lamAD.addTerm(-BIG, eta.get(sc)); + m.addConstr(lam.get(sc), GRB.LESS_EQUAL, lamAU, "lamU["+sc+"]"); + m.addConstr(lam.get(sc), GRB.GREATER_EQUAL, lamAD, "lamD["+sc+"]"); uplus.put(sc, new HashMap<>()); umin.put(sc, new HashMap<>()); Iterator>> iter = imdp.getTransitionsIterator(s, c); @@ -1138,15 +1344,11 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); // if ηₛₐ == 1 then uplusₛₐₜ == 0 - GRBLinExpr linP = new GRBLinExpr(); - linP.addTerm(1.0, uplus.get(sc).get(t)); - GRBLinExpr linM = new GRBLinExpr(); - linM.addTerm(1.0, umin.get(sc).get(t)); - m.addGenConstrIndicator(eta.get(sc),1,linP,GRB.EQUAL,0.0,"ind_uplus-"+sc+"-"+t); - // similarly for umin: - m.addGenConstrIndicator(eta.get(sc),1,linM,GRB.EQUAL,0.0,"ind_umin-"+sc+"-"+t); - /* m.addConstr(uplus.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uPlusHigh-"+sc+"-"+t); - m.addConstr(umin.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uMinHigh-"+sc+"-"+t); */ + GRBLinExpr allowed = new GRBLinExpr(); + allowed.addConstant(BIG); + allowed.addTerm(-BIG, eta.get(sc)); + m.addConstr(uplus.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uPlusHigh-"+sc+"-"+t); + m.addConstr(umin.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uMinHigh-"+sc+"-"+t); GRBLinExpr dualExpr = new GRBLinExpr(); dualExpr.addTerm(1.0, lam.get(sc)); dualExpr.addTerm(-1.0, uplus.get(sc).get(t)); @@ -1157,12 +1359,56 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew } // Action per state Constraint (multi >= 1.0, deter == 1.0) - for (int s = 0; s < n; s++) { + /* for (int s = 0; s < n; s++) { GRBLinExpr expr = new GRBLinExpr(); for (int c = 0; c < imdp.getNumChoices(s); c++) expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } */ + fakeKey = sInit + "-DUMMY"; + GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); + eta.put(fakeKey, etaDummy); + for(int s =0; s preds = predecessor.get(s); + if (preds == null || preds.isEmpty()) + continue; + GRBLinExpr lhs1 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs1.addTerm(1.0, eta.get(s + "-" + a)); + } + // RHS = c * sum of eta over all predecessors (t–*) + GRBLinExpr rhs1 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs1.addTerm(BIG, eta.get(predKey)); + } + m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); + + // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} + GRBLinExpr lhs2 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs2.addTerm(BIG, eta.get(s + "-" + a)); + } + GRBLinExpr rhs2 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs2.addTerm(1.0, eta.get(predKey)); + } + m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); + } + + GRBLinExpr seed = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(sInit); a++) { + seed.addTerm(1.0, eta.get(sInit + "-" + a)); } + m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); //Pre-bell Map phi = new HashMap<>(); @@ -1222,7 +1468,7 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew // Bound for v[0]; - /* m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); m.update(); double eps = 0.01; @@ -1246,22 +1492,34 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew obj.add(pen); obj.add(tieB); System.out.println("Hello"); - m.setObjective(pen, GRB.MINIMIZE); */ + m.setObjective(pen, GRB.MINIMIZE); // set the model’s objective to pen, minimize it - GRBLinExpr pen = new GRBLinExpr(); + /* GRBLinExpr pen = new GRBLinExpr(); pen.addTerm(1.0, v.get(sInit)); - m.setObjective(pen, GRB.MAXIMIZE); + m.setObjective(pen, GRB.MAXIMIZE); */ int numVars = m.get(GRB.IntAttr.NumVars); int numConstr = m.get(GRB.IntAttr.NumConstrs); int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types int numContVars = numVars - numIntVars; mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + m.setCallback(new trigger(m, 3600)); // now optimize m.optimize(); - + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { + System.out.println("Model infeasible—computing IIS..."); + m.computeIIS(); + for (GRBConstr c : m.getConstrs()) { + if (c.get(GRB.IntAttr.IISConstr) == 1) { + System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); + } + } + // Optionally write the IIS to a file: + m.write("model.IIS"); + } System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); soln = new double[n]; @@ -1305,13 +1563,12 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew try { // create environment & model GRBEnv env = new GRBEnv("gurobi.log"); - env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit + //env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit env.set(GRB.IntParam.Threads, 0); // (optional) use all cores env.set(GRB.IntParam.OutputFlag, 1); - env.set(GRB.IntParam.Cuts, 2); - env.set(GRB.DoubleParam.MIPGap,1e-2); + /* env.set(GRB.IntParam.Cuts, 2); + env.set(GRB.DoubleParam.MIPGap,1e-2); */ GRBModel m = new GRBModel(env); - m.set(GRB.IntParam.NonConvex, 2); // --- 1) Value‐function vars v[s] --- Map v = new HashMap<>(); @@ -1423,7 +1680,7 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types int numContVars = numVars - numIntVars; mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); - + m.setCallback(new trigger(m, 300.0)); m.optimize(); //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); @@ -1494,10 +1751,10 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa int n = imdp.getNumStates(); System.out.println(n); int sInit = imdp.getFirstInitialState(); - double BIG = 1.0; + + double BIG = 10000.0; BitSet no = imdp.getLabelStates("Crash"); BitSet targetS = imdp.getLabelStates("goal"); - System.out.println(targetS); no.andNot(targetS); //targetS.andNot(no); BitSet everything = new BitSet(); @@ -1522,21 +1779,66 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa PrimitiveIterator.OfInt states = eS.iterator(); IntSet nStates = IntSet.asIntSet(no); PrimitiveIterator.OfInt ns = nStates.iterator(); - System.out.println(no); + System.out.println("sInit = " + sInit); + System.out.println("Crash states = " + no); + System.out.println("Goal states = " + targetS); + for (int bad : new int[]{4,6,14,15,16,32}) { + System.out.printf("state %d has %d choices%n", + bad, imdp.getNumChoices(bad)); + } + + //compute predecessor + /* Map> predecessor = new HashMap<>(); + states = eS.iterator(); + for(int s = 0; s < n; s++){ + //final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String key = s + "-" + c; + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + if (predecessor.containsKey(t) == false){ + predecessor.computeIfAbsent(t, k -> new ArrayList<>()).add(key); + } else { + List l = predecessor.computeIfAbsent(t,k -> new ArrayList<>()); + if (!l.contains(key)){ + l.add(key); + } + } + } + } + } */ + /* String fakeKey = sInit + "-DUMMY"; + predecessor.computeIfAbsent(sInit, __ -> new ArrayList<>()).add(fakeKey); + for (Map.Entry> entry : predecessor.entrySet()) { + Integer state = entry.getKey(); + List preds = entry.getValue(); + mainLog.println("State " + state + " has predecessors:"); + for (String actionKey : preds) { + mainLog.println(" " + actionKey); + } + } */ + + + if (robust==true){ mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); try { // Initialise MILP solver GRBEnv env = new GRBEnv("gurobi.log"); //env.set(GRB.DoubleParam.TimeLimit, 10800.0); // 60-second limit - /* env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.Threads, 0); // (optional) use all cores env.set(GRB.IntParam.OutputFlag, 1); - env.set(GRB.IntParam.Cuts, 2); + /* env.set(GRB.IntParam.MIRCuts, 2); env.set(GRB.IntParam.CoverCuts, 2); env.set(GRB.IntParam.FlowCoverCuts,2); env.set(GRB.IntParam.GUBCoverCuts, 2); env.set(GRB.IntParam.ImpliedCuts, 2); */ + GRBModel m = new GRBModel(env); Map v; Map eta, lam; @@ -1545,7 +1847,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa // Value-function v = new HashMap<>(); for (int s = 0; s imdp, MDPRewa while(ns.hasNext()){ final int s = ns.nextInt(); - v.put(s, m.addVar(0.0, BIG, 0, GRB.CONTINUOUS, "mu["+s+"]")); + //v.put(s, m.addVar(0.0, BIG, 0, GRB.CONTINUOUS, "mu["+s+"]")); m.addConstr(v.get(s),GRB.EQUAL,0.0,"v-no"); } @@ -1571,7 +1873,13 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa for (int c = 0; c < numChoices; c++){ String sc = s + "-" + c; eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); - lam.put(sc, m.addVar(-BIG,BIG,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + lam.put(sc, m.addVar(-1.0,1.0,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + GRBLinExpr lamAU = new GRBLinExpr(); + lamAU.addTerm(BIG, eta.get(sc)); + GRBLinExpr lamAD = new GRBLinExpr(); + lamAD.addTerm(-BIG, eta.get(sc)); + m.addConstr(lam.get(sc), GRB.LESS_EQUAL, lamAU, "lamU["+sc+"]"); + m.addConstr(lam.get(sc), GRB.GREATER_EQUAL, lamAD, "lamD["+sc+"]"); uplus.put(sc, new HashMap<>()); umin.put(sc, new HashMap<>()); Iterator>> iter = imdp.getTransitionsIterator(s, c); @@ -1580,11 +1888,12 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa int t = e.getKey(); Interval transition_val = e.getValue(); String key = sc + "->" + t; - GRBVar up = m.addVar(0,BIG,0,GRB.CONTINUOUS,"uplus["+key+"]"); - GRBVar um = m.addVar(0,BIG,0,GRB.CONTINUOUS,"umin["+key+"]"); + GRBVar up = m.addVar(0,1.0,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,1.0,0,GRB.CONTINUOUS,"umin["+key+"]"); uplus.get(sc).put(t, up); umin.get(sc).put(t, um); GRBLinExpr allowed = new GRBLinExpr(); + //allowed.addConstant(BIG); allowed.addTerm(BIG, eta.get(sc)); m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); @@ -1598,6 +1907,9 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa } } } + /* fakeKey = sInit + "-DUMMY"; + GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); + eta.put(fakeKey, etaDummy); */ // Action per state Constraint (multi >= 1.0, deter == 1.0) states = eS.iterator(); @@ -1608,6 +1920,48 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); } +/* states = eS.iterator(); + while(states.hasNext()){ + final int s = states.nextInt(); + // LHS = sum of eta[s–*] + if (s == sInit) + continue; // skip initial + if (imdp.getNumChoices(s) == 0){ + System.out.println(s); + continue; + } + + List preds = predecessor.get(s); + if (preds == null || preds.isEmpty()) + continue; + GRBLinExpr lhs1 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs1.addTerm(1.0, eta.get(s + "-" + a)); + } + // RHS = c * sum of eta over all predecessors (t–*) + GRBLinExpr rhs1 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs1.addTerm(BIG, eta.get(predKey)); + } + m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); + + // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} + GRBLinExpr lhs2 = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(s); a++) { + lhs2.addTerm(BIG, eta.get(s + "-" + a)); + } + GRBLinExpr rhs2 = new GRBLinExpr(); + for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { + rhs2.addTerm(1.0, eta.get(predKey)); + } + m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); + } + + GRBLinExpr seed = new GRBLinExpr(); + for (int a = 0; a < imdp.getNumChoices(sInit); a++) { + seed.addTerm(1.0, eta.get(sInit + "-" + a)); + } + m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); */ //Pre-bell Map phi = new HashMap<>(); @@ -1617,7 +1971,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa for (int c = 0; c < imdp.getNumChoices(s); c++) { String sc = s + "-" + c; GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); - GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); + GRBVar phiVar = m.addVar(-1.0,1.0, 0.0, GRB.CONTINUOUS, "phi-" + sc); phi.put(sc, phiVar); // 3) φ <= λ + BIG*(1−η) @@ -1691,10 +2045,28 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa /* GRBLinExpr pen = new GRBLinExpr(); pen.addTerm(1.0, v.get(sInit)); m.setObjective(pen, GRB.MAXIMIZE); */ - + m.setCallback(new trigger(m, 3600.0)); // now optimize + int numVars = m.get(GRB.IntAttr.NumVars); + int numConstr = m.get(GRB.IntAttr.NumConstrs); + int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types + int numContVars = numVars - numIntVars; + mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + m.optimize(); - + //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { + System.out.println("Model infeasible—computing IIS..."); + m.computeIIS(); + for (GRBConstr c : m.getConstrs()) { + if (c.get(GRB.IntAttr.IISConstr) == 1) { + System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); + } + } + // Optionally write the IIS to a file: + m.write("model.IIS"); + } System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); soln = new double[n]; @@ -1737,6 +2109,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa try { // create environment & model + System.out.println("Im here"); GRBEnv env = new GRBEnv("gurobi.log"); env.set(GRB.IntParam.OutputFlag, 0); env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit @@ -1867,10 +2240,16 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa /* GRBLinExpr pen = new GRBLinExpr(); pen.addTerm(1.0, v.get(sInit)); m.setObjective(pen, GRB.MAXIMIZE); */ - - - + int numVars = m.get(GRB.IntAttr.NumVars); + int numConstr = m.get(GRB.IntAttr.NumConstrs); + int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types + int numContVars = numVars - numIntVars; + mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + + m.setCallback(new trigger(m, 3600.0)); m.optimize(); + //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { System.out.println("Model infeasible—computing IIS..."); @@ -1928,6 +2307,487 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa return res; } + public ModelCheckerResult computeMultiStrategyProbMaxIndicator(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException + { + double[] soln = null; + + // Start solution + long timer = System.currentTimeMillis(); + mainLog.println("Starting linear programming (min)..."); + + int n = imdp.getNumStates(); + System.out.println(n); + int sInit = imdp.getFirstInitialState(); + double BIG = 1.0; + BitSet no = imdp.getLabelStates("Crash"); + BitSet targetS = imdp.getLabelStates("goal"); + System.out.println(targetS); + no.andNot(targetS); + //targetS.andNot(no); + BitSet everything = new BitSet(); + everything.set(0, n); + //everything.andNot(no); + IntSet targetStates = IntSet.asIntSet(targetS); + IntSet eS = IntSet.asIntSet(everything); + PrimitiveIterator.OfInt Tstates = targetStates.iterator(); + int numTarget = 0; + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + numTarget += 1; + } + int[] target = new int[numTarget]; + Tstates = targetStates.iterator(); + int counter = 0; + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + target[counter] = s; + counter += 1; + } + PrimitiveIterator.OfInt states = eS.iterator(); + IntSet nStates = IntSet.asIntSet(no); + PrimitiveIterator.OfInt ns = nStates.iterator(); + System.out.println(no); + if (robust==true){ + mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); + try { + // Initialise MILP solver + GRBEnv env = new GRBEnv("gurobi.log"); + //env.set(GRB.DoubleParam.TimeLimit, 10800.0); // 60-second limit + /* env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + env.set(GRB.IntParam.MIRCuts, 2); + env.set(GRB.IntParam.CoverCuts, 2); + env.set(GRB.IntParam.FlowCoverCuts,2); + env.set(GRB.IntParam.GUBCoverCuts, 2); + env.set(GRB.IntParam.ImpliedCuts, 2); */ + GRBModel m = new GRBModel(env); + Map v; + Map eta, lam; + Map> uplus, umin; + + // Value-function + v = new HashMap<>(); + for (int s = 0; s (); + lam = new HashMap<>(); + uplus = new HashMap<>(); + umin = new HashMap<>(); + states = eS.iterator(); + while(states.hasNext()){ + final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); + lam.put(sc, m.addVar(-BIG,BIG,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + uplus.put(sc, new HashMap<>()); + umin.put(sc, new HashMap<>()); + Iterator>> iter = imdp.getTransitionsIterator(s, c); + while(iter.hasNext()){ + Map.Entry> e = iter.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc + "->" + t; + GRBVar up = m.addVar(0,BIG,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,BIG,0,GRB.CONTINUOUS,"umin["+key+"]"); + uplus.get(sc).put(t, up); + umin.get(sc).put(t, um); + GRBLinExpr allowed = new GRBLinExpr(); + allowed.addTerm(BIG, eta.get(sc)); + m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); + m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); + GRBLinExpr upp = new GRBLinExpr(); + upp.addTerm(1.0, uplus.get(sc).get(t)); + GRBLinExpr umm = new GRBLinExpr(); + umm.addTerm(1.0, umin.get(sc).get(t)); + m.addGenConstrIndicator( + eta.get(sc), // indicator var + 1, // when η(sc) == 1 + upp, // target var + GRB.EQUAL, // equality + 0.0, // to 0.0 + "ind_uPlusZe-" + sc + "-" + t + ); + m.addGenConstrIndicator( + eta.get(sc), // indicator var + 0, // when η(sc) == 0 + upp, // target var + GRB.LESS_EQUAL, // equality + BIG, // to 0.0 + "ind_uPlus-" + sc + "-" + t + ); + + m.addGenConstrIndicator( + eta.get(sc), // same η(sc) + 1, // when η(sc) == 1 + umm, // target var + GRB.EQUAL, + 0.0, + "ind_uMinZe-" + sc + "-" + t + ); + m.addGenConstrIndicator( + eta.get(sc), // same η(sc) + 0, // when η(sc) == 0 + umm, // target var + GRB.LESS_EQUAL, + BIG, + "ind_uMin-" + sc + "-" + t + ); + GRBLinExpr dualExpr = new GRBLinExpr(); + dualExpr.addTerm(1.0, lam.get(sc)); + dualExpr.addTerm(-1.0, uplus.get(sc).get(t)); + dualExpr.addTerm(+1.0, umin.get(sc).get(t)); + m.addConstr(dualExpr, GRB.LESS_EQUAL, v.get(t), "dualFeas_"+sc+"_"+t); + } + } + } + + // Action per state Constraint (multi >= 1.0, deter == 1.0) + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + //Pre-bell + Map phi = new HashMap<>(); + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); + GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); + phi.put(sc, phiVar); + + // 3) φ <= λ + BIG*(1−η) + GRBLinExpr c3 = new GRBLinExpr(); + c3.addTerm(1.0, phiVar); + c3.addTerm(-1.0, lamVar); + c3.addConstant(-BIG); + c3.addTerm(+BIG, etaVar); + m.addConstr(c3, GRB.LESS_EQUAL, 0.0, "philem3-" + sc); + } + } + + + m.update(); + + + // Bellman constraint + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++) { + String sc = s + "-" + c; + GRBLinExpr expr = new GRBLinExpr(); + //expr.addConstant(mdpRewards.getTransitionReward(s,c)); + + // add phi = λ·η + expr.addTerm(1.0, phi.get(sc)); + + // add ∑[hi·uplus – lo·umin] + GRBLinExpr ins = new GRBLinExpr(); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); + ins.addTerm(-hi, uplus.get(sc).get(t) ); + ins.addTerm(+lo, umin .get(sc).get(t) ); + } + expr.add(ins); + + expr.addConstant(+BIG); + expr.addTerm(-BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + m.addConstr( v.get(s), GRB.LESS_EQUAL, expr, "bell-"+sc ); + + + } + } + + // Bound for v[0]; + + /* m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); + + m.update(); + + // Objective + GRBLinExpr pen = new GRBLinExpr(); + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + m.setObjective(pen, GRB.MINIMIZE); */ + // set the model’s objective to pen, minimize it + GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MAXIMIZE); + + // now optimize + m.optimize(); + + System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + + // Clean up + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } else { + + + // Multi-strategy under best assumption + mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); + + try { + // create environment & model + GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit + env.set(GRB.IntParam.Threads, 0); // (optional) use all cores + env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); + GRBModel m = new GRBModel(env); + + + // --- 1) Value‐function vars v[s] --- + Map v = new HashMap<>(); + for (int s = 0; s < n; s++) { + v.put(s, m.addVar(0.0,1.0, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); + } + /* for (int i = 0; i < numTarget; i++) { + m.addConstr(v.get(target[i]), GRB.EQUAL, 1.0, "v-target-"+target[i]); + } */ + Tstates = targetStates.iterator(); + while(Tstates.hasNext()){ + final int s = Tstates.nextInt(); + m.addConstr(v.get(s),GRB.EQUAL,1.0,"v-target"); + } + + while(ns.hasNext()){ + final int s = ns.nextInt(); + v.put(s, m.addVar(0.0, 1.0, 0, GRB.CONTINUOUS, "mu["+s+"]")); + m.addConstr(v.get(s),GRB.EQUAL,0.0,"v-no"); + } + m.update(); + + // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- + Map eta = new HashMap<>(); + Map> delta = new HashMap<>(); + + states = eS.iterator(); + while(states.hasNext()){ + final int s = states.nextInt(); + int numC = imdp.getNumChoices(s); + for (int c = 0; c < numC; c++) { + String sc = s + "-" + c; + eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); + delta.put(sc, new HashMap<>()); + Iterator>> it = imdp.getTransitionsIterator(s,c); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + Interval transition_val = e.getValue(); + String key = sc+"->"+t; + GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); + delta.get(sc).put(t, up); + GRBLinExpr allowedUp = new GRBLinExpr(); + GRBLinExpr allowedLow = new GRBLinExpr(); + allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); + allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); + m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); + m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); + } + GRBLinExpr norm = new GRBLinExpr(); + for (int t : delta.get(sc).keySet()) + norm.addTerm(1.0, delta.get(sc).get(t)); + m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); + } + } + + // --- 3) Action‐selection: sum η ≥ 1 at each state --- + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + GRBLinExpr expr = new GRBLinExpr(); + for (int c = 0; c < imdp.getNumChoices(s); c++) + expr.addTerm(1.0, eta.get(s+"-"+c)); + m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); + } + + + // 3g) Bellman + states = eS.iterator(); + while(states.hasNext()) { + final int s = states.nextInt(); + for (int c = 0; c < imdp.getNumChoices(s); c++) { + String sc = s + "-" + c; + GRBQuadExpr rhs = new GRBQuadExpr(); + //rhs.addConstant(mdpRewards.getTransitionReward(s,c)); + + Iterator>> it = imdp.getTransitionsIterator(s,c); + GRBQuadExpr qexpr = new GRBQuadExpr(); + while (it.hasNext()) { + Map.Entry> e = it.next(); + int t = e.getKey(); + qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); + } + + rhs.add(qexpr); + + // add big‑M disable term + rhs.addConstant(+BIG); + rhs.addTerm(-BIG, eta.get(sc) ); + + + // post v[s] ≥ expr + + m.addQConstr(v.get(s), GRB.LESS_EQUAL, rhs, "bell-"+sc ); + + + } + } + + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "prefBound"); + + + m.update(); + + // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) + GRBLinExpr pen = new GRBLinExpr(); + + for (int s = 0; s < n; s++){ + int numChoices = imdp.getNumChoices(s); + for (int c = 0; c < numChoices; c++){ + String sc = s +"-"+c; + pen.addConstant(1.0); + pen.addTerm(-1.0, eta.get(sc)); + } + } + + // set the model’s objective to pen, minimize it + + m.setObjective(pen, GRB.MINIMIZE); + /* GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MAXIMIZE); */ + + + m.setCallback(new trigger(m, 300)); + m.optimize(); + //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { + System.out.println("Model infeasible—computing IIS..."); + m.computeIIS(); + for (GRBConstr c : m.getConstrs()) { + if (c.get(GRB.IntAttr.IISConstr) == 1) { + System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); + } + } + // Optionally write the IIS to a file: + m.write("model.IIS"); + } + int status = m.get(GRB.IntAttr.Status); + System.out.println("Gurobi Status = " + status); + + soln = new double[n]; + for (int s = 0; s < n; s++) { + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + } + + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); + + + // How many solutions are in the pool? + int solCount = m.get(GRB.IntAttr.SolCount); + + // Loop over each solution k=0…solCount−1 + + for (int s = 0; s < n; s++) { + mainLog.print(s + ":"); + int numChoices = imdp.getNumChoices(s); + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + mainLog.print(" " + imdp.getAction(s, i)); + } + } + mainLog.println(); + } + m.dispose(); + env.dispose(); + } catch (GRBException e) { + throw new PrismException("Error solving LP: " +e.getMessage()); + } + } + long time = (System.currentTimeMillis() - timer); + mainLog.println("It took "+time + " milli-seconds to finish synthesize the permissive strategy"); + + // Return results + ModelCheckerResult res = new ModelCheckerResult(); +// res.accuracy = AccuracyFactory.boundedNumericalIterations(); + res.soln = soln; +// res.timeTaken = timer / 1000.0; + return res; + } + + public ModelCheckerResult computeMultiStrategyProbMin(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException { double[] soln = null; diff --git a/prism/src/explicit/trigger.java b/prism/src/explicit/trigger.java new file mode 100644 index 0000000000..6e8d0272ca --- /dev/null +++ b/prism/src/explicit/trigger.java @@ -0,0 +1,60 @@ +package explicit; + +import com.gurobi.gurobi.GRB; +import com.gurobi.gurobi.GRBEnv; +import com.gurobi.gurobi.GRBException; +import com.gurobi.gurobi.GRBLinExpr; +import com.gurobi.gurobi.GRBQuadExpr; +import com.gurobi.gurobi.GRBModel; +import com.gurobi.gurobi.GRBVar; +import com.gurobi.gurobi.GRBConstr; +import lpsolve.LpSolve; +import lpsolve.LpSolveException; +import com.gurobi.gurobi.GRBCallback; + + +public class trigger extends GRBCallback { + private double lastImproveTime; + private double timeout; + private GRBModel model; + private double bestObj = Double.POSITIVE_INFINITY; + + public trigger(GRBModel model, double timeoutSeconds) { + this.model = model; + this.timeout = timeoutSeconds; + // initialize lastImproveTime to zero so first incumbent counts as improvement + this.lastImproveTime = 0.0; + } + + @Override + protected void callback() { + try { + // 1) Whenever a new integer solution is found, record it: + if (where == GRB.CB_MIPSOL) { + double runtime = getDoubleInfo(GRB.Callback.RUNTIME); + double obj = getDoubleInfo(GRB.Callback.MIPSOL_OBJ); + // For minimization, lower is better + if (obj < bestObj) { + bestObj = obj; + lastImproveTime = runtime; + System.out.println("New incumbent: " + obj + " at t=" + runtime); + } + } + + // 2) At nodes / periodically, check for stall + if (where == GRB.CB_MIPNODE || where == GRB.CB_MIP) { + double runtime = getDoubleInfo(GRB.Callback.RUNTIME); + // if we've seen at least one solution, and it's been > timeout s + if (lastImproveTime > 0 && runtime - lastImproveTime > timeout) { + System.out.printf( + "No improvement for %.1f seconds (last at %.1f)—aborting%n", + timeout, lastImproveTime + ); + abort(); // stop the solve and keep the current incumbent + } + } + } catch (GRBException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file From ecfb79f835f17cd8b70411d2d048a1e64ed9c6d1 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Tue, 1 Jul 2025 04:08:21 -0400 Subject: [PATCH 08/11] fix bug --- chain-imdp.prism | 2 +- hover-imdp.prism | 51 ++++++ log.txt2 | 171 ++++++++++++++++++ navigate-imdp.prism | 73 ++++++++ prism/src/explicit/IMDPModelChecker.java | 217 ++++------------------- sav-imdp.prism | 4 +- task_assigning.prism | 56 ++++++ warehouse.prism | 116 ++++++++++++ 8 files changed, 501 insertions(+), 189 deletions(-) create mode 100644 hover-imdp.prism create mode 100644 log.txt2 create mode 100644 navigate-imdp.prism create mode 100644 task_assigning.prism create mode 100644 warehouse.prism diff --git a/chain-imdp.prism b/chain-imdp.prism index 79e40aa773..1e1ac5a978 100644 --- a/chain-imdp.prism +++ b/chain-imdp.prism @@ -2,7 +2,7 @@ mdp const double p=0.4; const double uncertainty=0.05; -const int H = 13; +const int H = 6; module chain diff --git a/hover-imdp.prism b/hover-imdp.prism new file mode 100644 index 0000000000..cc872c56d9 --- /dev/null +++ b/hover-imdp.prism @@ -0,0 +1,51 @@ +mdp + +// UAV Altitude Control under Wind Uncertainty - Interval MDP +// Discrete altitude band [0..MaxAlt], actions: inc, dec, maint + +const int MaxAlt = 20; // maximum altitude band +const int StartAlt = 10; // initial altitude +const int acceptable_error = 2; +const int upper = StartAlt + acceptable_error; +const int lower = StartAlt - acceptable_error; +const int T = 10; + +// Safe altitude corridor: bands 3 through 7 +formula safe = (alt >= lower & alt <= upper); + +module UAV + alt : [0..MaxAlt] init StartAlt; + t : [0..T] init 0; + + // Increase thrust: intended +2, plus wind disturbance + [inc] alt <= MaxAlt - 2 & (t < T) -> + [0.6,0.8] : (alt' = min(alt+2, MaxAlt)) & (t' = t + 1) + + [0.1,0.2] : (alt' = min(alt+1, MaxAlt)) & (t' = t + 1) + + [0.1,0.2] : (alt' = alt) & (t' = t + 1); + + // Decrease thrust: intended -1, plus wind disturbance + [dec] alt >= 2 & (t < T) -> + [0.6,0.8] : (alt' = max(alt-2, 0)) + + [0.1,0.2] : (alt' = max(alt-1, 0)) + + [0.1,0.2] : (alt' = alt); + + [stop_engine] alt > MaxAlt - 2 & (t < T) -> 1.0 : (alt' = max(alt-2, 0)) & (t' = t + 1); + + [full_speed] alt >= 0 & alt < 2 -> 1.0 : (alt' = alt + 2) & (t' = t + 1); + + // Maintain thrust: intended 0, plus wind disturbance + [maint] safe & (t < T) -> + [0.7,0.9] : (alt' = min(alt+1, MaxAlt)) & (t' = t + 1) + + [0.05,0.15] : (alt' = alt) & (t' = t + 1) + + [0.05,0.15] : (alt' = max(alt-1, 0)) & (t' = t + 1); + + [done] t = T -> 1.0 : (t' = t + 1); + [stop] (t = T + 1) -> 1.0 : true; +endmodule + +// Reward for staying in safe corridor vs. violation +rewards "safety" + safe : 1; +endrewards + +label "goal" = (t = T + 1); \ No newline at end of file diff --git a/log.txt2 b/log.txt2 new file mode 100644 index 0000000000..127df9f818 --- /dev/null +++ b/log.txt2 @@ -0,0 +1,171 @@ +PRISM +===== + +Version: 4.8.1.dev +Date: Tue Jul 01 03:10:02 EDT 2025 +Hostname: Khangs-MacBook-Pro.local +Memory limits: cudd=1g, java(heap)=1g +Command line: prism kobe-imdp.prism -pf '<<*>>{multi}R>5200[C]' -mainlog log.txt2 + +Parsing PRISM model file "kobe-imdp.prism"... + +Type: IMDP +Modules: robot +Variables: loc step +Labels: "goal" +Rewards: 1 + +1 property: +(1) <<*>> {multi}R>5200 [ C ] + +--------------------------------------------------------------------- + +Model checking: <<*>> {multi}R>5200 [ C ] + +Warning: Switching to explicit engine to allow model checking of interval model. + +Building model (engine:explicit)... + +Computing reachable states... 111 states +Reachable states exploration and model construction done in 0.027 secs. +Sorting reachable states list... + +Time for model construction: 0.042 seconds. + +Type: IMDP +States: 111 (1 initial) +Transitions: 777 +Choices: 389 +Max/avg: 4/3.50 +Building reward structure... +Starting linear programming (min)... +Calcualting multi Strategy under the assumption of worst transition per objective: +Continuous Variables = 2443, Integer Variables = 389, Constraints = 4776 +Multi Strategy to Obtain at most under worst assumption of adversary 5200.0 +0: west south +1: west south east north +2: west south east north +3: west south east north +4: west south east north +5: west south east north +6: west south east north +7: west south east north +8: west south east north +9: west south east north +10: west south +11: south +12: west south east north +13: west south east north +14: west south east north +15: west south east north +16: west south east north +17: west south east north +18: west south east north +19: west south east north +20: west south east north +21: south +22: south east +23: west south east north +24: west south east north +25: west south east north +26: west south east north +27: west south east north +28: west south east north +29: west south east north +30: west south east north +31: west south east north +32: south east +33: south east +34: west south east north +35: west south east north +36: west south east north +37: west south east north +38: west south east north +39: west south east north +40: west south east north +41: west south east north +42: west south east north +43: south east +44: south +45: west south east north +46: west south east north +47: west south east north +48: west south east north +49: west south east north +50: west south east north +51: west south east north +52: west south east north +53: west south east north +54: south +55: east +56: west south east north +57: west south east north +58: west south east north +59: west south east north +60: west south east north +61: west south east north +62: west south east north +63: west south east north +64: west south east north +65: east +66: south east +67: west south east north +68: west south east north +69: west south east north +70: west south east north +71: west south east north +72: west south east north +73: west south east north +74: west south east north +75: west south east north +76: south east +77: east +78: west south east north +79: west south east north +80: west south east north +81: west south east north +82: west south east north +83: west south east north +84: west south east north +85: west south east north +86: west south east north +87: east +88: east +89: west south east north +90: west south east north +91: west south east north +92: west south east north +93: west south east north +94: west south east north +95: west south east north +96: west south east north +97: west south east north +98: east +99: north +100: west south east north +101: west south east north +102: west south east north +103: west south east north +104: west south east north +105: west south east north +106: west south east north +107: west south east north +108: west south east north +109: north +110: stop +It took 69 milli-seconds to finish synthesize the permissive strategy + +java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.Boolean (java.lang.Double and java.lang.Boolean are in module java.base of loader 'bootstrap') + at parser.ast.ExpressionFilter.applyForAll(ExpressionFilter.java:391) + at parser.ast.ExpressionFilter.apply(ExpressionFilter.java:226) + at explicit.StateModelChecker.checkExpressionFilter(StateModelChecker.java:1194) + at explicit.StateModelChecker.checkExpression(StateModelChecker.java:674) + at explicit.NonProbModelChecker.checkExpression(NonProbModelChecker.java:78) + at explicit.ProbModelChecker.checkExpression(ProbModelChecker.java:555) + at explicit.StateModelChecker.check(StateModelChecker.java:589) + at prism.Prism.modelCheck(Prism.java:3317) + at prism.PrismCL.run(PrismCL.java:441) + at prism.PrismCL.go(PrismCL.java:246) + at prism.PrismCL.main(PrismCL.java:3098) + +Error: Caught unhandled exception, aborting.... diff --git a/navigate-imdp.prism b/navigate-imdp.prism new file mode 100644 index 0000000000..d535141958 --- /dev/null +++ b/navigate-imdp.prism @@ -0,0 +1,73 @@ +// Interval‐MDP Grid‐World with parameterizable trap +mdp + +//–– Grid dimensions ––// +const int width = 7; // width (number of columns) +const int height = 7; // height (number of rows) + +//–– Special locations ––// +// starting position: +const int START_X = 0; +const int START_Y = 0; +// trap (you can move the trap by changing these): +const int TRAP_X1 = 2; +const int TRAP_Y1 = 1; + +const int TRAP_X2 = 3; +const int TRAP_Y2 = 5; +// goal: +const int GOAL_X = 4; +const int GOAL_Y = 4; + +// success probability intervals for motions: +const double p_low = 0.7; +const double p_high = 0.9; + +// formulas to detect special cells +formula atStart = (x=START_X & y=START_Y); +formula atTrap = (x=TRAP_X1 & y=TRAP_Y1) | (x=TRAP_X2 & y=TRAP_Y2); +formula atGoal = (x=GOAL_X & y=GOAL_Y); + +// state variables: robot’s (x,y) coordinates +module robot + x : [0..width-1] init START_X; + y : [0..height-1] init START_Y; + + // if in trap or goal, stay there (absorbing) + [crash] atTrap -> 1:true; + [done] atGoal -> 1:true; + + // move up + [up] !atTrap & !atGoal & y < height-1 -> + [p_low, p_high]:(y'=y+1) + + [1-p_high, 1-p_low]:(y'=y); + + // move down + [down] !atTrap & !atGoal & y > 0 -> + [p_low, p_high]:(y'=y-1) + + [1-p_high, 1-p_low]:(y'=y); + + // move right + [right] !atTrap & !atGoal & x < width-1 -> + [p_low, p_high]:(x'=x+1) + + [1-p_high, 1-p_low]:(x'=x); + + // move left + [left] !atTrap & !atGoal & x > 0 -> + [p_low, p_high]:(x'=x-1) + + [1-p_high, 1-p_low]:(x'=x); + +endmodule + +rewards + [crash] true : 10; + [up] true : 1; + [down] true : 1; + [left] true : 1; + [right] true : 1; +endrewards + +// labels for properties +label "Crash" = atTrap; +label "goal" = atGoal; +label "start" = atStart; diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index 5289b3d7a5..ad56ce63b7 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -626,9 +626,9 @@ public ModelCheckerResult computeReachRewards(IMDP imdp, MDPRewards imdp, MDPRewards mdpRewards, double bound) throws PrismException { - boolean value =false; - boolean min = false; - boolean robust = false; + boolean value =true; + boolean min = true; + boolean robust = true; if (value){ if (min){ return computeMultiStrategyValueMin(imdp, mdpRewards, bound, robust); @@ -667,10 +667,10 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew System.out.println(n); int sInit = imdp.getFirstInitialState(); - double BIG = 10000.0; + double BIG = 1000.0; System.out.println(imdp.getLabelStates("goal")); BitSet targetS = imdp.getLabelStates("goal"); - System.out.println(imdp.getInitialStates()); + System.out.println("Hi: " + imdp.getInitialStates()); IntSet targetStates = IntSet.asIntSet(targetS); PrimitiveIterator.OfInt states = targetStates.iterator(); int numTarget = 0; @@ -686,33 +686,9 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew target[counter] = s; counter += 1; } - System.out.println(target[0]); - //compute predecessor - Map> predecessor = new HashMap<>(); - //cstates = eS.iterator(); - for(int s = 0; s < n; s++){ - //final int s = states.nextInt(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String key = s + "-" + c; - Iterator>> iter = imdp.getTransitionsIterator(s, c); - while(iter.hasNext()){ - Map.Entry> e = iter.next(); - int t = e.getKey(); - Interval transition_val = e.getValue(); - if (predecessor.containsKey(t) == false){ - predecessor.computeIfAbsent(t, k -> new ArrayList<>()).add(key); - } else { - List l = predecessor.computeIfAbsent(t,k -> new ArrayList<>()); - if (!l.contains(key)){ - l.add(key); - } - } - } - } + for (int s = 0; s < n; s++){ + System.out.println("State: " + s + ", nch: "+ imdp.getNumChoices(s)); } - String fakeKey = sInit + "-DUMMY"; - predecessor.computeIfAbsent(sInit, __ -> new ArrayList<>()).add(fakeKey); if (robust==true){ mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); try { @@ -743,7 +719,7 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew for (int c = 0; c < numChoices; c++){ String sc = s + "-" + c; eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); - lam.put(sc, m.addVar(-GRB.INFINITY,GRB.INFINITY,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + lam.put(sc, m.addVar(-BIG,BIG,0,GRB.CONTINUOUS,"lam"+"-"+sc)); uplus.put(sc, new HashMap<>()); umin.put(sc, new HashMap<>()); Iterator>> iter = imdp.getTransitionsIterator(s, c); @@ -752,8 +728,8 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew int t = e.getKey(); Interval transition_val = e.getValue(); String key = sc + "->" + t; - GRBVar up = m.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,"uplus["+key+"]"); - GRBVar um = m.addVar(0,GRB.INFINITY,0,GRB.CONTINUOUS,"umin["+key+"]"); + GRBVar up = m.addVar(0,BIG,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,BIG,0,GRB.CONTINUOUS,"umin["+key+"]"); uplus.get(sc).put(t, up); umin.get(sc).put(t, um); GRBLinExpr allowed = new GRBLinExpr(); @@ -778,50 +754,6 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); } - /* fakeKey = sInit + "-DUMMY"; - GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); - eta.put(fakeKey, etaDummy); - for(int s =0; s preds = predecessor.get(s); - if (preds == null || preds.isEmpty()) - continue; - GRBLinExpr lhs1 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs1.addTerm(1.0, eta.get(s + "-" + a)); - } - // RHS = c * sum of eta over all predecessors (t–*) - GRBLinExpr rhs1 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs1.addTerm(BIG, eta.get(predKey)); - } - m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); - - // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} - GRBLinExpr lhs2 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs2.addTerm(BIG, eta.get(s + "-" + a)); - } - GRBLinExpr rhs2 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs2.addTerm(1.0, eta.get(predKey)); - } - m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); - } - - GRBLinExpr seed = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(sInit); a++) { - seed.addTerm(1.0, eta.get(sInit + "-" + a)); - } - m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); */ //Pre-bell Map phi = new HashMap<>(); @@ -832,7 +764,13 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); phi.put(sc, phiVar); + // 1) φ ≤ λMore actions + m.addConstr(phiVar, GRB.LESS_EQUAL, lamVar, "philem1-" + sc); + // 2) φ ≤ BIG * η → build RHS as a LinExpr + GRBLinExpr rhs2 = new GRBLinExpr(); + rhs2.addTerm(BIG, etaVar); + m.addConstr(phiVar, GRB.LESS_EQUAL, rhs2, "philem2-" + sc); // 3) φ ≥ λ − BIG*(1−η) GRBLinExpr c3 = new GRBLinExpr(); c3.addTerm(1.0, phiVar); @@ -975,7 +913,7 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew // --- 1) Value‐function vars v[s] --- Map v = new HashMap<>(); for (int s = 0; s < n; s++) { - v.put(s, m.addVar(0.0,GRB.INFINITY, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); + v.put(s, m.addVar(0.0,BIG, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); } for (int i = 0; i < numTarget; i++) { m.addConstr(v.get(target[i]), GRB.EQUAL, 0.0, "v-target-"+target[i]); @@ -1015,13 +953,13 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } // --- 3) Action‐selection: sum η ≥ 1 at each state --- - /* for (int s = 0; s < n; s++) { + for (int s = 0; s < n; s++) { GRBLinExpr expr = new GRBLinExpr(); for (int c = 0; c < imdp.getNumChoices(s); c++) expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); - } */ - fakeKey = sInit + "-DUMMY"; + } + /* fakeKey = sInit + "-DUMMY"; GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); eta.put(fakeKey, etaDummy); for(int s =0; s imdp, MDPRew for (int a = 0; a < imdp.getNumChoices(sInit); a++) { seed.addTerm(1.0, eta.get(sInit + "-" + a)); } - m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); + m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); */ // 3g) Bellman @@ -1225,62 +1163,8 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew counter += 1; } System.out.println(target[0]); - //Map> predecessor = new HashMap<>(); - Map> predecessor = new HashMap<>(); - //cstates = eS.iterator(); - for(int s = 0; s < n; s++){ - //final int s = states.nextInt(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String key = s + "-" + c; - Iterator>> iter = imdp.getTransitionsIterator(s, c); - while(iter.hasNext()){ - Map.Entry> e = iter.next(); - int t = e.getKey(); - Interval transition_val = e.getValue(); - if (predecessor.containsKey(t) == false){ - predecessor.computeIfAbsent(t, k -> new ArrayList<>()).add(key); - } else { - List l = predecessor.computeIfAbsent(t,k -> new ArrayList<>()); - if (!l.contains(key)){ - l.add(key); - } - } - } - } - } - String fakeKey = sInit + "-DUMMY"; - predecessor.computeIfAbsent(sInit, __ -> new ArrayList<>()).add(fakeKey); - - BitSet reachable = new BitSet(n); - Queue q = new ArrayDeque<>(); - reachable.set(sInit); - q.add(sInit); - - for (int s = 0; s < n; s++) - System.out.println(imdp.isSuccessor(sInit, s)); - - while (!q.isEmpty()) { - int s = q.remove(); - for (int c = 0; c < imdp.getNumChoices(s); c++) { - Iterator>> it = imdp.getTransitionsIterator(s,c); - while (it.hasNext()) { - int t = it.next().getKey(); - if (!reachable.get(t)) { - reachable.set(t); - q.add(t); - } - } - } - } - - System.out.println(reachable); - - // collect into a List for convenient looping - List reachStates = new ArrayList<>(); - for (int s = 0; s < n; s++) { - if (reachable.get(s)); - } + + if (robust==true){ mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); @@ -1321,12 +1205,12 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew String sc = s + "-" + c; eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); lam.put(sc, m.addVar(-BIG,BIG,0,GRB.CONTINUOUS,"lam"+"-"+sc)); - GRBLinExpr lamAU = new GRBLinExpr(); + /* GRBLinExpr lamAU = new GRBLinExpr(); lamAU.addTerm(BIG, eta.get(sc)); GRBLinExpr lamAD = new GRBLinExpr(); lamAD.addTerm(-BIG, eta.get(sc)); m.addConstr(lam.get(sc), GRB.LESS_EQUAL, lamAU, "lamU["+sc+"]"); - m.addConstr(lam.get(sc), GRB.GREATER_EQUAL, lamAD, "lamD["+sc+"]"); + m.addConstr(lam.get(sc), GRB.GREATER_EQUAL, lamAD, "lamD["+sc+"]"); */ uplus.put(sc, new HashMap<>()); umin.put(sc, new HashMap<>()); Iterator>> iter = imdp.getTransitionsIterator(s, c); @@ -1359,56 +1243,13 @@ public ModelCheckerResult computeMultiStrategyValueMax(IMDP imdp, MDPRew } // Action per state Constraint (multi >= 1.0, deter == 1.0) - /* for (int s = 0; s < n; s++) { + for (int s = 0; s < n; s++) { GRBLinExpr expr = new GRBLinExpr(); for (int c = 0; c < imdp.getNumChoices(s); c++) expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); - } */ - fakeKey = sInit + "-DUMMY"; - GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); - eta.put(fakeKey, etaDummy); - for(int s =0; s preds = predecessor.get(s); - if (preds == null || preds.isEmpty()) - continue; - GRBLinExpr lhs1 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs1.addTerm(1.0, eta.get(s + "-" + a)); - } - // RHS = c * sum of eta over all predecessors (t–*) - GRBLinExpr rhs1 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs1.addTerm(BIG, eta.get(predKey)); - } - m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); - - // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} - GRBLinExpr lhs2 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs2.addTerm(BIG, eta.get(s + "-" + a)); - } - GRBLinExpr rhs2 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs2.addTerm(1.0, eta.get(predKey)); - } - m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); } - - GRBLinExpr seed = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(sInit); a++) { - seed.addTerm(1.0, eta.get(sInit + "-" + a)); - } - m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); + //Pre-bell Map phi = new HashMap<>(); @@ -1786,6 +1627,10 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa System.out.printf("state %d has %d choices%n", bad, imdp.getNumChoices(bad)); } + + for (int s = 0; s < n; s++){ + System.out.println("State: " + s + ", nch: "+ imdp.getNumChoices(s)); + } //compute predecessor /* Map> predecessor = new HashMap<>(); diff --git a/sav-imdp.prism b/sav-imdp.prism index d3d72a23b2..370f4ded0c 100644 --- a/sav-imdp.prism +++ b/sav-imdp.prism @@ -22,8 +22,8 @@ const double pLMin=pL*(1-pLDiff); const double pHMin= pH*(1-pHDiff); // Grid size -const int Xsize = 6; -const int Ysize = 6; +const int Xsize = 7; +const int Ysize = 7; // Number of tries before an error const int MAXTRIES = 2; // Ball within the robot has to move. diff --git a/task_assigning.prism b/task_assigning.prism new file mode 100644 index 0000000000..676950aec5 --- /dev/null +++ b/task_assigning.prism @@ -0,0 +1,56 @@ +mdp + +// Autonomous Warehouse Scheduling - Interval MDP +// Single robot with task queue and battery management + +const int MaxTasks = 10; // maximum tasks in queue +const int StartTasks = 5; // initial queued tasks +const int MaxBat = 5; // maximum battery level +const int StartBat = 5; // initial battery level + +// State variables: +// tasks: remaining tasks in queue; bat: robot battery level +module Scheduler + tasks : [0..MaxTasks] init StartTasks; + bat : [0..MaxBat] init StartBat; + + // Assign a task: attempt to complete one + [assign] tasks>0 & bat>0 -> + [0.7,0.9] : (tasks' = tasks-1) & (bat' = bat-1) + + [0.1,0.3] : (tasks' = tasks) & (bat' = bat-1); + + // Robot idle (wait) + [wait] tasks>=0 -> 1 : (tasks' = tasks) & (bat' = bat); + + // Recharge at station + [recharge] bat 1 : (bat' = MaxBat); +endmodule + +// Probability of new task arrivals per timestep +global arrival : bool init false; + +module TaskArrival + // New task arrives + [arrival] true -> + [0.2,0.4] : (arrival' = true) + + [0.6,0.8] : (arrival' = false); + + // Update queue when arrival is true + [assign] arrival=true & tasks 1 : (tasks' = min(tasks+1, MaxTasks)); + [wait] arrival=true & tasks 1 : (tasks' = min(tasks+1, MaxTasks)); + [recharge] arrival=true & tasks 1 : (tasks' = min(tasks+1, MaxTasks)); +endmodule + +// Rewards: + for completed tasks, - for delay and recharge energy +//rewards "throughput" +// [assign] true : 1; +//endrewards + +rewards + [assign] true : 1; + [wait] true : 1; + [recharge] true : 2; +endrewards + +// Label when all tasks done and battery full +label "goal" = (tasks=0 & bat=MaxBat); \ No newline at end of file diff --git a/warehouse.prism b/warehouse.prism new file mode 100644 index 0000000000..dfb8870d4d --- /dev/null +++ b/warehouse.prism @@ -0,0 +1,116 @@ +mdp + +const int N=7; // N*N grid map + + + +module robot + + // define robot position + r:[1..N] init 1; // grid row + c:[1..N] init 1; // grid column + + // stop when entering human zone + [stop] (r=N & c=N) -> 1: true; + + // each state only allow certain moves based on the mission plan + + + [move_east] (r>=1 & r <= N & c >= 1 & c< N) & !(r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) + & !(r>=1 & r<=N/3 & c>=2*N/3 & c1 & r<=N/3 & c>=2*N/3 & c<=N) + & !(r>=2*N/3 & r=1 & c<=N/3) + & !(r>=2*N/3 & r<=N & c>1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>=1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>1 & c<=N/3) + & !(r>=2*N/3 & r=2*N/3 & c=2*N/3 & r<=N & c>=2*N/3 & c<=N) + & !(r = N & c = N) + -> [0.8, 0.9]:(c'=c+1) + [0.1, 0.2]:(c' = c); + + [move_south] (r>=1 & r < N & c >= 1 & c<= N) & !(r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) + & !(r>=1 & r<=N/3 & c>=2*N/3 & c1 & r<=N/3 & c>=2*N/3 & c<=N) + & !(r>=2*N/3 & r=1 & c<=N/3) + & !(r>=2*N/3 & r<=N & c>1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>=1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>1 & c<=N/3) + & !(r>=2*N/3 & r=2*N/3 & c=2*N/3 & r<=N & c>=2*N/3 & c<=N) + & !(r = N & c = N) + -> [0.8, 0.9]:(r'=r+1) + [0.1, 0.2]:(r' = r); + + [move_west] (r>=1 & r <= N & c > 1 & c<= N) & !(r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) + & !(r>=1 & r<=N/3 & c>=2*N/3 & c1 & r<=N/3 & c>=2*N/3 & c<=N) + & !(r>=2*N/3 & r=1 & c<=N/3) + & !(r>=2*N/3 & r<=N & c>1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>=1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>1 & c<=N/3) + & !(r>=2*N/3 & r=2*N/3 & c=2*N/3 & r<=N & c>=2*N/3 & c<=N) + & !(r = N & c = N) + -> [0.8,0.9]:(c'=c-1) + [0.1,0.2]:(c'=c); + + [move_north] (r>1 & r <= N & c >= 1 & c<= N) & !(r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) + & !(r>=1 & r<=N/3 & c>=2*N/3 & c1 & r<=N/3 & c>=2*N/3 & c<=N) + & !(r>=2*N/3 & r=1 & c<=N/3) + & !(r>=2*N/3 & r<=N & c>1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>=1 & c<=N/3) + & !(r>=2 & r<=N/3 & c>1 & c<=N/3) + & !(r>=2*N/3 & r=2*N/3 & c=2*N/3 & r<=N & c>=2*N/3 & c<=N) + & !(r = N & c = N) + ->[0.8,0.9]:(r'=r-1) + [0.1,0.2]:(r'=r); + + + // when in magnetic field, the sensor is not accurate + [move_east] (r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) & !(r = N & c = N) -> [0.1,0.4]:(r'=r+1) + [0.6,0.9]: (c'=c+1); + [move_south] (r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) & !(r = N & c = N)-> [0.6,0.9]:(r'=r+1) + [0.1,0.4]: (c'=c+1); + [move_west] (r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) & !(r = N & c = N) -> [0.1,0.4]:(r'=r-1) + [0.6,0.9]: (c'=c-1); + [move_north] (r>=N/3 & r<= 2*N/3 & c>=N/3 & c<= 2*N/3) & !(r = N & c = N) ->[0.6,0.9]:(r'=r-1) + [0.1,0.4]: (c'=c-1); + + + //red_zone + [move_east] (r>=1 & r<=N/3 & c>=2*N/3 & c [0.3,0.5]:(r'=r+1) + [0.5,0.7]: (c'=c+1); + [move_south] (r>=1 & r<=N/3 & c>=2*N/3 & c [0.5,0.7]:(r'=r+1) + [0.3,0.5]: (c'=c+1); + [move_west] (r>1 & r<=N/3 & c>=2*N/3 & c<=N) & !(r = N & c = N)-> [0.3,0.5]:(r'=r-1) + [0.5,0.7]: (c'=c-1); + [move_north] (r>1 & r<=N/3 & c>=2*N/3 & c<=N) & !(r = N & c = N)->[0.5,0.7]:(r'=r-1) + [0.3,0.5]: (c'=c-1); + + [move_east] (r>=2*N/3 & r=1 & c<=N/3) & !(r = N & c = N)-> [0.3,0.5]:(r'=r+1) + [0.5,0.7]: (c'=c+1); + [move_south] (r>=2*N/3 & r=1 & c<=N/3) & !(r = N & c = N)-> [0.5,0.7]:(r'=r+1) + [0.3,0.5]: (c'=c+1); + [move_west] (r>=2*N/3 & r<=N & c>1 & c<=N/3) & !(r = N & c = N)-> [0.3,0.5]:(r'=r-1) + [0.5,0.7]: (c'=c-1); + [move_north] (r>=2*N/3 & r<=N & c>1 & c<=N/3) & !(r = N & c = N)->[0.5,0.7]:(r'=r-1) + [0.3,0.5]: (c'=c-1); + + [move_east] (r>=2 & r<=N/3 & c>=1 & c<=N/3) & !(r = N & c = N)-> [0.3,0.5]:(r'=r+1) + [0.5,0.7]: (c'=c+1); + [move_south] (r>=2 & r<=N/3 & c>=1 & c<=N/3) & !(r = N & c = N) -> [0.5,0.7]:(r'=r+1) + [0.3,0.5]: (c'=c+1); + [move_west] (r>=2 & r<=N/3 & c>1 & c<=N/3) & !(r = N & c = N)-> [0.3,0.5]:(r'=r-1) + [0.5,0.7]: (c'=c-1); + [move_north] (r>=2 & r<=N/3 & c>1 & c<=N/3) & !(r = N & c = N) ->[0.5,0.7]:(r'=r-1) + [0.3,0.5]: (c'=c-1); + + [move_east] (r>=2*N/3 & r=2*N/3 & c [0.3,0.5]:(r'=r+1) + [0.5,0.7]: (c'=c+1); + [move_south] (r>=2*N/3 & r=2*N/3 & c [0.5,0.7]:(r'=r+1) + [0.3,0.5]: (c'=c+1); + [move_west] (r>=2*N/3 & r<=N & c>=2*N/3 & c<=N) & !(r=N & c=N) -> [0.3,0.5]:(r'=r-1) + [0.5,0.7]: (c'=c-1); + [move_north] (r>=2*N/3 & r<=N & c>=2*N/3 & c<=N) & !(r=N & c=N) ->[0.5,0.7]:(r'=r-1) + [0.3,0.5]: (c'=c-1); + [move_east] (r = N & c = N-1) -> [0.8, 0.9]:(c'=c+1) + [0.1, 0.2]:(c' = c); + [move_south] (r = N-1 & c=N) -> [0.8, 0.9]:(r'=r+1) + [0.1, 0.2]:(r' = r); +endmodule + + +// propperty: the robot enters human zone with probabilty at most p +// target states are human zones +//label "goal" = (r=N-2 & c>=(N/2 + 1) & c<=(N/2 + 2)) ; +label "goal" = (r=N & c=N); + +rewards + [move_east] true : 1; + [move_south] true : 1; + [move_west] true : 1; + [move_north] true : 1; +endrewards + + + + + + From 0e644562312139f7e7a770d13cb71216b5c62fb9 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Mon, 18 Aug 2025 10:03:48 -0400 Subject: [PATCH 09/11] final update for robust --- ac-imdp.prism | 4 +- ds-imdp.prism | 74 + energy.prism | 52 + kobe-small.prism | 51 + ov | 2263 ++++++++++++++++++++++ ov-10x10.prism | 76 + ov-6x6.prism | 86 + ov-v2-10x10.prism | 76 + ov-v2-6x6.prism | 74 + ov-v2-7x7.prism | 76 + ov-v2-8x8.prism | 76 + ov.prism | 74 + prism/src/explicit/IMDPModelChecker.java | 140 +- robot-imdp.prism | 301 +-- sav-imdp.prism | 6 +- test.prism | 21 + visualization.py | 43 + viu.csv | 19 + wh.prism | 119 ++ wp.prism | 41 + 20 files changed, 3363 insertions(+), 309 deletions(-) create mode 100644 ds-imdp.prism create mode 100644 energy.prism create mode 100644 kobe-small.prism create mode 100644 ov create mode 100644 ov-10x10.prism create mode 100644 ov-6x6.prism create mode 100644 ov-v2-10x10.prism create mode 100644 ov-v2-6x6.prism create mode 100644 ov-v2-7x7.prism create mode 100644 ov-v2-8x8.prism create mode 100644 ov.prism create mode 100644 test.prism create mode 100644 visualization.py create mode 100644 viu.csv create mode 100644 wh.prism create mode 100644 wp.prism diff --git a/ac-imdp.prism b/ac-imdp.prism index 1d9b7bc836..feaefc06ea 100644 --- a/ac-imdp.prism +++ b/ac-imdp.prism @@ -1,12 +1,12 @@ mdp -const int maxX = 10;//10; +const int maxX = 8;//10; const int maxY = 5;//4; const double r=0.8; //= 0.820795462532;// = 0.5; // pilot response factor const double e1 = 0.1; const double p=0.3;// = 0.19; // prob of adversary moving up or down, ensure 2p <= 1 -const double e2=0.05; +const double e2=0.01; formula xclose = (x-ax >= 0 & x-ax < 3) | (ax-x >= 0 & ax-x < 3); diff --git a/ds-imdp.prism b/ds-imdp.prism new file mode 100644 index 0000000000..325928326e --- /dev/null +++ b/ds-imdp.prism @@ -0,0 +1,74 @@ +mdp + +const int M = 15; +const int N = 15; +const double p=0.4; // with probability p robot moves to an adjacent location instead of desired +const double e = 0.02; +const int MAX_STEPS=16; // time cut off +const int TERM_COST = 500; +const int STEP_COST= 5; // cost for every time step + +formula treasure = (c=1 & r=4)|(c=2 & r=6)|(c=3 & r=6)| (c=4 & r=7)|(c=5 & r=8)|(c=6 & r=8)|(c=7 & r=9)|(c=8 & r=10)|(c=9 & r=10)|(c=10 & r=11)|(c=11 & r=12)|(c=12 & r=12)|(c=13 & r=13)|(c=14 & r=14)|(c=15 & r=14); +formula wall = (c=1 & r>4) | ((c=2 | c=3) & r>6) | (c=4 & r>7) | ((c=5 | c=6) & r>8) | (c=7 & r>9) | ((c=8 | c=9) & r>10)| (c=10 & r>11) | ((c=11 | c=12) & r>12)| (c=13 & r>13) | ((c=14 | c=15) & r>14); + +// action guards i.e. if south wall is true -> south action should not be allowed +formula west_wall = (c=2 & r=5); +formula south_west_wall = (c=2 & (r=4 | r=5)) | (c=4 & r=6) | (c=5 & r=7) | (c=7 & r=8) | (c=8 & r=9)| (c=10 & r=10) | (c=11 & r=11)| (c=13 & r=12) | (c=14 & r=13); + +module robot + //define robot position + r:[1..N] init 1; //grid row + c:[1..M] init 1; //grid column + t:[1..MAX_STEPS+1] init 1; // time step + + // transitions + [end] treasure -> (t'=MAX_STEPS+1); + [end] (t=MAX_STEPS) & !treasure -> (t'=t+1); + [east] (c [p/2-e,p/2+e]:(r'=min(r+1, N))&(c'=min(c+1, M))&(t'=min(t+1, MAX_STEPS))+ [p/2-e,p/2+e]: (r'=max(r-1, 1))&(c'=min(c+1, M))&(t'=min(t+1, MAX_STEPS)) + [1-p-e,1-p+e]: (c'=min(c+1, M))&(t'=min(t+1, MAX_STEPS)); + [south] (r [1-p-e,1-p+e]:(r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS)) + [p/2-e,p/2+e]: (c'=min(c+1, M))&(r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS))+ [p/2-e,p/2+e]: (c'=max(c-1, 1))&(r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS)); + [west] (c>1 | c=1) & !west_wall & !south_west_wall & (t [p/2-e,p/2+e]:(r'=max(r-1, 1))&(c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS))+ [p/2-e,p/2+e]:(r'=min(r+1, N))&(c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)) + [1-p-e,1-p+e]: (c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)); + [north] (r=1 | r>1) & (t [1-p-e,1-p+e]:(r'=max(r-1, 1))&(t'=min(t+1, MAX_STEPS)) + [p/2-e,p/2+e]: (c'=max(c-1, 1))&(r'=max(r-1, 1))&(t'=min(t+1, MAX_STEPS)) + [p/2-e,p/2+e]: (c'=min(c+1, M))&(r'=max(r-1, 1))&(t'=min(t+1, MAX_STEPS)) ; + + [south] (r [1-p-e,1-p+e]:(r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS)) + [p-e,p+e]: (c'=min(c+1, M))&(r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS)); + [west] (c>1 | c=1) & !west_wall & south_west_wall & (t [p-e,p+e]:(r'=max(r-1, 1))&(c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)) + [1-p-e,1-p+e]: (c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)); + + // diagonal transitions + [north_east] (c1) & (t p/2:(c'=min(c+1, M))&(t'=min(t+1, MAX_STEPS))+ p/2: (r'=max(r-1, 1))&(t'=min(t+1, MAX_STEPS)) + (1-p): (c'=min(c+1, M))&(r'=max(r-1, 1))&(t'=min(t+1, MAX_STEPS)); + [north_west] (c>1 | c=1) & (r=1 | r>1) & !west_wall & (t (1-p):(r'=max(r-1, 1))&(c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)) + p/2: (r'=max(r-1, 1))&(t'=min(t+1, MAX_STEPS))+ p/2: (c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)); + [south_east] (c p/2:(c'=min(c+1, M))&(t'=min(t+1, MAX_STEPS))+ p/2:(r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS)) + (1-p): (r'=min(r+1, N))&(c'=min(c+1, M))&(t'=min(t+1, MAX_STEPS)); + [south_west] (c>1 | c=1) & (r (1-p):(r'=min(r+1, N))&(c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)) + p/2: (c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)) + p/2: (r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS)) ; + + [north_west] (c>1 | c=1) & (r=1 | r>1) & west_wall & (t (1-p):(r'=max(r-1, 1))&(c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)) + p: (r'=max(r-1, 1))&(t'=min(t+1, MAX_STEPS)); + [south_west] (c>1 | c=1) & (r (1-p):(r'=min(r+1, N))&(c'=max(c-1, 1))&(t'=min(t+1, MAX_STEPS)) + p: (r'=min(r+1, N))&(t'=min(t+1, MAX_STEPS)) ; + +endmodule + +label "goal" = (t=MAX_STEPS+1); +label "obs" = (wall); + +rewards + [east] (t 1.0: (r'=r); + [east] (c [p/3-e,p/3+e]:(r'=min(r+1, N)) &(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]: (c'=max(c-1, 1))&(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]: (r'=max(r-1, 1)) &(battery'=max(battery-1, 0))+[1-p-e,1-p+e]: (c'=min(c+1, M))&(battery'=max(battery-1, 0)); + [south] (r [1-p-e,1-p+e]:(r'=min(r+1, N)) &(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]: (c'=min(c+1, M)) &(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]:(r'=max(r-1, 1))&(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]: (c'=max(c-1, 1))&(battery'=max(battery-1, 0)); + [west] (c>1 | c=1) & ! regen & !drained -> [p/3-e,p/3+e]:(r'=max(r-1, 1))&(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]:(r'=min(r+1, N))&(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]: (c'=min(c+1, M)) &(battery'=max(battery-1, 0))+ [1-p-e,1-p+e]: (c'=max(c-1, 1))&(battery'=max(battery-1, 0)); + [north] (r=1 | r>1) & ! regen & !drained -> [1-p-e,1-p+e]:(r'=max(r-1, 1)) &(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]: (c'=max(c-1, 1))&(battery'=max(battery-1, 0)) +[p/3-e,p/3+e]: (c'=min(c+1, M)) &(battery'=max(battery-1, 0))+ [p/3-e,p/3+e]:(r'=min(r+1, N))&(battery'=max(battery-1, 0)); + + // transitions battery regeneration + [east] (c p/3:(r'=min(r+1, N)) &(battery'=min(battery+2, B))+ p/3: (c'=max(c-1, 1))&(battery'=min(battery+2, B))+ p/3: (r'=max(r-1, 1)) &(battery'=min(battery+2, B))+ (1-p): (c'=min(c+1, M))&(battery'=min(battery+2, B)); + [south] (r (1-p):(r'=min(r+1, N)) &(battery'=min(battery+2, B))+ p/3: (c'=min(c+1, M)) &(battery'=min(battery+2, B))+ p/3:(r'=max(r-1, 1))&(battery'=min(battery+2, B))+ p/3: (c'=max(c-1, 1))&(battery'=min(battery+2, B)); + [west] (c>1 | c=1) & regen & !drained-> p/3:(r'=max(r-1, 1))&(battery'=min(battery+2, B))+ p/3:(r'=min(r+1, N))&(battery'=min(battery+2, B))+ p/3: (c'=min(c+1, M)) &(battery'=min(battery+2, B))+ (1-p): (c'=max(c-1, 1))&(battery'=min(battery+2, B)); + [north] (r=1 | r>1) & regen & !drained-> (1-p):(r'=max(r-1, 1)) &(battery'=min(battery+2, B))+ p/3: (c'=max(c-1, 1))&(battery'=min(battery+2, B)) + p/3: (c'=min(c+1, M)) &(battery'=min(battery+2, B))+ p/3:(r'=min(r+1, N))&(battery'=min(battery+2, B)); + [wait] regen & !drained -> 1: (r'=r) &(c'=c) & (battery'=min(battery+2, B)); + + // terminal state self-loop to avoid deadlock + [rescue] drained -> 1: (r'=r) &(c'=c) & (battery' = 0); + +endmodule + +label "goal" = area2; +label "obs" = drained; + +rewards + [east] !drained: 1; + [south] !drained: 1; + [west] !drained: 1; + [north] !drained: 1; + [wait] !drained: 1; + + // drained + [rescue] drained: 50; + +endrewards diff --git a/kobe-small.prism b/kobe-small.prism new file mode 100644 index 0000000000..d07695664c --- /dev/null +++ b/kobe-small.prism @@ -0,0 +1,51 @@ +mdp + +module robot + s : [0..10] init 0; + + // at state 0: west is very reliable, south less so + [west] (s=0) -> [0.8,1.0]:(s'=1) + [0.0,0.2]: (s'=0); + [south] (s=0) -> [0.7,0.9]:(s'=3) + [0.1,0.3]: (s'=0); + + // at state 1: south is quite noisy + [south] (s=1) -> [0.6,0.8]:(s'=2) + [0.2,0.4]:(s'=1); + + // at state 2: east is moderately reliable; south is very reliable + [east] (s=2) -> [0.75,0.9]:(s'=3) + [0.1,0.25]:(s'=2); + [south] (s=2) -> [0.85,1.0]:(s'=5) + [0.0,0.15]:(s'=2); + + // at state 3: east is less reliable, south more + [east] (s=3) -> [0.65,0.85]:(s'=4) + [0.15,0.35]:(s'=3); + [south] (s=3) -> [0.8,0.95]:(s'=6) + [0.05,0.2]:(s'=3); + + // at state 4 + [south] (s=4) -> [0.8,1.0]:(s'=7) + [0.0,0.2]:(s'=4); + + // at state 5 + [east] (s=5) -> [0.7,0.9]:(s'=6) + [0.1,0.3]:(s'=5); + + // at state 6 + [east] (s=6) -> [0.8,0.95]:(s'=7) + [0.05,0.2]:(s'=6); + [south] (s=6) -> [0.6,0.8]:(s'=8) + [0.2,0.4]:(s'=6); + + // at state 7 + [east] (s=7) -> [0.85,1.0]:(s'=10) + [0.0,0.15]:(s'=7); + + // at state 8 + [east] (s=8) -> [0.7,0.9]:(s'=9) + [0.1,0.3]:(s'=8); + + // at state 9 + [north] (s=9) -> [0.8,0.9]:(s'=7) + [0.1,0.2]:(s'=9); + + // stop at destination + [stop] (s=10) -> true; +endmodule + +label "goal" = (s=10); + +rewards + [west] true: 1; + [south] true: 1; + [east] true: 1; + [north] true: 1; +endrewards diff --git a/ov b/ov new file mode 100644 index 0000000000..f0e2beab68 --- /dev/null +++ b/ov @@ -0,0 +1,2263 @@ +digraph IMDP { +node [label="",shape="box"]; +0 [label="0"]; +0 -> n0_0 [label="0:choose_e",arrowhead="none"]; +n0_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n0_0 -> 0 [label="[0.09999999999999998,0.2999999999999999]"]; +n0_0 -> 3 [label="[0.7000000000000001,0.9]"]; +0 -> n0_1 [label="1:choose_s",arrowhead="none"]; +n0_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n0_1 -> 0 [label="[0.09999999999999998,0.2999999999999999]"]; +n0_1 -> 4 [label="[0.7000000000000001,0.9]"]; +1 [label="1"]; +1 -> n1_0 [label="0:choose_e",arrowhead="none"]; +n1_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n1_0 -> 1 [label="[0.09999999999999998,0.2999999999999999]"]; +n1_0 -> 3 [label="[0.7000000000000001,0.9]"]; +1 -> n1_1 [label="1:choose_s",arrowhead="none"]; +n1_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n1_1 -> 1 [label="[0.09999999999999998,0.2999999999999999]"]; +n1_1 -> 4 [label="[0.7000000000000001,0.9]"]; +2 [label="2"]; +2 -> n2_0 [label="0:choose_e",arrowhead="none"]; +n2_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n2_0 -> 2 [label="[0.09999999999999998,0.2999999999999999]"]; +n2_0 -> 3 [label="[0.7000000000000001,0.9]"]; +2 -> n2_1 [label="1:choose_s",arrowhead="none"]; +n2_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n2_1 -> 2 [label="[0.09999999999999998,0.2999999999999999]"]; +n2_1 -> 4 [label="[0.7000000000000001,0.9]"]; +3 [label="3"]; +3 -> n3_0 [label="0:forward",arrowhead="none"]; +n3_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n3_0 -> 5 [label="[1,1]"]; +4 [label="4"]; +4 -> n4_0 [label="0:forward",arrowhead="none"]; +n4_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n4_0 -> 6 [label="[1,1]"]; +5 [label="5"]; +5 -> n5_0 [label="0:forward",arrowhead="none"]; +n5_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n5_0 -> 7 [label="[1,1]"]; +6 [label="6"]; +6 -> n6_0 [label="0:forward",arrowhead="none"]; +n6_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n6_0 -> 8 [label="[1,1]"]; +7 [label="7"]; +7 -> n7_0 [label="0:forward",arrowhead="none"]; +n7_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n7_0 -> 9 [label="[1,1]"]; +8 [label="8"]; +8 -> n8_0 [label="0:forward",arrowhead="none"]; +n8_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n8_0 -> 10 [label="[1,1]"]; +9 [label="9"]; +9 -> n9_0 [label="0:arrive",arrowhead="none"]; +n9_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n9_0 -> 9 [label="[0.09999999999999998,0.2999999999999999]"]; +n9_0 -> 66 [label="[0.7000000000000001,0.9]"]; +10 [label="10"]; +10 -> n10_0 [label="0:arrive",arrowhead="none"]; +n10_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n10_0 -> 10 [label="[0.09999999999999998,0.2999999999999999]"]; +n10_0 -> 11 [label="[0.7000000000000001,0.9]"]; +11 [label="11"]; +11 -> n11_0 [label="0:choose_e",arrowhead="none"]; +n11_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n11_0 -> 11 [label="[0.09999999999999998,0.2999999999999999]"]; +n11_0 -> 14 [label="[0.7000000000000001,0.9]"]; +11 -> n11_1 [label="1:choose_s",arrowhead="none"]; +n11_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n11_1 -> 11 [label="[0.09999999999999998,0.2999999999999999]"]; +n11_1 -> 15 [label="[0.7000000000000001,0.9]"]; +11 -> n11_2 [label="2:choose_n",arrowhead="none"]; +n11_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n11_2 -> 11 [label="[0.09999999999999998,0.2999999999999999]"]; +n11_2 -> 16 [label="[0.7000000000000001,0.9]"]; +12 [label="12"]; +12 -> n12_0 [label="0:choose_e",arrowhead="none"]; +n12_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n12_0 -> 12 [label="[0.09999999999999998,0.2999999999999999]"]; +n12_0 -> 14 [label="[0.7000000000000001,0.9]"]; +12 -> n12_1 [label="1:choose_s",arrowhead="none"]; +n12_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n12_1 -> 12 [label="[0.09999999999999998,0.2999999999999999]"]; +n12_1 -> 15 [label="[0.7000000000000001,0.9]"]; +12 -> n12_2 [label="2:choose_n",arrowhead="none"]; +n12_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n12_2 -> 12 [label="[0.09999999999999998,0.2999999999999999]"]; +n12_2 -> 16 [label="[0.7000000000000001,0.9]"]; +13 [label="13"]; +13 -> n13_0 [label="0:choose_e",arrowhead="none"]; +n13_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n13_0 -> 13 [label="[0.09999999999999998,0.2999999999999999]"]; +n13_0 -> 14 [label="[0.7000000000000001,0.9]"]; +13 -> n13_1 [label="1:choose_s",arrowhead="none"]; +n13_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n13_1 -> 13 [label="[0.09999999999999998,0.2999999999999999]"]; +n13_1 -> 15 [label="[0.7000000000000001,0.9]"]; +13 -> n13_2 [label="2:choose_n",arrowhead="none"]; +n13_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n13_2 -> 13 [label="[0.09999999999999998,0.2999999999999999]"]; +n13_2 -> 16 [label="[0.7000000000000001,0.9]"]; +14 [label="14"]; +14 -> n14_0 [label="0:forward",arrowhead="none"]; +n14_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n14_0 -> 17 [label="[1,1]"]; +15 [label="15"]; +15 -> n15_0 [label="0:forward",arrowhead="none"]; +n15_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n15_0 -> 18 [label="[1,1]"]; +16 [label="16"]; +16 -> n16_0 [label="0:forward",arrowhead="none"]; +n16_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n16_0 -> 19 [label="[1,1]"]; +17 [label="17"]; +17 -> n17_0 [label="0:forward",arrowhead="none"]; +n17_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n17_0 -> 20 [label="[1,1]"]; +18 [label="18"]; +18 -> n18_0 [label="0:forward",arrowhead="none"]; +n18_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n18_0 -> 21 [label="[1,1]"]; +19 [label="19"]; +19 -> n19_0 [label="0:forward",arrowhead="none"]; +n19_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n19_0 -> 22 [label="[1,1]"]; +20 [label="20"]; +20 -> n20_0 [label="0:forward",arrowhead="none"]; +n20_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n20_0 -> 23 [label="[1,1]"]; +21 [label="21"]; +21 -> n21_0 [label="0:forward",arrowhead="none"]; +n21_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n21_0 -> 24 [label="[1,1]"]; +22 [label="22"]; +22 -> n22_0 [label="0:forward",arrowhead="none"]; +n22_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n22_0 -> 25 [label="[1,1]"]; +23 [label="23"]; +23 -> n23_0 [label="0:arrive",arrowhead="none"]; +n23_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n23_0 -> 23 [label="[0.09999999999999998,0.2999999999999999]"]; +n23_0 -> 81 [label="[0.7000000000000001,0.9]"]; +24 [label="24"]; +24 -> n24_0 [label="0:arrive",arrowhead="none"]; +n24_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n24_0 -> 24 [label="[0.09999999999999998,0.2999999999999999]"]; +n24_0 -> 26 [label="[0.7000000000000001,0.9]"]; +25 [label="25"]; +25 -> n25_0 [label="0:arrive",arrowhead="none"]; +n25_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n25_0 -> 1 [label="[0.7000000000000001,0.9]"]; +n25_0 -> 25 [label="[0.09999999999999998,0.2999999999999999]"]; +26 [label="26"]; +26 -> n26_0 [label="0:choose_e",arrowhead="none"]; +n26_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n26_0 -> 26 [label="[0.09999999999999998,0.2999999999999999]"]; +n26_0 -> 29 [label="[0.7000000000000001,0.9]"]; +26 -> n26_1 [label="1:choose_s",arrowhead="none"]; +n26_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n26_1 -> 26 [label="[0.09999999999999998,0.2999999999999999]"]; +n26_1 -> 30 [label="[0.7000000000000001,0.9]"]; +26 -> n26_2 [label="2:choose_n",arrowhead="none"]; +n26_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n26_2 -> 26 [label="[0.09999999999999998,0.2999999999999999]"]; +n26_2 -> 31 [label="[0.7000000000000001,0.9]"]; +27 [label="27"]; +27 -> n27_0 [label="0:choose_e",arrowhead="none"]; +n27_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n27_0 -> 27 [label="[0.09999999999999998,0.2999999999999999]"]; +n27_0 -> 29 [label="[0.7000000000000001,0.9]"]; +27 -> n27_1 [label="1:choose_s",arrowhead="none"]; +n27_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n27_1 -> 27 [label="[0.09999999999999998,0.2999999999999999]"]; +n27_1 -> 30 [label="[0.7000000000000001,0.9]"]; +27 -> n27_2 [label="2:choose_n",arrowhead="none"]; +n27_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n27_2 -> 27 [label="[0.09999999999999998,0.2999999999999999]"]; +n27_2 -> 31 [label="[0.7000000000000001,0.9]"]; +28 [label="28"]; +28 -> n28_0 [label="0:choose_e",arrowhead="none"]; +n28_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n28_0 -> 28 [label="[0.09999999999999998,0.2999999999999999]"]; +n28_0 -> 29 [label="[0.7000000000000001,0.9]"]; +28 -> n28_1 [label="1:choose_s",arrowhead="none"]; +n28_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n28_1 -> 28 [label="[0.09999999999999998,0.2999999999999999]"]; +n28_1 -> 30 [label="[0.7000000000000001,0.9]"]; +28 -> n28_2 [label="2:choose_n",arrowhead="none"]; +n28_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n28_2 -> 28 [label="[0.09999999999999998,0.2999999999999999]"]; +n28_2 -> 31 [label="[0.7000000000000001,0.9]"]; +29 [label="29"]; +29 -> n29_0 [label="0:forward",arrowhead="none"]; +n29_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n29_0 -> 32 [label="[1,1]"]; +30 [label="30"]; +30 -> n30_0 [label="0:forward",arrowhead="none"]; +n30_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n30_0 -> 33 [label="[1,1]"]; +31 [label="31"]; +31 -> n31_0 [label="0:forward",arrowhead="none"]; +n31_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n31_0 -> 34 [label="[1,1]"]; +32 [label="32"]; +32 -> n32_0 [label="0:forward",arrowhead="none"]; +n32_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n32_0 -> 35 [label="[1,1]"]; +33 [label="33"]; +33 -> n33_0 [label="0:forward",arrowhead="none"]; +n33_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n33_0 -> 36 [label="[1,1]"]; +34 [label="34"]; +34 -> n34_0 [label="0:forward",arrowhead="none"]; +n34_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n34_0 -> 37 [label="[1,1]"]; +35 [label="35"]; +35 -> n35_0 [label="0:forward",arrowhead="none"]; +n35_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n35_0 -> 38 [label="[1,1]"]; +36 [label="36"]; +36 -> n36_0 [label="0:forward",arrowhead="none"]; +n36_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n36_0 -> 39 [label="[1,1]"]; +37 [label="37"]; +37 -> n37_0 [label="0:forward",arrowhead="none"]; +n37_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n37_0 -> 40 [label="[1,1]"]; +38 [label="38"]; +38 -> n38_0 [label="0:arrive",arrowhead="none"]; +n38_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n38_0 -> 38 [label="[0.09999999999999998,0.2999999999999999]"]; +n38_0 -> 101 [label="[0.7000000000000001,0.9]"]; +39 [label="39"]; +39 -> n39_0 [label="0:arrive",arrowhead="none"]; +n39_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n39_0 -> 39 [label="[0.09999999999999998,0.2999999999999999]"]; +n39_0 -> 41 [label="[0.7000000000000001,0.9]"]; +40 [label="40"]; +40 -> n40_0 [label="0:arrive",arrowhead="none"]; +n40_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n40_0 -> 12 [label="[0.7000000000000001,0.9]"]; +n40_0 -> 40 [label="[0.09999999999999998,0.2999999999999999]"]; +41 [label="41"]; +41 -> n41_0 [label="0:choose_e",arrowhead="none"]; +n41_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n41_0 -> 41 [label="[0.09999999999999998,0.2999999999999999]"]; +n41_0 -> 44 [label="[0.7000000000000001,0.9]"]; +41 -> n41_1 [label="1:choose_s",arrowhead="none"]; +n41_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n41_1 -> 41 [label="[0.09999999999999998,0.2999999999999999]"]; +n41_1 -> 45 [label="[0.7000000000000001,0.9]"]; +41 -> n41_2 [label="2:choose_n",arrowhead="none"]; +n41_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n41_2 -> 41 [label="[0.09999999999999998,0.2999999999999999]"]; +n41_2 -> 46 [label="[0.7000000000000001,0.9]"]; +42 [label="42"]; +42 -> n42_0 [label="0:choose_e",arrowhead="none"]; +n42_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n42_0 -> 42 [label="[0.09999999999999998,0.2999999999999999]"]; +n42_0 -> 44 [label="[0.7000000000000001,0.9]"]; +42 -> n42_1 [label="1:choose_s",arrowhead="none"]; +n42_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n42_1 -> 42 [label="[0.09999999999999998,0.2999999999999999]"]; +n42_1 -> 45 [label="[0.7000000000000001,0.9]"]; +42 -> n42_2 [label="2:choose_n",arrowhead="none"]; +n42_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n42_2 -> 42 [label="[0.09999999999999998,0.2999999999999999]"]; +n42_2 -> 46 [label="[0.7000000000000001,0.9]"]; +43 [label="43"]; +43 -> n43_0 [label="0:choose_e",arrowhead="none"]; +n43_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n43_0 -> 43 [label="[0.09999999999999998,0.2999999999999999]"]; +n43_0 -> 44 [label="[0.7000000000000001,0.9]"]; +43 -> n43_1 [label="1:choose_s",arrowhead="none"]; +n43_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n43_1 -> 43 [label="[0.09999999999999998,0.2999999999999999]"]; +n43_1 -> 45 [label="[0.7000000000000001,0.9]"]; +43 -> n43_2 [label="2:choose_n",arrowhead="none"]; +n43_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n43_2 -> 43 [label="[0.09999999999999998,0.2999999999999999]"]; +n43_2 -> 46 [label="[0.7000000000000001,0.9]"]; +44 [label="44"]; +44 -> n44_0 [label="0:forward",arrowhead="none"]; +n44_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n44_0 -> 47 [label="[1,1]"]; +45 [label="45"]; +45 -> n45_0 [label="0:forward",arrowhead="none"]; +n45_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n45_0 -> 48 [label="[1,1]"]; +46 [label="46"]; +46 -> n46_0 [label="0:forward",arrowhead="none"]; +n46_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n46_0 -> 49 [label="[1,1]"]; +47 [label="47"]; +47 -> n47_0 [label="0:forward",arrowhead="none"]; +n47_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n47_0 -> 50 [label="[1,1]"]; +48 [label="48"]; +48 -> n48_0 [label="0:forward",arrowhead="none"]; +n48_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n48_0 -> 51 [label="[1,1]"]; +49 [label="49"]; +49 -> n49_0 [label="0:forward",arrowhead="none"]; +n49_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n49_0 -> 52 [label="[1,1]"]; +50 [label="50"]; +50 -> n50_0 [label="0:forward",arrowhead="none"]; +n50_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n50_0 -> 53 [label="[1,1]"]; +51 [label="51"]; +51 -> n51_0 [label="0:forward",arrowhead="none"]; +n51_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n51_0 -> 54 [label="[1,1]"]; +52 [label="52"]; +52 -> n52_0 [label="0:forward",arrowhead="none"]; +n52_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n52_0 -> 55 [label="[1,1]"]; +53 [label="53"]; +53 -> n53_0 [label="0:arrive",arrowhead="none"]; +n53_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n53_0 -> 53 [label="[0.09999999999999998,0.2999999999999999]"]; +n53_0 -> 121 [label="[0.7000000000000001,0.9]"]; +54 [label="54"]; +54 -> n54_0 [label="0:arrive",arrowhead="none"]; +n54_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n54_0 -> 54 [label="[0.09999999999999998,0.2999999999999999]"]; +n54_0 -> 56 [label="[0.7000000000000001,0.9]"]; +55 [label="55"]; +55 -> n55_0 [label="0:arrive",arrowhead="none"]; +n55_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n55_0 -> 27 [label="[0.7000000000000001,0.9]"]; +n55_0 -> 55 [label="[0.09999999999999998,0.2999999999999999]"]; +56 [label="56"]; +56 -> n56_0 [label="0:choose_e",arrowhead="none"]; +n56_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n56_0 -> 56 [label="[0.09999999999999998,0.2999999999999999]"]; +n56_0 -> 58 [label="[0.7000000000000001,0.9]"]; +56 -> n56_1 [label="1:choose_n",arrowhead="none"]; +n56_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n56_1 -> 56 [label="[0.09999999999999998,0.2999999999999999]"]; +n56_1 -> 59 [label="[0.7000000000000001,0.9]"]; +57 [label="57"]; +57 -> n57_0 [label="0:choose_e",arrowhead="none"]; +n57_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n57_0 -> 57 [label="[0.09999999999999998,0.2999999999999999]"]; +n57_0 -> 58 [label="[0.7000000000000001,0.9]"]; +57 -> n57_1 [label="1:choose_n",arrowhead="none"]; +n57_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n57_1 -> 57 [label="[0.09999999999999998,0.2999999999999999]"]; +n57_1 -> 59 [label="[0.7000000000000001,0.9]"]; +58 [label="58"]; +58 -> n58_0 [label="0:forward",arrowhead="none"]; +n58_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n58_0 -> 60 [label="[1,1]"]; +59 [label="59"]; +59 -> n59_0 [label="0:forward",arrowhead="none"]; +n59_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n59_0 -> 61 [label="[1,1]"]; +60 [label="60"]; +60 -> n60_0 [label="0:forward",arrowhead="none"]; +n60_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n60_0 -> 62 [label="[1,1]"]; +61 [label="61"]; +61 -> n61_0 [label="0:forward",arrowhead="none"]; +n61_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n61_0 -> 63 [label="[1,1]"]; +62 [label="62"]; +62 -> n62_0 [label="0:forward",arrowhead="none"]; +n62_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n62_0 -> 64 [label="[1,1]"]; +63 [label="63"]; +63 -> n63_0 [label="0:forward",arrowhead="none"]; +n63_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n63_0 -> 65 [label="[1,1]"]; +64 [label="64"]; +64 -> n64_0 [label="0:arrive",arrowhead="none"]; +n64_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n64_0 -> 64 [label="[0.09999999999999998,0.2999999999999999]"]; +n64_0 -> 141 [label="[0.7000000000000001,0.9]"]; +65 [label="65"]; +65 -> n65_0 [label="0:arrive",arrowhead="none"]; +n65_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n65_0 -> 42 [label="[0.7000000000000001,0.9]"]; +n65_0 -> 65 [label="[0.09999999999999998,0.2999999999999999]"]; +66 [label="66"]; +66 -> n66_0 [label="0:choose_e",arrowhead="none"]; +n66_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n66_0 -> 66 [label="[0.09999999999999998,0.2999999999999999]"]; +n66_0 -> 69 [label="[0.7000000000000001,0.9]"]; +66 -> n66_1 [label="1:choose_s",arrowhead="none"]; +n66_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n66_1 -> 66 [label="[0.09999999999999998,0.2999999999999999]"]; +n66_1 -> 70 [label="[0.7000000000000001,0.9]"]; +66 -> n66_2 [label="2:choose_w",arrowhead="none"]; +n66_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n66_2 -> 66 [label="[0.09999999999999998,0.2999999999999999]"]; +n66_2 -> 71 [label="[0.7000000000000001,0.9]"]; +67 [label="67"]; +67 -> n67_0 [label="0:choose_e",arrowhead="none"]; +n67_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n67_0 -> 67 [label="[0.09999999999999998,0.2999999999999999]"]; +n67_0 -> 69 [label="[0.7000000000000001,0.9]"]; +67 -> n67_1 [label="1:choose_s",arrowhead="none"]; +n67_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n67_1 -> 67 [label="[0.09999999999999998,0.2999999999999999]"]; +n67_1 -> 70 [label="[0.7000000000000001,0.9]"]; +67 -> n67_2 [label="2:choose_w",arrowhead="none"]; +n67_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n67_2 -> 67 [label="[0.09999999999999998,0.2999999999999999]"]; +n67_2 -> 71 [label="[0.7000000000000001,0.9]"]; +68 [label="68"]; +68 -> n68_0 [label="0:choose_e",arrowhead="none"]; +n68_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n68_0 -> 68 [label="[0.09999999999999998,0.2999999999999999]"]; +n68_0 -> 69 [label="[0.7000000000000001,0.9]"]; +68 -> n68_1 [label="1:choose_s",arrowhead="none"]; +n68_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n68_1 -> 68 [label="[0.09999999999999998,0.2999999999999999]"]; +n68_1 -> 70 [label="[0.7000000000000001,0.9]"]; +68 -> n68_2 [label="2:choose_w",arrowhead="none"]; +n68_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n68_2 -> 68 [label="[0.09999999999999998,0.2999999999999999]"]; +n68_2 -> 71 [label="[0.7000000000000001,0.9]"]; +69 [label="69"]; +69 -> n69_0 [label="0:forward",arrowhead="none"]; +n69_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n69_0 -> 72 [label="[1,1]"]; +70 [label="70"]; +70 -> n70_0 [label="0:forward",arrowhead="none"]; +n70_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n70_0 -> 73 [label="[1,1]"]; +71 [label="71"]; +71 -> n71_0 [label="0:forward",arrowhead="none"]; +n71_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n71_0 -> 74 [label="[1,1]"]; +72 [label="72"]; +72 -> n72_0 [label="0:forward",arrowhead="none"]; +n72_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n72_0 -> 75 [label="[1,1]"]; +73 [label="73"]; +73 -> n73_0 [label="0:forward",arrowhead="none"]; +n73_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n73_0 -> 76 [label="[1,1]"]; +74 [label="74"]; +74 -> n74_0 [label="0:forward",arrowhead="none"]; +n74_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n74_0 -> 77 [label="[1,1]"]; +75 [label="75"]; +75 -> n75_0 [label="0:forward",arrowhead="none"]; +n75_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n75_0 -> 78 [label="[1,1]"]; +76 [label="76"]; +76 -> n76_0 [label="0:forward",arrowhead="none"]; +n76_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n76_0 -> 79 [label="[1,1]"]; +77 [label="77"]; +77 -> n77_0 [label="0:forward",arrowhead="none"]; +n77_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n77_0 -> 80 [label="[1,1]"]; +78 [label="78"]; +78 -> n78_0 [label="0:arrive",arrowhead="none"]; +n78_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n78_0 -> 78 [label="[0.09999999999999998,0.2999999999999999]"]; +n78_0 -> 155 [label="[0.7000000000000001,0.9]"]; +79 [label="79"]; +79 -> n79_0 [label="0:arrive",arrowhead="none"]; +n79_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n79_0 -> 79 [label="[0.09999999999999998,0.2999999999999999]"]; +n79_0 -> 82 [label="[0.7000000000000001,0.9]"]; +80 [label="80"]; +80 -> n80_0 [label="0:arrive",arrowhead="none"]; +n80_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n80_0 -> 2 [label="[0.7000000000000001,0.9]"]; +n80_0 -> 80 [label="[0.09999999999999998,0.2999999999999999]"]; +81 [label="81"]; +81 -> n81_0 [label="0:choose_e",arrowhead="none"]; +n81_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n81_0 -> 81 [label="[0.09999999999999998,0.2999999999999999]"]; +n81_0 -> 85 [label="[0.7000000000000001,0.9]"]; +81 -> n81_1 [label="1:choose_s",arrowhead="none"]; +n81_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n81_1 -> 81 [label="[0.09999999999999998,0.2999999999999999]"]; +n81_1 -> 86 [label="[0.7000000000000001,0.9]"]; +81 -> n81_2 [label="2:choose_n",arrowhead="none"]; +n81_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n81_2 -> 81 [label="[0.09999999999999998,0.2999999999999999]"]; +n81_2 -> 87 [label="[0.7000000000000001,0.9]"]; +81 -> n81_3 [label="3:choose_w",arrowhead="none"]; +n81_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n81_3 -> 81 [label="[0.09999999999999998,0.2999999999999999]"]; +n81_3 -> 88 [label="[0.7000000000000001,0.9]"]; +82 [label="82"]; +82 -> n82_0 [label="0:choose_e",arrowhead="none"]; +n82_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n82_0 -> 82 [label="[0.09999999999999998,0.2999999999999999]"]; +n82_0 -> 85 [label="[0.7000000000000001,0.9]"]; +82 -> n82_1 [label="1:choose_s",arrowhead="none"]; +n82_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n82_1 -> 82 [label="[0.09999999999999998,0.2999999999999999]"]; +n82_1 -> 86 [label="[0.7000000000000001,0.9]"]; +82 -> n82_2 [label="2:choose_n",arrowhead="none"]; +n82_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n82_2 -> 82 [label="[0.09999999999999998,0.2999999999999999]"]; +n82_2 -> 87 [label="[0.7000000000000001,0.9]"]; +82 -> n82_3 [label="3:choose_w",arrowhead="none"]; +n82_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n82_3 -> 82 [label="[0.09999999999999998,0.2999999999999999]"]; +n82_3 -> 88 [label="[0.7000000000000001,0.9]"]; +83 [label="83"]; +83 -> n83_0 [label="0:choose_e",arrowhead="none"]; +n83_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n83_0 -> 83 [label="[0.09999999999999998,0.2999999999999999]"]; +n83_0 -> 85 [label="[0.7000000000000001,0.9]"]; +83 -> n83_1 [label="1:choose_s",arrowhead="none"]; +n83_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n83_1 -> 83 [label="[0.09999999999999998,0.2999999999999999]"]; +n83_1 -> 86 [label="[0.7000000000000001,0.9]"]; +83 -> n83_2 [label="2:choose_n",arrowhead="none"]; +n83_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n83_2 -> 83 [label="[0.09999999999999998,0.2999999999999999]"]; +n83_2 -> 87 [label="[0.7000000000000001,0.9]"]; +83 -> n83_3 [label="3:choose_w",arrowhead="none"]; +n83_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n83_3 -> 83 [label="[0.09999999999999998,0.2999999999999999]"]; +n83_3 -> 88 [label="[0.7000000000000001,0.9]"]; +84 [label="84"]; +84 -> n84_0 [label="0:choose_e",arrowhead="none"]; +n84_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n84_0 -> 84 [label="[0.09999999999999998,0.2999999999999999]"]; +n84_0 -> 85 [label="[0.7000000000000001,0.9]"]; +84 -> n84_1 [label="1:choose_s",arrowhead="none"]; +n84_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n84_1 -> 84 [label="[0.09999999999999998,0.2999999999999999]"]; +n84_1 -> 86 [label="[0.7000000000000001,0.9]"]; +84 -> n84_2 [label="2:choose_n",arrowhead="none"]; +n84_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n84_2 -> 84 [label="[0.09999999999999998,0.2999999999999999]"]; +n84_2 -> 87 [label="[0.7000000000000001,0.9]"]; +84 -> n84_3 [label="3:choose_w",arrowhead="none"]; +n84_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n84_3 -> 84 [label="[0.09999999999999998,0.2999999999999999]"]; +n84_3 -> 88 [label="[0.7000000000000001,0.9]"]; +85 [label="85"]; +85 -> n85_0 [label="0:forward",arrowhead="none"]; +n85_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n85_0 -> 89 [label="[1,1]"]; +86 [label="86"]; +86 -> n86_0 [label="0:forward",arrowhead="none"]; +n86_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n86_0 -> 90 [label="[1,1]"]; +87 [label="87"]; +87 -> n87_0 [label="0:forward",arrowhead="none"]; +n87_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n87_0 -> 91 [label="[1,1]"]; +88 [label="88"]; +88 -> n88_0 [label="0:forward",arrowhead="none"]; +n88_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n88_0 -> 92 [label="[1,1]"]; +89 [label="89"]; +89 -> n89_0 [label="0:forward",arrowhead="none"]; +n89_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n89_0 -> 93 [label="[1,1]"]; +90 [label="90"]; +90 -> n90_0 [label="0:forward",arrowhead="none"]; +n90_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n90_0 -> 94 [label="[1,1]"]; +91 [label="91"]; +91 -> n91_0 [label="0:forward",arrowhead="none"]; +n91_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n91_0 -> 95 [label="[1,1]"]; +92 [label="92"]; +92 -> n92_0 [label="0:forward",arrowhead="none"]; +n92_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n92_0 -> 96 [label="[1,1]"]; +93 [label="93"]; +93 -> n93_0 [label="0:forward",arrowhead="none"]; +n93_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n93_0 -> 97 [label="[1,1]"]; +94 [label="94"]; +94 -> n94_0 [label="0:forward",arrowhead="none"]; +n94_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n94_0 -> 98 [label="[1,1]"]; +95 [label="95"]; +95 -> n95_0 [label="0:forward",arrowhead="none"]; +n95_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n95_0 -> 99 [label="[1,1]"]; +96 [label="96"]; +96 -> n96_0 [label="0:forward",arrowhead="none"]; +n96_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n96_0 -> 100 [label="[1,1]"]; +97 [label="97"]; +97 -> n97_0 [label="0:arrive",arrowhead="none"]; +n97_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n97_0 -> 97 [label="[0.09999999999999998,0.2999999999999999]"]; +n97_0 -> 170 [label="[0.7000000000000001,0.9]"]; +98 [label="98"]; +98 -> n98_0 [label="0:arrive",arrowhead="none"]; +n98_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n98_0 -> 98 [label="[0.09999999999999998,0.2999999999999999]"]; +n98_0 -> 102 [label="[0.7000000000000001,0.9]"]; +99 [label="99"]; +99 -> n99_0 [label="0:arrive",arrowhead="none"]; +n99_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n99_0 -> 67 [label="[0.7000000000000001,0.9]"]; +n99_0 -> 99 [label="[0.09999999999999998,0.2999999999999999]"]; +100 [label="100"]; +100 -> n100_0 [label="0:arrive",arrowhead="none"]; +n100_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n100_0 -> 13 [label="[0.7000000000000001,0.9]"]; +n100_0 -> 100 [label="[0.09999999999999998,0.2999999999999999]"]; +101 [label="101"]; +101 -> n101_0 [label="0:choose_e",arrowhead="none"]; +n101_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n101_0 -> 101 [label="[0.09999999999999998,0.2999999999999999]"]; +n101_0 -> 105 [label="[0.7000000000000001,0.9]"]; +101 -> n101_1 [label="1:choose_s",arrowhead="none"]; +n101_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n101_1 -> 101 [label="[0.09999999999999998,0.2999999999999999]"]; +n101_1 -> 106 [label="[0.7000000000000001,0.9]"]; +101 -> n101_2 [label="2:choose_n",arrowhead="none"]; +n101_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n101_2 -> 101 [label="[0.09999999999999998,0.2999999999999999]"]; +n101_2 -> 107 [label="[0.7000000000000001,0.9]"]; +101 -> n101_3 [label="3:choose_w",arrowhead="none"]; +n101_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n101_3 -> 101 [label="[0.09999999999999998,0.2999999999999999]"]; +n101_3 -> 108 [label="[0.7000000000000001,0.9]"]; +102 [label="102"]; +102 -> n102_0 [label="0:choose_e",arrowhead="none"]; +n102_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n102_0 -> 102 [label="[0.09999999999999998,0.2999999999999999]"]; +n102_0 -> 105 [label="[0.7000000000000001,0.9]"]; +102 -> n102_1 [label="1:choose_s",arrowhead="none"]; +n102_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n102_1 -> 102 [label="[0.09999999999999998,0.2999999999999999]"]; +n102_1 -> 106 [label="[0.7000000000000001,0.9]"]; +102 -> n102_2 [label="2:choose_n",arrowhead="none"]; +n102_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n102_2 -> 102 [label="[0.09999999999999998,0.2999999999999999]"]; +n102_2 -> 107 [label="[0.7000000000000001,0.9]"]; +102 -> n102_3 [label="3:choose_w",arrowhead="none"]; +n102_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n102_3 -> 102 [label="[0.09999999999999998,0.2999999999999999]"]; +n102_3 -> 108 [label="[0.7000000000000001,0.9]"]; +103 [label="103"]; +103 -> n103_0 [label="0:choose_e",arrowhead="none"]; +n103_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n103_0 -> 103 [label="[0.09999999999999998,0.2999999999999999]"]; +n103_0 -> 105 [label="[0.7000000000000001,0.9]"]; +103 -> n103_1 [label="1:choose_s",arrowhead="none"]; +n103_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n103_1 -> 103 [label="[0.09999999999999998,0.2999999999999999]"]; +n103_1 -> 106 [label="[0.7000000000000001,0.9]"]; +103 -> n103_2 [label="2:choose_n",arrowhead="none"]; +n103_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n103_2 -> 103 [label="[0.09999999999999998,0.2999999999999999]"]; +n103_2 -> 107 [label="[0.7000000000000001,0.9]"]; +103 -> n103_3 [label="3:choose_w",arrowhead="none"]; +n103_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n103_3 -> 103 [label="[0.09999999999999998,0.2999999999999999]"]; +n103_3 -> 108 [label="[0.7000000000000001,0.9]"]; +104 [label="104"]; +104 -> n104_0 [label="0:choose_e",arrowhead="none"]; +n104_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n104_0 -> 104 [label="[0.09999999999999998,0.2999999999999999]"]; +n104_0 -> 105 [label="[0.7000000000000001,0.9]"]; +104 -> n104_1 [label="1:choose_s",arrowhead="none"]; +n104_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n104_1 -> 104 [label="[0.09999999999999998,0.2999999999999999]"]; +n104_1 -> 106 [label="[0.7000000000000001,0.9]"]; +104 -> n104_2 [label="2:choose_n",arrowhead="none"]; +n104_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n104_2 -> 104 [label="[0.09999999999999998,0.2999999999999999]"]; +n104_2 -> 107 [label="[0.7000000000000001,0.9]"]; +104 -> n104_3 [label="3:choose_w",arrowhead="none"]; +n104_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n104_3 -> 104 [label="[0.09999999999999998,0.2999999999999999]"]; +n104_3 -> 108 [label="[0.7000000000000001,0.9]"]; +105 [label="105"]; +105 -> n105_0 [label="0:forward",arrowhead="none"]; +n105_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n105_0 -> 109 [label="[1,1]"]; +106 [label="106"]; +106 -> n106_0 [label="0:forward",arrowhead="none"]; +n106_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n106_0 -> 110 [label="[1,1]"]; +107 [label="107"]; +107 -> n107_0 [label="0:forward",arrowhead="none"]; +n107_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n107_0 -> 111 [label="[1,1]"]; +108 [label="108"]; +108 -> n108_0 [label="0:forward",arrowhead="none"]; +n108_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n108_0 -> 112 [label="[1,1]"]; +109 [label="109"]; +109 -> n109_0 [label="0:forward",arrowhead="none"]; +n109_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n109_0 -> 113 [label="[1,1]"]; +110 [label="110"]; +110 -> n110_0 [label="0:forward",arrowhead="none"]; +n110_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n110_0 -> 114 [label="[1,1]"]; +111 [label="111"]; +111 -> n111_0 [label="0:forward",arrowhead="none"]; +n111_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n111_0 -> 115 [label="[1,1]"]; +112 [label="112"]; +112 -> n112_0 [label="0:forward",arrowhead="none"]; +n112_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n112_0 -> 116 [label="[1,1]"]; +113 [label="113"]; +113 -> n113_0 [label="0:forward",arrowhead="none"]; +n113_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n113_0 -> 117 [label="[1,1]"]; +114 [label="114"]; +114 -> n114_0 [label="0:forward",arrowhead="none"]; +n114_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n114_0 -> 118 [label="[1,1]"]; +115 [label="115"]; +115 -> n115_0 [label="0:forward",arrowhead="none"]; +n115_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n115_0 -> 119 [label="[1,1]"]; +116 [label="116"]; +116 -> n116_0 [label="0:forward",arrowhead="none"]; +n116_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n116_0 -> 120 [label="[1,1]"]; +117 [label="117"]; +117 -> n117_0 [label="0:arrive",arrowhead="none"]; +n117_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n117_0 -> 117 [label="[0.09999999999999998,0.2999999999999999]"]; +n117_0 -> 190 [label="[0.7000000000000001,0.9]"]; +118 [label="118"]; +118 -> n118_0 [label="0:arrive",arrowhead="none"]; +n118_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n118_0 -> 118 [label="[0.09999999999999998,0.2999999999999999]"]; +n118_0 -> 122 [label="[0.7000000000000001,0.9]"]; +119 [label="119"]; +119 -> n119_0 [label="0:arrive",arrowhead="none"]; +n119_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n119_0 -> 83 [label="[0.7000000000000001,0.9]"]; +n119_0 -> 119 [label="[0.09999999999999998,0.2999999999999999]"]; +120 [label="120"]; +120 -> n120_0 [label="0:arrive",arrowhead="none"]; +n120_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n120_0 -> 28 [label="[0.7000000000000001,0.9]"]; +n120_0 -> 120 [label="[0.09999999999999998,0.2999999999999999]"]; +121 [label="121"]; +121 -> n121_0 [label="0:choose_e",arrowhead="none"]; +n121_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n121_0 -> 121 [label="[0.09999999999999998,0.2999999999999999]"]; +n121_0 -> 125 [label="[0.7000000000000001,0.9]"]; +121 -> n121_1 [label="1:choose_s",arrowhead="none"]; +n121_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n121_1 -> 121 [label="[0.09999999999999998,0.2999999999999999]"]; +n121_1 -> 126 [label="[0.7000000000000001,0.9]"]; +121 -> n121_2 [label="2:choose_n",arrowhead="none"]; +n121_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n121_2 -> 121 [label="[0.09999999999999998,0.2999999999999999]"]; +n121_2 -> 127 [label="[0.7000000000000001,0.9]"]; +121 -> n121_3 [label="3:choose_w",arrowhead="none"]; +n121_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n121_3 -> 121 [label="[0.09999999999999998,0.2999999999999999]"]; +n121_3 -> 128 [label="[0.7000000000000001,0.9]"]; +122 [label="122"]; +122 -> n122_0 [label="0:choose_e",arrowhead="none"]; +n122_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n122_0 -> 122 [label="[0.09999999999999998,0.2999999999999999]"]; +n122_0 -> 125 [label="[0.7000000000000001,0.9]"]; +122 -> n122_1 [label="1:choose_s",arrowhead="none"]; +n122_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n122_1 -> 122 [label="[0.09999999999999998,0.2999999999999999]"]; +n122_1 -> 126 [label="[0.7000000000000001,0.9]"]; +122 -> n122_2 [label="2:choose_n",arrowhead="none"]; +n122_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n122_2 -> 122 [label="[0.09999999999999998,0.2999999999999999]"]; +n122_2 -> 127 [label="[0.7000000000000001,0.9]"]; +122 -> n122_3 [label="3:choose_w",arrowhead="none"]; +n122_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n122_3 -> 122 [label="[0.09999999999999998,0.2999999999999999]"]; +n122_3 -> 128 [label="[0.7000000000000001,0.9]"]; +123 [label="123"]; +123 -> n123_0 [label="0:choose_e",arrowhead="none"]; +n123_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n123_0 -> 123 [label="[0.09999999999999998,0.2999999999999999]"]; +n123_0 -> 125 [label="[0.7000000000000001,0.9]"]; +123 -> n123_1 [label="1:choose_s",arrowhead="none"]; +n123_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n123_1 -> 123 [label="[0.09999999999999998,0.2999999999999999]"]; +n123_1 -> 126 [label="[0.7000000000000001,0.9]"]; +123 -> n123_2 [label="2:choose_n",arrowhead="none"]; +n123_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n123_2 -> 123 [label="[0.09999999999999998,0.2999999999999999]"]; +n123_2 -> 127 [label="[0.7000000000000001,0.9]"]; +123 -> n123_3 [label="3:choose_w",arrowhead="none"]; +n123_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n123_3 -> 123 [label="[0.09999999999999998,0.2999999999999999]"]; +n123_3 -> 128 [label="[0.7000000000000001,0.9]"]; +124 [label="124"]; +124 -> n124_0 [label="0:choose_e",arrowhead="none"]; +n124_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n124_0 -> 124 [label="[0.09999999999999998,0.2999999999999999]"]; +n124_0 -> 125 [label="[0.7000000000000001,0.9]"]; +124 -> n124_1 [label="1:choose_s",arrowhead="none"]; +n124_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n124_1 -> 124 [label="[0.09999999999999998,0.2999999999999999]"]; +n124_1 -> 126 [label="[0.7000000000000001,0.9]"]; +124 -> n124_2 [label="2:choose_n",arrowhead="none"]; +n124_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n124_2 -> 124 [label="[0.09999999999999998,0.2999999999999999]"]; +n124_2 -> 127 [label="[0.7000000000000001,0.9]"]; +124 -> n124_3 [label="3:choose_w",arrowhead="none"]; +n124_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n124_3 -> 124 [label="[0.09999999999999998,0.2999999999999999]"]; +n124_3 -> 128 [label="[0.7000000000000001,0.9]"]; +125 [label="125"]; +125 -> n125_0 [label="0:forward",arrowhead="none"]; +n125_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n125_0 -> 129 [label="[1,1]"]; +126 [label="126"]; +126 -> n126_0 [label="0:forward",arrowhead="none"]; +n126_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n126_0 -> 130 [label="[1,1]"]; +127 [label="127"]; +127 -> n127_0 [label="0:forward",arrowhead="none"]; +n127_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n127_0 -> 131 [label="[1,1]"]; +128 [label="128"]; +128 -> n128_0 [label="0:forward",arrowhead="none"]; +n128_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n128_0 -> 132 [label="[1,1]"]; +129 [label="129"]; +129 -> n129_0 [label="0:forward",arrowhead="none"]; +n129_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n129_0 -> 133 [label="[1,1]"]; +130 [label="130"]; +130 -> n130_0 [label="0:forward",arrowhead="none"]; +n130_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n130_0 -> 134 [label="[1,1]"]; +131 [label="131"]; +131 -> n131_0 [label="0:forward",arrowhead="none"]; +n131_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n131_0 -> 135 [label="[1,1]"]; +132 [label="132"]; +132 -> n132_0 [label="0:forward",arrowhead="none"]; +n132_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n132_0 -> 136 [label="[1,1]"]; +133 [label="133"]; +133 -> n133_0 [label="0:forward",arrowhead="none"]; +n133_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n133_0 -> 137 [label="[1,1]"]; +134 [label="134"]; +134 -> n134_0 [label="0:forward",arrowhead="none"]; +n134_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n134_0 -> 138 [label="[1,1]"]; +135 [label="135"]; +135 -> n135_0 [label="0:forward",arrowhead="none"]; +n135_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n135_0 -> 139 [label="[1,1]"]; +136 [label="136"]; +136 -> n136_0 [label="0:forward",arrowhead="none"]; +n136_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n136_0 -> 140 [label="[1,1]"]; +137 [label="137"]; +137 -> n137_0 [label="0:arrive",arrowhead="none"]; +n137_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n137_0 -> 137 [label="[0.09999999999999998,0.2999999999999999]"]; +n137_0 -> 210 [label="[0.7000000000000001,0.9]"]; +138 [label="138"]; +138 -> n138_0 [label="0:arrive",arrowhead="none"]; +n138_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n138_0 -> 138 [label="[0.09999999999999998,0.2999999999999999]"]; +n138_0 -> 142 [label="[0.7000000000000001,0.9]"]; +139 [label="139"]; +139 -> n139_0 [label="0:arrive",arrowhead="none"]; +n139_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n139_0 -> 103 [label="[0.7000000000000001,0.9]"]; +n139_0 -> 139 [label="[0.09999999999999998,0.2999999999999999]"]; +140 [label="140"]; +140 -> n140_0 [label="0:arrive",arrowhead="none"]; +n140_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n140_0 -> 43 [label="[0.7000000000000001,0.9]"]; +n140_0 -> 140 [label="[0.09999999999999998,0.2999999999999999]"]; +141 [label="141"]; +141 -> n141_0 [label="0:choose_e",arrowhead="none"]; +n141_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n141_0 -> 141 [label="[0.09999999999999998,0.2999999999999999]"]; +n141_0 -> 143 [label="[0.7000000000000001,0.9]"]; +141 -> n141_1 [label="1:choose_n",arrowhead="none"]; +n141_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n141_1 -> 141 [label="[0.09999999999999998,0.2999999999999999]"]; +n141_1 -> 144 [label="[0.7000000000000001,0.9]"]; +141 -> n141_2 [label="2:choose_w",arrowhead="none"]; +n141_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n141_2 -> 141 [label="[0.09999999999999998,0.2999999999999999]"]; +n141_2 -> 145 [label="[0.7000000000000001,0.9]"]; +142 [label="142"]; +142 -> n142_0 [label="0:choose_e",arrowhead="none"]; +n142_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n142_0 -> 142 [label="[0.09999999999999998,0.2999999999999999]"]; +n142_0 -> 143 [label="[0.7000000000000001,0.9]"]; +142 -> n142_1 [label="1:choose_n",arrowhead="none"]; +n142_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n142_1 -> 142 [label="[0.09999999999999998,0.2999999999999999]"]; +n142_1 -> 144 [label="[0.7000000000000001,0.9]"]; +142 -> n142_2 [label="2:choose_w",arrowhead="none"]; +n142_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n142_2 -> 142 [label="[0.09999999999999998,0.2999999999999999]"]; +n142_2 -> 145 [label="[0.7000000000000001,0.9]"]; +143 [label="143"]; +143 -> n143_0 [label="0:forward",arrowhead="none"]; +n143_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n143_0 -> 146 [label="[1,1]"]; +144 [label="144"]; +144 -> n144_0 [label="0:forward",arrowhead="none"]; +n144_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n144_0 -> 147 [label="[1,1]"]; +145 [label="145"]; +145 -> n145_0 [label="0:forward",arrowhead="none"]; +n145_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n145_0 -> 148 [label="[1,1]"]; +146 [label="146"]; +146 -> n146_0 [label="0:forward",arrowhead="none"]; +n146_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n146_0 -> 149 [label="[1,1]"]; +147 [label="147"]; +147 -> n147_0 [label="0:forward",arrowhead="none"]; +n147_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n147_0 -> 150 [label="[1,1]"]; +148 [label="148"]; +148 -> n148_0 [label="0:forward",arrowhead="none"]; +n148_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n148_0 -> 151 [label="[1,1]"]; +149 [label="149"]; +149 -> n149_0 [label="0:forward",arrowhead="none"]; +n149_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n149_0 -> 152 [label="[1,1]"]; +150 [label="150"]; +150 -> n150_0 [label="0:forward",arrowhead="none"]; +n150_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n150_0 -> 153 [label="[1,1]"]; +151 [label="151"]; +151 -> n151_0 [label="0:forward",arrowhead="none"]; +n151_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n151_0 -> 154 [label="[1,1]"]; +152 [label="152"]; +152 -> n152_0 [label="0:arrive",arrowhead="none"]; +n152_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n152_0 -> 152 [label="[0.09999999999999998,0.2999999999999999]"]; +n152_0 -> 229 [label="[0.7000000000000001,0.9]"]; +153 [label="153"]; +153 -> n153_0 [label="0:arrive",arrowhead="none"]; +n153_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n153_0 -> 123 [label="[0.7000000000000001,0.9]"]; +n153_0 -> 153 [label="[0.09999999999999998,0.2999999999999999]"]; +154 [label="154"]; +154 -> n154_0 [label="0:arrive",arrowhead="none"]; +n154_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n154_0 -> 57 [label="[0.7000000000000001,0.9]"]; +n154_0 -> 154 [label="[0.09999999999999998,0.2999999999999999]"]; +155 [label="155"]; +155 -> n155_0 [label="0:choose_e",arrowhead="none"]; +n155_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n155_0 -> 155 [label="[0.09999999999999998,0.2999999999999999]"]; +n155_0 -> 158 [label="[0.7000000000000001,0.9]"]; +155 -> n155_1 [label="1:choose_s",arrowhead="none"]; +n155_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n155_1 -> 155 [label="[0.09999999999999998,0.2999999999999999]"]; +n155_1 -> 159 [label="[0.7000000000000001,0.9]"]; +155 -> n155_2 [label="2:choose_w",arrowhead="none"]; +n155_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n155_2 -> 155 [label="[0.09999999999999998,0.2999999999999999]"]; +n155_2 -> 160 [label="[0.7000000000000001,0.9]"]; +156 [label="156"]; +156 -> n156_0 [label="0:choose_e",arrowhead="none"]; +n156_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n156_0 -> 156 [label="[0.09999999999999998,0.2999999999999999]"]; +n156_0 -> 158 [label="[0.7000000000000001,0.9]"]; +156 -> n156_1 [label="1:choose_s",arrowhead="none"]; +n156_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n156_1 -> 156 [label="[0.09999999999999998,0.2999999999999999]"]; +n156_1 -> 159 [label="[0.7000000000000001,0.9]"]; +156 -> n156_2 [label="2:choose_w",arrowhead="none"]; +n156_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n156_2 -> 156 [label="[0.09999999999999998,0.2999999999999999]"]; +n156_2 -> 160 [label="[0.7000000000000001,0.9]"]; +157 [label="157"]; +157 -> n157_0 [label="0:choose_e",arrowhead="none"]; +n157_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n157_0 -> 157 [label="[0.09999999999999998,0.2999999999999999]"]; +n157_0 -> 158 [label="[0.7000000000000001,0.9]"]; +157 -> n157_1 [label="1:choose_s",arrowhead="none"]; +n157_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n157_1 -> 157 [label="[0.09999999999999998,0.2999999999999999]"]; +n157_1 -> 159 [label="[0.7000000000000001,0.9]"]; +157 -> n157_2 [label="2:choose_w",arrowhead="none"]; +n157_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n157_2 -> 157 [label="[0.09999999999999998,0.2999999999999999]"]; +n157_2 -> 160 [label="[0.7000000000000001,0.9]"]; +158 [label="158"]; +158 -> n158_0 [label="0:forward",arrowhead="none"]; +n158_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n158_0 -> 161 [label="[1,1]"]; +159 [label="159"]; +159 -> n159_0 [label="0:forward",arrowhead="none"]; +n159_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n159_0 -> 162 [label="[1,1]"]; +160 [label="160"]; +160 -> n160_0 [label="0:forward",arrowhead="none"]; +n160_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n160_0 -> 163 [label="[1,1]"]; +161 [label="161"]; +161 -> n161_0 [label="0:forward",arrowhead="none"]; +n161_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n161_0 -> 164 [label="[1,1]"]; +162 [label="162"]; +162 -> n162_0 [label="0:forward",arrowhead="none"]; +n162_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n162_0 -> 165 [label="[1,1]"]; +163 [label="163"]; +163 -> n163_0 [label="0:forward",arrowhead="none"]; +n163_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n163_0 -> 166 [label="[1,1]"]; +164 [label="164"]; +164 -> n164_0 [label="0:forward",arrowhead="none"]; +n164_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n164_0 -> 167 [label="[1,1]"]; +165 [label="165"]; +165 -> n165_0 [label="0:forward",arrowhead="none"]; +n165_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n165_0 -> 168 [label="[1,1]"]; +166 [label="166"]; +166 -> n166_0 [label="0:forward",arrowhead="none"]; +n166_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n166_0 -> 169 [label="[1,1]"]; +167 [label="167"]; +167 -> n167_0 [label="0:arrive",arrowhead="none"]; +n167_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n167_0 -> 167 [label="[0.09999999999999998,0.2999999999999999]"]; +n167_0 -> 232 [label="[0.7000000000000001,0.9]"]; +168 [label="168"]; +168 -> n168_0 [label="0:arrive",arrowhead="none"]; +n168_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n168_0 -> 168 [label="[0.09999999999999998,0.2999999999999999]"]; +n168_0 -> 171 [label="[0.7000000000000001,0.9]"]; +169 [label="169"]; +169 -> n169_0 [label="0:arrive",arrowhead="none"]; +n169_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n169_0 -> 68 [label="[0.7000000000000001,0.9]"]; +n169_0 -> 169 [label="[0.09999999999999998,0.2999999999999999]"]; +170 [label="170"]; +170 -> n170_0 [label="0:choose_e",arrowhead="none"]; +n170_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n170_0 -> 170 [label="[0.09999999999999998,0.2999999999999999]"]; +n170_0 -> 174 [label="[0.7000000000000001,0.9]"]; +170 -> n170_1 [label="1:choose_s",arrowhead="none"]; +n170_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n170_1 -> 170 [label="[0.09999999999999998,0.2999999999999999]"]; +n170_1 -> 175 [label="[0.7000000000000001,0.9]"]; +170 -> n170_2 [label="2:choose_n",arrowhead="none"]; +n170_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n170_2 -> 170 [label="[0.09999999999999998,0.2999999999999999]"]; +n170_2 -> 176 [label="[0.7000000000000001,0.9]"]; +170 -> n170_3 [label="3:choose_w",arrowhead="none"]; +n170_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n170_3 -> 170 [label="[0.09999999999999998,0.2999999999999999]"]; +n170_3 -> 177 [label="[0.7000000000000001,0.9]"]; +171 [label="171"]; +171 -> n171_0 [label="0:choose_e",arrowhead="none"]; +n171_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n171_0 -> 171 [label="[0.09999999999999998,0.2999999999999999]"]; +n171_0 -> 174 [label="[0.7000000000000001,0.9]"]; +171 -> n171_1 [label="1:choose_s",arrowhead="none"]; +n171_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n171_1 -> 171 [label="[0.09999999999999998,0.2999999999999999]"]; +n171_1 -> 175 [label="[0.7000000000000001,0.9]"]; +171 -> n171_2 [label="2:choose_n",arrowhead="none"]; +n171_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n171_2 -> 171 [label="[0.09999999999999998,0.2999999999999999]"]; +n171_2 -> 176 [label="[0.7000000000000001,0.9]"]; +171 -> n171_3 [label="3:choose_w",arrowhead="none"]; +n171_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n171_3 -> 171 [label="[0.09999999999999998,0.2999999999999999]"]; +n171_3 -> 177 [label="[0.7000000000000001,0.9]"]; +172 [label="172"]; +172 -> n172_0 [label="0:choose_e",arrowhead="none"]; +n172_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n172_0 -> 172 [label="[0.09999999999999998,0.2999999999999999]"]; +n172_0 -> 174 [label="[0.7000000000000001,0.9]"]; +172 -> n172_1 [label="1:choose_s",arrowhead="none"]; +n172_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n172_1 -> 172 [label="[0.09999999999999998,0.2999999999999999]"]; +n172_1 -> 175 [label="[0.7000000000000001,0.9]"]; +172 -> n172_2 [label="2:choose_n",arrowhead="none"]; +n172_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n172_2 -> 172 [label="[0.09999999999999998,0.2999999999999999]"]; +n172_2 -> 176 [label="[0.7000000000000001,0.9]"]; +172 -> n172_3 [label="3:choose_w",arrowhead="none"]; +n172_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n172_3 -> 172 [label="[0.09999999999999998,0.2999999999999999]"]; +n172_3 -> 177 [label="[0.7000000000000001,0.9]"]; +173 [label="173"]; +173 -> n173_0 [label="0:choose_e",arrowhead="none"]; +n173_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n173_0 -> 173 [label="[0.09999999999999998,0.2999999999999999]"]; +n173_0 -> 174 [label="[0.7000000000000001,0.9]"]; +173 -> n173_1 [label="1:choose_s",arrowhead="none"]; +n173_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n173_1 -> 173 [label="[0.09999999999999998,0.2999999999999999]"]; +n173_1 -> 175 [label="[0.7000000000000001,0.9]"]; +173 -> n173_2 [label="2:choose_n",arrowhead="none"]; +n173_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n173_2 -> 173 [label="[0.09999999999999998,0.2999999999999999]"]; +n173_2 -> 176 [label="[0.7000000000000001,0.9]"]; +173 -> n173_3 [label="3:choose_w",arrowhead="none"]; +n173_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n173_3 -> 173 [label="[0.09999999999999998,0.2999999999999999]"]; +n173_3 -> 177 [label="[0.7000000000000001,0.9]"]; +174 [label="174"]; +174 -> n174_0 [label="0:forward",arrowhead="none"]; +n174_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n174_0 -> 178 [label="[1,1]"]; +175 [label="175"]; +175 -> n175_0 [label="0:forward",arrowhead="none"]; +n175_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n175_0 -> 179 [label="[1,1]"]; +176 [label="176"]; +176 -> n176_0 [label="0:forward",arrowhead="none"]; +n176_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n176_0 -> 180 [label="[1,1]"]; +177 [label="177"]; +177 -> n177_0 [label="0:forward",arrowhead="none"]; +n177_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n177_0 -> 181 [label="[1,1]"]; +178 [label="178"]; +178 -> n178_0 [label="0:forward",arrowhead="none"]; +n178_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n178_0 -> 182 [label="[1,1]"]; +179 [label="179"]; +179 -> n179_0 [label="0:forward",arrowhead="none"]; +n179_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n179_0 -> 183 [label="[1,1]"]; +180 [label="180"]; +180 -> n180_0 [label="0:forward",arrowhead="none"]; +n180_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n180_0 -> 184 [label="[1,1]"]; +181 [label="181"]; +181 -> n181_0 [label="0:forward",arrowhead="none"]; +n181_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n181_0 -> 185 [label="[1,1]"]; +182 [label="182"]; +182 -> n182_0 [label="0:forward",arrowhead="none"]; +n182_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n182_0 -> 186 [label="[1,1]"]; +183 [label="183"]; +183 -> n183_0 [label="0:forward",arrowhead="none"]; +n183_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n183_0 -> 187 [label="[1,1]"]; +184 [label="184"]; +184 -> n184_0 [label="0:forward",arrowhead="none"]; +n184_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n184_0 -> 188 [label="[1,1]"]; +185 [label="185"]; +185 -> n185_0 [label="0:forward",arrowhead="none"]; +n185_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n185_0 -> 189 [label="[1,1]"]; +186 [label="186"]; +186 -> n186_0 [label="0:arrive",arrowhead="none"]; +n186_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n186_0 -> 186 [label="[0.09999999999999998,0.2999999999999999]"]; +n186_0 -> 246 [label="[0.7000000000000001,0.9]"]; +187 [label="187"]; +187 -> n187_0 [label="0:arrive",arrowhead="none"]; +n187_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n187_0 -> 187 [label="[0.09999999999999998,0.2999999999999999]"]; +n187_0 -> 191 [label="[0.7000000000000001,0.9]"]; +188 [label="188"]; +188 -> n188_0 [label="0:arrive",arrowhead="none"]; +n188_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n188_0 -> 156 [label="[0.7000000000000001,0.9]"]; +n188_0 -> 188 [label="[0.09999999999999998,0.2999999999999999]"]; +189 [label="189"]; +189 -> n189_0 [label="0:arrive",arrowhead="none"]; +n189_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n189_0 -> 84 [label="[0.7000000000000001,0.9]"]; +n189_0 -> 189 [label="[0.09999999999999998,0.2999999999999999]"]; +190 [label="190"]; +190 -> n190_0 [label="0:choose_e",arrowhead="none"]; +n190_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n190_0 -> 190 [label="[0.09999999999999998,0.2999999999999999]"]; +n190_0 -> 194 [label="[0.7000000000000001,0.9]"]; +190 -> n190_1 [label="1:choose_s",arrowhead="none"]; +n190_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n190_1 -> 190 [label="[0.09999999999999998,0.2999999999999999]"]; +n190_1 -> 195 [label="[0.7000000000000001,0.9]"]; +190 -> n190_2 [label="2:choose_n",arrowhead="none"]; +n190_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n190_2 -> 190 [label="[0.09999999999999998,0.2999999999999999]"]; +n190_2 -> 196 [label="[0.7000000000000001,0.9]"]; +190 -> n190_3 [label="3:choose_w",arrowhead="none"]; +n190_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n190_3 -> 190 [label="[0.09999999999999998,0.2999999999999999]"]; +n190_3 -> 197 [label="[0.7000000000000001,0.9]"]; +191 [label="191"]; +191 -> n191_0 [label="0:choose_e",arrowhead="none"]; +n191_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n191_0 -> 191 [label="[0.09999999999999998,0.2999999999999999]"]; +n191_0 -> 194 [label="[0.7000000000000001,0.9]"]; +191 -> n191_1 [label="1:choose_s",arrowhead="none"]; +n191_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n191_1 -> 191 [label="[0.09999999999999998,0.2999999999999999]"]; +n191_1 -> 195 [label="[0.7000000000000001,0.9]"]; +191 -> n191_2 [label="2:choose_n",arrowhead="none"]; +n191_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n191_2 -> 191 [label="[0.09999999999999998,0.2999999999999999]"]; +n191_2 -> 196 [label="[0.7000000000000001,0.9]"]; +191 -> n191_3 [label="3:choose_w",arrowhead="none"]; +n191_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n191_3 -> 191 [label="[0.09999999999999998,0.2999999999999999]"]; +n191_3 -> 197 [label="[0.7000000000000001,0.9]"]; +192 [label="192"]; +192 -> n192_0 [label="0:choose_e",arrowhead="none"]; +n192_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n192_0 -> 192 [label="[0.09999999999999998,0.2999999999999999]"]; +n192_0 -> 194 [label="[0.7000000000000001,0.9]"]; +192 -> n192_1 [label="1:choose_s",arrowhead="none"]; +n192_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n192_1 -> 192 [label="[0.09999999999999998,0.2999999999999999]"]; +n192_1 -> 195 [label="[0.7000000000000001,0.9]"]; +192 -> n192_2 [label="2:choose_n",arrowhead="none"]; +n192_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n192_2 -> 192 [label="[0.09999999999999998,0.2999999999999999]"]; +n192_2 -> 196 [label="[0.7000000000000001,0.9]"]; +192 -> n192_3 [label="3:choose_w",arrowhead="none"]; +n192_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n192_3 -> 192 [label="[0.09999999999999998,0.2999999999999999]"]; +n192_3 -> 197 [label="[0.7000000000000001,0.9]"]; +193 [label="193"]; +193 -> n193_0 [label="0:choose_e",arrowhead="none"]; +n193_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n193_0 -> 193 [label="[0.09999999999999998,0.2999999999999999]"]; +n193_0 -> 194 [label="[0.7000000000000001,0.9]"]; +193 -> n193_1 [label="1:choose_s",arrowhead="none"]; +n193_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n193_1 -> 193 [label="[0.09999999999999998,0.2999999999999999]"]; +n193_1 -> 195 [label="[0.7000000000000001,0.9]"]; +193 -> n193_2 [label="2:choose_n",arrowhead="none"]; +n193_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n193_2 -> 193 [label="[0.09999999999999998,0.2999999999999999]"]; +n193_2 -> 196 [label="[0.7000000000000001,0.9]"]; +193 -> n193_3 [label="3:choose_w",arrowhead="none"]; +n193_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n193_3 -> 193 [label="[0.09999999999999998,0.2999999999999999]"]; +n193_3 -> 197 [label="[0.7000000000000001,0.9]"]; +194 [label="194"]; +194 -> n194_0 [label="0:forward",arrowhead="none"]; +n194_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n194_0 -> 198 [label="[1,1]"]; +195 [label="195"]; +195 -> n195_0 [label="0:forward",arrowhead="none"]; +n195_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n195_0 -> 199 [label="[1,1]"]; +196 [label="196"]; +196 -> n196_0 [label="0:forward",arrowhead="none"]; +n196_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n196_0 -> 200 [label="[1,1]"]; +197 [label="197"]; +197 -> n197_0 [label="0:forward",arrowhead="none"]; +n197_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n197_0 -> 201 [label="[1,1]"]; +198 [label="198"]; +198 -> n198_0 [label="0:forward",arrowhead="none"]; +n198_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n198_0 -> 202 [label="[1,1]"]; +199 [label="199"]; +199 -> n199_0 [label="0:forward",arrowhead="none"]; +n199_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n199_0 -> 203 [label="[1,1]"]; +200 [label="200"]; +200 -> n200_0 [label="0:forward",arrowhead="none"]; +n200_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n200_0 -> 204 [label="[1,1]"]; +201 [label="201"]; +201 -> n201_0 [label="0:forward",arrowhead="none"]; +n201_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n201_0 -> 205 [label="[1,1]"]; +202 [label="202"]; +202 -> n202_0 [label="0:forward",arrowhead="none"]; +n202_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n202_0 -> 206 [label="[1,1]"]; +203 [label="203"]; +203 -> n203_0 [label="0:forward",arrowhead="none"]; +n203_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n203_0 -> 207 [label="[1,1]"]; +204 [label="204"]; +204 -> n204_0 [label="0:forward",arrowhead="none"]; +n204_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n204_0 -> 208 [label="[1,1]"]; +205 [label="205"]; +205 -> n205_0 [label="0:forward",arrowhead="none"]; +n205_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n205_0 -> 209 [label="[1,1]"]; +206 [label="206"]; +206 -> n206_0 [label="0:arrive",arrowhead="none"]; +n206_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n206_0 -> 206 [label="[0.09999999999999998,0.2999999999999999]"]; +n206_0 -> 266 [label="[0.7000000000000001,0.9]"]; +207 [label="207"]; +207 -> n207_0 [label="0:arrive",arrowhead="none"]; +n207_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n207_0 -> 207 [label="[0.09999999999999998,0.2999999999999999]"]; +n207_0 -> 211 [label="[0.7000000000000001,0.9]"]; +208 [label="208"]; +208 -> n208_0 [label="0:arrive",arrowhead="none"]; +n208_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n208_0 -> 172 [label="[0.7000000000000001,0.9]"]; +n208_0 -> 208 [label="[0.09999999999999998,0.2999999999999999]"]; +209 [label="209"]; +209 -> n209_0 [label="0:arrive",arrowhead="none"]; +n209_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n209_0 -> 104 [label="[0.7000000000000001,0.9]"]; +n209_0 -> 209 [label="[0.09999999999999998,0.2999999999999999]"]; +210 [label="210"]; +210 -> n210_0 [label="0:choose_e",arrowhead="none"]; +n210_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n210_0 -> 210 [label="[0.09999999999999998,0.2999999999999999]"]; +n210_0 -> 213 [label="[0.7000000000000001,0.9]"]; +210 -> n210_1 [label="1:choose_s",arrowhead="none"]; +n210_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n210_1 -> 210 [label="[0.09999999999999998,0.2999999999999999]"]; +n210_1 -> 214 [label="[0.7000000000000001,0.9]"]; +210 -> n210_2 [label="2:choose_n",arrowhead="none"]; +n210_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n210_2 -> 210 [label="[0.09999999999999998,0.2999999999999999]"]; +n210_2 -> 215 [label="[0.7000000000000001,0.9]"]; +210 -> n210_3 [label="3:choose_w",arrowhead="none"]; +n210_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n210_3 -> 210 [label="[0.09999999999999998,0.2999999999999999]"]; +n210_3 -> 216 [label="[0.7000000000000001,0.9]"]; +211 [label="211"]; +211 -> n211_0 [label="0:choose_e",arrowhead="none"]; +n211_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n211_0 -> 211 [label="[0.09999999999999998,0.2999999999999999]"]; +n211_0 -> 213 [label="[0.7000000000000001,0.9]"]; +211 -> n211_1 [label="1:choose_s",arrowhead="none"]; +n211_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n211_1 -> 211 [label="[0.09999999999999998,0.2999999999999999]"]; +n211_1 -> 214 [label="[0.7000000000000001,0.9]"]; +211 -> n211_2 [label="2:choose_n",arrowhead="none"]; +n211_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n211_2 -> 211 [label="[0.09999999999999998,0.2999999999999999]"]; +n211_2 -> 215 [label="[0.7000000000000001,0.9]"]; +211 -> n211_3 [label="3:choose_w",arrowhead="none"]; +n211_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n211_3 -> 211 [label="[0.09999999999999998,0.2999999999999999]"]; +n211_3 -> 216 [label="[0.7000000000000001,0.9]"]; +212 [label="212"]; +212 -> n212_0 [label="0:choose_e",arrowhead="none"]; +n212_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n212_0 -> 212 [label="[0.09999999999999998,0.2999999999999999]"]; +n212_0 -> 213 [label="[0.7000000000000001,0.9]"]; +212 -> n212_1 [label="1:choose_s",arrowhead="none"]; +n212_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n212_1 -> 212 [label="[0.09999999999999998,0.2999999999999999]"]; +n212_1 -> 214 [label="[0.7000000000000001,0.9]"]; +212 -> n212_2 [label="2:choose_n",arrowhead="none"]; +n212_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n212_2 -> 212 [label="[0.09999999999999998,0.2999999999999999]"]; +n212_2 -> 215 [label="[0.7000000000000001,0.9]"]; +212 -> n212_3 [label="3:choose_w",arrowhead="none"]; +n212_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n212_3 -> 212 [label="[0.09999999999999998,0.2999999999999999]"]; +n212_3 -> 216 [label="[0.7000000000000001,0.9]"]; +213 [label="213"]; +213 -> n213_0 [label="0:forward",arrowhead="none"]; +n213_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n213_0 -> 217 [label="[1,1]"]; +214 [label="214"]; +214 -> n214_0 [label="0:forward",arrowhead="none"]; +n214_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n214_0 -> 218 [label="[1,1]"]; +215 [label="215"]; +215 -> n215_0 [label="0:forward",arrowhead="none"]; +n215_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n215_0 -> 219 [label="[1,1]"]; +216 [label="216"]; +216 -> n216_0 [label="0:forward",arrowhead="none"]; +n216_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n216_0 -> 220 [label="[1,1]"]; +217 [label="217"]; +217 -> n217_0 [label="0:forward",arrowhead="none"]; +n217_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n217_0 -> 221 [label="[1,1]"]; +218 [label="218"]; +218 -> n218_0 [label="0:forward",arrowhead="none"]; +n218_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n218_0 -> 222 [label="[1,1]"]; +219 [label="219"]; +219 -> n219_0 [label="0:forward",arrowhead="none"]; +n219_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n219_0 -> 223 [label="[1,1]"]; +220 [label="220"]; +220 -> n220_0 [label="0:forward",arrowhead="none"]; +n220_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n220_0 -> 224 [label="[1,1]"]; +221 [label="221"]; +221 -> n221_0 [label="0:forward",arrowhead="none"]; +n221_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n221_0 -> 225 [label="[1,1]"]; +222 [label="222"]; +222 -> n222_0 [label="0:forward",arrowhead="none"]; +n222_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n222_0 -> 226 [label="[1,1]"]; +223 [label="223"]; +223 -> n223_0 [label="0:forward",arrowhead="none"]; +n223_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n223_0 -> 227 [label="[1,1]"]; +224 [label="224"]; +224 -> n224_0 [label="0:forward",arrowhead="none"]; +n224_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n224_0 -> 228 [label="[1,1]"]; +225 [label="225"]; +225 -> n225_0 [label="0:arrive",arrowhead="none"]; +n225_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n225_0 -> 225 [label="[0.09999999999999998,0.2999999999999999]"]; +n225_0 -> 286 [label="[0.7000000000000001,0.9]"]; +226 [label="226"]; +226 -> n226_0 [label="0:arrive",arrowhead="none"]; +n226_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n226_0 -> 226 [label="[0.09999999999999998,0.2999999999999999]"]; +n226_0 -> 230 [label="[0.7000000000000001,0.9]"]; +227 [label="227"]; +227 -> n227_0 [label="0:arrive",arrowhead="none"]; +n227_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n227_0 -> 192 [label="[0.7000000000000001,0.9]"]; +n227_0 -> 227 [label="[0.09999999999999998,0.2999999999999999]"]; +228 [label="228"]; +228 -> n228_0 [label="0:arrive",arrowhead="none"]; +n228_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n228_0 -> 124 [label="[0.7000000000000001,0.9]"]; +n228_0 -> 228 [label="[0.09999999999999998,0.2999999999999999]"]; +229 [label="229"]; +229 -> n229_0 [label="0:trap",arrowhead="none"]; +n229_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n229_0 -> 229 [label="[1,1]"]; +230 [label="230"]; +230 -> n230_0 [label="0:trap",arrowhead="none"]; +n230_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n230_0 -> 230 [label="[1,1]"]; +231 [label="231"]; +231 -> n231_0 [label="0:trap",arrowhead="none"]; +n231_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n231_0 -> 231 [label="[1,1]"]; +232 [label="232"]; +232 -> n232_0 [label="0:choose_e",arrowhead="none"]; +n232_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n232_0 -> 232 [label="[0.09999999999999998,0.2999999999999999]"]; +n232_0 -> 234 [label="[0.7000000000000001,0.9]"]; +232 -> n232_1 [label="1:choose_s",arrowhead="none"]; +n232_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n232_1 -> 232 [label="[0.09999999999999998,0.2999999999999999]"]; +n232_1 -> 235 [label="[0.7000000000000001,0.9]"]; +232 -> n232_2 [label="2:choose_w",arrowhead="none"]; +n232_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n232_2 -> 232 [label="[0.09999999999999998,0.2999999999999999]"]; +n232_2 -> 236 [label="[0.7000000000000001,0.9]"]; +233 [label="233"]; +233 -> n233_0 [label="0:choose_e",arrowhead="none"]; +n233_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n233_0 -> 233 [label="[0.09999999999999998,0.2999999999999999]"]; +n233_0 -> 234 [label="[0.7000000000000001,0.9]"]; +233 -> n233_1 [label="1:choose_s",arrowhead="none"]; +n233_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n233_1 -> 233 [label="[0.09999999999999998,0.2999999999999999]"]; +n233_1 -> 235 [label="[0.7000000000000001,0.9]"]; +233 -> n233_2 [label="2:choose_w",arrowhead="none"]; +n233_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n233_2 -> 233 [label="[0.09999999999999998,0.2999999999999999]"]; +n233_2 -> 236 [label="[0.7000000000000001,0.9]"]; +234 [label="234"]; +234 -> n234_0 [label="0:forward",arrowhead="none"]; +n234_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n234_0 -> 237 [label="[1,1]"]; +235 [label="235"]; +235 -> n235_0 [label="0:forward",arrowhead="none"]; +n235_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n235_0 -> 238 [label="[1,1]"]; +236 [label="236"]; +236 -> n236_0 [label="0:forward",arrowhead="none"]; +n236_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n236_0 -> 239 [label="[1,1]"]; +237 [label="237"]; +237 -> n237_0 [label="0:forward",arrowhead="none"]; +n237_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n237_0 -> 240 [label="[1,1]"]; +238 [label="238"]; +238 -> n238_0 [label="0:forward",arrowhead="none"]; +n238_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n238_0 -> 241 [label="[1,1]"]; +239 [label="239"]; +239 -> n239_0 [label="0:forward",arrowhead="none"]; +n239_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n239_0 -> 242 [label="[1,1]"]; +240 [label="240"]; +240 -> n240_0 [label="0:forward",arrowhead="none"]; +n240_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n240_0 -> 243 [label="[1,1]"]; +241 [label="241"]; +241 -> n241_0 [label="0:forward",arrowhead="none"]; +n241_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n241_0 -> 244 [label="[1,1]"]; +242 [label="242"]; +242 -> n242_0 [label="0:forward",arrowhead="none"]; +n242_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n242_0 -> 245 [label="[1,1]"]; +243 [label="243"]; +243 -> n243_0 [label="0:arrive",arrowhead="none"]; +n243_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n243_0 -> 243 [label="[0.09999999999999998,0.2999999999999999]"]; +n243_0 -> 319 [label="[0.7000000000000001,0.9]"]; +244 [label="244"]; +244 -> n244_0 [label="0:arrive",arrowhead="none"]; +n244_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n244_0 -> 244 [label="[0.09999999999999998,0.2999999999999999]"]; +n244_0 -> 247 [label="[0.7000000000000001,0.9]"]; +245 [label="245"]; +245 -> n245_0 [label="0:arrive",arrowhead="none"]; +n245_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n245_0 -> 157 [label="[0.7000000000000001,0.9]"]; +n245_0 -> 245 [label="[0.09999999999999998,0.2999999999999999]"]; +246 [label="246"]; +246 -> n246_0 [label="0:choose_e",arrowhead="none"]; +n246_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n246_0 -> 246 [label="[0.09999999999999998,0.2999999999999999]"]; +n246_0 -> 250 [label="[0.7000000000000001,0.9]"]; +246 -> n246_1 [label="1:choose_s",arrowhead="none"]; +n246_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n246_1 -> 246 [label="[0.09999999999999998,0.2999999999999999]"]; +n246_1 -> 251 [label="[0.7000000000000001,0.9]"]; +246 -> n246_2 [label="2:choose_n",arrowhead="none"]; +n246_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n246_2 -> 246 [label="[0.09999999999999998,0.2999999999999999]"]; +n246_2 -> 252 [label="[0.7000000000000001,0.9]"]; +246 -> n246_3 [label="3:choose_w",arrowhead="none"]; +n246_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n246_3 -> 246 [label="[0.09999999999999998,0.2999999999999999]"]; +n246_3 -> 253 [label="[0.7000000000000001,0.9]"]; +247 [label="247"]; +247 -> n247_0 [label="0:choose_e",arrowhead="none"]; +n247_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n247_0 -> 247 [label="[0.09999999999999998,0.2999999999999999]"]; +n247_0 -> 250 [label="[0.7000000000000001,0.9]"]; +247 -> n247_1 [label="1:choose_s",arrowhead="none"]; +n247_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n247_1 -> 247 [label="[0.09999999999999998,0.2999999999999999]"]; +n247_1 -> 251 [label="[0.7000000000000001,0.9]"]; +247 -> n247_2 [label="2:choose_n",arrowhead="none"]; +n247_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n247_2 -> 247 [label="[0.09999999999999998,0.2999999999999999]"]; +n247_2 -> 252 [label="[0.7000000000000001,0.9]"]; +247 -> n247_3 [label="3:choose_w",arrowhead="none"]; +n247_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n247_3 -> 247 [label="[0.09999999999999998,0.2999999999999999]"]; +n247_3 -> 253 [label="[0.7000000000000001,0.9]"]; +248 [label="248"]; +248 -> n248_0 [label="0:choose_e",arrowhead="none"]; +n248_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n248_0 -> 248 [label="[0.09999999999999998,0.2999999999999999]"]; +n248_0 -> 250 [label="[0.7000000000000001,0.9]"]; +248 -> n248_1 [label="1:choose_s",arrowhead="none"]; +n248_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n248_1 -> 248 [label="[0.09999999999999998,0.2999999999999999]"]; +n248_1 -> 251 [label="[0.7000000000000001,0.9]"]; +248 -> n248_2 [label="2:choose_n",arrowhead="none"]; +n248_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n248_2 -> 248 [label="[0.09999999999999998,0.2999999999999999]"]; +n248_2 -> 252 [label="[0.7000000000000001,0.9]"]; +248 -> n248_3 [label="3:choose_w",arrowhead="none"]; +n248_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n248_3 -> 248 [label="[0.09999999999999998,0.2999999999999999]"]; +n248_3 -> 253 [label="[0.7000000000000001,0.9]"]; +249 [label="249"]; +249 -> n249_0 [label="0:choose_e",arrowhead="none"]; +n249_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n249_0 -> 249 [label="[0.09999999999999998,0.2999999999999999]"]; +n249_0 -> 250 [label="[0.7000000000000001,0.9]"]; +249 -> n249_1 [label="1:choose_s",arrowhead="none"]; +n249_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n249_1 -> 249 [label="[0.09999999999999998,0.2999999999999999]"]; +n249_1 -> 251 [label="[0.7000000000000001,0.9]"]; +249 -> n249_2 [label="2:choose_n",arrowhead="none"]; +n249_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n249_2 -> 249 [label="[0.09999999999999998,0.2999999999999999]"]; +n249_2 -> 252 [label="[0.7000000000000001,0.9]"]; +249 -> n249_3 [label="3:choose_w",arrowhead="none"]; +n249_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n249_3 -> 249 [label="[0.09999999999999998,0.2999999999999999]"]; +n249_3 -> 253 [label="[0.7000000000000001,0.9]"]; +250 [label="250"]; +250 -> n250_0 [label="0:forward",arrowhead="none"]; +n250_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n250_0 -> 254 [label="[1,1]"]; +251 [label="251"]; +251 -> n251_0 [label="0:forward",arrowhead="none"]; +n251_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n251_0 -> 255 [label="[1,1]"]; +252 [label="252"]; +252 -> n252_0 [label="0:forward",arrowhead="none"]; +n252_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n252_0 -> 256 [label="[1,1]"]; +253 [label="253"]; +253 -> n253_0 [label="0:forward",arrowhead="none"]; +n253_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n253_0 -> 257 [label="[1,1]"]; +254 [label="254"]; +254 -> n254_0 [label="0:forward",arrowhead="none"]; +n254_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n254_0 -> 258 [label="[1,1]"]; +255 [label="255"]; +255 -> n255_0 [label="0:forward",arrowhead="none"]; +n255_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n255_0 -> 259 [label="[1,1]"]; +256 [label="256"]; +256 -> n256_0 [label="0:forward",arrowhead="none"]; +n256_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n256_0 -> 260 [label="[1,1]"]; +257 [label="257"]; +257 -> n257_0 [label="0:forward",arrowhead="none"]; +n257_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n257_0 -> 261 [label="[1,1]"]; +258 [label="258"]; +258 -> n258_0 [label="0:forward",arrowhead="none"]; +n258_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n258_0 -> 262 [label="[1,1]"]; +259 [label="259"]; +259 -> n259_0 [label="0:forward",arrowhead="none"]; +n259_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n259_0 -> 263 [label="[1,1]"]; +260 [label="260"]; +260 -> n260_0 [label="0:forward",arrowhead="none"]; +n260_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n260_0 -> 264 [label="[1,1]"]; +261 [label="261"]; +261 -> n261_0 [label="0:forward",arrowhead="none"]; +n261_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n261_0 -> 265 [label="[1,1]"]; +262 [label="262"]; +262 -> n262_0 [label="0:arrive",arrowhead="none"]; +n262_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n262_0 -> 262 [label="[0.09999999999999998,0.2999999999999999]"]; +n262_0 -> 321 [label="[0.7000000000000001,0.9]"]; +263 [label="263"]; +263 -> n263_0 [label="0:arrive",arrowhead="none"]; +n263_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n263_0 -> 263 [label="[0.09999999999999998,0.2999999999999999]"]; +n263_0 -> 267 [label="[0.7000000000000001,0.9]"]; +264 [label="264"]; +264 -> n264_0 [label="0:arrive",arrowhead="none"]; +n264_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n264_0 -> 233 [label="[0.7000000000000001,0.9]"]; +n264_0 -> 264 [label="[0.09999999999999998,0.2999999999999999]"]; +265 [label="265"]; +265 -> n265_0 [label="0:arrive",arrowhead="none"]; +n265_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n265_0 -> 173 [label="[0.7000000000000001,0.9]"]; +n265_0 -> 265 [label="[0.09999999999999998,0.2999999999999999]"]; +266 [label="266"]; +266 -> n266_0 [label="0:choose_e",arrowhead="none"]; +n266_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n266_0 -> 266 [label="[0.09999999999999998,0.2999999999999999]"]; +n266_0 -> 270 [label="[0.7000000000000001,0.9]"]; +266 -> n266_1 [label="1:choose_s",arrowhead="none"]; +n266_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n266_1 -> 266 [label="[0.09999999999999998,0.2999999999999999]"]; +n266_1 -> 271 [label="[0.7000000000000001,0.9]"]; +266 -> n266_2 [label="2:choose_n",arrowhead="none"]; +n266_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n266_2 -> 266 [label="[0.09999999999999998,0.2999999999999999]"]; +n266_2 -> 272 [label="[0.7000000000000001,0.9]"]; +266 -> n266_3 [label="3:choose_w",arrowhead="none"]; +n266_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n266_3 -> 266 [label="[0.09999999999999998,0.2999999999999999]"]; +n266_3 -> 273 [label="[0.7000000000000001,0.9]"]; +267 [label="267"]; +267 -> n267_0 [label="0:choose_e",arrowhead="none"]; +n267_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n267_0 -> 267 [label="[0.09999999999999998,0.2999999999999999]"]; +n267_0 -> 270 [label="[0.7000000000000001,0.9]"]; +267 -> n267_1 [label="1:choose_s",arrowhead="none"]; +n267_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n267_1 -> 267 [label="[0.09999999999999998,0.2999999999999999]"]; +n267_1 -> 271 [label="[0.7000000000000001,0.9]"]; +267 -> n267_2 [label="2:choose_n",arrowhead="none"]; +n267_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n267_2 -> 267 [label="[0.09999999999999998,0.2999999999999999]"]; +n267_2 -> 272 [label="[0.7000000000000001,0.9]"]; +267 -> n267_3 [label="3:choose_w",arrowhead="none"]; +n267_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n267_3 -> 267 [label="[0.09999999999999998,0.2999999999999999]"]; +n267_3 -> 273 [label="[0.7000000000000001,0.9]"]; +268 [label="268"]; +268 -> n268_0 [label="0:choose_e",arrowhead="none"]; +n268_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n268_0 -> 268 [label="[0.09999999999999998,0.2999999999999999]"]; +n268_0 -> 270 [label="[0.7000000000000001,0.9]"]; +268 -> n268_1 [label="1:choose_s",arrowhead="none"]; +n268_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n268_1 -> 268 [label="[0.09999999999999998,0.2999999999999999]"]; +n268_1 -> 271 [label="[0.7000000000000001,0.9]"]; +268 -> n268_2 [label="2:choose_n",arrowhead="none"]; +n268_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n268_2 -> 268 [label="[0.09999999999999998,0.2999999999999999]"]; +n268_2 -> 272 [label="[0.7000000000000001,0.9]"]; +268 -> n268_3 [label="3:choose_w",arrowhead="none"]; +n268_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n268_3 -> 268 [label="[0.09999999999999998,0.2999999999999999]"]; +n268_3 -> 273 [label="[0.7000000000000001,0.9]"]; +269 [label="269"]; +269 -> n269_0 [label="0:choose_e",arrowhead="none"]; +n269_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n269_0 -> 269 [label="[0.09999999999999998,0.2999999999999999]"]; +n269_0 -> 270 [label="[0.7000000000000001,0.9]"]; +269 -> n269_1 [label="1:choose_s",arrowhead="none"]; +n269_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n269_1 -> 269 [label="[0.09999999999999998,0.2999999999999999]"]; +n269_1 -> 271 [label="[0.7000000000000001,0.9]"]; +269 -> n269_2 [label="2:choose_n",arrowhead="none"]; +n269_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n269_2 -> 269 [label="[0.09999999999999998,0.2999999999999999]"]; +n269_2 -> 272 [label="[0.7000000000000001,0.9]"]; +269 -> n269_3 [label="3:choose_w",arrowhead="none"]; +n269_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n269_3 -> 269 [label="[0.09999999999999998,0.2999999999999999]"]; +n269_3 -> 273 [label="[0.7000000000000001,0.9]"]; +270 [label="270"]; +270 -> n270_0 [label="0:forward",arrowhead="none"]; +n270_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n270_0 -> 274 [label="[1,1]"]; +271 [label="271"]; +271 -> n271_0 [label="0:forward",arrowhead="none"]; +n271_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n271_0 -> 275 [label="[1,1]"]; +272 [label="272"]; +272 -> n272_0 [label="0:forward",arrowhead="none"]; +n272_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n272_0 -> 276 [label="[1,1]"]; +273 [label="273"]; +273 -> n273_0 [label="0:forward",arrowhead="none"]; +n273_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n273_0 -> 277 [label="[1,1]"]; +274 [label="274"]; +274 -> n274_0 [label="0:forward",arrowhead="none"]; +n274_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n274_0 -> 278 [label="[1,1]"]; +275 [label="275"]; +275 -> n275_0 [label="0:forward",arrowhead="none"]; +n275_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n275_0 -> 279 [label="[1,1]"]; +276 [label="276"]; +276 -> n276_0 [label="0:forward",arrowhead="none"]; +n276_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n276_0 -> 280 [label="[1,1]"]; +277 [label="277"]; +277 -> n277_0 [label="0:forward",arrowhead="none"]; +n277_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n277_0 -> 281 [label="[1,1]"]; +278 [label="278"]; +278 -> n278_0 [label="0:forward",arrowhead="none"]; +n278_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n278_0 -> 282 [label="[1,1]"]; +279 [label="279"]; +279 -> n279_0 [label="0:forward",arrowhead="none"]; +n279_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n279_0 -> 283 [label="[1,1]"]; +280 [label="280"]; +280 -> n280_0 [label="0:forward",arrowhead="none"]; +n280_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n280_0 -> 284 [label="[1,1]"]; +281 [label="281"]; +281 -> n281_0 [label="0:forward",arrowhead="none"]; +n281_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n281_0 -> 285 [label="[1,1]"]; +282 [label="282"]; +282 -> n282_0 [label="0:arrive",arrowhead="none"]; +n282_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n282_0 -> 282 [label="[0.09999999999999998,0.2999999999999999]"]; +n282_0 -> 335 [label="[0.7000000000000001,0.9]"]; +283 [label="283"]; +283 -> n283_0 [label="0:arrive",arrowhead="none"]; +n283_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n283_0 -> 283 [label="[0.09999999999999998,0.2999999999999999]"]; +n283_0 -> 287 [label="[0.7000000000000001,0.9]"]; +284 [label="284"]; +284 -> n284_0 [label="0:arrive",arrowhead="none"]; +n284_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n284_0 -> 248 [label="[0.7000000000000001,0.9]"]; +n284_0 -> 284 [label="[0.09999999999999998,0.2999999999999999]"]; +285 [label="285"]; +285 -> n285_0 [label="0:arrive",arrowhead="none"]; +n285_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n285_0 -> 193 [label="[0.7000000000000001,0.9]"]; +n285_0 -> 285 [label="[0.09999999999999998,0.2999999999999999]"]; +286 [label="286"]; +286 -> n286_0 [label="0:choose_e",arrowhead="none"]; +n286_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n286_0 -> 286 [label="[0.09999999999999998,0.2999999999999999]"]; +n286_0 -> 290 [label="[0.7000000000000001,0.9]"]; +286 -> n286_1 [label="1:choose_s",arrowhead="none"]; +n286_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n286_1 -> 286 [label="[0.09999999999999998,0.2999999999999999]"]; +n286_1 -> 291 [label="[0.7000000000000001,0.9]"]; +286 -> n286_2 [label="2:choose_n",arrowhead="none"]; +n286_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n286_2 -> 286 [label="[0.09999999999999998,0.2999999999999999]"]; +n286_2 -> 292 [label="[0.7000000000000001,0.9]"]; +286 -> n286_3 [label="3:choose_w",arrowhead="none"]; +n286_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n286_3 -> 286 [label="[0.09999999999999998,0.2999999999999999]"]; +n286_3 -> 293 [label="[0.7000000000000001,0.9]"]; +287 [label="287"]; +287 -> n287_0 [label="0:choose_e",arrowhead="none"]; +n287_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n287_0 -> 287 [label="[0.09999999999999998,0.2999999999999999]"]; +n287_0 -> 290 [label="[0.7000000000000001,0.9]"]; +287 -> n287_1 [label="1:choose_s",arrowhead="none"]; +n287_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n287_1 -> 287 [label="[0.09999999999999998,0.2999999999999999]"]; +n287_1 -> 291 [label="[0.7000000000000001,0.9]"]; +287 -> n287_2 [label="2:choose_n",arrowhead="none"]; +n287_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n287_2 -> 287 [label="[0.09999999999999998,0.2999999999999999]"]; +n287_2 -> 292 [label="[0.7000000000000001,0.9]"]; +287 -> n287_3 [label="3:choose_w",arrowhead="none"]; +n287_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n287_3 -> 287 [label="[0.09999999999999998,0.2999999999999999]"]; +n287_3 -> 293 [label="[0.7000000000000001,0.9]"]; +288 [label="288"]; +288 -> n288_0 [label="0:choose_e",arrowhead="none"]; +n288_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n288_0 -> 288 [label="[0.09999999999999998,0.2999999999999999]"]; +n288_0 -> 290 [label="[0.7000000000000001,0.9]"]; +288 -> n288_1 [label="1:choose_s",arrowhead="none"]; +n288_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n288_1 -> 288 [label="[0.09999999999999998,0.2999999999999999]"]; +n288_1 -> 291 [label="[0.7000000000000001,0.9]"]; +288 -> n288_2 [label="2:choose_n",arrowhead="none"]; +n288_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n288_2 -> 288 [label="[0.09999999999999998,0.2999999999999999]"]; +n288_2 -> 292 [label="[0.7000000000000001,0.9]"]; +288 -> n288_3 [label="3:choose_w",arrowhead="none"]; +n288_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n288_3 -> 288 [label="[0.09999999999999998,0.2999999999999999]"]; +n288_3 -> 293 [label="[0.7000000000000001,0.9]"]; +289 [label="289"]; +289 -> n289_0 [label="0:choose_e",arrowhead="none"]; +n289_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n289_0 -> 289 [label="[0.09999999999999998,0.2999999999999999]"]; +n289_0 -> 290 [label="[0.7000000000000001,0.9]"]; +289 -> n289_1 [label="1:choose_s",arrowhead="none"]; +n289_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n289_1 -> 289 [label="[0.09999999999999998,0.2999999999999999]"]; +n289_1 -> 291 [label="[0.7000000000000001,0.9]"]; +289 -> n289_2 [label="2:choose_n",arrowhead="none"]; +n289_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n289_2 -> 289 [label="[0.09999999999999998,0.2999999999999999]"]; +n289_2 -> 292 [label="[0.7000000000000001,0.9]"]; +289 -> n289_3 [label="3:choose_w",arrowhead="none"]; +n289_3 [ shape=point,width=0.1,height=0.1,label="" ]; +n289_3 -> 289 [label="[0.09999999999999998,0.2999999999999999]"]; +n289_3 -> 293 [label="[0.7000000000000001,0.9]"]; +290 [label="290"]; +290 -> n290_0 [label="0:forward",arrowhead="none"]; +n290_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n290_0 -> 294 [label="[1,1]"]; +291 [label="291"]; +291 -> n291_0 [label="0:forward",arrowhead="none"]; +n291_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n291_0 -> 295 [label="[1,1]"]; +292 [label="292"]; +292 -> n292_0 [label="0:forward",arrowhead="none"]; +n292_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n292_0 -> 296 [label="[1,1]"]; +293 [label="293"]; +293 -> n293_0 [label="0:forward",arrowhead="none"]; +n293_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n293_0 -> 297 [label="[1,1]"]; +294 [label="294"]; +294 -> n294_0 [label="0:forward",arrowhead="none"]; +n294_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n294_0 -> 298 [label="[1,1]"]; +295 [label="295"]; +295 -> n295_0 [label="0:forward",arrowhead="none"]; +n295_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n295_0 -> 299 [label="[1,1]"]; +296 [label="296"]; +296 -> n296_0 [label="0:forward",arrowhead="none"]; +n296_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n296_0 -> 300 [label="[1,1]"]; +297 [label="297"]; +297 -> n297_0 [label="0:forward",arrowhead="none"]; +n297_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n297_0 -> 301 [label="[1,1]"]; +298 [label="298"]; +298 -> n298_0 [label="0:forward",arrowhead="none"]; +n298_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n298_0 -> 302 [label="[1,1]"]; +299 [label="299"]; +299 -> n299_0 [label="0:forward",arrowhead="none"]; +n299_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n299_0 -> 303 [label="[1,1]"]; +300 [label="300"]; +300 -> n300_0 [label="0:forward",arrowhead="none"]; +n300_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n300_0 -> 304 [label="[1,1]"]; +301 [label="301"]; +301 -> n301_0 [label="0:forward",arrowhead="none"]; +n301_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n301_0 -> 305 [label="[1,1]"]; +302 [label="302"]; +302 -> n302_0 [label="0:arrive",arrowhead="none"]; +n302_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n302_0 -> 302 [label="[0.09999999999999998,0.2999999999999999]"]; +n302_0 -> 350 [label="[0.7000000000000001,0.9]"]; +303 [label="303"]; +303 -> n303_0 [label="0:arrive",arrowhead="none"]; +n303_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n303_0 -> 303 [label="[0.09999999999999998,0.2999999999999999]"]; +n303_0 -> 306 [label="[0.7000000000000001,0.9]"]; +304 [label="304"]; +304 -> n304_0 [label="0:arrive",arrowhead="none"]; +n304_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n304_0 -> 268 [label="[0.7000000000000001,0.9]"]; +n304_0 -> 304 [label="[0.09999999999999998,0.2999999999999999]"]; +305 [label="305"]; +305 -> n305_0 [label="0:arrive",arrowhead="none"]; +n305_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n305_0 -> 212 [label="[0.7000000000000001,0.9]"]; +n305_0 -> 305 [label="[0.09999999999999998,0.2999999999999999]"]; +306 [label="306"]; +306 -> n306_0 [label="0:choose_e",arrowhead="none"]; +n306_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n306_0 -> 306 [label="[0.09999999999999998,0.2999999999999999]"]; +n306_0 -> 307 [label="[0.7000000000000001,0.9]"]; +306 -> n306_1 [label="1:choose_n",arrowhead="none"]; +n306_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n306_1 -> 306 [label="[0.09999999999999998,0.2999999999999999]"]; +n306_1 -> 308 [label="[0.7000000000000001,0.9]"]; +306 -> n306_2 [label="2:choose_w",arrowhead="none"]; +n306_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n306_2 -> 306 [label="[0.09999999999999998,0.2999999999999999]"]; +n306_2 -> 309 [label="[0.7000000000000001,0.9]"]; +307 [label="307"]; +307 -> n307_0 [label="0:forward",arrowhead="none"]; +n307_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n307_0 -> 310 [label="[1,1]"]; +308 [label="308"]; +308 -> n308_0 [label="0:forward",arrowhead="none"]; +n308_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n308_0 -> 311 [label="[1,1]"]; +309 [label="309"]; +309 -> n309_0 [label="0:forward",arrowhead="none"]; +n309_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n309_0 -> 312 [label="[1,1]"]; +310 [label="310"]; +310 -> n310_0 [label="0:forward",arrowhead="none"]; +n310_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n310_0 -> 313 [label="[1,1]"]; +311 [label="311"]; +311 -> n311_0 [label="0:forward",arrowhead="none"]; +n311_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n311_0 -> 314 [label="[1,1]"]; +312 [label="312"]; +312 -> n312_0 [label="0:forward",arrowhead="none"]; +n312_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n312_0 -> 315 [label="[1,1]"]; +313 [label="313"]; +313 -> n313_0 [label="0:forward",arrowhead="none"]; +n313_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n313_0 -> 316 [label="[1,1]"]; +314 [label="314"]; +314 -> n314_0 [label="0:forward",arrowhead="none"]; +n314_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n314_0 -> 317 [label="[1,1]"]; +315 [label="315"]; +315 -> n315_0 [label="0:forward",arrowhead="none"]; +n315_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n315_0 -> 318 [label="[1,1]"]; +316 [label="316"]; +316 -> n316_0 [label="0:arrive",arrowhead="none"]; +n316_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n316_0 -> 316 [label="[0.09999999999999998,0.2999999999999999]"]; +n316_0 -> 364 [label="[0.7000000000000001,0.9]"]; +317 [label="317"]; +317 -> n317_0 [label="0:arrive",arrowhead="none"]; +n317_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n317_0 -> 288 [label="[0.7000000000000001,0.9]"]; +n317_0 -> 317 [label="[0.09999999999999998,0.2999999999999999]"]; +318 [label="318"]; +318 -> n318_0 [label="0:arrive",arrowhead="none"]; +n318_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n318_0 -> 231 [label="[0.7000000000000001,0.9]"]; +n318_0 -> 318 [label="[0.09999999999999998,0.2999999999999999]"]; +319 [label="319"]; +319 -> n319_0 [label="0:trap",arrowhead="none"]; +n319_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n319_0 -> 319 [label="[1,1]"]; +320 [label="320"]; +320 -> n320_0 [label="0:trap",arrowhead="none"]; +n320_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n320_0 -> 320 [label="[1,1]"]; +321 [label="321"]; +321 -> n321_0 [label="0:choose_s",arrowhead="none"]; +n321_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n321_0 -> 321 [label="[0.09999999999999998,0.2999999999999999]"]; +n321_0 -> 323 [label="[0.7000000000000001,0.9]"]; +321 -> n321_1 [label="1:choose_n",arrowhead="none"]; +n321_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n321_1 -> 321 [label="[0.09999999999999998,0.2999999999999999]"]; +n321_1 -> 324 [label="[0.7000000000000001,0.9]"]; +321 -> n321_2 [label="2:choose_w",arrowhead="none"]; +n321_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n321_2 -> 321 [label="[0.09999999999999998,0.2999999999999999]"]; +n321_2 -> 325 [label="[0.7000000000000001,0.9]"]; +322 [label="322"]; +322 -> n322_0 [label="0:choose_s",arrowhead="none"]; +n322_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n322_0 -> 322 [label="[0.09999999999999998,0.2999999999999999]"]; +n322_0 -> 323 [label="[0.7000000000000001,0.9]"]; +322 -> n322_1 [label="1:choose_n",arrowhead="none"]; +n322_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n322_1 -> 322 [label="[0.09999999999999998,0.2999999999999999]"]; +n322_1 -> 324 [label="[0.7000000000000001,0.9]"]; +322 -> n322_2 [label="2:choose_w",arrowhead="none"]; +n322_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n322_2 -> 322 [label="[0.09999999999999998,0.2999999999999999]"]; +n322_2 -> 325 [label="[0.7000000000000001,0.9]"]; +323 [label="323"]; +323 -> n323_0 [label="0:forward",arrowhead="none"]; +n323_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n323_0 -> 326 [label="[1,1]"]; +324 [label="324"]; +324 -> n324_0 [label="0:forward",arrowhead="none"]; +n324_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n324_0 -> 327 [label="[1,1]"]; +325 [label="325"]; +325 -> n325_0 [label="0:forward",arrowhead="none"]; +n325_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n325_0 -> 328 [label="[1,1]"]; +326 [label="326"]; +326 -> n326_0 [label="0:forward",arrowhead="none"]; +n326_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n326_0 -> 329 [label="[1,1]"]; +327 [label="327"]; +327 -> n327_0 [label="0:forward",arrowhead="none"]; +n327_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n327_0 -> 330 [label="[1,1]"]; +328 [label="328"]; +328 -> n328_0 [label="0:forward",arrowhead="none"]; +n328_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n328_0 -> 331 [label="[1,1]"]; +329 [label="329"]; +329 -> n329_0 [label="0:forward",arrowhead="none"]; +n329_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n329_0 -> 332 [label="[1,1]"]; +330 [label="330"]; +330 -> n330_0 [label="0:forward",arrowhead="none"]; +n330_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n330_0 -> 333 [label="[1,1]"]; +331 [label="331"]; +331 -> n331_0 [label="0:forward",arrowhead="none"]; +n331_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n331_0 -> 334 [label="[1,1]"]; +332 [label="332"]; +332 -> n332_0 [label="0:arrive",arrowhead="none"]; +n332_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n332_0 -> 332 [label="[0.09999999999999998,0.2999999999999999]"]; +n332_0 -> 336 [label="[0.7000000000000001,0.9]"]; +333 [label="333"]; +333 -> n333_0 [label="0:arrive",arrowhead="none"]; +n333_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n333_0 -> 320 [label="[0.7000000000000001,0.9]"]; +n333_0 -> 333 [label="[0.09999999999999998,0.2999999999999999]"]; +334 [label="334"]; +334 -> n334_0 [label="0:arrive",arrowhead="none"]; +n334_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n334_0 -> 249 [label="[0.7000000000000001,0.9]"]; +n334_0 -> 334 [label="[0.09999999999999998,0.2999999999999999]"]; +335 [label="335"]; +335 -> n335_0 [label="0:choose_s",arrowhead="none"]; +n335_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n335_0 -> 335 [label="[0.09999999999999998,0.2999999999999999]"]; +n335_0 -> 338 [label="[0.7000000000000001,0.9]"]; +335 -> n335_1 [label="1:choose_n",arrowhead="none"]; +n335_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n335_1 -> 335 [label="[0.09999999999999998,0.2999999999999999]"]; +n335_1 -> 339 [label="[0.7000000000000001,0.9]"]; +335 -> n335_2 [label="2:choose_w",arrowhead="none"]; +n335_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n335_2 -> 335 [label="[0.09999999999999998,0.2999999999999999]"]; +n335_2 -> 340 [label="[0.7000000000000001,0.9]"]; +336 [label="336"]; +336 -> n336_0 [label="0:choose_s",arrowhead="none"]; +n336_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n336_0 -> 336 [label="[0.09999999999999998,0.2999999999999999]"]; +n336_0 -> 338 [label="[0.7000000000000001,0.9]"]; +336 -> n336_1 [label="1:choose_n",arrowhead="none"]; +n336_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n336_1 -> 336 [label="[0.09999999999999998,0.2999999999999999]"]; +n336_1 -> 339 [label="[0.7000000000000001,0.9]"]; +336 -> n336_2 [label="2:choose_w",arrowhead="none"]; +n336_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n336_2 -> 336 [label="[0.09999999999999998,0.2999999999999999]"]; +n336_2 -> 340 [label="[0.7000000000000001,0.9]"]; +337 [label="337"]; +337 -> n337_0 [label="0:choose_s",arrowhead="none"]; +n337_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n337_0 -> 337 [label="[0.09999999999999998,0.2999999999999999]"]; +n337_0 -> 338 [label="[0.7000000000000001,0.9]"]; +337 -> n337_1 [label="1:choose_n",arrowhead="none"]; +n337_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n337_1 -> 337 [label="[0.09999999999999998,0.2999999999999999]"]; +n337_1 -> 339 [label="[0.7000000000000001,0.9]"]; +337 -> n337_2 [label="2:choose_w",arrowhead="none"]; +n337_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n337_2 -> 337 [label="[0.09999999999999998,0.2999999999999999]"]; +n337_2 -> 340 [label="[0.7000000000000001,0.9]"]; +338 [label="338"]; +338 -> n338_0 [label="0:forward",arrowhead="none"]; +n338_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n338_0 -> 341 [label="[1,1]"]; +339 [label="339"]; +339 -> n339_0 [label="0:forward",arrowhead="none"]; +n339_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n339_0 -> 342 [label="[1,1]"]; +340 [label="340"]; +340 -> n340_0 [label="0:forward",arrowhead="none"]; +n340_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n340_0 -> 343 [label="[1,1]"]; +341 [label="341"]; +341 -> n341_0 [label="0:forward",arrowhead="none"]; +n341_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n341_0 -> 344 [label="[1,1]"]; +342 [label="342"]; +342 -> n342_0 [label="0:forward",arrowhead="none"]; +n342_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n342_0 -> 345 [label="[1,1]"]; +343 [label="343"]; +343 -> n343_0 [label="0:forward",arrowhead="none"]; +n343_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n343_0 -> 346 [label="[1,1]"]; +344 [label="344"]; +344 -> n344_0 [label="0:forward",arrowhead="none"]; +n344_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n344_0 -> 347 [label="[1,1]"]; +345 [label="345"]; +345 -> n345_0 [label="0:forward",arrowhead="none"]; +n345_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n345_0 -> 348 [label="[1,1]"]; +346 [label="346"]; +346 -> n346_0 [label="0:forward",arrowhead="none"]; +n346_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n346_0 -> 349 [label="[1,1]"]; +347 [label="347"]; +347 -> n347_0 [label="0:arrive",arrowhead="none"]; +n347_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n347_0 -> 347 [label="[0.09999999999999998,0.2999999999999999]"]; +n347_0 -> 351 [label="[0.7000000000000001,0.9]"]; +348 [label="348"]; +348 -> n348_0 [label="0:arrive",arrowhead="none"]; +n348_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n348_0 -> 322 [label="[0.7000000000000001,0.9]"]; +n348_0 -> 348 [label="[0.09999999999999998,0.2999999999999999]"]; +349 [label="349"]; +349 -> n349_0 [label="0:arrive",arrowhead="none"]; +n349_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n349_0 -> 269 [label="[0.7000000000000001,0.9]"]; +n349_0 -> 349 [label="[0.09999999999999998,0.2999999999999999]"]; +350 [label="350"]; +350 -> n350_0 [label="0:choose_s",arrowhead="none"]; +n350_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n350_0 -> 350 [label="[0.09999999999999998,0.2999999999999999]"]; +n350_0 -> 352 [label="[0.7000000000000001,0.9]"]; +350 -> n350_1 [label="1:choose_n",arrowhead="none"]; +n350_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n350_1 -> 350 [label="[0.09999999999999998,0.2999999999999999]"]; +n350_1 -> 353 [label="[0.7000000000000001,0.9]"]; +350 -> n350_2 [label="2:choose_w",arrowhead="none"]; +n350_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n350_2 -> 350 [label="[0.09999999999999998,0.2999999999999999]"]; +n350_2 -> 354 [label="[0.7000000000000001,0.9]"]; +351 [label="351"]; +351 -> n351_0 [label="0:choose_s",arrowhead="none"]; +n351_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n351_0 -> 351 [label="[0.09999999999999998,0.2999999999999999]"]; +n351_0 -> 352 [label="[0.7000000000000001,0.9]"]; +351 -> n351_1 [label="1:choose_n",arrowhead="none"]; +n351_1 [ shape=point,width=0.1,height=0.1,label="" ]; +n351_1 -> 351 [label="[0.09999999999999998,0.2999999999999999]"]; +n351_1 -> 353 [label="[0.7000000000000001,0.9]"]; +351 -> n351_2 [label="2:choose_w",arrowhead="none"]; +n351_2 [ shape=point,width=0.1,height=0.1,label="" ]; +n351_2 -> 351 [label="[0.09999999999999998,0.2999999999999999]"]; +n351_2 -> 354 [label="[0.7000000000000001,0.9]"]; +352 [label="352"]; +352 -> n352_0 [label="0:forward",arrowhead="none"]; +n352_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n352_0 -> 355 [label="[1,1]"]; +353 [label="353"]; +353 -> n353_0 [label="0:forward",arrowhead="none"]; +n353_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n353_0 -> 356 [label="[1,1]"]; +354 [label="354"]; +354 -> n354_0 [label="0:forward",arrowhead="none"]; +n354_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n354_0 -> 357 [label="[1,1]"]; +355 [label="355"]; +355 -> n355_0 [label="0:forward",arrowhead="none"]; +n355_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n355_0 -> 358 [label="[1,1]"]; +356 [label="356"]; +356 -> n356_0 [label="0:forward",arrowhead="none"]; +n356_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n356_0 -> 359 [label="[1,1]"]; +357 [label="357"]; +357 -> n357_0 [label="0:forward",arrowhead="none"]; +n357_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n357_0 -> 360 [label="[1,1]"]; +358 [label="358"]; +358 -> n358_0 [label="0:forward",arrowhead="none"]; +n358_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n358_0 -> 361 [label="[1,1]"]; +359 [label="359"]; +359 -> n359_0 [label="0:forward",arrowhead="none"]; +n359_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n359_0 -> 362 [label="[1,1]"]; +360 [label="360"]; +360 -> n360_0 [label="0:forward",arrowhead="none"]; +n360_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n360_0 -> 363 [label="[1,1]"]; +361 [label="361"]; +361 -> n361_0 [label="0:arrive",arrowhead="none"]; +n361_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n361_0 -> 361 [label="[0.09999999999999998,0.2999999999999999]"]; +n361_0 -> 365 [label="[0.7000000000000001,0.9]"]; +362 [label="362"]; +362 -> n362_0 [label="0:arrive",arrowhead="none"]; +n362_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n362_0 -> 337 [label="[0.7000000000000001,0.9]"]; +n362_0 -> 362 [label="[0.09999999999999998,0.2999999999999999]"]; +363 [label="363"]; +363 -> n363_0 [label="0:arrive",arrowhead="none"]; +n363_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n363_0 -> 289 [label="[0.7000000000000001,0.9]"]; +n363_0 -> 363 [label="[0.09999999999999998,0.2999999999999999]"]; +364 [label="364"]; +364 -> n364_0 [label="0:goal",arrowhead="none"]; +n364_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n364_0 -> 364 [label="[1,1]"]; +365 [label="365"]; +365 -> n365_0 [label="0:goal",arrowhead="none"]; +n365_0 [ shape=point,width=0.1,height=0.1,label="" ]; +n365_0 -> 365 [label="[1,1]"]; +} diff --git a/ov-10x10.prism b/ov-10x10.prism new file mode 100644 index 0000000000..109983c6fa --- /dev/null +++ b/ov-10x10.prism @@ -0,0 +1,76 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 10; // grid size: 0..N-1 in both x and y +const double p = 0.8; // probability of moving in intended direction + // slip to each of the other 3 directions with (1-p)/3 +const double e = 0.05; + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +// 10×10 layout; S = start, F = frozen, H = hole, G = goal +// (holes placed at various locations to create challenge) +formula hole = (x=1 & y=0) + | (x=2 & y=3) + | (x=3 & y=6) + | (x=4 & y=2) + | (x=5 & y=5) + | (x=6 & y=1) + | (x=7 & y=7) + | (x=2 & y=8) + | (x=8 & y=4) + | (x=4 & y=9); + +formula goal = (x=9 & y=9); +formula terminal = hole | goal; + +//─── MODULE ─────────────────────────────────────────────────────────────────── +module frozenlake + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + //──– North ─────────────────────────────────────────────────────────────── + [north] !terminal & !goal -> + [p-e, p+e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)); + + //──– South ─────────────────────────────────────────────────────────────── + [south] !terminal & !goal -> + [p-e, p+e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)); + + //──– East ──────────────────────────────────────────────────────────────── + [east] !terminal & !goal -> + [p-e, p+e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)); + + //──– West ──────────────────────────────────────────────────────────────── + [west] !terminal & !goal -> + [p-e, p+e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)); + + //──– At terminal (hole or goal), stay where you are ─────────────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y); + [done] goal -> true; +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0); +label "Crash" = hole; +label "goal" = goal; +label "safe" = !hole & !goal; + +//─── REWARDS ───────────────────────────────────────────────────────────────── +rewards + [north] !terminal & !goal : 1; + [south] !terminal & !goal : 1; + [east] !terminal & !goal : 1; + [west] !terminal & !goal : 1; +endrewards diff --git a/ov-6x6.prism b/ov-6x6.prism new file mode 100644 index 0000000000..7de8c029f4 --- /dev/null +++ b/ov-6x6.prism @@ -0,0 +1,86 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 6; // grid size: 0..N-1 in both x and y +const int K = 100; // # of intermediate sub-steps per move +const double p = 0.8; // intended-direction probability +const double e = 0.03; // slip‐interval half-width + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +formula hole = (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1) + | (x=4 & y=4); +formula goal = (x=5 & y=5); +formula terminal = hole | goal; + +//─── MODULE ──────────────────────────────────────────────────────────────────── +module frozenlake + + // “true” state + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + // internal bookkeeping for a “multi-step” move + tx : [0..N-1] init 0; // target column + ty : [0..N-1] init 0; // target row + step: [0..K] init 0; // current sub-step (0 = ready to pick a direction) + + //── Initial direction choice (step=0) ──────────────────────────────────────── + [north] step=0 & !terminal -> + // intended north + [p-e, p+e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + // slip west + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + // slip east + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + // slip south + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1); + + [south] step=0 & !terminal -> + [p-e, p+e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1); + + [east] step=0 & !terminal -> + [p-e, p+e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1); + + [west] step=0 & !terminal -> + [p-e, p+e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1); + + //── Substep “in-flight” transitions ───────────────────────────────────────── + // for 1 ≤ step < K, only one action: advance sub-step + [move] step>0 & step 1.0 : (step'=step+1); + + // at step=K commit the move into (x,y) and reset + [move] step=K -> 1.0 : (x'=tx) & (y'=ty) & (step'=0); + + //── Terminal self-loops ───────────────────────────────────────────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y) & (step'=0); + [done] goal & step = 0 -> true; + +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0) & step=0; +label "Crash" = hole; +label "goal" = goal & step=0; +label "safe" = !hole & !goal; + +//─── REWARDS ───────────────────────────────────────────────────────────────── +rewards + // count 1 reward per *grid-to-grid* move (i.e. when you pick a direction at step=0) + [north] step=0 & !terminal : 1; + [south] step=0 & !terminal : 1; + [east] step=0 & !terminal : 1; + [west] step=0 & !terminal : 1; +endrewards diff --git a/ov-v2-10x10.prism b/ov-v2-10x10.prism new file mode 100644 index 0000000000..3b8ee7586b --- /dev/null +++ b/ov-v2-10x10.prism @@ -0,0 +1,76 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 10; // grid size: 0..N-1 in both x and y +const double p = 0.8; // probability of moving in intended direction + // slip to each of the other 3 directions with (1-p)/3 +const double e = 0.05; // uncertainty radius + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +// original holes plus four new traps +formula hole = + (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1) + | (x=4 & y=4) + | (x=2 & y=2) // new + | (x=3 & y=7) // new + | (x=6 & y=3) // new + | (x=8 & y=6); // new + +formula goal = (x=9 & y=9); +formula terminal = hole | goal; + +//─── MODULE ─────────────────────────────────────────────────────────────────── +module frozenlake + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + //─── North ─────────────────────────────────────────────────────────────── + [north] !terminal & !goal-> + [p-e,p+e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)); + + //─── South ─────────────────────────────────────────────────────────────── + [south] !terminal & !goal -> + [p-e,p+e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)); + + //─── East ──────────────────────────────────────────────────────────────── + [east] !terminal & !goal-> + [p-e,p+e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)); + + //─── West ──────────────────────────────────────────────────────────────── + [west] !terminal & !goal -> + [p-e,p+e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)); + + //─── At terminal (hole or goal), stay in place ──────────────────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y); + [done] goal -> true; +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0); +label "Crash" = hole; +label "goal" = goal; +label "safe" = !hole & !goal; + +//─── REWARDS ────────────────────────────────────────────────────────────────── +rewards + [north] !terminal : 1; + [south] !terminal : 1; + [east] !terminal : 1; + [west] !terminal : 1; +endrewards diff --git a/ov-v2-6x6.prism b/ov-v2-6x6.prism new file mode 100644 index 0000000000..dd2edc75f3 --- /dev/null +++ b/ov-v2-6x6.prism @@ -0,0 +1,74 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 6; // grid size: 0..N-1 in both x and y +const double p = 0.8; // probability of moving in intended direction + // slip to each of the other 3 directions with (1-p)/3 +const double e = 0.05; + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +// standard 4×4 layout: +// S F F F +// H F H F +// F F F H +// H F F G +formula hole = (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1) + | (x=4 & y=4); +formula goal = (x=5 & y=5); +formula terminal = hole | goal; + +//─── MODULE ──────────────────────────────────────────────────────────────────── +module frozenlake + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + //──– North ─────────────────────────────────────────────────────────── + [north] !terminal & !goal -> + [p-e,p+e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)); + + //──– South ─────────────────────────────────────────────────────────── + [south] !terminal & !goal -> + [p-e,p+e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)); + + //──– East ──────────────────────────────────────────────────────────── + [east] !terminal & !goal-> + [p-e,p+e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)); + + //──– West ──────────────────────────────────────────────────────────── + [west] !terminal & !goal-> + [p-e,p+e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)); + + //──– At terminal (hole or goal), stay where you are ───────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y); + + [done] goal -> true; +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0); +label "Crash" = hole; +label "goal" = goal; +label "safe" = !hole & !goal; + +rewards + [north] !terminal & !goal : 1; + [west] !terminal & !goal : 1; + [east] !terminal & !goal : 1; + [south] !terminal & !goal : 1; +endrewards diff --git a/ov-v2-7x7.prism b/ov-v2-7x7.prism new file mode 100644 index 0000000000..b8aeaf89a2 --- /dev/null +++ b/ov-v2-7x7.prism @@ -0,0 +1,76 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 7; // grid size: 0..N-1 in both x and y +const double p = 0.8; // probability of moving in intended direction + // slip to each of the other 3 directions with (1-p)/3 +const double e = 0.05; // uncertainty radius + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +// original holes plus four new traps, adjusted for 0..6 range +formula hole = + (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1) + | (x=4 & y=4) + | (x=2 & y=2) // new + | (x=3 & y=6) // new (top row) + | (x=6 & y=3) // new + | (x=5 & y=6); // new + +formula goal = (x=6 & y=6); +formula terminal = hole | goal; + +//─── MODULE ─────────────────────────────────────────────────────────────────── +module frozenlake + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + //─── North ─────────────────────────────────────────────────────────────── + [north] !terminal & !goal -> + [p-e,p+e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)); + + //─── South ─────────────────────────────────────────────────────────────── + [south] !terminal & !goal -> + [p-e,p+e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)); + + //─── East ──────────────────────────────────────────────────────────────── + [east] !terminal & !goal -> + [p-e,p+e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)); + + //─── West ──────────────────────────────────────────────────────────────── + [west] !terminal & !goal -> + [p-e,p+e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)); + + //─── At terminal (hole or goal), stay in place ──────────────────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y); + [done] goal -> true; +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0); +label "Crash" = hole; +label "goal" = goal; +label "safe" = !hole & !goal; + +//─── REWARDS ────────────────────────────────────────────────────────────────── +rewards + [north] !terminal & !goal : 1; + [south] !terminal & !goal : 1; + [east] !terminal & !goal : 1; + [west] !terminal & !goal : 1; +endrewards diff --git a/ov-v2-8x8.prism b/ov-v2-8x8.prism new file mode 100644 index 0000000000..9d184f19b1 --- /dev/null +++ b/ov-v2-8x8.prism @@ -0,0 +1,76 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 8; // grid size: 0..N-1 in both x and y +const double p = 0.8; // probability of moving in intended direction + // slip to each of the other 3 directions with (1-p)/3 +const double e = 0.05; // uncertainty radius + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +// original holes plus four new traps, adjusted for 0..7 range +formula hole = + (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1) + | (x=4 & y=4) + | (x=2 & y=2) // new + | (x=3 & y=7) // new (top row) + | (x=6 & y=3) // new + | (x=7 & y=6); // new (shifted from (8,6)) + +formula goal = (x=7 & y=7); +formula terminal = hole | goal; + +//─── MODULE ─────────────────────────────────────────────────────────────────── +module frozenlake + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + //─── North ─────────────────────────────────────────────────────────────── + [north] !terminal & !goal -> + [p-e,p+e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)); + + //─── South ─────────────────────────────────────────────────────────────── + [south] !terminal & !goal -> + [p-e,p+e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)); + + //─── East ──────────────────────────────────────────────────────────────── + [east] !terminal & !goal -> + [p-e,p+e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)); + + //─── West ──────────────────────────────────────────────────────────────── + [west] !terminal & !goal -> + [p-e,p+e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)); + + //─── At terminal (hole or goal), stay in place ──────────────────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y); + [done] goal -> true; +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0); +label "Crash" = hole; +label "goal" = goal; +label "safe" = !hole & !goal; + +//─── REWARDS ────────────────────────────────────────────────────────────────── +rewards + [north] !terminal : 1; + [south] !terminal : 1; + [east] !terminal : 1; + [west] !terminal : 1; +endrewards diff --git a/ov.prism b/ov.prism new file mode 100644 index 0000000000..c192af7ced --- /dev/null +++ b/ov.prism @@ -0,0 +1,74 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 4; // grid size: 0..N-1 in both x and y +const double p = 0.8; // probability of moving in intended direction + // slip to each of the other 3 directions with (1-p)/3 +const double e = 0.05; + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +// standard 4×4 layout: +// S F F F +// H F H F +// F F F H +// H F F G +formula hole = (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1) + | (x=4 & y=4); +formula goal = (x=5 & y=5); +formula terminal = hole | goal; + +//─── MODULE ──────────────────────────────────────────────────────────────────── +module frozenlake + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + //──– North ─────────────────────────────────────────────────────────── + [north] !terminal & !goal -> + [p-e,p+e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)); + + //──– South ─────────────────────────────────────────────────────────── + [south] !terminal & !goal -> + [p-e,p+e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)); + + //──– East ──────────────────────────────────────────────────────────── + [east] !terminal & !goal-> + [p-e,p+e] : (x'=min(x+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=max(x-1,0)); + + //──– West ──────────────────────────────────────────────────────────── + [west] !terminal & !goal-> + [p-e,p+e] : (x'=max(x-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=max(y-1,0)) + + [(1-p)/3 - e, (1-p)/3 + e] : (y'=min(y+1,N-1)) + + [(1-p)/3 - e, (1-p)/3 + e] : (x'=min(x+1,N-1)); + + //──– At terminal (hole or goal), stay where you are ───────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y); + + [done] goal -> true; +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0); +label "Crash" = hole; +label "goal" = goal; +label "safe" = !hole & !goal; + +rewards + [north] !terminal & !goal : 1; + [west] !terminal & !goal : 1; + [east] !terminal & !goal : 1; + [south] !terminal & !goal : 1; +endrewards diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index ad56ce63b7..2f52ebdd29 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -627,8 +627,8 @@ public ModelCheckerResult computeReachRewards(IMDP imdp, MDPRewards imdp, MDPRewards mdpRewards, double bound) throws PrismException { boolean value =true; - boolean min = true; - boolean robust = true; + boolean min =true; + boolean robust=true; if (value){ if (min){ return computeMultiStrategyValueMin(imdp, mdpRewards, bound, robust); @@ -667,7 +667,7 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew System.out.println(n); int sInit = imdp.getFirstInitialState(); - double BIG = 1000.0; + double BIG = 100.0; System.out.println(imdp.getLabelStates("goal")); BitSet targetS = imdp.getLabelStates("goal"); System.out.println("Hi: " + imdp.getInitialStates()); @@ -686,9 +686,6 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew target[counter] = s; counter += 1; } - for (int s = 0; s < n; s++){ - System.out.println("State: " + s + ", nch: "+ imdp.getNumChoices(s)); - } if (robust==true){ mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); try { @@ -847,8 +844,10 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew // now optimize m.setObjective(pen, GRB.MINIMIZE); m.setCallback(new trigger(m, 3600)); - + m.write("gurobi.lp"); m.optimize(); + + if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { System.out.println("Model infeasible—computing IIS..."); m.computeIIS(); @@ -864,10 +863,20 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew soln = new double[n]; for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + if (s==0){ + System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + } + + soln[s] = v.get(s).get(GRB.DoubleAttr.X); } + int isMIP = m.get(GRB.IntAttr.IsMIP); // 1 => has integer vars + int isQP = m.get(GRB.IntAttr.IsQP); // 1 => quadratic objective + int isQCP = m.get(GRB.IntAttr.IsQCP); // 1 => quadratic constraints + int numQC = m.get(GRB.IntAttr.NumQConstrs); // # quadratic constraints + System.out.printf("IsMIP=%d IsQP=%d IsQCP=%d NumQConstrs=%d%n",isMIP, isQP, isQCP, numQC); + mainLog.println("Multi Strategy to Obtain at most under worst assumption of adversary " + bound); @@ -879,10 +888,8 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew for (int s = 0; s < n; s++) { mainLog.print(s + ":"); int numChoices = imdp.getNumChoices(s); - System.out.println(numChoices); for (int i = 0; i < numChoices; i++) { String sc = s +"-"+i; - System.out.println(eta.get(sc).get(GRB.DoubleAttr.X)); if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { mainLog.print(" " + imdp.getAction(s, i)); @@ -890,7 +897,27 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } mainLog.println(); } - + int permC = 0; + for (int s = 0; s < n; s++) { + //System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + int numChoices = imdp.getNumChoices(s); + + if (numChoices == 1){ + continue; + } else { + int tmC = 0; + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + tmC += 1; + } + } + if (tmC > 1){ + permC += 1; + } + } + } + mainLog.println("Number of Permissive States: " + permC); // Clean up m.dispose(); env.dispose(); @@ -899,7 +926,6 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } } else { - // Multi-strategy under best assumption mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); @@ -908,7 +934,7 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew GRBEnv env = new GRBEnv("gurobi.log"); env.set(GRB.IntParam.OutputFlag, 1); GRBModel m = new GRBModel(env); - //m.set(GRB.IntParam.NonConvex, 2); + m.set(GRB.IntParam.NonConvex, 2); // --- 1) Value‐function vars v[s] --- Map v = new HashMap<>(); @@ -935,15 +961,8 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew Map.Entry> e = it.next(); int t = e.getKey(); Interval transition_val = e.getValue(); - String key = sc+"->"+t; - GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); - delta.get(sc).put(t, up); - GRBLinExpr allowedUp = new GRBLinExpr(); - GRBLinExpr allowedLow = new GRBLinExpr(); - allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); - allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); - m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); - m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); + transition_val.getLower(); + transition_val.getUpper(); } GRBLinExpr norm = new GRBLinExpr(); for (int t : delta.get(sc).keySet()) @@ -1105,6 +1124,28 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } mainLog.println(); } + + int permC = 0; + for (int s = 0; s < n; s++) { + //System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + int numChoices = imdp.getNumChoices(s); + + if (numChoices == 1){ + continue; + } else { + int tmC = 0; + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + tmC += 1; + } + } + if (tmC > 1){ + permC += 1; + } + } + } + System.out.println("Number of Permissive States: " + permC); m.dispose(); env.dispose(); } catch (GRBException e) { @@ -1623,14 +1664,14 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa System.out.println("sInit = " + sInit); System.out.println("Crash states = " + no); System.out.println("Goal states = " + targetS); - for (int bad : new int[]{4,6,14,15,16,32}) { + /* for (int bad : new int[]{4,6,14,15,16,32}) { System.out.printf("state %d has %d choices%n", bad, imdp.getNumChoices(bad)); } for (int s = 0; s < n; s++){ System.out.println("State: " + s + ", nch: "+ imdp.getNumChoices(s)); - } + } */ //compute predecessor /* Map> predecessor = new HashMap<>(); @@ -1718,7 +1759,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa for (int c = 0; c < numChoices; c++){ String sc = s + "-" + c; eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); - lam.put(sc, m.addVar(-1.0,1.0,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + lam.put(sc, m.addVar(0.0,1.0,0,GRB.CONTINUOUS,"lam"+"-"+sc)); GRBLinExpr lamAU = new GRBLinExpr(); lamAU.addTerm(BIG, eta.get(sc)); GRBLinExpr lamAD = new GRBLinExpr(); @@ -1915,10 +1956,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); soln = new double[n]; - for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); - soln[s] = v.get(s).get(GRB.DoubleAttr.X); - } + mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); @@ -1939,7 +1977,27 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa } mainLog.println(); } - + int permC = 0; + for (int s = 0; s < n; s++) { + //System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + int numChoices = imdp.getNumChoices(s); + + if (numChoices == 1){ + continue; + } else { + int tmC = 0; + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + tmC += 1; + } + } + if (tmC > 1){ + permC += 1; + } + } + } + mainLog.println("Number of Permissive States: " + permC); // Clean up m.dispose(); env.dispose(); @@ -1948,7 +2006,6 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa } } else { - // Multi-strategy under best assumption mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); @@ -2135,6 +2192,27 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa } mainLog.println(); } + int permC = 0; + for (int s = 0; s < n; s++) { + //System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); + int numChoices = imdp.getNumChoices(s); + + if (numChoices == 1){ + continue; + } else { + int tmC = 0; + for (int i = 0; i < numChoices; i++) { + String sc = s +"-"+i; + if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { + tmC += 1; + } + } + if (tmC > 1){ + permC += 1; + } + } + } + mainLog.println("Number of Permissive States: " + permC); m.dispose(); env.dispose(); } catch (GRBException e) { diff --git a/robot-imdp.prism b/robot-imdp.prism index 3322e4349c..fef774afbd 100644 --- a/robot-imdp.prism +++ b/robot-imdp.prism @@ -1,286 +1,41 @@ mdp +const int N=10; // N*N grid map +const double p=0.1; // with probability p, a move to a neighboring state state occurs due to seeing and control noise +const double e = 0.02; -// operator parameters -const double p=0.5; // probability of increasing workload due to other uncertain tasks -const double accu_load1; // accuracy at the low workload level (real numbers between 0 and 1) -const double accu_load2; // accuracy at the high workload level (real numbers between 0 and 1) -const double fd; // accuracy discount due to fatigue (real numbers between 0 and 1) -const int COUNTER; // fatigue threshold (integers, e.g, 10) -const double risky2; // at w2: probability of choosing a risky route -const double risky6; // at w6: probability of choosing a risky route +formula wall = (r=6 & c=2) | (r=8 & c=1) | (r=4 & c=1) | (r=5 & c=2) | (r=7 & c=1) | (r=8 & c=3) | (r=9 & c=2) | (r=9 & c=1) | (r=4 & c=4) | (r=7 & c=6) | (r=9 & c=5) | (r=3 & c=5) | (r=6 & c=4) | (r=7 & c=2) | (r=5 & c=9) | (r=8 & c=9); -global stop : bool init false; // done visiting all waypoints -formula roz = (r=8) | (w=3&a=1) | (w=3&a=2) | (w=5&a=2); // restricted operating zones +module robot + //define robot position + r:[1..N] init 1; //grid row + c:[1..N] init 1; //grid column + // go to the terminal state when hitting an obstacle + // [obstacle] wall -> (r'=10) & (c'=1); -// OPERATOR MODEL -module operator - - k:[0..100] init 0; // fatigue level measured by completetd tasks - t:[0..2] init 0; // workload level - s:[0..2] init 0; // status of image processing, 0: init, 1: good, 2: bad - c:[0..3] init 0; // choices at the check point + // transitions + [east] (c [p/3-e,p/3+e]:(r'=min(r+1, N))+ [p/3-e,p/3+e]: (c'=max(c-1, 1))+ [p/3-e,p/3+e]: (r'=max(r-1, 1)) + [1-p-e,1-p+e]: (c'=min(c+1, N)); + [south] (r [1-p-e,1-p+e]:(r'=min(r+1, N)) + [p/3-e,p/3+e]: (c'=min(c+1, N)) + [p/3-e,p/3+e]:(r'=max(r-1, 1))+ [p/3-e,p/3+e]: (c'=max(c-1, 1)); + [west] (c>1 | c=1) -> [p/3-e,p/3+e]:(r'=max(r-1, 1))+ [p/3-e,p/3+e]:(r'=min(r+1, N))+ [p/3-e,p/3+e]: (c'=min(c+1, N)) + [1-p-e,1-p+e]: (c'=max(c-1, 1)); + [north] (r=1 | r>1) -> [1-p-e,1-p+e]:(r'=max(r-1, 1)) + [p/3-e,p/3+e]: (c'=max(c-1, 1)) + [p/3-e,p/3+e]: (c'=min(c+1, N)) + [p/3-e,p/3+e]:(r'=min(r+1, N)); - // image processing, the workload may increase due to other unknown tasks - [image] !stop & t=0 & s=0 -> (1-p):(t'=1) & (s'=0) + p:(t'=2) & (s'=0); - // not fatigue, workload level 1 - [process] !stop & t=1 & s=0 & k<=COUNTER -> accu_load1:(s'=1)&(k'=k+1) + (1-accu_load1):(s'=2)&(k'=k+1); - // fatigue, workload level 1 - [process] !stop & t=1 & s=0 & k>COUNTER -> accu_load1*fd:(s'=1) + (1-accu_load1*fd):(s'=2); - // not fatigue, workload level 2 - [process] !stop & t=2 & s=0 & k<=COUNTER -> accu_load2:(s'=1)&(k'=k+1) + (1-accu_load2):(s'=2)&(k'=k+1); - // fatigue, workload level 2 - [process] !stop & t=2 & s=0 & k>COUNTER -> accu_load2*fd:(s'=1) + (1-accu_load2*fd):(s'=2); - - // image analysis is bad, UAV need to wait at the waypoint and take another image - [wait] !stop & s=2 -> (t'=0) & (s'=0); - - // if image analysis is good, UAV can continue flying - // at check points, operator may suggest route for the UAV - - // w2 -> r5 (c=0) |r6 (c=1) |r7 (c=2)|r9 (c=3) - [go] !stop & s=1 & w=2 -> risky2:(c'=2) & (t'=0) & (s'=0) + (1-risky2)/3:(c'=3) & (t'=0) & (s'=0) - +(1-risky2)/3:(c'=1) & (t'=0) & (s'=0) + (1-risky2)/3:(c'=0) & (t'=0) & (s'=0); - - // w5 -> r3 (c=0)| r4 (c=1)| w4 (c=2) - [go] !stop & s=1 & w=5 -> 1/3:(c'=2) & (t'=0) & (s'=0) + 1/3:(c'=1) & (t'=0) & (s'=0) - + 1/3:(c'=0) & (t'=0) & (s'=0); - - // w6 -> r2 (c=0)| r3 (c=1) |r8 (c=2) - [go] !stop & s=1 & w=6 -> risky6:(c'=2) & (t'=0) & (s'=0) + (1-risky6)/2:(c'=1) & (t'=0) & (s'=0) - + (1-risky6)/2:(c'=0) & (t'=0) & (s'=0); - - // at non-check-points, UAV has full autonomy to choose flying route - [go] !stop & s=1 & (w!=2 & w!=5 & w!=6) -> (t'=0) & (s'=0); - - // operator stops - [] !stop & w1 & w2 & w6 -> (stop'=true); - [operator_stop] stop -> true; + // terminal state self-loop to avoid deadlock + [done] r=10 & c=1 -> true; endmodule +label "goal" = r=10 & c=1; -// UAV MODEL -module UAV - // UAV positions: - // inside a waypoint: w!=0, a=0, r=0 - // fly through certain angle of a waypoint: w!=0, a!=0, r=0 - // fly through a road point: w=0, a=0, r!=0 - w:[0..6] init 1; // waypoint - a:[0..8] init 0; // angle points - r:[0..9] init 0; // road points - send: bool init true; - in: bool init true; - // flag that a waypoint has been visited - w1: bool init true; - w2: bool init false; - w3: bool init false; - w4: bool init false; - w5: bool init false; - w6: bool init false; - - // at any waypoint: - // send image to human operator for analysis - [image] w!=0 & a=0 & r=0 & send -> (send'=false); - // wait at the waypoint and send another image - [wait] !send -> (send'=true); - // fly into a waypoint and take an image - [camera] w=1 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w1'=true); - [camera] w=2 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w2'=true); - [camera] w=3 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w3'=true); - [camera] w=4 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w4'=true); - [camera] w=5 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w5'=true); - [camera] w=6 & a!=0 & r=0 & in -> (a'=0) & (send'=true) & (w6'=true); - // fly out of the waypoint via any angle point - [go] w!=0 & a=0 & r=0 -> 1/8:(a'=1) & (in'=false) - + 1/8:(a'=2) & (in'=false) - + 1/8:(a'=3) & (in'=false) - + 1/8:(a'=4) & (in'=false) - + 1/8:(a'=5) & (in'=false) - + 1/8:(a'=6) & (in'=false) - + 1/8:(a'=7) & (in'=false) - + 1/8:(a'=8) & (in'=false); - - - // UAV flying plans (based on the road map) - // check points: receiving commands from the operator - // w2 -> r5 |r6 |r7 |r9 - [fly] c=0 & w=2 & (a!=0) & r=0 & !in -> (r'=5); - [fly] c=1 & w=2 & (a!=0) & r=0 & !in -> (r'=6); - [fly] c=2 & w=2 & (a!=0) & r=0 & !in -> (r'=7); - [fly] c=3 & w=2 & (a!=0) & r=0 & !in -> (r'=9); - // w5 -> r3 | r4 | w4 (at any angle point) - [fly] c=0 & w=5 & (a!=0) & r=0 & !in -> (r'=3); - [fly] c=1 & w=5 & (a!=0) & r=0 & !in -> (r'=4); - [fly] c=2 & w=5 & (a!=0) & r=0 & !in -> 1/8:(w'=4) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=8) & (r'=0) & (in'=true); - // w6 -> r2 | r3 |r8 - [fly] c=0 & w=6 & (a!=0) & r=0 & !in -> (r'=2); - [fly] c=1 & w=6 & (a!=0) & r=0 & !in -> (r'=3); - [fly] c=2 & w=6 & (a!=0) & r=0 & !in -> (r'=8); - - // non check points: fly autonomy - // w1 -> r1 | r9 - [fly] w=1 & (a!=0) & r=0 & !in -> (r'=1); - [fly] w=1 & (a!=0) & r=0 & !in -> (r'=9); - // w3 -> r6 | w4 (any angle point) - [fly] w=3 & (a!=0) & r=0 & !in -> (r'=6); - [fly] w=3 & (a!=0) & r=0 & !in -> 1/8:(w'=4) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=4) & (a'=8) & (r'=0) & (in'=true); +label "obs" = (r=6 & c=2) | (r=8 & c=1) | (r=4 & c=1) | (r=5 & c=2) | (r=7 & c=1) | (r=8 & c=3) | (r=9 & c=2) | (r=9 & c=1) | (r=4 & c=4) | (r=7 & c=6) | (r=9 & c=5) | (r=3 & c=5) | (r=6 & c=4) | (r=7 & c=2) | (r=5 & c=9) | (r=8 & c=9); - // w4 -> w3 | w5 - [fly] w=4 & (a!=0) & r=0 & !in -> 1/8:(w'=3) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=8) & (r'=0) & (in'=true); +rewards + [east] !wall : 1; + [south] !wall : 1; + [west] !wall : 1; + [north] !wall : 1; - [fly] w=4 & (a!=0) & r=0 & !in -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); - // r1 -> r2 | w1 - [fly] r=1 -> (r'=2); - [fly] r=1 -> 1/8:(w'=1) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=8) & (r'=0) & (in'=true); - // r2 -> r1 | w6 - [fly] r=2 -> (r'=1); - [fly] r=2 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); - // r3 -> w5 | w6 - [fly] r=3 -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); - - [fly] r=3 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); - // r4 -> r5 | w5 - [fly] r=4 -> (r'=5); - [fly] r=4 -> 1/8:(w'=5) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=5) & (a'=8) & (r'=0) & (in'=true); - // r5 -> r4 | w2 - [fly] r=5 -> (r'=4); - [fly] r=5 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); - // r6 -> w2 | w3 - [fly] r=6 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); - - [fly] r=6 -> 1/8:(w'=3) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=3) & (a'=8) & (r'=0) & (in'=true); - // r7 -> w2 | r8 - [fly] r=7 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); - [fly] r=7 -> (r'=8); - // r8 -> w6 | r7 - [fly] r=8 -> 1/8:(w'=6) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=6) & (a'=8) & (r'=0) & (in'=true); - [fly] r=8 -> (r'=7); - // r9 -> w1 | w2 - [fly] r=9 -> 1/8:(w'=1) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=1) & (a'=8) & (r'=0) & (in'=true); - - [fly] r=9 -> 1/8:(w'=2) & (a'=1) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=2) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=3) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=4) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=5) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=6) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=7) & (r'=0) & (in'=true) - + 1/8:(w'=2) & (a'=8) & (r'=0) & (in'=true); - -endmodule - - -rewards "time" // flight time - [wait] true: 10; - [fly] true: 60; + [east] wall : 20; + [south] wall : 20; + [west] wall : 20; + [north] wall : 20; endrewards - -rewards "ROZ" // ROZ occupancy - [fly] roz : 1; -endrewards \ No newline at end of file diff --git a/sav-imdp.prism b/sav-imdp.prism index 370f4ded0c..3d140258d7 100644 --- a/sav-imdp.prism +++ b/sav-imdp.prism @@ -11,7 +11,7 @@ mdp //The difference of the reliability of the channels between the worst and at the best position const double pLDiff=0.7; const double pHDiff=0.1; -const double u=0.1; +const double u=0.08; //Scaling factor for the minimum reliability of the channels const double pL=0.2; const double pH=0.3; @@ -22,8 +22,8 @@ const double pLMin=pL*(1-pLDiff); const double pHMin= pH*(1-pHDiff); // Grid size -const int Xsize = 7; -const int Ysize = 7; +const int Xsize = 8; +const int Ysize = 8; // Number of tries before an error const int MAXTRIES = 2; // Ball within the robot has to move. diff --git a/test.prism b/test.prism new file mode 100644 index 0000000000..6f93335cd3 --- /dev/null +++ b/test.prism @@ -0,0 +1,21 @@ +mdp + +module robot + s : [0..10] init 0; + + // at state 0: west is very reliable, south less so + [west] (s=0) -> [0.8,0.95]:(s'=1) + [0.05,0.2]: (s'=0); + [south] (s=0) -> [0.7,0.9]:(s'=3) + [0.1,0.3]: (s'=0); + + // at state 1: south is quite noisy + [stop] (s=1) -> 1.0 : true; + + [stop] (s=3) -> 1.0 : true; +endmodule + +label "goal" = (s=3) | (s=1); + +rewards + [west] true: 1; + [south] true: 1; +endrewards diff --git a/visualization.py b/visualization.py new file mode 100644 index 0000000000..daf0473ab0 --- /dev/null +++ b/visualization.py @@ -0,0 +1,43 @@ +import pandas as pd +import matplotlib.pyplot as plt + +# Load the data +df = pd.read_csv('viu.csv') + + +# Compute permissiveness metric + +# Friendly titles for each task +title_map = { + 'ac-8x5': 'Aircraft Collision', + 'SAV-5x5': 'Semi. Autonomous Vehicle', + 'obst-v1-100': 'Frozen Lake', + 'warehouse' : 'Warehouse Navigation' +} + +tasks = df['Task'].unique() +colors = ['tab:blue', 'tab:orange', 'tab:green', 'tab:red'] + +# Create horizontal subplots +fig, axes = plt.subplots(1, len(tasks), figsize=(15, 4), sharex=True) + +for ax, task, color in zip(axes, tasks, colors): + data = df[df['Task'] == task] + ax.plot(data['uGap'], data['Permissiveness'], marker='o', color=color) + ax.set_title(title_map[task], fontsize=12) + ax.set_xlabel('u-gap') + ax.set_ylabel('Permissiveness') + ax.grid(axis='y', linestyle='--', alpha=0.7) + +# Add a centered caption under the plots +fig.text( + 0.5, # x = center + 0.01, # y = 1% from bottom of figure + 'Permissiveness = 1 - #DiscardedActions / #Interger', + ha='center', # horizontal alignment + va='bottom', # vertical alignment + fontsize='medium' +) + +plt.tight_layout(rect=[0, 0.03, 1, 1]) # leave space at bottom for the caption +plt.show() diff --git a/viu.csv b/viu.csv new file mode 100644 index 0000000000..0599cbeec9 --- /dev/null +++ b/viu.csv @@ -0,0 +1,19 @@ +Task,uGap,States,Transitions,Choices,Discarded,NumberPermissiveState,Permissiveness +ac-8x5,0.01,231,2572,693,26,221,0.9624819625 +ac-8x5,0.03,231,2572,693,28,220,0.9595959596 +ac-8x5,0.05,231,2572,693,30,219,0.9567099567 +ac-8x5,0.08,231,2572,693,32,218,0.9538239538 +ac-8x5,0.1,231,2572,693,36,217,0.9480519481 +SAV-5x5,0.01,243,3628,1120,22,217,0.9803571429 +SAV-5x5,0.03,243,3628,1120,23,216,0.9794642857 +SAV-5x5,0.05,243,3628,1120,24,215,0.9785714286 +SAV-5x5,0.08,243,3628,1120,25,214,0.9776785714 +SAV-5x5,0.1,243,3628,1120,26,213,0.9767857143 +obst-v1-100,0.01,11336,1760,11424,30,21,0.9973739496 +obst-v1-100,0.03,11336,1760,11424,37,19,0.9967612045 +obst-v1-100,0.05,11336,1760,11424,54,12,0.9952731092 +warehouse,0.01,5512,7535,7518,2,2004,0.9997339718 +warehouse,0.03,5512,7535,7518,2,2004,0.9997339718 +warehouse,0.05,5512,7535,7518,2,2004,0.9997339718 +warehouse,0.08,5512,7535,7518,2,2004,0.9997339718 +warehouse,0.1,5512,7535,7518,2,2004,0.9997339718 \ No newline at end of file diff --git a/wh.prism b/wh.prism new file mode 100644 index 0000000000..35b28c1bdb --- /dev/null +++ b/wh.prism @@ -0,0 +1,119 @@ +mdp + +//─── PARAMETERS ────────────────────────────────────────────────────────────── +const int K = 500; // # of sub‐steps per move +const double p = 0.7; // nominal success prob. +const double e = 0.01; // uncertainty radius + +//─── STATE ──────────────────────────────────────────────────────────────────── +module graph_imdp + s : [0..14] init 0; // which node + step : [0..K] init 0; // progress along chosen edge + + //─────────────────────────────────────────────────────────────────────────── + // EAST moves (horizontal rightwards) + //────────── sub‐steps ───────────────────────────────────────────────────── + [east] (step < K) & (s=0|s=3|s=4|s=8|s=11|s=12) + -> 1 : (step' = step + 1); + + //────────── final jump ───────────────────────────────────────────────────── + [east] (step = K) & (s=0) + -> [p-e, p+e]:(s'=1)&(step'=0) + + [1-p-e, 1-p+e]:(s'=0)&(step'=step); + [east] (step = K) & (s=2) + -> [p-2*e, p+2*e]:(s'=1)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=0)&(step'=step); + [east] (step = K) & (s=3) + -> [p-e, p+e]:(s'=2)&(step'=0) + + [1-p-e, 1-p+e]:(s'=3)&(step'=step); + [east] (step = K) & (s=4) + -> [p-e, p+e]:(s'=5)&(step'=0) + + [1-p-e, 1-p+e]:(s'=4)&(step'=step); + [east] (step = K) & (s=8) + -> [p-e, p+e]:(s'=9)&(step'=0) + + [1-p-e, 1-p+e]:(s'=8)&(step'=step); + [east] (step = K) & (s=11) + -> [p-e, p+e]:(s'=12)&(step'=0) + + [1-p-e, 1-p+e]:(s'=11)&(step'=step); + [east] (step = K) & (s=12) + -> [p-e, p+e]:(s'=13)&(step'=0) + + [1-p-e, 1-p+e]:(s'=12)&(step'=step); + [east] (step = K) & (s=13) + -> [p-e, p+e]:(s'=14)&(step'=0) + + [1-p-e, 1-p+e]:(s'=13)&(step'=step); + + //─────────────────────────────────────────────────────────────────────────── + // SOUTH moves (vertical downwards) + [south] (step < K) & (s=0|s=1|s=2|s=3|s=4|s=5|s=6|s=7|s=8|s=9) + -> 1 : (step' = step + 1); + + [south] (step = K) & (s=0) + -> [p-e, p+e]:(s'=3)&(step'=0) + + [1-p-e, 1-p+e]:(s'=0)&(step'=step); + [south] (step = K) & (s=1) + -> [p-e, p+e]:(s'=2)&(step'=0) + + [1-p-e, 1-p+e]:(s'=1)&(step'=step); + [south] (step = K) & (s=2) + -> [p-e, p+e]:(s'=5)&(step'=0) + + [1-p-e, 1-p+e]:(s'=2)&(step'=step); + [south] (step = K) & (s=3) + -> [p-e, p+e]:(s'=4)&(step'=0) + + [1-p-e, 1-p+e]:(s'=3)&(step'=step); + [south] (step = K) & (s=4) + -> [p-e, p+e]:(s'=8)&(step'=0) + + [1-p-e, 1-p+e]:(s'=4)&(step'=step); + [south] (step = K) & (s=5) + -> [p-e, p+e]:(s'=9)&(step'=0) + + [1-p-e, 1-p+e]:(s'=5)&(step'=step); + [south] (step = K) & (s=6) + -> [p-2*e, p+2*e]:(s'=7)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=6)&(step'=step); + [south] (step = K) & (s=7) + -> [p-2*e, p+2*e]:(s'=10)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=7)&(step'=step); + [south] (step = K) & (s=8) + -> [p-e, p+e]:(s'=11)&(step'=0) + + [1-p-e, 1-p+e]:(s'=8)&(step'=step); + [south] (step = K) & (s=9) + -> [p-e, p+e]:(s'=12)&(step'=0) + + [1-p-e, 1-p+e]:(s'=9)&(step'=step); + + //─────────────────────────────────────────────────────────────────────────── + // WEST moves (horizontal leftwards) + [west] (step < K) & (s=7) + -> 1 : (step' = step + 1); + [west] (step = K) & (s=7) + -> [p-2*e, p+2*e]:(s'=5)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=7)&(step'=step); + + [west] (step < K) & (s=10) + -> 1 : (step' = step + 1); + [west] (step = K) & (s=10) + -> [p-2*e, p+2*e]:(s'=9)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=10)&(step'=step); + + //─────────────────────────────────────────────────────────────────────────── + // EXIT moves (diagonal/termination from 10→14) + [exit] (step < K) & (s=10) + -> 1 : (step' = step + 1); + [exit] (step = K) & (s=10) + -> [p-2*e, p+2*e]:(s'=14)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=10)&(step'=step); + [exit] (step < K) & (s=13) + -> 1 : (step' = step + 1); + [exit] (step = K) & (s=13) + -> [p-e, p+e]:(s'=14)&(step'=0) + + [1-p-e, 1-p+e]:(s'=13)&(step'=step); + + // state 14 has no outgoing moves + [done] s = 14 & step = 0 -> true; +endmodule + + +label "goal" = (s = 14 & step = 0); + +rewards + [east] true : 1; + [west] true : 1; + [south] true : 1; +endrewards diff --git a/wp.prism b/wp.prism new file mode 100644 index 0000000000..f2985ad7f3 --- /dev/null +++ b/wp.prism @@ -0,0 +1,41 @@ +mdp +const int N=5; // N*N grid map +const double p=0.1; // with probability p, a move to a neighboring state state occurs due to seeing and control noise +const double e = 0.02; + +formula wall = (r=6 & c=2) | (r=8 & c=1) | (r=4 & c=1) | (r=5 & c=2) | (r=7 & c=1) | (r=8 & c=3) | (r=9 & c=2) | (r=9 & c=1) | (r=4 & c=4) | (r=7 & c=6) | (r=9 & c=5) | (r=3 & c=5) | (r=6 & c=4) | (r=7 & c=2) | (r=5 & c=9) | (r=8 & c=9); + +module robot + //define robot position + r:[1..N] init 1; //grid row + c:[1..N] init 1; //grid column + + // go to the terminal state when hitting an obstacle + // [obstacle] wall -> (r'=10) & (c'=1); + + // transitions + [east] (c [p/3-e,p/3+e]:(r'=min(r+1, N))+ [p/3-e,p/3+e]: (c'=max(c-1, 1))+ [p/3-e,p/3+e]: (r'=max(r-1, 1)) + [1-p-e,1-p+e]: (c'=min(c+1, N)); + [south] (r [1-p-e,1-p+e]:(r'=min(r+1, N)) + [p/3-e,p/3+e]: (c'=min(c+1, N)) + [p/3-e,p/3+e]:(r'=max(r-1, 1))+ [p/3-e,p/3+e]: (c'=max(c-1, 1)); + [west] (c>1 | c=1) -> [p/3-e,p/3+e]:(r'=max(r-1, 1))+ [p/3-e,p/3+e]:(r'=min(r+1, N))+ [p/3-e,p/3+e]: (c'=min(c+1, N)) + [1-p-e,1-p+e]: (c'=max(c-1, 1)); + [north] (r=1 | r>1) -> [1-p-e,1-p+e]:(r'=max(r-1, 1)) + [p/3-e,p/3+e]: (c'=max(c-1, 1)) + [p/3-e,p/3+e]: (c'=min(c+1, N)) + [p/3-e,p/3+e]:(r'=min(r+1, N)); + + // terminal state self-loop to avoid deadlock + [done] r=10 & c=1 -> true; + +endmodule + +label "goal" = r=10 & c=1; + +label "obs" = (r=6 & c=2) | (r=8 & c=1) | (r=4 & c=1) | (r=5 & c=2) | (r=7 & c=1) | (r=8 & c=3) | (r=9 & c=2) | (r=9 & c=1) | (r=4 & c=4) | (r=7 & c=6) | (r=9 & c=5) | (r=3 & c=5) | (r=6 & c=4) | (r=7 & c=2) | (r=5 & c=9) | (r=8 & c=9); + +rewards + [east] !wall : 1; + [south] !wall : 1; + [west] !wall : 1; + [north] !wall : 1; + + [east] wall : 20; + [south] wall : 20; + [west] wall : 20; + [north] wall : 20; +endrewards From 5da4b5e0a8b64a0255bc56b665beae446c7aab00 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Thu, 11 Sep 2025 08:33:13 -0400 Subject: [PATCH 10/11] organizing files --- ad-6x5.prism | 51 + dual_e005.lp | 127 ++ dual_e005_strat.txt | 4 + dual_e01.lp | 127 ++ dual_e01_strat.txt | 4 + experiment/ac-imdp-6x5-10.prism | 54 + experiment/ac-imdp-6x5-12.prism | 54 + experiment/ac-imdp-6x5-14.prism | 54 + experiment/ac-imdp.prism | 54 + experiment/ad-6x6-10.prism | 80 + experiment/ad-6x6-6.prism | 68 + experiment/ad-6x6-og.prism | 62 + experiment/ad-running.prism | 48 + experiment/ov-5x5.prism | 86 ++ experiment/ov-6x6.prism | 86 ++ experiment/re.prism | 27 + experiment/sav-imdp.prism | 61 + experiment/wh.prism | 119 ++ naive_e005.lp | 36 + naive_e005_strat.txt | 4 + naive_e01.lp | 34 + naive_e01_strat.txt | 4 + outgoing/test1.prism | 25 + outgoing/test10.prism | 66 + outgoing/test15.prism | 76 + outgoing/test20.prism | 77 + outgoing/test3.prism | 37 + outgoing/test5.prism | 43 + outgoing/test8.prism | 52 + prism/src/explicit/IMDPModelChecker.java | 1719 +++++++--------------- sav-imdp.prism | 4 +- strat1.txt | 231 +++ strat2.txt | 231 +++ test1.prism | 20 + test15.prism | 71 + value1.txt | 231 +++ value2.txt | 231 +++ wh.prism | 2 +- 38 files changed, 3187 insertions(+), 1173 deletions(-) create mode 100644 ad-6x5.prism create mode 100644 dual_e005.lp create mode 100644 dual_e005_strat.txt create mode 100644 dual_e01.lp create mode 100644 dual_e01_strat.txt create mode 100644 experiment/ac-imdp-6x5-10.prism create mode 100644 experiment/ac-imdp-6x5-12.prism create mode 100644 experiment/ac-imdp-6x5-14.prism create mode 100644 experiment/ac-imdp.prism create mode 100644 experiment/ad-6x6-10.prism create mode 100644 experiment/ad-6x6-6.prism create mode 100644 experiment/ad-6x6-og.prism create mode 100644 experiment/ad-running.prism create mode 100644 experiment/ov-5x5.prism create mode 100644 experiment/ov-6x6.prism create mode 100644 experiment/re.prism create mode 100644 experiment/sav-imdp.prism create mode 100644 experiment/wh.prism create mode 100644 naive_e005.lp create mode 100644 naive_e005_strat.txt create mode 100644 naive_e01.lp create mode 100644 naive_e01_strat.txt create mode 100644 outgoing/test1.prism create mode 100644 outgoing/test10.prism create mode 100644 outgoing/test15.prism create mode 100644 outgoing/test20.prism create mode 100644 outgoing/test3.prism create mode 100644 outgoing/test5.prism create mode 100644 outgoing/test8.prism create mode 100644 strat1.txt create mode 100644 strat2.txt create mode 100644 test1.prism create mode 100644 test15.prism create mode 100644 value1.txt create mode 100644 value2.txt diff --git a/ad-6x5.prism b/ad-6x5.prism new file mode 100644 index 0000000000..354ad11453 --- /dev/null +++ b/ad-6x5.prism @@ -0,0 +1,51 @@ +mdp + +// Model parameters +const double p = 0.1; // Mean disturbance probability +const double e = 0.05; // Epistemic uncertainty +formula a = x * e; // Epistemic uncertainty grows with x-coordinate + +const int M = 5; // Environment width +const int N = 6; // Environment height + +const double eps = 0.0001; // Lower bound for probability ranges + +// Goal +formula goal = x = 1 & y = N; + +// Obstacles +formula crashed = (x = 2 & y = 3) | (x = 3 & y = 3) | (x = 3 & y = 4); + +// UAV behaviour +module env + + x : [1..M] init 1; + y : [1..N] init 1; + + [up] !crashed & y < N -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (y'=min(y+1,N)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=max(x-1,1)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true; + + [right] !crashed & x < M -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (x'=min(x+1,M)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) + + [max(eps,p-a), min(p+a,1)] : true; + + [left] !crashed & x > 1 -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (x'=max(x-1,1)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true; + +endmodule + +// Your handcrafted policy +module policy + [up] x < 3 -> true; + [left] x >= 3 -> true; + [right] false -> true; +endmodule + +// Labelling +label "Crash" = crashed; +label "goal" = goal; \ No newline at end of file diff --git a/dual_e005.lp b/dual_e005.lp new file mode 100644 index 0000000000..740de4c4ae --- /dev/null +++ b/dual_e005.lp @@ -0,0 +1,127 @@ +\ LP format - for model browsing. Use MPS format to capture full model detail. +\ Signature: 0x14645777317348bd +Minimize + - eta-0-0 - eta-0-1 - eta-1-0 - eta-2-0 - eta-3-0 + 5 Constant +Subject To + v-target: mu[3] = 1 + v-no: mu[2] = 0 + lamU[0-0]: - 1.01 eta-0-0 + lam-0-0 <= 0 + lamD[0-0]: 1.01 eta-0-0 + lam-0-0 >= 0 + uPlusLow-0-0-1: uplus[0-0->1] >= 0 + uMinLow-0-0-1: umin[0-0->1] >= 0 + uPlusHigh-0-0-1: - 1.01 eta-0-0 + uplus[0-0->1] <= 0 + uMinHigh-0-0-1: - 1.01 eta-0-0 + umin[0-0->1] <= 0 + dualFeas_0-0_1: - mu[1] + lam-0-0 - uplus[0-0->1] + umin[0-0->1] <= 0 + uPlusLow-0-0-2: uplus[0-0->2] >= 0 + uMinLow-0-0-2: umin[0-0->2] >= 0 + uPlusHigh-0-0-2: - 1.01 eta-0-0 + uplus[0-0->2] <= 0 + uMinHigh-0-0-2: - 1.01 eta-0-0 + umin[0-0->2] <= 0 + dualFeas_0-0_2: - mu[2] + lam-0-0 - uplus[0-0->2] + umin[0-0->2] <= 0 + lamU[0-1]: - 1.01 eta-0-1 + lam-0-1 <= 0 + lamD[0-1]: 1.01 eta-0-1 + lam-0-1 >= 0 + uPlusLow-0-1-2: uplus[0-1->2] >= 0 + uMinLow-0-1-2: umin[0-1->2] >= 0 + uPlusHigh-0-1-2: - 1.01 eta-0-1 + uplus[0-1->2] <= 0 + uMinHigh-0-1-2: - 1.01 eta-0-1 + umin[0-1->2] <= 0 + dualFeas_0-1_2: - mu[2] + lam-0-1 - uplus[0-1->2] + umin[0-1->2] <= 0 + uPlusLow-0-1-3: uplus[0-1->3] >= 0 + uMinLow-0-1-3: umin[0-1->3] >= 0 + uPlusHigh-0-1-3: - 1.01 eta-0-1 + uplus[0-1->3] <= 0 + uMinHigh-0-1-3: - 1.01 eta-0-1 + umin[0-1->3] <= 0 + dualFeas_0-1_3: - mu[3] + lam-0-1 - uplus[0-1->3] + umin[0-1->3] <= 0 + lamU[1-0]: - 1.01 eta-1-0 + lam-1-0 <= 0 + lamD[1-0]: 1.01 eta-1-0 + lam-1-0 >= 0 + uPlusLow-1-0-2: uplus[1-0->2] >= 0 + uMinLow-1-0-2: umin[1-0->2] >= 0 + uPlusHigh-1-0-2: - 1.01 eta-1-0 + uplus[1-0->2] <= 0 + uMinHigh-1-0-2: - 1.01 eta-1-0 + umin[1-0->2] <= 0 + dualFeas_1-0_2: - mu[2] + lam-1-0 - uplus[1-0->2] + umin[1-0->2] <= 0 + uPlusLow-1-0-3: uplus[1-0->3] >= 0 + uMinLow-1-0-3: umin[1-0->3] >= 0 + uPlusHigh-1-0-3: - 1.01 eta-1-0 + uplus[1-0->3] <= 0 + uMinHigh-1-0-3: - 1.01 eta-1-0 + umin[1-0->3] <= 0 + dualFeas_1-0_3: - mu[3] + lam-1-0 - uplus[1-0->3] + umin[1-0->3] <= 0 + lamU[2-0]: - 1.01 eta-2-0 + lam-2-0 <= 0 + lamD[2-0]: 1.01 eta-2-0 + lam-2-0 >= 0 + uPlusLow-2-0-2: uplus[2-0->2] >= 0 + uMinLow-2-0-2: umin[2-0->2] >= 0 + uPlusHigh-2-0-2: - 1.01 eta-2-0 + uplus[2-0->2] <= 0 + uMinHigh-2-0-2: - 1.01 eta-2-0 + umin[2-0->2] <= 0 + dualFeas_2-0_2: - mu[2] + lam-2-0 - uplus[2-0->2] + umin[2-0->2] <= 0 + lamU[3-0]: - 1.01 eta-3-0 + lam-3-0 <= 0 + lamD[3-0]: 1.01 eta-3-0 + lam-3-0 >= 0 + uPlusLow-3-0-3: uplus[3-0->3] >= 0 + uMinLow-3-0-3: umin[3-0->3] >= 0 + uPlusHigh-3-0-3: - 1.01 eta-3-0 + uplus[3-0->3] <= 0 + uMinHigh-3-0-3: - 1.01 eta-3-0 + umin[3-0->3] <= 0 + dualFeas_3-0_3: - mu[3] + lam-3-0 - uplus[3-0->3] + umin[3-0->3] <= 0 + actSel-0: eta-0-0 + eta-0-1 >= 1 + actSel-1: eta-1-0 >= 1 + actSel-2: eta-2-0 >= 1 + actSel-3: eta-3-0 >= 1 + mc1-0-0: eta-0-0 + phi-0-0 >= 0 + mc2-0-0: - eta-0-0 + phi-0-0 <= 0 + mc3-0-0: - eta-0-0 - lam-0-0 + phi-0-0 >= -1 + mc4-0-0: eta-0-0 - lam-0-0 + phi-0-0 <= 1 + mc1-0-1: eta-0-1 + phi-0-1 >= 0 + mc2-0-1: - eta-0-1 + phi-0-1 <= 0 + mc3-0-1: - eta-0-1 - lam-0-1 + phi-0-1 >= -1 + mc4-0-1: eta-0-1 - lam-0-1 + phi-0-1 <= 1 + mc1-1-0: eta-1-0 + phi-1-0 >= 0 + mc2-1-0: - eta-1-0 + phi-1-0 <= 0 + mc3-1-0: - eta-1-0 - lam-1-0 + phi-1-0 >= -1 + mc4-1-0: eta-1-0 - lam-1-0 + phi-1-0 <= 1 + mc1-2-0: eta-2-0 + phi-2-0 >= 0 + mc2-2-0: - eta-2-0 + phi-2-0 <= 0 + mc3-2-0: - eta-2-0 - lam-2-0 + phi-2-0 >= -1 + mc4-2-0: eta-2-0 - lam-2-0 + phi-2-0 <= 1 + mc1-3-0: eta-3-0 + phi-3-0 >= 0 + mc2-3-0: - eta-3-0 + phi-3-0 <= 0 + mc3-3-0: - eta-3-0 - lam-3-0 + phi-3-0 >= -1 + mc4-3-0: eta-3-0 - lam-3-0 + phi-3-0 <= 1 + bell-0-0: mu[0] + 1.01 eta-0-0 + 0.95 uplus[0-0->1] - 0.85 umin[0-0->1] + + 0.15 uplus[0-0->2] - 0.05 umin[0-0->2] - phi-0-0 <= 1.01 + bell-0-1: mu[0] + 1.01 eta-0-1 + 0.27 uplus[0-1->2] - 0.17 umin[0-1->2] + + 0.83 uplus[0-1->3] - 0.73 umin[0-1->3] - phi-0-1 <= 1.01 + bell-1-0: mu[1] + 1.01 eta-1-0 + 0.15 uplus[1-0->2] - 0.05 umin[1-0->2] + + 0.95 uplus[1-0->3] - 0.85 umin[1-0->3] - phi-1-0 <= 1.01 + bell-2-0: mu[2] + 1.01 eta-2-0 + uplus[2-0->2] - umin[2-0->2] - phi-2-0 + <= 1.01 + bell-3-0: mu[3] + 1.01 eta-3-0 + uplus[3-0->3] - umin[3-0->3] - phi-3-0 + <= 1.01 + multi-bound: mu[0] >= 0.65 +Bounds + mu[0] <= 1 + mu[1] <= 1 + mu[2] <= 1 + mu[3] <= 1 + -1 <= lam-0-0 <= 1 + uplus[0-0->1] <= 1.01 + umin[0-0->1] <= 1.01 + uplus[0-0->2] <= 1.01 + umin[0-0->2] <= 1.01 + -1 <= lam-0-1 <= 1 + uplus[0-1->2] <= 1.01 + umin[0-1->2] <= 1.01 + uplus[0-1->3] <= 1.01 + umin[0-1->3] <= 1.01 + -1 <= lam-1-0 <= 1 + uplus[1-0->2] <= 1.01 + umin[1-0->2] <= 1.01 + uplus[1-0->3] <= 1.01 + umin[1-0->3] <= 1.01 + -1 <= lam-2-0 <= 1 + uplus[2-0->2] <= 1.01 + umin[2-0->2] <= 1.01 + -1 <= lam-3-0 <= 1 + uplus[3-0->3] <= 1.01 + umin[3-0->3] <= 1.01 + -1 <= phi-0-0 <= 1 + -1 <= phi-0-1 <= 1 + -1 <= phi-1-0 <= 1 + -1 <= phi-2-0 <= 1 + -1 <= phi-3-0 <= 1 + Constant = 1 +Binaries + eta-0-0 eta-0-1 eta-1-0 eta-2-0 eta-3-0 +End diff --git a/dual_e005_strat.txt b/dual_e005_strat.txt new file mode 100644 index 0000000000..ed12f595a2 --- /dev/null +++ b/dual_e005_strat.txt @@ -0,0 +1,4 @@ +0: m f +1: m +2: trapped +3: done \ No newline at end of file diff --git a/dual_e01.lp b/dual_e01.lp new file mode 100644 index 0000000000..7c87c7ecad --- /dev/null +++ b/dual_e01.lp @@ -0,0 +1,127 @@ +\ LP format - for model browsing. Use MPS format to capture full model detail. +\ Signature: 0xf334aa5b69baf57d +Minimize + - eta-0-0 - eta-0-1 - eta-1-0 - eta-2-0 - eta-3-0 + 5 Constant +Subject To + v-target: mu[3] = 1 + v-no: mu[2] = 0 + lamU[0-0]: - 1.01 eta-0-0 + lam-0-0 <= 0 + lamD[0-0]: 1.01 eta-0-0 + lam-0-0 >= 0 + uPlusLow-0-0-1: uplus[0-0->1] >= 0 + uMinLow-0-0-1: umin[0-0->1] >= 0 + uPlusHigh-0-0-1: - 1.01 eta-0-0 + uplus[0-0->1] <= 0 + uMinHigh-0-0-1: - 1.01 eta-0-0 + umin[0-0->1] <= 0 + dualFeas_0-0_1: - mu[1] + lam-0-0 - uplus[0-0->1] + umin[0-0->1] <= 0 + uPlusLow-0-0-2: uplus[0-0->2] >= 0 + uMinLow-0-0-2: umin[0-0->2] >= 0 + uPlusHigh-0-0-2: - 1.01 eta-0-0 + uplus[0-0->2] <= 0 + uMinHigh-0-0-2: - 1.01 eta-0-0 + umin[0-0->2] <= 0 + dualFeas_0-0_2: - mu[2] + lam-0-0 - uplus[0-0->2] + umin[0-0->2] <= 0 + lamU[0-1]: - 1.01 eta-0-1 + lam-0-1 <= 0 + lamD[0-1]: 1.01 eta-0-1 + lam-0-1 >= 0 + uPlusLow-0-1-2: uplus[0-1->2] >= 0 + uMinLow-0-1-2: umin[0-1->2] >= 0 + uPlusHigh-0-1-2: - 1.01 eta-0-1 + uplus[0-1->2] <= 0 + uMinHigh-0-1-2: - 1.01 eta-0-1 + umin[0-1->2] <= 0 + dualFeas_0-1_2: - mu[2] + lam-0-1 - uplus[0-1->2] + umin[0-1->2] <= 0 + uPlusLow-0-1-3: uplus[0-1->3] >= 0 + uMinLow-0-1-3: umin[0-1->3] >= 0 + uPlusHigh-0-1-3: - 1.01 eta-0-1 + uplus[0-1->3] <= 0 + uMinHigh-0-1-3: - 1.01 eta-0-1 + umin[0-1->3] <= 0 + dualFeas_0-1_3: - mu[3] + lam-0-1 - uplus[0-1->3] + umin[0-1->3] <= 0 + lamU[1-0]: - 1.01 eta-1-0 + lam-1-0 <= 0 + lamD[1-0]: 1.01 eta-1-0 + lam-1-0 >= 0 + uPlusLow-1-0-2: uplus[1-0->2] >= 0 + uMinLow-1-0-2: umin[1-0->2] >= 0 + uPlusHigh-1-0-2: - 1.01 eta-1-0 + uplus[1-0->2] <= 0 + uMinHigh-1-0-2: - 1.01 eta-1-0 + umin[1-0->2] <= 0 + dualFeas_1-0_2: - mu[2] + lam-1-0 - uplus[1-0->2] + umin[1-0->2] <= 0 + uPlusLow-1-0-3: uplus[1-0->3] >= 0 + uMinLow-1-0-3: umin[1-0->3] >= 0 + uPlusHigh-1-0-3: - 1.01 eta-1-0 + uplus[1-0->3] <= 0 + uMinHigh-1-0-3: - 1.01 eta-1-0 + umin[1-0->3] <= 0 + dualFeas_1-0_3: - mu[3] + lam-1-0 - uplus[1-0->3] + umin[1-0->3] <= 0 + lamU[2-0]: - 1.01 eta-2-0 + lam-2-0 <= 0 + lamD[2-0]: 1.01 eta-2-0 + lam-2-0 >= 0 + uPlusLow-2-0-2: uplus[2-0->2] >= 0 + uMinLow-2-0-2: umin[2-0->2] >= 0 + uPlusHigh-2-0-2: - 1.01 eta-2-0 + uplus[2-0->2] <= 0 + uMinHigh-2-0-2: - 1.01 eta-2-0 + umin[2-0->2] <= 0 + dualFeas_2-0_2: - mu[2] + lam-2-0 - uplus[2-0->2] + umin[2-0->2] <= 0 + lamU[3-0]: - 1.01 eta-3-0 + lam-3-0 <= 0 + lamD[3-0]: 1.01 eta-3-0 + lam-3-0 >= 0 + uPlusLow-3-0-3: uplus[3-0->3] >= 0 + uMinLow-3-0-3: umin[3-0->3] >= 0 + uPlusHigh-3-0-3: - 1.01 eta-3-0 + uplus[3-0->3] <= 0 + uMinHigh-3-0-3: - 1.01 eta-3-0 + umin[3-0->3] <= 0 + dualFeas_3-0_3: - mu[3] + lam-3-0 - uplus[3-0->3] + umin[3-0->3] <= 0 + actSel-0: eta-0-0 + eta-0-1 >= 1 + actSel-1: eta-1-0 >= 1 + actSel-2: eta-2-0 >= 1 + actSel-3: eta-3-0 >= 1 + mc1-0-0: eta-0-0 + phi-0-0 >= 0 + mc2-0-0: - eta-0-0 + phi-0-0 <= 0 + mc3-0-0: - eta-0-0 - lam-0-0 + phi-0-0 >= -1 + mc4-0-0: eta-0-0 - lam-0-0 + phi-0-0 <= 1 + mc1-0-1: eta-0-1 + phi-0-1 >= 0 + mc2-0-1: - eta-0-1 + phi-0-1 <= 0 + mc3-0-1: - eta-0-1 - lam-0-1 + phi-0-1 >= -1 + mc4-0-1: eta-0-1 - lam-0-1 + phi-0-1 <= 1 + mc1-1-0: eta-1-0 + phi-1-0 >= 0 + mc2-1-0: - eta-1-0 + phi-1-0 <= 0 + mc3-1-0: - eta-1-0 - lam-1-0 + phi-1-0 >= -1 + mc4-1-0: eta-1-0 - lam-1-0 + phi-1-0 <= 1 + mc1-2-0: eta-2-0 + phi-2-0 >= 0 + mc2-2-0: - eta-2-0 + phi-2-0 <= 0 + mc3-2-0: - eta-2-0 - lam-2-0 + phi-2-0 >= -1 + mc4-2-0: eta-2-0 - lam-2-0 + phi-2-0 <= 1 + mc1-3-0: eta-3-0 + phi-3-0 >= 0 + mc2-3-0: - eta-3-0 + phi-3-0 <= 0 + mc3-3-0: - eta-3-0 - lam-3-0 + phi-3-0 >= -1 + mc4-3-0: eta-3-0 - lam-3-0 + phi-3-0 <= 1 + bell-0-0: mu[0] + 1.01 eta-0-0 + uplus[0-0->1] - 0.8 umin[0-0->1] + + 0.2 uplus[0-0->2] - phi-0-0 <= 1.01 + bell-0-1: mu[0] + 1.01 eta-0-1 + 0.32 uplus[0-1->2] - 0.12 umin[0-1->2] + + 0.88 uplus[0-1->3] - 0.68 umin[0-1->3] - phi-0-1 <= 1.01 + bell-1-0: mu[1] + 1.01 eta-1-0 + 0.2 uplus[1-0->2] + uplus[1-0->3] + - 0.8 umin[1-0->3] - phi-1-0 <= 1.01 + bell-2-0: mu[2] + 1.01 eta-2-0 + uplus[2-0->2] - umin[2-0->2] - phi-2-0 + <= 1.01 + bell-3-0: mu[3] + 1.01 eta-3-0 + uplus[3-0->3] - umin[3-0->3] - phi-3-0 + <= 1.01 + multi-bound: mu[0] >= 0.65 +Bounds + mu[0] <= 1 + mu[1] <= 1 + mu[2] <= 1 + mu[3] <= 1 + -1 <= lam-0-0 <= 1 + uplus[0-0->1] <= 1.01 + umin[0-0->1] <= 1.01 + uplus[0-0->2] <= 1.01 + umin[0-0->2] <= 1.01 + -1 <= lam-0-1 <= 1 + uplus[0-1->2] <= 1.01 + umin[0-1->2] <= 1.01 + uplus[0-1->3] <= 1.01 + umin[0-1->3] <= 1.01 + -1 <= lam-1-0 <= 1 + uplus[1-0->2] <= 1.01 + umin[1-0->2] <= 1.01 + uplus[1-0->3] <= 1.01 + umin[1-0->3] <= 1.01 + -1 <= lam-2-0 <= 1 + uplus[2-0->2] <= 1.01 + umin[2-0->2] <= 1.01 + -1 <= lam-3-0 <= 1 + uplus[3-0->3] <= 1.01 + umin[3-0->3] <= 1.01 + -1 <= phi-0-0 <= 1 + -1 <= phi-0-1 <= 1 + -1 <= phi-1-0 <= 1 + -1 <= phi-2-0 <= 1 + -1 <= phi-3-0 <= 1 + Constant = 1 +Binaries + eta-0-0 eta-0-1 eta-1-0 eta-2-0 eta-3-0 +End diff --git a/dual_e01_strat.txt b/dual_e01_strat.txt new file mode 100644 index 0000000000..263c6ef829 --- /dev/null +++ b/dual_e01_strat.txt @@ -0,0 +1,4 @@ +0: f +1: m +2: trapped +3: done \ No newline at end of file diff --git a/experiment/ac-imdp-6x5-10.prism b/experiment/ac-imdp-6x5-10.prism new file mode 100644 index 0000000000..74349dc892 --- /dev/null +++ b/experiment/ac-imdp-6x5-10.prism @@ -0,0 +1,54 @@ +mdp + + +const int maxX = 6;//10; +const int maxY = 5;//4; +const double r=0.8; //= 0.820795462532;// = 0.5; // pilot response factor +const double e1 = 0.1; +const double p=0.25;// = 0.19; // prob of adversary moving up or down, ensure 2p <= 1 +const double e2=0.01; + + +formula xclose = (x-ax >= 0 & x-ax < 3) | (ax-x >= 0 & ax-x < 3); +formula yclose = (y-ay >= 0 & y-ay < 2) | (ay-y >= 0 & ay-y < 2); +formula collision = xclose & yclose; + +module aircraft + + x : [0..maxX] init 0; + y : [0..maxY] init 1; + + + [down] x < maxX -> [r-e1,r+e1] : (y'=max(y-1,0)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [up] x < maxX -> [r-e1,r+e1] : (y'=min(y+1,maxY)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [stay] x < maxX -> (y'=y) & (x'=x+1); + + [down] x = maxX -> true; + [up] x = maxX -> true; + [stay] x = maxX -> true; + +endmodule + + +module adversary + + ax : [0..maxX] init maxX; + ay : [0..maxY] init 1; + + [up] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1)+ p/2: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/2:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [down] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + p/2: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/2:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [stay] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + p/2: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/2:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [up] ax = 0 -> true; + [down] ax = 0 -> true; + [stay] ax = 0 -> true; + +endmodule + +rewards + [up] true : 1; + [down] true : 1; + [stay] true : 1; +endrewards + +label "goal" = x=maxX; +label "Crash" = collision; \ No newline at end of file diff --git a/experiment/ac-imdp-6x5-12.prism b/experiment/ac-imdp-6x5-12.prism new file mode 100644 index 0000000000..d6bbcab026 --- /dev/null +++ b/experiment/ac-imdp-6x5-12.prism @@ -0,0 +1,54 @@ +mdp + + +const int maxX = 6;//10; +const int maxY = 5;//4; +const double r=0.8; //= 0.820795462532;// = 0.5; // pilot response factor +const double e1 = 0.1; +const double p=0.25;// = 0.19; // prob of adversary moving up or down, ensure 2p <= 1 +const double e2=0.01; + + +formula xclose = (x-ax >= 0 & x-ax < 3) | (ax-x >= 0 & ax-x < 3); +formula yclose = (y-ay >= 0 & y-ay < 2) | (ay-y >= 0 & ay-y < 2); +formula collision = xclose & yclose; + +module aircraft + + x : [0..maxX] init 0; + y : [0..maxY] init 1; + + + [down] x < maxX -> [r-e1,r+e1] : (y'=max(y-1,0)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [up] x < maxX -> [r-e1,r+e1] : (y'=min(y+1,maxY)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [stay] x < maxX -> (y'=y) & (x'=x+1); + + [down] x = maxX -> true; + [up] x = maxX -> true; + [stay] x = maxX -> true; + +endmodule + + +module adversary + + ax : [0..maxX] init maxX; + ay : [0..maxY] init 1; + + [up] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + p/3: (ay'=min(ay+1,maxY)) & (ax'=ax-2) + p/3: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/3:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [down] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1)+ p/3: (ay'=min(ay+1,maxY)) & (ax'=ax-2) + p/3: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/3:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [stay] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1)+ p/3: (ay'=min(ay+1,maxY)) & (ax'=ax-2) + p/3: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/3:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [up] ax = 0 -> true; + [down] ax = 0 -> true; + [stay] ax = 0 -> true; + +endmodule + +rewards + [up] true : 1; + [down] true : 1; + [stay] true : 1; +endrewards + +label "goal" = x=maxX; +label "Crash" = collision; \ No newline at end of file diff --git a/experiment/ac-imdp-6x5-14.prism b/experiment/ac-imdp-6x5-14.prism new file mode 100644 index 0000000000..f0d8347a5e --- /dev/null +++ b/experiment/ac-imdp-6x5-14.prism @@ -0,0 +1,54 @@ +mdp + + +const int maxX = 6;//10; +const int maxY = 5;//4; +const double r=0.8; //= 0.820795462532;// = 0.5; // pilot response factor +const double e1 = 0.1; +const double p=0.25;// = 0.19; // prob of adversary moving up or down, ensure 2p <= 1 +const double e2=0.01; + + +formula xclose = (x-ax >= 0 & x-ax < 3) | (ax-x >= 0 & ax-x < 3); +formula yclose = (y-ay >= 0 & y-ay < 2) | (ay-y >= 0 & ay-y < 2); +formula collision = xclose & yclose; + +module aircraft + + x : [0..maxX] init 0; + y : [0..maxY] init 1; + + + [down] x < maxX -> [r-e1,r+e1] : (y'=max(y-1,0)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [up] x < maxX -> [r-e1,r+e1] : (y'=min(y+1,maxY)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [stay] x < maxX -> (y'=y) & (x'=x+1); + + [down] x = maxX -> true; + [up] x = maxX -> true; + [stay] x = maxX -> true; + +endmodule + + +module adversary + + ax : [0..maxX] init maxX; + ay : [0..maxY] init 1; + + [up] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + p/4: (ay'=min(ay-1,maxY)) & (ax'=ax-2)+ p/4: (ay'=min(ay+1,maxY)) & (ax'=ax-2) + p/4: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/4:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [down] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1)+ p/4: (ay'=min(ay-1,maxY)) & (ax'=ax-2)+ p/4: (ay'=min(ay+1,maxY)) & (ax'=ax-2) + p/4: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/4:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [stay] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1)+p/4: (ay'=min(ay-1,maxY)) & (ax'=ax-2)+ p/4: (ay'=min(ay+1,maxY)) & (ax'=ax-2) + p/4: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/4:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [up] ax = 0 -> true; + [down] ax = 0 -> true; + [stay] ax = 0 -> true; + +endmodule + +rewards + [up] true : 1; + [down] true : 1; + [stay] true : 1; +endrewards + +label "goal" = x=maxX; +label "Crash" = collision; \ No newline at end of file diff --git a/experiment/ac-imdp.prism b/experiment/ac-imdp.prism new file mode 100644 index 0000000000..baa395164f --- /dev/null +++ b/experiment/ac-imdp.prism @@ -0,0 +1,54 @@ +mdp + + +const int maxX = 6;//10; +const int maxY = 5;//4; +const double r=0.8; //= 0.820795462532;// = 0.5; // pilot response factor +const double e1 = 0.1; +const double p=0.25;// = 0.19; // prob of adversary moving up or down, ensure 2p <= 1 +const double e2=0.01; + + +formula xclose = (x-ax >= 0 & x-ax < 3) | (ax-x >= 0 & ax-x < 3); +formula yclose = (y-ay >= 0 & y-ay < 2) | (ay-y >= 0 & ay-y < 2); +formula collision = xclose & yclose; + +module aircraft + + x : [0..maxX] init 0; + y : [0..maxY] init 1; + + + [down] x < maxX -> [r-e1,r+e1] : (y'=max(y-1,0)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [up] x < maxX -> [r-e1,r+e1] : (y'=min(y+1,maxY)) & (x'=x+1) + [1-r-e1,1-r+e1] : (y'=y) & (x'=x+1); + [stay] x < maxX -> (y'=y) & (x'=x+1); + + [down] x = maxX -> true; + [up] x = maxX -> true; + [stay] x = maxX -> true; + +endmodule + + +module adversary + + ax : [0..maxX] init maxX; + ay : [0..maxY] init 1; + + [up] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + p/2: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/2:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [down] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + p/2: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/2:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [stay] ax > 0 -> p : (ay'=max(ay-1,0)) & (ax'=ax-1) + p : (ay'=min(ay+1,maxY)) & (ax'=ax-1) + p/2: (ay'=min(ay+2,maxY)) & (ax'=ax-1) + p/2:(ay'=min(ay+2,maxY)) & (ax'=max(ax-2,0)) + (1-3*p) : (ay'=ay) & (ax'=ax-1); + [up] ax = 0 -> true; + [down] ax = 0 -> true; + [stay] ax = 0 -> true; + +endmodule + +rewards + [up] true : 1; + [down] true : 1; + [stay] true : 1; +endrewards + +label "goal" = x=maxX; +label "Crash" = collision; \ No newline at end of file diff --git a/experiment/ad-6x6-10.prism b/experiment/ad-6x6-10.prism new file mode 100644 index 0000000000..0318c48451 --- /dev/null +++ b/experiment/ad-6x6-10.prism @@ -0,0 +1,80 @@ +mdp + +// Model parameters +const double p = 0.1; // Mean disturbance probability +const double e = 0.05; // Epistemic uncertainty +formula a = x * e; // Epistemic uncertainty grows with x-coordinate + +const int M = 8; // Environment width +const int N = 8; // Environment height + +const double eps = 0.0001; // Lower bound for probability ranges + +// Goal +formula goal = x = 1 & y = N; + +// Obstacles +// Obstacles +formula crashed = (x = 2 & y = 3) + | (x = 3 & y = 3) + | (x = 3 & y = 4) + | (x = 2 & y = 2) + | (x = 4 & y = 1) + | (x = 5 & y = 3) // new + | (x = 6 & y = 2) // new + | (x = 7 & y = 5) // new + | (x = 4 & y = 6) // new + | (x = 2 & y = 7); // new + + +// UAV behaviour +module env + + x : [1..M] init 1; + y : [1..N] init 1; + + [up] !crashed & y < N -> [max(eps,1-4*(p+a)), min(1-4*(p-a),1)] : (y'=min(y+1,N)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=max(x-1,1)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+1,N)) & (x'=max(x-2,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+1,N)) & (x'=max(x+2,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=max(x-2,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=max(x+2,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=max(x-2,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=max(x+2,1)); + + [right] !crashed & x < M -> [max(eps,1-4*(p+a)), min(1-4*(p-a),1)] : (x'=min(x+1,M)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) + + [max(eps,p-a), min(p+a,1)] : true + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=max(x+1,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (x'=max(x-2,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=min(x+2,M)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (x'=max(x-2,1)) & (y'=min(y+1,N)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=max(y-1,N)) & (x'=min(x+1,M)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (x'=max(x-2,1)) & (y'=max(y-1,1)); + + [left] !crashed & x > 1 -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (x'=max(x-1,1)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=max(x-1,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (x'=min(x+2,M)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (y'=min(y+2,N)) & (x'=max(x-2,1)) + + [max(eps,(p-a)/6), min((p+a)/6,1)]: (x'=min(x+2,M)) & (y'=min(y+1,N)) + + [max(eps,(p-a)/6), min((p+a)/6,1)] : (x'=max(x-1,1)) & (y'=min(y+2,N)) // Probabilities to get pushed by wind + + [max(eps,(p-a)/6), min((p+a)/6,1)] : (x'=min(x+1,M)) & (y' = min(y+2,N)); + +endmodule + + +rewards + [up] true : 1; + [right] true: 1; + [left] true : 1; +endrewards + +// Labelling +label "Crash" = crashed; +label "goal" = goal; \ No newline at end of file diff --git a/experiment/ad-6x6-6.prism b/experiment/ad-6x6-6.prism new file mode 100644 index 0000000000..7b0e6cd9c2 --- /dev/null +++ b/experiment/ad-6x6-6.prism @@ -0,0 +1,68 @@ +mdp + +// Model parameters +const double p = 0.1; // Mean disturbance probability +const double e = 0.05; // Epistemic uncertainty +formula a = x * e; // Epistemic uncertainty grows with x-coordinate + +const int M = 8; // Environment width +const int N = 8; // Environment height + +const double eps = 0.0001; // Lower bound for probability ranges + +// Goal +formula goal = x = 1 & y = N; + +// Obstacles +// Obstacles +formula crashed = (x = 2 & y = 3) + | (x = 3 & y = 3) + | (x = 3 & y = 4) + | (x = 2 & y = 2) + | (x = 4 & y = 1) + | (x = 5 & y = 3) // new + | (x = 6 & y = 2) // new + | (x = 7 & y = 5) // new + | (x = 4 & y = 6) // new + | (x = 2 & y = 7); // new + + +// UAV behaviour +module env + + x : [1..M] init 1; + y : [1..N] init 1; + + [up] !crashed & y < N -> [max(eps,1-4*(p+a)), min(1-4*(p-a),1)] : (y'=min(y+1,N)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=max(x-1,1)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true + + [max(eps,(p-a)/2), min((p+a)/2,1)]: (y'=min(y+1,N)) & (x'=max(x-2,1)) + + [max(eps,(p-a)/2), min((p+a)/2,1)]: (y'=min(y+1,N)) & (x'=max(x+2,1)) ; + + [right] !crashed & x < M -> [max(eps,1-4*(p+a)), min(1-4*(p-a),1)] : (x'=min(x+1,M)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) + + [max(eps,p-a), min(p+a,1)] : true + + [max(eps,(p-a)/2), min((p+a)/2,1)]: (y'=min(y+2,N)) & (x'=max(x+1,1)) + + [max(eps,(p-a)/2), min((p+a)/2,1)]: (x'=max(x-2,1)); + + [left] !crashed & x > 1 -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (x'=max(x-1,1)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true + + [max(eps,(p-a)/2), min((p+a)/2,1)]: (y'=min(y+2,N)) & (x'=max(x-1,1)) + + [max(eps,(p-a)/2), min((p+a)/2,1)]: (x'=min(x+2,M)); + +endmodule + + +rewards + [up] true : 1; + [right] true: 1; + [left] true : 1; +endrewards + +// Labelling +label "Crash" = crashed; +label "goal" = goal; \ No newline at end of file diff --git a/experiment/ad-6x6-og.prism b/experiment/ad-6x6-og.prism new file mode 100644 index 0000000000..bfbcda5747 --- /dev/null +++ b/experiment/ad-6x6-og.prism @@ -0,0 +1,62 @@ +mdp + +// Model parameters +const double p = 0.1; // Mean disturbance probability +const double e = 0.05; // Epistemic uncertainty +formula a = x * e; // Epistemic uncertainty grows with x-coordinate + +const int M = 8; // Environment width +const int N = 8; // Environment height + +const double eps = 0.0001; // Lower bound for probability ranges + +// Goal +formula goal = x = 1 & y = N; + +// Obstacles +// Obstacles +formula crashed = (x = 2 & y = 3) + | (x = 3 & y = 3) + | (x = 3 & y = 4) + | (x = 2 & y = 2) + | (x = 4 & y = 1) + | (x = 5 & y = 3) // new + | (x = 6 & y = 2) // new + | (x = 7 & y = 5) // new + | (x = 4 & y = 6) // new + | (x = 2 & y = 7); // new + + +// UAV behaviour +module env + + x : [1..M] init 1; + y : [1..N] init 1; + + [up] !crashed & y < N -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (y'=min(y+1,N)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=max(x-1,1)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (y'=min(y+1,N)) & (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true; + + [right] !crashed & x < M -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (x'=min(x+1,M)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) + + [max(eps,p-a), min(p+a,1)] : true; + + [left] !crashed & x > 1 -> [max(eps,1-3*(p+a)), min(1-3*(p-a),1)] : (x'=max(x-1,1)) // Probability to move in intended direction + + [max(eps,p-a), min(p+a,1)] : (x'=max(x-1,1)) & (y'=min(y+1,N)) // Probabilities to get pushed by wind + + [max(eps,p-a), min(p+a,1)] : (x'=min(x+1,M)) + + [max(eps,p-a), min(p+a,1)] : true; + +endmodule + + +rewards + [up] true : 1; + [right] true: 1; + [left] true : 1; +endrewards + +// Labelling +label "Crash" = crashed; +label "goal" = goal; \ No newline at end of file diff --git a/experiment/ad-running.prism b/experiment/ad-running.prism new file mode 100644 index 0000000000..a64a2aa96e --- /dev/null +++ b/experiment/ad-running.prism @@ -0,0 +1,48 @@ +mdp + +// Model parameters +const double p = 0.1; // Mean disturbance probability +const double e = 0.05; // Epistemic uncertainty + +// Goal +formula goal = (s=2); + +// Obstacles +formula crashed = (s = 1); + +// UAV behaviour +module env + + s : [0..5] init 0; + + // s = 0 + + [right] s = 0 -> [0.5, 0.75] : (s'=1) + [0.4, 0.5] : (s'=4) + [0.05, 0.1] : (s'=0); + [down] s = 0 -> [0.6, 0.8] : (s'=3) + [0.35, 0.45] : (s'=4); + + // s = 1 + [crash] crashed -> true; + + // s = 2 + [done] goal -> true; + + // s = 3 + [right] s = 3 -> [0.5, 0.75] : (s'=4) + [0.25, 0.5] : (s'=1); + + // s = 4 + [up] s = 4 -> [0.5, 0.75] : (s' = 1) + [0.25, 0.5] : (s' = 2); + [right] s = 4 -> [0.5, 0.75] : (s'=5) + [0.25, 0.5] : (s' = 2); + + // s = 5 + [up] s = 5 -> [0.5, 0.75] : (s' = 2) + [0.25, 0.5]: (s' = 5); +endmodule + +rewards + [up] true : 1; + [right] true : 1; + [down] true : 1; +endrewards + +// Labelling +label "Crash" = crashed; +label "goal" = goal; \ No newline at end of file diff --git a/experiment/ov-5x5.prism b/experiment/ov-5x5.prism new file mode 100644 index 0000000000..f9fddd9aa9 --- /dev/null +++ b/experiment/ov-5x5.prism @@ -0,0 +1,86 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 5; // grid size: 0..N-1 in both x and y +const int K = 1000; // # of intermediate sub-steps per move +const double p = 0.8; // intended-direction probability +const double e = 0.05; // slip‐interval half-width + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +formula hole = (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1); + +formula goal = (x=4 & y=4); +formula terminal = hole | goal; + +//─── MODULE ──────────────────────────────────────────────────────────────────── +module frozenlake + + // “true” state + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + // internal bookkeeping for a “multi-step” move + tx : [0..N-1] init 0; // target column + ty : [0..N-1] init 0; // target row + step: [0..K] init 0; // current sub-step (0 = ready to pick a direction) + + //── Initial direction choice (step=0) ──────────────────────────────────────── + [north] step=0 & !terminal -> + // intended north + [p-e, p+e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + // slip west + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + // slip east + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + // slip south + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1); + + [south] step=0 & !terminal -> + [p-e, p+e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1); + + [east] step=0 & !terminal -> + [p-e, p+e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1); + + [west] step=0 & !terminal -> + [p-e, p+e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1); + + //── Substep “in-flight” transitions ───────────────────────────────────────── + // for 1 ≤ step < K, only one action: advance sub-step + [move] step>0 & step 1.0 : (step'=step+1); + + // at step=K commit the move into (x,y) and reset + [move] step=K -> 1.0 : (x'=tx) & (y'=ty) & (step'=0); + + //── Terminal self-loops ───────────────────────────────────────────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y) & (step'=0); + [done] goal & step = 0 -> true; + +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0) & step=0; +label "Crash" = hole; +label "goal" = goal & step=0; +label "safe" = !hole & !goal; + +//─── REWARDS ───────────────────────────────────────────────────────────────── +rewards + // count 1 reward per *grid-to-grid* move (i.e. when you pick a direction at step=0) + [north] step=0 & !terminal : 1; + [south] step=0 & !terminal : 1; + [east] step=0 & !terminal : 1; + [west] step=0 & !terminal : 1; +endrewards diff --git a/experiment/ov-6x6.prism b/experiment/ov-6x6.prism new file mode 100644 index 0000000000..80f19ff722 --- /dev/null +++ b/experiment/ov-6x6.prism @@ -0,0 +1,86 @@ +mdp + +//─── PARAMETERS ──────────────────────────────────────────────────────────────── +const int N = 6; // grid size: 0..N-1 in both x and y +const int K = 1000; // # of intermediate sub-steps per move +const double p = 0.8; // intended-direction probability +const double e = 0.05; // slip‐interval half-width + +//─── HOLES & GOAL ────────────────────────────────────────────────────────────── +formula hole = (x=1 & y=0) + | (x=1 & y=3) + | (x=2 & y=4) + | (x=3 & y=2) + | (x=4 & y=1) + | (x=4 & y=4); +formula goal = (x=5 & y=5); +formula terminal = hole | goal; + +//─── MODULE ──────────────────────────────────────────────────────────────────── +module frozenlake + + // “true” state + x : [0..N-1] init 0; // column + y : [0..N-1] init 0; // row + + // internal bookkeeping for a “multi-step” move + tx : [0..N-1] init 0; // target column + ty : [0..N-1] init 0; // target row + step: [0..K] init 0; // current sub-step (0 = ready to pick a direction) + + //── Initial direction choice (step=0) ──────────────────────────────────────── + [north] step=0 & !terminal -> + // intended north + [p-e, p+e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + // slip west + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + // slip east + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + // slip south + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1); + + [south] step=0 & !terminal -> + [p-e, p+e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1); + + [east] step=0 & !terminal -> + [p-e, p+e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1); + + [west] step=0 & !terminal -> + [p-e, p+e] : (tx'=max(x-1,0)) & (ty'=y) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=max(y-1,0)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=x) & (ty'=min(y+1,N-1)) & (step'=1) + + [(1-p)/3 - e, (1-p)/3 + e] : (tx'=min(x+1,N-1)) & (ty'=y) & (step'=1); + + //── Substep “in-flight” transitions ───────────────────────────────────────── + // for 1 ≤ step < K, only one action: advance sub-step + [move] step>0 & step 1.0 : (step'=step+1); + + // at step=K commit the move into (x,y) and reset + [move] step=K -> 1.0 : (x'=tx) & (y'=ty) & (step'=0); + + //── Terminal self-loops ───────────────────────────────────────────────────── + [getTrap] terminal -> 1.0 : (x'=x) & (y'=y) & (step'=0); + [done] goal & step = 0 -> true; + +endmodule + +//─── LABELS ─────────────────────────────────────────────────────────────────── +label "start" = (x=0 & y=0) & step=0; +label "Crash" = hole; +label "goal" = goal & step=0; +label "safe" = !hole & !goal; + +//─── REWARDS ───────────────────────────────────────────────────────────────── +rewards + // count 1 reward per *grid-to-grid* move (i.e. when you pick a direction at step=0) + [north] step=0 & !terminal : 1; + [south] step=0 & !terminal : 1; + [east] step=0 & !terminal : 1; + [west] step=0 & !terminal : 1; +endrewards diff --git a/experiment/re.prism b/experiment/re.prism new file mode 100644 index 0000000000..3090821548 --- /dev/null +++ b/experiment/re.prism @@ -0,0 +1,27 @@ +mdp + +const double e = 0.1; + +module OneOut_allLoPositive + // States: 0 initial; 1 goes to goal; 2 goes to sink; 3 goal; 4 sink + s : [0..3] init 0; + + // s = 0 + [m] s=0 -> [0.9 - e, 0.9 + e] : (s'=1) + [0.1 - e, 0.1 + e] : (s' = 2); + [f] s=0 -> [0.78-e,0.78+e] : (s'=3) + [0.22-e, 0.22+e] : (s' = 2); + + // s = 1 + + [m] s = 1 -> [0.9 - e, 0.9 + e] : (s'=3) + [0.1 - e, 0.1 + e] : (s' = 2); + + [trapped] s=2 -> (s'=2); // trap + [done] s=3 -> (s'=3); // goal +endmodule + +rewards + [m] true : 1; + [f] true : 1; +endrewards + +label "goal" = s=3; +label "Crash" = s=2; diff --git a/experiment/sav-imdp.prism b/experiment/sav-imdp.prism new file mode 100644 index 0000000000..dd5662ac10 --- /dev/null +++ b/experiment/sav-imdp.prism @@ -0,0 +1,61 @@ +// GRID WORLD MODEL OF A SEMIAUTONOMOUS EXPLORING ROBOT +// Sebastian Junges, RWTH Aachen University +// As described in +// Junges, Jansen, Dehnert, Topcu, Katoen: +// Safety Constrained Reinforcement Learning +// Proc. of TACAS’16 + +mdp + +//PARAMETERS +//The difference of the reliability of the channels between the worst and at the best position +const double pLDiff=0.7; +const double pHDiff=0.1; +const double u=0.08; +//Scaling factor for the minimum reliability of the channels +const double pL=0.2; +const double pH=0.3; + +//CONSTANTS +//The minimum reliablities +const double pLMin=pL*(1-pLDiff); +const double pHMin= pH*(1-pHDiff); + +// Grid size +const int Xsize = 5; +const int Ysize = 5; +// Number of tries before an error +const int MAXTRIES = 2; +// Ball within the robot has to move. +const int B = 2; + + +formula T = (xLoc = Xsize & yLoc = Ysize); + + +module robot + xLoc : [1..Ysize] init 1; + yLoc : [1..Xsize] init 1; + unreported : [0..B] init 0; + hasSendNow : bool init false; + tries : [0..MAXTRIES] init 0; + + [up] xLoc < Xsize & !T & hasSendNow -> 1:(xLoc'=xLoc+1) & (unreported' = 0) & (hasSendNow'=false); + [up] xLoc < Xsize & !T & !hasSendNow -> 1:(xLoc'=xLoc+1) & (unreported'=min(unreported+1, B)); + [right] yLoc < Ysize & !T & hasSendNow -> 1:(yLoc'=yLoc+1) & (unreported' = 0)& (hasSendNow'=false); + [right] yLoc < Ysize & !T & !hasSendNow -> 1:(yLoc'=yLoc+1) & (unreported'=min(unreported+1,B)); + [sendL] !hasSendNow & !T & tries < MAXTRIES -> [pLMin + pLDiff * xLoc/Xsize-u,pLMin + pLDiff * xLoc/Xsize+u]:(hasSendNow'=true) & (tries'=0) + [1 - pLMin - pLDiff * xLoc/Xsize-u,1 - pLMin - pLDiff * xLoc/Xsize+u]: (tries'=tries+1); + [sendH] !hasSendNow & !T & tries < MAXTRIES -> [pHMin + pHDiff * yLoc/Ysize-u,pHMin + pHDiff * yLoc/Ysize+u]:(hasSendNow'=true) & (tries'=0) + [1 - pHMin - pHDiff * yLoc/Ysize-u,1 - pHMin - pHDiff * yLoc/Ysize+u]: (tries'=tries+1); + [done] T -> 1:true; +endmodule + +rewards + [up] true: 0.03; + [right] true: 0.03; + [sendL] true: max(10, min(11 + xLoc - yLoc, 20)); + [sendH] true: min(13 + xLoc + yLoc, 24); +endrewards + + +label "goal" = T; +label "Crash" = unreported=B; \ No newline at end of file diff --git a/experiment/wh.prism b/experiment/wh.prism new file mode 100644 index 0000000000..3a32b446f6 --- /dev/null +++ b/experiment/wh.prism @@ -0,0 +1,119 @@ +mdp + +//─── PARAMETERS ────────────────────────────────────────────────────────────── +const int K = 250; // # of sub‐steps per move +const double p = 0.7; // nominal success prob. +const double e = 0.01; // uncertainty radius + +//─── STATE ──────────────────────────────────────────────────────────────────── +module graph_imdp + s : [0..14] init 0; // which node + step : [0..K] init 0; // progress along chosen edge + + //─────────────────────────────────────────────────────────────────────────── + // EAST moves (horizontal rightwards) + //────────── sub‐steps ───────────────────────────────────────────────────── + [east] (step < K) & (s=0|s=3|s=4|s=8|s=11|s=12) + -> 1 : (step' = step + 1); + + //────────── final jump ───────────────────────────────────────────────────── + [east] (step = K) & (s=0) + -> [p-e, p+e]:(s'=1)&(step'=0) + + [1-p-e, 1-p+e]:(s'=0)&(step'=step); + [east] (step = K) & (s=2) + -> [p-2*e, p+2*e]:(s'=1)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=0)&(step'=step); + [east] (step = K) & (s=3) + -> [p-e, p+e]:(s'=2)&(step'=0) + + [1-p-e, 1-p+e]:(s'=3)&(step'=step); + [east] (step = K) & (s=4) + -> [p-e, p+e]:(s'=5)&(step'=0) + + [1-p-e, 1-p+e]:(s'=4)&(step'=step); + [east] (step = K) & (s=8) + -> [p-e, p+e]:(s'=9)&(step'=0) + + [1-p-e, 1-p+e]:(s'=8)&(step'=step); + [east] (step = K) & (s=11) + -> [p-e, p+e]:(s'=12)&(step'=0) + + [1-p-e, 1-p+e]:(s'=11)&(step'=step); + [east] (step = K) & (s=12) + -> [p-e, p+e]:(s'=13)&(step'=0) + + [1-p-e, 1-p+e]:(s'=12)&(step'=step); + [east] (step = K) & (s=13) + -> [p-e, p+e]:(s'=14)&(step'=0) + + [1-p-e, 1-p+e]:(s'=13)&(step'=step); + + //─────────────────────────────────────────────────────────────────────────── + // SOUTH moves (vertical downwards) + [south] (step < K) & (s=0|s=1|s=2|s=3|s=4|s=5|s=6|s=7|s=8|s=9) + -> 1 : (step' = step + 1); + + [south] (step = K) & (s=0) + -> [p-e, p+e]:(s'=3)&(step'=0) + + [1-p-e, 1-p+e]:(s'=0)&(step'=step); + [south] (step = K) & (s=1) + -> [p-e, p+e]:(s'=2)&(step'=0) + + [1-p-e, 1-p+e]:(s'=1)&(step'=step); + [south] (step = K) & (s=2) + -> [p-e, p+e]:(s'=5)&(step'=0) + + [1-p-e, 1-p+e]:(s'=2)&(step'=step); + [south] (step = K) & (s=3) + -> [p-e, p+e]:(s'=4)&(step'=0) + + [1-p-e, 1-p+e]:(s'=3)&(step'=step); + [south] (step = K) & (s=4) + -> [p-e, p+e]:(s'=8)&(step'=0) + + [1-p-e, 1-p+e]:(s'=4)&(step'=step); + [south] (step = K) & (s=5) + -> [p-e, p+e]:(s'=9)&(step'=0) + + [1-p-e, 1-p+e]:(s'=5)&(step'=step); + [south] (step = K) & (s=6) + -> [p-2*e, p+2*e]:(s'=7)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=6)&(step'=step); + [south] (step = K) & (s=7) + -> [p-2*e, p+2*e]:(s'=10)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=7)&(step'=step); + [south] (step = K) & (s=8) + -> [p-e, p+e]:(s'=11)&(step'=0) + + [1-p-e, 1-p+e]:(s'=8)&(step'=step); + [south] (step = K) & (s=9) + -> [p-e, p+e]:(s'=12)&(step'=0) + + [1-p-e, 1-p+e]:(s'=9)&(step'=step); + + //─────────────────────────────────────────────────────────────────────────── + // WEST moves (horizontal leftwards) + [west] (step < K) & (s=7) + -> 1 : (step' = step + 1); + [west] (step = K) & (s=7) + -> [p-2*e, p+2*e]:(s'=5)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=7)&(step'=step); + + [west] (step < K) & (s=10) + -> 1 : (step' = step + 1); + [west] (step = K) & (s=10) + -> [p-2*e, p+2*e]:(s'=9)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=10)&(step'=step); + + //─────────────────────────────────────────────────────────────────────────── + // EXIT moves (diagonal/termination from 10→14) + [exit] (step < K) & (s=10) + -> 1 : (step' = step + 1); + [exit] (step = K) & (s=10) + -> [p-2*e, p+2*e]:(s'=14)&(step'=0) + + [1-p-2*e, 1-p+2*e]:(s'=10)&(step'=step); + [exit] (step < K) & (s=13) + -> 1 : (step' = step + 1); + [exit] (step = K) & (s=13) + -> [p-e, p+e]:(s'=14)&(step'=0) + + [1-p-e, 1-p+e]:(s'=13)&(step'=step); + + // state 14 has no outgoing moves + [done] s = 14 & step = 0 -> true; +endmodule + + +label "goal" = (s = 14 & step = 0); + +rewards + [east] true : 1; + [west] true : 1; + [south] true : 1; +endrewards diff --git a/naive_e005.lp b/naive_e005.lp new file mode 100644 index 0000000000..8be37f13ba --- /dev/null +++ b/naive_e005.lp @@ -0,0 +1,36 @@ +\ LP format - for model browsing. Use MPS format to capture full model detail. +\ Signature: 0x4dfdf1b6b4a61f7c +Minimize + 0 mu[2] - eta-0-0 - eta-0-1 - eta-1-0 - eta-2-0 - eta-3-0 + 5 Constant +Subject To + v-target: mu[3] = 1 + v-no: mu[2] = 0 + state-0-choice-0-combination-0: mu[0] - 0.95 mu[1] - 0.05 mu[2] + + 1.01 eta-0-0 <= 1.01 + state-0-choice-0-combination-1: mu[0] - 0.85 mu[1] - 0.15 mu[2] + + 1.01 eta-0-0 <= 1.01 + state-0-choice-1-combination-0: mu[0] - 0.73 mu[3] - 0.27 mu[2] + + 1.01 eta-0-1 <= 1.01 + state-0-choice-1-combination-1: mu[0] - 0.83 mu[3] - 0.17 mu[2] + + 1.01 eta-0-1 <= 1.01 + state-1-choice-0-combination-0: mu[1] - 0.85 mu[3] - 0.15 mu[2] + + 1.01 eta-1-0 <= 1.01 + state-1-choice-0-combination-1: mu[1] - 0.95 mu[3] - 0.05 mu[2] + + 1.01 eta-1-0 <= 1.01 + state-2-choice-0-combination-0: 1.01 eta-2-0 <= 1.01 + state-3-choice-0-combination-0: 1.01 eta-3-0 <= 1.01 + actSel-0: eta-0-0 + eta-0-1 >= 1 + actSel-1: eta-1-0 >= 1 + actSel-2: eta-2-0 >= 1 + actSel-3: eta-3-0 >= 1 + multi-bound: mu[0] >= 0.65 +Bounds + mu[0] <= 1 + mu[1] <= 1 + mu[2] <= 1 + mu[3] <= 1 + mu[2] <= 1 + Constant = 1 +Binaries + eta-0-0 eta-0-1 eta-1-0 eta-2-0 eta-3-0 +End diff --git a/naive_e005_strat.txt b/naive_e005_strat.txt new file mode 100644 index 0000000000..ed12f595a2 --- /dev/null +++ b/naive_e005_strat.txt @@ -0,0 +1,4 @@ +0: m f +1: m +2: trapped +3: done \ No newline at end of file diff --git a/naive_e01.lp b/naive_e01.lp new file mode 100644 index 0000000000..68cc0898f2 --- /dev/null +++ b/naive_e01.lp @@ -0,0 +1,34 @@ +\ LP format - for model browsing. Use MPS format to capture full model detail. +\ Signature: 0x24c8caa659d02ef +Minimize + 0 mu[2] - eta-0-0 - eta-0-1 - eta-1-0 - eta-2-0 - eta-3-0 + 5 Constant +Subject To + v-target: mu[3] = 1 + v-no: mu[2] = 0 + state-0-choice-0-combination-0: mu[0] - mu[1] + 1.01 eta-0-0 <= 1.01 + state-0-choice-0-combination-1: mu[0] - 0.8 mu[1] - 0.2 mu[2] + + 1.01 eta-0-0 <= 1.01 + state-0-choice-1-combination-0: mu[0] - 0.68 mu[3] - 0.32 mu[2] + + 1.01 eta-0-1 <= 1.01 + state-0-choice-1-combination-1: mu[0] - 0.88 mu[3] - 0.12 mu[2] + + 1.01 eta-0-1 <= 1.01 + state-1-choice-0-combination-0: mu[1] - 0.8 mu[3] - 0.2 mu[2] + + 1.01 eta-1-0 <= 1.01 + state-1-choice-0-combination-1: mu[1] - mu[3] + 1.01 eta-1-0 <= 1.01 + state-2-choice-0-combination-0: 1.01 eta-2-0 <= 1.01 + state-3-choice-0-combination-0: 1.01 eta-3-0 <= 1.01 + actSel-0: eta-0-0 + eta-0-1 >= 1 + actSel-1: eta-1-0 >= 1 + actSel-2: eta-2-0 >= 1 + actSel-3: eta-3-0 >= 1 + multi-bound: mu[0] >= 0.65 +Bounds + mu[0] <= 1 + mu[1] <= 1 + mu[2] <= 1 + mu[3] <= 1 + mu[2] <= 1 + Constant = 1 +Binaries + eta-0-0 eta-0-1 eta-1-0 eta-2-0 eta-3-0 +End diff --git a/naive_e01_strat.txt b/naive_e01_strat.txt new file mode 100644 index 0000000000..263c6ef829 --- /dev/null +++ b/naive_e01_strat.txt @@ -0,0 +1,4 @@ +0: f +1: m +2: trapped +3: done \ No newline at end of file diff --git a/outgoing/test1.prism b/outgoing/test1.prism new file mode 100644 index 0000000000..4f617afcb7 --- /dev/null +++ b/outgoing/test1.prism @@ -0,0 +1,25 @@ +mdp + +module OneOut_allLoPositive + // States: 0 initial; 1 goes to goal; 2 goes to sink; 3 goal; 4 sink + s : [0..4] init 0; + + // Only one successor per action (prob must be 1 in any feasible assignment) + [a] s=0 -> [0.90,1.00] : (s'=1); + [b] s=0 -> [0.90,1.00] : (s'=2); + + // Route to absorbing goal/sink + [t1] s=1 -> (s'=3); + [t2] s=2 -> (s'=4); + + [end1] s=3 -> (s'=3); // goal + [end2] s=4 -> (s'=4); // sink +endmodule + +rewards + [a] true : 1; + [b] true : 1; +endrewards + +label "goal" = s=3; +label "Crash" = s=4; diff --git a/outgoing/test10.prism b/outgoing/test10.prism new file mode 100644 index 0000000000..383a6e0ee0 --- /dev/null +++ b/outgoing/test10.prism @@ -0,0 +1,66 @@ +mdp + +module TenOut_allLoPositive + // States: 0 initial; 1..6 lead to goal; 7..10 lead to sink; 11 goal; 12 sink + s : [0..12] init 0; + + // -------- action a -------- + // lo(goal)=6*0.02=0.12, lo(sink)=4*0.03=0.12 → sum lo = 0.24 ≤ 1 + // hi(sink)=4*0.20 = 0.80 → Pmin(goal) ≥ max(sum_lo_goal, 1 - sum_hi_sink) + // = max(0.12, 1-0.80) = 0.20 + [a] s=0 -> + // 6 goal-ward successors + [0.02,0.25] : (s'=1) + + [0.02,0.25] : (s'=2) + + [0.02,0.25] : (s'=3) + + [0.02,0.25] : (s'=4) + + [0.02,0.25] : (s'=5) + + [0.02,0.25] : (s'=6) + + // 4 sink-ward successors + [0.03,0.20] : (s'=7) + + [0.03,0.20] : (s'=8) + + [0.03,0.20] : (s'=9) + + [0.03,0.20] : (s'=10); + + // -------- action b -------- + // lo(goal)=6*0.03=0.18, lo(sink)=4*0.02=0.08 → sum lo = 0.26 ≤ 1 + // hi(sink)=4*0.15=0.60 → Pmin(goal) ≥ max(0.18, 1-0.60)=0.40 + [b] s=0 -> + // 6 goal-ward successors + [0.03,0.25] : (s'=1) + + [0.03,0.25] : (s'=2) + + [0.03,0.25] : (s'=3) + + [0.03,0.25] : (s'=4) + + [0.03,0.25] : (s'=5) + + [0.03,0.25] : (s'=6) + + // 4 sink-ward successors + [0.02,0.15] : (s'=7) + + [0.02,0.15] : (s'=8) + + [0.02,0.15] : (s'=9) + + [0.02,0.15] : (s'=10); + + // Route successors + [t1] s=1 -> (s'=11); + [t1] s=2 -> (s'=11); + [t1] s=3 -> (s'=11); + [t1] s=4 -> (s'=11); + [t1] s=5 -> (s'=11); + [t1] s=6 -> (s'=11); + [t2] s=7 -> (s'=12); + [t2] s=8 -> (s'=12); + [t2] s=9 -> (s'=12); + [t2] s=10 -> (s'=12); + + // Absorbing goal/sink + [end1] s=11 -> (s'=11); + [end2] s=12 -> (s'=12); +endmodule + +rewards + [a] true : 1; + [b] true : 1; +endrewards + +label "goal" = s=11; +label "Crash" = s=12; + diff --git a/outgoing/test15.prism b/outgoing/test15.prism new file mode 100644 index 0000000000..aff36e510b --- /dev/null +++ b/outgoing/test15.prism @@ -0,0 +1,76 @@ +mdp + +module Fifteen + // 0 = initial; 1..15 = uncertain successors; 16 = goal; 17 = sink + s : [0..17] init 0; + + // ---- Action a: one heavy, two medium, rest small + // lo sum = 0.30 + 2*0.05 + 12*0.02 = 0.64 <= 1 + // hi sum = 0.60 + 2*0.25 + 12*0.12 = 2.54 >= 1 + [a] s=0 -> + [0.30,0.60] : (s'=1) + + [0.05,0.25] : (s'=2) + + [0.05,0.25] : (s'=3) + + [0.02,0.12] : (s'=4) + + [0.02,0.12] : (s'=5) + + [0.02,0.12] : (s'=6) + + [0.02,0.12] : (s'=7) + + [0.02,0.12] : (s'=8) + + [0.02,0.12] : (s'=9) + + [0.02,0.12] : (s'=10) + + [0.02,0.12] : (s'=11) + + [0.02,0.12] : (s'=12) + + [0.02,0.12] : (s'=13) + + [0.02,0.12] : (s'=14) + + [0.02,0.12] : (s'=15); + + // ---- Action b: two “heads” elsewhere, many smalls (different shape) + // lo sum = 2*0.12 + 13*0.01 = 0.37 <= 1 + // hi sum = 2*0.32 + 13*0.09 = 1.81 >= 1 + [b] s=0 -> + [0.01,0.09] : (s'=1) + + [0.01,0.09] : (s'=2) + + [0.01,0.09] : (s'=3) + + [0.01,0.09] : (s'=4) + + [0.01,0.09] : (s'=5) + + [0.01,0.09] : (s'=6) + + [0.01,0.09] : (s'=7) + + [0.12,0.32] : (s'=8) + // head #1 placed away from action a's heavy + [0.12,0.32] : (s'=9) + // head #2 + [0.01,0.09] : (s'=10) + + [0.01,0.09] : (s'=11) + + [0.01,0.09] : (s'=12) + + [0.01,0.09] : (s'=13) + + [0.01,0.09] : (s'=14) + + [0.01,0.09] : (s'=15); + + // successors: 1..6 -> goal, 7..15 -> sink + [t1] s=1 -> (s'=16); + [t1] s=2 -> (s'=16); + [t1] s=3 -> (s'=16); + [t1] s=4 -> (s'=16); + [t1] s=5 -> (s'=16); + [t1] s=6 -> (s'=16); + + [t2] s=7 -> (s'=17); + [t2] s=8 -> (s'=17); + [t2] s=9 -> (s'=17); + [t2] s=10 -> (s'=17); + [t2] s=11 -> (s'=17); + [t2] s=12 -> (s'=17); + [t2] s=13 -> (s'=17); + [t2] s=14 -> (s'=17); + [t2] s=15 -> (s'=17); + + // absorbing goal/sink + [end1] s=16 -> (s'=16); + [end2] s=17 -> (s'=17); +endmodule + +label "goal" = s=16; +label "Crash" = s=17; + +rewards + [a] true : 1; + [b] true : 1; +endrewards diff --git a/outgoing/test20.prism b/outgoing/test20.prism new file mode 100644 index 0000000000..7ce414e10f --- /dev/null +++ b/outgoing/test20.prism @@ -0,0 +1,77 @@ +mdp + +module TwentyOut_allLoPositive + // 0 initial; 1..12 to goal; 13..20 to sink; 21 goal; 22 sink + s : [0..22] init 0; + + // --- action a --- + // lo(goal)=12*0.01=0.12; hi(sink)=8*0.08=0.64 → Pmin(goal) ≥ max(0.12, 0.36)=0.36 + [a] s=0 -> + // 12 goal-ward + [0.01,0.10] : (s'=1) + + [0.01,0.10] : (s'=2) + + [0.01,0.10] : (s'=3) + + [0.01,0.10] : (s'=4) + + [0.01,0.10] : (s'=5) + + [0.01,0.10] : (s'=6) + + [0.01,0.10] : (s'=7) + + [0.01,0.10] : (s'=8) + + [0.01,0.10] : (s'=9) + + [0.01,0.10] : (s'=10) + + [0.01,0.10] : (s'=11) + + [0.01,0.10] : (s'=12) + + // 8 sink-ward + [0.02,0.08] : (s'=13) + + [0.02,0.08] : (s'=14) + + [0.02,0.08] : (s'=15) + + [0.02,0.08] : (s'=16) + + [0.02,0.08] : (s'=17) + + [0.02,0.08] : (s'=18) + + [0.02,0.08] : (s'=19) + + [0.02,0.08] : (s'=20); + + // --- action b --- + // lo(goal)=12*0.015=0.18; hi(sink)=8*0.05=0.40 → Pmin(goal) ≥ max(0.18, 0.60)=0.60 + [b] s=0 -> + // 12 goal-ward + [0.015,0.11] : (s'=1) + + [0.015,0.11] : (s'=2) + + [0.015,0.11] : (s'=3) + + [0.015,0.11] : (s'=4) + + [0.015,0.11] : (s'=5) + + [0.015,0.11] : (s'=6) + + [0.015,0.11] : (s'=7) + + [0.015,0.11] : (s'=8) + + [0.015,0.11] : (s'=9) + + [0.015,0.11] : (s'=10) + + [0.015,0.11] : (s'=11) + + [0.015,0.11] : (s'=12) + + // 8 sink-ward + [0.01,0.05] : (s'=13) + + [0.01,0.05] : (s'=14) + + [0.01,0.05] : (s'=15) + + [0.01,0.05] : (s'=16) + + [0.01,0.05] : (s'=17) + + [0.01,0.05] : (s'=18) + + [0.01,0.05] : (s'=19) + + [0.01,0.05] : (s'=20); + + // Route successors + [t1] s=1 -> (s'=21); [t1] s=2 -> (s'=21); [t1] s=3 -> (s'=21); [t1] s=4 -> (s'=21); + [t1] s=5 -> (s'=21); [t1] s=6 -> (s'=21); [t1] s=7 -> (s'=21); [t1] s=8 -> (s'=21); + [t1] s=9 -> (s'=21); [t1] s=10 -> (s'=21); [t1] s=11 -> (s'=21); [t1] s=12 -> (s'=21); + [t2] s=13 -> (s'=22); [t2] s=14 -> (s'=22); [t2] s=15 -> (s'=22); [t2] s=16 -> (s'=22); + [t2] s=17 -> (s'=22); [t2] s=18 -> (s'=22); [t2] s=19 -> (s'=22); [t2] s=20 -> (s'=22); + + // Absorbing + [end1] s=21 -> (s'=21); + [end2] s=22 -> (s'=22); +endmodule + +rewards + [a] true : 1; + [b] true : 1; +endrewards + +label "goal" = s=21; +label "Crash" = s=22; diff --git a/outgoing/test3.prism b/outgoing/test3.prism new file mode 100644 index 0000000000..f88940dab4 --- /dev/null +++ b/outgoing/test3.prism @@ -0,0 +1,37 @@ +mdp + +module ThreeOut_allLoPositive + // 0 initial; 1,2 route to goal; 3 routes to sink; 4 goal; 5 sink + s : [0..5] init 0; + + // --- action a --- + // lo(goal)=0.05+0.05=0.10; hi(sink)=0.60 -> Pmin(goal) ≥ max(0.10, 1-0.60=0.40)=0.40 + [a] s=0 -> + [0.05,0.50] : (s'=1) + + [0.05,0.50] : (s'=2) + + [0.02,0.60] : (s'=3); + + // --- action b --- + // lo(goal)=0.06+0.06=0.12; hi(sink)=0.30 -> Pmin(goal) ≥ max(0.12, 0.70)=0.70 + [b] s=0 -> + [0.06,0.60] : (s'=1) + + [0.06,0.60] : (s'=2) + + [0.02,0.30] : (s'=3); + + // Route successors + [] s=1 -> (s'=4); + [] s=2 -> (s'=4); + [] s=3 -> (s'=5); + + // Absorbing + [] s=4 -> (s'=4); + [] s=5 -> (s'=5); +endmodule + +rewards + [a] true : 1; + [b] true : 1; +endrewards + +label "goal" = s=4; +label "Crash" = s=5; diff --git a/outgoing/test5.prism b/outgoing/test5.prism new file mode 100644 index 0000000000..65aadab3cb --- /dev/null +++ b/outgoing/test5.prism @@ -0,0 +1,43 @@ +mdp + +module FiveOut_allLoPositive + // States: 0 initial; 1..3 goal-ward; 4..5 sink-ward; 6 goal; 7 sink + s : [0..7] init 0; + + // Action a: max sink mass = 0.90 ⇒ Pmin(goal) ≥ 0.10 + [a] s=0 -> + [0.02,0.50] : (s'=1) + // goal + [0.02,0.30] : (s'=2) + // goal + [0.02,0.30] : (s'=3) + // goal + [0.10,0.45] : (s'=4) + // sink + [0.10,0.45] : (s'=5); // sink + // Feasible: sum lo = 0.26 ≤ 1 ≤ sum hi = 2.00 + + // Action b: max sink mass = 0.75 ⇒ Pmin(goal) ≥ 0.25 + [b] s=0 -> + [0.05,0.35] : (s'=1) + // goal + [0.05,0.30] : (s'=2) + // goal + [0.05,0.30] : (s'=3) + // goal + [0.05,0.35] : (s'=4) + // sink + [0.05,0.40] : (s'=5); // sink + // Feasible: sum lo = 0.25 ≤ 1 ≤ sum hi = 1.70 + + // Route successors + [t1] s=1 -> (s'=6); + [t1] s=2 -> (s'=6); + [t1] s=3 -> (s'=6); + [t2] s=4 -> (s'=7); + [t2] s=5 -> (s'=7); + + // Absorbing goal/sink + [end1] s=6 -> (s'=6); + [end2] s=7 -> (s'=7); +endmodule + +label "goal" = s=6; +label "Crash" = s=7; + +rewards + [a] true : 1; + [b] true : 1; +endrewards diff --git a/outgoing/test8.prism b/outgoing/test8.prism new file mode 100644 index 0000000000..db1454b96a --- /dev/null +++ b/outgoing/test8.prism @@ -0,0 +1,52 @@ +mdp + +module EightOut_allLoPositive + // 0 initial; 1..5 to goal; 6..8 to sink; 9 goal; 10 sink + s : [0..10] init 0; + + // --- action a --- + // lo(goal)=5*0.02=0.10; hi(sink)=3*0.25=0.75 → Pmin(goal) ≥ max(0.10, 0.25)=0.25 + [a] s=0 -> + [0.02,0.20] : (s'=1) + + [0.02,0.20] : (s'=2) + + [0.02,0.20] : (s'=3) + + [0.02,0.20] : (s'=4) + + [0.02,0.20] : (s'=5) + + [0.03,0.25] : (s'=6) + + [0.03,0.25] : (s'=7) + + [0.03,0.25] : (s'=8); + + // --- action b --- + // lo(goal)=5*0.03=0.15; hi(sink)=3*0.15=0.45 → Pmin(goal) ≥ max(0.15, 0.55)=0.55 + [b] s=0 -> + [0.03,0.22] : (s'=1) + + [0.03,0.22] : (s'=2) + + [0.03,0.22] : (s'=3) + + [0.03,0.22] : (s'=4) + + [0.03,0.22] : (s'=5) + + [0.02,0.15] : (s'=6) + + [0.02,0.15] : (s'=7) + + [0.02,0.15] : (s'=8); + + // Route successors + [t1] s=1 -> (s'=9); + [t1] s=2 -> (s'=9); + [t1] s=3 -> (s'=9); + [t1] s=4 -> (s'=9); + [t1] s=5 -> (s'=9); + [t2] s=6 -> (s'=10); + [t2] s=7 -> (s'=10); + [t2] s=8 -> (s'=10); + + // Absorbing + [end1] s=9 -> (s'=9); + [end2] s=10 -> (s'=10); +endmodule + +rewards + [a] true : 1; + [b] true : 1; +endrewards + +label "goal" = s=9; +label "Crash" = s=10; diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index 2f52ebdd29..3a50d9b407 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -30,10 +30,13 @@ import java.util.ArrayList; import java.util.BitSet; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.PrimitiveIterator; import java.util.Queue; @@ -626,8 +629,8 @@ public ModelCheckerResult computeReachRewards(IMDP imdp, MDPRewards imdp, MDPRewards mdpRewards, double bound) throws PrismException { - boolean value =true; - boolean min =true; + boolean value =false; + boolean min =false; boolean robust=true; if (value){ if (min){ @@ -667,7 +670,7 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew System.out.println(n); int sInit = imdp.getFirstInitialState(); - double BIG = 100.0; + double BIG = 10000.0; System.out.println(imdp.getLabelStates("goal")); BitSet targetS = imdp.getLabelStates("goal"); System.out.println("Hi: " + imdp.getInitialStates()); @@ -845,7 +848,11 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew m.setObjective(pen, GRB.MINIMIZE); m.setCallback(new trigger(m, 3600)); m.write("gurobi.lp"); + long timerGurobi = System.currentTimeMillis(); m.optimize(); + long afterGurobi = System.currentTimeMillis(); + long timeTake = afterGurobi - timerGurobi; + mainLog.println("Gurobi Solve time: " + timeTake); if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { @@ -871,6 +878,10 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew soln[s] = v.get(s).get(GRB.DoubleAttr.X); } + for (int s = 0; s < n; s++) { + mainLog.println("state: " + s + ", value: " + soln[s]); + } + int isMIP = m.get(GRB.IntAttr.IsMIP); // 1 => has integer vars int isQP = m.get(GRB.IntAttr.IsQP); // 1 => quadratic objective int isQCP = m.get(GRB.IntAttr.IsQCP); // 1 => quadratic constraints @@ -918,6 +929,45 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } } mainLog.println("Number of Permissive States: " + permC); + + int reachable = 0; + for (int s = 0; s < n; s++) { + if (soln[s] > 0.0){ + if (soln[s] <= bound){ + int numChoices = imdp.getNumChoices(s); + if (numChoices == 1){ + continue; + } else { + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + } + + + } + } + + mainLog.println("Total number of reachable permissable state-action pairs: " + reachable); + + + reachable = 0; + for (int s = 0; s < n; s++) { + if (soln[s] >= 0.0){ + if (soln[s] <= bound){ + int numChoices = imdp.getNumChoices(s); + + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + + + + } + } + + mainLog.println("Total number of reachable state-action pairs: " + reachable); // Clean up m.dispose(); env.dispose(); @@ -928,21 +978,27 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew // Multi-strategy under best assumption mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); - - try { + double tol = 1e-9; + + try { // create environment & model + System.out.println("Im here"); GRBEnv env = new GRBEnv("gurobi.log"); + env.set(GRB.IntParam.OutputFlag, 0); + env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit + env.set(GRB.IntParam.Threads, 0); // (optional) use all cores env.set(GRB.IntParam.OutputFlag, 1); + env.set(GRB.IntParam.Cuts, 2); GRBModel m = new GRBModel(env); - m.set(GRB.IntParam.NonConvex, 2); + // --- 1) Value‐function vars v[s] --- Map v = new HashMap<>(); - for (int s = 0; s < n; s++) { - v.put(s, m.addVar(0.0,BIG, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); + for (int s = 0; s imdp, MDPRew Map eta = new HashMap<>(); Map> delta = new HashMap<>(); - for (int s = 0; s < n; s++) { + + for (int s = 0; s ()); - Iterator>> it = imdp.getTransitionsIterator(s,c); + eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); + // collect successors + bounds, and create delta vars + List tList = new ArrayList<>(); + List loList = new ArrayList<>(), hiList = new ArrayList<>(); + Iterator>> it = imdp.getTransitionsIterator(s, c); + List> li = new ArrayList<>(); while (it.hasNext()) { - Map.Entry> e = it.next(); + Map.Entry> e = it.next(); int t = e.getKey(); - Interval transition_val = e.getValue(); - transition_val.getLower(); - transition_val.getUpper(); + Interval w = e.getValue(); + li.add(w); + tList.add(t); + } + + System.out.println("tList: " + tList.toString()); + for (int i = 0; i < li.size(); i++) { + Interval w = li.get(i); + double lo = Math.min(w.getLower(), w.getUpper()); // normalize just in case + double hi = Math.max(w.getLower(), w.getUpper()); + loList.add(lo); + hiList.add(hi); + } + + + + + // Enumerate all vertices via "n-1 at bounds + 1 free" + + + List> result = new ArrayList<>(); + Set seen = new HashSet<>(); + for (int j = 0; j < tList.size(); j++) { + int freeState = tList.get(j); + List> verts = + findExtremeCombos(tList, loList, hiList, tol, freeState); // <-- new overload + for (Map combo : verts) { + String key = comboKey(combo, tList); + if (seen.add(key)) result.add(combo); // keep only novel vertices + } + } + + mainLog.println("State: " + s + ", Action: " + c); + + int count = 0; + for (Map combo : result) { + StringBuilder sb = new StringBuilder(); + GRBLinExpr expr = new GRBLinExpr(); + expr.addConstant(mdpRewards.getTransitionReward(s,c)); + for (int i = 0; i < tList.size(); i++) { + int t = tList.get(i); + double p = combo.get(t); + if (i > 0) sb.append(", "); + sb.append("state ").append(t).append(": ") + .append(String.format(Locale.US, "%.9f", p)); + expr.addTerm(p, v.get(t)); + } + // indicator-style big-M for the chosen (s,c) + expr.addConstant(-BIG); + expr.addTerm(+BIG, eta.get(sc)); + m.addConstr(v.get(s), GRB.GREATER_EQUAL, expr, + "state-"+s+"-choice-"+c+"-combination-"+count); + + mainLog.println(sb.toString()); + count++; } - GRBLinExpr norm = new GRBLinExpr(); - for (int t : delta.get(sc).keySet()) - norm.addTerm(1.0, delta.get(sc).get(t)); - m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); } } @@ -978,84 +1086,13 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); } - /* fakeKey = sInit + "-DUMMY"; - GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); - eta.put(fakeKey, etaDummy); - for(int s =0; s preds = predecessor.get(s); - if (preds == null || preds.isEmpty()) - continue; - GRBLinExpr lhs1 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs1.addTerm(1.0, eta.get(s + "-" + a)); - } - // RHS = c * sum of eta over all predecessors (t–*) - GRBLinExpr rhs1 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs1.addTerm(BIG, eta.get(predKey)); - } - m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); - - // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} - GRBLinExpr lhs2 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs2.addTerm(BIG, eta.get(s + "-" + a)); - } - GRBLinExpr rhs2 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs2.addTerm(1.0, eta.get(predKey)); - } - m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); - } - - GRBLinExpr seed = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(sInit); a++) { - seed.addTerm(1.0, eta.get(sInit + "-" + a)); - } - m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); */ // 3g) Bellman - for (int s = 0; s < n; s++) { - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++) { - String sc = s + "-" + c; - GRBQuadExpr rhs = new GRBQuadExpr(); - rhs.addConstant(mdpRewards.getTransitionReward(s,c)); - - Iterator>> it = imdp.getTransitionsIterator(s,c); - GRBQuadExpr qexpr = new GRBQuadExpr(); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); - } - - rhs.add(qexpr); - - // add big‑M disable term - - rhs.addConstant(-BIG); - rhs.addTerm(BIG,eta.get(sc)); + m.addConstr(v.get(sInit), GRB.LESS_EQUAL, bound, "multi-bound"); + m.update(); - // post v[s] ≥ expr - m.addQConstr(v.get(s), GRB.GREATER_EQUAL, rhs, "bell-"+sc ); - - } - } - m.addConstr(v.get(sInit), GRB.LESS_EQUAL, bound, "prefBound"); - - m.update(); // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) GRBLinExpr pen = new GRBLinExpr(); @@ -1068,21 +1105,28 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew pen.addTerm(-1.0, eta.get(sc)); } } - - - // set the model’s objective to pen, minimize it m.setObjective(pen, GRB.MINIMIZE); - + // set the model’s objective to pen, minimize it + + /* GRBLinExpr pen = new GRBLinExpr(); + pen.addTerm(1.0, v.get(sInit)); + m.setObjective(pen, GRB.MINIMIZE); */ int numVars = m.get(GRB.IntAttr.NumVars); int numConstr = m.get(GRB.IntAttr.NumConstrs); int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types int numContVars = numVars - numIntVars; mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); - m.setCallback(new trigger(m, 3600)); + + m.setCallback(new trigger(m, 3600.0)); + long timerGurobi = System.currentTimeMillis(); m.optimize(); + long afterGurobi = System.currentTimeMillis(); + long timeTake = afterGurobi - timerGurobi; + mainLog.println("Gurobi Solve time: " + timeTake); + //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { System.out.println("Model infeasible—computing IIS..."); @@ -1100,11 +1144,10 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew soln = new double[n]; for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); soln[s] = v.get(s).get(GRB.DoubleAttr.X); + mainLog.println("state: " + s + ", value: " + soln[s]); } - mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); @@ -1124,7 +1167,6 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } mainLog.println(); } - int permC = 0; for (int s = 0; s < n; s++) { //System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); @@ -1145,12 +1187,56 @@ public ModelCheckerResult computeMultiStrategyValueMin(IMDP imdp, MDPRew } } } - System.out.println("Number of Permissive States: " + permC); + mainLog.println("Number of Permissive States: " + permC); + mainLog.println("Value at inital state " + v.get(sInit).get(GRB.DoubleAttr.X)); + + mainLog.println("Number of Permissive States: " + permC); + + int reachable = 0; + for (int s = 0; s < n; s++) { + if (soln[s] > 0.0){ + if (soln[s] < BIG){ + int numChoices = imdp.getNumChoices(s); + if (numChoices == 1){ + continue; + } else { + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + } + + + } + } + + mainLog.println("Total number of reachable permissable state-action pairs: " + reachable); + + + reachable = 0; + for (int s = 0; s < n; s++) { + if (soln[s] > 0.0){ + if (soln[s] <= BIG){ + int numChoices = imdp.getNumChoices(s); + + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + + + + } + } + + mainLog.println("Total number of reachable state-action pairs: " + reachable); + m.dispose(); env.dispose(); } catch (GRBException e) { throw new PrismException("Error solving LP: " +e.getMessage()); } + } long time = (System.currentTimeMillis() - timer); mainLog.println("It took "+time + " milli-seconds to finish synthesize the permissive strategy"); @@ -1630,13 +1716,15 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa long timer = System.currentTimeMillis(); mainLog.println("Starting linear programming (min)..."); + int n = imdp.getNumStates(); System.out.println(n); int sInit = imdp.getFirstInitialState(); - double BIG = 10000.0; + double BIG = 1.01; BitSet no = imdp.getLabelStates("Crash"); BitSet targetS = imdp.getLabelStates("goal"); + imdp.checkForDeadlocks(); no.andNot(targetS); //targetS.andNot(no); BitSet everything = new BitSet(); @@ -1664,50 +1752,6 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa System.out.println("sInit = " + sInit); System.out.println("Crash states = " + no); System.out.println("Goal states = " + targetS); - /* for (int bad : new int[]{4,6,14,15,16,32}) { - System.out.printf("state %d has %d choices%n", - bad, imdp.getNumChoices(bad)); - } - - for (int s = 0; s < n; s++){ - System.out.println("State: " + s + ", nch: "+ imdp.getNumChoices(s)); - } */ - - //compute predecessor - /* Map> predecessor = new HashMap<>(); - states = eS.iterator(); - for(int s = 0; s < n; s++){ - //final int s = states.nextInt(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String key = s + "-" + c; - Iterator>> iter = imdp.getTransitionsIterator(s, c); - while(iter.hasNext()){ - Map.Entry> e = iter.next(); - int t = e.getKey(); - Interval transition_val = e.getValue(); - if (predecessor.containsKey(t) == false){ - predecessor.computeIfAbsent(t, k -> new ArrayList<>()).add(key); - } else { - List l = predecessor.computeIfAbsent(t,k -> new ArrayList<>()); - if (!l.contains(key)){ - l.add(key); - } - } - } - } - } */ - /* String fakeKey = sInit + "-DUMMY"; - predecessor.computeIfAbsent(sInit, __ -> new ArrayList<>()).add(fakeKey); - for (Map.Entry> entry : predecessor.entrySet()) { - Integer state = entry.getKey(); - List preds = entry.getValue(); - mainLog.println("State " + state + " has predecessors:"); - for (String actionKey : preds) { - mainLog.println(" " + actionKey); - } - } */ - if (robust==true){ @@ -1759,7 +1803,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa for (int c = 0; c < numChoices; c++){ String sc = s + "-" + c; eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); - lam.put(sc, m.addVar(0.0,1.0,0,GRB.CONTINUOUS,"lam"+"-"+sc)); + lam.put(sc, m.addVar(-1.0,1.0,0,GRB.CONTINUOUS,"lam"+"-"+sc)); GRBLinExpr lamAU = new GRBLinExpr(); lamAU.addTerm(BIG, eta.get(sc)); GRBLinExpr lamAD = new GRBLinExpr(); @@ -1774,8 +1818,8 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa int t = e.getKey(); Interval transition_val = e.getValue(); String key = sc + "->" + t; - GRBVar up = m.addVar(0,1.0,0,GRB.CONTINUOUS,"uplus["+key+"]"); - GRBVar um = m.addVar(0,1.0,0,GRB.CONTINUOUS,"umin["+key+"]"); + GRBVar up = m.addVar(0,1.01,0,GRB.CONTINUOUS,"uplus["+key+"]"); + GRBVar um = m.addVar(0,1.01,0,GRB.CONTINUOUS,"umin["+key+"]"); uplus.get(sc).put(t, up); umin.get(sc).put(t, um); GRBLinExpr allowed = new GRBLinExpr(); @@ -1793,11 +1837,6 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa } } } - /* fakeKey = sInit + "-DUMMY"; - GRBVar etaDummy = m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-" + fakeKey); - eta.put(fakeKey, etaDummy); */ - - // Action per state Constraint (multi >= 1.0, deter == 1.0) states = eS.iterator(); while(states.hasNext()) { final int s = states.nextInt(); @@ -1806,67 +1845,47 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa expr.addTerm(1.0, eta.get(s+"-"+c)); m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); } -/* states = eS.iterator(); - while(states.hasNext()){ - final int s = states.nextInt(); - // LHS = sum of eta[s–*] - if (s == sInit) - continue; // skip initial - if (imdp.getNumChoices(s) == 0){ - System.out.println(s); - continue; - } - - List preds = predecessor.get(s); - if (preds == null || preds.isEmpty()) - continue; - GRBLinExpr lhs1 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs1.addTerm(1.0, eta.get(s + "-" + a)); - } - // RHS = c * sum of eta over all predecessors (t–*) - GRBLinExpr rhs1 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs1.addTerm(BIG, eta.get(predKey)); - } - m.addConstr(lhs1, GRB.LESS_EQUAL, rhs1, "reach1b_s" + s); - - // (1c): c · ∑_{a∈α(s)} η_{s,a} ≥ ∑_{(t,a)∈ρ(s)} η_{t,a} - GRBLinExpr lhs2 = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(s); a++) { - lhs2.addTerm(BIG, eta.get(s + "-" + a)); - } - GRBLinExpr rhs2 = new GRBLinExpr(); - for (String predKey : predecessor.getOrDefault(s, Collections.emptyList())) { - rhs2.addTerm(1.0, eta.get(predKey)); - } - m.addConstr(lhs2, GRB.GREATER_EQUAL, rhs2, "reach1c_s" + s); - } - - GRBLinExpr seed = new GRBLinExpr(); - for (int a = 0; a < imdp.getNumChoices(sInit); a++) { - seed.addTerm(1.0, eta.get(sInit + "-" + a)); - } - m.addConstr(seed, GRB.GREATER_EQUAL, 1.0, "seed_s0"); */ + + double LAM_MIN = -1.0; + double LAM_MAX = 1.0; //Pre-bell Map phi = new HashMap<>(); states = eS.iterator(); while(states.hasNext()) { final int s = states.nextInt(); for (int c = 0; c < imdp.getNumChoices(s); c++) { - String sc = s + "-" + c; + String sc = s + "-" + c; GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); - GRBVar phiVar = m.addVar(-1.0,1.0, 0.0, GRB.CONTINUOUS, "phi-" + sc); + + // φ in the same bounds as λ + GRBVar phiVar = m.addVar(LAM_MIN, LAM_MAX, 0.0, GRB.CONTINUOUS, "phi-"+sc); phi.put(sc, phiVar); - // 3) φ <= λ + BIG*(1−η) - GRBLinExpr c3 = new GRBLinExpr(); - c3.addTerm(1.0, phiVar); - c3.addTerm(-1.0, lamVar); - c3.addConstant(-BIG); - c3.addTerm(+BIG, etaVar); - m.addConstr(c3, GRB.LESS_EQUAL, 0.0, "philem3-" + sc); + // McCormick: exact for binary η and bounded λ + // 1) φ ≥ L * η + GRBLinExpr mc1 = new GRBLinExpr(); + mc1.addTerm(LAM_MIN, etaVar); + m.addConstr(phiVar, GRB.GREATER_EQUAL, mc1, "mc1-"+sc); + + // 2) φ ≤ U * η + GRBLinExpr mc2 = new GRBLinExpr(); + mc2.addTerm(LAM_MAX, etaVar); + m.addConstr(phiVar, GRB.LESS_EQUAL, mc2, "mc2-"+sc); + + // 3) φ ≥ λ − U*(1−η) + GRBLinExpr mc3 = new GRBLinExpr(); + mc3.addTerm(1.0, lamVar); + mc3.addConstant(-LAM_MAX); + mc3.addTerm(LAM_MAX, etaVar); + m.addConstr(phiVar, GRB.GREATER_EQUAL, mc3, "mc3-"+sc); + + // 4) φ ≤ λ − L*(1−η) + GRBLinExpr mc4 = new GRBLinExpr(); + mc4.addTerm(1.0, lamVar); + mc4.addConstant(-LAM_MIN); + mc4.addTerm(LAM_MIN, etaVar); + m.addConstr(phiVar, GRB.LESS_EQUAL, mc4, "mc4-"+sc); } } @@ -1939,8 +1958,13 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa int numContVars = numVars - numIntVars; mainLog.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); + m.write("gurobi.lp"); + long timerGurobi = System.currentTimeMillis(); m.optimize(); + long afterGurobi = System.currentTimeMillis(); + long timeTake = afterGurobi - timerGurobi; + mainLog.println("Gurobi solve time: " + timeTake); //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { System.out.println("Model infeasible—computing IIS..."); @@ -1956,6 +1980,10 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); soln = new double[n]; + for (int s = 0; s < n; s++) { + soln[s] = v.get(s).get(GRB.DoubleAttr.X); + mainLog.println("state: " + s + ", value: " + soln[s]); + } mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); @@ -1999,6 +2027,41 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa } mainLog.println("Number of Permissive States: " + permC); // Clean up + int reachable = 0; + for (int s = 0; s < n; s++) { + if (soln[s] > 0.0){ + if (soln[s] < 1.0){ + int numChoices = imdp.getNumChoices(s); + if (numChoices == 1){ + continue; + } else { + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + } + + + } + } + + mainLog.println("Total number of reachable permissable state-action pairs: " + reachable); + + + reachable = 0; + for (int s = 0; s < n; s++) { + if (soln[s] > 0.0){ + if (soln[s] <= 1.0){ + int numChoices = imdp.getNumChoices(s); + + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + } + } + + mainLog.println("Total number of reachable state-action pairs: " + reachable); m.dispose(); env.dispose(); } catch (GRBException e) { @@ -2008,6 +2071,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa // Multi-strategy under best assumption mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); + double tol = 1e-9; try { // create environment & model @@ -2047,32 +2111,73 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa Map> delta = new HashMap<>(); states = eS.iterator(); + while(states.hasNext()){ final int s = states.nextInt(); int numC = imdp.getNumChoices(s); for (int c = 0; c < numC; c++) { String sc = s + "-" + c; - eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); - delta.put(sc, new HashMap<>()); - Iterator>> it = imdp.getTransitionsIterator(s,c); + eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); + // collect successors + bounds, and create delta vars + List tList = new ArrayList<>(); + List loList = new ArrayList<>(), hiList = new ArrayList<>(); + Iterator>> it = imdp.getTransitionsIterator(s, c); + List> li = new ArrayList<>(); while (it.hasNext()) { - Map.Entry> e = it.next(); + Map.Entry> e = it.next(); int t = e.getKey(); - Interval transition_val = e.getValue(); - String key = sc+"->"+t; - GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); - delta.get(sc).put(t, up); - GRBLinExpr allowedUp = new GRBLinExpr(); - GRBLinExpr allowedLow = new GRBLinExpr(); - allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); - allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); - m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); - m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); + Interval w = e.getValue(); + li.add(w); + tList.add(t); + } + + System.out.println("tList: " + tList.toString()); + for (int i = 0; i < li.size(); i++) { + Interval w = li.get(i); + double lo = Math.min(w.getLower(), w.getUpper()); // normalize just in case + double hi = Math.max(w.getLower(), w.getUpper()); + loList.add(lo); + hiList.add(hi); + } + + + + + // Enumerate all vertices via "n-1 at bounds + 1 free" + + + List> result = new ArrayList<>(); + Set seen = new HashSet<>(); + for (int j = 0; j < tList.size(); j++) { + int freeState = tList.get(j); + List> verts = + findExtremeCombos(tList, loList, hiList, tol, freeState); // <-- new overload + for (Map combo : verts) { + String key = comboKey(combo, tList); + if (seen.add(key)) result.add(combo); // keep only novel vertices + } + } + + int count = 0; + for (Map combo : result) { + StringBuilder sb = new StringBuilder(); + GRBLinExpr expr = new GRBLinExpr(); + for (int i = 0; i < tList.size(); i++) { + int t = tList.get(i); + double p = combo.get(t); + if (i > 0) sb.append(", "); + sb.append("state ").append(t).append(": ") + .append(String.format(Locale.US, "%.9f", p)); + expr.addTerm(p, v.get(t)); + } + // indicator-style big-M for the chosen (s,c) + expr.addConstant(+BIG); + expr.addTerm(-BIG, eta.get(sc)); + m.addConstr(v.get(s), GRB.LESS_EQUAL, expr, + "state-"+s+"-choice-"+c+"-combination-"+count); + + count++; } - GRBLinExpr norm = new GRBLinExpr(); - for (int t : delta.get(sc).keySet()) - norm.addTerm(1.0, delta.get(sc).get(t)); - m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); } } @@ -2088,41 +2193,10 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa // 3g) Bellman - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - for (int c = 0; c < imdp.getNumChoices(s); c++) { - String sc = s + "-" + c; - GRBQuadExpr rhs = new GRBQuadExpr(); - //rhs.addConstant(mdpRewards.getTransitionReward(s,c)); - - Iterator>> it = imdp.getTransitionsIterator(s,c); - GRBQuadExpr qexpr = new GRBQuadExpr(); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); - } + m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); + m.update(); - rhs.add(qexpr); - // add big‑M disable term - rhs.addConstant(+BIG); - rhs.addTerm(-BIG, eta.get(sc) ); - - - // post v[s] ≥ expr - - m.addQConstr(v.get(s), GRB.LESS_EQUAL, rhs, "bell-"+sc ); - - - } - } - - m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "prefBound"); - - - m.update(); // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) GRBLinExpr pen = new GRBLinExpr(); @@ -2135,13 +2209,15 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa pen.addTerm(-1.0, eta.get(sc)); } } + + m.setObjective(pen, GRB.MINIMIZE); // set the model’s objective to pen, minimize it m.setObjective(pen, GRB.MINIMIZE); - /* GRBLinExpr pen = new GRBLinExpr(); + /*GRBLinExpr pen = new GRBLinExpr(); pen.addTerm(1.0, v.get(sInit)); - m.setObjective(pen, GRB.MAXIMIZE); */ + m.setObjective(pen, GRB.MAXIMIZE);*/ int numVars = m.get(GRB.IntAttr.NumVars); int numConstr = m.get(GRB.IntAttr.NumConstrs); int numIntVars = m.get(GRB.IntAttr.NumIntVars); // counts both BINARY and INTEGER types @@ -2150,7 +2226,13 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa System.out.println("Continuous Variables = " + numContVars + ", Integer Variables = "+ numIntVars + ", Constraints = " + numConstr); m.setCallback(new trigger(m, 3600.0)); + m.write("gurobi.lp"); + + long timerGurobi = System.currentTimeMillis(); m.optimize(); + long afterGurobi = System.currentTimeMillis(); + long timeTake = afterGurobi - timerGurobi; + mainLog.println("Gurobi Solve time: " + timeTake); //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { @@ -2169,8 +2251,8 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa soln = new double[n]; for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); soln[s] = v.get(s).get(GRB.DoubleAttr.X); + mainLog.println("state: " + s + ", value: " + soln[s]); } mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); @@ -2181,6 +2263,7 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa // Loop over each solution k=0…solCount−1 + for (int s = 0; s < n; s++) { mainLog.print(s + ":"); int numChoices = imdp.getNumChoices(s); @@ -2213,6 +2296,49 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa } } mainLog.println("Number of Permissive States: " + permC); + mainLog.println("Value at inital state " + v.get(sInit).get(GRB.DoubleAttr.X)); + + int reachable = 0; + int reachable_state = 0; + for (int s = 0; s < n; s++) { + if (soln[s] > 0.0){ + if (soln[s] < 1.0){ + reachable_state += 1; + int numChoices = imdp.getNumChoices(s); + if (numChoices == 1){ + continue; + } else { + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + } + + + } + } + + mainLog.println("Total number of reachable permissable state-action pairs: " + reachable); + mainLog.println("Reachable States: " + reachable_state); + + + reachable = 0; + for (int s = 0; s < n; s++) { + if (soln[s] > 0.0){ + if (soln[s] <= 1.0){ + int numChoices = imdp.getNumChoices(s); + + for (int i = 0; i < numChoices; i++) { + reachable += 1; + } + } + + + + } + } + + mainLog.println("Total number of reachable state-action pairs: " + reachable); m.dispose(); env.dispose(); } catch (GRBException e) { @@ -2230,931 +2356,184 @@ public ModelCheckerResult computeMultiStrategyProbMax(IMDP imdp, MDPRewa return res; } - public ModelCheckerResult computeMultiStrategyProbMaxIndicator(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException - { - double[] soln = null; - - // Start solution - long timer = System.currentTimeMillis(); - mainLog.println("Starting linear programming (min)..."); - - int n = imdp.getNumStates(); - System.out.println(n); - int sInit = imdp.getFirstInitialState(); - double BIG = 1.0; - BitSet no = imdp.getLabelStates("Crash"); - BitSet targetS = imdp.getLabelStates("goal"); - System.out.println(targetS); - no.andNot(targetS); - //targetS.andNot(no); - BitSet everything = new BitSet(); - everything.set(0, n); - //everything.andNot(no); - IntSet targetStates = IntSet.asIntSet(targetS); - IntSet eS = IntSet.asIntSet(everything); - PrimitiveIterator.OfInt Tstates = targetStates.iterator(); - int numTarget = 0; - while(Tstates.hasNext()){ - final int s = Tstates.nextInt(); - numTarget += 1; - } - int[] target = new int[numTarget]; - Tstates = targetStates.iterator(); - int counter = 0; - while(Tstates.hasNext()){ - final int s = Tstates.nextInt(); - target[counter] = s; - counter += 1; + /* public static List> findExtremeCombos( + List tList, + List loList, + List hiList, + double tol + ) { + final int n = tList.size(); + if (loList.size() != n || hiList.size() != n) { + throw new IllegalArgumentException("tList, loList, hiList must have same length"); } - PrimitiveIterator.OfInt states = eS.iterator(); - IntSet nStates = IntSet.asIntSet(no); - PrimitiveIterator.OfInt ns = nStates.iterator(); - System.out.println(no); - if (robust==true){ - mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); - try { - // Initialise MILP solver - GRBEnv env = new GRBEnv("gurobi.log"); - //env.set(GRB.DoubleParam.TimeLimit, 10800.0); // 60-second limit - /* env.set(GRB.IntParam.Threads, 0); // (optional) use all cores - env.set(GRB.IntParam.OutputFlag, 1); - env.set(GRB.IntParam.Cuts, 2); - env.set(GRB.IntParam.MIRCuts, 2); - env.set(GRB.IntParam.CoverCuts, 2); - env.set(GRB.IntParam.FlowCoverCuts,2); - env.set(GRB.IntParam.GUBCoverCuts, 2); - env.set(GRB.IntParam.ImpliedCuts, 2); */ - GRBModel m = new GRBModel(env); - Map v; - Map eta, lam; - Map> uplus, umin; - - // Value-function - v = new HashMap<>(); - for (int s = 0; s (); - lam = new HashMap<>(); - uplus = new HashMap<>(); - umin = new HashMap<>(); - states = eS.iterator(); - while(states.hasNext()){ - final int s = states.nextInt(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String sc = s + "-" + c; - eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); - lam.put(sc, m.addVar(-BIG,BIG,0,GRB.CONTINUOUS,"lam"+"-"+sc)); - uplus.put(sc, new HashMap<>()); - umin.put(sc, new HashMap<>()); - Iterator>> iter = imdp.getTransitionsIterator(s, c); - while(iter.hasNext()){ - Map.Entry> e = iter.next(); - int t = e.getKey(); - Interval transition_val = e.getValue(); - String key = sc + "->" + t; - GRBVar up = m.addVar(0,BIG,0,GRB.CONTINUOUS,"uplus["+key+"]"); - GRBVar um = m.addVar(0,BIG,0,GRB.CONTINUOUS,"umin["+key+"]"); - uplus.get(sc).put(t, up); - umin.get(sc).put(t, um); - GRBLinExpr allowed = new GRBLinExpr(); - allowed.addTerm(BIG, eta.get(sc)); - m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); - m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); - GRBLinExpr upp = new GRBLinExpr(); - upp.addTerm(1.0, uplus.get(sc).get(t)); - GRBLinExpr umm = new GRBLinExpr(); - umm.addTerm(1.0, umin.get(sc).get(t)); - m.addGenConstrIndicator( - eta.get(sc), // indicator var - 1, // when η(sc) == 1 - upp, // target var - GRB.EQUAL, // equality - 0.0, // to 0.0 - "ind_uPlusZe-" + sc + "-" + t - ); - m.addGenConstrIndicator( - eta.get(sc), // indicator var - 0, // when η(sc) == 0 - upp, // target var - GRB.LESS_EQUAL, // equality - BIG, // to 0.0 - "ind_uPlus-" + sc + "-" + t - ); - - m.addGenConstrIndicator( - eta.get(sc), // same η(sc) - 1, // when η(sc) == 1 - umm, // target var - GRB.EQUAL, - 0.0, - "ind_uMinZe-" + sc + "-" + t - ); - m.addGenConstrIndicator( - eta.get(sc), // same η(sc) - 0, // when η(sc) == 0 - umm, // target var - GRB.LESS_EQUAL, - BIG, - "ind_uMin-" + sc + "-" + t - ); - GRBLinExpr dualExpr = new GRBLinExpr(); - dualExpr.addTerm(1.0, lam.get(sc)); - dualExpr.addTerm(-1.0, uplus.get(sc).get(t)); - dualExpr.addTerm(+1.0, umin.get(sc).get(t)); - m.addConstr(dualExpr, GRB.LESS_EQUAL, v.get(t), "dualFeas_"+sc+"_"+t); - } - } - } - - // Action per state Constraint (multi >= 1.0, deter == 1.0) - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - GRBLinExpr expr = new GRBLinExpr(); - for (int c = 0; c < imdp.getNumChoices(s); c++) - expr.addTerm(1.0, eta.get(s+"-"+c)); - m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); - } - - //Pre-bell - Map phi = new HashMap<>(); - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - for (int c = 0; c < imdp.getNumChoices(s); c++) { - String sc = s + "-" + c; - GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); - GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); - phi.put(sc, phiVar); - - // 3) φ <= λ + BIG*(1−η) - GRBLinExpr c3 = new GRBLinExpr(); - c3.addTerm(1.0, phiVar); - c3.addTerm(-1.0, lamVar); - c3.addConstant(-BIG); - c3.addTerm(+BIG, etaVar); - m.addConstr(c3, GRB.LESS_EQUAL, 0.0, "philem3-" + sc); - } - } - - - m.update(); + // Copy into arrays for speed; normalize (lo<=hi). + final int[] t = new int[n]; + final double[] lo = new double[n]; + final double[] hi = new double[n]; + for (int i = 0; i < n; i++) { + t[i] = tList.get(i); + double a = loList.get(i), b = hiList.get(i); + lo[i] = Math.min(a, b); + hi[i] = Math.max(a, b); + } - // Bellman constraint - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++) { - String sc = s + "-" + c; - GRBLinExpr expr = new GRBLinExpr(); - //expr.addConstant(mdpRewards.getTransitionReward(s,c)); + // Suffix MIN/MAX over remaining indices i..n-1 for pruning. + final double[] minSuf = new double[n + 1]; + final double[] maxSuf = new double[n + 1]; + for (int i = n - 1; i >= 0; --i) { + minSuf[i] = minSuf[i + 1] + Math.min(lo[i], hi[i]); + maxSuf[i] = maxSuf[i + 1] + Math.max(lo[i], hi[i]); + } - // add phi = λ·η - expr.addTerm(1.0, phi.get(sc)); + // Global feasibility check. + if (1.0 < minSuf[0] - tol || 1.0 > maxSuf[0] + tol) { + return Collections.emptyList(); + } - // add ∑[hi·uplus – lo·umin] - GRBLinExpr ins = new GRBLinExpr(); - Iterator>> it = imdp.getTransitionsIterator(s,c); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); - ins.addTerm(-hi, uplus.get(sc).get(t) ); - ins.addTerm(+lo, umin .get(sc).get(t) ); + final List> out = new ArrayList<>(); + final int[] choice = new int[n]; // 0 => lo[i], 1 => hi[i] + + // DFS with branch-and-bound. + class DFS { + void go(int i, double sum) { + if (i == n) { + if (Math.abs(sum - 1.0) <= tol) { + // Build { t -> chosen value } for this combination. + Map combo = new LinkedHashMap<>(n); + for (int k = 0; k < n; k++) { + combo.put(t[k], choice[k] == 0 ? lo[k] : hi[k]); } - expr.add(ins); - - expr.addConstant(+BIG); - expr.addTerm(-BIG, eta.get(sc) ); - - - // post v[s] ≥ expr - m.addConstr( v.get(s), GRB.LESS_EQUAL, expr, "bell-"+sc ); - - + out.add(combo); } + return; } + double low = sum + minSuf[i]; + double high = sum + maxSuf[i]; + if (1.0 < low - tol || 1.0 > high + tol) return; // prune - // Bound for v[0]; - - /* m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); - - m.update(); + choice[i] = 0; go(i + 1, sum + lo[i]); // pick lower + choice[i] = 1; go(i + 1, sum + hi[i]); // pick upper + } + } + new DFS().go(0, 0.0); + return out; + } */ + + public static List> findExtremeCombos( + List tList, + List loList, + List hiList, + double tol, + int freeState // the state id that gets the dumped remainder + ) { + final int n = tList.size(); + System.out.println("n = " + n); + System.out.println(loList.size()); + System.out.println(hiList.size()); + if (loList.size() != n || hiList.size() != n) { + throw new IllegalArgumentException("tList, loList, hiList must have same length"); + } + + // copy + normalize + final int[] t = new int[n]; + final double[] lo = new double[n]; + final double[] hi = new double[n]; + for (int i = 0; i < n; i++) { + t[i] = tList.get(i); + double a = loList.get(i), b = hiList.get(i); + lo[i] = Math.min(a, b); + hi[i] = Math.max(a, b); + } + + // locate free index by state id + int jTmp = -1; + for (int i = 0; i < n; i++) if (t[i] == freeState) { jTmp = i; break; } + if (jTmp < 0) throw new IllegalArgumentException("freeState not found in tList"); + + // **** make all captured locals final **** + final int freeIdx = jTmp; + final int nLocal = n; + + // build arrays for the other (n-1) indices + final int m = nLocal - 1; + final int[] tO = new int[m]; + final double[] loO = new double[m]; + final double[] hiO = new double[m]; + for (int i = 0, k = 0; i < nLocal; i++) { + if (i == freeIdx) continue; + tO[k] = t[i]; + loO[k] = lo[i]; + hiO[k] = hi[i]; + k++; + } + final double loJ = lo[freeIdx], hiJ = hi[freeIdx]; + final int tJ = t[freeIdx]; + + // suffix bounds over "others" + final double[] minSuf = new double[m + 1]; + final double[] maxSuf = new double[m + 1]; + for (int i = m - 1; i >= 0; --i) { + minSuf[i] = minSuf[i + 1] + Math.min(loO[i], hiO[i]); + maxSuf[i] = maxSuf[i + 1] + Math.max(loO[i], hiO[i]); + } + + // feasible sum range for others so that p_free is within its interval + final double sMinFeas = 1.0 - hiJ; + final double sMaxFeas = 1.0 - loJ; + if (maxSuf[0] + tol < sMinFeas || minSuf[0] - tol > sMaxFeas) { + return Collections.emptyList(); + } + + final List> out = new ArrayList<>(); + final int[] choice = new int[m]; // 0->lo, 1->hi + + class DFS { + void go(int i, double sumOthers) { + if (i == m) { + final double pJ = 1.0 - sumOthers; + if (pJ >= loJ - tol && pJ <= hiJ + tol) { + Map combo = new LinkedHashMap<>(nLocal); + int k = 0; + for (int idx = 0; idx < nLocal; idx++) { + if (idx == freeIdx) { + combo.put(tJ, pJ); + } else { + double v = (choice[k] == 0 ? loO[k] : hiO[k]); + combo.put(tO[k], v); + k++; + } + } + out.add(combo); + } + return; + } + double low = sumOthers + minSuf[i]; + double high = sumOthers + maxSuf[i]; + if (high + tol < sMinFeas || low - tol > sMaxFeas) return; - // Objective - GRBLinExpr pen = new GRBLinExpr(); - for (int s = 0; s < n; s++){ - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String sc = s +"-"+c; - pen.addConstant(1.0); - pen.addTerm(-1.0, eta.get(sc)); + choice[i] = 0; go(i + 1, sumOthers + loO[i]); + choice[i] = 1; go(i + 1, sumOthers + hiO[i]); } } - m.setObjective(pen, GRB.MINIMIZE); */ - // set the model’s objective to pen, minimize it - GRBLinExpr pen = new GRBLinExpr(); - pen.addTerm(1.0, v.get(sInit)); - m.setObjective(pen, GRB.MAXIMIZE); - - // now optimize - m.optimize(); - - System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); + new DFS().go(0, 0.0); + return out; + } - soln = new double[n]; - for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); - soln[s] = v.get(s).get(GRB.DoubleAttr.X); + // Helper to de-dupe combos (round to ~1e-12 to be safe) + static String comboKey(Map combo, List tOrder) { + StringBuilder sb = new StringBuilder(); + for (int tt : tOrder) { + double p = combo.get(tt); + sb.append(tt).append(':') + .append(String.format(Locale.US, "%.12f", p)) + .append('|'); } + return sb.toString(); + } - mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); - - - // How many solutions are in the pool? - int solCount = m.get(GRB.IntAttr.SolCount); - // Loop over each solution k=0…solCount−1 - for (int s = 0; s < n; s++) { - mainLog.print(s + ":"); - int numChoices = imdp.getNumChoices(s); - for (int i = 0; i < numChoices; i++) { - String sc = s +"-"+i; - if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { - mainLog.print(" " + imdp.getAction(s, i)); - } - } - mainLog.println(); - } - - // Clean up - m.dispose(); - env.dispose(); - } catch (GRBException e) { - throw new PrismException("Error solving LP: " +e.getMessage()); - } - } else { - - - // Multi-strategy under best assumption - mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); - - try { - // create environment & model - GRBEnv env = new GRBEnv("gurobi.log"); - env.set(GRB.IntParam.OutputFlag, 0); - env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit - env.set(GRB.IntParam.Threads, 0); // (optional) use all cores - env.set(GRB.IntParam.OutputFlag, 1); - env.set(GRB.IntParam.Cuts, 2); - GRBModel m = new GRBModel(env); - - - // --- 1) Value‐function vars v[s] --- - Map v = new HashMap<>(); - for (int s = 0; s < n; s++) { - v.put(s, m.addVar(0.0,1.0, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); - } - /* for (int i = 0; i < numTarget; i++) { - m.addConstr(v.get(target[i]), GRB.EQUAL, 1.0, "v-target-"+target[i]); - } */ - Tstates = targetStates.iterator(); - while(Tstates.hasNext()){ - final int s = Tstates.nextInt(); - m.addConstr(v.get(s),GRB.EQUAL,1.0,"v-target"); - } - - while(ns.hasNext()){ - final int s = ns.nextInt(); - v.put(s, m.addVar(0.0, 1.0, 0, GRB.CONTINUOUS, "mu["+s+"]")); - m.addConstr(v.get(s),GRB.EQUAL,0.0,"v-no"); - } - m.update(); - - // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- - Map eta = new HashMap<>(); - Map> delta = new HashMap<>(); - - states = eS.iterator(); - while(states.hasNext()){ - final int s = states.nextInt(); - int numC = imdp.getNumChoices(s); - for (int c = 0; c < numC; c++) { - String sc = s + "-" + c; - eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); - delta.put(sc, new HashMap<>()); - Iterator>> it = imdp.getTransitionsIterator(s,c); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - Interval transition_val = e.getValue(); - String key = sc+"->"+t; - GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); - delta.get(sc).put(t, up); - GRBLinExpr allowedUp = new GRBLinExpr(); - GRBLinExpr allowedLow = new GRBLinExpr(); - allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); - allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); - m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); - m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); - } - GRBLinExpr norm = new GRBLinExpr(); - for (int t : delta.get(sc).keySet()) - norm.addTerm(1.0, delta.get(sc).get(t)); - m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); - } - } - - // --- 3) Action‐selection: sum η ≥ 1 at each state --- - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - GRBLinExpr expr = new GRBLinExpr(); - for (int c = 0; c < imdp.getNumChoices(s); c++) - expr.addTerm(1.0, eta.get(s+"-"+c)); - m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); - } - - - // 3g) Bellman - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - for (int c = 0; c < imdp.getNumChoices(s); c++) { - String sc = s + "-" + c; - GRBQuadExpr rhs = new GRBQuadExpr(); - //rhs.addConstant(mdpRewards.getTransitionReward(s,c)); - - Iterator>> it = imdp.getTransitionsIterator(s,c); - GRBQuadExpr qexpr = new GRBQuadExpr(); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); - } - - rhs.add(qexpr); - - // add big‑M disable term - rhs.addConstant(+BIG); - rhs.addTerm(-BIG, eta.get(sc) ); - - - // post v[s] ≥ expr - - m.addQConstr(v.get(s), GRB.LESS_EQUAL, rhs, "bell-"+sc ); - - - } - } - - m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "prefBound"); - - - m.update(); - - // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) - GRBLinExpr pen = new GRBLinExpr(); - - for (int s = 0; s < n; s++){ - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String sc = s +"-"+c; - pen.addConstant(1.0); - pen.addTerm(-1.0, eta.get(sc)); - } - } - - // set the model’s objective to pen, minimize it - - m.setObjective(pen, GRB.MINIMIZE); - /* GRBLinExpr pen = new GRBLinExpr(); - pen.addTerm(1.0, v.get(sInit)); - m.setObjective(pen, GRB.MAXIMIZE); */ - - - m.setCallback(new trigger(m, 300)); - m.optimize(); - //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); - if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { - System.out.println("Model infeasible—computing IIS..."); - m.computeIIS(); - for (GRBConstr c : m.getConstrs()) { - if (c.get(GRB.IntAttr.IISConstr) == 1) { - System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); - } - } - // Optionally write the IIS to a file: - m.write("model.IIS"); - } - int status = m.get(GRB.IntAttr.Status); - System.out.println("Gurobi Status = " + status); - - soln = new double[n]; - for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); - soln[s] = v.get(s).get(GRB.DoubleAttr.X); - } - - mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); - - - // How many solutions are in the pool? - int solCount = m.get(GRB.IntAttr.SolCount); - - // Loop over each solution k=0…solCount−1 - - for (int s = 0; s < n; s++) { - mainLog.print(s + ":"); - int numChoices = imdp.getNumChoices(s); - for (int i = 0; i < numChoices; i++) { - String sc = s +"-"+i; - if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { - mainLog.print(" " + imdp.getAction(s, i)); - } - } - mainLog.println(); - } - m.dispose(); - env.dispose(); - } catch (GRBException e) { - throw new PrismException("Error solving LP: " +e.getMessage()); - } - } - long time = (System.currentTimeMillis() - timer); - mainLog.println("It took "+time + " milli-seconds to finish synthesize the permissive strategy"); - - // Return results - ModelCheckerResult res = new ModelCheckerResult(); -// res.accuracy = AccuracyFactory.boundedNumericalIterations(); - res.soln = soln; -// res.timeTaken = timer / 1000.0; - return res; - } - - - public ModelCheckerResult computeMultiStrategyProbMin(IMDP imdp, MDPRewards mdpRewards, double bound, boolean robust) throws PrismException - { - double[] soln = null; - - // Start solution - long timer = System.currentTimeMillis(); - mainLog.println("Starting linear programming (min)..."); - - int n = imdp.getNumStates(); - System.out.println(n); - int sInit = imdp.getFirstInitialState(); - double BIG = 1.00; - BitSet no = imdp.getLabelStates("Crash"); - BitSet targetS = imdp.getLabelStates("goal"); - System.out.println(targetS); - no.andNot(targetS); - //targetS.andNot(no); - BitSet everything = new BitSet(); - everything.set(0, n); - //everything.andNot(no); - IntSet targetStates = IntSet.asIntSet(targetS); - IntSet eS = IntSet.asIntSet(everything); - PrimitiveIterator.OfInt Tstates = targetStates.iterator(); - int numTarget = 0; - while(Tstates.hasNext()){ - final int s = Tstates.nextInt(); - numTarget += 1; - } - int[] target = new int[numTarget]; - Tstates = targetStates.iterator(); - int counter = 0; - while(Tstates.hasNext()){ - final int s = Tstates.nextInt(); - target[counter] = s; - counter += 1; - } - PrimitiveIterator.OfInt states = eS.iterator(); - IntSet nStates = IntSet.asIntSet(no); - PrimitiveIterator.OfInt ns = nStates.iterator(); - System.out.println(no); - if (robust==true){ - mainLog.println("Calcualting multi Strategy under the assumption of worst transition per objective: "); - try { - // Initialise MILP solver - GRBEnv env = new GRBEnv("gurobi.log"); - //env.set(GRB.DoubleParam.TimeLimit, 10800.0); // 60-second limit - env.set(GRB.IntParam.Threads, 0); // (optional) use all cores - env.set(GRB.IntParam.OutputFlag, 1); - env.set(GRB.IntParam.Cuts, 2); - env.set(GRB.IntParam.MIRCuts, 2); - env.set(GRB.IntParam.CoverCuts, 2); - env.set(GRB.IntParam.FlowCoverCuts,2); - env.set(GRB.IntParam.GUBCoverCuts, 2); - env.set(GRB.IntParam.ImpliedCuts, 2); - GRBModel m = new GRBModel(env); - Map v; - Map eta, lam; - Map> uplus, umin; - - // Value-function - v = new HashMap<>(); - for (int s = 0; s (); - lam = new HashMap<>(); - uplus = new HashMap<>(); - umin = new HashMap<>(); - states = eS.iterator(); - while(states.hasNext()){ - final int s = states.nextInt(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String sc = s + "-" + c; - eta.put(sc, m.addVar(0.0,1.0,0.0,GRB.BINARY,"eta"+"-"+sc)); - lam.put(sc, m.addVar(-1.0,1.0,0,GRB.CONTINUOUS,"lam"+"-"+sc)); - uplus.put(sc, new HashMap<>()); - umin.put(sc, new HashMap<>()); - Iterator>> iter = imdp.getTransitionsIterator(s, c); - while(iter.hasNext()){ - Map.Entry> e = iter.next(); - int t = e.getKey(); - Interval transition_val = e.getValue(); - String key = sc + "->" + t; - GRBVar up = m.addVar(0,1.0,0,GRB.CONTINUOUS,"uplus["+key+"]"); - GRBVar um = m.addVar(0,1.0,0,GRB.CONTINUOUS,"umin["+key+"]"); - uplus.get(sc).put(t, up); - umin.get(sc).put(t, um); - GRBLinExpr allowed = new GRBLinExpr(); - allowed.addTerm(BIG, eta.get(sc)); - m.addConstr(uplus.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uPlusLow-"+sc+"-"+t ); - m.addConstr(umin.get(sc).get(t), GRB.GREATER_EQUAL, 0.0,"uMinLow-"+sc+"-"+t ); - m.addConstr(uplus.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uPlusHigh-"+sc+"-"+t); - m.addConstr(umin.get(sc).get(t), GRB.LESS_EQUAL, allowed,"uMinHigh-"+sc+"-"+t); - GRBLinExpr dualExpr = new GRBLinExpr(); - dualExpr.addTerm(1.0, lam.get(sc)); - dualExpr.addTerm(1.0, uplus.get(sc).get(t)); - dualExpr.addTerm(-1.0, umin.get(sc).get(t)); - m.addConstr(dualExpr, GRB.GREATER_EQUAL, v.get(t), "dualFeas_"+sc+"_"+t); - } - } - } - - // Action per state Constraint (multi >= 1.0, deter == 1.0) - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - GRBLinExpr expr = new GRBLinExpr(); - for (int c = 0; c < imdp.getNumChoices(s); c++) - expr.addTerm(1.0, eta.get(s+"-"+c)); - m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); - } - - //Pre-bell - Map phi = new HashMap<>(); - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - for (int c = 0; c < imdp.getNumChoices(s); c++) { - String sc = s + "-" + c; - GRBVar etaVar = eta.get(sc), lamVar = lam.get(sc); - GRBVar phiVar = m.addVar(-BIG, BIG, 0.0, GRB.CONTINUOUS, "phi-" + sc); - phi.put(sc, phiVar); - - // 3) φ >= λ - BIG*(1−η) - GRBLinExpr c3 = new GRBLinExpr(); - c3.addTerm(1.0, phiVar); - c3.addTerm(-1.0, lamVar); - c3.addConstant(-BIG); - c3.addTerm(+BIG, etaVar); - m.addConstr(c3, GRB.GREATER_EQUAL, 0.0, "philem3-" + sc); - } - } - - - m.update(); - - - // Bellman constraint - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++) { - String sc = s + "-" + c; - GRBLinExpr expr = new GRBLinExpr(); - //expr.addConstant(mdpRewards.getTransitionReward(s,c)); - - // add phi = λ·η - expr.addTerm(1.0, phi.get(sc)); - - // add ∑[hi·uplus – lo·umin] - GRBLinExpr ins = new GRBLinExpr(); - Iterator>> it = imdp.getTransitionsIterator(s,c); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - double lo = e.getValue().getLower(), hi = e.getValue().getUpper(); - ins.addTerm(+hi, uplus.get(sc).get(t) ); - ins.addTerm(-lo, umin .get(sc).get(t) ); - } - expr.add(ins); - - expr.addConstant(-BIG); - expr.addTerm(+BIG, eta.get(sc) ); - - - // post v[s] ≥ expr - m.addConstr( v.get(s), GRB.GREATER_EQUAL, expr, "bell-"+sc ); - - - } - } - - // Bound for v[0]; - - m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "multi-bound"); - - m.update(); - - // Objective - GRBLinExpr pen = new GRBLinExpr(); - for (int s = 0; s < n; s++){ - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String sc = s +"-"+c; - pen.addConstant(1.0); - pen.addTerm(-1.0, eta.get(sc)); - } - } - m.setObjective(pen, GRB.MINIMIZE); - // set the model’s objective to pen, minimize it - /* GRBLinExpr pen = new GRBLinExpr(); - pen.addTerm(1.0, v.get(sInit)); - m.setObjective(pen, GRB.MAXIMIZE); */ - - // now optimize - m.optimize(); - - System.out.printf("v[0]: %.4f%n", v.get(sInit).get(GRB.DoubleAttr.X)); - - soln = new double[n]; - for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); - soln[s] = v.get(s).get(GRB.DoubleAttr.X); - } - - mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); - - - // How many solutions are in the pool? - int solCount = m.get(GRB.IntAttr.SolCount); - - // Loop over each solution k=0…solCount−1 - - for (int s = 0; s < n; s++) { - mainLog.print(s + ":"); - int numChoices = imdp.getNumChoices(s); - for (int i = 0; i < numChoices; i++) { - String sc = s +"-"+i; - if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { - mainLog.print(" " + imdp.getAction(s, i)); - } - } - mainLog.println(); - } - - // Clean up - m.dispose(); - env.dispose(); - } catch (GRBException e) { - throw new PrismException("Error solving LP: " +e.getMessage()); - } - } else { - - - // Multi-strategy under best assumption - mainLog.println("Calcualting multi Strategy under the assumption of best transition per objective: "); - - try { - // create environment & model - GRBEnv env = new GRBEnv("gurobi.log"); - env.set(GRB.IntParam.OutputFlag, 0); - env.set(GRB.DoubleParam.TimeLimit, 3600.0); // 60-second limit - env.set(GRB.IntParam.Threads, 0); // (optional) use all cores - env.set(GRB.IntParam.OutputFlag, 1); - env.set(GRB.IntParam.Cuts, 2); - GRBModel m = new GRBModel(env); - - - // --- 1) Value‐function vars v[s] --- - Map v = new HashMap<>(); - for (int s = 0; s < n; s++) { - v.put(s, m.addVar(0.0,1.0, 0.0, GRB.CONTINUOUS, "mu["+s+"]")); - } - /* for (int i = 0; i < numTarget; i++) { - m.addConstr(v.get(target[i]), GRB.EQUAL, 1.0, "v-target-"+target[i]); - } */ - Tstates = targetStates.iterator(); - while(Tstates.hasNext()){ - final int s = Tstates.nextInt(); - m.addConstr(v.get(s),GRB.EQUAL,1.0,"v-target"); - } - - while(ns.hasNext()){ - final int s = ns.nextInt(); - v.put(s, m.addVar(0.0, 1.0, 0, GRB.CONTINUOUS, "mu["+s+"]")); - m.addConstr(v.get(s),GRB.EQUAL,0.0,"v-no"); - } - m.update(); - - // --- 2) Binary η and dual vars lam (α), uplus (β), umin (γ) --- - Map eta = new HashMap<>(); - Map> delta = new HashMap<>(); - - states = eS.iterator(); - while(states.hasNext()){ - final int s = states.nextInt(); - int numC = imdp.getNumChoices(s); - for (int c = 0; c < numC; c++) { - String sc = s + "-" + c; - eta.put(sc, m.addVar(0.0, 1.0, 0.0, GRB.BINARY, "eta-"+sc)); - delta.put(sc, new HashMap<>()); - Iterator>> it = imdp.getTransitionsIterator(s,c); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - Interval transition_val = e.getValue(); - String key = sc+"->"+t; - GRBVar up = m.addVar(0.0, 1.0, 0.0,GRB.CONTINUOUS, "delta-"+key); - delta.get(sc).put(t, up); - GRBLinExpr allowedUp = new GRBLinExpr(); - GRBLinExpr allowedLow = new GRBLinExpr(); - allowedUp.addTerm(transition_val.getUpper(), eta.get(sc)); - allowedLow.addTerm(transition_val.getLower(), eta.get(sc)); - m.addConstr(delta.get(sc).get(t), GRB.LESS_EQUAL, allowedUp, "upperBound"); - m.addConstr(delta.get(sc).get(t), GRB.GREATER_EQUAL, allowedLow, "LowerBound"); - } - GRBLinExpr norm = new GRBLinExpr(); - for (int t : delta.get(sc).keySet()) - norm.addTerm(1.0, delta.get(sc).get(t)); - m.addConstr(norm, GRB.EQUAL, eta.get(sc), "norm-"+sc); - } - } - - // --- 3) Action‐selection: sum η ≥ 1 at each state --- - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - GRBLinExpr expr = new GRBLinExpr(); - for (int c = 0; c < imdp.getNumChoices(s); c++) - expr.addTerm(1.0, eta.get(s+"-"+c)); - m.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "actSel-"+s); - } - - - // 3g) Bellman - states = eS.iterator(); - while(states.hasNext()) { - final int s = states.nextInt(); - for (int c = 0; c < imdp.getNumChoices(s); c++) { - String sc = s + "-" + c; - GRBQuadExpr rhs = new GRBQuadExpr(); - //rhs.addConstant(mdpRewards.getTransitionReward(s,c)); - - Iterator>> it = imdp.getTransitionsIterator(s,c); - GRBQuadExpr qexpr = new GRBQuadExpr(); - while (it.hasNext()) { - Map.Entry> e = it.next(); - int t = e.getKey(); - qexpr.addTerm(1.0,delta.get(sc).get(t),v.get(t)); - } - - rhs.add(qexpr); - - // add big‑M disable term - rhs.addConstant(-BIG); - rhs.addTerm(BIG, eta.get(sc) ); - - - // post v[s] ≥ expr - - m.addQConstr(v.get(s), GRB.GREATER_EQUAL, rhs, "bell-"+sc ); - - - } - } - - m.addConstr(v.get(sInit), GRB.GREATER_EQUAL, bound, "prefBound"); - - - m.update(); - - // 5) objective: minimize sum(1−η) ≡ minimize ( #actions − sum η ) - GRBLinExpr pen = new GRBLinExpr(); - - for (int s = 0; s < n; s++){ - int numChoices = imdp.getNumChoices(s); - for (int c = 0; c < numChoices; c++){ - String sc = s +"-"+c; - pen.addConstant(1.0); - pen.addTerm(-1.0, eta.get(sc)); - } - } - - // set the model’s objective to pen, minimize it - - m.setObjective(pen, GRB.MINIMIZE); - /* GRBLinExpr pen = new GRBLinExpr(); - pen.addTerm(1.0, v.get(sInit)); - m.setObjective(pen, GRB.MAXIMIZE); */ - - - - m.optimize(); - //System.out.printf("v[0]: %.4f%n", v.get(0).get(GRB.DoubleAttr.X)); - if (m.get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE) { - System.out.println("Model infeasible—computing IIS..."); - m.computeIIS(); - for (GRBConstr c : m.getConstrs()) { - if (c.get(GRB.IntAttr.IISConstr) == 1) { - System.out.println("IIS: " + c.get(GRB.StringAttr.ConstrName)); - } - } - // Optionally write the IIS to a file: - m.write("model.IIS"); - } - int status = m.get(GRB.IntAttr.Status); - System.out.println("Gurobi Status = " + status); - - soln = new double[n]; - for (int s = 0; s < n; s++) { - System.out.println(v.get(s).get(GRB.StringAttr.VarName) + " = "+v.get(s).get(GRB.DoubleAttr.X)); - soln[s] = v.get(s).get(GRB.DoubleAttr.X); - } - - mainLog.println("Multi Strategy to Obtain at least under worst assumption of adversary" + bound); - - - // How many solutions are in the pool? - int solCount = m.get(GRB.IntAttr.SolCount); - - // Loop over each solution k=0…solCount−1 - - for (int s = 0; s < n; s++) { - mainLog.print(s + ":"); - int numChoices = imdp.getNumChoices(s); - for (int i = 0; i < numChoices; i++) { - String sc = s +"-"+i; - if (eta.get(sc).get(GRB.DoubleAttr.X) > 0) { - mainLog.print(" " + imdp.getAction(s, i)); - } - } - mainLog.println(); - } - m.dispose(); - env.dispose(); - } catch (GRBException e) { - throw new PrismException("Error solving LP: " +e.getMessage()); - } - } - long time = (System.currentTimeMillis() - timer); - mainLog.println("It took "+time + " milli-seconds to finish synthesize the permissive strategy"); - - // Return results - ModelCheckerResult res = new ModelCheckerResult(); -// res.accuracy = AccuracyFactory.boundedNumericalIterations(); - res.soln = soln; -// res.timeTaken = timer / 1000.0; - return res; - } /** * Simple test program. diff --git a/sav-imdp.prism b/sav-imdp.prism index 3d140258d7..dd5662ac10 100644 --- a/sav-imdp.prism +++ b/sav-imdp.prism @@ -22,8 +22,8 @@ const double pLMin=pL*(1-pLDiff); const double pHMin= pH*(1-pHDiff); // Grid size -const int Xsize = 8; -const int Ysize = 8; +const int Xsize = 5; +const int Ysize = 5; // Number of tries before an error const int MAXTRIES = 2; // Ball within the robot has to move. diff --git a/strat1.txt b/strat1.txt new file mode 100644 index 0000000000..ec5f9b25e0 --- /dev/null +++ b/strat1.txt @@ -0,0 +1,231 @@ +0: up +1: down up stay +2: down up stay +3: down up stay +4: up +5: up +6: down up stay +7: up +8: up +9: up +10: down up stay +11: down up stay +12: down up stay +13: down up stay +14: down up stay +15: down up stay +16: down up stay +17: down up stay +18: up +19: up +20: up +21: down up stay +22: up stay +23: up +24: up +25: down up stay +26: down up stay +27: down up stay +28: down up stay +29: down up stay +30: down up stay +31: down up stay +32: down up stay +33: down up stay +34: down up stay +35: down up stay +36: up stay +37: down up stay +38: down up stay +39: down up stay +40: down up stay +41: up stay +42: up +43: down up stay +44: down up stay +45: down up stay +46: down up stay +47: up stay +48: up stay +49: down up stay +50: down up stay +51: down up stay +52: down up stay +53: down up stay +54: down up stay +55: down up stay +56: down up stay +57: down up stay +58: down up stay +59: down up stay +60: down up stay +61: down up stay +62: down up stay +63: up stay +64: down up stay +65: down up stay +66: down up stay +67: down up stay +68: down up stay +69: up stay +70: up +71: down up stay +72: down up stay +73: down up stay +74: down up stay +75: down up stay +76: up stay +77: up +78: down up stay +79: down up stay +80: down up stay +81: down up stay +82: down up stay +83: down up stay +84: down up stay +85: down up stay +86: down up stay +87: down up stay +88: down up stay +89: down up stay +90: down up stay +91: down up stay +92: down up stay +93: down up stay +94: down up stay +95: down up stay +96: down up stay +97: down up stay +98: down up stay +99: down up stay +100: down up stay +101: down up stay +102: down up stay +103: down up stay +104: down up stay +105: down up stay +106: down up stay +107: down up stay +108: down up stay +109: down up stay +110: down up stay +111: down up stay +112: down up stay +113: down up stay +114: down up stay +115: down up stay +116: down up stay +117: down up stay +118: down up stay +119: down up stay +120: down up stay +121: down up stay +122: down up stay +123: down up stay +124: down up stay +125: down up stay +126: down up stay +127: down up stay +128: down up stay +129: down up stay +130: down up stay +131: down up stay +132: down up stay +133: down up stay +134: down up stay +135: down up stay +136: down up stay +137: down up stay +138: down up stay +139: down up stay +140: down up stay +141: down up stay +142: down up stay +143: down up stay +144: down up stay +145: down up stay +146: down up stay +147: down up stay +148: down up stay +149: down up stay +150: down up stay +151: down up stay +152: down up stay +153: down up stay +154: down up stay +155: down up stay +156: down up stay +157: down up stay +158: down up stay +159: down up stay +160: down up stay +161: down up stay +162: down up stay +163: down up stay +164: down up stay +165: down up stay +166: down up stay +167: down up stay +168: down up stay +169: down up stay +170: down up stay +171: down up stay +172: down up stay +173: down up stay +174: down up stay +175: down up stay +176: down up stay +177: down up stay +178: down up stay +179: down up stay +180: down up stay +181: down up stay +182: down up stay +183: down up stay +184: down up stay +185: down up stay +186: down up stay +187: down up stay +188: down up stay +189: down up stay +190: down up stay +191: down up stay +192: down up stay +193: down up stay +194: down up stay +195: down up stay +196: down up stay +197: down up stay +198: down up stay +199: down up stay +200: down up stay +201: down up stay +202: down up stay +203: down up stay +204: down up stay +205: down up stay +206: down up stay +207: down up stay +208: down up stay +209: down up stay +210: down up stay +211: down up stay +212: down up stay +213: down up stay +214: down up stay +215: down up stay +216: down up stay +217: down up stay +218: down up stay +219: down up stay +220: down up stay +221: down up stay +222: down up stay +223: down up stay +224: down up stay +225: down up stay +226: down up stay +227: down up stay +228: down up stay +229: down up stay +230: down up stay \ No newline at end of file diff --git a/strat2.txt b/strat2.txt new file mode 100644 index 0000000000..5616dbcab2 --- /dev/null +++ b/strat2.txt @@ -0,0 +1,231 @@ +0: up +1: down up stay +2: down up stay +3: down up stay +4: up +5: up +6: down up stay +7: up +8: up +9: up +10: down up stay +11: down up stay +12: down up stay +13: down up stay +14: down up stay +15: down up stay +16: down up stay +17: down up stay +18: up +19: up +20: up +21: down up stay +22: up stay +23: up +24: up +25: down up stay +26: down up stay +27: down up stay +28: down up stay +29: down up stay +30: down up stay +31: down up stay +32: down up stay +33: down up stay +34: down up stay +35: down up stay +36: up +37: down up stay +38: down up stay +39: down up stay +40: down up stay +41: up stay +42: up +43: down up stay +44: down up stay +45: down up stay +46: down up stay +47: up stay +48: up stay +49: down up stay +50: down up stay +51: down up stay +52: down up stay +53: down up stay +54: down up stay +55: down up stay +56: down up stay +57: down up stay +58: down up stay +59: down up stay +60: down up stay +61: down up stay +62: down up stay +63: down up stay +64: down up stay +65: down up stay +66: down up stay +67: down up stay +68: down up stay +69: up stay +70: up +71: down up stay +72: down up stay +73: down up stay +74: down up stay +75: down up stay +76: up stay +77: up +78: down up stay +79: down up stay +80: down up stay +81: down up stay +82: down up stay +83: down up stay +84: down up stay +85: down up stay +86: down up stay +87: down up stay +88: down up stay +89: down up stay +90: down up stay +91: down up stay +92: down up stay +93: down up stay +94: down up stay +95: down up stay +96: down up stay +97: down up stay +98: down up stay +99: down up stay +100: down up stay +101: down up stay +102: down up stay +103: down up stay +104: down up stay +105: down up stay +106: down up stay +107: down up stay +108: down up stay +109: down up stay +110: down up stay +111: down up stay +112: down up stay +113: down up stay +114: down up stay +115: down up stay +116: down up stay +117: down up stay +118: down up stay +119: down up stay +120: down up stay +121: down up stay +122: down up stay +123: down up stay +124: down up stay +125: down up stay +126: down up stay +127: down up stay +128: down up stay +129: down up stay +130: down up stay +131: down up stay +132: down up stay +133: down up stay +134: down up stay +135: down up stay +136: down up stay +137: down up stay +138: down up stay +139: down up stay +140: down up stay +141: down up stay +142: down up stay +143: down up stay +144: down up stay +145: down up stay +146: down up stay +147: down up stay +148: down up stay +149: down up stay +150: down up stay +151: down up stay +152: down up stay +153: down up stay +154: down up stay +155: down up stay +156: down up stay +157: down up stay +158: down up stay +159: down up stay +160: down up stay +161: down up stay +162: down up stay +163: down up stay +164: down up stay +165: down up stay +166: down up stay +167: down up stay +168: down up stay +169: down up stay +170: down up stay +171: down up stay +172: down up stay +173: down up stay +174: down up stay +175: down up stay +176: down up stay +177: down up stay +178: down up stay +179: down up stay +180: down up stay +181: down up stay +182: down up stay +183: down up stay +184: down up stay +185: down up stay +186: down up stay +187: down up stay +188: down up stay +189: down up stay +190: down up stay +191: down up stay +192: down up stay +193: down up stay +194: down up stay +195: down up stay +196: down up stay +197: down up stay +198: down up stay +199: down up stay +200: down up stay +201: down up stay +202: down up stay +203: down up stay +204: down up stay +205: down up stay +206: down up stay +207: down up stay +208: down up stay +209: down up stay +210: down up stay +211: down up stay +212: down up stay +213: down up stay +214: down up stay +215: down up stay +216: down up stay +217: down up stay +218: down up stay +219: down up stay +220: down up stay +221: down up stay +222: down up stay +223: down up stay +224: down up stay +225: down up stay +226: down up stay +227: down up stay +228: down up stay +229: down up stay +230: down up stay \ No newline at end of file diff --git a/test1.prism b/test1.prism new file mode 100644 index 0000000000..442fe72cb4 --- /dev/null +++ b/test1.prism @@ -0,0 +1,20 @@ +mdp + +module OneOut_allLoPositive + // States: 0 initial; 1 goes to goal; 2 goes to sink; 3 goal; 4 sink + s : [0..4] init 0; + + // Only one successor per action (prob must be 1 in any feasible assignment) + [a] s=0 -> [0.90,1.00] : (s'=1); + [b] s=0 -> [0.90,1.00] : (s'=2); + + // Route to absorbing goal/sink + [t1] s=1 -> (s'=3); + [t2] s=2 -> (s'=4); + + [end1] s=3 -> (s'=3); // goal + [end2] s=4 -> (s'=4); // sink +endmodule + +label "goal" = s=3; +label "Crash" = s=4; diff --git a/test15.prism b/test15.prism new file mode 100644 index 0000000000..38b46bfcfb --- /dev/null +++ b/test15.prism @@ -0,0 +1,71 @@ +mdp + +module Fifteen + // 0 = initial; 1..15 = uncertain successors; 16 = goal; 17 = sink + s : [0..17] init 0; + + // ---- Action a: one heavy, two medium, rest small + // lo sum = 0.30 + 2*0.05 + 12*0.02 = 0.64 <= 1 + // hi sum = 0.60 + 2*0.25 + 12*0.12 = 2.54 >= 1 + [a] s=0 -> + [0.30,0.60] : (s'=1) + + [0.05,0.25] : (s'=2) + + [0.05,0.25] : (s'=3) + + [0.02,0.12] : (s'=4) + + [0.02,0.12] : (s'=5) + + [0.02,0.12] : (s'=6) + + [0.02,0.12] : (s'=7) + + [0.02,0.12] : (s'=8) + + [0.02,0.12] : (s'=9) + + [0.02,0.12] : (s'=10) + + [0.02,0.12] : (s'=11) + + [0.02,0.12] : (s'=12) + + [0.02,0.12] : (s'=13) + + [0.02,0.12] : (s'=14) + + [0.02,0.12] : (s'=15); + + // ---- Action b: two “heads” elsewhere, many smalls (different shape) + // lo sum = 2*0.12 + 13*0.01 = 0.37 <= 1 + // hi sum = 2*0.32 + 13*0.09 = 1.81 >= 1 + [b] s=0 -> + [0.01,0.09] : (s'=1) + + [0.01,0.09] : (s'=2) + + [0.01,0.09] : (s'=3) + + [0.01,0.09] : (s'=4) + + [0.01,0.09] : (s'=5) + + [0.01,0.09] : (s'=6) + + [0.01,0.09] : (s'=7) + + [0.12,0.32] : (s'=8) + // head #1 placed away from action a's heavy + [0.12,0.32] : (s'=9) + // head #2 + [0.01,0.09] : (s'=10) + + [0.01,0.09] : (s'=11) + + [0.01,0.09] : (s'=12) + + [0.01,0.09] : (s'=13) + + [0.01,0.09] : (s'=14) + + [0.01,0.09] : (s'=15); + + // successors: 1..6 -> goal, 7..15 -> sink + [] s=1 -> (s'=16); + [] s=2 -> (s'=16); + [] s=3 -> (s'=16); + [] s=4 -> (s'=16); + [] s=5 -> (s'=16); + [] s=6 -> (s'=16); + + [] s=7 -> (s'=17); + [] s=8 -> (s'=17); + [] s=9 -> (s'=17); + [] s=10 -> (s'=17); + [] s=11 -> (s'=17); + [] s=12 -> (s'=17); + [] s=13 -> (s'=17); + [] s=14 -> (s'=17); + [] s=15 -> (s'=17); + + // absorbing goal/sink + [] s=16 -> (s'=16); + [] s=17 -> (s'=17); +endmodule + +label "goal" = s=16; +label "Crash" = s=17; diff --git a/value1.txt b/value1.txt new file mode 100644 index 0000000000..c8f43fde19 --- /dev/null +++ b/value1.txt @@ -0,0 +1,231 @@ +state: 0, value: 0.48 +state: 1, value: 0.0 +state: 2, value: 0.0 +state: 3, value: 0.0 +state: 4, value: 0.4689952656874547 +state: 5, value: 0.327516845792529 +state: 6, value: 0.0 +state: 7, value: 0.8231826224370418 +state: 8, value: 0.6118128488940866 +state: 9, value: 0.30537841530425824 +state: 10, value: 0.0 +state: 11, value: 0.0 +state: 12, value: 0.0 +state: 13, value: 0.0 +state: 14, value: 0.0 +state: 15, value: 0.0 +state: 16, value: 0.0 +state: 17, value: 0.0 +state: 18, value: 0.7586770833603308 +state: 19, value: 0.46306426114710747 +state: 20, value: 0.18350792936033053 +state: 21, value: 0.0 +state: 22, value: 0.9432541848004731 +state: 23, value: 0.7618576232185752 +state: 24, value: 0.3909836966810877 +state: 25, value: 0.0 +state: 26, value: 0.0 +state: 27, value: 0.0 +state: 28, value: 0.0 +state: 29, value: 0.0 +state: 30, value: 0.0 +state: 31, value: 0.0 +state: 32, value: 0.0 +state: 33, value: 0.0 +state: 34, value: 0.0 +state: 35, value: 0.0 +state: 36, value: 0.4685673999999999 +state: 37, value: 0.0 +state: 38, value: 0.0 +state: 39, value: 0.0 +state: 40, value: 0.0 +state: 41, value: 0.9730000000000004 +state: 42, value: 0.8738472826682405 +state: 43, value: 0.0 +state: 44, value: 0.0 +state: 45, value: 0.0 +state: 46, value: 0.9757000000000003 +state: 47, value: 0.9182981884454935 +state: 48, value: 0.6140202093838816 +state: 49, value: 0.0 +state: 50, value: 0.0 +state: 51, value: 0.0 +state: 52, value: 0.0 +state: 53, value: 0.0 +state: 54, value: 0.0 +state: 55, value: 0.0 +state: 56, value: 0.0 +state: 57, value: 0.0 +state: 58, value: 0.0 +state: 59, value: 0.0 +state: 60, value: 0.0 +state: 61, value: 0.0 +state: 62, value: 0.0 +state: 63, value: 0.6693819999999999 +state: 64, value: 0.0 +state: 65, value: 0.0 +state: 66, value: 0.0 +state: 67, value: 0.0 +state: 68, value: 0.0 +state: 69, value: 1.0 +state: 70, value: 0.91 +state: 71, value: 0.0 +state: 72, value: 0.0 +state: 73, value: 0.0 +state: 74, value: 0.0 +state: 75, value: 1.0 +state: 76, value: 1.0 +state: 77, value: 0.9061010469194081 +state: 78, value: 0.0 +state: 79, value: 0.0 +state: 80, value: 0.0 +state: 81, value: 0.9999999999999999 +state: 82, value: 1.0 +state: 83, value: 0.7287003489731361 +state: 84, value: 0.27942237732139374 +state: 85, value: 0.0 +state: 86, value: 0.0 +state: 87, value: 0.0 +state: 88, value: 0.0 +state: 89, value: 0.0 +state: 90, value: 0.0 +state: 91, value: 0.0 +state: 92, value: 0.0 +state: 93, value: 0.0 +state: 94, value: 0.0 +state: 95, value: 0.0 +state: 96, value: 0.0 +state: 97, value: 0.0 +state: 98, value: 0.0 +state: 99, value: 0.95626 +state: 100, value: 0.0 +state: 101, value: 0.0 +state: 102, value: 0.0 +state: 103, value: 0.0 +state: 104, value: 0.0 +state: 105, value: 1.0 +state: 106, value: 1.0 +state: 107, value: 0.0 +state: 108, value: 0.0 +state: 109, value: 0.0 +state: 110, value: 0.0 +state: 111, value: 1.0 +state: 112, value: 1.0 +state: 113, value: 1.0 +state: 114, value: 0.0 +state: 115, value: 0.0 +state: 116, value: 0.0 +state: 117, value: 1.0 +state: 118, value: 1.0 +state: 119, value: 1.0 +state: 120, value: 0.9855594330348446 +state: 121, value: 0.0 +state: 122, value: 0.0 +state: 123, value: 0.0 +state: 124, value: 0.0 +state: 125, value: 0.0 +state: 126, value: 0.0 +state: 127, value: 0.01280000000000002 +state: 128, value: 0.0 +state: 129, value: 1.0 +state: 130, value: 0.8380000000000001 +state: 131, value: 0.0 +state: 132, value: 0.0 +state: 133, value: 0.0 +state: 134, value: 0.0 +state: 135, value: 1.0 +state: 136, value: 1.0 +state: 137, value: 1.0 +state: 138, value: 0.0 +state: 139, value: 0.0 +state: 140, value: 0.24879999999999988 +state: 141, value: 1.0 +state: 142, value: 1.0 +state: 143, value: 1.0 +state: 144, value: 1.0 +state: 145, value: 0.0 +state: 146, value: 0.07001108447457788 +state: 147, value: 1.0 +state: 148, value: 1.0 +state: 149, value: 1.0 +state: 150, value: 1.0 +state: 151, value: 0.9598873139856795 +state: 152, value: 0.0 +state: 153, value: 1.0 +state: 154, value: 1.0 +state: 155, value: 1.0 +state: 156, value: 1.0 +state: 157, value: 0.9598873139856795 +state: 158, value: 0.05800747767960671 +state: 159, value: 1.0 +state: 160, value: 1.0 +state: 161, value: 0.40000000000000013 +state: 162, value: 0.0 +state: 163, value: 0.04000000000000006 +state: 164, value: 0.0 +state: 165, value: 1.0 +state: 166, value: 1.0 +state: 167, value: 1.0 +state: 168, value: 1.0 +state: 169, value: 0.0 +state: 170, value: 0.9771428571428568 +state: 171, value: 1.0 +state: 172, value: 1.0 +state: 173, value: 1.0 +state: 174, value: 1.0 +state: 175, value: 1.0 +state: 176, value: 0.0 +state: 177, value: 1.0 +state: 178, value: 1.0 +state: 179, value: 1.0 +state: 180, value: 1.0 +state: 181, value: 1.0 +state: 182, value: 0.9240290037607566 +state: 183, value: 1.0 +state: 184, value: 1.0 +state: 185, value: 1.0 +state: 186, value: 1.0 +state: 187, value: 1.0 +state: 188, value: 0.9088348045129081 +state: 189, value: 1.0 +state: 190, value: 1.0 +state: 191, value: 1.0 +state: 192, value: 1.0 +state: 193, value: 1.0 +state: 194, value: 0.908834804512908 +state: 195, value: 1.0 +state: 196, value: 1.0 +state: 197, value: 1.0 +state: 198, value: 1.0 +state: 199, value: 1.0 +state: 200, value: 1.0 +state: 201, value: 1.0 +state: 202, value: 1.0 +state: 203, value: 1.0 +state: 204, value: 1.0 +state: 205, value: 1.0 +state: 206, value: 1.0 +state: 207, value: 1.0 +state: 208, value: 1.0 +state: 209, value: 1.0 +state: 210, value: 1.0 +state: 211, value: 1.0 +state: 212, value: 1.0 +state: 213, value: 1.0 +state: 214, value: 1.0 +state: 215, value: 1.0 +state: 216, value: 1.0 +state: 217, value: 1.0 +state: 218, value: 1.0 +state: 219, value: 1.0 +state: 220, value: 1.0 +state: 221, value: 1.0 +state: 222, value: 1.0 +state: 223, value: 1.0 +state: 224, value: 1.0 +state: 225, value: 1.0 +state: 226, value: 1.0 +state: 227, value: 1.0 +state: 228, value: 1.0 +state: 229, value: 1.0 +state: 230, value: 1.0 \ No newline at end of file diff --git a/value2.txt b/value2.txt new file mode 100644 index 0000000000..5ab106abf1 --- /dev/null +++ b/value2.txt @@ -0,0 +1,231 @@ +state: 0, value: 0.48 +state: 1, value: 8.270999999893114E-5 +state: 2, value: 0.0016831499999979682 +state: 3, value: 0.011973429999998508 +state: 4, value: 0.49397929000000035 +state: 5, value: 0.33987007000000025 +state: 6, value: 0.008263499999999738 +state: 7, value: 0.8315032600000005 +state: 8, value: 0.6144472900000003 +state: 9, value: 0.30597061 +state: 10, value: 0.0 +state: 11, value: 0.0027569999999997874 +state: 12, value: 0.033129999999999105 +state: 13, value: 0.14650299999999838 +state: 14, value: 0.0 +state: 15, value: 0.0 +state: 16, value: 0.0027569999999997874 +state: 17, value: 0.023868999999999252 +state: 18, value: 0.8066170000000006 +state: 19, value: 0.47017600000000037 +state: 20, value: 0.18372900000000006 +state: 21, value: 0.0014339999999997133 +state: 22, value: 0.9435700000000009 +state: 23, value: 0.762391 +state: 24, value: 0.391381 +state: 25, value: 0.0 +state: 26, value: 0.0 +state: 27, value: 0.0 +state: 28, value: 0.09189999999999954 +state: 29, value: 0.3384999999999986 +state: 30, value: 0.6840999999999993 +state: 31, value: 0.0 +state: 32, value: 0.0 +state: 33, value: 0.0 +state: 34, value: 0.0918999999999992 +state: 35, value: 0.33849999999999925 +state: 36, value: 0.6958 +state: 37, value: 0.0 +state: 38, value: 0.0 +state: 39, value: 0.0 +state: 40, value: 0.04779999999999929 +state: 41, value: 0.9730000000000012 +state: 42, value: 0.8749000000000002 +state: 43, value: 0.0 +state: 44, value: 0.0 +state: 45, value: 0.0 +state: 46, value: 0.9757000000000007 +state: 47, value: 0.9189999999999999 +state: 48, value: 0.6147999999999998 +state: 49, value: 0.0 +state: 50, value: 0.0 +state: 51, value: 0.0 +state: 52, value: 0.0 +state: 53, value: 0.28 +state: 54, value: 0.7300000000000002 +state: 55, value: 1.0 +state: 56, value: 1.0 +state: 57, value: 0.0 +state: 58, value: 0.0 +state: 59, value: 0.0 +state: 60, value: 0.28 +state: 61, value: 0.7300000000000002 +state: 62, value: 1.0 +state: 63, value: 0.07 +state: 64, value: 0.0 +state: 65, value: 0.0 +state: 66, value: 0.0 +state: 67, value: 0.28 +state: 68, value: 0.7300000000000002 +state: 69, value: 1.0 +state: 70, value: 0.91 +state: 71, value: 0.0 +state: 72, value: 0.0 +state: 73, value: 0.0 +state: 74, value: 0.07 +state: 75, value: 1.0 +state: 76, value: 1.0 +state: 77, value: 0.91 +state: 78, value: 0.0 +state: 79, value: 0.0 +state: 80, value: 0.0 +state: 81, value: 1.0 +state: 82, value: 1.0 +state: 83, value: 0.7299999999999999 +state: 84, value: 0.28 +state: 85, value: 0.0 +state: 86, value: 0.0 +state: 87, value: 0.0 +state: 88, value: 0.0 +state: 89, value: 1.0 +state: 90, value: 1.0 +state: 91, value: 1.0 +state: 92, value: 1.0 +state: 93, value: 0.0 +state: 94, value: 0.0 +state: 95, value: 0.0 +state: 96, value: 1.0 +state: 97, value: 1.0 +state: 98, value: 1.0 +state: 99, value: 1.0 +state: 100, value: 0.0 +state: 101, value: 0.0 +state: 102, value: 0.0 +state: 103, value: 1.0 +state: 104, value: 1.0 +state: 105, value: 1.0 +state: 106, value: 1.0 +state: 107, value: 0.0 +state: 108, value: 0.0 +state: 109, value: 0.0 +state: 110, value: 1.0 +state: 111, value: 1.0 +state: 112, value: 1.0 +state: 113, value: 1.0 +state: 114, value: 0.0 +state: 115, value: 0.0 +state: 116, value: 0.0 +state: 117, value: 1.0 +state: 118, value: 1.0 +state: 119, value: 1.0 +state: 120, value: 1.0 +state: 121, value: 0.0 +state: 122, value: 0.0 +state: 123, value: 0.0 +state: 124, value: 1.0 +state: 125, value: 1.0 +state: 126, value: 1.0 +state: 127, value: 1.0 +state: 128, value: 1.0 +state: 129, value: 1.0 +state: 130, value: 1.0 +state: 131, value: 1.0 +state: 132, value: 1.0 +state: 133, value: 1.0 +state: 134, value: 1.0 +state: 135, value: 1.0 +state: 136, value: 1.0 +state: 137, value: 1.0 +state: 138, value: 1.0 +state: 139, value: 1.0 +state: 140, value: 1.0 +state: 141, value: 1.0 +state: 142, value: 1.0 +state: 143, value: 1.0 +state: 144, value: 1.0 +state: 145, value: 1.0 +state: 146, value: 1.0 +state: 147, value: 1.0 +state: 148, value: 1.0 +state: 149, value: 1.0 +state: 150, value: 1.0 +state: 151, value: 1.0 +state: 152, value: 1.0 +state: 153, value: 1.0 +state: 154, value: 1.0 +state: 155, value: 1.0 +state: 156, value: 1.0 +state: 157, value: 1.0 +state: 158, value: 0.0 +state: 159, value: 1.0 +state: 160, value: 1.0 +state: 161, value: 1.0 +state: 162, value: 1.0 +state: 163, value: 1.0 +state: 164, value: 1.0 +state: 165, value: 1.0 +state: 166, value: 1.0 +state: 167, value: 1.0 +state: 168, value: 1.0 +state: 169, value: 1.0 +state: 170, value: 1.0 +state: 171, value: 1.0 +state: 172, value: 1.0 +state: 173, value: 1.0 +state: 174, value: 1.0 +state: 175, value: 1.0 +state: 176, value: 1.0 +state: 177, value: 1.0 +state: 178, value: 1.0 +state: 179, value: 1.0 +state: 180, value: 1.0 +state: 181, value: 1.0 +state: 182, value: 1.0 +state: 183, value: 1.0 +state: 184, value: 1.0 +state: 185, value: 1.0 +state: 186, value: 1.0 +state: 187, value: 1.0 +state: 188, value: 1.0 +state: 189, value: 1.0 +state: 190, value: 1.0 +state: 191, value: 1.0 +state: 192, value: 1.0 +state: 193, value: 1.0 +state: 194, value: 1.0 +state: 195, value: 1.0 +state: 196, value: 1.0 +state: 197, value: 1.0 +state: 198, value: 1.0 +state: 199, value: 1.0 +state: 200, value: 1.0 +state: 201, value: 1.0 +state: 202, value: 1.0 +state: 203, value: 1.0 +state: 204, value: 1.0 +state: 205, value: 1.0 +state: 206, value: 1.0 +state: 207, value: 1.0 +state: 208, value: 1.0 +state: 209, value: 1.0 +state: 210, value: 1.0 +state: 211, value: 1.0 +state: 212, value: 1.0 +state: 213, value: 1.0 +state: 214, value: 1.0 +state: 215, value: 1.0 +state: 216, value: 1.0 +state: 217, value: 1.0 +state: 218, value: 1.0 +state: 219, value: 1.0 +state: 220, value: 1.0 +state: 221, value: 1.0 +state: 222, value: 1.0 +state: 223, value: 1.0 +state: 224, value: 1.0 +state: 225, value: 1.0 +state: 226, value: 1.0 +state: 227, value: 1.0 +state: 228, value: 1.0 +state: 229, value: 1.0 +state: 230, value: 1.0 \ No newline at end of file diff --git a/wh.prism b/wh.prism index 35b28c1bdb..49277f1899 100644 --- a/wh.prism +++ b/wh.prism @@ -1,7 +1,7 @@ mdp //─── PARAMETERS ────────────────────────────────────────────────────────────── -const int K = 500; // # of sub‐steps per move +const int K = 1000; // # of sub‐steps per move const double p = 0.7; // nominal success prob. const double e = 0.01; // uncertainty radius From 28c8c192557f775c1834401dbd86c753873d8da3 Mon Sep 17 00:00:00 2001 From: HVKHCM Date: Thu, 13 Nov 2025 11:27:14 -0500 Subject: [PATCH 11/11] All experiment --- experiment/ov-5x5.prism | 2 +- experiment/sav-imdp.prism | 2 +- experiment/wh.prism | 2 +- prism/src/explicit/IMDPModelChecker.java | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/experiment/ov-5x5.prism b/experiment/ov-5x5.prism index f9fddd9aa9..7b26f1a164 100644 --- a/experiment/ov-5x5.prism +++ b/experiment/ov-5x5.prism @@ -4,7 +4,7 @@ mdp const int N = 5; // grid size: 0..N-1 in both x and y const int K = 1000; // # of intermediate sub-steps per move const double p = 0.8; // intended-direction probability -const double e = 0.05; // slip‐interval half-width +const double e = 0.01; // slip‐interval half-width //─── HOLES & GOAL ────────────────────────────────────────────────────────────── formula hole = (x=1 & y=0) diff --git a/experiment/sav-imdp.prism b/experiment/sav-imdp.prism index dd5662ac10..6af53a15f5 100644 --- a/experiment/sav-imdp.prism +++ b/experiment/sav-imdp.prism @@ -11,7 +11,7 @@ mdp //The difference of the reliability of the channels between the worst and at the best position const double pLDiff=0.7; const double pHDiff=0.1; -const double u=0.08; +const double u=0.03; //Scaling factor for the minimum reliability of the channels const double pL=0.2; const double pH=0.3; diff --git a/experiment/wh.prism b/experiment/wh.prism index 3a32b446f6..0a6d34c384 100644 --- a/experiment/wh.prism +++ b/experiment/wh.prism @@ -3,7 +3,7 @@ mdp //─── PARAMETERS ────────────────────────────────────────────────────────────── const int K = 250; // # of sub‐steps per move const double p = 0.7; // nominal success prob. -const double e = 0.01; // uncertainty radius +const double e = 0.05; // uncertainty radius //─── STATE ──────────────────────────────────────────────────────────────────── module graph_imdp diff --git a/prism/src/explicit/IMDPModelChecker.java b/prism/src/explicit/IMDPModelChecker.java index 3a50d9b407..0370d2809c 100644 --- a/prism/src/explicit/IMDPModelChecker.java +++ b/prism/src/explicit/IMDPModelChecker.java @@ -629,9 +629,9 @@ public ModelCheckerResult computeReachRewards(IMDP imdp, MDPRewards imdp, MDPRewards mdpRewards, double bound) throws PrismException { - boolean value =false; - boolean min =false; - boolean robust=true; + boolean value =true; + boolean min =true; + boolean robust=false; if (value){ if (min){ return computeMultiStrategyValueMin(imdp, mdpRewards, bound, robust);