Skip to content

Commit

Permalink
Update Traverse API (#362, #367, #394 and #387)
Browse files Browse the repository at this point in the history
Signed-off-by: Sébastien LAIGRE <[email protected]>
  • Loading branch information
sebalaig committed May 24, 2022
1 parent 61bb7f4 commit b4fde65
Show file tree
Hide file tree
Showing 23 changed files with 396 additions and 46 deletions.
10 changes: 9 additions & 1 deletion include/powsybl/iidm/VoltageLevelViews.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <powsybl/iidm/InternalConnection.hpp>
#include <powsybl/iidm/InternalConnectionAdder.hpp>
#include <powsybl/iidm/SwitchAdder.hpp>
#include <powsybl/math/TraverseResult.hpp>
#include <powsybl/math/Traverser.hpp>
#include <powsybl/stdcxx/range.hpp>
#include <powsybl/stdcxx/reference.hpp>

Expand All @@ -35,6 +37,8 @@ class BusBreakerView {
public:
using SwitchAdder = bus_breaker_view::SwitchAdder;

using Traverser = std::function<math::TraverseResult(const Bus& bus1, const stdcxx::Reference<Switch>& sw, const Bus& bus2)>;

public:
virtual ~BusBreakerView() noexcept = default;

Expand Down Expand Up @@ -75,6 +79,8 @@ class BusBreakerView {
virtual void removeBus(const std::string& busId) = 0;

virtual void removeSwitch(const std::string& switchId) = 0;

virtual void traverse(const Bus& bus, Traverser& traverser) = 0;
};

class BusView {
Expand Down Expand Up @@ -102,7 +108,7 @@ class NodeBreakerView {

using SwitchAdder = node_breaker_view::SwitchAdder;

using Traverser = std::function<bool(unsigned long node1, const stdcxx::Reference<Switch>& sw, unsigned long node2)>;
using Traverser = std::function<math::TraverseResult(unsigned long node1, const stdcxx::Reference<Switch>& sw, unsigned long node2)>;

public:
virtual ~NodeBreakerView() noexcept = default;
Expand Down Expand Up @@ -172,6 +178,8 @@ class NodeBreakerView {
virtual void removeSwitch(const std::string& switchId) = 0;

virtual void traverse(unsigned long node, const Traverser& traverser) const = 0;

virtual void traverse(stdcxx::const_range<unsigned long>& nodes, const Traverser& traverser) const = 0;
};

} // namespace voltage_level
Expand Down
29 changes: 29 additions & 0 deletions include/powsybl/iidm/util/NodeBreakerTopology.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Copyright (c) 2022, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#ifndef POWSYBL_IIDM_UTIL_NODEBREAKERTOPOLOGY_HPP
#define POWSYBL_IIDM_UTIL_NODEBREAKERTOPOLOGY_HPP

#include <powsybl/iidm/VoltageLevelViews.hpp>

namespace powsybl {

namespace iidm {

namespace NodeBreakerTopology {

unsigned long newStandardConnection(BusbarSection& bb);

void removeIsolatedSwitches(voltage_level::NodeBreakerView& topo);

} // namespace NodeBreakerTopology

} // namespace iidm

} // namespace powsybl

#endif // POWSYBL_IIDM_UTIL_NODEBREAKERTOPOLOGY_HPP
8 changes: 7 additions & 1 deletion include/powsybl/math/TraverseResult.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ namespace powsybl {
namespace math {

enum class TraverseResult {
/** Indicates that traversal should continue */
CONTINUE,
TERMINATE

/** Indicates that traversal should terminate on current path */
TERMINATE_PATH,

/** Indicates that traversal should break, i.e., terminate on all paths */
TERMINATE_TRAVERSER
};

} // namespace math
Expand Down
6 changes: 4 additions & 2 deletions include/powsybl/math/UndirectedGraph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,11 @@ class UndirectedGraph {

void setVertexObject(unsigned long v, const stdcxx::Reference<V>& object);

void traverse(unsigned long v, const Traverser& traverser) const;
bool traverse(unsigned long v, const Traverser& traverser) const;

void traverse(unsigned long v, const Traverser& traverser, std::vector<bool>& encountered) const;
bool traverse(stdcxx::const_range<unsigned long>& startingVertices, const Traverser& traverser) const;

bool traverse(unsigned long v, const Traverser& traverser, std::vector<bool>& encountered) const;

bool vertexExists(unsigned long v) const;

Expand Down
44 changes: 36 additions & 8 deletions include/powsybl/math/UndirectedGraph.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -418,14 +418,28 @@ void UndirectedGraph<V, E>::setVertexObject(unsigned long v, const stdcxx::Refer
}

template <typename V, typename E>
void UndirectedGraph<V, E>::traverse(unsigned long v, const Traverser& traverser) const {
bool UndirectedGraph<V, E>::traverse(unsigned long v, const Traverser& traverser) const {
std::vector<bool> encountered(m_vertices.size(), false);

traverse(v, traverser, encountered);
return traverse(v, traverser, encountered);
}

template <typename V, typename E>
void UndirectedGraph<V, E>::traverse(unsigned long v, const Traverser& traverser, std::vector<bool>& encountered) const {
bool UndirectedGraph<V, E>::traverse(stdcxx::const_range<unsigned long>& startingVertices, const Traverser& traverser) const {
std::vector<bool> encountered(m_vertices.size(), false);

for (unsigned long startingVertex : startingVertices) {
if (!encountered[startingVertex]) {
if (!traverse(startingVertex, traverser, encountered)) {
return false;
}
}
}
return true;
}

template <typename V, typename E>
bool UndirectedGraph<V, E>::traverse(unsigned long v, const Traverser& traverser, std::vector<bool>& encountered) const {
checkVertex(v);

encountered.resize(m_vertices.size(), false);
Expand All @@ -434,20 +448,34 @@ void UndirectedGraph<V, E>::traverse(unsigned long v, const Traverser& traverser
const std::vector<unsigned long>& adjacentEdges = adjacencyList[v];

encountered[v] = true;
bool keepGoing = true;
for (unsigned long e : adjacentEdges) {
const std::unique_ptr<Edge>& edge = m_edges[e];
unsigned long v1 = edge->getVertex1();
unsigned long v2 = edge->getVertex2();
if (!encountered[v1]) {
if (traverser(v2, e, v1) == TraverseResult::CONTINUE) {
const TraverseResult& traverserResult = traverser(v2, e, v1);
if (traverserResult == TraverseResult::CONTINUE) {
encountered[v1] = true;
traverse(v1, traverser, encountered);
keepGoing = traverse(v1, traverser, encountered);
} else if (traverserResult == TraverseResult::TERMINATE_TRAVERSER) {
keepGoing = false;
}
} else if (!encountered[v2]) {
const TraverseResult& traverserResult = traverser(v1, e, v2);
if (traverserResult == TraverseResult::CONTINUE) {
encountered[v2] = true;
keepGoing = traverse(v2, traverser, encountered);
} else if (traverserResult == TraverseResult::TERMINATE_TRAVERSER) {
keepGoing = false;
}
} else if (!encountered[v2] && (traverser(v1, e, v2) == TraverseResult::CONTINUE)) {
encountered[v2] = true;
traverse(v2, traverser, encountered);
}
if (!keepGoing) {
break;
}
}

return keepGoing;
}

template <typename V, typename E>
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ set(IIDM_SOURCES
iidm/util/LimitViolationUtils.cpp
iidm/util/LinkData.cpp
iidm/util/Networks.cpp
iidm/util/NodeBreakerTopology.cpp
iidm/util/Substations.cpp
iidm/util/SV.cpp
iidm/util/TerminalFinder.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/iidm/BusBreakerVoltageLevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ void BusBreakerVoltageLevel::traverse(BusTerminal& terminal, VoltageLevel::Topol
return math::TraverseResult::CONTINUE;
}
}
return math::TraverseResult::TERMINATE;
return math::TraverseResult::TERMINATE_PATH;
});

for (Terminal& t : nextTerminals) {
Expand Down
2 changes: 1 addition & 1 deletion src/iidm/BusBreakerVoltageLevelTopology.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void CalculatedBusTopology::updateCache() {
graph.traverse(v, [&busSet, &graph](unsigned long /*v1*/, unsigned long e, unsigned long v2) {
stdcxx::Reference<Switch> aSwitch = graph.getEdgeObject(e);
if (aSwitch.get().isOpen()) {
return math::TraverseResult::TERMINATE;
return math::TraverseResult::TERMINATE_PATH;
}

busSet.push_back(std::ref(graph.getVertexObject(v2).get()));
Expand Down
9 changes: 9 additions & 0 deletions src/iidm/BusBreakerVoltageLevelViews.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ void BusBreakerViewImpl::removeSwitch(const std::string& switchId) {
m_voltageLevel.removeSwitch(switchId);
}

void BusBreakerViewImpl::traverse(const Bus& bus, Traverser& traverser) {
math::Traverser graphTraverser = [this, &traverser](unsigned long v1, unsigned long e, unsigned long v2) {
const auto& graph = m_voltageLevel.getGraph();
return traverser(graph.getVertexObject(v1), graph.getEdgeObject(e), graph.getVertexObject(v2));
};

m_voltageLevel.getGraph().traverse(*m_voltageLevel.getVertex(bus.getId(), true), graphTraverser);
}

BusViewImpl::BusViewImpl(BusBreakerVoltageLevel& voltageLevel) :
m_voltageLevel(voltageLevel) {
}
Expand Down
2 changes: 2 additions & 0 deletions src/iidm/BusBreakerVoltageLevelViews.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class BusBreakerViewImpl : public voltage_level::BusBreakerView {

void removeSwitch(const std::string& switchId) override;

void traverse(const Bus& bus, Traverser& traverser) override;

public:
explicit BusBreakerViewImpl(BusBreakerVoltageLevel& voltageLevel);

Expand Down
19 changes: 2 additions & 17 deletions src/iidm/CalculatedBus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <powsybl/iidm/Switch.hpp>
#include <powsybl/iidm/SynchronousComponentsManager.hpp>
#include <powsybl/iidm/TopologyVisitor.hpp>
#include <powsybl/iidm/util/Networks.hpp>
#include <powsybl/stdcxx/cast.hpp>
#include <powsybl/stdcxx/math.hpp>

Expand Down Expand Up @@ -38,23 +39,7 @@ stdcxx::CReference<NodeTerminal> CalculatedBus::findTerminal(const NodeBreakerVo
if (!terminals.empty()) {
return stdcxx::cref<NodeTerminal>(terminals.front().get());
}

stdcxx::CReference<Terminal> terminal;

VoltageLevel::NodeBreakerView::Traverser traverser = [&terminal, &voltageLevel](unsigned long /*node1*/, const stdcxx::Reference<Switch>& sw, unsigned long node2) {
if (terminal) {
return false;
}

if (static_cast<bool>(sw) && sw.get().isOpen()) {
return false;
}
terminal = voltageLevel.getNodeBreakerView().getTerminal(node2);
return !static_cast<bool>(terminal);
};
voltageLevel.getNodeBreakerView().traverse(nodes.front(), traverser);

return stdcxx::cref<NodeTerminal>(terminal);
return stdcxx::cref<NodeTerminal>(Networks::getEquivalentTerminal(voltageLevel, nodes.front()));
}

double CalculatedBus::getAngle() const {
Expand Down
4 changes: 2 additions & 2 deletions src/iidm/NodeBreakerVoltageLevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,9 @@ void NodeBreakerVoltageLevel::traverse(NodeTerminal& terminal, VoltageLevel::Top
addNextTerminals(otherTerminal.get(), nextTerminals);
return math::TraverseResult::CONTINUE;
}
return math::TraverseResult::TERMINATE;
return math::TraverseResult::TERMINATE_PATH;
}
return math::TraverseResult::TERMINATE;
return math::TraverseResult::TERMINATE_PATH;
});

for (auto nextTerminal : nextTerminals) {
Expand Down
6 changes: 3 additions & 3 deletions src/iidm/NodeBreakerVoltageLevelTopology.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ stdcxx::Reference<Bus> CalculatedBusTopology::getConnectableBus(unsigned long no
if (static_cast<bool>(connectableBus)) {
// traverse does not stop the algorithm when TERMINATE, it only stops searching in a given direction
// this condition insures that while checking all the edges (in every direction) of a node, if a bus is found, it will not be lost
return math::TraverseResult::TERMINATE;
return math::TraverseResult::TERMINATE_PATH;
}
connectableBus = getBus(v2);

return static_cast<bool>(connectableBus) ? math::TraverseResult::TERMINATE : math::TraverseResult::CONTINUE;
return static_cast<bool>(connectableBus) ? math::TraverseResult::TERMINATE_PATH : math::TraverseResult::CONTINUE;
});

// if nothing found, just take the first bus
Expand Down Expand Up @@ -255,7 +255,7 @@ void CalculatedBusTopology::traverse(unsigned long v, std::vector<bool>& encount
graph.traverse(v, [&graph, &terminate, &vertices](unsigned long /*v1*/, unsigned long e, unsigned long v2) {
const stdcxx::Reference<Switch> aSwitch = graph.getEdgeObject(e);
if (static_cast<bool>(aSwitch) && terminate(aSwitch)) {
return math::TraverseResult::TERMINATE;
return math::TraverseResult::TERMINATE_PATH;
}

vertices.push_back(v2);
Expand Down
16 changes: 14 additions & 2 deletions src/iidm/NodeBreakerVoltageLevelViews.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ void BusBreakerViewImpl::removeSwitch(const std::string& /*switchId*/) {
throw AssertionError("Not implemented");
}

void BusBreakerViewImpl::traverse(const Bus& /*bus*/, Traverser& /*traverser*/) {
throw AssertionError("Not implemented");
}

BusViewImpl::BusViewImpl(NodeBreakerVoltageLevel& voltageLevel) :
m_voltageLevel(voltageLevel) {
}
Expand Down Expand Up @@ -312,13 +316,21 @@ void NodeBreakerViewImpl::removeSwitch(const std::string& switchId) {
}

void NodeBreakerViewImpl::traverse(unsigned long node, const Traverser& traverser) const {
powsybl::math::Traverser graphTraverser = [this, &traverser](unsigned long v1, unsigned long e, unsigned long v2) {
return traverser(v1, m_voltageLevel.getGraph().getEdgeObject(e), v2) ? powsybl::math::TraverseResult::CONTINUE : powsybl::math::TraverseResult::TERMINATE;
math::Traverser graphTraverser = [this, &traverser](unsigned long v1, unsigned long e, unsigned long v2) {
return traverser(v1, m_voltageLevel.getGraph().getEdgeObject(e), v2);
};

m_voltageLevel.getGraph().traverse(node, graphTraverser);
}

void NodeBreakerViewImpl::traverse(stdcxx::const_range<unsigned long>& nodes, const Traverser& traverser) const {
powsybl::math::Traverser graphTraverser = [this, &traverser](unsigned long v1, unsigned long e, unsigned long v2) {
return traverser(v1, m_voltageLevel.getGraph().getEdgeObject(e), v2);
};

m_voltageLevel.getGraph().traverse(nodes, graphTraverser);
}

} // namespace node_breaker_voltage_level

} // namespace iidm
Expand Down
4 changes: 4 additions & 0 deletions src/iidm/NodeBreakerVoltageLevelViews.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class NodeBreakerViewImpl : public voltage_level::NodeBreakerView {

void traverse(unsigned long node, const Traverser& traverser) const override;

void traverse(stdcxx::const_range<unsigned long>& nodes, const Traverser& traverser) const override;

public:
explicit NodeBreakerViewImpl(NodeBreakerVoltageLevel& voltageLevel);

Expand Down Expand Up @@ -121,6 +123,8 @@ class BusBreakerViewImpl : public voltage_level::BusBreakerView {

unsigned long getSwitchCount() const override;

void traverse(const Bus& bus, Traverser& traverser) override;

public:
explicit BusBreakerViewImpl(NodeBreakerVoltageLevel& voltageLevel);

Expand Down
4 changes: 2 additions & 2 deletions src/iidm/util/Networks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ stdcxx::CReference<Terminal> getEquivalentTerminal(const VoltageLevel& voltageLe

VoltageLevel::NodeBreakerView::Traverser traverser = [&equivalentTerminal, &voltageLevel](unsigned long /*node1*/, const stdcxx::Reference<Switch>& sw, unsigned long node2) {
if (sw && sw.get().isOpen()) {
return false;
return math::TraverseResult::TERMINATE_PATH;
}
const auto& terminal = voltageLevel.getNodeBreakerView().getTerminal(node2);
if (terminal) {
equivalentTerminal = terminal;
}
return !terminal;
return terminal ? math::TraverseResult::TERMINATE_TRAVERSER : math::TraverseResult::CONTINUE;
};

voltageLevel.getNodeBreakerView().traverse(node, traverser);
Expand Down
Loading

0 comments on commit b4fde65

Please sign in to comment.