Stefan Scherfke | 7 Jan 10:17
Picon

Notifiy a PEM that a simulation is over

Moin moin,

is there an easy way to notify a PEM that the simulation finished while the PEM was in a "yield hold"?

Example for a battery controller:

    …

    charge_start = self.sim.now()
    duration = self.get_charge_duration()
    yield hold, self, duration

    # This will be called if the battery is full or if someone
    # pulled the plug (and thus interruped the charging) 
    duration = self.sim.now() - charge_start
    self.battery.charge(self.kw, duration)

    …

If the simulation ends while the PEM has yielded "yield hold, self, duration", "self.battery.charge()"
wont get called.

I’ve tryied to wrap the yield in a try: yield except GeneratorExit, but this works neither. It seems like
the generator is not deleted correctly, when the simulation finishes and so no GeneratorExit is raised.

My current work-around for this is to call charge() manually for each process, when the simulation has
finished, but this is not really satisfying … ;-)

Ontje and I are currently fiddling around with it and try to find out, where references to the PEM could be
still alive after the sim. The eventlist is set to None and process._nextpoint is also None …
(Continue reading)

Stefan Scherfke | 7 Jan 10:52
Picon

Re: Notifiy a PEM that a simulation is over

Here is a minimal example:

    from SimPy.Simulation import Simulation, Process, hold

    class MyProcess(Process):
        def __init__(self, sim):
            super(MyProcess, self).__init__(sim=sim)

        def run(self):
            self.called = False
            try:
                yield hold, self, 10
            finally:
                self.called = True

    sim = Simulation()
    p = MyProcess(sim)
    sim.activate(p, p.run())
    sim.simulate(until=1)
    print 'called at simulation end?', p.called
    sim = None
    print 'called after deleting simulation?', p.called
    p._nextpoint = None
    print 'called after deleting nextpoint?', p.called

p._nextpoint is actually the last reference to the PEM generator and if you set it to None, the
finally-block will be called. (It didn’t work in my “real” simulation, because I set _nextpoint =
None for the wrong processes … ;-)).

But it is still not very nice if you have to set _nextpoint = None manually for each process. Maybe this could
(Continue reading)

Klaus G. Muller | 7 Jan 14:11
Picon
Picon
Favicon

Re: suggestion : one monitor, multiple values monitored

Rayene,
yes, if you have to monitor the same of variables for the same time frame, your approach is handy.

Klaus

Rayene Ben Rayana wrote:
Hello,
Isn't it more handy and efficient to have a single monitor instance that monitors multiple variable ?

Advantages : 
- You save a list of timestamps for the following (interesting for large monitors) 
- it is easier to plot multiple parameters into the same plot.

I began a Monitor class for my network simulator. It can be used as the following :
m = Monitor()
m.add_variable(lambda: car.speed, "The speed of the car in km/h")

and in the simulation loop:
m.observe() # without specifying any parameter


class Monitor(list):
    def __init__(self, world, time_label = 'time(s)'):
        self.world = world
        self.funcs = [lambda: self.world.time]
        self.labels = [time_label]

    def add_variable(func, label = None):
        if not label:
            label = func.__name__
        self.funcs.append(func)
        self.labels.append(label)
    
    def observe(self):
        self += [f() for f in self.funcs]

------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Simpy-users mailing list Simpy-users <at> lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/simpy-users

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
Simpy-users mailing list
Simpy-users <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/simpy-users
Klaus G. Muller | 7 Jan 13:47
Picon
Picon
Favicon

Re: Notifiy a PEM that a simulation is over

Stefan,
Happy New Year!

An interesting question. My answer to this is one of semantics: the 
simulation is NOT over, if something still needs to be done in the 
model. The battery controller process (the one in the "yield hold") 
should therefore be interrupted by whatever ends the charge process, 
like so:

    charge_start = self.sim.now()
    duration = self.get_charge_duration()
    yield hold, self, duration
    if self.interrupted():
         # This will be called if the battery is full or if someone
         # pulled the plug (and thus interrupted the charging) 
         duration = self.sim.now() - charge_start
         self.battery.charge(self.kw, duration)

What do you think? I believe this is a clean way of miodeling the charge 
termination action.

