//============================================================================== // // Copyright (c) 2002- // Authors: // * Dave Parker (University of Birmingham/Oxford) // //------------------------------------------------------------------------------ // // This file is part of PRISM. // // PRISM is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // PRISM is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with PRISM; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //============================================================================== package explicit; import java.util.BitSet; import java.util.Iterator; import java.util.PrimitiveIterator; import java.util.function.IntPredicate; import prism.PrismLog; import strat.MDStrategy; /** * Interface for (abstract) classes that provide (read-only) access to an explicit-state model with nondeterminism. */ public interface NondetModel extends Model { // Accessors /** * Get the number of nondeterministic choices in state s. */ public int getNumChoices(int s); /** * Get the maximum number of nondeterministic choices in any state. */ public int getMaxNumChoices(); /** * Get the total number of nondeterministic choices over all states. */ public int getNumChoices(); /** * Get the action label (if any) for choice {@code i} of state {@code s}. */ public Object getAction(int s, int i); /** * Do all choices in in each state have a unique action label? */ public boolean areAllChoiceActionsUnique(); /** * Get the number of transitions from choice {@code i} of state {@code s}. */ public int getNumTransitions(int s, int i); /** * Get the number of transitions leaving a set of states. *
* Default implementation: Iterate over the states s and choices i * and sum the result of getNumTransitions(s,i). * @param states The set of states, specified by a OfInt iterator * @return the number of transitions */ public default long getNumTransitions(PrimitiveIterator.OfInt states) { long count = 0; while (states.hasNext()) { int s = states.nextInt(); for (int choice = 0, numChoices = getNumChoices(s); choice < numChoices; choice++) { count += getNumTransitions(s, choice); } } return count; } /** * Check if all the successor states from choice {@code i} of state {@code s} are in the set {@code set}. * @param s The state to check * @param i Choice index * @param set The set to test for inclusion */ public default boolean allSuccessorsInSet(int s, int i, BitSet set) { return allSuccessorsMatch(s, i, set::get); } /** * Check if some successor state from choice {@code i} of state {@code s} is in the set {@code set}. * @param s The state to check * @param i Choice index * @param set The set to test for inclusion */ public default boolean someSuccessorsInSet(int s, int i, BitSet set) { return someSuccessorsMatch(s, i, set::get); } /** * Check the successor states from choice {@code i} of state {@code s}: * Return {@code true} iff all successors are contained in {@code u} * (remain in a "safe" region) and at least one is contained in {@code v} * (can reach the region defined by v). * @param s The state to check * @param i Choice index * @param u The BitSet that all successors have to be in * @param v The BitSet that some successors have to be in */ public default boolean successorsSafeAndCanReach(int s, int i, BitSet u, BitSet v) { return successorsSafeAndCanReach(s, i, u::get, v::get); } /** * Check if all the successor states from choice {@code i} of state {@code s} match the predicate. * @param s The state to check * @param i Choice index * @param p The predicate */ public default boolean allSuccessorsMatch(int s, int i, IntPredicate p) { // the code for this method is equivalent to the following stream expression, // but kept explicit for performance // // return getSuccessors(s,i).stream().allMatch(p); SuccessorsIterator it = getSuccessors(s,i); while (it.hasNext()) { int t = it.nextInt(); if (!p.test(t)) return false; } return true; } /** * Check if some successor state from choice {@code i} of state {@code s} match the predicate. * @param s The state to check * @param i Choice index * @param p The predicate */ public default boolean someSuccessorsMatch(int s, int i, IntPredicate p) { // the code for this method is equivalent to the following stream expression, // but kept explicit for performance // // return getSuccessors(s,i).stream().anyMatch(p); SuccessorsIterator it = getSuccessors(s, i); while (it.hasNext()) { int t = it.nextInt(); if (p.test(t)) return true; } return false; } /** * Check the successor states from choice {@code i} of state {@code s}: * Return {@code true} iff all successors match the predicate {@code u} * (remain in a "safe" region) and at least one matches predicate {@code v} * (can reach the region defined by v). * @param s The state to check * @param i Choice index * @param u The first predicate (all successors have to match) * @param v The second predicate (some successors have to match) */ public default boolean successorsSafeAndCanReach(int s, int i, IntPredicate u, IntPredicate v) { SuccessorsIterator it = getSuccessors(s, i); boolean hadTransitionToV = false; while (it.hasNext()) { int t = it.nextInt(); if (!u.test(t)) return false; if (!hadTransitionToV) { hadTransitionToV = v.test(t); } } return hadTransitionToV; } /** * Get an iterator over the successor states from choice {@code i} of state {@code s}. * @param s The state * @param i Choice index */ public default Iterator getSuccessorsIterator(int s, int i) { SuccessorsIterator successors = getSuccessors(s, i); return successors.distinct(); } /** * Get a SuccessorsIterator for state s and choice i. * @param s The state * @param i Choice index */ public SuccessorsIterator getSuccessors(int s, int i); @Override public default SuccessorsIterator getSuccessors(final int s) { return SuccessorsIterator.chain(new Iterator() { private int choice = 0; private int choices = getNumChoices(s); @Override public boolean hasNext() { return choice < choices; } @Override public SuccessorsIterator next() { return getSuccessors(s, choice++); } }); } /** * Construct a model that is induced by applying strategy {@code strat} to this model. * Note that the "new" model may be just an implicit (read-only) representation. * @param strat (Memoryless) strategy to use */ public Model constructInducedModel(MDStrategy strat); /** * Export to a dot file, highlighting states in 'mark' and choices for a (memoryless) strategy. */ public void exportToDotFileWithStrat(PrismLog out, BitSet mark, int strat[]); }