math-spec-mapping 0.3.5__py3-none-any.whl → 0.3.7__py3-none-any.whl

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.
@@ -37,6 +37,7 @@ class Block:
37
37
  )
38
38
  ]
39
39
  )
40
+ self.domain_blocks2 = self.domain_blocks[:]
40
41
  self.codomain_blocks = tuple(
41
42
  [
42
43
  self
@@ -191,6 +192,9 @@ class ParallelBlock(Block):
191
192
  self.domain_blocks = tuple(
192
193
  [i for x in self.components for i in x.domain_blocks]
193
194
  )
195
+ self.domain_blocks2 = tuple(
196
+ [x for x in self.components for i in x.domain_blocks2]
197
+ )
194
198
  self.codomain_blocks = tuple(
195
199
  [i for x in self.components for i in x.codomain_blocks]
196
200
  )
@@ -320,6 +324,7 @@ class StackBlock(Block):
320
324
  )
321
325
 
322
326
  self.domain_blocks = self.components[0].domain_blocks
327
+ self.domain_blocks2 = self.components[0].domain_blocks2
323
328
  self.codomain_blocks = self.components[-1].codomain_blocks
324
329
  self.domain_blocks_empty = self.components[0].domain_blocks_empty
325
330
  self.codomain_blocks_empty = self.components[-1].codomain_blocks_empty
@@ -7,6 +7,7 @@ from .BoundaryAction import BoundaryAction
7
7
  import os
8
8
  from copy import deepcopy
9
9
  import shutil
10
+ import pandas as pd
10
11
 
11
12
 
12
13
  class MathSpec:
@@ -45,6 +46,7 @@ class MathSpec:
45
46
  self._check_dictionary_names()
46
47
  self._build_functional_parameters()
47
48
  self._build_parameter_types()
49
+ self._crawl_spaces()
48
50
 
49
51
  def _check_dictionary_names(self):
50
52
  for key in self.boundary_actions:
@@ -406,6 +408,18 @@ class MathSpec:
406
408
  self.behavioral_parameters_types = behavioral_parameters_types
407
409
  self.functional_parameters_types = functional_parameters_types
408
410
 
411
+ def _crawl_spaces(self):
412
+ self._used_spaces = []
413
+ self._used_spaces.extend([x.codomain for x in self.control_actions.values()])
414
+ self._used_spaces.extend([x.codomain for x in self.boundary_actions.values()])
415
+ self._used_spaces.extend([x.domain for x in self.policies.values()])
416
+ self._used_spaces.extend([x.codomain for x in self.policies.values()])
417
+ self._used_spaces.extend([x.domain for x in self.mechanisms.values()])
418
+
419
+ self._used_spaces = list(set().union(*self._used_spaces))
420
+ us_names = [y.name for y in self._used_spaces]
421
+ self._unused_spaces = [self.spaces[x] for x in self.spaces if x not in us_names]
422
+
409
423
  def metaprogramming_python_types(self, model_directory, overwrite=False):
410
424
  path = model_directory + "/types.py"
411
425
  if not overwrite:
@@ -456,6 +470,75 @@ class MathSpec:
456
470
  with open(path, "w") as f:
457
471
  f.write(out)
458
472
 
473
+ def run_experiment(
474
+ self,
475
+ experiment,
476
+ params_base,
477
+ state_base,
478
+ post_processing_function,
479
+ state_preperation_functions=None,
480
+ metrics_functions=None,
481
+ ):
482
+ if experiment["Param Modifications"]:
483
+ params_base = deepcopy(params_base)
484
+ for key in experiment["Param Modifications"]:
485
+ params_base[key] = experiment["Param Modifications"][key]
486
+ msi = self.build_implementation(params_base)
487
+ state, params = msi.prepare_state_and_params(
488
+ state_base,
489
+ params_base,
490
+ state_preperation_functions=state_preperation_functions,
491
+ )
492
+
493
+ state = msi.execute_blocks(state, params, experiment["Blocks"])
494
+ df = post_processing_function(state, params)
495
+
496
+ if metrics_functions:
497
+ metrics = {}
498
+ for metrics_function in metrics_functions:
499
+ metrics_function(metrics, state, params, df)
500
+ metrics = pd.Series(metrics)
501
+ else:
502
+ metrics = None
503
+
504
+ return state, params, msi, df, metrics
505
+
506
+ def run_experiments(
507
+ self,
508
+ experiments,
509
+ params_base,
510
+ state_base,
511
+ post_processing_function,
512
+ state_preperation_functions=None,
513
+ metrics_functions=None,
514
+ ):
515
+ state_l = []
516
+ params_l = []
517
+ df_l = []
518
+ metrics_l = []
519
+ for experiment in experiments:
520
+ for i in range(experiment["Monte Carlo Runs"]):
521
+ state, params, msi, df, metrics = self.run_experiment(
522
+ experiment,
523
+ params_base,
524
+ state_base,
525
+ post_processing_function,
526
+ state_preperation_functions=state_preperation_functions,
527
+ metrics_functions=metrics_functions,
528
+ )
529
+ df["Monte Carlo Run"] = i + 1
530
+ df["Experiment"] = experiment["Name"]
531
+ metrics.loc["Monte Carlo Run"] = i + 1
532
+ metrics.loc["Experiment"] = experiment["Name"]
533
+ metrics.name = "{}-{}".format(experiment["Name"], i + 1)
534
+ state_l.append(state)
535
+ params_l.append(params)
536
+ df_l.append(df)
537
+ metrics_l.append(metrics)
538
+ df = pd.concat(df_l)
539
+ metrics = pd.concat(metrics_l, axis=1).T
540
+ return df, metrics, state_l, params_l
541
+
459
542
  def metaprogramming_python_states(
460
543
  self, model_directory, overwrite=False, default_values=None
461
544
  ):
@@ -683,7 +766,9 @@ class MathSpecImplementation:
683
766
  self.boundary_actions = self.load_boundary_actions()
684
767
  self.policies = self.load_policies()
685
768
  self.mechanisms = self.load_mechanisms()
769
+ self.stateful_metrics = self.load_stateful_metrics()
686
770
  self.load_wiring()
771
+ self.load_components()
687
772
 
688
773
  def load_control_actions(self):
689
774
  control_actions = {}
@@ -761,6 +846,10 @@ class MathSpecImplementation:
761
846
  return mechanisms
762
847
 
763
848
  def load_single_wiring(self, wiring):
849
+ hold = wiring
850
+ domain_sizes = {}
851
+ for x in wiring.components:
852
+ domain_sizes[x.name] = len(x.domain)
764
853
  components = [x.name for x in wiring.components]
765
854
  if wiring.block_type == "Stack Block":
766
855
 
@@ -772,16 +861,32 @@ class MathSpecImplementation:
772
861
  elif wiring.block_type == "Parallel Block":
773
862
 
774
863
  spaces_mapping = {}
775
- for x in wiring.components:
776
- spaces_mapping[x.name] = []
777
864
 
778
- for i, x in enumerate([x.name for x in wiring.domain_blocks]):
865
+ for y in [x.name for x in wiring.domain_blocks2]:
866
+ spaces_mapping[y] = []
867
+
868
+ for i, x in enumerate([x.name for x in wiring.domain_blocks2]):
779
869
  spaces_mapping[x].append(i)
780
870
 
781
871
  def wiring(state, params, spaces):
872
+ spaces_mapping_temp = deepcopy(spaces_mapping)
782
873
  codomain = []
783
874
  for component in components:
784
- spaces_i = [spaces[i] for i in spaces_mapping[component]]
875
+ if component in spaces_mapping_temp:
876
+ spaces_i = [spaces[i] for i in spaces_mapping_temp[component]][
877
+ : domain_sizes[component]
878
+ ]
879
+ # Fix for repeated block names
880
+ spaces_mapping_temp[component] = spaces_mapping_temp[component][
881
+ domain_sizes[component] :
882
+ ]
883
+ else:
884
+ assert component in [
885
+ x.name for x in hold.domain_blocks_empty
886
+ ], "{} not in domain_blocks_empty of wiring {}".format(
887
+ component, hold
888
+ )
889
+ spaces_i = []
785
890
  spaces_i = self.blocks[component](state, params, spaces_i)
786
891
  if spaces_i:
787
892
  codomain.extend(spaces_i)
@@ -822,6 +927,22 @@ class MathSpecImplementation:
822
927
  policies[p.name] = opt.implementations["python"]
823
928
  return policies
824
929
 
930
+ def load_stateful_metrics(self):
931
+ stateful_metrics = {}
932
+
933
+ for sm in self.ms.stateful_metrics_map:
934
+ sm = self.ms.stateful_metrics_map[sm]
935
+ if "python" not in sm.implementations:
936
+ print(
937
+ "No python implementation for {}. To fix this, go to Implementations/Python/StatefulMetrics and add {}".format(
938
+ sm.name, sm.name
939
+ )
940
+ )
941
+ else:
942
+ stateful_metrics[sm.name] = sm.implementations["python"]
943
+
944
+ return stateful_metrics
945
+
825
946
  def load_wiring(
826
947
  self,
827
948
  ):
@@ -885,3 +1006,29 @@ class MathSpecImplementation:
885
1006
  assert (
886
1007
  len(shouldnt_be_in_params) == 0
887
1008
  ), "The following parameters are extra: {}".format(shouldnt_be_in_params)
1009
+
1010
+ def prepare_state_and_params(self, state, params, state_preperation_functions=None):
1011
+ self.validate_state_and_params(state, params)
1012
+ state = deepcopy(state)
1013
+ params = deepcopy(params)
1014
+ state["Stateful Metrics"] = self.stateful_metrics
1015
+ if state_preperation_functions:
1016
+ for f in state_preperation_functions:
1017
+ state = f(state)
1018
+ assert (
1019
+ state is not None
1020
+ ), "A state must be returned from the state preperation functions"
1021
+ return state, params
1022
+
1023
+ def load_components(self):
1024
+ self.components = {}
1025
+ self.components.update(self.control_actions)
1026
+ self.components.update(self.boundary_actions)
1027
+ self.components.update(self.policies)
1028
+ self.components.update(self.mechanisms)
1029
+ self.components.update(self.wiring)
1030
+
1031
+ def execute_blocks(self, state, params, blocks):
1032
+ for block in blocks:
1033
+ self.components[block](state, params, [])
1034
+ return state
@@ -16,6 +16,7 @@ class StatefulMetric:
16
16
  else:
17
17
  self.label = self.name
18
18
  self.metadata = data["metadata"]
19
+ self.implementations = data["implementations"]
19
20
 
20
21
 
21
22
  class StatefulMetricSet:
@@ -39,6 +39,15 @@ def convert_stateful_metric(ms, data: Dict) -> StatefulMetricSet:
39
39
  ), "Variable '{}' not in variable map for stateful metrics variables used".format(
40
40
  x[1]
41
41
  )
