Integrating a control mechanism

The scenario that we’re going to create in this last part of the tutorial will be similar to the one we created before but incorporate the control mechanism that we just created.

Again, we start by setting some configuration values and creating a simulation world:

# demo_2.py
import mosaik
import mosaik.util


# Sim config. and other parameters
SIM_CONFIG = {
    'ExampleSim': {
        'python': 'simulator_mosaik:ExampleSim',
    },
    'ExampleCtrl': {
        'python': 'controller:Controller',
    },
    'Collector': {
        'cmd': 'python collector.py %(addr)s',
    },
}
END = 10 * 60  # 10 minutes

# Create World
world = mosaik.World(SIM_CONFIG)

We added ExampleCtrl to the sim config and let all simulators be executed in-process with mosaik.

We can now start one instance of each simulator:

# Start simulators
examplesim = world.start('ExampleSim', eid_prefix='Model_')
examplectrl = world.start('ExampleCtrl')
collector = world.start('Collector', step_size=60)

We’ll create three model instances and one agent, and one database:

# Instantiate models
models = [examplesim.ExampleModel(init_val=i) for i in range(-2, 3, 2)]
agents = examplectrl.Agent.create(len(models))
monitor = collector.Monitor()

We use a list comprehension to create three model instances with individual initial values (-2, 0 and 2). For instantiating the same amount of agent instances we use create() which does the same as a list comprehension but is a bit shorter.

We finally connect each model to an agent (one-to-one):

# Connect entities
for model, agent in zip(models, agents):
    world.connect(model, agent, ('val', 'val_in'), async_requests=True)

The important thing here is the async_requests=True argument that we pass to connect(). This tells mosaik that our control mechanism may do async. requests (e.g., setting data to the models).

Finally, we can connect the models to the monitor and run the simulation:

mosaik.util.connect_many_to_one(world, models, monitor, 'val', 'delta')

# Run simulation
world.run(until=END)

In the output, you can clearly see the effect of our control mechanism:

Starting "ExampleSim" as "ExampleSim-0" ...
Starting "ExampleCtrl" as "ExampleCtrl-0" ...
Starting "Collector" as "Collector-0" ...
Starting simulation.
Progress: 3.33%
Progress: 6.67%
Progress: 10.00%
Progress: 13.33%
Progress: 16.67%
Progress: 20.00%
  - delta: [1, 1, 1, -1, -1, -1, -1, -1, -1, 1]
  - val: [1, 2, 3, 2, 1, 0, -1, -2, -3, -2]
- ExampleSim-0.Model_2:
  - delta: [1, -1, -1, -1, -1, -1, -1, 1, 1, 1]
  - val: [3, 2, 1, 0, -1, -2, -3, -2, -1, 0]

This is the complete scenario:

# demo_2.py
import mosaik
import mosaik.util


# Sim config. and other parameters
SIM_CONFIG = {
    'ExampleSim': {
        'python': 'simulator_mosaik:ExampleSim',
    },
    'ExampleCtrl': {
        'python': 'controller:Controller',
    },
    'Collector': {
        'cmd': 'python collector.py %(addr)s',
    },
}
END = 10 * 60  # 10 minutes

# Create World
world = mosaik.World(SIM_CONFIG)

# Start simulators
examplesim = world.start('ExampleSim', eid_prefix='Model_')
examplectrl = world.start('ExampleCtrl')
collector = world.start('Collector', step_size=60)

# Instantiate models
models = [examplesim.ExampleModel(init_val=i) for i in range(-2, 3, 2)]
agents = examplectrl.Agent.create(len(models))
monitor = collector.Monitor()

# Connect entities
for model, agent in zip(models, agents):
    world.connect(model, agent, ('val', 'val_in'), async_requests=True)

mosaik.util.connect_many_to_one(world, models, monitor, 'val', 'delta')

# Run simulation
world.run(until=END)

Congratulations, you have mastered the mosaik tutorial. The following sections provide a more detailed description of everything you learned so far.