Klaus Müller

Stefan Scherfke wrote:
> Moin moin,
>
> is there an easy way to notify a PEM that the simulation finished while the PEM was in a "yield hold"?
>
> Example for a battery controller:
>
>     …
>
>     charge_start = self.sim.now()
>     duration = self.get_charge_duration()
>     yield hold, self, duration
>
>     # This will be called if the battery is full or if someone
>     # pulled the plug (and thus interruped the charging) 
>     duration = self.sim.now() - charge_start
>     self.battery.charge(self.kw, duration)
>
>     …
>
>
> If the simulation ends while the PEM has yielded "yield hold, self, duration", "self.battery.charge()"
wont get called.
>
> I’ve tryied to wrap the yield in a try: yield except GeneratorExit, but this works neither. It seems like
the generator is not deleted correctly, when the simulation finishes and so no GeneratorExit is raised.
>
> My current work-around for this is to call charge() manually for each process, when the simulation has
finished, but this is not really satisfying … ;-)
>
> Ontje and I are currently fiddling around with it and try to find out, where references to the PEM could be
still alive after the sim. The eventlist is set to None and process._nextpoint is also None …
>
> Any ideas?
>
> Best regards,
> Stefan
> ------------------------------------------------------------------------------
> This SF.Net email is sponsored by the Verizon Developer Community
> Take advantage of Verizon's best-in-class app development support
> A streamlined, 14 day to market process makes app distribution fast and easy
> Join now and get one step closer to millions of Verizon customers
> http://p.sf.net/sfu/verizon-dev2dev 
> _______________________________________________
> Simpy-users mailing list
> Simpy-users <at> lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/simpy-users
>
>   

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
Klaus G. Muller | 7 Jan 14:29
Picon
Picon
Favicon

Re: Code refactoring?

Ontje,
thanks for this contribution! I will apply the patch to the SimPy SourceForge repository and start my own tests. This is great material for a 2.1 release.

Klaus Müller

Ontje Lünsdorf wrote:
Hi Klaus, Am Donnerstag 26 November 2009 13:52:49 schrieb Klaus G. Muller:
please, maintain the simulate return values. They serve a purpose in status reporting.
Ack. SimulationTrace is now also fixed. The patch is feature-wise complete, the documentation may still need some more work. With the return values back in, I didn't need to touch the tests at all (I just had to add #coding=utf-8 to some files). Here's what I did for testing: - Ran all test*.py. Like this: for i in test*.py; do python $i; if (($? != 0)); then echo 'Oh noes, FAIL!!'; break; fi; done; - Ran MonitorTest.py - Ran Simulation.py, SimulationStep.py, SimulationTrace.py, SimulationRT.py - Manually checked the speed ratios in testRT_Behavior*.py - Piped output from patched and original SimulationTrace into separate files and ensured that contents are identical with diff. Here's the stupid benchmark I wrote. The patched version seems to be a little bit faster, but the difference is close to the measurement error. -------------8<------------- from SimPy.Simulation import Simulation, Process, hold class MyProcess(Process): def run(self): while True: yield hold, self, 1 def simulate(): sim = Simulation() p = MyProcess(sim=sim) sim.activate(p, p.run(), at=0) sim.simulate(until=100000) if __name__ == '__main__': for i in range(10): simulate() ------------->8------------- Results of three runs measured with time command: Patched: 9.434s, 9.397s, 9.429s Original: 9.856s, 9.584s, 9.620s So, should this go in? Anything I could do to improve the patch? Ontje ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Simpy-users mailing list Simpy-users <at> lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/simpy-users

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
Simpy-users mailing list
Simpy-users <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/simpy-users
Klaus G. Muller | 7 Jan 15:27
Picon
Picon
Favicon

Re: Notifiy a PEM that a simulation is over

Stefan,
I don't think that anything should happen to a process in a hold when a simulation has come to an end. If you end the simulation at t = 10, t = 15 is outside the simulation time frame. If, on the other hand, the event at t  = 15 is part of the model execution, just don't end the simulation at t = 10, but let it end with the event at t = 15.

I clearly argue from the semantics a modeling point of view, not from a Python programming point of view.