42
+
43
+ var["implementations"] = {}
44
+
45
+ if "python" in ms["Implementations"]:
46
+ if "stateful_metrics" in ms["Implementations"]["python"]:
47
+ if var["name"] in ms["Implementations"]["python"]["stateful_metrics"]:
48
+ var["implementations"]["python"] = ms["Implementations"]["python"][
49
+ "stateful_metrics"
50
+ ][var["name"]]
42
51
  new_variables.append(StatefulMetric(var))
43
52
  data["metrics"] = new_variables
44
53
 
@@ -538,7 +538,7 @@ def write_stateful_metrics_markdown_report(ms, path, metric, add_metadata=True):
538
538
  out += "Domain: {}\n\n".format(metric.domain)
539
539
 
540
540
  out += "## Parameters Used\n"
541
- for i, x in enumerate(sorted(metric.parameters_used, key=lambda x: x.name)):
541
+ for i, x in enumerate(sorted(metric.parameters_used, key=lambda x: x)):
542
542
  out += "{}. [[{}]]".format(i + 1, x)
543
543
  out += "\n"
544
544
  out += "\n"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: math-spec-mapping
3
- Version: 0.3.5
3
+ Version: 0.3.7
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
@@ -45,8 +45,9 @@ Writing mathematical specifications can be a difficult process, especially when
45
45
  ```mermaid
46
46
  graph TD
47
47
  A[JSON Object \n\n Each spec has a repo for tracking changes \n Must conform to the json specification \n Defines all aspects of the spec including blocks, spaces and actions] -->B[MSML Object \n\n JSON file is parsed, with validations and mappings along the way \n Can show different views on the fly]
48
- B --> C[Report Outputs \n\n Automatically build reports for the full spec or subviews \n Example: all blocks with an effect on variable XYZ]
49
-
48
+ B --> C[Report Outputs & Obsidian Directory \n\n Automatically build reports for the full spec or subviews \n Example: all blocks with an effect on variable XYZ\n Also builds an entire Obsidian directory of all components as linked notes]
49
+ D[Python Function Implementations \n\n Optional enhancement to actually execute code\n Done for each referenced policy option, mechanism, etc. \n Just needs a function definition for each] --> B
50
+ B --> E[Python Wirings & Simulations \n\n MSML can be used to run blocks \n Wirings automatically work to pass between domain/codomains \n Entire simulations can be built up as composed wirings]
50
51
  ```
