process-bigraph 0.0.1__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.
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.1
2
+ Name: process-bigraph
3
+ Version: 0.0.1
4
+ Summary: UNKNOWN
5
+ Home-page: https://github.com/vivarium-collective/process-bigraph
6
+ Author: Ryan Spangler, Eran Agmon
7
+ Author-email: ryan.spangler@gmail.com, agmon.eran@gmail.com
8
+ License: UNKNOWN
9
+ Platform: UNKNOWN
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.6
17
+ Classifier: Programming Language :: Python :: 3.7
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Requires-Python: >=3.6
23
+ Description-Content-Type: text/markdown
24
+
25
+ # Process-Bigraph
26
+
27
+ **Process-Bigraph** is...
28
+
29
+ <p align="center">
30
+ <img src="https://github.com/vivarium-collective/bigraph-viz/blob/main/doc/_static/cell_structure_function.png?raw=true" width="600" alt="Bigraph-viz example">
31
+ </p>
32
+
33
+ ## What are Process Bigraphs?
34
+
35
+ ## Getting Started
36
+
37
+ ### Installation
38
+
39
+ You can install `process-bigraph` using pip:
40
+
41
+ ```console
42
+ pip install process-bigraph
43
+ ```
44
+
45
+ ## Tutorial
46
+
47
+ To get started with Process-Bigraph, explore the *tutorial*. coming soon...
48
+
49
+
@@ -0,0 +1,23 @@
1
+ # Process-Bigraph
2
+
3
+ **Process-Bigraph** is...
4
+
5
+ <p align="center">
6
+ <img src="https://github.com/vivarium-collective/bigraph-viz/blob/main/doc/_static/cell_structure_function.png?raw=true" width="600" alt="Bigraph-viz example">
7
+ </p>
8
+
9
+ ## What are Process Bigraphs?
10
+
11
+ ## Getting Started
12
+
13
+ ### Installation
14
+
15
+ You can install `process-bigraph` using pip:
16
+
17
+ ```console
18
+ pip install process-bigraph
19
+ ```
20
+
21
+ ## Tutorial
22
+
23
+ To get started with Process-Bigraph, explore the *tutorial*. coming soon...
File without changes
@@ -0,0 +1,296 @@
1
+ import abc
2
+ from bigraph_schema import fill, registry_registry, type_registry, apply_update
3
+
4
+
5
+ def hierarchy_depth(hierarchy, path=()):
6
+ """
7
+ Create a mapping of every path in the hierarchy to the node living at
8
+ that path in the hierarchy.
9
+ """
10
+
11
+ base = {}
12
+
13
+ for key, inner in hierarchy.items():
14
+ down = tuple(path + (key,))
15
+ if isinstance(inner, dict):
16
+ base.update(hierarchy_depth(inner, down))
17
+ else:
18
+ base[down] = inner
19
+
20
+ return base
21
+
22
+
23
+ def find_processes(state):
24
+ found = {}
25
+
26
+ for key, inner in state.items():
27
+ if isinstance(inner, Process):
28
+ found[key] = inner
29
+ elif isinstance(inner, dict):
30
+ result = find_processes(inner)
31
+ if result:
32
+ found[key] = result
33
+
34
+ return found
35
+
36
+
37
+ def find_process_paths(state):
38
+ processes = find_processes(state)
39
+ return hierarchy_depth(processes)
40
+
41
+
42
+ def empty_front(time):
43
+ return {
44
+ 'time': time,
45
+ 'update': {}
46
+ }
47
+
48
+ # deal with steps vs temporal process vs edges
49
+
50
+ class Process:
51
+ config_schema = {}
52
+
53
+ def __init__(self, config=None):
54
+ if config is None:
55
+ config = {}
56
+
57
+ self.config_schema.setdefault(
58
+ 'timestep',
59
+ {'_type': 'float', '_default': '1.0'}
60
+ )
61
+
62
+ self.config = fill(
63
+ self.config_schema,
64
+ config
65
+ )
66
+
67
+ @abc.abstractmethod
68
+ def schema(self):
69
+ return {}
70
+
71
+ def calculate_timestep(self, state):
72
+ return self.config['timestep']
73
+
74
+ @abc.abstractmethod
75
+ def update(self, state, interval):
76
+ return {}
77
+
78
+ # TODO: should we include run(interval) here?
79
+ # process would have to maintain state
80
+
81
+
82
+ class Composite(Process):
83
+ config_schema = {
84
+ 'schema': 'tree[any]',
85
+ 'bridge': 'wires',
86
+ 'instance': 'tree[any]',
87
+ 'initial_time': 'float',
88
+ 'global_time_precision': 'maybe[float]',
89
+ }
90
+
91
+ def __init__(self, config=None):
92
+ super().__init__(config)
93
+ self.global_time = self.config['initial_time']
94
+ self.state = fill(
95
+ self.config['schema'],
96
+ self.config['instance']
97
+ )
98
+ self.process_paths = find_process_paths(state)
99
+ self.front: Dict = {
100
+ path: empty_front(self.global_time)
101
+ for path in self.process_paths
102
+ }
103
+ self.global_time_precision = self.config['global_time_precision']
104
+
105
+ def schema(self):
106
+ return self.config['schema']
107
+
108
+ def run_process(self, path, process):
109
+ if path not in self.front:
110
+ self.front[path] = empty_front(self.global_time)
111
+ process_time = self.front[path]['time']
112
+ if process_time <= self.global_time:
113
+ if self.front[path].get('future'):
114
+ future_front = self.front[path]['future']
115
+ process_timestep = future_front['timestep']
116
+ store = future_front['store']
117
+ state = future_front['state']
118
+ del self.front[path]['future']
119
+ else:
120
+ # get the time step
121
+ store, state = self._process_state(path)
122
+ process_timestep = process.calculate_timestep(state)
123
+
124
+ if force_complete:
125
+ # force the process to complete at end_time
126
+ future = min(process_time + process_timestep, end_time)
127
+ else:
128
+ future = process_time + process_timestep
129
+ if self.global_time_precision is not None:
130
+ # set future time based on global_time_precision
131
+ future = round(future, self.global_time_precision)
132
+
133
+ if future <= end_time:
134
+
135
+ update = self._process_update(
136
+ path,
137
+ process,
138
+ store,
139
+ state,
140
+ process_timestep
141
+ )
142
+
143
+ # update front, to be applied at its projected time
144
+ self.front[path]['time'] = future
145
+ self.front[path]['update'] = update
146
+
147
+ # absolute timestep
148
+ timestep = future - self.global_time
149
+ if timestep < full_step:
150
+ full_step = timestep
151
+ else:
152
+ # absolute timestep
153
+ timestep = future - self.global_time
154
+ if timestep < full_step:
155
+ full_step = timestep
156
+
157
+ else:
158
+ # don't shoot past processes that didn't run this time
159
+ process_delay = process_time - self.global_time
160
+ if process_delay < full_step:
161
+ full_step = process_delay
162
+
163
+ return full_step
164
+
165
+ def run(self, interval, force_complete=False):
166
+ end_time = self.global_time + interval
167
+ while self.global_time < end_time or force_complete:
168
+ full_step = math.inf
169
+ for path, process in self.process_paths.items():
170
+ full_step = self.run_process(process, path)
171
+
172
+ # apply updates based on process times in self.front
173
+ if full_step == math.inf:
174
+ # no processes ran, jump to next process
175
+ next_event = end_time
176
+ for path in self.front.keys():
177
+ if self.front[path]['time'] < next_event:
178
+ next_event = self.front[path]['time']
179
+ self.global_time = next_event
180
+
181
+ elif self.global_time + full_step <= end_time:
182
+ # at least one process ran within the interval
183
+ # increase the time, apply updates, and continue
184
+ self.global_time += full_step
185
+
186
+ # advance all quiet processes to current time
187
+ for quiet in quiet_paths:
188
+ self.front[quiet]['time'] = self.global_time
189
+
190
+ # apply updates that are behind global time
191
+ updates = []
192
+ paths = []
193
+ for path, advance in self.front.items():
194
+ if advance['time'] <= self.global_time \
195
+ and advance['update']:
196
+ new_update = advance['update']
197
+ updates.append(new_update)
198
+ advance['update'] = {}
199
+ paths.append(path)
200
+
201
+ self._send_updates(updates)
202
+
203
+ # display and emit
204
+ if self.progress_bar:
205
+ print_progress_bar(self.global_time, end_time)
206
+ if self.emit_step == 1:
207
+ self._emit_store_data()
208
+ elif emit_time <= self.global_time:
209
+ while emit_time <= self.global_time:
210
+ self._emit_store_data()
211
+ emit_time += self.emit_step
212
+
213
+ else:
214
+ # all processes have run past the interval
215
+ self.global_time = end_time
216
+
217
+ if force_complete and self.global_time == end_time:
218
+ force_complete = False
219
+
220
+ def update(self, state, interval):
221
+ # do everything
222
+
223
+ # this needs to go through the bridge
224
+ self.state = apply_update(
225
+ self.schema,
226
+ self.state,
227
+ state
228
+ )
229
+
230
+ self.run(interval)
231
+
232
+ # pull the update out of the state and return it
233
+
234
+
235
+ class IncreaseProcess(Process):
236
+ config_schema = {
237
+ 'rate': {
238
+ '_type': 'float',
239
+ '_default': '0.1',
240
+ }
241
+ }
242
+
243
+ def __init__(self, config=None):
244
+ super().__init__(config)
245
+
246
+ def schema(self):
247
+ return {
248
+ 'level': 'float',
249
+ }
250
+
251
+ def update(self, state, interval):
252
+ return {
253
+ 'level': state['level'] * self.config['rate']
254
+ }
255
+
256
+
257
+ def test_process():
258
+ process = IncreaseProcess({'rate': 0.2})
259
+ schema = process.schema()
260
+ state = fill(schema)
261
+ update = process.update({'level': 5.5}, 1.0)
262
+ new_state = apply_update(schema, state, update)
263
+ assert new_state['level'] == 1.1
264
+
265
+
266
+ {"level":"float","down":{"a":"int"}}
267
+
268
+ def test_composite():
269
+ # TODO: add support for the various vivarium emitters
270
+
271
+ increase = IncreaseProcess({'rate': 0.3})
272
+ composite = Composite({
273
+ 'schema': {
274
+ 'increase': 'process[level:float]',
275
+ # 'increase': 'process[{"level":"float","down":{"a":"int"}}]',
276
+ 'value': 'float',
277
+ },
278
+ 'bridge': {
279
+ 'exchange': 'value'
280
+ },
281
+ 'instance': {
282
+ 'increase': increase,
283
+ 'wires': {
284
+ 'level': 'value'
285
+ },
286
+ 'value': 11.11,
287
+ },
288
+ })
289
+
290
+ composite.update({'exchange': 3.33}, 10.0)
291
+ import ipdb; ipdb.set_trace()
292
+
293
+
294
+ if __name__ == '__main__':
295
+ test_process()
296
+ test_composite()
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.1
2
+ Name: process-bigraph
3
+ Version: 0.0.1
4
+ Summary: UNKNOWN
5
+ Home-page: https://github.com/vivarium-collective/process-bigraph
6
+ Author: Ryan Spangler, Eran Agmon
7
+ Author-email: ryan.spangler@gmail.com, agmon.eran@gmail.com
8
+ License: UNKNOWN
9
+ Platform: UNKNOWN
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.6
17
+ Classifier: Programming Language :: Python :: 3.7
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Requires-Python: >=3.6
23
+ Description-Content-Type: text/markdown
24
+
25
+ # Process-Bigraph
26
+
27
+ **Process-Bigraph** is...
28
+
29
+ <p align="center">
30
+ <img src="https://github.com/vivarium-collective/bigraph-viz/blob/main/doc/_static/cell_structure_function.png?raw=true" width="600" alt="Bigraph-viz example">
31
+ </p>
32
+
33
+ ## What are Process Bigraphs?
34
+
35
+ ## Getting Started
36
+
37
+ ### Installation
38
+
39
+ You can install `process-bigraph` using pip:
40
+
41
+ ```console
42
+ pip install process-bigraph
43
+ ```
44
+
45
+ ## Tutorial
46
+
47
+ To get started with Process-Bigraph, explore the *tutorial*. coming soon...
48
+
49
+
@@ -0,0 +1,9 @@
1
+ README.md
2
+ setup.py
3
+ process_bigraph/__init__.py
4
+ process_bigraph/composite.py
5
+ process_bigraph.egg-info/PKG-INFO
6
+ process_bigraph.egg-info/SOURCES.txt
7
+ process_bigraph.egg-info/dependency_links.txt
8
+ process_bigraph.egg-info/requires.txt
9
+ process_bigraph.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ bigraph-schema
@@ -0,0 +1 @@
1
+ process_bigraph
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,49 @@
1
+ import re
2
+ from setuptools import setup, find_packages
3
+
4
+
5
+ VERSION = '0.0.1'
6
+
7
+
8
+ with open("README.md", "r") as readme:
9
+ description = readme.read()
10
+ # Patch the relative links to absolute URLs that will work on PyPI.
11
+ description2 = re.sub(
12
+ r']\(([\w/.-]+\.png)\)',
13
+ r'](https://github.com/vivarium-collective/process-bigraph/raw/main/\1)',
14
+ description)
15
+ long_description = re.sub(
16
+ r']\(([\w/.-]+)\)',
17
+ r'](https://github.com/vivarium-collective/process-bigraph/blob/main/\1)',
18
+ description2)
19
+
20
+ setup(
21
+ name="process-bigraph",
22
+ version=VERSION,
23
+ author="Ryan Spangler, Eran Agmon",
24
+ author_email="ryan.spangler@gmail.com, agmon.eran@gmail.com",
25
+ description="",
26
+ long_description=long_description,
27
+ long_description_content_type="text/markdown",
28
+ url="https://github.com/vivarium-collective/process-bigraph",
29
+ packages=find_packages(),
30
+ classifiers=[
31
+ "Development Status :: 3 - Alpha",
32
+ "Intended Audience :: Developers",
33
+ "License :: OSI Approved :: MIT License",
34
+ "Operating System :: OS Independent",
35
+ "Programming Language :: Python",
36
+ "Programming Language :: Python :: 3",
37
+ "Programming Language :: Python :: 3.6",
38
+ "Programming Language :: Python :: 3.7",
39
+ "Programming Language :: Python :: 3.8",
40
+ "Programming Language :: Python :: 3.9",
41
+ "Programming Language :: Python :: 3.10",
42
+ "Programming Language :: Python :: 3.11",
43
+ ],
44
+ python_requires=">=3.6",
45
+ install_requires=[
46
+ # List your package dependencies here
47
+ "bigraph-schema"
48
+ ],
49
+ )