Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add clean up phase to UDPOR
authorMaxwell Pirtle <maxwellpirtle@gmail.com>
Mon, 13 Mar 2023 10:18:54 +0000 (11:18 +0100)
committerMaxwell Pirtle <maxwellpirtle@gmail.com>
Mon, 13 Mar 2023 10:22:00 +0000 (11:22 +0100)
The last part of processing during UDPOR
involves removing events from the unfolding
which are no longer needed. The events in
the unfolding which must be preserved are outlined
in the UDPOR paper and are labeled Q_CDU.

src/mc/explo/UdporChecker.cpp
src/mc/explo/udpor/EventSet.cpp
src/mc/explo/udpor/EventSet.hpp
src/mc/explo/udpor/Unfolding.cpp
src/mc/explo/udpor/Unfolding.hpp
src/mc/explo/udpor/UnfoldingEvent.cpp

index 4d89514..04f8744 100644 (file)
@@ -62,6 +62,7 @@ void UdporChecker::explore(const Configuration& C, EventSet D, EventSet A, std::
     // relation. Here, then, we would be in a deadlock.
     if (enC.empty()) {
       get_remote_app().check_deadlock();
+      DIE_IMPOSSIBLE;
     }
 
     return;
@@ -75,7 +76,7 @@ void UdporChecker::explore(const Configuration& C, EventSet D, EventSet A, std::
                            "the search, yet no events were actually chosen\n"
                            "*********************************\n\n");
 
-  // Move the application into stateCe and actually make note of that state
+  // Move the application into stateCe and make note of that state
   move_to_stateCe(*stateC, *e);
   auto stateCe = record_current_state();
 
@@ -199,8 +200,10 @@ void UdporChecker::move_to_stateCe(State& state, const UnfoldingEvent& e)
 
 void UdporChecker::restore_program_state_to(const State& stateC)
 {
-  // TODO: Perform state regeneration in the same manner as is done
-  // in the DFSChecker.cpp
+  get_remote_app().restore_initial_state();
+  // TODO: We need to have the stack of past states available at this
+  // point. Since the method is recursive, we'll need to keep track of
+  // this as we progress
 }
 
 std::unique_ptr<State> UdporChecker::record_current_state()
@@ -235,7 +238,21 @@ EventSet UdporChecker::compute_partial_alternative(const EventSet& D, const Conf
 
 void UdporChecker::clean_up_explore(const UnfoldingEvent* e, const Configuration& C, const EventSet& D)
 {
-  // TODO: Perform clean up here
+  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 (Q_CDU.contains(e)) {
+    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);
+    this->unfolding.remove(to_remove);
+  }
 }
 
 RecordTrace UdporChecker::get_record_trace()
index f0dd8d1..ea42f8b 100644 (file)
@@ -90,6 +90,11 @@ EventSet EventSet::make_union(const Configuration& config) const
   return make_union(config.get_events());
 }
 
+EventSet EventSet::get_local_config() const
+{
+  return History(*this).get_all_events();
+}
+
 size_t EventSet::size() const
 {
   return this->events_.size();
index c6e755b..37da51a 100644 (file)
@@ -48,6 +48,7 @@ public:
   EventSet make_union(const UnfoldingEvent*) const;
   EventSet make_union(const EventSet&) const;
   EventSet make_union(const Configuration&) const;
+  EventSet get_local_config() const;
 
   size_t size() const;
   bool empty() const;
index 84ad822..6a81ff2 100644 (file)
@@ -9,12 +9,20 @@
 
 namespace simgrid::mc::udpor {
 
+void Unfolding::remove(const EventSet& events)
+{
+  for (const auto e : events) {
+    remove(e);
+  }
+}
+
 void Unfolding::remove(const UnfoldingEvent* e)
 {
   if (e == nullptr) {
     throw std::invalid_argument("Expected a non-null pointer to an event, but received NULL");
   }
   this->global_events_.erase(e);
+  this->event_handles.remove(e);
 }
 
 void Unfolding::insert(std::unique_ptr<UnfoldingEvent> e)
@@ -29,6 +37,7 @@ void Unfolding::insert(std::unique_ptr<UnfoldingEvent> e)
   }
 
   // Map the handle to its owner
+  this->event_handles.insert(handle);
   this->global_events_[handle] = std::move(e);
 }
 
@@ -36,7 +45,7 @@ bool Unfolding::contains_event_equivalent_to(const UnfoldingEvent* e) const
 {
   // Notice the use of `==` equality here. `e` may not be contained in the
   // unfolding; but some event which is "equivalent" to it could be.
-  for (const auto& [event, _] : global_events_) {
+  for (const auto event : *this) {
     if (*event == *e) {
       return true;
     }
@@ -44,4 +53,17 @@ bool Unfolding::contains_event_equivalent_to(const UnfoldingEvent* e) const
   return false;
 }
 
+EventSet Unfolding::get_immediate_conflicts_of(const UnfoldingEvent* e) const
+{
+  EventSet immediate_conflicts;
+
+  for (const auto event : *this) {
+    if (event->immediately_conflicts_with(e)) {
+      immediate_conflicts.insert(e);
+    }
+  }
+
+  return immediate_conflicts;
+}
+
 } // namespace simgrid::mc::udpor
index 01c7663..4d854e3 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef SIMGRID_MC_UDPOR_UNFOLDING_HPP
 #define SIMGRID_MC_UDPOR_UNFOLDING_HPP
 
+#include "src/mc/explo/udpor/EventSet.hpp"
 #include "src/mc/explo/udpor/UnfoldingEvent.hpp"
 #include "src/mc/explo/udpor/udpor_forward.hpp"
 
@@ -26,17 +27,33 @@ private:
    */
   std::unordered_map<const UnfoldingEvent*, std::unique_ptr<UnfoldingEvent>> global_events_;
 
+  /**
+   * @brief: The collection of events in the unfolding
+   *
+   * @invariant: All of the events in this set are elements of `global_events_`
+   * and is kept updated at the same time as `global_events_`
+   */
+  EventSet event_handles;
+
 public:
   Unfolding()                       = default;
   Unfolding& operator=(Unfolding&&) = default;
   Unfolding(Unfolding&&)            = default;
 
   void remove(const UnfoldingEvent* e);
+  void remove(const EventSet& events);
   void insert(std::unique_ptr<UnfoldingEvent> e);
   bool contains_event_equivalent_to(const UnfoldingEvent* e) const;
 
+  auto begin() const { return this->event_handles.begin(); }
+  auto end() const { return this->event_handles.begin(); }
+  auto cbegin() const { return this->event_handles.cbegin(); }
+  auto cend() const { return this->event_handles.cend(); }
   size_t size() const { return this->global_events_.size(); }
   bool empty() const { return this->global_events_.empty(); }
+
+  /// @brief Computes "#ⁱ_U(e)" for the given event
+  EventSet get_immediate_conflicts_of(const UnfoldingEvent*) const;
 };
 
 } // namespace simgrid::mc::udpor
index b62ef1a..361ed36 100644 (file)
@@ -88,6 +88,7 @@ bool UnfoldingEvent::conflicts_with(const Configuration& config) const
 
 bool UnfoldingEvent::immediately_conflicts_with(const UnfoldingEvent* other) const
 {
+  // Computes "this #ⁱ other"
   // They have to be in conflict at a minimum
   if (not conflicts_with(other)) {
     return false;