Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Clarify that the issuer for a CommWait() action is that of the same actor
authorMaxwell Pirtle <maxwellpirtle@gmail.com>
Mon, 3 Apr 2023 09:42:38 +0000 (11:42 +0200)
committerMaxwell Pirtle <maxwellpirtle@gmail.com>
Wed, 5 Apr 2023 08:39:59 +0000 (10:39 +0200)
The `CommWait()` transition, in the manner that SimGrid
handles communications, can be said to be "issued" by either
the sender or the receiver that are a part of the communication
under consideration. We favor that which is run by the same actor;
indeed, we require it as this point unless otherwise noted.

If it is possible for a `CommWait` to wait on a communication
whose identity cannot be traced back to an event that already
executed by the same actor, the model would have to change
when computing extension sets for CommWait(), specifically
when checking whether or not that transition is enabled
at a prior state

src/mc/explo/UdporChecker.cpp
src/mc/explo/udpor/EventSet.hpp
src/mc/explo/udpor/ExtensionSetCalculator.cpp

index a3ff975..d4cb4ed 100644 (file)
@@ -10,6 +10,7 @@
 #include "src/mc/explo/udpor/History.hpp"
 #include "src/mc/explo/udpor/maximal_subsets_iterator.hpp"
 
+#include <numeric>
 #include <xbt/asserts.h>
 #include <xbt/log.h>
 #include <xbt/string.hpp>
