# -*- coding: utf-8 -*- # # Test computation of minimal initial loads for Büchi objective from math import inf from reachability_examples import ultimate, little_alsure from fimdp.energy_solvers import BasicES from fimdp.objectives import BUCHI # ## Test case 1 # Simple computation of Büchi values on a non-trivial example where we need to go through reload states to obtain the optimal values. # + m, targets = ultimate() solver = BasicES(m, 15, targets) result = solver.get_min_levels(BUCHI) expected = [6, inf, inf, 3, 0, 1, 10, inf, 4, inf, inf] solver # - assert result == expected, ("get_min_levels(BUCHI) returns" + " wrong values:\n" + f" expected: {expected}\n returns: {result}\n") print("Passed test 1 for get_min_levels(BUCHI) in test_buchi file.") # ## Test case 2: insufficient capacity # The same MDP, now with capacity 14. No initial load is enough. solver.cap = 14 result = solver.get_min_levels(BUCHI, recompute=True)
strategy_at(threshold_class, problematic, capacity=35) # This strategy uses the strong actions (`4`—`7`) for energy between 16 and 27. It goes `NORTH=4` only with interval 16—18, and prefers to go to `SOUTH=6` with energy in 19—28, and finally uses weak action to `EAST` with more than 27 units of energy. # ## Equivalent values # In this section, we show that the new solvers are actually improving the Basic solver while maintaining the same minimal energy levels needed to fulfill the objectives. These values can be obtained by calling the `get_min_levels(BUCHI)` on the solvers. from fimdp.objectives import BUCHI m, t = e.get_consmdp() basic = BasicES(m, cap=35, targets=t) goal = GoalLeaningES(m, cap=35, targets=t) threshold = GoalLeaningES(m, cap=35, targets=t, threshold=0.1) assert basic.get_min_levels(BUCHI) == goal.get_min_levels(BUCHI), ( "The basic and goal-leaning strategy " + "do not reach the same values of " + "initial load for the same task.") print( "Passed test 1 for values of goal-leaning strategies in file tut/Solvers.ipynb" ) assert basic.get_min_levels(BUCHI) == threshold.get_min_levels(BUCHI), ( "The basic and the threshold strategy " + "do not reach the same values of " + "initial load for the same task.") print( "Passed test 2 for values of goal-leaning strategies in file tut/Solvers.ipynb" ) # ## Interesting cases # # ### Sure path with 2 steps better than unlikely 1-step path.
try: selector.select_action(2, 16) assert False except NoFeasibleActionError: print( "Passed test 5 for CounterSelector (select_action) in file test_strategy.py" ) # ### Copy values from # + selector_from = selector #m, T = basic() solver = BasicES(m, 40, T) solver.get_min_levels(POS_REACH) selector_to = solver.get_selector(POS_REACH, True) selector_to expected = selector_to.copy() result = CounterSelector(m) result.copy_values_from(selector_to) assert result == expected # - expected[0][2] = m.actions_for_state(0).__next__() expected selector_to.copy_values_from(selector_from, [0]) assert selector_to == expected selector_to.copy_values_from(selector_from, [3])
prev_e = curr_e m.add_action(prev_o,{0:1},"p",1) m.add_action(prev_e,{1:1},"p",1) return m fimdp.dot.dotpr = "neato" "" cap = 32 # We have cap/2 reload states, cap/4 in each flower path = 6 m = consMDP_double_flower(cap, path) solver = BasicES(m, cap=cap + 2, targets=[2]) result = solver.get_min_levels(POS_REACH) expected = [3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3] solver "" assert result == expected, ("get_positive_reachability() returns" + " wrong values:\n" + f" expected: {expected}\n returns: {result}\n") print("Passed test 1 for get_positive_reachability() in test_reachability file.") "" solver = BasicES(m, cap=cap, targets=[2]) result = solver.get_min_levels(POS_REACH) expected = [31, 30, 0, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31, 32, 31] solver
# Create a deterministic automaton for the desired formula f = spot.formula("GF s1 & GF s2") aut = spot.translate(f, "BA", "deterministic", "complete") assert aut.is_deterministic() aut # Build the product. It should contain states named in the form `mdp_state,automaton_state`. p, T = lmdp.product_with_dba(aut) assert p.names == ['0,1', '1,0', '2,1', '3,1', '3,0', '0,0', '2,2'] print("Passed test 1 for product in file test_product.py") psolver = BasicES(p, 5, T) res = psolver.get_min_levels(BUCHI) assert res == [inf, inf, inf, inf, inf, inf, inf] print("Passed test 2 for product in file test_product.py") # + psolver.cap = 9 res = psolver.get_selector(BUCHI, recompute=True) result = [] for rule in res: result.append({k: v.label for k, v in rule.items()}) assert result == [{ 6: 'α', 2: 'β' }, { 3: 'r'
m.add_action(4, {1:1}, "a", 0) m.add_action(7, {3:1}, "a", 1) m.add_action(7, {6:1}, "b", 1) m.add_action(6, {4:.5, 5:.5}, "a", 5) m.add_action(5, {1:1}, "a", 6) m.add_action(8, {9:1}, "a", 1) m.add_action(8, {1:1}, "b", 3) m.add_action(10, {1:.5, 11:.5}, "a", 2) m.add_action(0, {0:1}, "r", 0) m.add_action(9, {9:1}, "r", 0) m.add_action(11, {11:1}, "a", 1) MI = BasicES(m, inf, None) # - result = MI.get_min_levels(MIN_INIT_CONS) expected = [0, 3, 2, 1, 3, 9, 14, 1, 1, 0, 5, 1, 1] MI assert result == expected, ("BasicES.get_min_levels(MIN_INIT_CONS) returns" + " wrong values:\n" + f" expected: {expected}\n returns: {result}\n") print("Passed test 1 for BasicES.get_min_levels(MIN_INIT_CONS) in test_safety file.") # If state 11 is not a reload state, we cannot reach reload from 10 for sure. # + m.unset_reload(11) result = MI.get_min_levels(MIN_INIT_CONS, recompute=True) expected = [0, 3, 2, 1, 3, 9, 14, 1, 1, 0, inf, inf, 1]
m.add_action(4, {5: 1}, "", 1) m.add_action(5, {4: 1}, "r", 1) m.add_action(5, {3: 1}, "t", 1) m.add_action(6, {7: .5, 10: .5}, "a", 3) m.add_action(6, {3: .5, 8: .5}, "B", 6) m.add_action(7, {9: 1}, "", 1) m.add_action(9, {9: 1}, "", 1) m.add_action(10, {9: 1}, "", 1) m.add_action(8, {5: 1}, "r", 3) solver = BasicES(m, 15, T) result = solver.get_min_levels(BUCHI) expected = [6, inf, inf, 3, 0, 1, 10, inf, 4, inf, inf] assert result == expected, ("get_min_levels(BUCHI) returns" + " wrong values:\n" + f" expected: {expected}\n returns: {result}\n") # WIth cap < 15, we get all infs solver = BasicES(m, 14, T) result = solver.get_min_levels(BUCHI) expected = [inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf] assert result == expected, ("get_min_levels(BUCHI) returns" + " wrong values:\n" + f" expected: {expected}\n returns: {result}\n")
} mdp = prism_to_consmdp("gw_param.prism", constants=constants) targets = [ 2789, 2768, 2915, 2786, 2566, 2302, 3408, 2260, 2641, 2176, 2695, 2881, 2893, 3414, 2361, 1835, 2199, 2267, 2967, 2983, 2672, 2977, 2176, 2367, 3326, 3448, 2903, 2549, 2659, 3408, 2776, 2385, 3185, 3421, 2195, 3292, 2109, 2379, 3018, 3224, 2559, 3112, 2956, 2448, 2294, 2790, 2464, 3291, 2294, 2546, 2200, 625, 676, 729, 2547, 2386, 2696, 2177, 2660, 2295, 2110 ] for target in [2110]: print("========construction on randomly chosen target========") cap = 60 targets = [target] solver = BasicES(mdp, cap, targets) SF = solver.get_min_levels(SAFE) SFR = solver.get_min_levels(POS_REACH) SFRR = solver.get_min_levels(BUCHI) formula = 'Pmax=? [F "target" ]' prop = stormpy.parse_properties(formula) bisimulation_mdp, nstorm_result, n_strategy = MRP_by_naive( mdp, targets, cap, SF) smart_mdp, storm_result, p_strategy = MRP_by_pruned( mdp, targets, cap, SF, SFR, SFRR) smarter_mdp, smarter_storm_result, q_strategy = MRP_by_quotient( smart_mdp, SFR, SFRR)
from fimdp.io import prism_to_consmdp, parse_cap_from_prism, \ consmdp_to_storm_consmdp, storm_sparsemdp_to_consmdp, \ encode_to_stormpy from fimdp.energy_solvers import BasicES from fimdp.objectives import BUCHI, AS_REACH from fimdp.examples.cons_mdp import little_alsure from fimdp.explicit import product_energy import stormpy mdp = prism_to_consmdp("prism_models/gw_50_full.prism") assert mdp.num_states == 2500, ("Wrong number of states: " f"{mdp.num_states} instead of 2500.") solver = BasicES(mdp, cap=180, targets=[620]) solver.get_min_levels(BUCHI) expected = "0: x=0 y=0" result = mdp.names[0] assert result == expected, ("Wrong state name, should be: " f"`{expected}` and is `{result}`.") print("Passed test 1 for prism_to_consmdp.") try: prism_to_consmdp("prism_models/gw_50_norew.prism") assert False, "Detection of missing consumption failed" except ValueError as e: print("Passed test 2 for prism_to_consmdp. [no consumption]") try: prism_to_consmdp("prism_models/gw_50_norel.prism") assert False, "Detection of missing reloads failed" except ValueError as e:
# # Test computation of minimal capacity from reachability_examples import ultimate from fimdp.energy_solvers import BasicES from fimdp.objectives import AS_REACH, BUCHI from fimdp.mincap_solvers import bin_search # In the following example, the minimal capacity is 15 for Buchi objective defined by the blue states. m, T = ultimate() solver15 = BasicES(m, 15, T) solver15.get_min_levels(BUCHI) solver15 solver14 = BasicES(m, 14, T) solver14.get_min_levels(BUCHI) solver14 # + result = bin_search(m, 0, T) expected = 15 assert result == expected, ( f"The minimal capacity should be {expected}, not {result}.") print("Passed test 1 for bin_search() in test_mincap.py file.") # - # ### Capacity too small # If the starting capacity is not enough, an exception should be raised. try: