2 #ifndef SYDEVS_SYSTEMS_COLLECTION_NODE_H_
3 #define SYDEVS_SYSTEMS_COLLECTION_NODE_H_
54 template<
typename AgentID,
typename Node>
126 template<
typename AgentNode>
192 timer& prototype_ET()
const;
196 template<data_mode dmode, data_goal dgoal,
typename T>
199 Node& handle_agent_planned_event(
int64 agent_index);
200 void erase_removed_agents();
203 std::string agent_name_from_id(
qualified_type<T> agent_id_type,
const AgentID& agent_id);
207 void adopt_component_print_flags(
const system_node& node)
const;
209 virtual duration macro_initialization_event() = 0;
211 virtual duration micro_planned_event(
const AgentID& agent_id,
duration elapsed_dt) = 0;
213 virtual void macro_finalization_event(
duration elapsed_dt) = 0;
216 std::map<AgentID, int64> agent_indices_;
217 std::map<int64, AgentID> agent_ids_;
218 std::map<int64, std::unique_ptr<Node>> agents_;
219 std::set<int64> removed_indices_;
229 template<
typename AgentID,
typename Node>
247 const int64 port_index_;
253 template<
typename AgentID,
typename Node>
271 const int64 port_index_;
277 template<
typename AgentID,
typename Node>
283 const AgentID* operator->()
const;
294 const_iterator(
const typename std::map<AgentID, int64>::const_iterator& iter);
296 typename std::map<AgentID, int64>::const_iterator iter_;
302 template<
typename AgentID,
typename Node>
305 , prototype(
"prototype", prototype_context())
306 , internal_context_(&const_cast<
node_interface&>(external_interface()),
314 , initialized_(false)
321 template<
typename AgentID,
typename Node>
324 external_IO().print_on_elapsed_duration(flag);
328 template<
typename AgentID,
typename Node>
331 external_IO().print_on_planned_duration(flag);
335 template<
typename AgentID,
typename Node>
338 if (initialized_)
throw std::logic_error(
"Attempt to initialize collection node (" + full_name() +
") more than once");
339 auto& current_t = event_time().t();
342 external_IO().print_event(
"macro-initialization");
344 auto dt = macro_initialization_event();
346 prototype_IO().clear_flow_inputs();
347 prototype_IO().clear_message_input();
348 prototype_IO().clear_flow_outputs();
349 auto macro_planned_dt = scale_planned_dt(dt);
350 if (macro_planned_dt.finite()) {
351 t_queue_.plan_event(macro_event_id, macro_planned_dt);
354 t_cache_.retain_event(macro_event_id, time_precision());
356 auto planned_dt = t_queue_.imminent_duration();
357 external_IO().print_planned_duration(planned_dt);
359 erase_removed_agents();
364 template<
typename AgentID,
typename Node>
367 auto& current_t = event_time().t();
368 t_queue_.advance_time(current_t);
369 t_cache_.advance_time(current_t);
370 external_IO().print_event(
"macro-unplanned");
371 external_IO().print_elapsed_duration(elapsed_dt);
373 auto dt = macro_unplanned_event(elapsed_dt);
375 prototype_IO().clear_flow_inputs();
376 prototype_IO().clear_message_input();
377 prototype_IO().clear_flow_outputs();
378 auto macro_planned_dt = scale_planned_dt(dt);
379 if (macro_planned_dt.finite()) {
380 t_queue_.plan_event(macro_event_id, macro_planned_dt);
383 t_queue_.cancel_event(macro_event_id);
386 t_cache_.retain_event(macro_event_id, time_precision());
388 auto planned_dt = t_queue_.imminent_duration();
389 external_IO().print_planned_duration(planned_dt);
390 erase_removed_agents();
395 template<
typename AgentID,
typename Node>
398 auto& current_t = event_time().t();
399 t_queue_.advance_time(current_t);
400 t_cache_.advance_time(current_t);
401 if (t_queue_.imminent_duration() != 0
_s)
throw std::logic_error(
"Unexpected error while advancing time to that of next planned event");
402 int64 agent_index = *std::begin(t_queue_.imminent_event_ids());
403 if (agent_index < macro_event_id) {
406 auto& agent = handle_agent_planned_event(agent_index);
407 int64 list_size = agent_IO(agent).message_output_list_size();
408 const auto& agent_id = agent_ids_[agent_index];
409 auto micro_elapsed_dt = elapsed_dt;
410 for (
int64 list_index = 0; list_index < list_size; ++list_index) {
411 event_time().advance();
412 int64 port_index = agent_IO(agent).message_output_index(list_index);
413 const auto& val = agent_IO(agent).message_output_value(list_index);
414 external_IO().print_event(
"micro-planned");
415 external_IO().print_elapsed_duration(micro_elapsed_dt);
416 prototype_IO().append_message_output(port_index, val);
418 auto dt = micro_planned_event(agent_id, micro_elapsed_dt);
420 prototype_IO().clear_flow_inputs();
421 prototype_IO().clear_message_input();
422 prototype_IO().clear_message_outputs();
423 prototype_IO().clear_flow_outputs();
424 auto macro_planned_dt = scale_planned_dt(dt);
425 external_IO().print_planned_duration(macro_planned_dt);
426 micro_elapsed_dt -= micro_elapsed_dt;
427 if (macro_planned_dt.finite()) {
428 t_queue_.plan_event(macro_event_id, macro_planned_dt);
431 t_queue_.cancel_event(macro_event_id);
434 t_cache_.retain_event(macro_event_id, time_precision());
437 agent_IO(agent).clear_message_outputs();
442 external_IO().print_event(
"macro-planned");
443 external_IO().print_elapsed_duration(elapsed_dt);
445 auto dt = macro_planned_event(elapsed_dt);
447 prototype_IO().clear_flow_inputs();
448 prototype_IO().clear_message_input();
449 prototype_IO().clear_flow_outputs();
450 auto macro_planned_dt = scale_planned_dt(dt);
451 external_IO().print_planned_duration(macro_planned_dt);
452 if (macro_planned_dt.finite()) {
453 t_queue_.plan_event(macro_event_id, macro_planned_dt);
456 t_queue_.pop_imminent_event(macro_event_id);
459 t_cache_.retain_event(macro_event_id, time_precision());
462 auto planned_dt = t_queue_.imminent_duration();
463 erase_removed_agents();
468 template<
typename AgentID,
typename Node>
471 if (finalized_)
throw std::logic_error(
"Attempt to finalize collection node (" + full_name() +
") more than once");
472 auto& current_t = event_time().t();
473 t_queue_.advance_time(current_t);
474 t_cache_.advance_time(current_t);
475 external_IO().print_event(
"macro-finalization");
476 external_IO().print_elapsed_duration(elapsed_dt);
478 macro_finalization_event(elapsed_dt);
479 while (agent_count() > 0) {
480 auto agent_id = *agent_begin();
481 remove_agent(agent_id);
484 erase_removed_agents();
489 template<
typename AgentID,
typename Node>
493 validate_prototype_port(prototype_port);
494 return prototype_port.
port_index() == prototype_IO().message_output_index(0);
498 template<
typename AgentID,
typename Node>
506 validate_prototype_port(prototype_port);
511 template<
typename AgentID,
typename Node>
519 validate_prototype_port(prototype_port);
520 if (prototype_IO().message_input_port_index() != -1) {
521 throw std::logic_error(
"Attempt to access message input port (" + prototype_port.
port_name() +
"), " +
522 "but another message input port of prototype agent (" + prototype.full_name() +
") " +
523 "has already been accessed");
532 template<
typename AgentID,
typename Node>
536 validate_prototype_port(prototype_port);
537 if (prototype_port.
port_index() != prototype_IO().message_output_index(0)) {
538 throw std::logic_error(
"Attempt to access message output port (" + prototype_port.
port_name() +
"), " +
539 "which is not the port of prototype agent (" + prototype.full_name() +
") " +
540 "on which the current message is being transmitted");
542 auto& val = prototype_IO().message_output_value(0);
543 return const_cast<const T&
>(val.template dereference<T>());
547 template<
typename AgentID,
typename Node>
551 validate_prototype_port(prototype_port);
552 auto& val = prototype_IO().flow_output_port_value(prototype_port.
port_index());
553 return const_cast<const T&
>(val.template dereference<T>());
557 template<
typename AgentID,
typename Node>
560 create_agent<Node>(agent_id);
564 template<
typename AgentID,
typename Node>
565 template<
typename AgentNode>
568 static_assert(std::is_base_of<Node, AgentNode>::value,
"AgentNode must inherit from Node");
569 if (prototype.node_dmode() ==
flow) {
570 throw std::logic_error(
"Attempt to use \"create_agent\" to create a flow node agent of a collection node (" + full_name() +
"); use \"invoke_agent\" instead");
572 event_time().advance();
574 std::unique_ptr<Node> agent_ptr(
new AgentNode(agent_name, internal_context_));
575 auto& agent = *agent_ptr;
576 agent.adopt_print_flags(prototype);
577 if (agent_exists(agent_id)) {
578 throw std::logic_error(
"Created agent (" + agent.full_name() +
") already exists.");
580 int64 agent_index = agent.node_index();
581 agent_indices_[agent_id] = agent_index;
582 agent_ids_[agent_index] = agent_id;
583 agents_[agent_index] = std::move(agent_ptr);
584 agent_IO(agent).print_event(
"initialization");
585 int64 missing_input = prototype_IO().missing_flow_input();
586 if (missing_input != -1) {
587 throw std::logic_error(
"Flow input port (" + agent_IO(agent).flow_input_port_name(missing_input) +
") " +
588 "of created agent (" + agent.full_name() +
") has no value");
590 auto input_port_count = prototype_IO().flow_input_port_count();
591 for (
int64 port_index = 0; port_index < input_port_count; ++port_index) {
592 const auto& flow_input_val = prototype_IO().flow_input_port_value(port_index);
593 agent_IO(agent).assign_flow_input(port_index, flow_input_val);
594 agent_IO(agent).print_flow_input(port_index);
599 planned_dt = agent.process_initialization_event();
601 catch (
const std::exception& e) {
602 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
605 agent_IO(agent).deactivate();
606 if (planned_dt.finite()) {
607 t_queue_.plan_event(agent_index, planned_dt);
609 if (agent.time_precision() !=
no_scale) {
610 t_cache_.retain_event(agent_index, agent.time_precision());
615 template<
typename AgentID,
typename Node>
618 if (prototype.node_dmode() ==
flow) {
619 throw std::logic_error(
"Attempt to use \"affect_agent\" to affect a flow node agent of a collection node (" + full_name() +
"); use \"invoke_agent\" instead");
621 event_time().advance();
622 auto agent_iter = agent_indices_.find(agent_id);
623 if (agent_iter == std::end(agent_indices_)) {
624 throw std::logic_error(
"Attempt to affect agent (" + full_name() +
"." +
tostring(agent_id) +
") that does not exist");
626 int64 agent_index = agent_iter->second;
627 auto& agent = *
dynamic_cast<Node*
>(&internal_structure().node(agent_index));
628 int64 port_index = prototype_IO().message_input_port_index();
629 if (port_index == -1) {
630 throw std::logic_error(
"Attempt to affect agent (" + agent.full_name() +
"), " +
631 "but none of the prototype's message input ports have been accessed");
633 auto val = prototype_IO().message_input_port_value(port_index);
635 throw std::logic_error(
"Attempt to affect agent (" + agent.full_name() +
"), " +
636 "but none of the prototype's message input ports have been assigned a value");
638 agent_IO(agent).print_event(
"unplanned");
639 agent_IO(agent).set_message_input(port_index, val);
640 agent_IO(agent).print_message_input(port_index);
642 if (agent.time_precision() !=
no_scale) {
643 elapsed_dt = t_cache_.duration_since(agent_index).fixed_at(agent.time_precision());
648 planned_dt = agent.process_unplanned_event(elapsed_dt);
650 catch (
const std::exception& e) {
651 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
654 agent_IO(agent).deactivate();
655 if (planned_dt.finite()) {
656 t_queue_.plan_event(agent_index, planned_dt);
659 t_queue_.cancel_event(agent_index);
661 if (agent.time_precision() !=
no_scale) {
662 t_cache_.retain_event(agent_index, agent.time_precision());
664 agent_IO(agent).clear_message_input();
665 prototype_IO().clear_message_input();
669 template<
typename AgentID,
typename Node>
672 if (prototype.node_dmode() ==
flow) {
673 throw std::logic_error(
"Attempt to use \"remove_agent\" to remove a flow node agent of a collection node (" + full_name() +
"); use \"invoke_agent\" instead");
675 event_time().advance();
676 auto agent_iter = agent_indices_.find(agent_id);
677 if (agent_iter == std::end(agent_indices_)) {
678 throw std::logic_error(
"Attempt to remove agent (" + full_name() +
"." +
tostring(agent_id) +
") that does not exist");
680 int64 agent_index = agent_iter->second;
681 auto& agent = *
dynamic_cast<Node*
>(&internal_structure().node(agent_index));
682 agent_IO(agent).print_event(
"finalization");
684 if (agent.time_precision() !=
no_scale) {
685 elapsed_dt = t_cache_.duration_since(agent_index).fixed_at(agent.time_precision());
689 agent.process_finalization_event(elapsed_dt);
691 catch (
const std::exception& e) {
692 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
695 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
696 agent_IO(agent).deactivate();
697 int64 missing_output = agent_IO(agent).missing_flow_output();
698 if (missing_output != -1) {
699 throw std::logic_error(
"Flow output port (" + agent_IO(agent).flow_output_port_name(missing_output) +
") " +
700 "of removed agent (" + agent.full_name() +
") not assigned");
702 int64 output_port_count = agent_IO(agent).flow_output_port_count();
703 for (
int64 port_index = 0; port_index < output_port_count; ++port_index) {
704 const auto& flow_output_val = agent_IO(agent).flow_output_port_value(port_index);
705 agent_IO(agent).print_flow_output(port_index);
706 prototype_IO().assign_flow_output(port_index, flow_output_val);
708 agent_indices_.erase(agent_iter);
709 removed_indices_.insert(agent_index);
710 t_queue_.cancel_event(agent_index);
711 t_cache_.release_event(agent_index);
715 template<
typename AgentID,
typename Node>
718 if (prototype.node_dmode() ==
message) {
719 throw std::logic_error(std::string(
"Attempt to use \"invoke_agent\" to invoke a message node agent of a collection node (" + full_name() +
"); ") +
720 "use \"create_agent\", \"affect_agent\", and \"remove_agent\" instead");
722 event_time().advance();
724 auto agent_ptr = std::make_unique<Node>(agent_name, internal_context_);
725 auto& agent = *agent_ptr;
726 int64 agent_index = agent.node_index();
727 agent.adopt_print_flags(prototype);
728 agent_IO(agent).print_event(
"flow");
729 int64 missing_input = prototype_IO().missing_flow_input();
730 if (missing_input != -1) {
731 throw std::logic_error(
"Flow input port (" + agent_IO(agent).flow_input_port_name(missing_input) +
") " +
732 "of invoked agent (" + agent.full_name() +
") has no value");
734 auto input_port_count = prototype_IO().flow_input_port_count();
735 for (
int64 port_index = 0; port_index < input_port_count; ++port_index) {
736 const auto& flow_input_val = prototype_IO().flow_input_port_value(port_index);
737 if (!flow_input_val)
throw std::logic_error(
"Flow input ports of created agent (" + agent.full_name() +
") not assigned");
738 agent_IO(agent).assign_flow_input(port_index, flow_input_val);
739 agent_IO(agent).print_flow_input(port_index);
743 agent.process_initialization_event();
745 catch (
const std::exception& e) {
746 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
749 agent_IO(agent).deactivate();
750 int64 missing_output = agent_IO(agent).missing_flow_output();
751 if (missing_output != -1) {
752 throw std::logic_error(
"Flow output port (" + agent_IO(agent).flow_output_port_name(missing_output) +
") " +
753 "of invoked agent (" + agent.full_name() +
") not assigned");
755 int64 output_port_count = agent_IO(agent).flow_output_port_count();
756 for (
int64 port_index = 0; port_index < output_port_count; ++port_index) {
757 agent_IO(agent).print_flow_output(port_index);
758 const auto& flow_output_val = agent_IO(agent).flow_output_port_value(port_index);
759 prototype_IO().assign_flow_output(port_index, flow_output_val);
761 internal_structure().erase_node(agent_index);
765 template<
typename AgentID,
typename Node>
768 return agent_indices_.find(agent_id) != std::end(agent_indices_);
772 template<
typename AgentID,
typename Node>
775 return int64(agent_indices_.size());
779 template<
typename AgentID,
typename Node>
786 template<
typename AgentID,
typename Node>
793 template<
typename AgentID,
typename Node>
796 return internal_context_.internal_structure();
800 template<
typename AgentID,
typename Node>
801 inline node_interface& collection_node<AgentID, Node>::prototype_IO()
const
803 return const_cast<node_interface&
>(
const_cast<Node&
>(prototype).external_interface());
807 template<
typename AgentID,
typename Node>
808 inline timer& collection_node<AgentID, Node>::prototype_ET()
const
810 return const_cast<timer&
>(prototype.event_timer());
814 template<
typename AgentID,
typename Node>
815 inline node_interface& collection_node<AgentID, Node>::agent_IO(
const system_node& agent)
const
817 return const_cast<node_interface&
>(
const_cast<system_node&
>(agent).external_interface());
821 template<
typename AgentID,
typename Node>
822 inline discrete_event_time& collection_node<AgentID, Node>::event_time()
824 return external_IO().external_context().event_time();
828 template<
typename AgentID,
typename Node>
829 template<data_mode dmode, data_goal dgoal,
typename T>
830 inline void collection_node<AgentID, Node>::validate_prototype_port(
const port<dmode, dgoal, T>& prototype_port)
832 if (&prototype_port.external_interface() != &prototype_IO()) {
834 "port (" + prototype_port.port_name() +
"), " +
835 "which is not a port of the prototype agent (" + prototype.full_name() +
")");
837 if (!external_interface().active()) {
839 "port (" + prototype_port.port_name() +
"), " +
840 "which is a prototype port of inactive node (" + full_name() +
")");
845 template<
typename AgentID,
typename Node>
846 inline Node& collection_node<AgentID, Node>::handle_agent_planned_event(
int64 agent_index)
848 event_time().advance();
849 auto& agent = *
dynamic_cast<Node*
>(&internal_structure().node(agent_index));
850 agent_IO(agent).print_event(
"planned");
852 if (agent.time_precision() !=
no_scale) {
853 elapsed_dt = t_cache_.duration_since(agent_index).fixed_at(agent.time_precision());
859 planned_dt = agent.process_planned_event(elapsed_dt);
862 catch (
const std::exception& e) {
866 prototype_ET() = timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
869 agent_IO(agent).deactivate();
870 if (planned_dt.finite()) {
871 t_queue_.plan_event(agent_index, planned_dt);
874 t_queue_.pop_imminent_event(agent_index);
876 if (agent.time_precision() !=
no_scale) {
877 t_cache_.retain_event(agent_index, agent.time_precision());
879 int64 list_size = agent_IO(agent).message_output_list_size();
880 for (
int64 list_index = 0; list_index < list_size; ++list_index) {
881 int64 port_index = agent_IO(agent).message_output_index(list_index);
882 agent_IO(agent).print_message_output(list_index, port_index);
888 template<
typename AgentID,
typename Node>
889 inline void collection_node<AgentID, Node>::erase_removed_agents()
891 for (
int64 agent_index : removed_indices_) {
892 internal_structure().erase_node(agent_index);
893 agent_ids_.erase(agent_index);
894 agents_.erase(agent_index);
896 removed_indices_.clear();
900 template<
typename AgentID,
typename Node>
902 inline std::string collection_node<AgentID, Node>::agent_name_from_id(qualified_type<T> agent_id_type,
const AgentID& agent_id)
908 template<
typename AgentID,
typename Node>
909 inline std::string collection_node<AgentID, Node>::agent_name_from_id(qualified_type<std::string> agent_id_type,
const AgentID& agent_id)
915 template<
typename AgentID,
typename Node>
916 inline void collection_node<AgentID, Node>::adopt_component_print_flags(
const system_node& node)
const
918 const auto node_ptr =
dynamic_cast<const collection_node*
>(&node);
920 throw std::logic_error(
"Attempt to transfer print flags from node (" + node.full_name() +
")" +
921 "to node (" + full_name() +
"), but the nodes are of different types");
923 auto& other_node =
const_cast<collection_node&
>(*node_ptr);
924 prototype.adopt_print_flags(other_node.prototype);
930 template<
typename AgentID,
typename Node>
943 template<
typename AgentID,
typename Node>
952 external_interface_.assign_flow_input(port_index_, val);
957 template<
typename AgentID,
typename Node>
960 : external_interface_(const_cast<
node_interface&>(input_port.external_interface()))
961 , port_index_(input_port.port_index())
968 template<
typename AgentID,
typename Node>
981 template<
typename AgentID,
typename Node>
990 external_interface_.set_message_input(port_index_, val);
995 template<
typename AgentID,
typename Node>
999 , port_index_(input_port.port_index())
1006 template<
typename AgentID,
typename Node>
1009 return iter_->first;
1013 template<
typename AgentID,
typename Node>
1016 return &iter_->first;
1020 template<
typename AgentID,
typename Node>
1028 template<
typename AgentID,
typename Node>
1037 template<
typename AgentID,
typename Node>
1045 template<
typename AgentID,
typename Node>
1054 template<
typename AgentID,
typename Node>
1057 return iter_ == rhs.iter_;
1061 template<
typename AgentID,
typename Node>
1064 return iter_ != rhs.iter_;
1068 template<
typename AgentID,
typename Node>
duration handle_planned_event(duration elapsed_dt)
Invoked when the planned duration elapses for either an agent or the overall collection; calls micro_...
Definition: collection_node.h:396
arraynd< bool, ndims > operator==(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:931
const auto output
Equivalent to data_goal::output.
Definition: data_goal.h:22
std::string tostring(const T &val)
Definition: qualified_type.h:35
const std::string & node_name() const
Returns the name of the node.
Definition: system_node.h:135
bool operator!=(const const_iterator &rhs) const
Definition: collection_node.h:1062
const auto input
Equivalent to data_goal::input.
Definition: data_goal.h:21
const_iterator & operator--()
Definition: collection_node.h:1038
collection_node(const std::string &node_name, const node_context &external_context)
Constructs a collection_node.
Definition: collection_node.h:303
A data structure which represents progress through a simulation, encapsulating both simulated time an...
Definition: discrete_event_time.h:36
A generic port class template declaration.
Definition: port.h:53
duration handle_unplanned_event(duration elapsed_dt)
Invoked whenever a message is received; calls macro_unplanned_event.
Definition: collection_node.h:365
A base class for all nodes from which systems models are constructed.
Definition: system_node.h:41
void invoke_agent(const AgentID &agent_id)
Creates, invokes, and removes an agent.
Definition: collection_node.h:716
constexpr scale no_scale
Definition: scale.h:153
Definition: qualified_type.h:24
const_iterator & operator++()
Definition: collection_node.h:1021
const_iterator agent_begin()
Returns an iterator pointing to the oldest agent.
Definition: collection_node.h:780
Definition: qualified_type.h:76
A class for measuring and accumulating intervals of wallclock time.
Definition: timer.h:24
A base class for the collection node class template.
Definition: collection_node_base.h:21
void remove_agent(const AgentID &agent_id)
Finalizes and removes an agent.
Definition: collection_node.h:670
const_iterator agent_end()
Returns an iterator pointing beyond the newest agent.
Definition: collection_node.h:787
const std::string & port_name() const
Returns the name of the port.
Definition: port.h:212
constexpr auto _s
Definition: units.h:128
A data structure which provides durations elapsed since past events.
Definition: time_cache.h:27
const Node prototype
A node that serves as a proxy for all agent nodes.
Definition: collection_node.h:86
system_node & operator=(const system_node &)=delete
No copy assignment.
const std::string & string_from_data_goal(data_goal dgoal)
Returns the std::string representation of the dgoal value.
Definition: data_goal.cpp:21
flow_port_proxy< T > access(const port< flow, input, T > &prototype_port)
Returns a proxy of the flow input port prototype_port, allowing its value to be modified.
A data structure which supports the scheduling of future events.
Definition: time_queue.h:34
bool operator==(const const_iterator &rhs) const
Definition: collection_node.h:1055
Definition: collection_node.h:278
void print_on_planned_duration(bool flag=true) const
If flag is true, all planned durations are printed for this node.
Definition: collection_node.h:329
Definition: node_context.h:16
const AgentID * operator->() const
Definition: collection_node.h:1014
duration handle_initialization_event()
Invoked at the beginning of a simulation; calls macro_initialization_event.
Definition: collection_node.h:336
Definition: node_interface.h:16
A base class template for all collection nodes.
Definition: collection_node.h:55
const auto flow
Equivalent to data_mode::flow.
Definition: data_mode.h:22
void create_agent(const AgentID &agent_id)
Creates a new agent of type AgentNode.
Definition: collection_node.h:566
bool agent_exists(const AgentID &agent_id)
Returns true if an agent with ID agent_id currently exists.
Definition: collection_node.h:766
quantity< seconds > duration
Definition: quantity.h:1006
static const int64 macro_event_id
The index used to schedule macro events; it must not conflict with any of the agent indices...
Definition: collection_node.h:94
int64 agent_count()
Returns the current number of agents.
Definition: collection_node.h:773
const auto message
Equivalent to data_mode::message.
Definition: data_mode.h:23
A class template for message output ports.
Definition: port.h:145
Definition: node_structure.h:15
Definition: collection_node.h:62
void handle_finalization_event(duration elapsed_dt)
Invoked at the end of a simulation; calls macro_finalization_event.
Definition: collection_node.h:469
arraynd< bool, ndims > operator!=(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:941
const pointer & flow_input_port_value(int64 port_index)
Definition: node_interface.cpp:62
const std::string & string_from_data_mode(data_mode dmode)
Returns the std::string representation of the dmode value.
Definition: data_mode.cpp:21
bool transmitted(const port< message, output, T > &prototype_port)
Returns true if a message was transmitted by an agent on the port corresponding to prototype_port...
Definition: collection_node.h:491
arraynd< T, ndims > operator*(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:796
int64_t int64
Definition: number_types.h:14
void affect_agent(const AgentID &agent_id)
Sends a message to an agent.
Definition: collection_node.h:616
A class template for flow output ports.
Definition: port.h:183
const pointer & message_input_port_value(int64 port_index)
Definition: node_interface.cpp:113
int64 port_index() const
Returns the index of the port within the encompassing node_interface object.
Definition: port.h:219
const AgentID & operator*() const
Definition: collection_node.h:1007
void print_on_elapsed_duration(bool flag=true) const
If flag is true, all elapsed durations are printed for this node.
Definition: collection_node.h:322
const node_interface & external_interface() const
Returns the object responsible for exchanging information between the node and its surrounding contex...
Definition: system_node.h:153
Definition: collection_node.h:59
virtual ~collection_node()=default
Destructor.
A data type which represents a pointer to anything.
Definition: pointer.h:27