@@ -50,7 +51,7 @@ void UdporChecker::explore(const Configuration& C, EventSet D, EventSet A, Event
   // exploration would lead to a so-called
   // "sleep-set blocked" trace.
   if (enC.is_subset_of(D)) {
-    XBT_DEBUG("en(C) is a subset of the sleep set D (size %zu); if we"
+    XBT_DEBUG("en(C) is a subset of the sleep set D (size %zu); if we "
               "kept exploring, we'd hit a sleep-set blocked trace",
               D.size());
     XBT_DEBUG("The current configuration has %zu elements", C.get_events().size());
@@ -151,6 +152,7 @@ EventSet UdporChecker::compute_exC(const Configuration& C, const State& stateC,
 
   for (const auto& [aid, actor_state] : stateC.get_actors_list()) {
     for (const auto& transition : actor_state.get_enabled_transitions()) {
+      XBT_DEBUG("\t Considering partial extension for %s", transition->to_string().c_str());
       EventSet extension = ExtensionSetCalculator::partially_extend(C, &unfolding, transition);
       exC.form_union(extension);
     }
@@ -248,23 +250,55 @@ UnfoldingEvent* UdporChecker::select_next_unfolding_event(const EventSet& A, con
 
 void UdporChecker::clean_up_explore(const UnfoldingEvent* e, const Configuration& C, const EventSet& D)
 {
-  const EventSet C_union_D              = C.get_events().make_union(D);
-  const EventSet es_immediate_conflicts = this->unfolding.get_immediate_conflicts_of(e);
-  const EventSet Q_CDU                  = C_union_D.make_union(es_immediate_conflicts.get_local_config());
-
-  // Move {e} \ Q_CDU from U to G
-  if (not Q_CDU.contains(e)) {
-    XBT_DEBUG("Removing %s from U to G...", e->to_string().c_str());
-    this->unfolding.remove(e);
-  }
-
-  // foreach ê in #ⁱ_U(e)
-  for (const auto* e_hat : es_immediate_conflicts) {
-    // Move [ê] \ Q_CDU from U to G
-    const EventSet to_remove = e_hat->get_history().subtracting(Q_CDU);
-    XBT_DEBUG("Removing {%s} from U to G...", to_remove.to_string().c_str());
-    this->unfolding.remove(to_remove);
-  }
+  // // The "clean-up set" conceptually represents
+  // // those events which will no longer be considered
+  // // by UDPOR during its exploration. The concept is
+  // // introduced to avoid modification during iteration
+  // // over the current unfolding to determine who needs to
+  // // be removed. Since sets are unordered, it's quite possible
+  // // that e.g. two events `e` and `e'` such that `e < e'`
+  // // which are determined eligible for removal are removed
+  // // in the order `e` and then `e'`. Determining that `e'`
+  // // needs to be removed requires that its history be in
+  // // tact to e.g. compute the conflicts with the event.
+  // //
+  // // Thus, we compute the set and remove all of the events
+  // // at once in lieu of removing events while iterating over them.
+  // // We can hypothesize that processing the events in reverse
+  // // topological order would prevent any issues concerning
+  // // the order in which are processed
+  // EventSet clean_up_set;
+
+  // // Q_(C, D, U) = C u D u U (complicated expression)
+  // // See page 9 of "Unfolding-based Partial Order Reduction"
+
+  // // "C u D" portion
+  // const EventSet C_union_D = C.get_events().make_union(D);
+
+  // // "U (complicated expression)" portion
+  // const EventSet conflict_union = std::accumulate(
+  //     C_union_D.begin(), C_union_D.end(), EventSet(), [&](const EventSet acc, const UnfoldingEvent* e_prime) {
+  //       return acc.make_union(unfolding.get_immediate_conflicts_of(e_prime));
+  //     });
+
+  // const EventSet Q_CDU = C_union_D.make_union(conflict_union.get_local_config());
+
+  // XBT_DEBUG("Computed Q_CDU as '%s'", Q_CDU.to_string().c_str());
+
+  // // Move {e} \ Q_CDU from U to G
+  // if (not Q_CDU.contains(e)) {
+  //   XBT_DEBUG("Moving %s from U to G...", e->to_string().c_str());
+  //   clean_up_set.insert(e);
+  // }
+
+  // // foreach ê in #ⁱ_U(e)
+  // for (const auto* e_hat : this->unfolding.get_immediate_conflicts_of(e)) {
+  //   // Move [ê] \ Q_CDU from U to G
+  //   const EventSet to_remove = e_hat->get_history().subtracting(Q_CDU);
+  //   XBT_DEBUG("Moving {%s} from U to G...", to_remove.to_string().c_str());
+  //   clean_up_set.form_union(to_remove);
+  // }
+  // // this->unfolding.remove(clean_up_set);
 }
 
 RecordTrace UdporChecker::get_record_trace()
index f682e3c..a29e25a 100644 (file)
@@ -8,10 +8,12 @@
 
 #include "src/mc/explo/udpor/udpor_forward.hpp"
 
+#include <algorithm>
 #include <cstddef>
 #include <initializer_list>
 #include <unordered_set>
 #include <vector>
+#include <xbt/asserts.h>
 
 namespace simgrid::mc::udpor {
 
@@ -26,9 +28,18 @@ public:
   EventSet& operator=(EventSet&&)      = default;
   EventSet(EventSet&&)                 = default;
   explicit EventSet(Configuration&& config);
-  explicit EventSet(std::vector<const UnfoldingEvent*>&& raw_events) : events_(raw_events.begin(), raw_events.end()) {}
-  explicit EventSet(std::unordered_set<const UnfoldingEvent*>&& raw_events) : events_(raw_events) {}
-  explicit EventSet(std::initializer_list<const UnfoldingEvent*> event_list) : events_(std::move(event_list)) {}
+  explicit EventSet(std::vector<const UnfoldingEvent*>&& raw_events) : events_(raw_events.begin(), raw_events.end())
+  {
+    xbt_assert(std::none_of(events_.begin(), events_.end(), [](const auto* e) { return e == nullptr; }), "Oh no");
+  }
+  explicit EventSet(std::unordered_set<const UnfoldingEvent*>&& raw_events) : events_(raw_events)
+  {
+    xbt_assert(std::none_of(events_.begin(), events_.end(), [](const auto* e) { return e == nullptr; }), "Oh no");
+  }
+  explicit EventSet(std::initializer_list<const UnfoldingEvent*> event_list) : events_(std::move(event_list))
+  {
+    xbt_assert(std::none_of(events_.begin(), events_.end(), [](const auto* e) { return e == nullptr; }), "Oh no");
+  }
 
   auto begin() const { return this->events_.begin(); }
   auto end() const { return this->events_.end(); }
index f8c4bac..f04fefc 100644 (file)
@@ -151,15 +151,15 @@ EventSet ExtensionSetCalculator::partially_extend_CommWait(const Configuration&
   // in `C`. The issuer of the `CommWait` in `C` is the event in `C`
   // whose transition is the `CommRecv` or `CommSend` whose resulting
   // communication this `CommWait` waits on
-  const auto issuer = std::find_if(C.begin(), C.end(), [=](const UnfoldingEvent* e) {
+  const auto issuer = std::find_if(C.begin(), C.end(), [&](const UnfoldingEvent* e) {
     if (const CommRecvTransition* e_issuer_receive = dynamic_cast<const CommRecvTransition*>(e->get_transition());
         e_issuer_receive != nullptr) {
-      return wait_comm == e_issuer_receive->get_comm();
+      return e_issuer_receive->aid_ == wait_action->aid_ && wait_comm == e_issuer_receive->get_comm();
     }
 
     if (const CommSendTransition* e_issuer_send = dynamic_cast<const CommSendTransition*>(e->get_transition());
         e_issuer_send != nullptr) {
-      return wait_comm == e_issuer_send->get_comm();
+      return e_issuer_send->aid_ == wait_action->aid_ && wait_comm == e_issuer_send->get_comm();
     }
 
     return false;
@@ -331,7 +331,7 @@ EventSet ExtensionSetCalculator::partially_extend_CommWait(const Configuration&
         continue;
       }
 
-      const auto issuer_mailbox        = e_issuer_send->get_mailbox();
+      const auto issuer_mailbox        = e_issuer_recv->get_mailbox();
       const CommSendTransition* e_send = dynamic_cast<const CommSendTransition*>(e->get_transition());
       if (e_send->get_mailbox() != issuer_mailbox) {
         continue;