math-spec-mapping 0.1.4__tar.gz → 0.1.5__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/PKG-INFO +1 -1
  2. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/pyproject.toml +1 -1
  3. math_spec_mapping-0.1.5/src/Classes/Block.py +338 -0
  4. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/MathSpec.py +1 -0
  5. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/Mechanism.py +2 -1
  6. math_spec_mapping-0.1.5/src/Classes/Space.py +14 -0
  7. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/__init__.py +1 -1
  8. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/action_transmission_channel.py +5 -3
  9. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/general.py +0 -1
  10. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/load.py +2 -2
  11. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/spaces.py +4 -1
  12. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/wiring.py +27 -0
  13. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/math_spec_mapping.egg-info/PKG-INFO +1 -1
  14. math_spec_mapping-0.1.4/src/Classes/Block.py +0 -184
  15. math_spec_mapping-0.1.4/src/Classes/Space.py +0 -7
  16. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/LICENSE +0 -0
  17. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/README.md +0 -0
  18. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/setup.cfg +0 -0
  19. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/ActionTransmissionChannel.py +0 -0
  20. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/BoundaryAction.py +0 -0
  21. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/ControlAction.py +0 -0
  22. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/Entity.py +0 -0
  23. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/Parameter.py +0 -0
  24. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/Policy.py +0 -0
  25. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/State.py +0 -0
  26. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/StateUpdateTransmissionChannel.py +0 -0
  27. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Classes/StatefulMetric.py +0 -0
  28. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Convenience/__init__.py +0 -0
  29. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Convenience/starter.py +0 -0
  30. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/__init__.py +0 -0
  31. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/boundary_actions.py +0 -0
  32. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/control_actions.py +0 -0
  33. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/entities.py +0 -0
  34. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/mechanism.py +0 -0
  35. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/parameters.py +0 -0
  36. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/policy.py +0 -0
  37. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/state_update_transmission_channels.py +0 -0
  38. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/stateful_metrics.py +0 -0
  39. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Load/states.py +0 -0
  40. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/__init__.py +0 -0
  41. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/boundary_actions.py +0 -0
  42. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/control_actions.py +0 -0
  43. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/general.py +0 -0
  44. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/html.py +0 -0
  45. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/mechanisms.py +0 -0
  46. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/node_map.py +0 -0
  47. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/parameters.py +0 -0
  48. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/policies.py +0 -0
  49. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/spaces.py +0 -0
  50. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/state.py +0 -0
  51. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/Reports/tables.py +0 -0
  52. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/__init__.py +0 -0
  53. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/math_spec_mapping.egg-info/SOURCES.txt +0 -0
  54. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/math_spec_mapping.egg-info/dependency_links.txt +0 -0
  55. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/math_spec_mapping.egg-info/requires.txt +0 -0
  56. {math_spec_mapping-0.1.4 → math_spec_mapping-0.1.5}/src/math_spec_mapping.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: math_spec_mapping
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: A library for easy mapping of mathematical specifications.
5
5
  Author-email: Sean McOwen <Sean@Block.Science>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -3,7 +3,7 @@ requires = ["setuptools>=61.0"]
3
3
  build-backend = "setuptools.build_meta"
4
4
  [project]
5
5
  name = "math_spec_mapping"
6
- version = "0.1.4"
6
+ version = "0.1.5"
7
7
  authors = [
8
8
  { name="Sean McOwen", email="Sean@Block.Science" },
9
9
  ]
