1#ifndef FPMAS_GRID_BUILDER_H
2#define FPMAS_GRID_BUILDER_H
12namespace fpmas {
namespace model {
namespace detail {
28 template<
typename CellType>
44 mutable std::map<DiscretePoint, std::size_t> built_cells;
47 mutable std::map<GridCellIndex, CellType*> cell_index;
59 std::vector<CellType*> _build(
128 std::vector<CellType*>& frontier
154 : cell_factory(cell_factory), _width(
width), _height(
height) {
208 return this->_build(spatial_model, {});
217 return this->_build(spatial_model, groups);
259 std::function<
void(CellType*)> init_function
306 const std::vector<T>& items,
309 typename std::vector<T>::const_reference
315 template<
typename CellType>
318 template<
typename CellType>
323 matrix.resize(height);
324 for(
auto& row : matrix)
328 template<
typename CellType>
338 allocate(cells, local_dimensions.
width(), local_dimensions.
height());
342 auto cell = cell_factory.
build({x, y});
343 cells[y-origin.
y][x-origin.
x] = cell;
345 for(
auto group : groups)
346 group.get().add(cell);
352 built_cells.insert(std::pair<api::model::DiscretePoint, std::size_t>(
359 for(
auto row : cells) {
360 for(
auto cell : row) {
364 cell_index.insert({index, cell});
369 std::vector<std::mt19937_64::result_type> local_seeds(
373 for(std::size_t i = 0; i < local_seeds.size(); i++)
379 std::seed_seq seed_generator(local_seeds.begin(), local_seeds.end());
380 seed_generator.generate(local_seeds.begin(), local_seeds.end());
382 initSequence(local_seeds, [] (
384 const std::mt19937_64::result_type&
seed) {
391 template<
typename CellType>
392 std::vector<CellType*> GridBuilder<CellType>::_build(
393 api::model::SpatialModel<CellType>& model,
395 typedef std::pair<std::pair<DistributedId, DiscretePoint>, std::vector<api::model::GroupId>>
399 auto& mpi_comm = model.graph().getMpiCommunicator();
402 TreeProcessMapping tree_process_mapping(
403 this->width(), this->height(), mpi_comm
406 GridDimensions local_dimensions
407 = tree_process_mapping.gridDimensions(mpi_comm.getRank());
410 cells = buildLocalCells(
411 model, local_dimensions, groups
415 buildLocalGrid(model, local_dimensions, cells);
417 std::unordered_map<int, std::vector<GridCellPack>> mpi_frontiers;
440 auto cell = cells[y][0];
441 std::set<int> processes = {
442 tree_process_mapping.process({left_x, cell->location().y})
444 if(cell->location().y+1 < this->height())
446 tree_process_mapping.process({left_x, cell->location().y+1})
448 if(cell->location().y-1 >= 0)
450 tree_process_mapping.process({left_x, cell->location().y-1})
453 for(
int process : processes) {
454 mpi_frontiers[process].push_back(
455 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
463 auto cell = cells[0][x];
464 std::set<int> processes = {
465 tree_process_mapping.process({cell->location().x, bottom_y})
467 if(cell->location().x+1 < this->width())
469 tree_process_mapping.process({cell->location().x+1, bottom_y})
471 if(cell->location().x-1 >= 0)
473 tree_process_mapping.process({cell->location().x-1, bottom_y})
475 for(
int process : processes) {
476 mpi_frontiers[process].push_back(
477 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
483 if(right_x < this->width()) {
486 auto cell = cells[y][local_dimensions.width()-1];
487 std::set<int> processes = {
488 tree_process_mapping.process({right_x, cell->location().y})
490 if(cell->location().y+1 < this->height())
492 tree_process_mapping.process({right_x, cell->location().y+1})
495 if(cell->location().y-1 >= 0)
497 tree_process_mapping.process({right_x, cell->location().y-1})
499 for(
int process : processes) {
500 mpi_frontiers[process].push_back(
501 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
507 if(top_y < this->height()) {
510 auto cell = cells[local_dimensions.height()-1][x];
511 std::set<int> processes = {
512 tree_process_mapping.process({cell->location().x, top_y})
517 if(cell->location().x+1 < this->width())
519 tree_process_mapping.process({cell->location().x+1, top_y})
521 if(cell->location().x-1 >= 0)
523 tree_process_mapping.process({cell->location().x-1, top_y})
526 for(
int process : processes) {
527 mpi_frontiers[process].push_back(
528 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
553 if(local_dimensions.height() > 0 && local_dimensions.width() > 0) {
554 std::set<int> corners_processes;
557 auto cell = cells[0][0];
558 std::set<int> processes;
559 auto x = cell->location().x;
560 auto y = cell->location().y;
563 tree_process_mapping.process({x, y-1})
567 tree_process_mapping.process({x-1, y-1})
569 if(x+1 < this->width())
571 tree_process_mapping.process({x+1, y-1})
576 tree_process_mapping.process({x-1, y})
578 if(y+1 < this->height())
580 tree_process_mapping.process({x-1, y+1})
583 for(
int process : processes) {
584 mpi_frontiers[process].push_back(
585 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
586 corners_processes.insert(processes.begin(), processes.end());
592 auto cell = cells[0][local_dimensions.width()-1];
593 std::set<int> processes;
594 auto x = cell->location().x;
595 auto y = cell->location().y;
598 tree_process_mapping.process({x, y-1})
602 tree_process_mapping.process({x-1, y-1})
604 if(x+1 < this->width())
606 tree_process_mapping.process({x+1, y-1})
609 if(x+1 < this->width()) {
611 tree_process_mapping.process({x+1, y})
613 if(y+1 < this->height())
615 tree_process_mapping.process({x+1, y+1})
618 for(
int process : processes) {
619 mpi_frontiers[process].push_back(
620 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
621 corners_processes.insert(processes.begin(), processes.end());
627 auto cell = cells[local_dimensions.height()-1][0];
628 std::set<int> processes;
629 auto x = cell->location().x;
630 auto y = cell->location().y;
631 if(y+1 < this->height()) {
633 tree_process_mapping.process({x, y+1})
637 tree_process_mapping.process({x-1, y+1})
639 if(x+1 < this->width())
641 tree_process_mapping.process({x+1, y+1})
646 tree_process_mapping.process({x-1, y})
650 tree_process_mapping.process({x-1, y+1})
653 for(
int process : processes) {
654 mpi_frontiers[process].push_back(
655 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
656 corners_processes.insert(processes.begin(), processes.end());
662 auto cell = cells[local_dimensions.height()-1][local_dimensions.width()-1];
663 std::set<int> processes;
664 auto x = cell->location().x;
665 auto y = cell->location().y;
666 if(y+1 < this->height()) {
668 tree_process_mapping.process({x, y+1})
672 tree_process_mapping.process({x-1, y+1})
674 if(x+1 < this->width())
676 tree_process_mapping.process({x+1, y+1})
679 if(x+1 < this->width()) {
681 tree_process_mapping.process({x+1, y})
685 tree_process_mapping.process({x+1, y-1})
688 for(
int process : processes) {
689 mpi_frontiers[process].push_back(
690 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
691 corners_processes.insert(processes.begin(), processes.end());
694 if(local_dimensions.width() <= 2 || local_dimensions.height() <=2) {
698 auto less_grid_cell_pack = [](
const GridCellPack& p1,
const GridCellPack& p2) {
699 return p1.first.first < p2.first.first;
701 for(
int process : corners_processes) {
702 std::set<GridCellPack,
decltype(less_grid_cell_pack)> packs(less_grid_cell_pack);
703 for(
auto pack : mpi_frontiers[process])
705 mpi_frontiers[process].clear();
706 for(
auto pack : packs)
707 mpi_frontiers[process].push_back(pack);
714 mpi_frontiers = mpi.allToAll(mpi_frontiers);
716 std::vector<CellType*> cell_frontiers;
717 for(
auto frontier : mpi_frontiers) {
718 for(
auto cell_pack : frontier.second) {
720 auto cell = cell_factory.
build(cell_pack.first.second);
723 for(
auto gid : cell_pack.second)
724 cell->addGroupId(gid);
728 api::graph::DistributedNode<AgentPtr>* tmp_node
729 =
new graph::DistributedNode<AgentPtr>(cell_pack.first.first, cell);
730 tmp_node->setLocation(frontier.first);
731 model.graph().insertDistant(tmp_node);
732 cell_frontiers.push_back(cell);
736 linkFrontiers(model, local_dimensions, cells, cell_frontiers);
738 model.graph().synchronize();
739 std::vector<CellType*> built_cells;
740 for(
auto row : cells)
742 built_cells.push_back(cell);
746 template<
typename CellType>
749 std::function<
void(CellType*)> init_function)
const {
752 for(
auto index : indexes) {
753 auto it = cell_index.find(index);
754 if(it != cell_index.end())
755 init_function(it->second);
759 template<
typename CellType>
762 const std::vector<T> &items,
765 typename std::vector<T>::const_reference
766 )> init_function)
const {
768 auto map_index = cell_index.
begin();
770 while(map_index != cell_index.end()) {
771 if(map_index->first == grid_index) {
Definition: spatial_model.h:568
virtual CellType * build(DiscretePoint location)=0
virtual void add(CellType *cell)=0
Definition: grid_load_balancing.h:30
DiscreteCoordinate height() const
Definition: grid_load_balancing.h:79
DiscreteCoordinate width() const
Definition: grid_load_balancing.h:72
DiscretePoint getOrigin() const
Definition: grid_load_balancing.h:53
DiscretePoint getExtent() const
Definition: grid_load_balancing.h:62
Definition: grid_builder.h:29
virtual void buildLocalGrid(api::model::SpatialModel< CellType > &model, GridDimensions local_dimensions, CellMatrix &cells) const =0
void initSequence(const std::vector< T > &items, std::function< void(CellType *, typename std::vector< T >::const_reference)> init_function) const
Definition: grid_builder.h:761
static GridCellFactory< CellType > default_cell_factory
Definition: grid_builder.h:136
virtual void linkFrontiers(api::model::SpatialModel< CellType > &model, GridDimensions local_dimensions, CellMatrix &local_cells, std::vector< CellType * > &frontier) const =0
std::vector< CellType * > build(api::model::SpatialModel< CellType > &spatial_model, api::model::GroupList groups) const override
Definition: grid_builder.h:214
std::vector< CellType * > build(api::model::SpatialModel< CellType > &spatial_model) const override
Definition: grid_builder.h:206
DiscreteCoordinate width() const
Definition: grid_builder.h:176
GridBuilder(DiscreteCoordinate width, DiscreteCoordinate height)
Definition: grid_builder.h:166
DiscreteCoordinate height() const
Definition: grid_builder.h:182
std::vector< std::vector< CellType * > > CellMatrix
Definition: grid_builder.h:37
void initSample(std::size_t n, std::function< void(CellType *)> init_function) const
Definition: grid_builder.h:747
GridBuilder(api::model::GridCellFactory< CellType > &cell_factory, DiscreteCoordinate width, DiscreteCoordinate height)
Definition: grid_builder.h:150
static Index end(const std::map< DiscretePoint, std::size_t > *item_counts)
Definition: random.h:479
static std::size_t distance(const Index &i1, const Index &i2)
Definition: random.h:529
static Index begin(const std::map< DiscretePoint, std::size_t > *item_counts)
Definition: random.h:471
std::vector< std::reference_wrapper< AgentGroup > > GroupList
Definition: model.h:833
long DiscreteCoordinate
Definition: grid.h:15
random::Index< DiscretePoint > GridCellIndex
Definition: grid_builder.h:17
std::vector< Index_t > sample_indexes(Index_t begin, Index_t end, std::size_t n, Generator_t &gen)
Definition: random.h:292
void seed(unsigned long seed)
Definition: fpmas.cpp:23
DiscreteCoordinate x
Definition: grid.h:25
DiscreteCoordinate y
Definition: grid.h:29
Definition: communication.h:585
static random::mt19937_64 rd
Definition: grid.h:238