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);
258 std::function<
void(CellType*)> init_function
305 const std::vector<T>& items,
308 typename std::vector<T>::const_reference
314 template<
typename CellType>
317 template<
typename CellType>
322 matrix.resize(height);
323 for(
auto& row : matrix)
327 template<
typename CellType>
337 allocate(cells, local_dimensions.
width(), local_dimensions.
height());
341 auto cell = cell_factory.
build({x, y});
342 cells[y-origin.
y][x-origin.
x] = cell;
344 for(
auto group : groups)
345 group.get().add(cell);
351 built_cells.insert(std::pair<api::model::DiscretePoint, std::size_t>(
358 for(
auto row : cells) {
359 for(
auto cell : row) {
363 cell_index.insert({index, cell});
368 std::vector<std::mt19937_64::result_type> local_seeds(
372 for(std::size_t i = 0; i < local_seeds.size(); i++)
378 std::seed_seq seed_generator(local_seeds.begin(), local_seeds.end());
379 seed_generator.generate(local_seeds.begin(), local_seeds.end());
381 initSequence(local_seeds, [] (
383 const std::mt19937_64::result_type&
seed) {
390 template<
typename CellType>
391 std::vector<CellType*> GridBuilder<CellType>::_build(
392 api::model::SpatialModel<CellType>& model,
394 typedef std::pair<std::pair<DistributedId, DiscretePoint>, std::vector<api::model::GroupId>>
398 auto& mpi_comm = model.graph().getMpiCommunicator();
401 TreeProcessMapping tree_process_mapping(
402 this->width(), this->height(), mpi_comm
405 GridDimensions local_dimensions
406 = tree_process_mapping.gridDimensions(mpi_comm.getRank());
409 cells = buildLocalCells(
410 model, local_dimensions, groups
414 buildLocalGrid(model, local_dimensions, cells);
416 std::unordered_map<int, std::vector<GridCellPack>> mpi_frontiers;
439 auto cell = cells[y][0];
440 std::set<int> processes = {
441 tree_process_mapping.process({left_x, cell->location().y})
443 if(cell->location().y+1 < this->height())
445 tree_process_mapping.process({left_x, cell->location().y+1})
447 if(cell->location().y-1 >= 0)
449 tree_process_mapping.process({left_x, cell->location().y-1})
452 for(
int process : processes) {
453 mpi_frontiers[process].push_back(
454 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
462 auto cell = cells[0][x];
463 std::set<int> processes = {
464 tree_process_mapping.process({cell->location().x, bottom_y})
466 if(cell->location().x+1 < this->width())
468 tree_process_mapping.process({cell->location().x+1, bottom_y})
470 if(cell->location().x-1 >= 0)
472 tree_process_mapping.process({cell->location().x-1, bottom_y})
474 for(
int process : processes) {
475 mpi_frontiers[process].push_back(
476 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
482 if(right_x < this->width()) {
485 auto cell = cells[y][local_dimensions.width()-1];
486 std::set<int> processes = {
487 tree_process_mapping.process({right_x, cell->location().y})
489 if(cell->location().y+1 < this->height())
491 tree_process_mapping.process({right_x, cell->location().y+1})
494 if(cell->location().y-1 >= 0)
496 tree_process_mapping.process({right_x, cell->location().y-1})
498 for(
int process : processes) {
499 mpi_frontiers[process].push_back(
500 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
506 if(top_y < this->height()) {
509 auto cell = cells[local_dimensions.height()-1][x];
510 std::set<int> processes = {
511 tree_process_mapping.process({cell->location().x, top_y})
516 if(cell->location().x+1 < this->width())
518 tree_process_mapping.process({cell->location().x+1, top_y})
520 if(cell->location().x-1 >= 0)
522 tree_process_mapping.process({cell->location().x-1, top_y})
525 for(
int process : processes) {
526 mpi_frontiers[process].push_back(
527 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
552 if(local_dimensions.height() > 0 && local_dimensions.width() > 0) {
553 std::set<int> corners_processes;
556 auto cell = cells[0][0];
557 std::set<int> processes;
558 auto x = cell->location().x;
559 auto y = cell->location().y;
562 tree_process_mapping.process({x, y-1})
566 tree_process_mapping.process({x-1, y-1})
568 if(x+1 < this->width())
570 tree_process_mapping.process({x+1, y-1})
575 tree_process_mapping.process({x-1, y})
577 if(y+1 < this->height())
579 tree_process_mapping.process({x-1, y+1})
582 for(
int process : processes) {
583 mpi_frontiers[process].push_back(
584 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
585 corners_processes.insert(processes.begin(), processes.end());
591 auto cell = cells[0][local_dimensions.width()-1];
592 std::set<int> processes;
593 auto x = cell->location().x;
594 auto y = cell->location().y;
597 tree_process_mapping.process({x, y-1})
601 tree_process_mapping.process({x-1, y-1})
603 if(x+1 < this->width())
605 tree_process_mapping.process({x+1, y-1})
608 if(x+1 < this->width()) {
610 tree_process_mapping.process({x+1, y})
612 if(y+1 < this->height())
614 tree_process_mapping.process({x+1, y+1})
617 for(
int process : processes) {
618 mpi_frontiers[process].push_back(
619 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
620 corners_processes.insert(processes.begin(), processes.end());
626 auto cell = cells[local_dimensions.height()-1][0];
627 std::set<int> processes;
628 auto x = cell->location().x;
629 auto y = cell->location().y;
630 if(y+1 < this->height()) {
632 tree_process_mapping.process({x, y+1})
636 tree_process_mapping.process({x-1, y+1})
638 if(x+1 < this->width())
640 tree_process_mapping.process({x+1, y+1})
645 tree_process_mapping.process({x-1, y})
649 tree_process_mapping.process({x-1, y+1})
652 for(
int process : processes) {
653 mpi_frontiers[process].push_back(
654 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
655 corners_processes.insert(processes.begin(), processes.end());
661 auto cell = cells[local_dimensions.height()-1][local_dimensions.width()-1];
662 std::set<int> processes;
663 auto x = cell->location().x;
664 auto y = cell->location().y;
665 if(y+1 < this->height()) {
667 tree_process_mapping.process({x, y+1})
671 tree_process_mapping.process({x-1, y+1})
673 if(x+1 < this->width())
675 tree_process_mapping.process({x+1, y+1})
678 if(x+1 < this->width()) {
680 tree_process_mapping.process({x+1, y})
684 tree_process_mapping.process({x+1, y-1})
687 for(
int process : processes) {
688 mpi_frontiers[process].push_back(
689 {{cell->node()->getId(), cell->location()}, cell->groupIds()});
690 corners_processes.insert(processes.begin(), processes.end());
693 if(local_dimensions.width() <= 2 || local_dimensions.height() <=2) {
697 auto less_grid_cell_pack = [](
const GridCellPack& p1,
const GridCellPack& p2) {
698 return p1.first.first < p2.first.first;
700 for(
int process : corners_processes) {
701 std::set<GridCellPack,
decltype(less_grid_cell_pack)> packs(less_grid_cell_pack);
702 for(
auto pack : mpi_frontiers[process])
704 mpi_frontiers[process].clear();
705 for(
auto pack : packs)
706 mpi_frontiers[process].push_back(pack);
713 mpi_frontiers = mpi.allToAll(mpi_frontiers);
715 std::vector<CellType*> cell_frontiers;
716 for(
auto frontier : mpi_frontiers) {
717 for(
auto cell_pack : frontier.second) {
719 auto cell = cell_factory.
build(cell_pack.first.second);
722 for(
auto gid : cell_pack.second)
723 cell->addGroupId(gid);
727 api::graph::DistributedNode<AgentPtr>* tmp_node
728 =
new graph::DistributedNode<AgentPtr>(cell_pack.first.first, cell);
729 tmp_node->setLocation(frontier.first);
730 model.graph().insertDistant(tmp_node);
731 cell_frontiers.push_back(cell);
735 linkFrontiers(model, local_dimensions, cells, cell_frontiers);
737 model.graph().synchronize();
738 std::vector<CellType*> built_cells;
739 for(
auto row : cells)
741 built_cells.push_back(cell);
745 template<
typename CellType>
748 std::function<
void(CellType*)> init_function)
const {
751 for(
auto index : indexes) {
752 auto it = cell_index.find(index);
753 if(it != cell_index.end())
754 init_function(it->second);
758 template<
typename CellType>
761 const std::vector<T> &items,
764 typename std::vector<T>::const_reference
765 )> init_function)
const {
767 auto map_index = cell_index.
begin();
769 while(map_index != cell_index.end()) {
770 if(map_index->first == grid_index) {
Definition: spatial_model.h:558
virtual CellType * build(DiscretePoint location)=0
Definition: spatial_model.h:479
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:760
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:746
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:590
static random::mt19937_64 rd
Definition: grid.h:238