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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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