Allocation using PartitionedProcess

PartitionedProcess is the new base class for wcEcoli processes. Requester and Evolver run one after the other, with requester calling a partitioned process’ calculate_request and the evolving calling the evolve_state. Allocator is a process that reads the requests placed for all the processes, and allocates them for the next update.

PartitionedProcess, Requester, and Evolver can all be found in ecoli.processes.partition. Allocator can be found in ecoli.processes.allocator.

[1]:
# Make sure notebook runs out of vivarium-ecoli directory
import sys, os

# get the path to the notebook, and change working directory
notebook_path = sys.path[0][:sys.path[0].index('notebooks')]
sys.path.append(notebook_path)
os.chdir(sys.path[-1])
cwd = os.getcwd()

# print(cwd)
[2]:
import numpy as np

from vivarium.core.process import Process
from vivarium.core.store import Store
from vivarium.core.engine import Engine, pp
from vivarium.core.composer import Composite
from vivarium.core.composition import simulate_process, simulate_composite
from vivarium.plots.topology import plot_topology

from ecoli.processes.allocator import Allocator
from ecoli.processes.partition import PartitionedProcess, Evolver, Requester

process_row = 1.2
topology_settings = {
    'buffer': 1,
    'show_ports': False,
    'node_size': 10000,
    'dashed_edges': True,
    'node_distance': 4,
    'graph_format': 'hierarchy',
    'coordinates': {
        'example': (1,process_row),
        'Requester': (0,process_row),
        'Evolver': (3,process_row),
    }
}

Make a Partitioned Process

[3]:
MOLECULE_IDS = ['molecule_A']

class ExampleProcess(PartitionedProcess):
    name = 'example'
    topology = {'port': ('store',)}
    def ports_schema(self):
        return {
            'port': {
                mol_id: {
                    '_default': 100.,
                    '_properties': {'bulk': True}
                }
                for mol_id in MOLECULE_IDS}}
    def calculate_request(self, timestep, states):
        # request molecules
        return {
            'port': {
                mol_id: 10
                for mol_id in MOLECULE_IDS}}
    def evolve_state(self, timestep, states):
        allocated = states['port']
        # use all allocated molecules
        return {
            'port': allocated}
[4]:
example_1 = ExampleProcess()
process_topo_fig = plot_topology(example_1, topology_settings)
../_images/notebooks_allocation_processes_5_0.png

Make an Evolver for the Example PartitionedProcess

[5]:
evolver_1 = Evolver({'process': example_1})
evolver_topo_fig = plot_topology(evolver_1, topology_settings)
../_images/notebooks_allocation_processes_7_0.png

Make an Requester for the Example PartitionedProcess

[6]:
requester_1 = Requester({'process': example_1})
requester_topo_fig = plot_topology(requester_1, topology_settings)
../_images/notebooks_allocation_processes_9_0.png

Make a second partitioned process and an Allocator

This processes will be wired with the first through an Allocator. The allocator will read

[7]:
example_2 = ExampleProcess()
evolver_2 = Evolver({'process': example_2})
requester_2 = Requester({'process': example_2})

allocator_config = {
    'process_names': ['example_1', 'example_2'],
    'molecule_names': np.array(MOLECULE_IDS),
    'seed': 0,
    'custom_priorities': {
        'example_1': 1,
        'example_2': 2,
    }
}
allocator = Allocator(allocator_config)

Wire the requesters, evolvers, and allocator together in a Composite

[8]:
evolver_1.ports_schema()
[8]:
{'port': {'molecule_A': {'_default': 100.0, '_properties': {'bulk': True}}},
 'allocate': {'port': {'molecule_A': {'_default': 100.0,
    '_properties': {'bulk': True},
    '_updater': 'set',
    '_emit': False}}}}
[9]:
allocation_composite = Composite({
    'processes': {
        'evolver_1': evolver_1,
        'evolver_2': evolver_2,
        'requester_1': requester_1,
        'requester_2': requester_2,
        'allocator': allocator,
    },
    'topology': {
        'evolver_1': {
            'port': ('store1',),
            'allocate': {
                '_path': ('allocate','example_1'),
                'port': ('store1',)
            },
        },
        'evolver_2': {
            'port': ('store1',),
            'allocate': {
                '_path': ('allocate','example_2'),
                'port': ('store1',)
            },
        },
        'requester_1': {
            'port': ('store1',),
            'request': {
                '_path': ('request','example_1'),
                'port': ('store1',)
            },
        },
        'requester_2': {
            'port': ('store1',),
            'request': {
                '_path': ('request','example_2'),
                'port': ('store1',)
            },
        },
        'allocator': {
            'bulk': ('store1',),
            'allocate': ('allocate',),
            'request': ('request',)
        },
    }
})
[10]:
process_row = 1.2
store_row = 0
request_column = 0.7
allocate_column = 2.3
offset = 0.4
topology_settings = {
    'buffer': 1,
    'show_ports': False,
    'node_size': 10000,
    'dashed_edges': True,
    'node_distance': 4,
    'graph_format': 'hierarchy',
    'coordinates': {
        # Processes
        'requester_1': (0,process_row+1),
        'requester_2': (0,process_row),
        'evolver_1': (3,process_row+1),
        'evolver_2': (3,process_row),
        'allocator': (1.5,process_row-0.5),
        # Stores
        'store1': (1.5,process_row+0.5),
        'allocate': (allocate_column,store_row),
        'request': (request_column,store_row),
        'allocate\nexample_1': (allocate_column+offset,store_row-1),
        'allocate\nexample_2': (allocate_column-offset,store_row-1),
        'request\nexample_1': (request_column+offset,store_row-1),
        'request\nexample_2': (request_column-offset,store_row-1),
    },
    'remove_nodes': [
        'allocate\nexample_1\nstore1',
        'allocate\nexample_2\nstore1',
        'request\nexample_1\nstore1',
        'request\nexample_2\nstore1',
    ],
}
allocation_composite_topo_fig = plot_topology(allocation_composite, topology_settings)
../_images/notebooks_allocation_processes_15_0.png
[ ]: