{
XBT_VERB("Creating a guide for the state");
-
if (_sg_mc_strategy == "none")
strategy_ = std::make_shared<BasicStrategy>();
else if (_sg_mc_strategy == "max_match_comm")
else if (_sg_mc_strategy == "min_match_comm")
strategy_ = std::make_shared<MinMatchComm>();
else if (_sg_mc_strategy == "uniform") {
- xbt::random::set_mersenne_seed(_sg_mc_random_seed);
+ xbt::random::set_mersenne_seed(_sg_mc_random_seed);
strategy_ = std::make_shared<UniformStrategy>();
- }
- else
+ } else
THROW_IMPOSSIBLE;
remote_app.get_actors_status(strategy_->actors_to_run_);
strategy_ = std::make_shared<MaxMatchComm>();
else if (_sg_mc_strategy == "min_match_comm")
strategy_ = std::make_shared<MinMatchComm>();
- else if (_sg_mc_strategy == "uniform")
+ else if (_sg_mc_strategy == "uniform")
strategy_ = std::make_shared<UniformStrategy>();
else
THROW_IMPOSSIBLE;
{
// 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
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();
"deciding when to make subtrees in ODPOR is incorrect");
xbt_assert((get_transition_in()->aid_ == min_process_node.value()->get_actor()) &&
(get_transition_in()->type_ == min_process_node.value()->get_action()->type_),
- "We tried to make a subtree from a parent state who claimed to have executed `%s` on actor %ld"
+ "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?",
*/
void remove_subtree_using_current_out_transition();
bool has_empty_tree() const { return this->wakeup_tree_.empty(); }
+ std::string string_of_wut() const { return this->wakeup_tree_.string_of_whole_tree(); }
+
/**
* @brief
*/
XBT_INFO("DFS exploration ended. %ld unique states visited; %lu backtracks (%lu transition replays, %lu states "
"visited overall)",
State::get_expanded_states(), backtrack_count_, Transition::get_replayed_transitions(),
- visited_states_count_);
+ visited_states_count_);
Exploration::log_state();
}
// If there are processes to interleave and the maximum depth has not been
// reached then perform one step of the exploration algorithm.
- XBT_VERB("Execute %ld: %.60s (stack depth: %zu, state: %ld, %zu interleaves)", state->get_transition_out()->aid_,
+ XBT_VERB("Execute %ld: %.150s (stack depth: %zu, state: %ld, %zu interleaves)", state->get_transition_out()->aid_,
state->get_transition_out()->to_string().c_str(), stack_.size(), state->get_num(), state->count_todo());
/* Create the new expanded state (copy the state of MCed into our MCer data) */
for (const auto& [aid, transition] : state->get_sleep_set())
XBT_DEBUG("\t <%ld,%s>", aid, transition->to_string().c_str());
if (not state->has_empty_tree()) {
+ XBT_DEBUG("\t found the following non-empty WuT:\n"
+ "%s", state->string_of_wut().c_str());
return state;
}
}
if (const auto v = execution_seq_.get_odpor_extension_from(e, e_prime, prev_state); v.has_value()) {
switch (prev_state.insert_into_wakeup_tree(v.value(), execution_seq_.get_prefix_before(e))) {
case odpor::WakeupTree::InsertionResult::root: {
- XBT_DEBUG("ODPOR: Reversible race with `%u` unaccounted for in the wakeup tree for "
- "the execution prior to event `%u`:",
- e_prime, e);
+ XBT_DEBUG("ODPOR: Reversible race with `%u`(%ld: %.20s) unaccounted for in the wakeup tree for "
+ "the execution prior to event `%u`(%ld: %.20s):",
+ e_prime, stack_[e_prime]->get_transition_out()->aid_,
+ stack_[e_prime]->get_transition_out()->to_string(true).c_str(), e,
+ prev_state.get_transition_out()->aid_,
+ prev_state.get_transition_out()->to_string(true).c_str());
break;
}
case odpor::WakeupTree::InsertionResult::interior_node: {
#include <memory>
#include <queue>
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_wut, mc, "Logging specific to ODPOR WakeupTrees");
+
+
namespace simgrid::mc::odpor {
void WakeupTreeNode::add_child(WakeupTreeNode* node)
node->parent_ = this;
}
+std::string WakeupTreeNode::string_of_whole_tree(int indentation_level) const
+{
+ std::string tabulations = "";
+ for (int i = 0; i < indentation_level; i++)
+ tabulations += " ";
+ std::string final_string = action_ == nullptr ? "<>\n" :
+ tabulations + "Actor " + std::to_string(action_->aid_) + ": " + action_->to_string(true) + "\n";
+ for (auto node : children_)
+ final_string += node->string_of_whole_tree(indentation_level + 1);
+ return final_string;
+}
+
PartialExecution WakeupTreeNode::get_sequence() const
{
// TODO: Prevent having to compute this at the node level
return this->root_->children_.front();
}
+std::string WakeupTree::string_of_whole_tree() const
+{
+ return root_->string_of_whole_tree(0);
+}
+
WakeupTree WakeupTree::make_subtree_rooted_at(WakeupTreeNode* root)
{
// Perform a BFS search to perform a deep copy of the portion
std::shared_ptr<Transition> get_action() const { return action_; }
const std::list<WakeupTreeNode*>& get_ordered_children() const { return children_; }
+ std::string string_of_whole_tree(int indentation_level) const;
+
/** Insert a node `node` as a new child of this node */
void add_child(WakeupTreeNode* node);
};
std::vector<std::string> get_single_process_texts() const;
+ std::string string_of_whole_tree() const;
+
/**
* @brief Remove the subtree of the smallest (with respect
* to the tree's "<" relation) single-process node.
auto res = xbt::string_printf("WaitAny{ ");
for (auto const* t : transitions_)
res += t->to_string(verbose);
- res += " }";
+ res += " } (times considered = " + std::to_string(times_considered_) + ")";
return res;
}
bool WaitAnyTransition::depends(const Transition* other) const
if (o->type_ < type_)
return o->depends(this);
+ // Actions executed by the same actor are always dependent
+ if (o->aid_ == aid_)
+ return true;
+
if (const auto* other = dynamic_cast<const BarrierTransition*>(o)) {
if (bar_ != other->bar_)
return false;
if (o->type_ < type_)
return o->depends(this);
+ // Actions executed by the same actor are always dependent
+ if (o->aid_ == aid_)
+ return true;
+
if (const auto* other = dynamic_cast<const SemaphoreTransition*>(o)) {
if (sem_ != other->sem_)
return false;