fpmas 1.6
spatial_model.h
Go to the documentation of this file.
1#ifndef FPMAS_ENVIRONMENT_H
2#define FPMAS_ENVIRONMENT_H
3
8#include "dist_move_algo.h"
10#include "../serializer.h"
11#include <type_traits>
12
13
27#define FPMAS_MOBILITY_RANGE(RANGE)\
28 const decltype(RANGE)& mobilityRange() const override {return RANGE;}
29
44#define FPMAS_PERCEPTION_RANGE(RANGE)\
45 const decltype(RANGE)& perceptionRange() const override {return RANGE;}
46
47namespace fpmas { namespace model {
49 using api::model::DistributedId;
50
54 static const api::model::GroupId CELL_GROUP_ID = -1;
55
60 static const bool EXCLUDE_LOCATION = false;
65 static const bool INCLUDE_LOCATION = true;
66
70 template<typename CellType>
72 public api::model::MoveAgentGroup<CellType>,
74 private:
77
78 public:
93 api::model::GroupId group_id,
97 AgentGroupBase(group_id, model.graph(), behavior),
98 model(model),
99 dist_move_algo(model, *this, model.getGroup(CELL_GROUP_ID), end_condition) {
100 }
101
119 api::scheduler::JobList jobs() const override;
120
122 return dist_move_algo;
123 }
124 };
125
126 template<typename CellType>
129 job_list.push_back(this->agentExecutionJob());
130
131 for(auto job : dist_move_algo.jobs())
132 job_list.push_back(job);
133 return job_list;
134 }
135
136 namespace detail {
142 private:
143 api::model::Agent* _agent;
144 fpmas::graph::LayerId layer_id;
145 std::vector<DistributedId> current_layer_ids;
146
147 public:
156 : _agent(agent), layer_id(layer_id) {
157 auto edges = agent->node()->getOutgoingEdges(layer_id);
158 current_layer_ids.resize(edges.size());
159
160 for(std::size_t i = 0; i < edges.size(); i++)
161 current_layer_ids[i] = edges[i]->getTargetNode()->getId();
162 }
163
173 return std::find(
174 current_layer_ids.begin(),
175 current_layer_ids.end(),
176 agent->node()->getId()
177 ) != current_layer_ids.end();
178 }
179
189 void link(fpmas::api::model::Agent* other_agent) {
190 current_layer_ids.push_back(other_agent->node()->getId());
191 _agent->model()->link(_agent, other_agent, layer_id);
192 }
193 };
194 }
195
214 template<typename CellInterface, typename CellType, typename TypeIdBase = CellType>
215 class CellBase : public detail::AgentBase<CellInterface, CellType, TypeIdBase> {
216 private:
217 /*
218 * Some profiling analysis show that the successors() method calls,
219 * have a significant performance cost.
220 * The purpose of the following structures is to drastically reduce
221 * the call to the successors() method, buffering the result only
222 * when required.
223 * This is safe, since the Cell network can't be modified during
224 * the DistributedMoveAlgorithm execution.
225 * The buffer is safely used by init(), handleNewLocation(),
226 * handleMove() and handlePerceive(), but is not safe for a generic
227 * use since new CELL_SUCCESSOR edges might be deleted or created
228 * at any time, out of the DistributedMoveAlgorithm context.
229 */
230 std::vector<CellType*> successors_buffer;
231 std::vector<api::model::AgentEdge*> raw_successors_buffer;
232 const std::vector<CellType*>& bufferedSuccessors();
233
234
235 void updateLocation(
236 api::model::Agent* agent, api::model::AgentEdge* new_location_edge
237 );
238
239 void growMobilityField(api::model::Agent* agent);
240 void growPerceptionField(api::model::Agent* agent);
241
242 protected:
249 std::set<DistributedId> no_move_flags;
257 std::set<DistributedId> move_flags;
265 std::set<DistributedId> perception_flags;
266
267 public:
271 CellBase() = default;
272
287 CellBase(const CellBase&) = default;
288
303 CellBase& operator=(const CellBase&) = default;
304
319 CellBase(CellBase&&) = default;
320
333 return *this;
334 }
335
341 std::vector<api::model::Cell*> successors() override;
347 void handleNewLocation() override;
348
354 void handleMove() override;
355
361 void handlePerceive() override;
362
369
375 void init() override;
376
377
378 };
379
380 template<typename CellInterface, typename CellType, typename TypeIdBase>
382 return this->successors_buffer;
383 }
384
385 template<typename CellInterface, typename CellType, typename TypeIdBase>
387 bool init_successors;
388
389 // This has no performance impact
390 auto current_successors
391 = this->node()->getOutgoingEdges(SpatialModelLayers::CELL_SUCCESSOR);
392 // Checks if the currently buffered successors are stricly equal to the
393 // current_successors. In this case, there is no need to update the
394 // successors() list
395 if(current_successors.size() == 0 ||
396 current_successors.size() != raw_successors_buffer.size()) {
397 init_successors = false;
398 } else {
399 auto it = current_successors.begin();
400 auto raw_it = raw_successors_buffer.begin();
401 while(it != current_successors.end() && (*it) == *raw_it) {
402 it++;
403 raw_it++;
404 }
405 if(it == current_successors.end()) {
406 init_successors = true;
407 } else {
408 init_successors = false;
409 }
410 }
411
412 if(!init_successors) {
413 raw_successors_buffer = current_successors;
414 successors_buffer.resize(raw_successors_buffer.size());
415 for(std::size_t i = 0; i < raw_successors_buffer.size(); i++)
416 successors_buffer[i] = static_cast<CellType*>(
417 raw_successors_buffer[i]->getTargetNode()->data().get()
418 );
419 }
420
421 std::set<DistributedId> new_location_layer;
422 for(auto agent_edge
423 : this->node()->getIncomingEdges(SpatialModelLayers::NEW_LOCATION))
424 new_location_layer.insert(agent_edge->getSourceNode()->getId());
425
426 // The location of agents that are still linked on the MOVE /
427 // PERCEIVE layer has not been updated, since those layers are
428 // unlinked by SpatialAgent::updateLocation(), unless the current
429 // cell is actually their NEW_LOCATION.
430 for(auto agent_edge : this->node()->getIncomingEdges(SpatialModelLayers::MOVE)) {
431 if(new_location_layer.count(agent_edge->getSourceNode()->getId())==0)
432 this->no_move_flags.insert(agent_edge->getSourceNode()->getId());
433 }
434 for(auto agent_edge : this->node()->getIncomingEdges(SpatialModelLayers::PERCEIVE)) {
435 if(new_location_layer.count(agent_edge->getSourceNode()->getId())==0)
436 this->no_move_flags.insert(agent_edge->getSourceNode()->getId());
437 }
438 // All agents already linked on the LOCATION layer didn't update
439 // their location, since LOCATION links are unlinked by
440 // SpatialAgent::updateLocation().
441 for(auto agent_edge : this->node()->getIncomingEdges(SpatialModelLayers::LOCATION)) {
442 this->no_move_flags.insert(agent_edge->getSourceNode()->getId());
443 }
444 }
445
446 template<typename CellInterface, typename CellType, typename TypeIdBase>
448 if(agent->node()->state() == api::graph::LOCAL) {
449 // There is no need to create a temporary NEW_MOVE
450 // link, since the mobilityRange() of the agent is
451 // directly available on the current process.
452 auto* spatial_agent
453 = static_cast<api::model::SpatialAgent<CellType>*>(agent);
454
455 // Valid, since the agent is LOCAL
456 auto location = spatial_agent->locationCell();
457
458 fpmas::model::ReadGuard read_location(location);
459
460 // Cells currently in the move_layer
461 detail::CurrentOutLayer move_layer(agent, SpatialModelLayers::MOVE);
462 for(auto cell : this->bufferedSuccessors()) {
463 if(!move_layer.contains(cell)) {
464 // The cell as not already been linked in the
465 // MOVE layer
466 fpmas::model::ReadGuard read_cell(cell);
467
468 if(spatial_agent->mobilityRange().contains(
469 location,
470 cell
471 )) {
472 // The cell is contained in the agent
473 // mobility range: add it to its mobility
474 // field
475 move_layer.link(cell);
476 }
477 }
478 }
479 } else {
480 // In this case, the mobility range of the agent is not
481 // available on the current process, so a temporary
482 // NEW_MOVE edge must be created and handled later by
483 // the agent in the SpatialAgent::handleNewMove()
484 // method
485 for(auto cell : this->bufferedSuccessors())
486 this->model()->link(
487 agent,
488 cell,
489 SpatialModelLayers::NEW_MOVE
490 );
491 }
492 }
493
494 template<typename CellInterface, typename CellType, typename TypeIdBase>
496 std::vector<api::model::Cell*> neighbors;
497 for(auto edge : this->node()->getOutgoingEdges(SpatialModelLayers::CELL_SUCCESSOR)) {
498 // Assumes that agents on the CELL_SUCCESSOR layer are necessarily
499 // api::model::Cell, so there is no runtime check on the actuel
500 // Agent type (prevents a dynamic_cast)
501 neighbors.push_back(static_cast<api::model::Cell*>(edge->getTargetNode()->data().get()));
502 }
503 return neighbors;
504 }
505
510 template<typename CellInterface, typename CellType, typename TypeIdBase>
512 api::model::Agent* agent,
513 api::model::AgentEdge* new_location_edge
514 ) {
515 FPMAS_LOGD(this->model()->graph().getMpiCommunicator().getRank(), "[CELL]",
516 "%s Setting this Cell as %s location.",
517 FPMAS_C_STR(this->node()->getId()),
518 FPMAS_C_STR(agent->node()->getId()));
519 if(new_location_edge->state() == api::graph::LOCAL) {
520 agent->model()->graph().switchLayer(
521 new_location_edge, SpatialModelLayers::LOCATION
522 );
523 } else {
524 this->model()->link(agent, this, SpatialModelLayers::LOCATION);
525 this->model()->unlink(new_location_edge);
526 }
527 }
528
529 template<typename CellInterface, typename CellType, typename TypeIdBase>
531 FPMAS_LOGD(this->model()->graph().getMpiCommunicator().getRank(), "[CELL]",
532 "%s Updating ranges...",
533 FPMAS_C_STR(this->node()->getId()));
534
535 for(auto agent_edge : this->node()->getIncomingEdges(SpatialModelLayers::NEW_LOCATION)) {
536 AgentPtr& agent = agent_edge->getSourceNode()->data();
537 updateLocation(agent, agent_edge);
538 growMobilityField(agent);
539 growPerceptionField(agent);
540
541 // If this node is to be linked in the MOVE or PERCEPTION
542 // field, this has already been done by
543 // LocatedAgent::moveToCell(), so this current location does
544 // not need to be explored for this agent.
545 move_flags.insert(agent->node()->getId());
546 perception_flags.insert(agent->node()->getId());
547 }
548 }
549
550 template<typename CellInterface, typename CellType, typename TypeIdBase>
552 for(auto agent_edge : this->node()->getIncomingEdges(SpatialModelLayers::MOVE)) {
553 auto agent = agent_edge->getSourceNode();
554 if(
555 // The agent updated its location since the last
556 // DistributedMoveAlgorithm execution
557 no_move_flags.count(agent->getId()) == 0 &&
558 // The current cell was not explored yet
559 move_flags.count(agent->getId()) == 0) {
560 growMobilityField(agent->data());
561 move_flags.insert(agent->getId());
562 }
563 }
564 }
565
566 template<typename CellInterface, typename CellType, typename TypeIdBase>
568 for(auto agent_edge : this->node()->getIncomingEdges(SpatialModelLayers::PERCEIVE)) {
569 auto agent = agent_edge->getSourceNode();
570 if(
571 // The agent updated its location since the last
572 // DistributedMoveAlgorithm execution
573 no_move_flags.count(agent->getId()) == 0 &&
574 // The current cell was not explored yet
575 perception_flags.count(agent->getId()) == 0) {
576 growPerceptionField(agent->data());
577 perception_flags.insert(agent->getId());
578 }
579 }
580 }
581
582 template<typename CellInterface, typename CellType, typename TypeIdBase>
584 FPMAS_LOGD(this->model()->graph().getMpiCommunicator().getRank(), "[CELL]",
585 "%s Updating perceptions...",
586 FPMAS_C_STR(this->node()->getId()));
587
588 move_flags.clear();
589 perception_flags.clear();
590 std::vector<api::model::AgentEdge*> perceived_agent_edges =
591 this->node()->getIncomingEdges(SpatialModelLayers::LOCATION);
592 for(auto agent_edge : this->node()->getIncomingEdges(SpatialModelLayers::PERCEIVE)) {
593 auto agent = agent_edge->getSourceNode();
594 for(auto perceived_agent_edge : perceived_agent_edges) {
595 auto perceived_agent = perceived_agent_edge->getSourceNode();
596 // Perceptions need to be updated only if either the perceivee
597 // or the perceiver location has been updated since the last
598 // DistributedMoveAlgorithm execution
599 if(
600 this->no_move_flags.count(agent->getId()) == 0 ||
601 this->no_move_flags.count(perceived_agent->getId()) == 0
602 )
603 if(perceived_agent->getId() != agent->getId())
604 this->model()->graph().link(
605 agent, perceived_agent,
606 SpatialModelLayers::PERCEPTION
607 );
608 }
609 }
610 no_move_flags.clear();
611 }
612
613 template<typename CellInterface, typename CellType, typename TypeIdBase>
615 // Exactly the same process as growMobilityField().
616 if(agent->node()->state() == api::graph::LOCAL) {
617 auto* spatial_agent
618 = static_cast<api::model::SpatialAgent<CellType>*>(agent);
619
620 auto location = spatial_agent->locationCell();
621 fpmas::model::ReadGuard read_location(location);
622
623 detail::CurrentOutLayer perceive_layer(agent, SpatialModelLayers::PERCEIVE);
624 for(auto cell : this->bufferedSuccessors()) {
625 if(!perceive_layer.contains(cell)) {
626 fpmas::model::ReadGuard read_cell(cell);
627 if(spatial_agent->perceptionRange().contains(
628 location,
629 cell
630 )) {
631 perceive_layer.link(cell);
632 }
633 }
634 }
635 } else {
636 for(auto cell : this->bufferedSuccessors())
637 this->model()->link(
638 agent,
639 cell,
640 SpatialModelLayers::NEW_PERCEIVE
641 );
642 }
643 }
644
656 template<typename CellType, typename TypeIdBase = CellType>
658
668 template<
669 template<typename> class SyncMode,
670 typename CellType = api::model::Cell,
671 typename EndCondition = DynamicEndCondition<CellType>>
673 public virtual api::model::SpatialModel<CellType>,
674 public Model<SyncMode> {
675 private:
676 AgentGroup& cell_group {this->buildGroup(CELL_GROUP_ID)};
677 EndCondition dist_move_algo_end_condition;
678
679 public:
681
685 void add(CellType* cell) override;
686 std::vector<CellType*> cells() override;
688 const fpmas::api::model::AgentGroup& cellGroup() const override;
691 const api::model::Behavior& behavior) override;
692 };
693
694 template<template<typename> class SyncMode, typename CellType, typename EndCondition>
696 cell_group.add(cell);
697 }
698
699 template<template<typename> class SyncMode, typename CellType, typename EndCondition>
701 std::vector<CellType*> cells;
702 for(auto agent : cell_group.localAgents())
703 cells.push_back(static_cast<CellType*>(agent));
704 return cells;
705 }
706
707 template<template<typename> class SyncMode, typename CellType, typename EndCondition>
709 return cell_group;
710 }
711
712 template<template<typename> class SyncMode, typename CellType, typename EndCondition>
714 return cell_group;
715 }
716
717 template<template<typename> class SyncMode, typename CellType, typename EndCondition>
719 api::model::GroupId id, const api::model::Behavior& behavior) {
720 auto* group = new MoveAgentGroup<CellType>(
721 id, behavior, *this, dist_move_algo_end_condition);
722 this->insert(id, group);
723 return *group;
724 }
725
750 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived = AgentType>
752 public detail::AgentBase<
753 SpatialAgentInterface, // Interface implemented by this base
754 AgentType, // Final agent type
755 SpatialAgentBase<SpatialAgentInterface, AgentType, CellType, Derived> // Serialization base
756 > {
757 friend nlohmann::adl_serializer<
761
762 public:
790
791 private:
792 mutable CellType* location_cell_buffer = nullptr;
793 DistributedId location_id;
794
795 protected:
809 void updateLocation(CellType* cell);
810
814 void handleNewMove() override;
818 void handleNewPerceive() override;
819
820 // Imports other moveTo overloads
821 using SpatialAgentInterface::moveTo;
825 void moveTo(DistributedId id) override;
826
834 return this->template outNeighbors<CellType>(SpatialModelLayers::MOVE);
835 }
836
846 template<typename NeighborType = api::model::Agent>
848 return this->template outNeighbors<NeighborType>(SpatialModelLayers::PERCEPTION);
849 }
850
851 public:
855 void initLocation(CellType* cell) override {
856 this->moveTo(cell);
857 }
858
862 DistributedId locationId() const override {
863 return location_id;
864 }
865
869 CellType* locationCell() const override;
870 };
871
872 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
874 // Links to new location
875 this->model()->link(this, cell, SpatialModelLayers::NEW_LOCATION);
876
877 // Unlinks obsolete location
878 auto location = this->node()->getOutgoingEdges(SpatialModelLayers::LOCATION);
879 if(location.size() > 0)
880 this->model()->unlink(location[0]);
881
882 // Unlinks obsolete mobility field
883 for(auto cell_edge :
884 this->node()->getOutgoingEdges(SpatialModelLayers::MOVE)) {
885 this->model()->unlink(cell_edge);
886 }
887
888 // Unlinks obsolete perception field
889 for(auto cell_edge
890 : this->node()->getOutgoingEdges(SpatialModelLayers::PERCEIVE))
891 this->model()->unlink(cell_edge);
892
893 // Unlinks obsolete perceptions
894 for(auto perception
895 : this->node()->getOutgoingEdges(fpmas::api::model::PERCEPTION))
896 this->model()->unlink(perception);
897
898
899 {
900 // The cell must be read before checking mobility ranges, to
901 // ensure cell data are available (e.g. cell->location())
902 fpmas::model::ReadGuard read(cell);
903
904 // Adds the NEW_LOCATION to the mobility/perceptions fields
905 // depending on the current ranges
906 if(this->mobilityRange().contains(cell, cell))
907 this->model()->link(this, cell, SpatialModelLayers::MOVE);
908 if(this->perceptionRange().contains(cell, cell))
909 this->model()->link(this, cell, SpatialModelLayers::PERCEIVE);
910 }
911
912 this->location_id = cell->node()->getId();
913 this->location_cell_buffer = cell;
914 }
915
916 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
918 if(location_cell_buffer != nullptr) {
919 return location_cell_buffer;
920 } else {
921 auto edges = this->node()->getOutgoingEdges(SpatialModelLayers::LOCATION);
922 if(!edges.empty())
923 location_cell_buffer = static_cast<CellType*>(
924 edges[0]->getTargetNode()->data().get()
925 );
926 else
927 location_cell_buffer = nullptr;
928 }
929
930 return location_cell_buffer;
931 }
932
933 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
935
936 detail::CurrentOutLayer move_layer(this, SpatialModelLayers::MOVE);
937
938 auto location = this->locationCell();
939 fpmas::model::ReadGuard read_location(location);
940 for(auto cell_edge : this->node()->getOutgoingEdges(SpatialModelLayers::NEW_MOVE)) {
941 auto* agent = cell_edge->getTargetNode()->data().get();
942 fpmas::model::ReadGuard read_cell(agent);
943 if(!move_layer.contains(agent)
944 && this->mobilityRange().contains(location, static_cast<CellType*>(agent)))
945 move_layer.link(agent);
946 this->model()->unlink(cell_edge);
947 }
948 }
949
950 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
952 detail::CurrentOutLayer perceive_layer(this, SpatialModelLayers::PERCEIVE);
953
954 auto location = this->locationCell();
955 fpmas::model::ReadGuard read_location(location);
956 for(auto cell_edge : this->node()->getOutgoingEdges(SpatialModelLayers::NEW_PERCEIVE)) {
957 auto* agent = cell_edge->getTargetNode()->data().get();
958 fpmas::model::ReadGuard read_cell(agent);
959 if(!perceive_layer.contains(agent)
960 && this->perceptionRange().contains(location, static_cast<CellType*>(agent)))
961 perceive_layer.link(agent);
962 this->model()->unlink(cell_edge);
963 }
964 }
965
966 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
968 bool found = false;
969 auto mobility_field = this->template outNeighbors<CellType>(SpatialModelLayers::MOVE);
970 auto it = mobility_field.begin();
971 while(!found && it != mobility_field.end()) {
972 if((*it)->node()->getId() == cell_id) {
973 found=true;
974 } else {
975 it++;
976 }
977 }
978 if(found)
979 this->moveTo(*it);
980 else
981 throw api::model::OutOfMobilityFieldException(this->node()->getId(), cell_id);
982 }
983
984
994 template<typename AgentType, typename CellType = api::model::Cell, typename Derived = AgentType>
996 public SpatialAgentBase<api::model::SpatialAgent<CellType>, AgentType, CellType, Derived> {
997 protected:
998 using SpatialAgentBase<api::model::SpatialAgent<CellType>, AgentType, CellType, Derived>::moveTo;
999 using SpatialAgentBase<api::model::SpatialAgent<CellType>, AgentType, CellType, Derived>::SpatialAgentBase;
1000
1004 void moveTo(CellType* cell) override {
1005 this->updateLocation(cell);
1006 }
1007 };
1008
1014 template<typename CellType>
1015 struct VoidRange : public api::model::Range<CellType> {
1019 bool contains(CellType*, CellType*) const override {
1020 return false;
1021 }
1022
1026 std::size_t radius(CellType*) const override {
1027 return 0;
1028 }
1029 };
1030
1037 template<typename CellType>
1038 struct LocationRange : public api::model::Range<CellType> {
1042 bool contains(CellType* location, CellType* cell) const override {
1043 return location->node()->getId() == cell->node()->getId();
1044 }
1045
1049 std::size_t radius(CellType*) const override {
1050 return 0;
1051 }
1052 };
1053
1058 template<typename AgentType>
1059 class DefaultSpatialAgentFactory : public api::model::SpatialAgentFactory<typename AgentType::Cell> {
1060 public:
1067 AgentType* build() override {
1068 return new AgentType;
1069 }
1070 };
1071
1086 template<typename CellType, typename MappingCellType>
1087 class SpatialAgentBuilderBase : public api::model::SpatialAgentBuilder<CellType, MappingCellType> {
1088 public:
1094
1095 protected:
1101 api::model::GroupList groups,
1104 );
1105
1106
1113 api::model::GroupList groups,
1114 std::function<api::model::SpatialAgent<CellType>*()> factory,
1116 );
1117 };
1118
1119 template<typename CellType, typename MappingCellType>
1122 api::model::GroupList groups,
1125 ) {
1126 build_agents(model, groups, [&factory] () {return factory.build();}, agent_mapping);
1127 }
1128
1129 template<typename CellType, typename MappingCellType>
1132 api::model::GroupList groups,
1133 std::function<api::model::SpatialAgent<CellType>*()> factory,
1135 ) {
1138 = model.buildMoveGroup(TEMP_GROUP_ID, _);
1139 std::vector<api::model::SpatialAgent<CellType>*> agents;
1140 for(auto cell : model.cells()) {
1141 for(std::size_t i = 0; i < agent_mapping.countAt(cell); i++) {
1142 auto agent = factory();
1143 agents.push_back(agent);
1144 temp_group.add(agent);
1145 for(api::model::AgentGroup& group : groups)
1146 group.add(agent);
1147 agent->initLocation(cell);
1148 }
1149 }
1150
1151 model.runtime().execute(
1152 temp_group.distributedMoveAlgorithm().jobs()
1153 );
1154 model.removeGroup(temp_group);
1155 }
1156
1164 template<typename CellType, typename MappingCellType = api::model::Cell>
1165 class SpatialAgentBuilder : public SpatialAgentBuilderBase<CellType, MappingCellType> {
1166 public:
1170 void build(
1172 api::model::GroupList groups,
1175 ) override {
1176 this->build_agents(model, groups, factory, agent_mapping);
1177 }
1178
1182 void build(
1184 api::model::GroupList groups,
1185 std::function<api::model::SpatialAgent<CellType>*()> factory,
1187 ) override {
1188 this->build_agents(model, groups, factory, agent_mapping);
1189 }
1190 };
1191}}
1192
1193namespace nlohmann {
1197 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
1198 struct adl_serializer<fpmas::api::utils::PtrWrapper<fpmas::model::SpatialAgentBase<SpatialAgentInterface, AgentType, CellType, Derived>>> {
1218 static void to_json(nlohmann::json& j, const Ptr& ptr) {
1219 // Derived serialization
1221 const_cast<Derived*>(static_cast<const Derived*>(ptr.get())));
1222 j[1] = ptr->location_id;
1223 }
1224
1243 static Ptr from_json(const nlohmann::json& j) {
1244 // Derived unserialization.
1245 // The current base is implicitly default initialized
1248
1249 derived_ptr->location_id = j[1].get<fpmas::api::graph::DistributedId>();
1250 return derived_ptr.get();
1251 }
1252 };
1253}
1254
1255namespace fpmas { namespace io { namespace json {
1267 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
1268 struct light_serializer<PtrWrapper<fpmas::model::SpatialAgentBase<SpatialAgentInterface, AgentType, CellType, Derived>>> {
1273
1286 static void to_json(light_json& j, const Ptr& agent) {
1287 // Derived serialization
1289 j,
1290 const_cast<Derived*>(static_cast<const Derived*>(agent.get()))
1291 );
1292 }
1293
1306 static Ptr from_json(const light_json& j) {
1307 // Derived unserialization.
1308 // The current base is implicitly default initialized
1309 PtrWrapper<Derived> derived_ptr
1311 return derived_ptr.get();
1312 }
1313 };
1314
1315}}}
1316
1317namespace fpmas { namespace io { namespace datapack {
1336 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
1337 struct Serializer<PtrWrapper<fpmas::model::SpatialAgentBase<SpatialAgentInterface, AgentType, CellType, Derived>>> {
1342
1347 static std::size_t size(const ObjectPack& p, const Ptr& ptr) {
1349 const_cast<Derived*>(static_cast<const Derived*>(ptr.get())));
1350 return p.size(derived) + p.size<DistributedId>();
1351 }
1352
1360 static void to_datapack(ObjectPack& pack, const Ptr& ptr) {
1361 // Derived serialization
1363 const_cast<Derived*>(static_cast<const Derived*>(ptr.get())));
1364 pack.put(derived);
1365 pack.put(ptr->locationId());
1366 }
1367
1385 static Ptr from_datapack(const ObjectPack& pack) {
1386 // Derived unserialization.
1387 // The current base is implicitly default initialized
1388 PtrWrapper<Derived> derived_ptr = pack
1390
1391 derived_ptr->location_id = pack.get<fpmas::api::graph::DistributedId>();
1392 return derived_ptr.get();
1393 }
1394 };
1395
1416 template<typename SpatialAgentInterface, typename AgentType, typename CellType, typename Derived>
1417 struct LightSerializer<PtrWrapper<fpmas::model::SpatialAgentBase<SpatialAgentInterface, AgentType, CellType, Derived>>> {
1422
1427 static std::size_t size(const LightObjectPack& p, const Ptr& ptr) {
1428 return p.size(PtrWrapper<Derived>(
1429 const_cast<Derived*>(
1430 static_cast<const Derived*>(ptr.get())
1431 )
1432 ));
1433 }
1434
1447 static void to_datapack(LightObjectPack& o, const Ptr& agent) {
1448 // Derived serialization
1450 o,
1451 const_cast<Derived*>(static_cast<const Derived*>(agent.get()))
1452 );
1453 }
1454
1468 // Derived unserialization.
1469 // The current base is implicitly default initialized
1470 PtrWrapper<Derived> derived_ptr
1472 return derived_ptr.get();
1473 }
1474 };
1475}}}
1476#endif
Definition: distributed_edge.h:91
virtual LocationState state() const =0
virtual void switchLayer(DistributedEdge< T > *edge, LayerId layer_id)=0
Definition: distributed_id.h:89
virtual LocationState state() const =0
virtual IdType getId() const =0
virtual const std::vector< EdgeType * > getOutgoingEdges() const =0
Definition: model.h:547
virtual void add(Agent *agent)=0
Definition: model.h:92
Definition: model.h:174
virtual Model * model()=0
virtual AgentNode * node()=0
Definition: model.h:520
Definition: spatial_model.h:90
Definition: spatial_model.h:425
Definition: spatial_model.h:376
virtual void removeGroup(AgentGroup &group)=0
virtual api::runtime::Runtime & runtime()=0
virtual AgentEdge * link(Agent *src_agent, Agent *tgt_agent, api::graph::LayerId layer)=0
virtual AgentGroup & buildGroup(GroupId id)=0
Definition: spatial_model.h:455
virtual DistributedMoveAlgorithm< CellType > & distributedMoveAlgorithm()=0
Definition: spatial_model.h:121
Definition: spatial_model.h:685
Definition: spatial_model.h:607
virtual SpatialAgent< CellType > * build()=0
Definition: spatial_model.h:656
virtual std::size_t countAt(CellType *cell)=0
Definition: spatial_model.h:234
virtual CellType * locationCell() const =0
api::model::Cell CellType
Definition: spatial_model.h:484
virtual MoveAgentGroup< CellType > & buildMoveGroup(GroupId id, const Behavior &behavior)=0
virtual std::vector< CellType * > cells()=0
virtual void execute(const scheduler::Job &job)=0
Definition: ptr_wrapper.h:21
T * get()
Definition: ptr_wrapper.h:58
Definition: datapack.h:301
std::size_t size() const
Definition: datapack.h:367
void put(const T &item)
Definition: datapack.h:447
T get() const
Definition: datapack.h:459
Definition: spatial_model.h:215
void init() override
Definition: spatial_model.h:386
CellBase & operator=(const CellBase &)=default
std::set< DistributedId > move_flags
Definition: spatial_model.h:257
void handleNewLocation() override
Definition: spatial_model.h:530
void updatePerceptions(api::model::AgentGroup &group) override
Definition: spatial_model.h:583
CellBase(CellBase &&)=default
void handleMove() override
Definition: spatial_model.h:551
CellBase< CellInterface, CellType, TypeIdBase > & operator=(CellBase< CellInterface, CellType, TypeIdBase > &&)
Definition: spatial_model.h:331
CellBase(const CellBase &)=default
std::vector< api::model::Cell * > successors() override
Definition: spatial_model.h:495
std::set< DistributedId > perception_flags
Definition: spatial_model.h:265
void handlePerceive() override
Definition: spatial_model.h:567
std::set< DistributedId > no_move_flags
Definition: spatial_model.h:249
Definition: model.h:30
Definition: spatial_model.h:1059
AgentType * build() override
Definition: spatial_model.h:1067
Definition: dist_move_algo.h:145
Definition: dist_move_algo.h:99
Definition: spatial_model.h:73
MoveAgentGroup(api::model::GroupId group_id, const api::model::Behavior &behavior, api::model::SpatialModel< CellType > &model, api::model::EndCondition< CellType > &end_condition)
Definition: spatial_model.h:92
api::model::DistributedMoveAlgorithm< CellType > & distributedMoveAlgorithm() override
Definition: spatial_model.h:121
api::scheduler::JobList jobs() const override
Definition: spatial_model.h:127
Definition: model.h:226
Definition: guards.h:19
Definition: spatial_model.h:756
Neighbors< CellType > mobilityField() const
Definition: spatial_model.h:833
CellType * locationCell() const override
Definition: spatial_model.h:917
void handleNewMove() override
Definition: spatial_model.h:934
void handleNewPerceive() override
Definition: spatial_model.h:951
DistributedId locationId() const override
Definition: spatial_model.h:862
void moveTo(DistributedId id) override
Definition: spatial_model.h:967
void initLocation(CellType *cell) override
Definition: spatial_model.h:855
SpatialAgentBase< SpatialAgentInterface, AgentType, CellType, Derived > JsonBase
Definition: spatial_model.h:789
Neighbors< NeighborType > perceptions() const
Definition: spatial_model.h:847
void updateLocation(CellType *cell)
Definition: spatial_model.h:873
Definition: spatial_model.h:1087
void build_agents(api::model::SpatialModel< CellType > &model, api::model::GroupList groups, api::model::SpatialAgentFactory< CellType > &factory, api::model::SpatialAgentMapping< MappingCellType > &agent_mapping)
Definition: spatial_model.h:1120
static const api::model::GroupId TEMP_GROUP_ID
Definition: spatial_model.h:1093
void build_agents(api::model::SpatialModel< CellType > &model, api::model::GroupList groups, std::function< api::model::SpatialAgent< CellType > *()> factory, api::model::SpatialAgentMapping< MappingCellType > &agent_mapping)
Definition: spatial_model.h:1130
Definition: spatial_model.h:1165
void build(api::model::SpatialModel< CellType > &model, api::model::GroupList groups, std::function< api::model::SpatialAgent< CellType > *()> factory, api::model::SpatialAgentMapping< MappingCellType > &agent_mapping) override
Definition: spatial_model.h:1182
void build(api::model::SpatialModel< CellType > &model, api::model::GroupList groups, api::model::SpatialAgentFactory< CellType > &factory, api::model::SpatialAgentMapping< MappingCellType > &agent_mapping) override
Definition: spatial_model.h:1170
Definition: spatial_model.h:996
void moveTo(CellType *cell) override
Definition: spatial_model.h:1004
Definition: spatial_model.h:674
fpmas::api::model::AgentGroup & cellGroup() override
Definition: spatial_model.h:708
void add(CellType *cell) override
Definition: spatial_model.h:695
MoveAgentGroup< CellType > & buildMoveGroup(api::model::GroupId id, const api::model::Behavior &behavior) override
Definition: spatial_model.h:718
std::vector< CellType * > cells() override
Definition: spatial_model.h:700
Definition: model.h:722
api::model::AgentGroup * group() override
Definition: model.h:851
AgentGroupBase(GroupId group_id, api::model::AgentGraph &agent_graph)
Definition: model.cpp:142
const api::model::Behavior & behavior() override
Definition: model.h:400
Definition: spatial_model.h:141
CurrentOutLayer(api::model::Agent *agent, fpmas::graph::LayerId layer_id)
Definition: spatial_model.h:155
bool contains(fpmas::api::model::Agent *agent)
Definition: spatial_model.h:172
void link(fpmas::api::model::Agent *other_agent)
Definition: spatial_model.h:189
Definition: model.h:638
api::model::AgentGraph & graph() override
Definition: model.h:487
#define FPMAS_C_STR(arg)
Definition: macros.h:24
@ LOCAL
Definition: location_state.h:21
int LayerId
Definition: edge.h:13
int GroupId
Definition: model.h:78
SpatialModelLayers
Definition: spatial_model.h:17
std::vector< std::reference_wrapper< AgentGroup > > GroupList
Definition: model.h:833
std::vector< std::reference_wrapper< const Job > > JobList
Definition: scheduler.h:215
nlohmann::basic_json< std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, std::allocator, light_serializer > light_json
Definition: json.h:14
CellBase< api::model::Cell, CellType, TypeIdBase > Cell
Definition: spatial_model.h:657
Definition: fpmas.cpp:3
static std::size_t size(const LightObjectPack &p, const Ptr &ptr)
Definition: spatial_model.h:1427
PtrWrapper< fpmas::model::SpatialAgentBase< SpatialAgentInterface, AgentType, CellType, Derived > > Ptr
Definition: spatial_model.h:1421
Definition: datapack.h:1411
static void to_datapack(LightObjectPack &pack, const T &item)
Definition: datapack.h:1438
static T from_datapack(const LightObjectPack &pack)
Definition: datapack.h:1451
PtrWrapper< fpmas::model::SpatialAgentBase< SpatialAgentInterface, AgentType, CellType, Derived > > Ptr
Definition: spatial_model.h:1341
Definition: datapack.h:55
PtrWrapper< fpmas::model::SpatialAgentBase< SpatialAgentInterface, AgentType, CellType, Derived > > Ptr
Definition: spatial_model.h:1272
static void from_json(const light_json &j, T &data)
Definition: json.h:123
static void to_json(light_json &j, const T &data)
Definition: json.h:107
Definition: spatial_model.h:1038
std::size_t radius(CellType *) const override
Definition: spatial_model.h:1049
bool contains(CellType *location, CellType *cell) const override
Definition: spatial_model.h:1042
Definition: spatial_model.h:1015
bool contains(CellType *, CellType *) const override
Definition: spatial_model.h:1019
std::size_t radius(CellType *) const override
Definition: spatial_model.h:1026
fpmas::api::utils::PtrWrapper< fpmas::model::SpatialAgentBase< SpatialAgentInterface, AgentType, CellType, Derived > > Ptr
Definition: spatial_model.h:1202