@@ -0,0 +1,338 @@
1
+ from typing import Dict
2
+ from .Space import TerminatingSpace, EmptySpace
3
+
4
+
5
+ class Block:
6
+ def __init__(self, data: Dict):
7
+ self.name = data["name"]
8
+ self.description = data["description"]
9
+ self.constraints = data["constraints"]
10
+ self.domain = data["domain"]
11
+ self.codomain = data["codomain"]
12
+ self.parameters_used = data["parameters_used"]
13
+ if "label" in data:
14
+ self.label = data["label"]
15
+ else:
16
+ self.label = self.name
17
+ self.called_by = []
18
+ self.calls = []
19
+ self.block_type = "Block"
20
+ # Will be overwritten in composite blocks to represent individual components
21
+ self.domain_blocks = tuple(
22
+ [
23
+ self
24
+ for _ in range(
25
+ len(
26
+ [
27
+ x
28
+ for x in self.domain
29
+ if x not in [TerminatingSpace, EmptySpace]
30
+ ]
31
+ )
32
+ )
33
+ ]
34
+ )
35
+ self.codomain_blocks = tuple(
36
+ [
37
+ self
38
+ for _ in range(
39
+ len(
40
+ [
41
+ x
42
+ for x in self.codomain
43
+ if x not in [TerminatingSpace, EmptySpace]
44
+ ]
45
+ )
46
+ )
47
+ ]
48
+ )
49
+ self.domain_blocks_empty = tuple(
50
+ self for _ in range(len([x for x in self.domain if x == EmptySpace]))
51
+ )
52
+ self.codomain_blocks_empty = tuple(
53
+ self for _ in range(len([x for x in self.codomain if x == EmptySpace]))
54
+ )
55
+ self.codomain_blocks_terminating = tuple(
56
+ self
57
+ for _ in range(len([x for x in self.codomain if x == TerminatingSpace]))
58
+ )
59
+
60
+ def render_mermaid(self, i):
61
+ i += 1
62
+ return "X{}[{}]".format(i, self.name), i
63
+
64
+ def render_mermaid_root(self):
65
+ out = """```mermaid\ngraph TB\n"""
66
+ out += self.render_mermaid(0)[0]
67
+ out += "\n```"
68
+ return out
69
+
70
+
71
+ class ParallelBlock(Block):
72
+ def __init__(self, data: Dict):
73
+ self.name = data["name"]
74
+ self.components = data["components"]
75
+ self.description = data["description"]
76
+ self.constraints = data["constraints"]
77
+ self.domain = tuple(
78
+ [
79
+ i
80
+ for x in self.components
81
+ for i in x.domain
82
+ if i not in [TerminatingSpace, EmptySpace]
83
+ ]
84
+ )
85
+ if len(self.domain) == 0:
86
+ self.domain = (EmptySpace,)
87
+
88
+ self.codomain = tuple(
89
+ [
90
+ i
91
+ for x in self.components
92
+ for i in x.codomain
93
+ if i not in [TerminatingSpace, EmptySpace]
94
+ ]
95
+ )
96
+ if len(self.codomain) == 0:
97
+ self.codomain = (EmptySpace,)
98
+ self.parameters_used = list(
99
+ set([i for x in self.components for i in x.parameters_used])
100
+ )
101
+
102
+ self.domain_blocks = tuple(
103
+ [i for x in self.components for i in x.domain_blocks]
104
+ )
105
+ self.codomain_blocks = tuple(
106
+ [i for x in self.components for i in x.codomain_blocks]
107
+ )
108
+
109
+ self.domain_blocks_empty = tuple(
110
+ [i for x in self.components for i in x.domain_blocks_empty]
111
+ )
112
+ self.codomain_blocks_empty = tuple(
113
+ [i for x in self.components for i in x.codomain_blocks_empty]
114
+ )
115
+ self.codomain_blocks_terminating = tuple(
116
+ [i for x in self.components for i in x.codomain_blocks_terminating]
117
+ )
118
+
119
+ self.called_by = []
120
+ self.calls = []
121
+ self.block_type = "Paralell Block"
122
+
123
+ def render_mermaid(self, i):
124
+ multi = None
125
+ if type(i) == list:
126
+ multi = i
127
+ i = i[-1]
128
+ start_i = i
129
+ out = ""
130
+
131
+ nodes = []
132
+
133
+ # Render components
134
+ for component in self.components:
135
+ component, i = component.render_mermaid(i)
136
+ out += component
137
+ out += "\n"
138
+ nodes.append(i)
139
+ end_i = i
140
+
141
+ # Render invisible connections
142
+ for ix1, ix2 in zip(nodes[:-1], nodes[1:]):
143
+ out += "X{} ~~~ X{}".format(ix1, ix2)
144
+ out += "\n"
145
+
146
+ # Subgraph it
147
+ i += 1
148
+ out = "subgraph X{}[{}]\ndirection LR\n".format(i, self.name) + out
149
+
150
+ out += "end"
151
+
152
+ return out, i
153
+
154
+
155
+ class StackBlock(Block):
156
+ def __init__(self, data: Dict):
157
+ self.name = data["name"]
158
+ self.components = data["components"]
159
+ self.description = data["description"]
160
+ self.constraints = data["constraints"]
161
+ self._check_domain_mapping()
162
+ self.domain = self.components[0].domain
163
+ self.codomain = self.components[-1].codomain
164
+ self.parameters_used = list(
165
+ set([i for x in self.components for i in x.parameters_used])
166
+ )
167
+
168
+ self.domain_blocks = self.components[0].domain_blocks
169
+ self.codomain_blocks = self.components[-1].codomain_blocks
170
+ self.domain_blocks_empty = self.components[0].domain_blocks_empty
171
+ self.codomain_blocks_empty = self.components[-1].codomain_blocks_empty
172
+ self.codomain_blocks_terminating = self.components[
173
+ -1
174
+ ].codomain_blocks_terminating
175
+
176
+ self.called_by = []
177
+ self.calls = []
178
+
179
+ self.block_type = "Stack Block"
180
+
181
+ def _check_domain_mapping(self):
182
+ for a, b in zip(self.components[:-1], self.components[1:]):
183
+ assert [
184
+ x for x in a.codomain if x not in [EmptySpace, TerminatingSpace]
185
+ ] == [
186
+ x for x in b.domain if x not in [EmptySpace, TerminatingSpace]
187
+ ], "{} codomain does not match {} domain, {} != {}".format(
188
+ a.name, b.name, a.codomain, b.domain
189
+ )
190
+
191
+ def build_action_transmission_channels(self):
192
+ channels = []
193
+ for a, b in zip(self.components[:-1], self.components[1:]):
194
+ assert len(a.codomain_blocks) == len(b.domain_blocks) and len(
195
+ b.domain_blocks
196
+ ) == len([x for x in b.domain if x not in [EmptySpace, TerminatingSpace]])
197
+ for x, y, z in zip(
198
+ a.codomain_blocks,
199
+ b.domain_blocks,
200
+ [x for x in b.domain if x not in [EmptySpace, TerminatingSpace]],
201
+ ):
202
+ channels.append(
203
+ {
204
+ "origin": x.name,
205
+ "target": y.name,
206
+ "space": z.name,
207
+ "optional": False,
208
+ }
209
+ )
210
+ for x in a.codomain_blocks_empty:
211
+ for y in b.domain_blocks_empty:
212
+ channels.append(
213
+ {
214
+ "origin": x.name,
215
+ "target": y.name,
216
+ "space": "Empty Space",
217
+ "optional": False,
218
+ }
219
+ )
220
+ return channels
221
+
222
+ def render_mermaid(self, i):
223
+ multi = None
224
+ if type(i) == list:
225
+ multi = i
226
+ i = i[-1]
227
+ start_i = i
228
+ out = ""
229
+
230
+ nodes = []
231
+
232
+ # Render components
233
+ for component in self.components:
234
+ component, i = component.render_mermaid(i)
235
+ out += component
236
+ out += "\n"
237
+ nodes.append(i)
238
+ if type(i) == list:
239
+ i = i[-1]
240
+ end_i = i
241
+
242
+ # Render connections
243
+ for ix1, ix2 in zip(nodes[:-1], nodes[1:]):
244
+ if type(ix1) != list:
245
+ ix1 = [ix1]
246
+ if type(ix2) != list:
247
+ ix2 = [ix2]
248
+ for ix3 in ix1:
249
+ for ix4 in ix2:
250
+ out += "X{}-->X{}".format(ix3, ix4)
251
+ out += "\n"
252
+
253
+ # Subgraph it
254
+ i += 1
255
+ out = "subgraph X{}[{}]\ndirection TB\n".format(i, self.name) + out
256
+ out += "end"
257
+
258
+ return out, i
259
+
260
+
261
+ class SplitBlock(Block):
262
+ def __init__(self, data: Dict):
263
+ self.name = data["name"]
264
+ self.components = data["components"]
265
+ self.description = data["description"]
266
+ self.constraints = data["constraints"]
267
+ self.domain = tuple(
268
+ [
269
+ i
270
+ for x in self.components
271
+ for i in x.domain
272
+ if i not in [TerminatingSpace, EmptySpace]
273
+ ]
274
+ )
275
+ if len(self.domain) == 0:
276
+ self.domain = (EmptySpace,)
277
+
278
+ self.codomain = tuple(
279
+ [
280
+ i
281
+ for x in self.components
282
+ for i in x.codomain
283
+ if i not in [TerminatingSpace, EmptySpace]
284
+ ]
285
+ )
286
+ if len(self.codomain) == 0:
287
+ self.codomain = (EmptySpace,)
288
+ self.parameters_used = list(
289
+ set([i for x in self.components for i in x.parameters_used])
290
+ )
291
+
292
+ self.domain_blocks = tuple(
293
+ [i for x in self.components for i in x.domain_blocks]
294
+ )
295
+ self.codomain_blocks = tuple(
296
+ [i for x in self.components for i in x.codomain_blocks]
297
+ )
298
+
299
+ self.domain_blocks_empty = tuple(
300
+ [i for x in self.components for i in x.domain_blocks_empty]
301
+ )
302
+ self.codomain_blocks_empty = tuple(
303
+ [i for x in self.components for i in x.codomain_blocks_empty]
304
+ )
305
+ self.codomain_blocks_terminating = tuple(
306
+ [i for x in self.components for i in x.codomain_blocks_terminating]
307
+ )
308
+
309
+ self.called_by = []
310
+ self.calls = []
311
+
312
+ self.block_type = "Split Block"
313
+
314
+ def render_mermaid(self, i):
315
+ multi = None
316
+ if type(i) == list:
317
+ multi = i
318
+ i = i[-1]
319
+ start_i = i
320
+ out = ""
321
+
322
+ nodes = []
323
+
324
+ # Render components
325
+ for component in self.components:
326
+ component, i = component.render_mermaid(i)
327
+ out += component
328
+ out += "\n"
329
+ nodes.append(i)
330
+ end_i = i
331
+
332
+ # Render invisible connections
333
+ for ix1, ix2 in zip(nodes[:-1], nodes[1:]):
334
+ out += "X{} ~~~ X{}".format(ix1, ix2)
335
+ out += "\n"
336
+ out = out[:-1]
337
+
338
+ return out, nodes
@@ -25,6 +25,7 @@ class MathSpec:
25
25
  ]
