Program Listing for File RingTopologyFactory.hpp¶
↰ Return to documentation for file (include/netuit/arrange/RingTopologyFactory.hpp)
#pragma once
#ifndef NETUIT_ARRANGE_RINGTOPOLOGYFACTORY_HPP_INCLUDE
#define NETUIT_ARRANGE_RINGTOPOLOGYFACTORY_HPP_INCLUDE
#include <algorithm>
#include <cassert>
#include <list>
#include <vector>
#include "../topology/TopoEdge.hpp"
#include "../topology/Topology.hpp"
#include "../topology/TopoNode.hpp"
namespace netuit {
inline Topology make_ring_topology(const size_t cardinality) {
/*
* goal
* nodes: -> 0 -> 1 -> 2 -> 3 ->
*
* node 0: input from 3 & output to 1
* node 1: input from 0 & output to 2
* node 2: input from 1 & output to 3
* node 3: input from 2 & output to 0
*
* node 0: outlet 3 & inlet 0
* node 1: outlet 0 & inlet 1
* node 2: outlet 1 & inlet 2
* node 3: outlet 2 & inlet 3
*/
size_t edge_counter{};
std::vector<TopoEdge> edges;
std::generate_n(
std::back_inserter(edges),
cardinality,
[&](){ return TopoEdge{++edge_counter}; }
);
std::list<TopoNodeOutput> outputs;
std::transform(
std::begin(edges),
std::end(edges),
std::back_inserter(outputs),
[](const auto & edge) { return edge.GetInlet(); }
);
std::list<TopoNodeInput> inputs;
std::transform(
std::begin(edges),
std::end(edges),
std::back_inserter(inputs),
[](const auto & edge) { return edge.GetOutlet(); }
);
/*
* before rotate
* outputs: 0 1 2 3 (inlets to conduits)
* | | | |
* inputs: 0 1 2 3 (outlets from conduits)
*/
// rotate node inputs a.k.a. conduit outlets right by one
if (cardinality) inputs.splice(
std::begin(inputs),
inputs,
std::prev(std::end(inputs))
);
/*
* after rotate
* nodes: 0 1 2 3
* outputs: 0 1 2 3 (inlets to conduits)
* \ \ \ \ \
* inputs: 3 0 1 2 (outlets from conduits)
* nodes: 0 1 2 3
*/
Topology res;
auto outputs_iterator = std::begin(outputs);
auto inputs_iterator = std::begin(inputs);
for (
;
outputs_iterator != std::end(outputs)
&& inputs_iterator != std::end(inputs);
++outputs_iterator, ++inputs_iterator
) {
res.push_back(TopoNode{
{*inputs_iterator},
{*outputs_iterator}
});
}
return res;
}
struct RingTopologyFactory {
Topology operator()(const size_t cardinality) const {
return make_ring_topology(cardinality);
}
netuit::Topology operator()(const std::vector<size_t> cardinality) const {
assert(cardinality.size() == 1);
return make_ring_topology(cardinality.front());
}
static std::string GetName() { return "Ring Topology"; }
static std::string GetSlug() { return "ring"; }
};
} // namespace netuit
#endif // #ifndef NETUIT_ARRANGE_RINGTOPOLOGYFACTORY_HPP_INCLUDE