what is the recommended way to log relevant events into a curated history for later analysis?

154 views
Skip to first unread message

Sebastián Arroyo

unread,
Apr 16, 2021, 11:21:39 AM4/16/21
to python-simpy
Hello, all. I've managed to program a simulation where several agents (implemented as separate python classes)  interact, each has it's own internal processes, they sometimes have to wait for another agent to finish some process, and so on, you get the idea.

I'd like to log each agents personal event history. Is there a recommended way to have each event logged in some kind of history object or list or something?  I can already imagine maybe adding a callback to each event and that callback writes env.now to some list or history object. But I'd prefer to hear some ideas or past experiences, maybe there is some simple and elegant way to 

jpgr...@gmail.com

unread,
Apr 16, 2021, 12:14:47 PM4/16/21
to python-simpy
How you keep records of simulation events depends on what you ultimately want to measure. So, maybe start by identifying your key performance indicators (KPI). Then identify what data you will need to capture from the simulation to compute the KPI. From there, it should be more obvious as to where in the model code you will need to add code to record data.

Regarding how you record data, it depends on how much data you plan on recording and perhaps what tools you would like to use to post-process the data.

The simplest strategy would be to capture records by appending to an in-memory list and performing post-processing within your simulation process. This can work well if you're dealing with short simulations and a relatively small amount of records.

For longer simulations and large amounts of data, capturing data to a file or database may work better. This also allows your post-processing to happen in a different process/tool/script than your simulation. If you're database-oriented, then using SQLite to capture records might be a good choice. Alternatively, outputting CSV or JSON can work well too.

My current projects use a one JSON object per line file format which can then easily be read into a pandas dataframe with:

    df = pandas.read_json(path, orient='records', lines=True)

Obviously, this approach assumes that you want to do post-processing with pandas.

Hope this helps.

Pete

Sebastián Arroyo

unread,
Apr 16, 2021, 2:44:15 PM4/16/21
to python-simpy
Pete, thanks a lot for your answer! Fortunately I already have well defined performance indicators. I already have a good idea of what data I want and also I'm convinced I know where it should be logged. 

The simulations don't run for long and don't take much RAM so the data will be stored in memory and later processed with pandas/numpy/scipy.

    > The simplest strategy would be to capture records by appending to an in-memory list and performing post-processing 
    > within your simulation process. This can work well if you're dealing with short simulations and a relatively small amount of records.

Sounds good!

What I want to know if there is some ... elegant? tidy? code-efficient? way to have an event appended to the list. For instance, here's my approach:

    class Agent():
        def __init__(self, env):
            self.env = env
            self.history = []  # to append event times
            
            # this event will be triggered somewhere else in the simulation
            self.externalEvent = env.event()
            
            # this one is triggered inside this agent
            self.internalEvent = env.event()
            
        def internalProcess(self):
            yield self.env.timeout(1)  # time the process needs
            self.internalEvent.succed()  # mark as succesfull 
            self.history.append([self.env.now, "Internal Event"])  # log event
        
        def simulate(self):
            '''The main process of this agent'''
            # wait for the external event to happen
            yield self.externalEvent
            self.history.append([self.env.now, "External Event"])  # log event
            
            # run the internal process
            yield self.env.process(self.internalProcess())


Basically I append to a list when the event is successful.

But I'm learning more about simpy and I wonder If maybe I should add a callback to each event and have the callback be a function that appends to the history. Or maybe use the method trigger in some clever way. IDK, I feel I'm a noobie approaching problems with a noobie approach . 

Thank you!

Seba
Reply all
Reply to author
Forward
0 new messages