26
26
  self.stateful_metrics = ms_dict["Stateful Metrics"]
27
27
  self.wiring = ms_dict["Wiring"]
28
+ self.blocks = ms_dict["Blocks"]
28
29
 
29
30
  self._check_parameters()
30
31
  self._crawl_parameters()
@@ -1,10 +1,11 @@
1
1
  from typing import Dict
2
2
  from .Block import Block
3
+ from .Space import TerminatingSpace
3
4
 
4
5
 
5
6
  class Mechanism(Block):
6
7
  def __init__(self, data: Dict):
7
- data["codomain"] = tuple()
8
+ data["codomain"] = (TerminatingSpace,)
8
9
  super().__init__(data)
9
10
  self.logic = data["logic"]
10
11
  self.updates = []
@@ -0,0 +1,14 @@
1
+ from typing import Dict
2
+
3
+
4
+ class Space:
5
+ def __init__(self, data: Dict):
6
+ self.name = data["name"]
7
+ self.schema = data["schema"]
8
+
9
+ def __repr__(self):
10
+ return self.name
11
+
12
+
13
+ TerminatingSpace = Space({"name": "Terminating Space", "schema": {}})
14
+ EmptySpace = Space({"name": "Empty Space", "schema": {}})
@@ -9,5 +9,5 @@ from .Policy import Policy, PolicyOption
9
9
  from .StateUpdateTransmissionChannel import StateUpdateTransmissionChannel
