process-bigraph 0.0.22__tar.gz → 0.0.23__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {process-bigraph-0.0.22/process_bigraph.egg-info → process-bigraph-0.0.23}/PKG-INFO +6 -1
- process-bigraph-0.0.23/process_bigraph/__init__.py +48 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/composite.py +283 -57
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/experiments/growth_division.py +3 -38
- process-bigraph-0.0.23/process_bigraph/experiments/minimal_gillespie.py +158 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/process_types.py +13 -1
- process-bigraph-0.0.23/process_bigraph/processes/__init__.py +18 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/processes/parameter_scan.py +3 -160
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/tests.py +307 -12
- {process-bigraph-0.0.22 → process-bigraph-0.0.23/process_bigraph.egg-info}/PKG-INFO +6 -1
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph.egg-info/SOURCES.txt +0 -11
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/setup.py +1 -1
- process-bigraph-0.0.22/.github/workflows/notebook_to_html.yml +0 -43
- process-bigraph-0.0.22/.github/workflows/pytest.yml +0 -35
- process-bigraph-0.0.22/.gitignore +0 -11
- process-bigraph-0.0.22/CLA.md +0 -113
- process-bigraph-0.0.22/CODE_OF_CONDUCT.md +0 -137
- process-bigraph-0.0.22/CONTRIBUTING.md +0 -44
- process-bigraph-0.0.22/doc/_static/process-bigraph.png +0 -0
- process-bigraph-0.0.22/notebooks/process-bigraphs.ipynb +0 -739
- process-bigraph-0.0.22/notebooks/visualize_processes.ipynb +0 -237
- process-bigraph-0.0.22/process_bigraph/__init__.py +0 -16
- process-bigraph-0.0.22/process_bigraph/experiments/minimal_gillespie.py +0 -321
- process-bigraph-0.0.22/process_bigraph/processes/__init__.py +0 -0
- process-bigraph-0.0.22/pytest.ini +0 -7
- process-bigraph-0.0.22/release.sh +0 -43
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/AUTHORS.md +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/LICENSE +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/README.md +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/experiments/__init__.py +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/protocols.py +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph.egg-info/dependency_links.txt +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph.egg-info/requires.txt +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph.egg-info/top_level.txt +0 -0
- {process-bigraph-0.0.22 → process-bigraph-0.0.23}/setup.cfg +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: process-bigraph
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.23
|
|
4
|
+
Summary: UNKNOWN
|
|
4
5
|
Home-page: https://github.com/vivarium-collective/process-bigraph
|
|
5
6
|
Author: Ryan Spangler, Eran Agmon
|
|
6
7
|
Author-email: ryan.spangler@gmail.com, agmon.eran@gmail.com
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Platform: UNKNOWN
|
|
7
10
|
Classifier: Development Status :: 3 - Alpha
|
|
8
11
|
Classifier: Intended Audience :: Developers
|
|
9
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -70,3 +73,5 @@ diagraph of a whole-cell E. coli model.
|
|
|
70
73
|
## License
|
|
71
74
|
|
|
72
75
|
Bigraph-schema is open-source software released under the [Apache 2 License](https://github.com/vivarium-collective/process-bigraph/blob/main/LICENSE).
|
|
76
|
+
|
|
77
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import pprint
|
|
2
|
+
from bigraph_schema.registry import deep_merge, default
|
|
3
|
+
from process_bigraph.processes import register_processes
|
|
4
|
+
from process_bigraph.composite import Process, Step, Composite, ProcessTypes, interval_time_precision
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
pretty = pprint.PrettyPrinter(indent=2)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def pp(x):
|
|
11
|
+
"""Print ``x`` in a pretty format."""
|
|
12
|
+
pretty.pprint(x)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def pf(x):
|
|
16
|
+
"""Format ``x`` for display."""
|
|
17
|
+
return pretty.pformat(x)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register_types(core):
|
|
21
|
+
core.register('default 1', {
|
|
22
|
+
'_inherit': 'float',
|
|
23
|
+
'_default': 1.0})
|
|
24
|
+
|
|
25
|
+
core.register('species_dependent_process', {
|
|
26
|
+
'_inherit': ['process'],
|
|
27
|
+
'_inputs': {
|
|
28
|
+
'species': {
|
|
29
|
+
'_type': 'array',
|
|
30
|
+
'_data': 'float'}},
|
|
31
|
+
'_outputs': {
|
|
32
|
+
'species': {
|
|
33
|
+
'_type': 'array',
|
|
34
|
+
'_data': 'float'}}})
|
|
35
|
+
|
|
36
|
+
core.register('ode_config', {
|
|
37
|
+
'stoichiometry': {
|
|
38
|
+
'_type': 'array',
|
|
39
|
+
'_data': 'integer'},
|
|
40
|
+
'rates': 'map[float]',
|
|
41
|
+
'species': 'map[float]'})
|
|
42
|
+
|
|
43
|
+
core = register_processes(
|
|
44
|
+
core)
|
|
45
|
+
|
|
46
|
+
return core
|
|
47
|
+
|
|
48
|
+
|
|
@@ -10,9 +10,8 @@ import math
|
|
|
10
10
|
import collections
|
|
11
11
|
from typing import Dict
|
|
12
12
|
|
|
13
|
-
from bigraph_schema import Edge, TypeSystem, get_path, set_path, deep_merge, is_schema_key, strip_schema_keys, Registry, hierarchy_depth
|
|
13
|
+
from bigraph_schema import Edge, TypeSystem, get_path, set_path, deep_merge, is_schema_key, strip_schema_keys, Registry, hierarchy_depth, visit_method
|
|
14
14
|
|
|
15
|
-
from process_bigraph.process_types import process_types
|
|
16
15
|
from process_bigraph.protocols import local_lookup, local_lookup_module
|
|
17
16
|
|
|
18
17
|
|
|
@@ -23,22 +22,227 @@ def assert_interface(interface: Dict):
|
|
|
23
22
|
assert existing_keys == set(required_keys), f"every interface requires an inputs schema and an outputs schema, not {existing_keys}"
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
def
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return core
|
|
25
|
+
def apply_process(schema, current, update, core):
|
|
26
|
+
"""Apply an update to a process."""
|
|
27
|
+
process_schema = schema.copy()
|
|
28
|
+
process_schema.pop('_apply')
|
|
29
|
+
return core.apply(
|
|
30
|
+
process_schema,
|
|
31
|
+
current,
|
|
32
|
+
update)
|
|
31
33
|
|
|
32
34
|
|
|
33
|
-
def
|
|
34
|
-
"""
|
|
35
|
-
|
|
35
|
+
def check_process(schema, state, core):
|
|
36
|
+
"""Check if this is a process."""
|
|
37
|
+
return 'instance' in state and isinstance(
|
|
38
|
+
state['instance'],
|
|
39
|
+
Edge)
|
|
36
40
|
|
|
37
41
|
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
def fold_visit(schema, state, method, values, core):
|
|
43
|
+
visit = visit_method(
|
|
44
|
+
schema,
|
|
45
|
+
state,
|
|
46
|
+
method,
|
|
47
|
+
values,
|
|
48
|
+
core)
|
|
49
|
+
|
|
50
|
+
return visit
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def divide_process(schema, state, values, core):
|
|
54
|
+
# daughter_configs must have a config per daughter
|
|
55
|
+
|
|
56
|
+
daughter_configs = values.get(
|
|
57
|
+
'daughter_configs',
|
|
58
|
+
[{} for index in range(values['divisions'])])
|
|
59
|
+
|
|
60
|
+
if 'config' not in state:
|
|
61
|
+
return daughter_configs
|
|
62
|
+
|
|
63
|
+
existing_config = state['config']
|
|
64
|
+
|
|
65
|
+
divisions = []
|
|
66
|
+
for index in range(values['divisions']):
|
|
67
|
+
daughter_config = copy.deepcopy(
|
|
68
|
+
existing_config)
|
|
69
|
+
daughter_config = deep_merge(
|
|
70
|
+
daughter_config,
|
|
71
|
+
daughter_configs[index])
|
|
72
|
+
|
|
73
|
+
# TODO: provide a way to override inputs and outputs
|
|
74
|
+
daughter_state = {
|
|
75
|
+
'address': state['address'],
|
|
76
|
+
'config': daughter_config,
|
|
77
|
+
'inputs': copy.deepcopy(state['inputs']),
|
|
78
|
+
'outputs': copy.deepcopy(state['outputs'])}
|
|
79
|
+
|
|
80
|
+
if 'interval' in state:
|
|
81
|
+
daughter_state['interval'] = state['interval']
|
|
82
|
+
|
|
83
|
+
divisions.append(daughter_state)
|
|
84
|
+
|
|
85
|
+
return divisions
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def serialize_process(schema, value, core):
|
|
89
|
+
"""Serialize a process to a JSON-safe representation."""
|
|
90
|
+
# TODO -- need to get back the protocol: address and the config
|
|
91
|
+
process = value.copy()
|
|
92
|
+
process['config'] = core.serialize(
|
|
93
|
+
process['instance'].config_schema,
|
|
94
|
+
process['config'])
|
|
95
|
+
del process['instance']
|
|
96
|
+
return process
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def deserialize_process(schema, encoded, core):
|
|
100
|
+
"""Deserialize a process from a serialized state.
|
|
101
|
+
|
|
102
|
+
This function is used by the type system to deserialize a process.
|
|
103
|
+
|
|
104
|
+
:param encoded: A JSON-safe representation of the process.
|
|
105
|
+
:param bindings: The bindings to use for deserialization.
|
|
106
|
+
:param core: The type system to use for deserialization.
|
|
107
|
+
|
|
108
|
+
:returns: The deserialized state with an instantiated process.
|
|
109
|
+
"""
|
|
110
|
+
encoded = encoded or {}
|
|
111
|
+
schema = schema or {}
|
|
112
|
+
|
|
113
|
+
if not encoded:
|
|
114
|
+
deserialized = core.default(schema)
|
|
115
|
+
else:
|
|
116
|
+
deserialized = encoded.copy()
|
|
117
|
+
|
|
118
|
+
if not deserialized.get('address'):
|
|
119
|
+
return deserialized
|
|
120
|
+
|
|
121
|
+
protocol, address = deserialized['address'].split(':', 1)
|
|
122
|
+
|
|
123
|
+
if 'instance' in deserialized:
|
|
124
|
+
instantiate = type(deserialized['instance'])
|
|
125
|
+
else:
|
|
126
|
+
process_lookup = core.protocol_registry.access(protocol)
|
|
127
|
+
if not process_lookup:
|
|
128
|
+
raise Exception(f'protocol "{protocol}" not implemented')
|
|
129
|
+
|
|
130
|
+
instantiate = process_lookup(core, address)
|
|
131
|
+
if not instantiate:
|
|
132
|
+
raise Exception(f'process "{address}" not found')
|
|
133
|
+
|
|
134
|
+
config = core.deserialize(
|
|
135
|
+
instantiate.config_schema,
|
|
136
|
+
deserialized.get('config', {}))
|
|
137
|
+
|
|
138
|
+
interval = core.deserialize(
|
|
139
|
+
'interval',
|
|
140
|
+
deserialized.get('interval'))
|
|
141
|
+
|
|
142
|
+
if interval is None:
|
|
143
|
+
interval = core.default(
|
|
144
|
+
schema.get(
|
|
145
|
+
'interval',
|
|
146
|
+
'interval'))
|
|
147
|
+
|
|
148
|
+
if not 'instance' in deserialized:
|
|
149
|
+
process = instantiate(
|
|
150
|
+
config,
|
|
151
|
+
core=core)
|
|
152
|
+
|
|
153
|
+
deserialized['instance'] = process
|
|
154
|
+
|
|
155
|
+
deserialized['config'] = config
|
|
156
|
+
deserialized['interval'] = interval
|
|
157
|
+
deserialized['_inputs'] = deserialized['instance'].inputs()
|
|
158
|
+
deserialized['_outputs'] = deserialized['instance'].outputs()
|
|
159
|
+
|
|
160
|
+
return deserialized
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def deserialize_step(schema, encoded, core):
|
|
164
|
+
if not encoded:
|
|
165
|
+
deserialized = core.default(schema)
|
|
166
|
+
else:
|
|
167
|
+
deserialized = encoded.copy()
|
|
168
|
+
|
|
169
|
+
if not deserialized['address']:
|
|
170
|
+
return deserialized
|
|
171
|
+
|
|
172
|
+
protocol, address = deserialized['address'].split(':', 1)
|
|
173
|
+
|
|
174
|
+
if 'instance' in deserialized:
|
|
175
|
+
instantiate = type(deserialized['instance'])
|
|
176
|
+
else:
|
|
177
|
+
process_lookup = core.protocol_registry.access(protocol)
|
|
178
|
+
if not process_lookup:
|
|
179
|
+
raise Exception(f'protocol "{protocol}" not implemented')
|
|
180
|
+
|
|
181
|
+
instantiate = process_lookup(core, address)
|
|
182
|
+
if not instantiate:
|
|
183
|
+
raise Exception(f'process "{address}" not found')
|
|
184
|
+
|
|
185
|
+
config = core.deserialize(
|
|
186
|
+
instantiate.config_schema,
|
|
187
|
+
deserialized.get('config', {}))
|
|
188
|
+
|
|
189
|
+
if not 'instance' in deserialized:
|
|
190
|
+
process = instantiate(config, core=core)
|
|
191
|
+
deserialized['instance'] = process
|
|
192
|
+
|
|
193
|
+
deserialized['config'] = config
|
|
194
|
+
deserialized['_inputs'] = deserialized['instance'].inputs()
|
|
195
|
+
deserialized['_outputs'] = deserialized['instance'].outputs()
|
|
196
|
+
|
|
197
|
+
return deserialized
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
PROCESS_TYPES = {
|
|
201
|
+
'protocol': {
|
|
202
|
+
'_type': 'protocol',
|
|
203
|
+
'_inherit': 'string'},
|
|
204
|
+
|
|
205
|
+
'emitter_mode': 'enum[none,all,stores,bridge,paths,ports]',
|
|
206
|
+
|
|
207
|
+
'interval': {
|
|
208
|
+
'_type': 'interval',
|
|
209
|
+
'_inherit': 'float',
|
|
210
|
+
'_apply': 'set',
|
|
211
|
+
'_default': '1.0'},
|
|
212
|
+
|
|
213
|
+
'step': {
|
|
214
|
+
'_type': 'step',
|
|
215
|
+
'_inherit': 'edge',
|
|
216
|
+
'_apply': apply_process,
|
|
217
|
+
'_serialize': serialize_process,
|
|
218
|
+
'_deserialize': deserialize_step,
|
|
219
|
+
'_check': check_process,
|
|
220
|
+
'_fold': fold_visit,
|
|
221
|
+
'_divide': divide_process,
|
|
222
|
+
'_description': '',
|
|
223
|
+
# TODO: support reference to type parameters from other states
|
|
224
|
+
'address': 'protocol',
|
|
225
|
+
'config': 'quote'},
|
|
226
|
+
|
|
227
|
+
# TODO: slice process to allow for navigating through a port
|
|
228
|
+
'process': {
|
|
229
|
+
'_type': 'process',
|
|
230
|
+
'_inherit': 'edge',
|
|
231
|
+
'_apply': apply_process,
|
|
232
|
+
'_serialize': serialize_process,
|
|
233
|
+
'_deserialize': deserialize_process,
|
|
234
|
+
'_check': check_process,
|
|
235
|
+
'_fold': fold_visit,
|
|
236
|
+
'_divide': divide_process,
|
|
237
|
+
'_description': '',
|
|
238
|
+
# TODO: support reference to type parameters from other states
|
|
239
|
+
'interval': 'interval',
|
|
240
|
+
'address': 'protocol',
|
|
241
|
+
'config': 'quote'}}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
BASE_PROTOCOLS = {
|
|
245
|
+
'local': local_lookup}
|
|
42
246
|
|
|
43
247
|
|
|
44
248
|
class ProcessTypes(TypeSystem):
|
|
@@ -53,13 +257,18 @@ class ProcessTypes(TypeSystem):
|
|
|
53
257
|
self.process_registry = Registry()
|
|
54
258
|
self.protocol_registry = Registry()
|
|
55
259
|
|
|
56
|
-
|
|
57
|
-
register_protocols(
|
|
58
|
-
|
|
260
|
+
self.register_types(PROCESS_TYPES)
|
|
261
|
+
self.register_protocols(BASE_PROTOCOLS)
|
|
262
|
+
self.register_processes(BASE_EMITTERS)
|
|
59
263
|
|
|
60
264
|
self.register_process('composite', Composite)
|
|
61
265
|
|
|
62
266
|
|
|
267
|
+
def register_protocols(self, protocols):
|
|
268
|
+
"""Register protocols with the core"""
|
|
269
|
+
self.protocol_registry.register_multiple(protocols)
|
|
270
|
+
|
|
271
|
+
|
|
63
272
|
def register_process(
|
|
64
273
|
self,
|
|
65
274
|
name,
|
|
@@ -75,6 +284,13 @@ class ProcessTypes(TypeSystem):
|
|
|
75
284
|
self.process_registry.register(name, process_data)
|
|
76
285
|
|
|
77
286
|
|
|
287
|
+
def register_processes(self, processes):
|
|
288
|
+
for process_key, process_data in processes.items():
|
|
289
|
+
self.register_process(
|
|
290
|
+
process_key,
|
|
291
|
+
process_data)
|
|
292
|
+
|
|
293
|
+
|
|
78
294
|
def initialize_edge_state(self, schema, path, edge):
|
|
79
295
|
"""
|
|
80
296
|
Initialize the state for an edge based on the schema and the edge.
|
|
@@ -181,10 +397,10 @@ class Process(Edge):
|
|
|
181
397
|
if config is None:
|
|
182
398
|
config = {}
|
|
183
399
|
|
|
184
|
-
# check that all keywords in config are in config_schema
|
|
185
|
-
for key in config.keys():
|
|
186
|
-
|
|
187
|
-
|
|
400
|
+
# # check that all keywords in config are in config_schema
|
|
401
|
+
# for key in config.keys():
|
|
402
|
+
# if key not in self.config_schema:
|
|
403
|
+
# raise Exception(f'config key {key} not in config_schema for {self.__class__.__name__}')
|
|
188
404
|
|
|
189
405
|
# fill in defaults for config
|
|
190
406
|
self.config = self.core.fill(
|
|
@@ -339,7 +555,9 @@ def find_leaves(tree_structure, path=None):
|
|
|
339
555
|
leaves = []
|
|
340
556
|
path = ()
|
|
341
557
|
|
|
342
|
-
if
|
|
558
|
+
if tree_structure is None:
|
|
559
|
+
pass
|
|
560
|
+
elif isinstance(tree_structure, list):
|
|
343
561
|
leaves = tree_structure
|
|
344
562
|
elif isinstance(tree_structure, tuple):
|
|
345
563
|
leaves.append(tree_structure)
|
|
@@ -519,18 +737,18 @@ class Composite(Process):
|
|
|
519
737
|
if 'global_time' not in initial_state:
|
|
520
738
|
initial_state['global_time'] = 0.0
|
|
521
739
|
|
|
522
|
-
composition, state = self.core.
|
|
740
|
+
self.composition, self.state = self.core.generate(
|
|
523
741
|
initial_composition,
|
|
524
742
|
initial_state)
|
|
525
743
|
|
|
526
|
-
self.composition = copy.deepcopy(
|
|
527
|
-
|
|
744
|
+
# self.composition = copy.deepcopy(
|
|
745
|
+
# self.core.access(composition))
|
|
528
746
|
|
|
529
747
|
# TODO: add flag to self.core.access(copy=True)
|
|
530
748
|
self.bridge = self.config.get('bridge', {})
|
|
531
749
|
|
|
532
750
|
self.find_instance_paths(
|
|
533
|
-
state)
|
|
751
|
+
self.state)
|
|
534
752
|
|
|
535
753
|
# merge the processes and steps into a single "edges" dict
|
|
536
754
|
self.edge_paths = self.process_paths.copy()
|
|
@@ -553,11 +771,13 @@ class Composite(Process):
|
|
|
553
771
|
raise Exception(
|
|
554
772
|
f'initial state from edge does not match initial state from other edges:\n{path}\n{edge}\n{edge_state}')
|
|
555
773
|
|
|
556
|
-
state = deep_merge(
|
|
774
|
+
self.state = deep_merge(
|
|
775
|
+
self.state,
|
|
776
|
+
edge_state)
|
|
557
777
|
|
|
558
|
-
self.state = self.core.deserialize(
|
|
559
|
-
|
|
560
|
-
|
|
778
|
+
# self.state = self.core.deserialize(
|
|
779
|
+
# self.composition,
|
|
780
|
+
# self.state)
|
|
561
781
|
|
|
562
782
|
# TODO: call validate on this composite, not just check
|
|
563
783
|
# assert self.core.validate(
|
|
@@ -603,6 +823,7 @@ class Composite(Process):
|
|
|
603
823
|
|
|
604
824
|
# self.run_steps(self.to_run)
|
|
605
825
|
|
|
826
|
+
|
|
606
827
|
def save(self,
|
|
607
828
|
filename='composite.json',
|
|
608
829
|
outdir='out',
|
|
@@ -729,7 +950,11 @@ class Composite(Process):
|
|
|
729
950
|
step_config = self.read_emitter_config(emitter_config)
|
|
730
951
|
emitter = set_path(
|
|
731
952
|
{}, path, step_config)
|
|
732
|
-
|
|
953
|
+
|
|
954
|
+
self.merge(
|
|
955
|
+
{},
|
|
956
|
+
emitter)
|
|
957
|
+
|
|
733
958
|
_, instance = self.core.slice(
|
|
734
959
|
self.composition,
|
|
735
960
|
self.state,
|
|
@@ -739,19 +964,14 @@ class Composite(Process):
|
|
|
739
964
|
self.step_paths[path] = instance
|
|
740
965
|
|
|
741
966
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
# the new schema
|
|
746
|
-
def merge(self, initial_state):
|
|
747
|
-
self.state = self.core.merge(
|
|
967
|
+
def merge(self, schema, state, path=None):
|
|
968
|
+
path = path or []
|
|
969
|
+
self.composition, self.state = self.core.merge(
|
|
748
970
|
self.composition,
|
|
749
971
|
self.state,
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
self.composition,
|
|
754
|
-
self.state)
|
|
972
|
+
path,
|
|
973
|
+
schema,
|
|
974
|
+
state)
|
|
755
975
|
|
|
756
976
|
|
|
757
977
|
def process_update(
|
|
@@ -1001,23 +1221,23 @@ class Composite(Process):
|
|
|
1001
1221
|
force_complete = False
|
|
1002
1222
|
|
|
1003
1223
|
|
|
1004
|
-
def determine_steps(self):
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1224
|
+
# def determine_steps(self):
|
|
1225
|
+
# to_run = []
|
|
1226
|
+
# for step_key, wires in trigger_state['steps']:
|
|
1227
|
+
# fulfilled = True
|
|
1228
|
+
# for input in wires['input_paths']:
|
|
1229
|
+
# if len(trigger_state['states'][tuple(input)]) > 0:
|
|
1230
|
+
# fulfilled = False
|
|
1231
|
+
# break
|
|
1232
|
+
# if fulfilled:
|
|
1233
|
+
# to_run.append(step_key)
|
|
1014
1234
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1235
|
+
# for step_key in to_run:
|
|
1236
|
+
# wires = trigger_state['steps'][step_key]
|
|
1237
|
+
# for output in wires['output_paths']:
|
|
1238
|
+
# trigger_state['states'][tuple(output)].remove(step_key)
|
|
1019
1239
|
|
|
1020
|
-
|
|
1240
|
+
# return to_run, trigger_state
|
|
1021
1241
|
|
|
1022
1242
|
|
|
1023
1243
|
def run_steps(self, step_paths):
|
|
@@ -1106,6 +1326,7 @@ class Composite(Process):
|
|
|
1106
1326
|
state)
|
|
1107
1327
|
|
|
1108
1328
|
self.merge(
|
|
1329
|
+
{},
|
|
1109
1330
|
projection)
|
|
1110
1331
|
|
|
1111
1332
|
self.run(interval)
|
|
@@ -1183,6 +1404,11 @@ class RAMEmitter(Emitter):
|
|
|
1183
1404
|
return result
|
|
1184
1405
|
|
|
1185
1406
|
|
|
1407
|
+
BASE_EMITTERS = {
|
|
1408
|
+
'console-emitter': ConsoleEmitter,
|
|
1409
|
+
'ram-emitter': RAMEmitter}
|
|
1410
|
+
|
|
1411
|
+
|
|
1186
1412
|
# def StateEmitter(Emitter):
|
|
1187
1413
|
|
|
1188
1414
|
|
{process-bigraph-0.0.22 → process-bigraph-0.0.23}/process_bigraph/experiments/growth_division.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pytest
|
|
2
|
-
from process_bigraph import Step, Process, Composite, ProcessTypes, interval_time_precision, deep_merge
|
|
2
|
+
from process_bigraph.composite import Step, Process, Composite, ProcessTypes, interval_time_precision, deep_merge
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class Grow(Process):
|
|
@@ -92,6 +92,7 @@ def generate_bridge(schema, state, interval=1.0):
|
|
|
92
92
|
for port in ['inputs', 'outputs']}
|
|
93
93
|
|
|
94
94
|
config = {
|
|
95
|
+
'_type': 'quote',
|
|
95
96
|
'state': state,
|
|
96
97
|
'bridge': bridge}
|
|
97
98
|
|
|
@@ -160,7 +161,7 @@ def grow_divide_agent(config=None, state=None, path=None):
|
|
|
160
161
|
state)
|
|
161
162
|
|
|
162
163
|
composite = generate_bridge({
|
|
163
|
-
'inputs': {},
|
|
164
|
+
'inputs': {'mass': ['mass']},
|
|
164
165
|
'outputs': agent_schema},
|
|
165
166
|
grow_divide_state)
|
|
166
167
|
|
|
@@ -170,39 +171,3 @@ def grow_divide_agent(config=None, state=None, path=None):
|
|
|
170
171
|
return composite
|
|
171
172
|
|
|
172
173
|
|
|
173
|
-
def test_grow_divide(core):
|
|
174
|
-
initial_mass = 1.0
|
|
175
|
-
|
|
176
|
-
grow_divide = grow_divide_agent(
|
|
177
|
-
{'grow': {'rate': 0.03}},
|
|
178
|
-
{'mass': initial_mass},
|
|
179
|
-
['environment', '0'])
|
|
180
|
-
|
|
181
|
-
environment = {
|
|
182
|
-
'environment': {
|
|
183
|
-
'0': {
|
|
184
|
-
'mass': initial_mass,
|
|
185
|
-
'grow_divide': grow_divide}}}
|
|
186
|
-
|
|
187
|
-
composite = Composite({
|
|
188
|
-
'state': environment},
|
|
189
|
-
core=core)
|
|
190
|
-
|
|
191
|
-
updates = composite.update({}, 100.0)
|
|
192
|
-
assert '0_0_0_0_0' in composite.state['environment']
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
@pytest.fixture
|
|
196
|
-
def core():
|
|
197
|
-
core = ProcessTypes()
|
|
198
|
-
core.register_process('grow', Grow)
|
|
199
|
-
core.register_process('divide', Divide)
|
|
200
|
-
return core
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if __name__ == '__main__':
|
|
204
|
-
core = ProcessTypes()
|
|
205
|
-
core.register_process('grow', Grow)
|
|
206
|
-
core.register_process('divide', Divide)
|
|
207
|
-
|
|
208
|
-
test_grow_divide(core)
|