Skip to content

Commit

Permalink
Merge branch 'PowerGridModel:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Laurynas-Jagutis authored Feb 26, 2025
2 parents 990a3e9 + 8bb5b4c commit 08f0d04
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,41 @@ template <symmetry_tag sym> struct NodeState {
}
};

class RankIteration {
public:
RankIteration(std::vector<IntS> iterations_per_rank, Idx rank_index)
: iterations_per_rank_{std::move(iterations_per_rank)}, rank_index_{rank_index} {}

// Getters
constexpr auto const& iterations_per_rank() const { return iterations_per_rank_; }
constexpr auto rank_index() const { return rank_index_; }

// Setters
void set_rank_index(Idx rank_index) { rank_index_ = rank_index; }

bool iterate_ranks(auto const& ranked_order, auto apply_single_object_in_rank, bool adjusted) {
for (Idx i = 0; i < static_cast<Idx>(ranked_order.size()); ++i) {
auto const& same_rank_regulators = ranked_order[i];
for (Idx j = 0; j < static_cast<Idx>(same_rank_regulators.size()); ++j) {
adjusted = apply_single_object_in_rank(i, j, same_rank_regulators) || adjusted;
}
if (adjusted) {
if (rank_index_ < static_cast<Idx>(iterations_per_rank_.size()) - 1) {
std::fill(iterations_per_rank_.begin() + rank_index_ + 1, iterations_per_rank_.end(), 0);
}
++iterations_per_rank_[rank_index_];
return adjusted;
}
++rank_index_;
}
return adjusted;
};

private:
std::vector<IntS> iterations_per_rank_{};
Idx rank_index_{};
};

template <typename... T> class TapPositionOptimizerImpl;
template <transformer_c... TransformerTypes, typename StateCalculator, typename StateUpdater_, typename State_,
typename TransformerRanker_>
Expand Down Expand Up @@ -879,32 +914,29 @@ class TapPositionOptimizerImpl<std::tuple<TransformerTypes...>, StateCalculator,
auto result = calculate_(state, method);
++total_iterations;

std::vector<IntS> iterations_per_rank(static_cast<signed char>(regulator_order.size() + 1),
static_cast<IntS>(0));
bool const strategy_max =
strategy_ == OptimizerStrategy::global_maximum || strategy_ == OptimizerStrategy::local_maximum;
bool tap_changed = true;
Idx rank_index = 0;
RankIteration rank_iterator(std::vector<IntS>(regulator_order.size()), rank_index);

while (tap_changed) {
tap_changed = false;
UpdateBuffer update_data;
Idx rank_index = 0;

for (Idx i = 0; i < static_cast<Idx>(regulator_order.size()); ++i) {
auto const& same_rank_regulators = regulator_order[i];
for (Idx j = 0; j < static_cast<Idx>(same_rank_regulators.size()); ++j) {
auto const& regulator = same_rank_regulators[j];
BinarySearchOptions const options{strategy_max, Idx2D{i, j}};
tap_changed =
adjust_transformer(regulator, state, result, update_data, search, options) || tap_changed;
}
if (tap_changed) {
iterations_per_rank[rank_index + 1] = 0;
++iterations_per_rank[rank_index];
break;
}
++rank_index;
}
rank_iterator.set_rank_index(0);

auto const adjust_transformer_in_rank = [&](Idx const& rank_idx, Idx const& transformer_idx,
std::vector<RegulatedTransformer> const& same_rank_regulators) {
auto const& regulator = same_rank_regulators[transformer_idx];
BinarySearchOptions const options{strategy_max, Idx2D{rank_idx, transformer_idx}};
tap_changed = adjust_transformer(regulator, state, result, update_data, search, options) || tap_changed;
return tap_changed;
};

tap_changed = rank_iterator.iterate_ranks(regulator_order, adjust_transformer_in_rank, tap_changed);
auto const& iterations_per_rank = rank_iterator.iterations_per_rank();
rank_index = rank_iterator.rank_index();

if (tap_changed) {
if (static_cast<uint64_t>(iterations_per_rank[rank_index]) > 2 * max_tap_ranges_per_rank[rank_index]) {
throw MaxIterationReached{"TapPositionOptimizer::iterate"};
Expand All @@ -914,7 +946,6 @@ class TapPositionOptimizerImpl<std::tuple<TransformerTypes...>, StateCalculator,
++total_iterations;
}
}

return result;
}

Expand Down
47 changes: 47 additions & 0 deletions tests/cpp_unit_tests/test_tap_position_optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,53 @@ TEST_CASE("Test tap position optmizer I/O") {
}
}

TEST_CASE("Test RankIterator") {
std::vector<std::vector<IntS>> regulator_order = {{0, 0, 0}, {0, 0, 0}};
bool tap_changed{false};
std::vector<IntS> iterations_per_rank = {2, 4, 6};
Idx rank_index{0};
bool update{false};
optimizer::tap_position_optimizer::RankIteration rank_iterator(iterations_per_rank, rank_index);

auto const mock_lambda = [&](Idx const& /*rank_idx*/, Idx const& /*transformer_idx*/,
std::vector<IntS> const& /*same_rank_regulators*/) { return update; };
SUBCASE("Test tap not changed") {
tap_changed = rank_iterator.iterate_ranks(regulator_order, mock_lambda, tap_changed);
iterations_per_rank = rank_iterator.iterations_per_rank();
rank_index = rank_iterator.rank_index();
CHECK(iterations_per_rank[0] == 2);
CHECK(iterations_per_rank[1] == 4);
CHECK(iterations_per_rank[2] == 6);
CHECK(rank_index == 2);
CHECK(tap_changed == false);
}
SUBCASE("Test tap changed") {
update = true;
tap_changed = rank_iterator.iterate_ranks(regulator_order, mock_lambda, tap_changed);
iterations_per_rank = rank_iterator.iterations_per_rank();
rank_index = rank_iterator.rank_index();
CHECK(iterations_per_rank[0] == 3);
CHECK(iterations_per_rank[1] == 0);
CHECK(iterations_per_rank[2] == 0);
CHECK(rank_index == 0);
}
SUBCASE("Test tap changed last rank") {
update = true;
rank_iterator.set_rank_index(2);
tap_changed = rank_iterator.iterate_ranks(regulator_order, mock_lambda, tap_changed);
iterations_per_rank = rank_iterator.iterations_per_rank();
rank_index = rank_iterator.rank_index();
CHECK(iterations_per_rank[0] == 2);
CHECK(iterations_per_rank[1] == 4);
CHECK(iterations_per_rank[2] == 7);
CHECK(rank_index == 2);
}
SUBCASE("Test set rank_index") {
rank_iterator.set_rank_index(1);
CHECK(rank_iterator.rank_index() == 1);
}
}

} // namespace power_grid_model

TEST_SUITE_END();

0 comments on commit 08f0d04

Please sign in to comment.