Skip to content

Comments

Optimization: the meshed observability check#1301

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

Optimization: the meshed observability check#1301
Jerry-Jinfeng-Guo wants to merge 19 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>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
@sonarqubecloud
Copy link

Comment on lines +536 to +538
constexpr auto min_avg_degree = 2;
Idx const avg_degree =
(avg_degree_size_t >= min_avg_degree) ? static_cast<Idx>(avg_degree_size_t) : static_cast<Idx>(min_avg_degree);
Copy link
Member

Choose a reason for hiding this comment

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

Can you move this to below where it gets used in max_iterations caluclation?

Copy link
Member

Choose a reason for hiding this comment

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

Also,
It would be direct if we dont move to the degree area. I see n_bus is divided and multiplied. So
n_visits = max(total_edges, min_avg_degree * n_bus)

Then below
max_iter_unclamped = n_visits * n_stages

(n_visits might not be the best name)

Comment on lines +557 to +558
auto const max_iterations =
static_cast<Idx>(std::min(max_iter_unclamped, static_cast<std::size_t>(std::numeric_limits<Idx>::max())));
Copy link
Member

Choose a reason for hiding this comment

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

Why this extra check on numeric limits max?

@nitbharambe
Copy link
Member

2 minor comments on naming/refactoring. LGTM otherwise. @Jerry-Jinfeng-Guo

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