10
10
  from .StatefulMetric import StatefulMetric, StatefulMetricSet
11
11
  from .ControlAction import ControlAction, ControlActionOption
12
- from .Space import Space
12
+ from .Space import Space, TerminatingSpace, EmptySpace
13
13
  from .Block import ParallelBlock, Block, StackBlock, SplitBlock
@@ -57,15 +57,17 @@ def convert_action_transmission_channel(
57
57
  return ActionTransmissionChannel(data)
58
58
 
59
59
 
60
- def load_action_transmission_channels(ms: Dict, json: Dict) -> None:
60
+ def load_action_transmission_channels(
61
+ ms: Dict, action_transmission_channels: list
62
+ ) -> None:
61
63
  """Function to load states into the new dictionary
62
64
 
63
65
  Args:
64
66
  ms (Dict): MathSpec dictionary
65
- json (Dict): JSON version of MathSpec to load
67
+ action_transmission_channels (list): List of action transmission channels
66
68
  """
67
69
 
68
70
  ms["Action Transmission Channels"] = []
69
- for atc in json["Action Transmission Channels"]:
71
+ for atc in action_transmission_channels:
70
72
  atc = convert_action_transmission_channel(atc, ms)
71
73
  ms["Action Transmission Channels"].append(atc)
@@ -30,7 +30,6 @@ def check_json_keys(json: Dict, check_set_key: str) -> None:
30
30
  "Blocks",
31
31
  ],