Klaus Müller


Stefan Scherfke wrote:
Hi Klaus, happy New Year to you, too! charge() should be called no matter whether the charging process was interrupted or not. The code I posted works quite fine during the simulation. The problem arises only, when the whole simulation ends while the controller is "in a hold": Imagine I want to simulate until t = 10. If the controller yields "hold, self, 10" at t = 5, it should continue to work (and call charge()) at t = 15. But at t = 15 the simulation already has stopped without the controller realizing this, so charge() doesn’t get called. Normally, if you delete/close a generator (here the PEM), it raises a GeneratorExit error to the generator/PEM, so I can except and handle the end of it. Since a SimPy process keeps a reference to its PEM in _nextpoint, if the PEM was in a "hold" when the simulation finished, then no GeneratorExit will be raised. So the simulator should imho check the event list for all outstanding events and either call close() directly on each generator or just set _nextpoint = None for each process. I can try to implement and test this and post my results here later. :-) cheers, Stefan Am 2010-01-07 um 13:47 schrieb Klaus G. Muller:
Stefan, Happy New Year! An interesting question. My answer to this is one of semantics: the simulation is NOT over, if something still needs to be done in the model. The battery controller process (the one in the "yield hold") should therefore be interrupted by whatever ends the charge process, like so: charge_start = self.sim.now() duration = self.get_charge_duration() yield hold, self, duration if self.interrupted(): # This will be called if the battery is full or if someone # pulled the plug (and thus interrupted the charging) duration = self.sim.now() - charge_start self.battery.charge(self.kw, duration) What do you think? I believe this is a clean way of miodeling the charge termination action. Klaus Müller Stefan Scherfke wrote:
Moin moin, is there an easy way to notify a PEM that the simulation finished while the PEM was in a "yield hold"? Example for a battery controller: … charge_start = self.sim.now() duration = self.get_charge_duration() yield hold, self, duration # This will be called if the battery is full or if someone # pulled the plug (and thus interruped the charging) duration = self.sim.now() - charge_start self.battery.charge(self.kw, duration) … If the simulation ends while the PEM has yielded "yield hold, self, duration", "self.battery.charge()" wont get called. I’ve tryied to wrap the yield in a try: yield except GeneratorExit, but this works neither. It seems like the generator is not deleted correctly, when the simulation finishes and so no GeneratorExit is raised. My current work-around for this is to call charge() manually for each process, when the simulation has finished, but this is not really satisfying … ;-) Ontje and I are currently fiddling around with it and try to find out, where references to the PEM could be still alive after the sim. The eventlist is set to None and process._nextpoint is also None … Any ideas? Best regards, Stefan ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ Simpy-users mailing list Simpy-users <at> lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/simpy-users

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
Simpy-users mailing list
Simpy-users <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/simpy-users
Stefan Scherfke | 7 Jan 16:03
Picon

Re: Notifiy a PEM that a simulation is over

Yes, this is right of course.

In my example, the battery would be fully charged at t = 15 if the simulation ran long enough (so it had 15 – 5 =
10 time unites to charge).

If the simulation ends at t = 10, I want my battery to be charged for 5 time units until t = 10. I do not want it to be
charged for 10 time units until t = 15 in this case. This behaviour should be semantically correct.

I just modified Evlist._nextev() to do delete all future events just before the simulation stops:

Simulation.py ~ line 403:

if self.sim._t > self.sim._endtime:
    self.sim._t = self.sim._endtime
    nextEvent._nextpoint = None # Delete ref. to PEM for the first future event
    for tstamp in self.timestamps: # Find further future events
        tstamp[2]._nextpoint = None # Delete refs to PEMs of further future events
    self.sim._stop = True

Those three lines do everything I want. With them you can do

try:
    yield hold, self, longtime
except GeneratorExit:
    # do some cleanup
finally:
    # do sth no matter whether "longtime" is over or the sim has finished

Of course, If you don’t want the try-except, it’s not required. :-)

cheers,
stefan

Am 2010-01-07 um 15:27 schrieb Klaus G. Muller:

> Stefan,
> I don't think that anything should happen to a process in a hold when a simulation has come to an end. If you
end the simulation at t = 10, t = 15 is outside the simulation time frame. If, on the other hand, the event at t  =
15 is part of the model execution, just don't end the simulation at t = 10, but let it end with the event at t = 15.
> 
> I clearly argue from the semantics a modeling point of view, not from a Python programming point of view.
> 
> Klaus Müller
> 
> 
> Stefan Scherfke wrote:
>> Hi Klaus,
>> 
>> happy New Year to you, too!
>> 
>> charge() should be called no matter whether the charging process was interrupted or not. The code I
posted works quite fine during the simulation.
>> 
>> The problem arises only, when the whole simulation ends while the controller is "in a hold":
>> 
>> Imagine I want to simulate until t = 10.
>> If the controller yields "hold, self, 10" at t = 5, it should continue to work (and call charge()) at t = 15.
>> But at t = 15 the simulation already has stopped without the controller realizing this, so charge()
doesn’t get called.
>> 
>> Normally, if you delete/close a generator (here the PEM), it raises a GeneratorExit error to the
generator/PEM, so I can except and handle the end of it.
>> 
>> Since a SimPy process keeps a reference to its PEM in _nextpoint, if the PEM was in a "hold" when the
simulation finished, then no GeneratorExit will be raised.
>> 
>> So the simulator should imho check the event list for all outstanding events and either call close()
directly on each generator or just set _nextpoint = None for each process. 
>> 
>> I can try to implement and test this and post my results here later. :-)
>> 
>> cheers,
>> Stefan
>> 
>> 
>> Am 2010-01-07 um 13:47 schrieb Klaus G. Muller:
>> 
>>   
>> 
>>> Stefan,
>>> Happy New Year!
>>> 
>>> An interesting question. My answer to this is one of semantics: the simulation is NOT over, if something
still needs to be done in the model. The battery controller process (the one in the "yield hold") should
therefore be interrupted by whatever ends the charge process, like so:
>>> 
>>>   charge_start = self.sim.now()
>>>   duration = self.get_charge_duration()
>>>   yield hold, self, duration
>>>   if self.interrupted():
>>>        # This will be called if the battery is full or if someone
>>>        # pulled the plug (and thus interrupted the charging)         duration = self.sim.now() - charge_start
>>>        self.battery.charge(self.kw, duration)
>>> 
>>> What do you think? I believe this is a clean way of miodeling the charge termination action.
>>> 
>>> Klaus Müller
>>> 
>>> 
>>> 
>>> 
>>> Stefan Scherfke wrote:
>>>     
>>> 
>>>> Moin moin,
>>>> 
>>>> is there an easy way to notify a PEM that the simulation finished while the PEM was in a "yield hold"?
>>>> 
>>>> Example for a battery controller:
>>>> 
>>>>    …
>>>> 
>>>>    charge_start = self.sim.now()
>>>>    duration = self.get_charge_duration()
>>>>    yield hold, self, duration
>>>> 
>>>>    # This will be called if the battery is full or if someone
>>>>    # pulled the plug (and thus interruped the charging)     duration = self.sim.now() - charge_start
>>>>    self.battery.charge(self.kw, duration)
>>>> 
>>>>    …
>>>> 
>>>> 
>>>> If the simulation ends while the PEM has yielded "yield hold, self, duration",
"self.battery.charge()" wont get called.
>>>> 
>>>> I’ve tryied to wrap the yield in a try: yield except GeneratorExit, but this works neither. It seems
like the generator is not deleted correctly, when the simulation finishes and so no GeneratorExit is raised.
>>>> 
>>>> My current work-around for this is to call charge() manually for each process, when the simulation has
finished, but this is not really satisfying … ;-)
>>>> 
>>>> Ontje and I are currently fiddling around with it and try to find out, where references to the PEM could
be still alive after the sim. The eventlist is set to None and process._nextpoint is also None …
>>>> 
>>>> Any ideas?
>>>> 
>>>> Best regards,
>>>> Stefan
>>>> ------------------------------------------------------------------------------
>>>> This SF.Net email is sponsored by the Verizon Developer Community
>>>> Take advantage of Verizon's best-in-class app development support
>>>> A streamlined, 14 day to market process makes app distribution fast and easy
>>>> Join now and get one step closer to millions of Verizon customers
>>>> 
>>>> http://p.sf.net/sfu/verizon-dev2dev
>>>>  _______________________________________________
>>>> Simpy-users mailing list
>>>> 
>>>> Simpy-users <at> lists.sourceforge.net
>>>> https://lists.sourceforge.net/lists/listinfo/simpy-users
>>>> 
>>>> 
>>>>  
>>>>       
>>>> 
>> 
>> 
>>   
>> 
> 

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
Stefan Scherfke | 19 Jan 16:30
Picon

A new approach for monitoring simulation data

Hello,

Ontje and I want to present and discuss a new way for monitoring SimPy
simulations. We have attached a commented sample implementation of our approach
with some usage examples.

Before we describe our idea, we want to point out some things we didn’t like
about SimPy’s ``Monitor`` and ``Tally`` classes:

* They use global variables.
* If you monitor multiple attributes, timestamps are stored with each of them
  (data duplication, requires more memory as necessary).
* They combine data collection and analysis in one class. These are different
  functional aspects and should in our opinion be separated.
* Coupling with Histogram and GUI stuff.

We never used any of both for our projects, because they never really fitted our
needs. So we debated intensely how an optimal monitoring would look like. It
should meet the following requirements:

* Easy to use (simple API, little typing)
* Memory and CPU efficiency

  * No impact on simulation speed if you don’t use it.
  * As little impact as possible if you use it.

* Flexibility and easy extensibility
* Separation of data collection and data analysis

Description of our approach
===========================

We know that there are many ways one might want to monitor simulations. We
focused on the use case, that you want to monitor several attributes for one
process—maybe with timestamp—so that your data looks something like this:

    ([t0, t1, t2], [x0, x1, x2], [y0, y1, y2])

Our approach can easily be extended to meet other use cases, too, but more on
this later. We also state that our approach does not cover data analysis. This
is something that should in our opinion be done by specialized frameworks like
e.g. NumPy, SciPy and Matplotlib.

Basic idea
----------

For performance reasons our monitoring works on SimPy processes rather than on
the simulation itself. This has the advantage of a minimized or even nonexisting
performance impact on the simulation speed if you monitor only a few processes or
don’t monitor anything at all.

We also wanted a very easy API: Create a monitor like ``m = Monitor(config)``
and trigger the monitoring of a process’ current state by just calling ``m()``.

How to exactly use it
---------------------

Monitors should be instanciated in ``MyProc.__init__()``. You must pass
some configuration for the *series* you want to create. Each *series* is
defined by a *name* and a *collector* function::

    class MyProc(Process):
        def __init__(self):
            # ...
            self.monitor = Monitor(
                ('a', func1),
                ('b', func2),
                # ...
            )

You can then retrieve the data for e.g. the series “a” via ``self.monitor.a``.
The collector functions describe, how the data should be collected. The two
common cases here are:

1. Automatically get an attribute’s value (e.g. ``self.a``)
2. Manually pass the value to be monitored

You can solve both cases with custom lambda functions, but we’ve also create a
shortcut for each of them.

And advanced example::

    class MyProc(Process):
        def __init__(self, sim):
            # ...
            self.monitor = Monitor(
                ('time', sim.now),
                get(self, 'a', 'b'),
                ('diff', manual)
            )

This will create a monitor containing the series ``time``, ``a``, ``b`` and
``diff``, where ``time`` stores the values returned by ``sim.now()``, ``self.a``
and ``self.b`` get collected automatically and and a value for ``diff`` has to
be passed manually. All this happens with the PEM of a process::

    def run(self)
        while True:
            # ...
            self.monitor(diff=self.get_diff()

That’s it!

Conclusion
==========

We hope we could make our idea clear. We think our solution is quite clean and
flexible. It can easily be extended (e.g. by adding other monitor classes) and
also easily be added to SimPy without interfering with any existing
functionality. Since it isn’t integrated into the simulation core, it won’t slow
down the simulation, if you don’t want monitoring.

The attached script contains the whole monitoring framework and an example
simulation that tests and shows how to use it. You need SimPy, NumPy and
Matplotlib to execute it (NumPy and Matplotlib are only required for the example
analysis part in the end, so if you uncomment these lines, you don’t need them).

Other monitor classes we thought of are:

* a *SimpleMonitor* that just creates one list of values (e.g. [x0, x1, ...]),
* a *GroupedMonitor* that collects groups of series (useful for a central
  collector process which just monitors other processes in the simulation) and
* aggregate monitors like e.g. and AvgMonitor. This could be useful if you are
  just interested in the average of all values (and not the values themselves),
  so it only needs to store the sum and count of all values.

What do you think of it?

Cheers,
Ontje and Stefan

Attachment (monitoring.py): text/x-python-script, 7760 bytes
------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
_______________________________________________
Simpy-users mailing list
Simpy-users <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/simpy-users
Harriv | 19 Jan 21:16
Picon

Simpy book?

Hi,

 There's this page about SimPy book -
http://simpy.sourceforge.net/simpy_book.htm

 What's the current status of it? I hope it is not abandoned..

------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
Rayene Ben Rayana | 20 Jan 09:08
Picon
Gravatar

Re: A new approach for monitoring simulation data

Dear Ontje and Stefan,

Thank you for your design effort, I really appreciated reading your proposal.
I have some comments though.

On 19 janv. 2010, at 16:30, Stefan Scherfke wrote:

> Hello,
> 
> Ontje and I want to present and discuss a new way for monitoring SimPy
> simulations. We have attached a commented sample implementation of our approach
> with some usage examples.
> 
> Before we describe our idea, we want to point out some things we didn’t like
> about SimPy’s ``Monitor`` and ``Tally`` classes:
> 
> * They use global variables.
> * If you monitor multiple attributes, timestamps are stored with each of them
>  (data duplication, requires more memory as necessary).

Totally agree !

> * They combine data collection and analysis in one class. These are different
>  functional aspects and should in our opinion be separated.
> * Coupling with Histogram and GUI stuff.

Partially agree. IMHO, an object usually gathers several different functional aspects.
The only link between these aspects is that they use the same data : the object attributes.

I think that having data collection and analysis in the same class is not a real issue.

> 
> We never used any of both for our projects, because they never really fitted our
> needs. So we debated intensely how an optimal monitoring would look like. It
> should meet the following requirements:
> 
> * Easy to use (simple API, little typing)
> * Memory and CPU efficiency
> 
>  * No impact on simulation speed if you don’t use it.
>  * As little impact as possible if you use it.
> 
> * Flexibility and easy extensibility
> * Separation of data collection and data analysis
> 
> 
> Description of our approach
> ===========================
> 
> We know that there are many ways one might want to monitor simulations. We
> focused on the use case, that you want to monitor several attributes for one
> process—maybe with timestamp—so that your data looks something like this:
> 
>    ([t0, t1, t2], [x0, x1, x2], [y0, y1, y2])

Can you please add  Monitor.zip() that rotates the vectors using the python builtin zip function ?
http://docs.python.org/library/functions.html
This may be useful sometimes.

> 
> Our approach can easily be extended to meet other use cases, too, but more on
> this later. We also state that our approach does not cover data analysis. This
> is something that should in our opinion be done by specialized frameworks like
> e.g. NumPy, SciPy and Matplotlib.

I agree that analysis should be minimal but not non-existent. No need to install SciPy if the analysis can be
done in one line of code.
Also, you may add an easy way to convert a Monitor to a numpy array.

> 
> 
> Basic idea
> ----------
> 
> For performance reasons our monitoring works on SimPy processes rather than on
> the simulation itself. This has the advantage of a minimized or even nonexisting
> performance impact on the simulation speed if you monitor only a few processes or
> don’t monitor anything at all.
> 
> We also wanted a very easy API: Create a monitor like ``m = Monitor(config)``
> and trigger the monitoring of a process’ current state by just calling ``m()``.

m() does not seem to be a good idea. IMHO, m is an instance of a Monitor class, 
calling it does not really make sense. 

m.append() or m.add() or m.watch() is easier to understand. 
A little more typing but much clearer.

> 
> 
> How to exactly use it
> ---------------------
> 
> Monitors should be instanciated in ``MyProc.__init__()``. You must pass
> some configuration for the *series* you want to create. Each *series* is
> defined by a *name* and a *collector* function::
> 
>    class MyProc(Process):
>        def __init__(self):
>            # ...
>            self.monitor = Monitor(
>                ('a', func1),
>                ('b', func2),
>                # ...
>            )

Great !
Did you manage to add optional parameters to the functions ?

> 
> You can then retrieve the data for e.g. the series “a” via ``self.monitor.a``.
> The collector functions describe, how the data should be collected. The two
> common cases here are:
> 
> 1. Automatically get an attribute’s value (e.g. ``self.a``)
> 2. Manually pass the value to be monitored
> 
> You can solve both cases with custom lambda functions, but we’ve also create a
> shortcut for each of them.

I am not sure that shortcuts are a good idea. Lambda functions are enough.
I agree that lambda functions are a bit hard to understand in the beginning. 
But once this hurdle passed, this is useful to every python developer.
Adding shortcuts adds a complexity level IMHO.

> 
> And advanced example::
> 
>    class MyProc(Process):
>        def __init__(self, sim):
>            # ...
>            self.monitor = Monitor(
>                ('time', sim.now),
>                get(self, 'a', 'b'),
>                ('diff', manual)
>            )
> 
> This will create a monitor containing the series ``time``, ``a``, ``b`` and
> ``diff``, where ``time`` stores the values returned by ``sim.now()``, ``self.a``
> and ``self.b`` get collected automatically and and a value for ``diff`` has to
> be passed manually. All this happens with the PEM of a process::
> 
>    def run(self)
>        while True:
>            # ...
>            self.monitor(diff=self.get_diff()
> 
> That’s it!
> 
> 
> Conclusion
> ==========
> 
> We hope we could make our idea clear. We think our solution is quite clean and
> flexible. It can easily be extended (e.g. by adding other monitor classes) and
> also easily be added to SimPy without interfering with any existing
> functionality. Since it isn’t integrated into the simulation core, it won’t slow
> down the simulation, if you don’t want monitoring.
> 
> The attached script contains the whole monitoring framework and an example
> simulation that tests and shows how to use it. You need SimPy, NumPy and
> Matplotlib to execute it (NumPy and Matplotlib are only required for the example
> analysis part in the end, so if you uncomment these lines, you don’t need them).
> 
> Other monitor classes we thought of are:
> 
> * a *SimpleMonitor* that just creates one list of values (e.g. [x0, x1, ...]),
> * a *GroupedMonitor* that collects groups of series (useful for a central
>  collector process which just monitors other processes in the simulation) and
> * aggregate monitors like e.g. and AvgMonitor. This could be useful if you are
>  just interested in the average of all values (and not the values themselves),
>  so it only needs to store the sum and count of all values.
> 
> What do you think of it?
> 
> Cheers,
> Ontje and Stefan
> 
Other things to think of :

1. An easy way to obtain a throughput plot (delta_value/delta_time)
2. Checking if the monitored data changed since last time. If not, give the user the possibility
to skip the storage of that line.

example : 
Instead of :

[time, x, y]
1, 14, 5
2, 14, 5
3, 14, 5
4, 12, 6

We can store :
[time, x, y]
1, 14, 5
4, 12, 6

Useful when data does not change too often.

> 
> <monitoring.py>------------------------------------------------------------------------------
> Throughout its 18-year history, RSA Conference consistently attracts the
> world's best and brightest in the field, creating opportunities for Conference
> attendees to learn about information security's most important issues through
> interactions with peers, luminaries and emerging and established companies.
> http://p.sf.net/sfu/rsaconf-dev2dev_______________________________________________
> Simpy-users mailing list
> Simpy-users <at> lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/simpy-users

Thank you again for your work. Please keep in mind that these are just my thoughts as a developer of a network
simulator based on SimPy (NetPyLab, http://rayene.github.com/netpylab/ ). Therefore, others may
disagree as they may have different needs.

Cheers,

Rayene BEN RAYANA
Telecom Bretagne, RSM Dpt

------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev

Gmane