+ return outgoing_transition_;
+}
+
+std::unordered_set<aid_t> State::get_backtrack_set() const
+{
+ std::unordered_set<aid_t> actors;
+ for (const auto& [aid, state] : get_actors_list()) {
+ if (state.is_todo() || state.is_done()) {
+ actors.insert(aid);
+ }
+ }
+ return actors;
+}
+
+std::unordered_set<aid_t> State::get_sleeping_actors() const
+{
+ std::unordered_set<aid_t> actors;
+ for (const auto& [aid, _] : get_sleep_set()) {
+ actors.insert(aid);
+ }
+ return actors;
+}
+
+std::unordered_set<aid_t> State::get_enabled_actors() const
+{
+ std::unordered_set<aid_t> actors;
+ for (const auto& [aid, state] : get_actors_list()) {
+ if (state.is_enabled()) {
+ actors.insert(aid);
+ }
+ }
+ return actors;
+}
+
+void State::seed_wakeup_tree_if_needed(const odpor::Execution& prior)
+{
+ // TODO: It would be better not to have such a flag.
+ if (has_initialized_wakeup_tree) {
+ XBT_DEBUG("Reached a node with the following initialized WuT:");
+ XBT_DEBUG("\n%s", wakeup_tree_.string_of_whole_tree().c_str());
+
+ return;
+ }
+ // TODO: Note that the next action taken by the actor may be updated
+ // after it executes. But we will have already inserted it into the
+ // tree and decided upon "happens-before" at that point for different
+ // executions :(
+ if (wakeup_tree_.empty()) {
+ // Find an enabled transition to pick
+ for (const auto& [_, actor] : get_actors_list()) {
+ if (actor.is_enabled()) {
+ // For each variant of the transition that is enabled, we want to insert the action into the tree.
+ // This ensures that all variants are searched
+ for (unsigned times = 0; times < actor.get_max_considered(); ++times) {
+ wakeup_tree_.insert(prior, odpor::PartialExecution{actor.get_transition(times)});
+ }
+ break; // Only one actor gets inserted (see pseudocode)
+ }
+ }
+ }
+ has_initialized_wakeup_tree = true;
+}
+
+void State::sprout_tree_from_parent_state()
+{
+
+ XBT_DEBUG("Initializing Wut with parent one:");
+ XBT_DEBUG("\n%s", parent_state_->wakeup_tree_.string_of_whole_tree().c_str());
+
+ xbt_assert(parent_state_ != nullptr, "Attempting to construct a wakeup tree for the root state "
+ "(or what appears to be, rather for state without a parent defined)");
+ const auto min_process_node = parent_state_->wakeup_tree_.get_min_single_process_node();
+ xbt_assert(min_process_node.has_value(), "Attempting to construct a subtree for a substate from a "
+ "parent with an empty wakeup tree. This indicates either that ODPOR "
+ "actor selection in State.cpp is incorrect, or that the code "
+ "deciding when to make subtrees in ODPOR is incorrect");
+ if (not(get_transition_in()->aid_ == min_process_node.value()->get_actor() &&
+ get_transition_in()->type_ == min_process_node.value()->get_action()->type_)) {
+ XBT_ERROR("We tried to make a subtree from a parent state who claimed to have executed `%s` on actor %ld "
+ "but whose wakeup tree indicates it should have executed `%s` on actor %ld. This indicates "
+ "that exploration is not following ODPOR. Are you sure you're choosing actors "
+ "to schedule from the wakeup tree? Trace so far:",
+ get_transition_in()->to_string(false).c_str(), get_transition_in()->aid_,
+ min_process_node.value()->get_action()->to_string(false).c_str(), min_process_node.value()->get_actor());
+ for (auto elm : Exploration::get_instance()->get_textual_trace())
+ XBT_ERROR("%s", elm.c_str());
+ xbt_abort();
+ }
+ this->wakeup_tree_ = odpor::WakeupTree::make_subtree_rooted_at(min_process_node.value());
+}
+
+void State::remove_subtree_using_current_out_transition()
+{
+ if (auto out_transition = get_transition_out(); out_transition != nullptr) {
+ if (const auto min_process_node = wakeup_tree_.get_min_single_process_node(); min_process_node.has_value()) {
+ xbt_assert((out_transition->aid_ == min_process_node.value()->get_actor()) &&
+ (out_transition->type_ == min_process_node.value()->get_action()->type_),
+ "We tried to make a subtree from a parent state who claimed to have executed `%s` "
+ "but whose wakeup tree indicates it should have executed `%s`. This indicates "
+ "that exploration is not following ODPOR. Are you sure you're choosing actors "
+ "to schedule from the wakeup tree?",
+ out_transition->to_string(false).c_str(),
+ min_process_node.value()->get_action()->to_string(false).c_str());
+ }
+ }
+ wakeup_tree_.remove_min_single_process_subtree();
+}
+
+void State::remove_subtree_at_aid(const aid_t proc)
+{
+ wakeup_tree_.remove_subtree_at_aid(proc);