51
52
 
52
53
  ## MSML in the Engineering Lifecycle
@@ -2,11 +2,11 @@ math_spec_mapping/__init__.py,sha256=CzT9KycdX5nuiUzDFmLXVeAIr8v8UKGbXsEQF8vjl1c
2
2
  math_spec_mapping/schema.py,sha256=6mrRqzEnTTSXjb19xJ63MBp0KjKH0s7i6TfT4MkAY9k,233
3
3
  math_spec_mapping/schema.schema.json,sha256=hJP2TcV5WPFPmx4u_A5U1xtnpkE1LeYaTeYOXadTot0,30916
4
4
  math_spec_mapping/Classes/ActionTransmissionChannel.py,sha256=zWMo5QsgPh5WGIWXl-xOrZNMXYJXmK6Vejw1dQvi0og,246
5
- math_spec_mapping/Classes/Block.py,sha256=OsWM1ZAi6ZvavDhMFJi_H7w8ZF9LqJIKR3ZLTXnts9w,17437
5
+ math_spec_mapping/Classes/Block.py,sha256=cGtIhNgRfoDZ0O3SxeXcNzNlHcdXIB89sT2uaZct8LY,17667
6
6
  math_spec_mapping/Classes/BoundaryAction.py,sha256=KuZqtvZwSHWDP7gFQXGnG-r3EuYJU_oU9wMCuqvRkzk,593
