Skip to content

Optimization: the meshed observability check#1301

Open
Jerry-Jinfeng-Guo wants to merge 18 commits intomainfrom
feature/meshed-observability-optimization
Open

Optimization: the meshed observability check#1301
Jerry-Jinfeng-Guo wants to merge 18 commits intomainfrom
feature/meshed-observability-optimization

Conversation

@Jerry-Jinfeng-Guo
Copy link
Member

There are several places for improvement from #1136. This PR follows up on that.

  • visited counter
  • move semantics
  • reduce max iteration
  • remove unused vector
  • some space reservations

Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo self-assigned this Feb 11, 2026
@Jerry-Jinfeng-Guo Jerry-Jinfeng-Guo added the improvement Improvement on internal implementation label Feb 11, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Follow-up optimization of the “meshed observability check” spanning-tree search to reduce overhead per iteration and cap runtime more tightly.

Changes:

  • Replaced repeated std::ranges::count(...) with an O(1) visited_count tracker.
  • Introduced a degree-based max_iterations limit and added small allocation optimizations (reserve).
  • Removed a previously maintained “discovered edges” vector used only for documentation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
@Jerry-Jinfeng-Guo
Copy link
Member Author

Apart from the three complains about if | and | what | not, this PR is ready to merge. @nitbharambe please take a look.

Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
throw NotObservableError{"Meshed observability check fail. Network unobservable.\n"};
// Failed attempt: rollback all modifications before trying next candidate
for (auto const& mod : modifications) {
*mod.ptr = mod.old_value;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not create a create a copy of modifications. And then reset it at this point?
What does the ptr achieve that this cant?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably also should be moved, not passed by reference, because otherwise you may run into lifetime issues

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of the optimizations done. The copy adds to the footprint and drags down runtime.

Idx const max_iterations = n_bus * n_bus; // prevent infinite loops
Idx iteration = 0;
// Context struct to hold shared state during spanning tree search
struct SpanningTreeContext {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have to keep track of this state via pointers and then dereference it each time, why not enclose everthing in a class?

Copy link
Member

@figueroa1395 figueroa1395 Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or alternatively, why not just declare and initialize this struct at find_spanning_tree_from_node directly, store the values there once (instead of references to the values) and pass this structure by reference/extract values by reference as needed.

I'm curious about why this choice, and why not other, besides my suggestion or Nitish's.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See f37f7f2. As discussed offline: no strong preference.

Jerry-Jinfeng-Guo and others added 2 commits February 17, 2026 16:17
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
.downwind = &downwind};

// Iteration limit: visit all nodes plus some backtracking allowance
auto const max_iter_unclamped = static_cast<std::size_t>(n_bus) * static_cast<std::size_t>(avg_degree) * 3u;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, why the choice of 3 here? Any special reason behind it? If so, can you make it a named variable with some meaning so we don't forget the intention later on?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 is a heuristic to account for the forward search, back tracking and different candidate retires

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i prefer a named variable over a comment, e.g.

constexpr auto n_stages = 3u; // heuristic: forward search, backtracking, candidate retries
auto const max_iter_unclamped = static_cast<std::size_t>(n_bus) * static_cast<std::size_t>(avg_degree) * n_stages;

idem for the 2u hardcoded value elsewhere

Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improvement on internal implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments