1

I am trying to run a simulation with SimPy. Unlike open systems, since my system is closed, I need to generate a constant amount of entities immediately (10 in my case). So, no interarrival times.

The problem is that when I try to generate entities in a while loop with or without interarrival times, I don't get an error. (Without interarrival times, of course it doesn't stop running, cause you know, it tries to generate as much as possible in a given runtime). The code below works but it is not what I need.

    def customer_generator(self, env, resource1, resource2):
        while True:
            p = self.customer(env, resource1, resource2) # create a new customer
            env.process(p) # start the simulation of the customer

But when I try to generate them in a for loop to create only 10 entities,

    def customer_generator(self, env, resource1, resource2):
        for x in range(10):
            p = self.customer(env, resource1, resource2) # create a new customer
            env.process(p) # start the simulation of the customer

I get this "None is not a generator" error.

  File "C:\Users\Can\Anaconda3\lib\site-packages\simpy\events.py", line 310, in __init__
    raise ValueError('%s is not a generator.' % generator)

ValueError: None is not a generator.

Maybe I am missing a simple detail. Any suggestions on how I can generate only 10 entities without getting this error?

Can Evin
  • 21
  • 1
  • 4
  • Could you create a minimal reproducible example? There must be something happening elsewhere in your code. Have you overwritten `range` perhaps? – FiddleStix Dec 13 '19 at 15:51
  • Sure, I actually changed it a little bit in the question to be more clear. The system I am trying to simulate is a cow milking barn (just to clarify the code a little bit). The cows change stations according to some probability matrix, in case you don't understand what it means, but I don't think the rest of my code causes this error. I am adding the rest of the code to the question since it is too long for a comment. – Can Evin Dec 13 '19 at 16:15

3 Answers3

1

If we dig into source of SimPy\envents.py (https://github.com/cristiklein/simpy/blob/9ac72fee4f079da331707bbdaf7e7cda929ded0b/src/simpy/events.py#L311), we will see following:

class Process(Event):
....
    def __init__(self, env, generator):
        if not hasattr(generator, 'throw'):
            # Implementation note: Python implementations differ in the
            # generator types they provide. Cython adds its own generator type
            # in addition to the CPython type, which renders a type check
            # impractical. To workaround this issue, we check for attribute
            # name instead of type and optimistically assume that all objects
            # with a ``throw`` attribute are generators (the more intuitive
            # name ``__next__`` cannot be used because it was renamed from
            # ``next`` in Python 2).
            # Remove this workaround if it causes issues in production!
            raise ValueError('%s is not a generator.' % generator)

It looks that this part of code may give errors as noted by developers. I cannot trace back when and what. Suggestion is to follow developers instructions and remove this workaround in your copy of SimPy (C:\Users\Can\Anaconda3\lib\site-packages\simpy\events.py)

MjH
  • 1,170
  • 1
  • 8
  • 16
1

Does your customer class have a env.process(<some customer process>) as part of its init method? If so then you do not need to call env.process(p) in your generator if not then you need to pass a process, not the object to env.process()

env.process(p.<some process>)

where <some process> is a generator that yields a event

Michael
  • 1,671
  • 2
  • 4
  • 8
0

By my understanding of SIMPY concepts, you should return something from the process like env.timeout(1) or env.exit()