7
7
  math_spec_mapping/Classes/ControlAction.py,sha256=ysqpgANwdizVdwqtgZmnxXMpCqrzmVEF_6YT0M3l4Ho,526
8
8
  math_spec_mapping/Classes/Entity.py,sha256=fA0-b128_OHHxfCg4pzqyQV083EYev1HlVpy86S5igg,1226
9
- math_spec_mapping/Classes/MathSpec.py,sha256=f0S-52Gh-LjZtOldXZTXPTTwqCWAz-ULsckzmNGxcSg,33257
9
+ math_spec_mapping/Classes/MathSpec.py,sha256=YopqG_ca7nxgPPZxQR9b442C155ZJGfs73CDEIL5uMc,39038
10
10
  math_spec_mapping/Classes/Mechanism.py,sha256=2sLm3wYBIeTQaMBcsJ9btqIWsbS895Ra8NY6Y9_G_Dg,379
11
11
  math_spec_mapping/Classes/Metric.py,sha256=AhPgYppOP6q49xvR8S9STxQsXUKJlTWx7wI1LfZEtww,581
12
12
  math_spec_mapping/Classes/Parameter.py,sha256=ZuJ_w0sChvRElJ4sOnXZ2EV4Ell2xXFulKLjVOpgz2E,1237
@@ -14,7 +14,7 @@ math_spec_mapping/Classes/Policy.py,sha256=fzV85tB3QScjiYGfhw_dyQt9L1BYYfTyTIQQc
14
14
  math_spec_mapping/Classes/Space.py,sha256=QsahxoUfRsDWQLBL683KnGx72MAmRxv7CDE7TMgCG-E,472
