Program Listing for File ToroidalTopologyFactory.hpp¶
↰ Return to documentation for file (include/netuit/arrange/ToroidalTopologyFactory.hpp)
#pragma once
#ifndef NETUIT_ARRANGE_TOROIDALTOPOLOGYFACTORY_HPP_INCLUDE
#define NETUIT_ARRANGE_TOROIDALTOPOLOGYFACTORY_HPP_INCLUDE
#include <algorithm>
#include <cmath>
#include <list>
#include <numeric>
#include <set>
#include <tuple>
#include <vector>
#include "../../uitsl/math/is_perfect_hypercube.hpp"
#include "../../uitsl/math/mapping_utils.hpp"
#include "../../uitsl/math/math_utils.hpp"
#include "../../uitsl/utility/UIDMap.hpp"
#include "../topology/TopoEdge.hpp"
#include "../topology/Topology.hpp"
#include "../topology/TopoNode.hpp"
#include "ToroidalGridTopologyFactory.hpp"
namespace netuit {
inline netuit::Topology make_toroidal_topology(
const uitsl::Dims& dim_cardinality
) {
// special case: if two-dimensional square, custom construct so it's easy
// to visualize
if ( dim_cardinality.size() == 2 && std::set<size_t>(
std::begin( dim_cardinality ), std::end( dim_cardinality )
).size() == 1 ) return netuit::make_toroidal_grid_topology( dim_cardinality );
/*
* goal
* make toroidal topology (such that opposite edges are the same edge)
*/
const size_t cardinality = std::accumulate(
dim_cardinality.begin(),
dim_cardinality.end(),
1ul,
std::multiplies<size_t>()
);
std::vector<netuit::TopoNode> nodes(cardinality);
uitsl::UIDMap<size_t> node_edge_map;
auto get_neighbor = [&dim_cardinality](uitsl::Point p, const size_t dim, const int n) -> uitsl::Point {
p[dim] = uitsl::circular_index(p[dim], dim_cardinality[dim], n);
return p;
};
// returns a vector containing all neighbors
auto get_neighbors = [&get_neighbor](const uitsl::Point& p) {
std::vector<uitsl::Point> neighbors;
for (size_t i{}; i < p.size(); ++i) {
neighbors.push_back(get_neighbor(p, i, +1));
}
for (size_t i{}; i < p.size(); ++i) {
// go through dimensions in reverse order
const size_t j = p.size() - 1 - i;
neighbors.push_back(get_neighbor(p, j, -1));
}
return neighbors;
};
for (size_t neigh{}; neigh < dim_cardinality.size() * 2; ++neigh) {
for (auto it = nodes.begin(); it != nodes.end(); ++it) {
const size_t my_idx = std::distance(nodes.begin(), it);
const auto my_point = uitsl::linear_decode(my_idx, dim_cardinality);
const auto neighbor_point = get_neighbors(my_point)[neigh];
const size_t neighbor_idx = uitsl::linear_encode(
neighbor_point, dim_cardinality
);
it->AddOutput(node_edge_map[{true, my_idx, neighbor_idx}]);
}
}
for (size_t neigh{}; neigh < dim_cardinality.size() * 2; ++neigh) {
for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) {
const size_t my_idx
= nodes.size() - std::distance(nodes.rbegin(), it) - 1;
const auto my_point = uitsl::linear_decode(my_idx, dim_cardinality);
const auto neighbor_point = get_neighbors(my_point)[neigh];
const size_t neighbor_idx = uitsl::linear_encode(
neighbor_point, dim_cardinality
);
it->AddInput(node_edge_map[{false, neighbor_idx, my_idx}]);
}
}
return nodes;
}
struct ToroidalTopologyFactory {
netuit::Topology operator()(const size_t cardinality) const {
return make_toroidal_topology({cardinality});
}
netuit::Topology operator()(const uitsl::Dims& dim_cardinality) const {
return make_toroidal_topology(dim_cardinality);
}
static std::string GetName() { return "Toroidal Topology"; }
static std::string GetSlug() { return "toroidal"; }
};
} // namespace netuit
#endif // #ifndef NETUIT_ARRANGE_TOROIDALTOPOLOGYFACTORY_HPP_INCLUDE