Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/minimum degree topology #440

Merged
merged 70 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
b387999
add sparse iteration to code base
mgovers Nov 20, 2023
bf05a4d
fix naming conventions
mgovers Nov 20, 2023
d970f42
different location
mgovers Nov 22, 2023
c507ba2
Merge remote-tracking branch 'origin/main' into feature/minimum-degre…
mgovers Nov 22, 2023
e97d594
use doctest instead of raw print
mgovers Nov 22, 2023
fbfe02d
remove deprecated
mgovers Nov 22, 2023
3d5b74b
remove redundant vector
mgovers Nov 22, 2023
6bb3c49
call minimum degree ordening from topology
mgovers Nov 22, 2023
1a4b122
switch to new min degree algorithm
mgovers Nov 27, 2023
ef9ae29
attempt to fix permutations
mgovers Dec 1, 2023
281486f
Merge branch 'main' into feature/minimum-degree-topology
mgovers Dec 11, 2023
0d8fe10
more debug
mgovers Dec 13, 2023
d2c7514
fix last remaining issue
mgovers Dec 15, 2023
15846b5
remove logging
mgovers Dec 15, 2023
e5a11ad
Merge branch 'feature/minimum-degree-topology' of https://github.com/…
mgovers Dec 15, 2023
3b1c090
Merge branch 'main' into feature/minimum-degree-topology
mgovers Dec 15, 2023
91257da
Merge remote-tracking branch 'origin/main' into feature/minimum-degre…
mgovers Jan 2, 2024
ed9f483
remove bad import
mgovers Jan 2, 2024
632798e
major cleanup minimum degree ordening
mgovers Jan 2, 2024
9de4a44
more cleanup
mgovers Jan 2, 2024
6f3e9b5
more improvements
mgovers Jan 2, 2024
0c0c667
minor
mgovers Jan 2, 2024
903ad46
Merge branch 'main' into feature/minimum-degree-topology
mgovers Jan 23, 2024
3110da1
Merge remote-tracking branch 'origin/main' into feature/minimum-degre…
mgovers Jan 30, 2024
f1e9923
update licenses of new files
mgovers Jan 30, 2024
7c78624
fix clang tidy
mgovers Feb 1, 2024
1e7dee2
Merge remote-tracking branch 'origin/main' into feature/minimum-degre…
mgovers Feb 8, 2024
ae8eea7
Merge branch 'main' into feature/minimum-degree-topology
Jerry-Jinfeng-Guo Feb 13, 2024
a4b1397
Merge branch 'main' into feature/minimum-degree-topology
Jerry-Jinfeng-Guo Feb 13, 2024
0541217
Merge branch 'main' into feature/minimum-degree-topology
mgovers Feb 14, 2024
d2b198a
resolve code smells - part 1
mgovers Feb 14, 2024
6c4e36c
resolve sonar cloud
mgovers Feb 14, 2024
d65b929
resolve sonar cloud
mgovers Feb 14, 2024
0d64526
fix compilation
mgovers Feb 14, 2024
8b03643
more efficient implementation
mgovers Feb 14, 2024
a3de21d
fix clang tidy
mgovers Feb 14, 2024
2b38049
resolve sonar cloud
mgovers Feb 14, 2024
6549be4
fix
mgovers Feb 14, 2024
a207fec
fix more code smells
mgovers Feb 14, 2024
f1000b7
fix
mgovers Feb 14, 2024
4ad9084
clang-tidy
mgovers Feb 14, 2024
01ea81e
rename sparse ordening -> sparse ordering
mgovers Feb 15, 2024
30fc68e
Merge branch 'main' into feature/minimum-degree-topology
mgovers Feb 16, 2024
5dd73a9
Merge branch 'main' into feature/minimum-degree-topology
mgovers Feb 16, 2024
c862036
Merge remote-tracking branch 'origin/main' into feature/minimum-degre…
mgovers Feb 16, 2024
26ca1bf
remove test code
mgovers Feb 16, 2024
9fd6e9f
[skip ci] minor
mgovers Feb 20, 2024
b105195
Merge branch 'main' into feature/minimum-degree-topology
mgovers Mar 13, 2024
68aa35b
Merge remote-tracking branch 'origin/main' into feature/minimum-degre…
mgovers Mar 13, 2024
9caf62d
minor fix
mgovers Mar 13, 2024
feb0755
fix benchmark
mgovers Mar 14, 2024
14def66
Merge remote-tracking branch 'origin/main' into feature/minimum-degre…
mgovers Mar 14, 2024
565907f
Merge branch 'main' into feature/minimum-degree-topology
mgovers Mar 22, 2024
f9d4216
capturing structured bindings will be supported starting Clang16
mgovers Mar 22, 2024
d6293a3
fix sonar cloud
mgovers Mar 22, 2024
89a894b
Merge branch 'main' into feature/minimum-degree-topology
mgovers May 21, 2024
0d6422a
Merge branch 'main' into feature/minimum-degree-topology
mgovers May 24, 2024
62c2710
Merge branch 'main' into feature/minimum-degree-topology
mgovers May 28, 2024
3303d10
Merge branch 'main' into feature/minimum-degree-topology
mgovers Jun 11, 2024
ce569a2
Merge branch 'main' into feature/minimum-degree-topology
mgovers Jun 17, 2024
49b87a0
minor fix to the fictional grid
mgovers Jun 17, 2024
d38417b
remove TODO
mgovers Jun 17, 2024
a64e775
minor
mgovers Jun 18, 2024
b38e813
minor improvements
mgovers Jun 18, 2024
c978774
significant improvements to sparse ordering
mgovers Jun 18, 2024
36afc79
major speedup in obtaining minimum degree vertex
mgovers Jun 19, 2024
74b9d52
improve current most expensive step
mgovers Jun 19, 2024
986a294
fix ci
mgovers Jun 19, 2024
cd55f73
fix
mgovers Jun 19, 2024
ca040d5
resolve sonar cloud
mgovers Jun 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
// SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
//
// SPDX-License-Identifier: MPL-2.0