15
15
  math_spec_mapping/Classes/State.py,sha256=U40DoF2qlx_k9gvqQiP1S3C9ZLk3cW_-jmJn71TiCxg,1599
16
16
  math_spec_mapping/Classes/StateUpdateTransmissionChannel.py,sha256=3hBLvD1lE64PkwqksBXAfFWv7foOZzGQLAFQWy42tOA,257
17
- math_spec_mapping/Classes/StatefulMetric.py,sha256=UCis1BJ7fsajHHxFF05ZiyDean2D4s4a95uYYW1Mjq4,749
17
+ math_spec_mapping/Classes/StatefulMetric.py,sha256=plMFMAFEk1y2t4DR5lA2SRC9UrYArsx_W33l3mZSdgE,804
18
18
  math_spec_mapping/Classes/Type.py,sha256=2KFY8d3cv1PzJJ7SSMHJf1zcfQ3ZbqxotK2KgTaLZdM,289
19
19
  math_spec_mapping/Classes/__init__.py,sha256=0zxgOqns_9JybD74HKMVh6aw8ij8WVbfQ4Q_1uWzof0,761
20
20
  math_spec_mapping/Convenience/__init__.py,sha256=z2W-E5Wg1CNEkDI5UqH3qIVBqp-3A1e63f3u9fA-N7w,112
@@ -35,7 +35,7 @@ math_spec_mapping/Load/parameters.py,sha256=W4utm7to3s2fo4z3XgLH0TM1agaIad1qfM2I
35
35
  math_spec_mapping/Load/policy.py,sha256=HvlhGHGJTweVs7DOI2HSL_2_diECr8ukDUmzoFLQELo,2444
36
36
  math_spec_mapping/Load/spaces.py,sha256=7zgGA57Te7T4hfuCCDElffiidWgn1lKm5E14e1yjt8M,1116
37
37
  math_spec_mapping/Load/state_update_transmission_channels.py,sha256=FJWp5n4HdtHAfof5BUQ6BnRakljatL2h8dWCapaVSc0,2238
38
- math_spec_mapping/Load/stateful_metrics.py,sha256=uGSTc6x6lld5xptgSUMHrO0Vg0QDRIL14C6zTg33S8o,1977
38
+ math_spec_mapping/Load/stateful_metrics.py,sha256=pX2w3MvX2akFAOo6XWybkRE_X-v5BqchV2jTx0EekF0,2356
39
39
  math_spec_mapping/Load/states.py,sha256=3YurI7eTNkN6nrXRFVrc58wH0VfM22XOuWE07HVpR7Y,1365
40
40
  math_spec_mapping/Load/type.py,sha256=z6cBdBNjWed7cRyA0Bj7Jd5PmtemVVh07n3mWFj_5U4,4356
41
41
  math_spec_mapping/Load/wiring.py,sha256=1dR94U5N1W_WI5rL6lYBltH25ZvApB2pIpq9r5Opkug,3083