32
32
  "JSON": [
33
- "Action Transmission Channels",
34
33
  "Boundary Actions",
35
34
  "Entities",
36
35
  "Mechanisms",
@@ -40,8 +40,8 @@ def load_from_json(json: Dict) -> MathSpec:
40
40
  load_parameters(ms, json)
41
41
  load_policies(ms, json)
42
42
  load_stateful_metrics(ms, json)
43
- load_wiring(ms, json)
44
- load_action_transmission_channels(ms, json)
43
+ action_transmission_channels = load_wiring(ms, json)
44
+ load_action_transmission_channels(ms, action_transmission_channels)
45
45
  load_state_update_transmission_channels(ms, json)
46
46
 
47
47
  # Assert all keys are correct for the ms version
@@ -1,5 +1,5 @@
1
1
  from typing import Dict
2
- from ..Classes import Space
2
+ from ..Classes import Space, TerminatingSpace, EmptySpace
3
3
  from .general import check_json_keys
4
4
 
5
5
 
@@ -24,6 +24,9 @@ def load_spaces(ms: Dict, json: Dict) -> None:
24
24
 
25
25
  # Placeholder for now
26
26
  ms["Spaces"] = {}
27
+ ms["Spaces"]["Terminating Space"] = TerminatingSpace
28
+ ms["Spaces"]["Empty Space"] = EmptySpace
27
29
 
28
30
  for space in json["Spaces"]:
31
+ assert space["name"] not in ms["Spaces"], "{} repeated"
29
32
  ms["Spaces"][space["name"]] = convert_space(space)
@@ -29,15 +29,42 @@ def load_single_wiring(data, ms):
29
29
  return block
30
30
 
31
31
 
32
+ def check_repeat(d, blocks):
33
+ for x in blocks:
34
+ assert x not in d, "{} was a repeated block".format(x)
35
+
36
+
37
+ def filter_atc(action_transmission_channels):
38
+ seen = []
39
+ out = []
40
+ for x in action_transmission_channels:
41
+ key = frozenset(x.items())
42
+ if key not in seen:
43
+ seen.append(key)
44
+ out.append(x)
45
+ return out
46
+
47
+
32
48
  def load_wiring(ms, json):
33
49
  ms["Blocks"] = {}
50
+ check_repeat(ms["Blocks"], ms["Boundary Actions"])
34
51
  ms["Blocks"].update(ms["Boundary Actions"])
52
+ check_repeat(ms["Blocks"], ms["Control Actions"])
35
53
  ms["Blocks"].update(ms["Control Actions"])
54
+ check_repeat(ms["Blocks"], ms["Policies"])
36
55
  ms["Blocks"].update(ms["Policies"])
56
+ check_repeat(ms["Blocks"], ms["Mechanisms"])
37
57
  ms["Blocks"].update(ms["Mechanisms"])
38
58
 
39
59
  ms["Wiring"] = {}
60
+ action_transmission_channels = []
40
61
  for w in json["Wiring"]:
41
62
  w = load_single_wiring(w, ms)
63
+ assert w.name not in ms["Blocks"], "{} was a repeated block".format(w.name)
42
64
  ms["Wiring"][w.name] = w
43
65
  ms["Blocks"][w.name] = w
66
+ if w.block_type == "Stack Block":
67
+ action_transmission_channels.extend(w.build_action_transmission_channels())
68
+ action_transmission_channels = filter_atc(action_transmission_channels)
69
+
70
+ return action_transmission_channels
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: math_spec_mapping
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: A library for easy mapping of mathematical specifications.
5
5
  Author-email: Sean McOwen <Sean@Block.Science>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,184 +0,0 @@
1
- from typing import Dict
2
-
3
-
4
- class Block:
5
- def __init__(self, data: Dict):
6
- self.name = data["name"]
7
- self.description = data["description"]
8
- self.constraints = data["constraints"]
9
- self.domain = data["domain"]
10
- self.codomain = data["codomain"]
11
- self.parameters_used = data["parameters_used"]
12
- if "label" in data:
13
- self.label = data["label"]
14
- else:
15
- self.label = self.name
16
- self.called_by = []
17
- self.calls = []
18
- self.block_type = "Block"
19
-
20
- def render_mermaid(self, i):
21
- i += 1
22
- return "X{}[{}]".format(i, self.name), i
23
-
24
- def render_mermaid_root(self):
25
- out = """```mermaid\ngraph TB\n"""
26
- out += self.render_mermaid(0)[0]
27
- out += "\n```"
28
- return out
29
-
30
-
31
- class ParallelBlock(Block):
32
- def __init__(self, data: Dict):
33
- self.name = data["name"]
34
- self.components = data["components"]
35
- self.description = data["description"]
36
- self.constraints = data["constraints"]
37
- self.domain = tuple([i for x in self.components for i in x.domain])
38
-
39
- self.codomain = tuple([i for x in self.components for i in x.codomain])
40
- self.parameters_used = list(
41
- set([i for x in self.components for i in x.parameters_used])
42
- )
43
-
44
- self.called_by = []
45
- self.calls = []
46
- self.block_type = "Paralell Block"
47
-
48
- def render_mermaid(self, i):
49
- multi = None
50
- if type(i) == list:
51
- multi = i
52
- i = i[-1]
53
- start_i = i
54
- out = ""
55
-
56
- nodes = []
57
-
58
- # Render components
59
- for component in self.components:
60
- component, i = component.render_mermaid(i)
61
- out += component
62
- out += "\n"
63
- nodes.append(i)
64
- end_i = i
65
-
66
- # Render invisible connections
67
- for ix1, ix2 in zip(nodes[:-1], nodes[1:]):
68
- out += "X{} ~~~ X{}".format(ix1, ix2)
69
- out += "\n"
70
-
71
- # Subgraph it
72
- i += 1
73
- out = "subgraph X{}[{}]\ndirection LR\n".format(i, self.name) + out
74
-
75
- out += "end"
76
-
77
- return out, i
78
-
79
-
80
- class StackBlock(Block):
81
- def __init__(self, data: Dict):
82
- self.name = data["name"]
83
- self.components = data["components"]
84
- self.description = data["description"]
85
- self.constraints = data["constraints"]
86
- self._check_domain_mapping()
87
- self.domain = self.components[0].domain
88
- self.codomain = self.components[-1].codomain
89
- self.parameters_used = list(
90
- set([i for x in self.components for i in x.parameters_used])
91
- )
92
-
93
- self.called_by = []
94
- self.calls = []
95
-
96
- self.block_type = "Stack Block"
97
-
98
- def _check_domain_mapping(self):
99
- for a, b in zip(self.components[:-1], self.components[1:]):
100
- assert (
101
- a.codomain == b.domain
102
- ), "{} codomain does not match {} domain".format(a.name, b.name)
103
-
104
- def render_mermaid(self, i):
105
- multi = None
106
- if type(i) == list:
107
- multi = i
108
- i = i[-1]
109
- start_i = i
110
- out = ""
111
-
112
- nodes = []
113
-
114
- # Render components
115
- for component in self.components:
116
- component, i = component.render_mermaid(i)
117
- out += component
118
- out += "\n"
119
- nodes.append(i)
120
- if type(i) == list:
121
- i = i[-1]
122
- end_i = i
123
-
124
- # Render connections
125
- for ix1, ix2 in zip(nodes[:-1], nodes[1:]):
126
- if type(ix1) != list:
127
- ix1 = [ix1]
128
- if type(ix2) != list:
129
- ix2 = [ix2]
130
- for ix3 in ix1:
131
- for ix4 in ix2:
132
- out += "X{}-->X{}".format(ix3, ix4)
133
- out += "\n"
134
-
135
- # Subgraph it
136
- i += 1
137
- out = "subgraph X{}[{}]\ndirection TB\n".format(i, self.name) + out
138
- out += "end"
139
-
140
- return out, i
141
-
142
-
143
- class SplitBlock(Block):
144
- def __init__(self, data: Dict):
145
- self.name = data["name"]
146
- self.components = data["components"]
147
- self.description = data["description"]
148
- self.constraints = data["constraints"]
149
- self.domain = tuple([i for x in self.components for i in x.domain])
150
- self.codomain = tuple([i for x in self.components for i in x.codomain])
151
- self.parameters_used = list(
152
- set([i for x in self.components for i in x.parameters_used])
153
- )
154
-
155
- self.called_by = []
156
- self.calls = []
157
-
158
- self.block_type = "Split Block"
159
-
160
- def render_mermaid(self, i):
161
- multi = None
162
- if type(i) == list:
163
- multi = i
164
- i = i[-1]
165
- start_i = i
166
- out = ""
167
-
168
- nodes = []
169
-
170
- # Render components
171
- for component in self.components:
172
- component, i = component.render_mermaid(i)
173
- out += component
174
- out += "\n"
175
- nodes.append(i)
176
- end_i = i
177
-
178
- # Render invisible connections
179
- for ix1, ix2 in zip(nodes[:-1], nodes[1:]):
180
- out += "X{} ~~~ X{}".format(ix1, ix2)
181
- out += "\n"
182
- out = out[:-1]
183
-
184
- return out, nodes
@@ -1,7 +0,0 @@
1
- from typing import Dict
2
-
3
-
4
- class Space:
5
- def __init__(self, data: Dict):
6
- self.name = data["name"]
7
- self.schema = data["schema"]