Program Listing for File ToroidalGridTopologyFactory.hpp¶
↰ Return to documentation for file (include/netuit/arrange/ToroidalGridTopologyFactory.hpp)
#pragma once
#ifndef NETUIT_ARRANGE_TOROIDALGRIDTOPOLOGYFACTORY_HPP_INCLUDE
#define NETUIT_ARRANGE_TOROIDALGRIDTOPOLOGYFACTORY_HPP_INCLUDE
#include <algorithm>
#include <cassert>
#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"
namespace netuit {
inline netuit::Topology make_toroidal_grid_topology(
const uitsl::Dims& dim_cardinality
) {
assert( dim_cardinality.size() == 2 ); // two-dimensional
assert( std::set<size_t>(
std::begin( dim_cardinality ), std::end( dim_cardinality )
).size() == 1 ); // square
const size_t dimension = dim_cardinality.front();
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_north_output_id = [cardinality](const size_t idx){
return cardinality * 0 + idx;
};
auto get_west_output_id = [cardinality](const size_t idx){
return cardinality * 1 + idx;
};
auto get_east_output_id = [cardinality](const size_t idx){
return cardinality * 2 + idx;
};
auto get_south_output_id = [cardinality](const size_t idx){
return cardinality * 3 + idx;
};
auto get_north_input_id = [&](const size_t idx){
// northern neighbor's southern input edge id
return get_south_output_id(
(idx + cardinality - dimension) % cardinality
);
};
auto get_south_input_id = [&](const size_t idx){
// southern neighbor's northern input edge id
return get_north_output_id(
(idx + dimension) % cardinality
);
};
auto get_east_input_id = [&](const size_t idx){
const size_t first_idx_in_row = (idx / dimension) * dimension;
const size_t idx_in_row = idx % dimension;
// eastern neighbor's western input id
return get_west_output_id(
first_idx_in_row + (idx_in_row + 1) % dimension
);
};
auto get_west_input_id = [&](const size_t idx){
const size_t first_idx_in_row = (idx / dimension) * dimension;
const size_t idx_in_row = idx % dimension;
// western neighbor's eastern input id
return get_east_output_id(
first_idx_in_row + (idx_in_row + dimension - 1) % dimension
);
};
for (auto it = nodes.begin(); it != nodes.end(); ++it) {
const size_t idx = std::distance(nodes.begin(), it);
it->AddInput( get_north_input_id( idx ) );
it->AddInput( get_west_input_id( idx ) );
it->AddInput( get_east_input_id( idx ) );
it->AddInput( get_south_input_id( idx ) );
it->AddOutput( get_north_output_id( idx ) );
it->AddOutput( get_west_output_id( idx ) );
it->AddOutput( get_east_output_id( idx ) );
it->AddOutput( get_south_output_id( idx ) );
}
return nodes;
}
struct ToroidalGridTopologyFactory {
netuit::Topology operator()(const size_t cardinality) const {
assert( uitsl::is_perfect_hypercube( cardinality, 2 ) );
const size_t dimension = static_cast<size_t>( std::sqrt(cardinality) );
return make_toroidal_grid_topology( { dimension, dimension } );
}
netuit::Topology operator()(const uitsl::Dims& dim_cardinality) const {
return make_toroidal_grid_topology(dim_cardinality);
}
static std::string GetName() { return "Toroidal Grid Topology"; }
static std::string GetSlug() { return "toroidal_grid"; }
};
} // namespace netuit
#endif // #ifndef NETUIT_ARRANGE_TOROIDALGRIDTOPOLOGYFACTORY_HPP_INCLUDE