@@ -44,7 +44,7 @@ math_spec_mapping/Reports/boundary_actions.py,sha256=45BPp4QjWdD-3E9ZWwqgj_nI2-Y
44
44
  math_spec_mapping/Reports/control_actions.py,sha256=NksekZKIPFSIkubttFstKFthc5AU9B9PWRLSl9j1wWs,1216
45
45
  math_spec_mapping/Reports/general.py,sha256=WOOn6Wlb8M4fsdN49FlKLwOka6vJPQ9aCUy88TL2ki0,1610
46
46
  math_spec_mapping/Reports/html.py,sha256=uUXxMgGoL2yQelSg7CmJjIsU84SbZarqPg2d9x7Z13k,9220
47
- math_spec_mapping/Reports/markdown.py,sha256=t6C2D6pk3Y9K9vOR0IC6rLe18tBm3JFgJ3rC9tnvt_Q,22871
47
+ math_spec_mapping/Reports/markdown.py,sha256=SdhgOMpMBnGKWDG0cimk-LI_UqjQDPy87IxTb-PrBQ0,22866
48
48
  math_spec_mapping/Reports/mechanisms.py,sha256=d2Rxt3JBYvqAOAYUynl0buYVoXEHrO8EGq7GK6hK8NA,1322
49
49
  math_spec_mapping/Reports/node_map.py,sha256=FdSMDQG16NX6n9sZcH-T5xwsvgjrV9OqBHc9J_VlNK0,3129
50
50
  math_spec_mapping/Reports/parameters.py,sha256=yizNG4lNGrgrlzYYcHMGfXKDFlPw4PMDYshDqZ3YARs,535
@@ -53,8 +53,8 @@ math_spec_mapping/Reports/spaces.py,sha256=-76hR5wQBv4lsG000ypBJ-OprjsNjI-rNRMYd
53
53
  math_spec_mapping/Reports/state.py,sha256=RkqfSonar74KVC8PpA9GgI2xaHX6BrkNdAuWMZlYQfI,2321
54
54
  math_spec_mapping/Reports/tables.py,sha256=O0CNuqh3LMECq5uLjBOoxMUk5hUvkUK660FNnwWUxDY,1505
55
55
  math_spec_mapping/Reports/wiring.py,sha256=u9SvKWy6T-WJUEgFI6-zgZanoOaTTs_2YwmEceDLsV8,1618
56
- math_spec_mapping-0.3.5.dist-info/LICENSE,sha256=ObyEzSw8kgCaFbEfpu1zP4TrcAKLA0xhqHMZZfyh7N0,1069
57
- math_spec_mapping-0.3.5.dist-info/METADATA,sha256=5V-r7KxzjQ0TpSTcMx9o0kmdi6L9xwqtZ2VQGDE081w,6012
58
- math_spec_mapping-0.3.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
59
- math_spec_mapping-0.3.5.dist-info/top_level.txt,sha256=AImhn9wgazkdV0a9vfiphtQR8uGe2nq-ZIOp-6yUk9o,18
60
- math_spec_mapping-0.3.5.dist-info/RECORD,,
56
+ math_spec_mapping-0.3.7.dist-info/LICENSE,sha256=ObyEzSw8kgCaFbEfpu1zP4TrcAKLA0xhqHMZZfyh7N0,1069
57
+ math_spec_mapping-0.3.7.dist-info/METADATA,sha256=Y4GIicxIeBa44LDgCxCdNAedQ7EZunZn-VD3JPMfFF4,6500
58
+ math_spec_mapping-0.3.7.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
59
+ math_spec_mapping-0.3.7.dist-info/top_level.txt,sha256=AImhn9wgazkdV0a9vfiphtQR8uGe2nq-ZIOp-6yUk9o,18
60
+ math_spec_mapping-0.3.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5