cristiklein / simpy

MIT License
107 stars 16 forks source link

How to trigger env.timeout? #8

Closed jott123 closed 4 years ago

jott123 commented 4 years ago

Hello,

I'm trying to set up an environment with simpy but in combination with the package osbrain to work with agents. If I look into debugging the environment is set at default time 0 and can be printed. Now I want to let some time pass with env.timeout(4) in my process and then the parameter 'height' is send to another agent, but nothing happens to the time. Due to the documentation and examples I thought I need to yield my time, but if I do so, I get the error: AttributeError: 'Tree' object has no attribute 'height' and I have a problem with the environment and the information I want to send.

So, I'm not sure, if the env.timeout is triggered without yield and why is then a problem with my other parameters?

I have tried different possibilities like a inner function, a inner class, call a function, etc. and don't know how to solve it.


import simpy
from osbrain import run_agent
from osbrain import run_nameserver
from osbrain import Agent

class Tree(Agent):
    def on_init(self):

        self.height=30

        self.env = simpy.Environment()
        self.env.timeout(4)
        #yield self.env.timeout(4)
        print(self.env.now)

class Fruit(Agent):
    def on_init(self):
        self.height=[]

def sende_height(agent, value):
    agent.height = value
    agent.log_info('Height %s' % value)

if __name__ == '__main__':
    # Initialisation of the name Server and the agent
    ns = run_nameserver()
    baum1 = run_agent('TreeAgent_01', base=Tree)
    apple1 = run_agent('FruitAgent_01', base=Fruit)

    # Communication between the agents
    addr1 = baum1.bind('PUB', alias='kanal1')
    apple1.connect(addr1, handler=sende_height)

    baum1.send('kanal1', baum1.get_attr('height'))

    env = simpy.Environment()
    tree = Tree(env)
    fruit = Fruit(env)
    env.run(until=20)

    ns.shutdown()

I'm probably missing something obvious, but I have been stuck on it for awhile. Does anyone have any suggestions? Thanks so much!

cristiklein commented 4 years ago

Hello,

I am a bit unsure what you try to achieve, but this is how I would use osbrain with simpy:

import simpy
from osbrain import run_agent
from osbrain import run_nameserver
from osbrain import Agent

class Tree(Agent):
    def on_init(self):
        self.height=30

class Fruit(Agent):
    def on_init(self):
        self.height=[]

def sende_height(agent, value):
    agent.height = value
    agent.log_info('Height %s' % value)

def run_stuff(env):
    yield env.timeout(10)
    baum1.send('kanal1', baum1.get_attr('height'))
    yield env.timeout(10)
    baum1.send('kanal1', baum1.get_attr('height'))

if __name__ == '__main__':
    # Initialisation of the name Server and the agent
    ns = run_nameserver()
    baum1 = run_agent('TreeAgent_01', base=Tree)
    apple1 = run_agent('FruitAgent_01', base=Fruit)

    # Communication between the agents
    addr1 = baum1.bind('PUB', alias='kanal1')
    apple1.connect(addr1, handler=sende_height)

    env = simpy.Environment()

    env.process(run_stuff(env))

    env.run(until=30)

    ns.shutdown()

Rationale: simpy process are Python generator functions that need to yield special simpy objects. The generated simpy objects need to be captured by the process method. Osbrain's on_init is not supposed to be a generator and its output is not captured by simpy.

Let me know if this helps.

cristiklein commented 4 years ago

Hello,

I am a bit unsure what you try to achieve, but this is how I would use osbrain with simpy:

import simpy
from osbrain import run_agent
from osbrain import run_nameserver
from osbrain import Agent

class Tree(Agent):
    def on_init(self):
        self.height=30

class Fruit(Agent):
    def on_init(self):
        self.height=[]

def sende_height(agent, value):
    agent.height = value
    agent.log_info('Height %s' % value)

def run_stuff(env):
    yield env.timeout(10)
    baum1.send('kanal1', baum1.get_attr('height'))
    yield env.timeout(10)
    baum1.send('kanal1', baum1.get_attr('height'))

if __name__ == '__main__':
    # Initialisation of the name Server and the agent
    ns = run_nameserver()
    baum1 = run_agent('TreeAgent_01', base=Tree)
    apple1 = run_agent('FruitAgent_01', base=Fruit)

    # Communication between the agents
    addr1 = baum1.bind('PUB', alias='kanal1')
    apple1.connect(addr1, handler=sende_height)

    env = simpy.Environment()

    env.process(run_stuff(env))

    env.run(until=30)

    ns.shutdown()

Rationale: simpy process are Python generator functions that need to yield special simpy objects. The generated simpy objects need to be captured by the process method. Osbrain's on_init is not supposed to be a generator and its output is not captured by simpy.

Let me know if this helps.

jott123 commented 4 years ago

Thank you very much for the explanantion and example.

I thought I have to work in the 'main' part and had problems with functions I tried. As a beginner in Python it's a bit complicated with functions and generators.

Now it's working thanks to you, I also tried more tasks and yielding.

cristiklein commented 4 years ago

Glad I could help!