#pragma once

#include "common/common.hpp"

#include <algorithm>
#include <cassert>
#include <compare>
#include <map>
#include <set>
#include <utility>
#include <vector>

namespace power_grid_model {

namespace detail {
class DegreeLookup {
public:
void set(Idx u, Idx degree) {
if (auto degree_it = vertex_to_degree.find(u); degree_it != vertex_to_degree.end()) {
remove_degree(u, degree_it->second);
degree_it->second = degree;
} else {
vertex_to_degree.try_emplace(u, degree);
}
degrees_to_vertex[degree].insert(u);
}

void erase(Idx u) {
auto vertex_it = vertex_to_degree.find(u);
if (vertex_it == vertex_to_degree.end()) {
return;
}
Idx const degree = vertex_it->second;
vertex_to_degree.erase(vertex_it);
remove_degree(u, degree);
}

friend auto min_element(DegreeLookup const& dgd);

private:
void remove_degree(Idx u, Idx degree) {
if (auto degree_it = degrees_to_vertex.find(degree); degree_it != degrees_to_vertex.end()) {
degree_it->second.erase(u);
if (degree_it->second.empty()) {
degrees_to_vertex.erase(degree_it);
}
}
}

std::map<Idx, Idx> vertex_to_degree;
std::map<Idx, std::set<Idx>> degrees_to_vertex;
};

inline auto min_element(DegreeLookup const& dgd) {
Idx const vertex = *dgd.degrees_to_vertex.begin()->second.begin();
return dgd.vertex_to_degree.find(vertex);
}

inline void remove_element_degree(Idx u, DegreeLookup& dgd) { dgd.erase(u); }

inline void set_element_degree(Idx u, Idx degree, DegreeLookup& dgd) { dgd.set(u, degree); }

inline Idx num_adjacent(Idx const u, std::map<Idx, IdxVector> const& d) {
if (auto it = d.find(u); it != d.end()) {
return static_cast<Idx>(it->second.size());
}
return 0;
}

inline IdxVector const& adj(Idx const u, std::map<Idx, IdxVector> const& d) { return d.at(u); }

inline std::vector<std::pair<Idx, DegreeLookup>> comp_size_degrees_graph(std::map<Idx, IdxVector> const& d) {
DegreeLookup dd;
IdxVector v;

for (auto const& [k, adjacent] : d) {
v.push_back(k);
set_element_degree(k, static_cast<Idx>(adjacent.size()), dd);
}

return {{d.size(), dd}};
}

inline std::map<Idx, IdxVector> make_clique(IdxVector& l) {
std::map<Idx, IdxVector> d;

for (Idx i = 0; i < static_cast<Idx>(l.size()); i++) {
IdxVector sl(l.size() - 1);
std::copy(l.begin(), l.begin() + i, sl.begin());
std::copy(l.begin() + i + 1, l.end(), sl.begin() + i);
d[l[i]] = std::move(sl);
}

return d;
}

inline std::vector<std::pair<IdxVector, IdxVector>> check_indistguishable(Idx const u,
std::map<Idx, IdxVector> const& d) {
IdxVector rl;

auto l = adj(u, d);
auto lu = l;
lu.push_back(u);
std::ranges::sort(lu);

for (auto const& v : l) {
auto lv = adj(v, d);
lv.push_back(v);
std::ranges::sort(lv);
mgovers marked this conversation as resolved.
Show resolved Hide resolved
if (lu == lv) {
rl.push_back(v);
}
}

return {{l, rl}};
}

inline bool in_graph(std::pair<Idx, Idx> const& e, std::map<Idx, IdxVector> const& d) {
if (auto edges_it = d.find(e.first);
edges_it != d.cend() && std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) {
return true;
}
return false;
}

inline IdxVector remove_vertices_update_degrees(Idx const u, std::map<Idx, IdxVector>& d, DegreeLookup& dgd,
std::vector<std::pair<Idx, Idx>>& fills) {
std::vector<std::pair<IdxVector, IdxVector>> nbsrl = check_indistguishable(u, d);
auto& [nbs, rl] = nbsrl[0];
IdxVector alpha = rl;
std::map<Idx, IdxVector> dd;

rl.push_back(u);

for (auto uu : rl) {
if (uu != u) {
std::erase(nbs, uu);
}

remove_element_degree(uu, dgd);
IdxVector el;
for (auto e : d[uu]) {
auto& adjacents = d[e];
std::erase(adjacents, uu);
if (adjacents.empty()) {
el.push_back(e);
}
}

el.push_back(uu);

for (auto const& it : el) {
d.erase(it);
}
}

dd = make_clique(nbs);

for (auto const& [k, adjacent] : dd) {
auto it = d.find(k);
for (Idx const e : adjacent) {
if (!in_graph(std::make_pair(k, e), d)) {
if (it == d.end()) {
std::tie(it, std::ignore) = d.try_emplace(k);
}
it->second.push_back(e);
d[e].push_back(k);
fills.emplace_back(k, e);
}
}
}

for (auto const& e : nbs) {
set_element_degree(e, num_adjacent(e, d), dgd);
}

return alpha;
}
} // namespace detail

inline std::pair<IdxVector, std::vector<std::pair<Idx, Idx>>> minimum_degree_ordering(std::map<Idx, IdxVector> d) {
// make symmetric
for (auto const& [k, adjacent] : d) {
for (auto e : adjacent) {
d[e].push_back(k);
}
}
for (auto& [k, adjacent] : d) {
std::set<Idx> const unique_sorted_adjacent{adjacent.begin(), adjacent.end()};
adjacent = IdxVector{unique_sorted_adjacent.begin(), unique_sorted_adjacent.end()};
}

auto data = detail::comp_size_degrees_graph(d);
auto& [n, dgd] = data[0];

IdxVector alpha;
std::vector<std::pair<Idx, Idx>> fills;

for (Idx k = 0; k < n; ++k) {
Idx const u = get<0>(*detail::min_element(dgd));
alpha.push_back(u);
if (d.size() == 2) {
assert(d.begin()->second.size() == 1);

Idx const from = d.begin()->first;
Idx const to = d.begin()->second[0];
alpha.push_back(alpha.back() == from ? to : from);
return {alpha, fills};
}
std::ranges::copy(detail::remove_vertices_update_degrees(u, d, dgd, fills), std::back_inserter(alpha));
if (d.empty()) {
return {alpha, fills};
}
}
return {alpha, fills};
}
} // namespace power_grid_model
Loading
Loading