X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/301109703c933c28285e0223836a570eaeb8875a..d60b44af675a79ff27e2b1ddbcbe0d9885905d2b:/src/mc/explo/udpor/Configuration.cpp diff --git a/src/mc/explo/udpor/Configuration.cpp b/src/mc/explo/udpor/Configuration.cpp index a05d3a7a0a..7f242d780b 100644 --- a/src/mc/explo/udpor/Configuration.cpp +++ b/src/mc/explo/udpor/Configuration.cpp @@ -6,6 +6,7 @@ #include "src/mc/explo/udpor/Configuration.hpp" #include "src/mc/explo/udpor/History.hpp" #include "src/mc/explo/udpor/UnfoldingEvent.hpp" +#include "src/mc/explo/udpor/maximal_subsets_iterator.hpp" #include "xbt/asserts.h" #include @@ -14,7 +15,8 @@ namespace simgrid::mc::udpor { -Configuration::Configuration(std::initializer_list events) : Configuration(EventSet(std::move(events))) +Configuration::Configuration(std::initializer_list events) + : Configuration(EventSet(std::move(events))) { } @@ -25,7 +27,7 @@ Configuration::Configuration(const EventSet& events) : events_(events) } } -void Configuration::add_event(UnfoldingEvent* e) +void Configuration::add_event(const UnfoldingEvent* e) { if (e == nullptr) { throw std::invalid_argument("Expected a nonnull `UnfoldingEvent*` but received NULL instead"); @@ -46,14 +48,14 @@ void Configuration::add_event(UnfoldingEvent* e) } } -std::vector Configuration::get_topologically_sorted_events() const +std::vector Configuration::get_topologically_sorted_events() const { if (events_.empty()) { - return std::vector(); + return std::vector(); } - std::stack event_stack; - std::vector topological_ordering; + std::stack event_stack; + std::vector topological_ordering; EventSet unknown_events = events_; EventSet temporarily_marked_events; EventSet permanently_marked_events; @@ -63,7 +65,7 @@ std::vector Configuration::get_topologically_sorted_events() co event_stack.push(*unknown_events.begin()); while (not event_stack.empty()) { - UnfoldingEvent* evt = event_stack.top(); + const UnfoldingEvent* evt = event_stack.top(); discovered_events.insert(evt); if (not temporarily_marked_events.contains(evt)) { @@ -87,10 +89,6 @@ std::vector Configuration::get_topologically_sorted_events() co event_stack.push(cause); } } else { - // Mark this event as: - // 1. discovered across all DFSs performed - // 2. permanently marked - // 3. part of the topological search unknown_events.remove(evt); temporarily_marked_events.remove(evt); permanently_marked_events.insert(evt); @@ -101,7 +99,7 @@ std::vector Configuration::get_topologically_sorted_events() co topological_ordering.push_back(evt); // Only now do we remove the event, i.e. once - // we've processed the same event again + // we've processed the same event twice event_stack.pop(); } } @@ -109,9 +107,9 @@ std::vector Configuration::get_topologically_sorted_events() co return topological_ordering; } -std::vector Configuration::get_topologically_sorted_events_of_reverse_graph() const +std::vector Configuration::get_topologically_sorted_events_of_reverse_graph() const { - // The method exploits the property that + // The implementation exploits the property that // a topological sorting S^R of the reverse graph G^R // of some graph G is simply the reverse of any // topological sorting S of G. @@ -120,4 +118,35 @@ std::vector Configuration::get_topologically_sorted_events_of_r return topological_events; } +EventSet Configuration::get_minimally_reproducible_events() const +{ + // The implementation exploits the following observations: + // + // To select the smallest reproducible set of events, we want + // to pick events that "knock out" a lot of others. Furthermore, + // we need to ensure that the events furthest down in the + // causality graph are also selected. If you combine these ideas, + // you're basically left with traversing the set of maximal + // subsets of C! And we have an iterator for that already! + // + // The next observation is that the moment we don't increase in size + // the current maximal set (or decrease the number of events), + // we know that the prior set `S` covered the entire history of C and + // was maximal. Subsequent sets will miss events earlier in the + // topological ordering that appear in `S` + EventSet minimally_reproducible_events = EventSet(); + + for (const auto& maximal_set : maximal_subsets_iterator_wrapper(*this)) { + if (maximal_set.size() > minimally_reproducible_events.size()) { + minimally_reproducible_events = maximal_set; + } else { + // The moment we see the iterator generate a set of size + // that is not monotonically increasing, we can stop: + // the set prior was the minimally-reproducible one + return minimally_reproducible_events; + } + } + return minimally_reproducible_events; +} + } // namespace simgrid::mc::udpor