-
Notifications
You must be signed in to change notification settings - Fork 33
CEP 31 - Agent Registered Discrete Event Timing #447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: source
Are you sure you want to change the base?
Changes from all commits
42de1cf
70c925c
eff0d51
d18f14c
225fc38
62b9367
194ad4e
1bb20a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| CEP 31 - Agent Registered Discrete Event Timing | ||
| *********************************************************** | ||
|
|
||
| :CEP: 31 | ||
| :Title: Agent Registered Discrete Event Timing | ||
| :Last-Modified: 2026-02-20 | ||
| :Author: Meghan Krieg <kriegm@oregonstate.edu> | ||
| :BDFP: Madicken Munk/Paul Wilson | ||
| :Status: Draft | ||
| :Type: Standards Track | ||
| :Created: 2026-02-19 | ||
| :Cyclus-Version: 1.6.0 | ||
|
|
||
| Background | ||
| =========== | ||
|
|
||
| |Cyclus| currently runs using a fixed increment time advancement mechanism, ``dt``. | ||
| Within each ``dt`` of the simulation, cyclus's cardinal function progresses through a distinct ordering | ||
| of 6 phases which include the | ||
|
|
||
| - Building Phase | ||
| - Tick Phase | ||
| - Exchange Phase | ||
| - Tock Phase | ||
| - Decision Phase | ||
| - Decomissioning Phase | ||
|
|
||
| before advancing to the next time step. One of the core paradigms of this implementation is | ||
| that all agents within the simulation must participate in the Dynamic Resource Exchange and | ||
| the surrounding time execution steps (Tick/Tock phases). The ordering of these phases allows | ||
| the maxiumum transition of resources with building phase completed first and decomissioning last. | ||
| In addition to this feature, the phase ordering toggles between two categories: agent phase nad kernel phase. | ||
| While the kernel phase represents events that alter the simulation state, agent phases include | ||
| actions that update an agent's internal state. For more information, refer to `CEP 20<https://fuelcycle.org/cep/cep20.html>`_. | ||
|
|
||
| Where `CEP 20<https://fuelcycle.org/cep/cep20.html>`_ defined cyclus as a broadly discrete event simulation, CEP 31 will push the implementation | ||
| further. | ||
|
|
||
| Motivation and Rationale | ||
| ========================== | ||
|
|
||
| Simulations with event based or discrete event timing run on an internal clock rather than a fixed simulation | ||
| clock (as featured in cyclus). For this internal clock, events that alter the simulation state are registered at distinct timestamps | ||
| within the simulation duration. The simulation progresses from scheduled event to scheduled event skipping timestamps | ||
| where no actions are registered. For example, an agent may schedule a build-event at timestamp 5, a trade event at timestamp 7, and a decomission event at timestamp 10. | ||
| Then, the timeline for a 10 month simulation will proceed as follows | ||
|
|
||
| START 3 (build) -- 5 (trade) -- 7 (decom) END | ||
|
|
||
| as opposed to the current implementation | ||
|
|
||
| START 0 -- 1 -- 2 -- 3 (build) -- 4 -- 5 (trade) -- 6 -- 7 (decom) -- 8 -- 9 -- 10 END | ||
|
|
||
| In cyclus, discrete even timing can be implemented by allowing agents to internally check their inventory | ||
| and status to register themselves for DRE participation, Build, or Decomission events. In instances | ||
| when no agents reigster actions, there will be no events, and the simulation will skip that timestmap. Agents will | ||
| dicate the dynamics of the simulation instead of a fixed timestep forcing interactions. | ||
|
|
||
| With many timesteps skipped between agent's cycle/event registrations, computational time will be lower. | ||
|
|
||
| Conceptualization | ||
| =============================== | ||
|
|
||
| Based on the current structure set up by the kernal and agent steps in the phase suit, the following | ||
| discrete event implementation is suggested... | ||
|
|
||
| Events in the simulation's internal clock can be requested by agents using their own ``EventRequest()`` function. | ||
| Events may only be registered when agents wish to complete the follwing actions: | ||
|
|
||
| - Build | ||
| - Request Materials | ||
| - Decomission | ||
|
|
||
| These actions map to the current *kernel* phases of cyclus's cardinal function. Thus, by extent, | ||
|
|
||
| - Tick | ||
| - Tock | ||
| - Decision | ||
|
|
||
| may not be considered events because they do *not* change the simulation state. They change | ||
| the agent's internal state (agent phase). As these actions are not events, they may never be independently registered by agents. | ||
| (There are scenarios in which build/requets/decomission may trigger them, however.) | ||
|
|
||
| For the DRE, agents will *only* be able to register for material requests; thus, material demands instead of material | ||
| supply will drive the DRE scheduling. When agents go to register an event by requesting a material, they are unaware of the state of other agent's | ||
| supplies. So, for the subset of agents that are triggering DRE events through material requests, *all available | ||
| agents in the simulation must be accessible to the DRE to request bids and responses*. This ensures that material request events aren't prohibited from being satisfied | ||
| even when requested material exists. | ||
|
|
||
| Because of the required attendance for all agents in the material bids stage of the DRE, the agent phases Tick/Tock/Decision must be triggered | ||
| for all available agents as well. These internal Tick/Tock/Decision updates are crucial for deriving accurate *bid* information for request portfolios. There are further | ||
| filtering options that consider deregistering an agent's Tocks/Decisions when they make no material bids. | ||
|
|
||
| Implementation | ||
| =============================== | ||
|
|
||
| Material requests, Build, and Decomissioin event registration will be handled by individual agents. Cyclus already creates a preconditioned timeline | ||
| for discrete-build and decomission events. An additional ``EventRequest()`` member funcition for all cycamore archetypes will check a facility's inventory. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If such a function is necessary, it should perhaps be added to the |
||
|
|
||
| 1. If inventory not at capacity, agent will register for the (+1) next immediate time step to attempt another request. | ||
| 2. If inventory at capacity, agent will register its next request event for a fixed ``+ cycle_length`` time from the current event. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is too rooted in the current set of archetypes. We need to think beyond the concept of cycle length and reactors. |
||
|
|
||
| These material request events will be registered within Context in a dynamic dictionary that contains the event's timestamp and a list of ``Trader`` objects. To ensure that all | ||
| facility agents' ``EventRequest()`` functions are checked regularly, A look-ahead function will be added to cyclus's cardinal phase suite after the decomissioning phase. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this degenerate to time steps again? I don't know what the purpose of a look-ahead function is and when/how it gets triggered?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pasted some general code below in case my words are really vague! Maybe this makes what I am thinking a little clearer? It is pretty bare-bones but just for a general idea -- in void Timer::RunSim() {
...
ctx_->Populate(0); // at time 0 everyone must register for a trade event to get started
while ( (time_ < si_.duration) && (prev_time_ != time_)) {
CLOG(LEV_INFO1) << "Current time: " << time_;
if (want_snapshot_) {
want_snapshot_ = false;
SimInit::Snapshot(ctx_);
}
// run through phases
DoBuild();
CLOG(LEV_INFO2) << "Beginning Tick for time: " << time_;
DoTick();
CLOG(LEV_INFO2) << "Beginning DRE for time: " << time_;
DoResEx(&matl_manager, &genrsrc_manager);
CLOG(LEV_INFO2) << "Beginning Tock for time: " << time_;
DoTock();
CLOG(LEV_INFO2) << "Beginning Decision for time: " << time_;
DoDecision();
DoDecom();
DoLookAhead();
#ifdef CYCLUS_WITH_PYTHON
EventLoop();
#endif
prev_time_ = time_;
time_ = NextEvent();
...
}Then, later in void Timer::DoLookAhead() {
std::set<Trader*> all_traders = ctx_->traders();
for(Trader* m : all_traders){
m->EventRequest();
};
// another check will probably go here
}
int Timer::NextEvent(){
auto reg_traders = ctx_->EventRequesters(); //the list of traders who have registered for events in the timeline
int t_p = time_ +1; // time plus +1
std::vector<int> event_lists = {decom_queue_.upper_bound(t_p)->first,build_queue_.upper_bound(t_p)->first}, reg_traders.upper_bound(t_p)->first};
return *std::min_element(event_lists.begin(), event_lists.end());
}So, the simulation finishes some event and it looks for the next closest timestamp that has an event. That timestamp could have events registered under any 3, 2, or 1 of build/trade/decom actions scheduled. The simulation knows it has the event at the timestamp but does not know which type (this could change maybe), so it checks each phase for that event. If the phase is filled with participants, that phase is one of the events and is triggered. This means that the phases will have some conditional check... for example void Timer::DoBuild() {
if(build_queue_.count(time_)==0){
continue;}
else{
std::vector<std::pair<std::string, Agent*>> build_list = build_queue_[time_];
for (int i = 0; i < build_list.size(); ++i) {
Agent* m = ctx_->CreateAgent<Agent>(build_list[i].first);
Agent* parent = build_list[i].second;
...
}
...
}Overall, this treatment should skip the timeline from event to event instead of timestep to next timestep when fully fleshed out. |
||
|
|
||
| .. code-block:: c++ | ||
| DoBuild(); | ||
| DoTick(); | ||
| DoResEx(&matl_manager, &genrsrc_manager); | ||
| DoTock(); | ||
| DoDecision(); | ||
| DoDecom(); | ||
| DoLookAhead(); | ||
|
|
||
| The cardinal phase suite will maintain its current ordering for the reasons described in CEP 20. Each of the 6 phases will be checked during each event (as opposed to each time step) but the phase will | ||
| only be triggered and completed if it has participants registered. Only the newly introduced ``DoLookAhead()`` that checks each agents ``EventRequest()`` will be executed for all agents each event. | ||
|
|
||
| The simulation will be terminated fully when ``DoLookAhead()`` registers no new events and the simulation has completed the last event registered. | ||
|
|
||
| Backwards Compatibility | ||
| ======================== | ||
|
|
||
| These changes will not be backwards compatible with cyclus v1.6.0 and may require a new release. An optional simulation parameter could be introduced to switch this treatment on and off | ||
| such that the original time implemenation can be used. | ||
|
|
||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a key point of discussion/contention. Can you say more about why you want this strict interpretation? If the context will be skipping time steps based on the registered events, how will agents know when it is time to tick or tock? How will they be triggered? What if a tick is necessary to determine whether or not to participate in a trade?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are scenarios in which i can see the Tock and Decision being registrable events based on the outcome of the DRE.
It is mainly the tick that cannot be registrable (in my opinion)! If all traders objects are available bidders every trade event and all bidders need accurate bid information and we don't know who will bid, then all bidders must all tick. In other words, all traders must tick either every scheduled event or every trade event.
I could be really off the mark though.