1#ifndef VERIFICATION_POLICY_VERIFICATION_H
2#define VERIFICATION_POLICY_VERIFICATION_H
4#include "probfd/storage/per_state_storage.h"
7#include "probfd/policy.h"
19template <
typename State,
typename Action>
20extern bool verify_policy(
29 bool explored =
false;
30 unsigned stack_id = std::numeric_limits<unsigned>::max();
33 struct ExplorationInfo {
41 unsigned lowlink = std::numeric_limits<unsigned>::max();
46 std::stack<ExplorationInfo> open;
47 std::vector<probfd::StateID> stack;
48 storage::PerStateStorage<StateInfo> state_infos;
50 open.emplace(init_id, 0);
54 ExplorationInfo* info = &open.top();
58 StateInfo* state_info = &state_infos[state_id];
60 state_info->explored =
true;
61 state_info->stack_id = stack.size();
62 stack.push_back(state_id);
68 if (decision)
return false;
69 state_info->is_dead =
false;
74 if (!decision)
return false;
86 for (
const auto [successor_id, probability] : info->successors) {
87 const State successor = mdp.
get_state(successor_id);
88 std::optional succ_decision = policy.
get_decision(successor);
91 succ_decision ? succ_decision->q_value_interval.lower
94 expected_cost += probability * succ_val;
98 decision->q_value_interval.lower,
103 if (info->successors.empty()) abort();
109 (info->successors.end() - 1)->item;
110 StateInfo& succ_info = state_infos[successor_id.id];
112 if (!succ_info.explored) {
113 open.emplace(successor_id, stack.size());
117 state_info->is_dead = state_info->is_dead && succ_info.is_dead;
118 info->lowlink = std::min(info->lowlink, succ_info.stack_id);
119 info->successors.erase(info->successors.end() - 1);
120 }
while (!info->successors.empty());
126 const unsigned stack_id = state_info->stack_id;
127 const unsigned lowlink = info->lowlink;
130 if (stack_id == lowlink) {
132 if (state_info->is_dead)
return false;
134 std::ranges::subrange scc(
135 stack.begin() + stack_id,
140 state_infos[state_id.id].stack_id =
141 std::numeric_limits<unsigned>::max();
144 stack.erase(scc.begin(), scc.end());
150 if (open.empty())
return true;
153 state_id = info->state_id;
155 state_info = &state_infos[state_id];
159 (info->successors.end() - 1)->item;
161 const StateInfo& succ_info = state_infos[successor_id.id];
162 state_info->is_dead = state_info->is_dead && succ_info.is_dead;
163 info->lowlink = std::min(info->lowlink, lowlink);
164 info->successors.erase(info->successors.end() - 1);
165 }
while (info->successors.empty());
virtual value_t get_action_cost(param_type< Action > action)=0
Gets the cost of an action.
virtual TerminationInfo get_termination_info(param_type< State > state)=0
Returns the cost to terminate in a given state and checks whether a state is a goal.
A convenience class that represents a finite probability distribution.
Definition task_state_space.h:27
Basic interface for MDPs.
Definition mdp_algorithm.h:14
Represents a deterministic, stationary, partial policy.
Definition solver_interface.h:16
virtual std::optional< PolicyDecision< Action > > get_decision(const State &state) const =0
Retrives the action and optimal state value interval specified by the policy for a given state.
virtual State get_state(StateID state_id)=0
Get the state mapped to a given state ID.
virtual void generate_action_transitions(param_type< State > state, param_type< Action > action, Distribution< StateID > &result)=0
Generates the successor distribution for a given state and action.
bool is_goal_state() const
Check if this state is a goal.
Definition cost_function.h:34
The top-level namespace of probabilistic Fast Downward.
Definition command_line.h:8
double value_t
Typedef for the state value type.
Definition aliases.h:7
bool is_approx_equal(value_t v1, value_t v2, value_t epsilon=g_epsilon)
Equivalent to .
A StateID represents a state within a StateIDMap. Just like Fast Downward's StateID type,...
Definition types.h:22