From a1d4f2aa136cdcfab6856c36b0fa88cf1d7e74dd Mon Sep 17 00:00:00 2001 From: jdcpni Date: Thu, 2 Dec 2021 23:23:32 -0500 Subject: [PATCH] Refactor/ocm/state input ports (#2221) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * • component.py docstring mod to **size** * • optimizationcontrolmechanism.py: added feature_input_ports attribute and num_feature_input_ports property * • optimizationcontrolmechanism.py: added feature_input_ports attribute and num_feature_input_ports property • parameterestimationcomposition.py: fixed misplacement of its Parameters() attribute * • optimizationcontrolmechanism.py: added feature_input_ports attribute and num_feature_input_ports property • parameterestimationcomposition.py: fixed misplacement of its Parameters() attribute • optimizationfunctions.py: made num_estimates a Parameter * - modified test_mode_based_num_estimates * - * - * • optimizationcontrolmechanism.py: - _instantiate_control_signals: random_seeds -> random_seed_mod_values * • composition.py - _add_controller: modifying to instantiate feature_input_ports if none are specified * • composition.py: - add_controller: now adds feature_input_ports for Compostion INPUT nodes if not state_features not specified * - * • composition.py - _add_controller: modifying to instantiate feature_input_ports if none are specified * • composition.py: - add_controller: assign simulation_input_ports * - * • optimizationcontrolmechanism.py: - feature_input_ports -> state_input_ports - _instantiate_input_ports(): state_features only allowed to specifying state_input_ports if agent_rep is a CompositionFunctionApproximator (i.e., model-free optimization) • composition.py: - add_controller: adds state_input_ports to shadow INPUT Nodes of Composition if controller.agent_rep is Composition (model-based optimziation) or state_features have not been specified (for model-free optimizaton) * - * • optimizationcontrolmechanism.py: _instantiate_input_ports: reinstate allowance of state_features specification if agent_rep is a Composition (i.e., model-based optimization) as long as they are all INPUT Nodes of agent_rep * - * - * • optimizationcontrolmechanism.py - _gen_llvm_evaluate_function: num_estimates -> num_estimates_per_trial * - * • optimizationcontrolmechanism.py - _gen_llvm_evaluate_function: num_estimates -> num_trial_per_estimate * • optimizationcontrolmechanism.py - _gen_llvm_evaluate_function: num_estimates -> num_trials_per_estimate * - * - * - * - * • composition.py - __init__: moved controller instantiation until after nodes, projections and pathways * • composition.py - __init__: restored add_controller position * llvm/struct generation: Make sure num_estimats per trial is always integer Signed-off-by: Jan Vesely * - * • composition.py: - _update_controller: added - add_controller and _analyze_graph(): call _update_controller * - * • composition.py _update_controller: fixed to loop through all input_ports of comp INPUT nodes * • test_control.py - test_agent_rep_assignement_as_controller_and_replacement: updated to test that shadowing projections to state_input_ports are properly added and deleted * • optimizationfunctions.py: - _function: refactored to put use aggregation_function at end - _grid_evaluate: still needs to return all_samples * - * • composition.py - added call to _update_controller to add_node - moved test for projections to controller.state_input_ports to run() * - * • composition.py: moved calls to _update_controller to _complete_init_of_partially_initialized_nodes moved _update_controller to ocm._update_state_input_ports • optimizationcontrolmechanism.py: added _update_state_input_ports [**still needed work**] * • composition.py: moved calls to _update_controller to _complete_init_of_partially_initialized_nodes moved _update_controller to ocm._update_state_input_ports _instantiate_controller_shadow_projections [still needs to be implemented] • optimizationcontrolmechanism.py: added _update_state_input_ports [**still needed work**] * • composition.py added needs_update_controller * - * • composition.py: - implemented self.needs_update_controller - moved implementation of controlsignal projections from add_controller to _instantiate_control_projections that is called in _complete_init_of_partially_initialized_nodes Note: still need to set self.needs_update_controller to False after instantiating state_input_ports and projections to them * - * - * - * - * - * - * - * - * • Passing all test_control tests except test_mode_based_num_estimates * • Passing all test_control tests * - * • optimizationcontrolmechanism.py - _update_state_input_ports_for_controller: handle nested input nodes * - * • optimizationcontrolmechanism.py _update_state_input_ports_for_controller: fixed bug with > 1 INPUT node in Composition * • test_show_graph.py: passes all tests * - * • test_report.py: passing all tests * • Passes all tests! * - * - * • composition.py: reorganize with #region and #enregions * • composition.py: reorganize with #region and #enregions * • controlmechanism.py, optimizationcontrolmechanism.py: - _instantiate_monitor_for_control_input_ports -> _parse_monitor_control_input_ports - refactored to support allow_probes option on ocm * - * - * - * • controlmechanism.py, optimizationcontrolmechanism.py: - _instantiate_monitor_for_control_input_ports -> _parse_monitor_control_input_ports - refactored to support allow_probes option on ocm * • controlmechanism.py, optimizationcontrolmechanism.py: - _instantiate_monitor_for_control_input_ports -> _parse_monitor_control_input_ports - refactored to support allow_probes option on ocm * - * • composition.py: __init__: move controller to after add_nodes and add_linear_pathway * - * - test_control: only test_hanging_control_spec_outer_controller not passing * - * - * - * - * - * - * • composition.py: _instantiate_control_projections: weird requirement for double-call to controller._instantiate_control_signal * • test_paremtercomposition.py: restored parameter spec that causes crash ('threshold',Decision2) * ª Attempt to fix problem with partially overlapping local and ocm control specs - composition.py - _get_control_signals_for_composition: (see 11/20/21) - added (but commented out change) to "if node.controller" to "if not node.controller" - changed append to extend - _instantiation_control_projection: - got rid of try and except double-call to controller._instantiate_control_signals - outdented call to self.controller._activate_projections_for_composition at end - controlmechanism.py: - _check_for_duplicates: add warning and return duplicates - optimizationcontrolmechanism._instantiate_control_signals: - add call to self.agent_rep._get_control_signals_for_composition() to get local control specs (on mechs in comp) - eliminate duplicates with control_signal specs on OCM - instantiate local + ocm control_signals - parameterestimationcomposition.py - added context to various calls * see later commit * see later commit * see later commit * see later commit * - This branch passes all tests except: - test_parameterestimationcomposition - test_composition/test_partially_overlapping_control_specs (ADDED IN THIS COMMINT) - All relevant changes to this branch are marked as "11/21/21." However, most are commented out as they break other things. - The tests above both involve local control specifications (on mechanism within a nested comp) and on the OCM for the outer composition, some of which are for the same nested mechs - Both tests fail with: "AttributeError: 'NoneType' object has no attribute '_get_by_time_scale'" (in component.py LINE 3276) This may be due to a problem with context setting, since the error is because the modulation Parameter of the ControlProjection is returning "None" rather than "multiplicative_param" (when called with get(context)), whereas "multiplicative_param" is returned with a call to get() (i.e., with no context specified) - Most of test_partially_overlapping_control_specs is passed if changes marked "11/21/21 NEW" in optimizationcontrolmechanism.py (LINE 1390) are implemented, but it does not properly route ControlProjections through parameter_CIMS (see last assert in test). Furthermore, test_parameterestimationcompsition fails with the mod param error, even though the model has similar structure (i.e., outer composition -- in this case a ParameterEstimationComposition) with an OCM that is given control specs that overlap with ones in a nested composition. - There are also several other things in composition I found puzzling and tried modifying, but that cuased failures: - _get_control_signals_for_composition(): - seems "if node.controller" should be "if **not** node.controller" (emphasis added just for comment) - "append" should be "extend" - _instantiate_control_projection(): - call to self.controller._activate_projections_for_composition (at end of method) should not be indented * - small mods; don't impact anything relevant to prior commit message * - small mods; don't impact anything relevant to prior commit message * - small mods; don't impact anything relevant to prior commit message * - finished adding formatting regions to composition.py * - * • composition.py: - rename _check_projection_initialization_status -> _check_controller_initialization_status - add _check_nodes_initialization_status(context=context) (and calls it with _check_controller_initialization_status) * • show_graph.py: addressed bug associated with ocm.allow_direct_probe * • show_graph.py: addressed bug associated with ocm.allow_direct_probe * - * Composition: add_controller: set METHOD as context source early * - * • composition.py retore append of control_signals in _instantiate_control_projections() * • composition.py restore append of control_signals in _instantiate_control_projections() • test_composition.py: add test_partially_overlapping_local_and_control_mech_control_specs_in_unnested_and_nested_comp * • test_partially_overlapping_local_and_control_mech_control_specs_in_unnested_and_nested_comp(): - added clear_registry() to allow names to be reused in both runs of test * • composition.py docstring: added projections entry to list of attributes - add_controller: added call to _add_node_aux_components() for controller * • composition.py _add_node_aux_components(): added deletion of item from aux_components if instantiated * • composition.py - comment out _add_node_aux_components() (causing new failures) - move _instantiate_control_projections to be with _instantiate_control_projections, after self.add_node(self.controller.objective_mechanism (to be more orderly) * - * - confirm that it passes all tests exception test_composition/test_partially_overlapping... (with addition of _add_aux_components in add_controller commented out) * • composition.py: some more fixed to add_controller that now fail only one test: - test_agent_rep_assignement_as_controller_and_replacement * • Passes *all* current tests * • composition.py: - add_controller: few more minor mods; still passes all tests * - * - * - * • controlmechanism.py: - __init__: resrict specification to only one of control, modulatory_signals, or control_signals (synonyms) * - * • composition.py: in progress fix of bug in instantiating shadow projections for ocm.state_input_ports * • composition.py: - _get_original_senders(): added support for nested composition needs to be checked for more than one level needs to be refactored to be recursive * • optimizationcontrolmechanism.py - _update_state_input_ports_for_controller: fix invalid_state_features to allow input_CIM of nested comp in agent_rep * - * • composition.py - _get_original_senders: made recursive * • test_show_graph.py: update for fixes * - * • tests: passes all in test_show_graph.py and test_report.py * Passes all tests * - comment clean-up * • composition.py - add_controller and _get_nested_node_CIM_port: added support for forced assignment of NodeRole.OUTPUT for nodes specified in OCM.monitor_for_control, but referenced 'allow_probes' attribute still needs to be implemented * • composition.py, optimizationcontrolmechanism.py: allow_probes fully implemented * • show_graph.py: fixed bug causing extra projections to OCM * • composition.py: - _update_shadow_projections(): fix handling of deep nesting * • optimizationcontrolmechanism.py: add agent_rep_type property * • optimizationcontrolmechanism.py: - state_feature_function -> state_feature_functions * • optimizationcontrolmechanism.py: - _validate_params: validate state_feature_functions - _update_state_input_ports_for_controller: implement assignment of state_feature_functions * - * - * • Passes all tests except test_json with 'model_with_control' * - * • composition.py - add_projection: delete instantiation of shadow projections (handled by _update_shadow_projections) * • composition.py - add_projection: delete instantiation of shadow projections (handled by _update_shadow_projections) - remove calls to _update_shadows_dict * • composition.py - add_projection: delete instantiation of shadow projections (handled by _update_shadow_projections) - remove calls to _update_shadows_dict * - * • test_two_origins_two_input_ports: crashes on failure of C->B to update * - * • composition.py - added property shadowing_dict that has shadowing ports as keys and the ports they shadow as values - refactored _update_shadowing_projections to use shadowing_dict * • optimizationcontrolmechanism.py - _update_state_input_ports: modified validations for nested nodes; still failing some tests * • optimizationcontrolmechanism.py - _update_state_input_ports: more careful and informative validation that state_input_ports are in comp or nested comp and are INPUT nodes thereof; passes all tests except test_two_origins_two_input_ports as before * • composition.py _get_invalid_aux_components(): defer all shadow projections until _update_shadow_projections * • composition.py _get_invalid_aux_components(): bug fix in test for shadow projections * Port: _remove_projection_to_port: don't reduce variable below length 1 even ports with no incoming projections have variable at least length 1 * • composition.py add_node(): marked (but haven't removed) code block instantiating shadow_projections that seems now to be redundant with _update_shadow_projection * • show_graph.py - _assign_cim_components: supress showing projections not in composition * • composition.py: _analyze_graph(): add extra call to _determine_node_roles after _update_shadow_projections _run(): moved block of code at beginning initializing scheduler to after _complete_init_of_partially_initialized_nodes and _analyze_graph() • show_graph.py - add test to all loops on projections: "if proj in composition.projection" * • show_graph.py - add show_projections_not_in_composition option for debugging * • composition.py _update_shadow_projections(): delete unused shadow projections and corresponding ports * • composition.py _update_shadow_projections(): fix bug in deletion of unused shadow projections and ports • test_show_graph: tests failing, need mods to accomodate changes * • composition.py: _analyze_graph(): add extra call to _determine_node_roles after _update_shadow_projections _run(): moved block of code at beginning initializing scheduler to after _complete_init_of_partially_initialized_nodes and _analyze_graph() • show_graph.py - add test to all loops on projections: "if proj in composition.projection" * • show_graph.py fixes; now passes all show_graph tests * - * • composition.py _update_shadow_projections: raise error for attempt to shadow INTERNAL Node of nested comp * - * - * • test_composition.py implemented test_shadow_nested_nodes that tests shadowing of nested nodes * - * - * - * - Co-authored-by: jdcpni Co-authored-by: Jan Vesely Co-authored-by: Katherine Mantel --- ...on_Reward_rate_with_penalty_with_inputs.py | 2 +- .../Debug/Predator-Prey Sebastian REDUCED.py | 2 +- Scripts/Debug/Predator-Prey Sebastian.py | 2 +- Scripts/Debug/Umemoto_Feb.py | 2 +- Scripts/Debug/Umemoto_Feb2.py | 2 +- Scripts/Debug/new_umemoto.py | 2 +- .../predator_prey_opt/predator_prey_dmt.py | 2 +- Scripts/Debug/stability_flexibility_simple.py | 2 +- Scripts/Examples/EVC OCM.py | 2 +- Scripts/Examples/EVC-Gratton Composition.py | 2 +- .../Examples/EVC-Gratton-GaussianProcess.py | 2 +- Scripts/Examples/StabilityFlexibility.py | 2 +- .../Examples/Tutorial/Stroop Model - EVC.py | 4 +- .../Predator-Prey Model DQN LVOC.py | 2 +- psyneulink/core/components/component.py | 7 +- .../nonstateful/optimizationfunctions.py | 22 +- .../modulatory/control/controlmechanism.py | 201 ++-- .../control/optimizationcontrolmechanism.py | 820 ++++++++++--- psyneulink/core/components/ports/inputport.py | 14 +- psyneulink/core/components/ports/port.py | 9 +- psyneulink/core/compositions/composition.py | 1066 +++++++++-------- .../compositionfunctionapproximator.py | 3 + .../parameterestimationcomposition.py | 87 +- psyneulink/core/compositions/pathway.py | 2 +- psyneulink/core/compositions/report.py | 6 +- psyneulink/core/compositions/showgraph.py | 206 ++-- psyneulink/core/globals/keywords.py | 35 +- psyneulink/core/llvm/builder_context.py | 3 +- .../compositions/autodiffcomposition.py | 3 +- .../library/compositions/gymforagercfa.py | 8 +- .../library/compositions/regressioncfa.py | 85 +- tests/composition/test_composition.py | 149 ++- tests/composition/test_control.py | 131 +- .../test_parameterestimationcomposition.py | 26 +- tests/composition/test_report.py | 5 +- tests/composition/test_show_graph.py | 105 +- tests/json/model_with_control.py | 2 +- tests/log/test_log.py | 2 +- 38 files changed, 1957 insertions(+), 1070 deletions(-) diff --git a/Scripts/Debug/Jason_Reward_rate_with_penalty_with_inputs.py b/Scripts/Debug/Jason_Reward_rate_with_penalty_with_inputs.py index 4f7ac2be8d5..ca0d4ebf933 100644 --- a/Scripts/Debug/Jason_Reward_rate_with_penalty_with_inputs.py +++ b/Scripts/Debug/Jason_Reward_rate_with_penalty_with_inputs.py @@ -204,7 +204,7 @@ def get_stroop_model(unit_noise_std=.01, dec_noise_std=.1): inp_task.input_port, reward.input_port, punish.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.1), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.1), objective_mechanism=objective_mech, function=pnl.GridSearch(), control_signals=[driftrate_control_signal, diff --git a/Scripts/Debug/Predator-Prey Sebastian REDUCED.py b/Scripts/Debug/Predator-Prey Sebastian REDUCED.py index 15ec7e4928b..c62a30a4078 100644 --- a/Scripts/Debug/Predator-Prey Sebastian REDUCED.py +++ b/Scripts/Debug/Predator-Prey Sebastian REDUCED.py @@ -62,7 +62,7 @@ def get_new_episode_flag(): ocm = OptimizationControlMechanism(name='EVC', state_features=[trial_type_input_mech], - # state_feature_function=FEATURE_FUNCTION, + # state_feature_functions=FEATURE_FUNCTION, agent_rep=RegressionCFA( name='RegressionCFA', update_weights=BayesGLM(mu_0=0.5, sigma_0=0.1), diff --git a/Scripts/Debug/Predator-Prey Sebastian.py b/Scripts/Debug/Predator-Prey Sebastian.py index 491cb9f5a63..b332f104e11 100644 --- a/Scripts/Debug/Predator-Prey Sebastian.py +++ b/Scripts/Debug/Predator-Prey Sebastian.py @@ -167,7 +167,7 @@ def get_action(variable=[[0,0],[0,0],[0,0]]): ocm = OptimizationControlMechanism(name='EVC', state_features=[trial_type_input_mech], - # state_feature_function=FEATURE_FUNCTION, + # state_feature_functions=FEATURE_FUNCTION, agent_rep=RegressionCFA( name='RegressionCFA', update_weights=BayesGLM(mu_0=0.5, sigma_0=0.1), diff --git a/Scripts/Debug/Umemoto_Feb.py b/Scripts/Debug/Umemoto_Feb.py index e289c3225db..a8ba6f4b11b 100644 --- a/Scripts/Debug/Umemoto_Feb.py +++ b/Scripts/Debug/Umemoto_Feb.py @@ -120,7 +120,7 @@ Umemoto_comp.add_model_based_optimizer(optimizer=pnl.OptimizationControlMechanism(agent_rep=Umemoto_comp, state_features=[Target_Stim.input_port, Distractor_Stim.input_port, Reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=1.0), + state_feature_functions=pnl.AdaptiveIntegrator(rate=1.0), objective_mechanism=pnl.ObjectiveMechanism(monitor_for_control=[Reward, (Decision.output_ports[pnl.PROBABILITY_UPPER_THRESHOLD], 1, -1)], ), diff --git a/Scripts/Debug/Umemoto_Feb2.py b/Scripts/Debug/Umemoto_Feb2.py index 2815e4fbb2d..1b75225342e 100644 --- a/Scripts/Debug/Umemoto_Feb2.py +++ b/Scripts/Debug/Umemoto_Feb2.py @@ -132,7 +132,7 @@ state_features=[Target_Stim.input_port, Distractor_Stim.input_port, Reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=1.0), + state_feature_functions=pnl.AdaptiveIntegrator(rate=1.0), objective_mechanism=pnl.ObjectiveMechanism( monitor_for_control=[Reward, (Decision.output_ports[pnl.PROBABILITY_UPPER_THRESHOLD], 1, -1)], diff --git a/Scripts/Debug/new_umemoto.py b/Scripts/Debug/new_umemoto.py index e10028ee6ae..621b0b3744a 100644 --- a/Scripts/Debug/new_umemoto.py +++ b/Scripts/Debug/new_umemoto.py @@ -114,7 +114,7 @@ Umemoto_comp.add_model_based_optimizer(optimizer=pnl.OptimizationControlMechanism(agent_rep=Umemoto_comp, state_features={pnl.SHADOW_EXTERNAL_INPUTS: [Target_Stim, Distractor_Stim, Reward]}, - state_feature_function=pnl.AdaptiveIntegrator(rate=1.0), + state_feature_functions=pnl.AdaptiveIntegrator(rate=1.0), objective_mechanism=pnl.ObjectiveMechanism(monitor_for_control=[Reward, (Decision.output_ports[pnl.PROBABILITY_UPPER_THRESHOLD], 1, -1)], ), diff --git a/Scripts/Debug/predator_prey_opt/predator_prey_dmt.py b/Scripts/Debug/predator_prey_opt/predator_prey_dmt.py index f1f4e80bcf1..0eb89fb2ed7 100644 --- a/Scripts/Debug/predator_prey_opt/predator_prey_dmt.py +++ b/Scripts/Debug/predator_prey_opt/predator_prey_dmt.py @@ -195,7 +195,7 @@ def get_action(variable=[[0, 0], [0, 0], [0, 0]]): # ************************************** CONOTROL APPARATUS *********************************************************** self.ocm = OptimizationControlMechanism(name='EVC', state_features=[self.prey_pred_trial_input_mech, self.single_prey_trial_input_mech, self.double_prey_trial_input_mech], - # state_feature_function=FEATURE_FUNCTION, + # state_feature_functions=FEATURE_FUNCTION, agent_rep=RegressionCFA( update_weights=BayesGLM(mu_0=-0.0, sigma_0=0.0001), prediction_terms=[PV.F, PV.C, PV.COST] diff --git a/Scripts/Debug/stability_flexibility_simple.py b/Scripts/Debug/stability_flexibility_simple.py index f16443aafc0..b2bf6b133c1 100644 --- a/Scripts/Debug/stability_flexibility_simple.py +++ b/Scripts/Debug/stability_flexibility_simple.py @@ -164,7 +164,7 @@ def computeAccuracy(variable): meta_controller = pnl.OptimizationControlMechanism(agent_rep=stabilityFlexibility, state_features=[inputLayer.input_port, stimulusInfo.input_port], - state_feature_function=pnl.Buffer(history=100), + state_feature_functions=pnl.Buffer(history=100), objective_mechanism=objective_mech, function=pnl.GridSearch(), control_signals=[signal]) diff --git a/Scripts/Examples/EVC OCM.py b/Scripts/Examples/EVC OCM.py index 6216f00dc2a..362ac5e07db 100644 --- a/Scripts/Examples/EVC OCM.py +++ b/Scripts/Examples/EVC OCM.py @@ -32,7 +32,7 @@ comp.add_model_based_optimizer(optimizer=OptimizationControlMechanism(name='OCM', agent_rep=comp, state_features=[Input.input_port, reward.input_port], - state_feature_function=AdaptiveIntegrator(rate=0.5), + state_feature_functions=AdaptiveIntegrator(rate=0.5), objective_mechanism=ObjectiveMechanism( name='OCM Objective Mechanism', function=LinearCombination(operation=PRODUCT), diff --git a/Scripts/Examples/EVC-Gratton Composition.py b/Scripts/Examples/EVC-Gratton Composition.py index 7d5a35f610e..071ae433155 100644 --- a/Scripts/Examples/EVC-Gratton Composition.py +++ b/Scripts/Examples/EVC-Gratton Composition.py @@ -65,7 +65,7 @@ state_features=[target_stim.input_port, flanker_stim.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator( + state_feature_functions=pnl.AdaptiveIntegrator( rate=1.0), objective_mechanism=objective_mech, function=pnl.GridSearch(), diff --git a/Scripts/Examples/EVC-Gratton-GaussianProcess.py b/Scripts/Examples/EVC-Gratton-GaussianProcess.py index 32cd454e6ea..5148e22d8a9 100644 --- a/Scripts/Examples/EVC-Gratton-GaussianProcess.py +++ b/Scripts/Examples/EVC-Gratton-GaussianProcess.py @@ -52,7 +52,7 @@ comp.add_linear_processing_pathway(task_execution_pathway) ocm = pnl.OptimizationControlMechanism(state_features=[Input, Reward], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.5), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.5), agent_rep=comp, # function=pnl.GaussianProcessOptimization, function=pnl.GridSearch, diff --git a/Scripts/Examples/StabilityFlexibility.py b/Scripts/Examples/StabilityFlexibility.py index 1b5c5a1b254..2a5f3b2c23f 100644 --- a/Scripts/Examples/StabilityFlexibility.py +++ b/Scripts/Examples/StabilityFlexibility.py @@ -177,7 +177,7 @@ def computeAccuracy(variable): meta_controller = pnl.OptimizationControlMechanism(agent_rep=stabilityFlexibility, state_features=[inputLayer.input_port, stimulusInfo.input_port], - state_feature_function=pnl.Buffer(history=3), + state_feature_functions=pnl.Buffer(history=3), objective_mechanism=objective_mech, function=pnl.GridSearch(), control_signals=[signal]) diff --git a/Scripts/Examples/Tutorial/Stroop Model - EVC.py b/Scripts/Examples/Tutorial/Stroop Model - EVC.py index ef20720c04f..1db6570ad1d 100644 --- a/Scripts/Examples/Tutorial/Stroop Model - EVC.py +++ b/Scripts/Examples/Tutorial/Stroop Model - EVC.py @@ -64,8 +64,8 @@ evc = OptimizationControlMechanism(name='EVC', agent_rep=Stroop_model, state_features=[color_input.input_port, word_input.input_port, reward.input_port], - state_feature_function=AdaptiveIntegrator(rate=1.0), - # state_feature_function=AdaptiveIntegrator, + state_feature_functions=AdaptiveIntegrator(rate=1.0), + # state_feature_functions=AdaptiveIntegrator, objective_mechanism= \ ObjectiveMechanism( name='EVC Objective Mechanism', diff --git a/Scripts/Models (Under Development)/Predator-Prey Model DQN LVOC.py b/Scripts/Models (Under Development)/Predator-Prey Model DQN LVOC.py index 52db2a7a4fa..f6525841a6d 100644 --- a/Scripts/Models (Under Development)/Predator-Prey Model DQN LVOC.py +++ b/Scripts/Models (Under Development)/Predator-Prey Model DQN LVOC.py @@ -161,7 +161,7 @@ def get_action(variable=[[0,0],[0,0],[0,0]]): ocm = OptimizationControlMechanism(name='EVC', state_features=trial_type_input_mech, - state_feature_function=FEATURE_FUNCTION, + state_feature_functions=FEATURE_FUNCTION, agent_rep=RegressionCFA( update_weights=BayesGLM(mu_0=0.5, sigma_0=0.1), prediction_terms=[PV.F, PV.C, PV.COST] diff --git a/psyneulink/core/components/component.py b/psyneulink/core/components/component.py index 117558c96d7..959b874ba03 100644 --- a/psyneulink/core/components/component.py +++ b/psyneulink/core/components/component.py @@ -1363,7 +1363,7 @@ def _get_compilation_params(self): # Invalid types "input_port_variables", "results", "simulation_results", "monitor_for_control", "state_feature_values", "simulation_ids", - "input_labels_dict", "output_labels_dict", + "input_labels_dict", "output_labels_dict", "num_estimates", "modulated_mechanisms", "grid", "control_signal_params", "activation_derivative_fct", "input_specification", # Reference to other components @@ -1448,9 +1448,8 @@ def _get_values(p): # Modulated parameters change shape to array if np.ndim(param) == 0 and self._is_param_modulated(p): return (param,) - elif p.name == 'num_estimates': - return 0 if param is None else param - # FIX: ADD num_trials_per_estimate HERE 11/3/21 + elif p.name == 'num_trials_per_estimate': # Should always be int + return 0 if param is None else int(param) elif p.name == 'matrix': # Flatten matrix return tuple(np.asfarray(param).flatten()) return _convert(param) diff --git a/psyneulink/core/components/functions/nonstateful/optimizationfunctions.py b/psyneulink/core/components/functions/nonstateful/optimizationfunctions.py index 0f35262b13c..dc9d110d404 100644 --- a/psyneulink/core/components/functions/nonstateful/optimizationfunctions.py +++ b/psyneulink/core/components/functions/nonstateful/optimizationfunctions.py @@ -71,6 +71,13 @@ def __init__(self, error_value): self.error_value = error_value +def _num_estimates_getter(owning_component, context): + if owning_component.parameters.randomization_dimension._get(context) is None: + return 1 + else: + return owning_component.parameters.search_space._get(context)[owning_component.randomization_dimension].num + + class OptimizationFunction(Function_Base): """ OptimizationFunction( \ @@ -308,6 +315,12 @@ class Parameters(Function_Base.Parameters): :default value: None :type: + num_estimates + see `num_estimates ` + + :default value: None + :type: ``int`` + objective_function see `objective_function ` @@ -371,6 +384,9 @@ class Parameters(Function_Base.Parameters): search_termination_function = Parameter(lambda x, y, z: True, stateful=False, loggable=False) search_space = Parameter([SampleIterator([0])], stateful=False, loggable=False) randomization_dimension = Parameter(None, stateful=False, loggable=False) + num_estimates = Parameter(None, stateful=True, loggable=True, read_only=True, + dependencies=[randomization_dimension, search_space], + getter=_num_estimates_getter) save_samples = Parameter(False, pnl_internal=True) save_values = Parameter(False, pnl_internal=True) @@ -642,12 +658,6 @@ def _report_value(self, new_value): """Report value returned by `objective_function ` for sample.""" pass - @property - def num_estimates(self): - if self.randomization_dimension is None: - return 1 - else: - return self.search_space[self.randomization_dimension].num class GridBasedOptimizationFunction(OptimizationFunction): """Implement helper method for parallelizing instantiation for evaluating samples from search space.""" diff --git a/psyneulink/core/components/mechanisms/modulatory/control/controlmechanism.py b/psyneulink/core/components/mechanisms/modulatory/control/controlmechanism.py index b098957d896..8f8bd9621e5 100644 --- a/psyneulink/core/components/mechanisms/modulatory/control/controlmechanism.py +++ b/psyneulink/core/components/mechanisms/modulatory/control/controlmechanism.py @@ -585,7 +585,7 @@ from psyneulink.core.components.ports.modulatorysignals.controlsignal import ControlSignal from psyneulink.core.components.ports.outputport import OutputPort from psyneulink.core.components.ports.parameterport import ParameterPort -from psyneulink.core.components.ports.port import Port, _parse_port_spec, PortError +from psyneulink.core.components.ports.port import Port, _parse_port_spec from psyneulink.core.globals.defaults import defaultControlAllocation from psyneulink.core.globals.keywords import \ AUTO_ASSIGN_MATRIX, COMBINE, CONTROL, CONTROL_PROJECTION, CONTROL_SIGNAL, CONTROL_SIGNALS, CONCATENATE, \ @@ -1254,20 +1254,42 @@ def __init__(self, monitor_for_control = convert_to_list(monitor_for_control) or [] control = convert_to_list(control) or [] + # For backward compatibility: if kwargs: if MONITOR_FOR_MODULATION in kwargs: args = kwargs.pop(MONITOR_FOR_MODULATION) if args: monitor_for_control.extend(convert_to_list(args)) + + # Only allow one of CONTROL, MODULATORY_SIGNALS OR CONTROL_SIGNALS to be specified + # These are synonyms, but allowing several to be specified and trying to combine the specifications + # can cause problems if different forms of specification are used to refer to the same Component(s) + control_specified = "'control'" if control else '' + modulatory_signals_specified = '' if MODULATORY_SIGNALS in kwargs: args = kwargs.pop(MODULATORY_SIGNALS) if args: - control.extend(convert_to_list(args)) + if control: + modulatory_signals_specified = f"'{MODULATORY_SIGNALS}'" + raise ControlMechanismError(f"Both {control_specified} and {modulatory_signals_specified} " + f"arguments have been specified for {self.name}. " + f"These are synonyms, but only one should be used to avoid " + f"creating unnecessary and/or duplicated Components.") + control = convert_to_list(args) if CONTROL_SIGNALS in kwargs: args = kwargs.pop(CONTROL_SIGNALS) if args: - control.extend(convert_to_list(args)) + if control: + if control_specified and modulatory_signals_specified: + prev_spec = ", ".join([control_specified, modulatory_signals_specified]) + else: + prev_spec = control_specified or modulatory_signals_specified + raise ControlMechanismError(f"Both {prev_spec} and '{CONTROL_SIGNALS}' arguments " + f"have been specified for {self.name}. " + f"These are synonyms, but only one should be used to avoid " + f"creating unnecessary and/or duplicated Components.") + control = convert_to_list(args) function = function or DefaultAllocationFunction @@ -1377,6 +1399,7 @@ def _instantiate_objective_mechanism(self, input_ports=None, context=None): # GET OutputPorts to Monitor (to specify as or add to ObjectiveMechanism's monitored_output_ports attribute # FIX: 11/3/21: put OUTCOME InputPort at the end rather than the beginning + # THEN SEE ALL INSTANCES IN COMMENTS OF: "NEED TO MODIFY ONCE OUTCOME InputPorts ARE MOVED" # Other input_ports are those passed into this method, that are presumed to be for other purposes # (e.g., used by OptimizationControlMechanism for representing state_features as inputs) # those are appended after the OUTCOME InputPort # FIX <- change to prepend when refactored @@ -1485,82 +1508,117 @@ def _instantiate_input_ports(self, input_ports=None, context=None): other_input_ports = input_ports or [] - # FIX 11/3/21: THIS SHOULD BE MODIFIED TO BE A LIST, THAT CONTAINS REFERENCES TO THE OUTCOME InputPorts + # FIX 11/3/21: THIS SHOULD BE MADE A PARAMETER self.outcome_input_ports = ContentAddressableList(component_type=OutputPort) # If ObjectiveMechanism is specified, instantiate it and OUTCOME InputPort that receives projection from it if self.objective_mechanism: # This instantiates an OUTCOME InputPort sized to match the ObjectiveMechanism's OUTCOME OutputPort + # Note: in this case, any items specified in monitor_for_control are passed to the **monitor** argument + # of the objective_mechanism's constructor self._instantiate_objective_mechanism(input_ports, context=context) # If no ObjectiveMechanism is specified, but items to monitor are specified, + # assign an outcome_input_port for each item specified elif self.monitor_for_control: - monitored_for_control_ports, \ - monitor_for_control_value_sizes = self._instantiate_montiored_for_control_input_ports(context) + # Get outcome_input_port_specs without including specifications of Projections to them, as those need to + # be constructed and specified as aux_components (below) for validation and activation by Composition + outcome_input_port_specs, outcome_value_sizes, projection_specs \ + = self._parse_monitor_for_control_input_ports(context) # Get sizes of input_ports passed in (that are presumably used for other purposes; - # e.g., ones used by OptimizationControlMechanism for state_features) + # e.g., ones used by OptimizationControlMechanism for simulated inputs or state_features) other_input_port_value_sizes = self._handle_arg_input_ports(other_input_ports)[0] # Construct full list of InputPort specifications and sizes - input_ports = monitored_for_control_ports + other_input_ports - input_port_value_sizes = monitor_for_control_value_sizes + other_input_port_value_sizes + input_ports = outcome_input_port_specs + other_input_ports + input_port_value_sizes = outcome_value_sizes + other_input_port_value_sizes super()._instantiate_input_ports(context=context, input_ports=input_ports, reference_value=input_port_value_sizes) # FIX: 11/3/21 NEED TO MODIFY ONCE OUTCOME InputPorts ARE MOVED - self.outcome_input_ports.extend(self.input_ports[:len(monitored_for_control_ports)]) - # FIX: 11/3/21 DELETE ONCE THIS IS A PROPERTY + self.outcome_input_ports.extend(self.input_ports[:len(outcome_input_port_specs)]) + + # Instantiate Projections to outcome_input_ports from items specified in monitor_for_control + # (list of which were placed in self.aux_components by _parse_monitor_for_control_input_ports) + option = self.outcome_input_ports_option + from psyneulink.core.components.projections.pathway.mappingprojection import MappingProjection + from psyneulink.core.components.mechanisms.processing.objectivemechanism import _parse_monitor_specs + + self.aux_components = [] + for i in range(len(projection_specs)): + if option == SEPARATE: + # Each outcome_input_port get its own Projection + outcome_port_index = i + else: + # The single outcome_input_port gets all the Projections + outcome_port_index = 0 + self.aux_components.append(MappingProjection(sender=projection_specs[i], + receiver=self.outcome_input_ports[outcome_port_index])) # Nothing has been specified, so just instantiate the default OUTCOME InputPort else: super()._instantiate_input_ports(context=context) self.outcome_input_ports.append(self.input_ports[OUTCOME]) - def _instantiate_montiored_for_control_input_ports(self, context): - """Instantiate InputPorts for items specified in monitor_for_control. + def _parse_monitor_for_control_input_ports(self, context): + """Get outcome_input_port specification dictionaries for items specified in monitor_for_control. - Return sender ports and their value sizes + Note: leave Projections unspecified, as they need to be added to self.aux_components + for validation and activation by Composition + + Return port specification dictionaries (*without* Projections to them specified), their value sizes, + and monitored ports (to be used as Projection specifications by _instantiate_input_ports) """ - monitor_for_control_specs = self.monitor_for_control - option = self.outcome_input_ports_option # FIX: 11/3/21 - MOVE _parse_monitor_specs TO HERE FROM ObjectiveMechanism from psyneulink.core.components.mechanisms.processing.objectivemechanism import _parse_monitor_specs - monitored_ports = _parse_monitor_specs(monitor_for_control_specs) - port_value_sizes = self._handle_arg_input_ports(monitor_for_control_specs)[0] + monitored_ports = _parse_monitor_specs(self.monitor_for_control) + port_value_sizes = self._handle_arg_input_ports(self.monitor_for_control)[0] + + outcome_input_ports_option = self.outcome_input_ports_option - # Construct port specification to assign its name - if option == SEPARATE: + outcome_input_port_specs = [] + + # SEPARATE outcome_input_ports OPTION: + # Assign separate outcome_input_ports for each item in monitored_ports + if outcome_input_ports_option == SEPARATE: + + # Construct port specification to assign its name for i, monitored_port in enumerate(monitored_ports): name = monitored_port.name if isinstance(monitored_port, OutputPort): name = f"{monitored_port.owner.name}[{name.upper()}]" name = 'MONITOR ' + name - monitored_ports[i] = {PORT_TYPE: InputPort, name: monitored_port} - return monitored_ports, port_value_sizes + outcome_input_port_specs.append({PORT_TYPE: InputPort, + NAME: name}) + # Return list of outcome_input_port specifications (and their sizes) for each monitored item - if option == CONCATENATE: - function = Concatenate + # SINGLE outcome_input_port OPTIONS: + # Either combine or concatenate inputs from all items specified in monitor_for_control + # as input to a single outcome_input_port + else: - elif option == COMBINE: - function = LinearCombination + if outcome_input_ports_option == CONCATENATE: + function = Concatenate - else: - assert False, f"PROGRAM ERROR: Unrecognized option ({option}) passed to " \ - f"ControlMechanism._instantiate_montiored_for_control_input_ports() for {self.name}" + elif outcome_input_ports_option == COMBINE: + function = LinearCombination - port_value_sizes = [function().function(port_value_sizes)] + else: + assert False, f"PROGRAM ERROR: Unrecognized option ({outcome_input_ports_option}) passed " \ + f"to ControlMechanism._parse_monitor_for_control_input_ports() for {self.name}" + + port_value_sizes = [function().function(port_value_sizes)] - outcome_input_port = {PORT_TYPE: InputPort, - NAME: 'OUTCOME', - FUNCTION: function, - # SIZE: len(self._handle_arg_input_ports(monitor_for_control_specs)[0]) - PROJECTIONS: monitored_ports} - return [outcome_input_port], port_value_sizes + # Return single outcome_input_port specification + outcome_input_port_specs.append({PORT_TYPE: InputPort, + NAME: 'OUTCOME', + FUNCTION: function}) + return outcome_input_port_specs, port_value_sizes, monitored_ports def _instantiate_output_ports(self, context=None): @@ -1589,7 +1647,7 @@ def _register_control_signal_type(self, context=None): ) def _instantiate_control_signals(self, context): - """Subclassess can override for class-specific implementation (see OptimiziationControlMechanism for example)""" + """Subclassess can override for class-specific implementation (see OptimizationControlMechanism for example)""" output_port_specs = list(enumerate(self.output_ports)) for i, control_signal in output_port_specs: @@ -1704,8 +1762,13 @@ def _check_for_duplicates(self, control_signal, control_signals, context): and also in the ControlMechanism's **control** arg control_signals arg passed in to allow override by subclasses - """ + Warn if control_signal shares any ControlProjections with others in control_signals. + Warn if control_signal is a duplicate of any in control_signals. + + Return True if control_signal is a duplicate + """ + duplicates = [] for existing_ctl_sig in control_signals: # OK if control_signal is one already assigned to ControlMechanism (i.e., let it get processed below); # this can happen if it was in deferred_init status and initalized in call to _instantiate_port above. @@ -1718,17 +1781,19 @@ def _check_for_duplicates(self, control_signal, control_signals, context): # A Projection in control_signal is not in this existing one: it is different, # so break and move on to next existing_mod_sig break - return + warnings.warn(f"{control_signal.name} for {self.name} duplicates another one specified " + f"({existing_ctl_sig.name}); it will be ignored.") + return True # Warn if *any* projections from control_signal are identical to ones in an existing control_signal projection_type = existing_ctl_sig.projection_type - if any( - any(new_p.receiver == existing_p.receiver - for existing_p in existing_ctl_sig.efferents) for new_p in control_signal.efferents): + if any(any(new_p.receiver == existing_p.receiver + for existing_p in existing_ctl_sig.efferents) for new_p in control_signal.efferents): warnings.warn(f"Specification of {control_signal.name} for {self.name} " - f"has one or more {projection_type}s redundant with ones already on " + f"has one or more {projection_type.__name__}s redundant with ones already on " f"an existing {ControlSignal.__name__} ({existing_ctl_sig.name}).") + def show(self): """Display the OutputPorts monitored by ControlMechanism's `objective_mechanism ` and the parameters modulated by its `control_signals @@ -1792,6 +1857,7 @@ def add_to_monitor(self, monitor_specs, context=None): output_ports = self.objective_mechanism.add_to_monitor(monitor_specs=monitor_specs, context=context) def _add_process(self, process, role:str): + assert False super()._add_process(process, role) if self.objective_mechanism: self.objective_mechanism._add_process(process, role) @@ -1812,7 +1878,7 @@ def _remove_default_control_signal(self, type:tc.enum(CONTROL_SIGNAL, GATING_SIG and not ctl_sig_attribute[0].efferents): self.remove_ports(ctl_sig_attribute[0]) - # FIX: 11/3/21 SHOULDN'T THIS BE PUT ON COMPOSITION?? + # FIX: 11/15/21 SHOULDN'T THIS BE PUT ON COMPOSITION?? def _activate_projections_for_compositions(self, composition=None): """Activate eligible Projections to or from Nodes in Composition. If Projection is to or from a node NOT (yet) in the Composition, @@ -1821,39 +1887,36 @@ def _activate_projections_for_compositions(self, composition=None): dependent_projections = set() if composition: + # Ensure that objective_mechanism has been included in the ControlMechanism's aux_components + # and then add all Projections to and from the objective_mechanism to it if self.objective_mechanism and self.objective_mechanism in composition.nodes: - # Safe to add this, as it is already in the ControlMechanism's aux_components + # Safe to assert this, as it is already in the ControlMechanism's aux_components # and will therefore be added to the Composition along with the ControlMechanism from psyneulink.core.compositions.composition import NodeRole assert (self.objective_mechanism, NodeRole.CONTROL_OBJECTIVE) in self.aux_components, \ f"PROGRAM ERROR: {OBJECTIVE_MECHANISM} for {self.name} not listed in its 'aux_components' attribute." dependent_projections.add(self._objective_projection) - + # Add all Projections to and from objective_mechanism for aff in self.objective_mechanism.afferents: dependent_projections.add(aff) + # for output_port in self.objective_mechanism.monitored_output_ports: + # for eff in output_port.efferents: + # dependent_projections.add(eff) + for eff in self.objective_mechanism.efferents: + dependent_projections.add(eff) else: - # FIX: NOTE: This will apply if controller has an objective_mechanism but it is not in the Composition - # FIX: 11/3/21: THIS NEEDS TO BE ADJUSTED IF OUTCOME InputPorts ARE MOVED ZZZ + # FIX: 11/3/21: NEED TO MODIFY ONCE OUTCOME InputPorts ARE MOVED # Add Projections to controller's OUTCOME InputPorts + # Note: this applies if ControlMechanism has an objective_mechanism that is not in the Composition for i in range(self.num_outcome_input_ports): for proj in self.outcome_input_ports[i].path_afferents: dependent_projections.add(proj) - for ms in self.control_signals: - for eff in ms.efferents: - dependent_projections.add(eff) - - # ??ELIMINATE SYSTEM - # FIX: 9/15/19 AND 11/3/21 - HOW IS THIS DIFFERENT THAN objective_mechanism's AFFERENTS ABOVE? - # assign any deferred init objective mech monitored OutputPort projections to this Composition - if self.objective_mechanism and composition and self.objective_mechanism in composition.nodes: - for output_port in self.objective_mechanism.monitored_output_ports: - for eff in output_port.efferents: - dependent_projections.add(eff) - - # # FIX: 9/15/19 AND 11/3/21 - HOW IS THIS DIFFERENT THAN control_signal's EFFERENTS ABOVE? - # for eff in self.efferents: - # dependent_projections.add(eff) + # Warn if any efferents have been added to the ContolMechanism that are not ControlSignals + if len(self.control_projections) != len(self.efferents): + warnings.warn(f"Projections from {self.name} have been added to {composition} that are not ControlSignals.") + for eff in self.efferents: + dependent_projections.add(eff) if composition: deeply_nested_aux_components = composition._get_deeply_nested_aux_projections(self) @@ -1889,18 +1952,18 @@ def monitored_output_ports(self, value): return None @property - def num_outcome_input_ports(self): + def monitored_output_ports_weights_and_exponents(self): try: - return len(self.outcome_input_ports) + return self.objective_mechanism.monitored_output_ports_weights_and_exponents except: - return 0 + return None @property - def monitored_output_ports_weights_and_exponents(self): + def num_outcome_input_ports(self): try: - return self.objective_mechanism.monitored_output_ports_weights_and_exponents + return len(self.outcome_input_ports) except: - return None + return 0 @property def control_signals(self): diff --git a/psyneulink/core/components/mechanisms/modulatory/control/optimizationcontrolmechanism.py b/psyneulink/core/components/mechanisms/modulatory/control/optimizationcontrolmechanism.py index 6ef3ece3d5d..6f92f85f3a1 100644 --- a/psyneulink/core/components/mechanisms/modulatory/control/optimizationcontrolmechanism.py +++ b/psyneulink/core/components/mechanisms/modulatory/control/optimizationcontrolmechanism.py @@ -80,7 +80,7 @@ parameterizations of OptimizationControlMechanism that implement various models of EVC Optimization. ### FIX: THROUGHOUT DOCUMENT, REWORD AS "optimizing control_allocation" RATHER THAN "maximizing" / "greatest" -### FIX: RESTORE agent_rep from agent_rep +### FIX: ADD REFERENCE TO agent_rep_type ATTRIBUTE COMMENT @@ -102,7 +102,7 @@ FULL MODEL-BASED USES THE COMPOSITION ITSELF AS THE OCM (BEST ESTIMATE IT HAS FOR ITS OWN POLICY) AND ACCESS TO STATE REPRESENTATIONS THAT FULLY DESCRIBE ALL EXPECTED STATES (I.E., DUPLICATE THE GENERATIVE PROCESS FOR) THE ENVIRONMENT. SO, FULLY MODEL-BASED PROCESSING USES THE COMPOSITION ITSELF AS THE agent_rep AND A FULLY GENERATIVE - MODEL FOR THE ENVIRONMENT AS THE state_feature_function + MODEL FOR THE ENVIRONMENT AS THE state_feature_functions PROVIDES 1/2 OF THIS; AT THE FAR OTHER EXTREME, MODEL-FREE CORRESPONDS TO USING THE CURRENT (OR PREDICTED) INPUTS FOR THE STATE @@ -123,16 +123,16 @@ algorithms or other forms of function approximation) that can be assigned as the OptimizationControlMechanism's `agent_rep `. -This is implemented by assigning as the `agent_rep ` a Composition other than the -one to which the OptimizationControlMechanism belongs (and for which it is the `controller `). -In each `TRIAL `, the `agent_rep ` is given the chance to -adapt, by adjusting its parameters in order to improve its prediction of the `net_outcome -` for the Composition (or part of one) that is controlled by the -OptimizationControlMechanism (based on the `state ` and `net_outcome -` of the prior trial). The `agent_rep ` is -then used to predict the `net_outcome ` for `control_allocation -` samples to find the one that yields the best predicted `net_outcome -` of processing on the upcoming trial, based on the current or (expected) +This is implemented by assigning as the `agent_rep ` a Composition other than +the one to which the OptimizationControlMechanism has been assigned as the `controller `), +or it is assigned a `CompositionFunctionApproximator`. In each `TRIAL `, the `agent_rep +` is given the chance to adapt, by adjusting its parameters in order to +improve its prediction of the `net_outcome ` for the Composition (or part of one) +that is controlled by the OptimizationControlMechanism (based on the `state ` +and `net_outcome ` of the prior trial). The `agent_rep +` is then used to predict the `net_outcome ` +for `control_allocation ` samples to find the one that yields the best predicted +`net_outcome ` of processing on the upcoming trial, based on the current or (expected) `state_feature_values ` for that trial. .. _OptimizationControlMechanism_Model_Based: @@ -151,34 +151,136 @@ Creating an OptimizationControlMechanism ---------------------------------------- -An OptimizationControlMechanism is created in the same was as any `ControlMechanism `. -The following arguments of its constructor are specific to the OptimizationControlMechanism: +The constructor for an OptimizationControlMechanism has the same arguments as a `ControlMechanism `, +with the following exceptions/additions, which are specific to the OptimizationControlMechanism: .. _OptimizationControlMechanism_State_Features_Arg: -* **state_features** -- takes the place of the standard **input_ports** argument in the constructor for a Mechanism`, - and specifies the values used by the OptimizationControlMechanism, together with a `control_allocation - `, to calculate a `net_outcome `. For - `model-based optimization ` these are also used as the inputs to the - Composition (i.e., `agent_rep `) when it's `evaluate ` - method is called (see `OptimizationControlMechanism_State_Features` below). Features can be specified using - any of the following, singly or combined in a list: +# FIX: 11/3/21: * REWORK TO EXPLAIN DIFFERENCES IN USE FOR MODEL-FREE VS. MODEL-BASED OPTIMIZATION + RE: state_feature SPECIFICATION: + - FOR MODEL-FREE **state_features**: + IF CompositionFunctionAppromixmator IS SPECIFIED AS agent_rep, THEN THESE MUST BE + SPECIFIED AND MUST MATCH THE INPUT TO THE **feature_values** ARGUMENT OF ITS EVALUATE METHOD + NOT VALIDATED; + IF ANY InputPorts ARE SPECIFIED (OF INPUT nodes OF THE COMPOSITION OR ANY ANOTHER Nodes) + SHADOW_PROJECTIONS ARE ASSIGNED + - FOR MODE-FREE WITH COMPOSITION AS agent_rep OR MODEL-BASED (ALWAYS A COMPOSITION AS agent_rep): + THE state_features ARE ALWAYS ALL OF THE INPUT nodes TO THE agent_rep + ANY THAT ARE EXPLICITLY SPECIFIED ARE ASSGINED THE stat_function_arg + ANY NOT SPECIFIED ARE AUTOMATCIALLY CREATED AND ASSIGNED THE DEFAULT InputPort Function + ANY SPECIFIED THAT ARE NOT AN InputPort TO AN INPUT Node OF THE agent_rep COMPOSITION + WILL CAUSE AND ERROR TO BE GENERATED + ALL ARE ASSIGNED SHADOW_PROJECTIONS + - ADD REFERENCE TO agent_rep_type ATTRIBUTE + + HINTS: + 1) IF ONLY SOME INPUTS ARE DESIRED FOR MODEL-BASED, USE Control FOR ATTENTIONAL REGULATION + (SEE PREDATOR PREY AS EXAMPLE?) + 2) IF A RESTRICTED PART OF THE NETWORK IS TO BE USED FOR MODEL-BASED, SIMPLY MAKE THAT + A NESTED COMPOSITION, AND ASSIGN THAT AS THE agent_rep; THEN *ITS* INPUT Nodes WILL BE USED + AS THE state_features, AND JUST THAT NESTED COMPOSITION WILL BE USED FOR SIMULATIONS + (CONSTRUCT EXAMPLES) + + + FROM BELOW: + + # FIX: MOVE MOST OF THIS TO _OptimizationControlMechanism_State_Features_Arg ABOVE. + # HERE FOCUS ON state_input_ports AND shadow_projections, + * *Model-free optimization*: the + - if a Composition is used, then state features specify inputs to the Composition, and there must be + one for every INPUT Node of the Composition; this is checked when the Composition to which the OCM + belongs is run(); any state_input_ports that don't exist are added, and any + + - if a CompositionFunctionApproximator is used, then they must align with the arguments to the + CompositionFunctionApproximator's `evaluate ` method; + since the latter cannot be determined programmatically, the `state_input_ports + `) cannot be created automatically nor validated + when a CompositionFunctionApproximator is used; in that case all of the **state_features** must be + validly specified in the OptimizationControlMechanism's constructor. + + the `CompositionFunctionApproximator` used as its `agent_rep ` in + `model-free optimization `; or that shadow the inputs of the + Composition assigned as its `agent_rep ` and that provide the inputs + to the `evaluate ` method of the Composition when it is used to simulate performance in + `model-based optimization ` + + + + By default, these are the current `input ` for the Composition to which the + OptimizationControlMechanism belongs. However, different values can be specified, as can a `state_feature_functions + ` that transforms these (see `above + `). + + For OptimizationControlMechanisms that + implement `model-free ` optimization, its `state_feature_values + ` are used by its `evaluate_agent_rep + ` method to predict the `net_outcome ` + for a given `control_allocation `. For OptimizationControlMechanisms that + implement fully `agent_rep-based ` optimization, the `state_feature_values + ` are used as the Composition's `input ` + when it is executed to evaluate the `net_outcome ` for a given + `control_allocation`. + + State features can be of two types: + + * *Input Features* -- these are values received as input by other Mechanisms in the `Composition`. + They are specified as `shadowed inputs ` in the **state_features** argument + of the OptimizationControlMechanism's constructor (see `OptimizationControlMechanism_Creation`). + An InputPort is created and assigned to the OptimizationControlMechanism's `state_input_ports + ` attribute for each feature, that receives a + `Projection` paralleling the input to be shadowed. + .. + * *Output Features* -- these are the `value ` of an `OutputPort` of some other + `Mechanism ` in the Composition. These too are specified in the **state_features** argument of the + OptimizationControlMechanism's constructor (see `OptimizationControlMechanism_Creation`), and each is assigned a + `Projection` from the specifiedOutputPort(s) to the InputPort of the OptimizationControlMechanism for that feature. + +ORIGINAL: + +* **state_features** -- specifies the values used by the OptimizationControlMechanism, together with a + `control_allocation `, to calculate a `net_outcome + `. By default, these are the current `input ` for the + Composition to which the OptimizationControlMechanism belongs. However, other values can be specified, in which + case those replace the inputs to the Composition which, if still desired, must be explicitly specified. If all + of the inputs to the Composition are still required, these can be specified using the keyword *INPUTS*, in which + case they are retained along with any others specified. Individual inputs to the Composition can be specified, + as well as the inputs to or outputs of any of its `Nodes `, using any of the following, either + singly or in a list: * *InputPort specification* -- this can be any form of `InputPort specification ` that resolves to an OutputPort from which the InputPort receives a Projection; the `value ` of that OutputPort is used as one of the `state_feature_values ` for the `state_features - ` of the OptimizationControlMechanism. Each of these InputPorts is - marked as `internal_only ` = `True`. + ` of the OptimizationControlMechanism. + + .. technical_note:: + The InputPorts specified as state_features are marked as `internal_only ` = `True`; + + * *Output specification* -- this can be any form of `OutputPort specification ` + for any `OutputPort` of another `Mechanism ` in the Composition; the `value ` + of the specified OutputPort is used as one of the `state_feature_values + ` for the `state_features + ` of the OptimizationControlMechanism. Features can also be added to an existing OptimizationControlMechanism using its `add_state_features` method. If the **state_features** argument is not specified, then the `input ` to the `Composition` on - the last trial of its execution is used to predict the `net_outcome ` for the upcoming - trial. + the last trial executed is used to predict the `net_outcome ` for the upcoming trial; + COMMENT: + FIX: CONFIRM THE FOLLOWING + COMMENT + if `controller_mode ` = *AFTER*, the input used is from the trial just + executed; if it is *BEFORE*, then it is from the previous trial. .. _OptimizationControlMechanism_Feature_Function_Arg: -* **state_feature_function** -- specifies `function ` of the InputPort created for each item listed in +COMMENT: + FIX: 11/26/21 EXPLAIN WHAT IS ACTUALLY FINALLY IMPLEMENTED: + PRESUMABLY THAT IF A SINGLE FUNCTION IS SPECIFIED, IT WILL BE APPLIED TO ALL state_input_ports + OTHERWISE A DICTIONARY MUST BE PROVIDED WITH A KEY FOR EACH state_input_port AND ITS FUNCTION AS THE VALUE + AND THIS CAN ONLY INCLUDE SPECIFIED state_features OR, IF THEY WERE AUTOMATICALY GENERATED, THEN + THE InputPorts OF ANY INPUT NODES ON THE agent_rep AND/OR ANY NESTED COMPOSITIONS WITHIN IT. +COMMENT +* **state_feature_functions** -- specifies `function ` of the InputPort created for each item listed in **state_features**. By default, this is the identity function, that assigns the current value of the feature to the OptimizationControlMechanism's `state_feature_values `attribute. However, other functions can be assigned, for example to maintain a record of past values, integrate them over @@ -256,36 +358,48 @@ *State Features* ^^^^^^^^^^^^^^^^ -In addition to its `primary InputPort ` (which typically receives a projection from the -*OUTCOME* OutputPort of the `objective_mechanism `, an -OptimizationControlMechanism also has an `InputPort` for each of its state_features. By default, these are the current -`input ` for the Composition to which the OptimizationControlMechanism belongs. However, -different values can be specified, as can a `state_feature_function ` -that transforms these. For OptimizationControlMechanisms that implement `model-free -` optimization, its `state_feature_values -` are used by its `evaluate_agent_rep -` method to predict the `net_outcome ` -for a given `control_allocation `. For OptimizationControlMechanisms that -implement fully `agent_rep-based ` optimization, the `state_feature_values -` are used as the Composition's `input ` -when it is executed to evaluate the `net_outcome ` for a given -`control_allocation`. +In addition to its `outcome_input_ports `, that receive Projections from +either the OptimizationControlMechanism's `objective_mechanism ` or directly +from the items in `monitor_for_control `, it also has `state_input_ports` that +receive Projections from any items specified in the **state_features** argument of the OptimizationControlMechanism's +constructor, or that are automatically constructed, based on the `agent_rep `. +These are used to provide the `state_feature_values ` to the +`agent_rep ` when it is executed. If the `agent_rep +is a `CompositionFunctionApproximator (`model-free optimization `), +then the OptimizationControlMechanism has a state_input_port for each **state_feature** specified. If the +`agent_rep ` is a Composition (`model-based optimization +`), then the OptimizationControlMechanism has a state_input_port for +every InputPort of every *INPUT* `Node ` of the `agent_rep` +Composition, each of which receives a `Projection` that `shadows its input ` (see +`OptimizationControlMechanism_State_Features` for additional details). In either, case the the `values +` of the `state_input_ports ` are used to +generate the `state_feature_values ` that, in turn, are used by the +OptimizationControlMechanism's `evaluate_agent_rep ` method to predict +the `net_outcome ` for a given `control_allocation `. State features can be of two types: -* *Input Features* -- these are values received as input by other Mechanisms in the `Composition`. They are - specified as `shadowed inputs ` in the **state_features** argument of the - OptimizationControlMechanism's constructor (see `OptimizationControlMechanism_Creation`). An InputPort is - created on the OptimizationControlMechanism for each feature, that receives a `Projection` paralleling - the input to be shadowed. +* *Input Features* -- these are values received as input by other `Mechanisms ` in the `Composition` + for which the OptimizationControlMechanism is a `controller ` (irrespective of whether + that is the OptimizationControlMechanism`s `agent_rep `). + They are specified as `shadowed inputs ` in the **state_features** argument + of the OptimizationControlMechanism's constructor (see `OptimizationControlMechanism_Creation`). + An InputPort is created and assigned to the OptimizationControlMechanism's `state_input_ports + ` attribute for each feature, that receives a + `Projection` paralleling the input to be shadowed. .. -* *Output Features* -- these are the `value ` of an `OutputPort` of some other `Mechanism ` - in the Composition. These too are specified in the **state_features** argument of the OptimizationControlMechanism's - constructor (see `OptimizationControlMechanism_Creation`), and each is assigned a `Projection` from the specified - OutputPort(s) to the InputPort of the OptimizationControlMechanism for that feature. +* *Output Features* -- these are the `value ` of an `OutputPort` of some other + `Mechanism ` in the `Composition`. These too are specified in the **state_features** argument of the + OptimizationControlMechanism's constructor (see `OptimizationControlMechanism_Creation`), and each is assigned a + `Projection` from the specified OutputPort(s) to the InputPort of the OptimizationControlMechanism for that feature. + +The InputPorts assigned to the **state_features** are listed in the OptimizationControlMechanism's `state_input_port +` attribute, and their current `values ` are +listed in its `state_feature_values ` attribute. -The current `value ` of the InputPorts for the state_features are listed in the `state_feature_values -` attribute. +The InputPorts assigned to the **state_features** are listed in the OptimizationControlMechanism's `state_input_port +` attribute, and their current `values ` are +listed in its `state_feature_values ` attribute. .. _OptimizationControlMechanism_State: @@ -446,7 +560,7 @@ Examples -------- -The table below lists `model-free ` and `model-based +The table below lists `model-free ` and `model-based ` + are created, the `values ` of which are assigned to `state_feature_values ` and used to predict `net_outcome `. Any `InputPort specification ` - can be used that resolves to an `OutputPort` that projects to that InputPort. + can be used that resolves to an `OutputPort` that projects to that InputPort (see + `state_features ). - state_feature_function : Function or function : default None - specifies the `function ` for the `InputPort` assigned to each `state_feature_value - `. + state_feature_functions : Function or function : default None + specifies the `function ` assigned the `InputPort` in `state_input_ports + ` assigned to each **state_feature** + (see `state_feature_functions ` for additional details). - agent_rep : None : default Composition to which the OptimizationControlMechanism is assigned + allow_probes : bool or DIRECT : default False + specifies whether `Projections ` are permitted to the ControlMechanism from items + `being monitored ` that are INTERNAL `Nodes ` + of a `nested Composition ` (see `allow_probes ` + for addition information). + + agent_rep : None or Composition : default None or Composition to which OptimizationControlMechanism is assigned specifies the `Composition` used by `evaluate_agent_rep ` to predict the `net_outcome ` for a given `state `. If a Composition is specified, it must be suitably configured - (see `above ` for additional details). If it is not specified, the + (see `agent_rep ` for additional details). It can also be a + `CompositionFunctionApproximator`, or subclass of one, used for `model-free + ` optimization. If **agent_rep** is not specified, the OptimizationControlMechanism is placed in `deferred_init` status until it is assigned as the `controller - ` of a Composition, at which that Composition is assigned as the `agent_rep + ` of a Composition, at which time that Composition is assigned as the `agent_rep ` for additional information). same_seed_for_all_parameter_combinations : bool : default False @@ -647,14 +774,54 @@ class OptimizationControlMechanism(ControlMechanism): ---------- state_feature_values : 2d array - the current value of each item of the OptimizationControlMechanism's `state_features - ` (each of which is a 1d array). + the current value of each item of the OptimizationControlMechanism's + `OptimizationControlMechanism_State_Features>` (each of which is a 1d array). + + state_input_ports : ContentAddressableList + lists the OptimizationControlMechanism's `InputPorts ` that receive `Projections ` + from the items specified in the **state_features** argument in the OptimizationControlMechanism's constructor + or constructed automatically (see `state_features `), and + that provide the `state_feature_values ` to the `agent_rep + ` (see `OptimizationControlMechanism_State_Features` for additional details). + + num_state_input_ports : int + cantains the number of `state_input_ports `. + + allow_probes : bool or DIRECT + this is a feature that is unique to OptimizationControlMechanism and any subclasses; it determines whether + any `Projections ` are permitted to the ControlMechanism from items being `monitored + `, including those that are INTERNAL `Nodes ` + in a `nested Composition `. This option only applies if an + `objective_mechanism` is not used. + + - False (the default): items specified in `monitor_for_control ` that + are in nested Composition must be *OUTPUT* `Nodes ` of that Composition; referencing any + INPUT or INTERNAL Nodes of a nested Composition raises an error. + + - True: *any* Node of a nested Composition can be specified in `monitor_for_control + `, including INPUT and INTERNAL nodes. These will project via the + nested Composition's `output_CIM ` (and those of any intervening Compositions) to + one of the OptimizationControlMechanism's `outcome_input_ports `, + and their values will be included in the Composition's `results ` attribute. + + - *DIRECT*: same as True, except that the specified Nodes will project *directly* to one of the + OptimizationControlMechanism's `outcome_input_ports `, + skipping all intervening `output_CIM `\\s. + + .. note:: + Specifying allow_probes as DIRECT is *not recommended*; it prevents use of `compilation + `. It is supported only for debugging purposes. agent_rep : Composition determines the `Composition` used by the `evaluate_agent_rep ` method to predict the `net_outcome ` for a given `state - ` (see `above `for additional - details). + `; see `Agent Representation ` + for additional details. + + agent_rep_type : None, MODEL_FREE or _MODEL_BASED + identifies whether the agent_rep is a `Composition` (*MODEL_BASED*), a `CompositionFunctionApproximator` or + one of its subclasses (*MODEL_FREE*), or it has not been assigned (None); see `Agent Representation and Types + of Optimization ` for additional details. num_estimates : int determines the number independent runs of `agent_rep ` (i.e., calls to @@ -666,7 +833,7 @@ class OptimizationControlMechanism(ControlMechanism): initial_seed : int or None determines the seed used to initialize the random number generator at construction. - If it is not specified then then the seed is set to a random value on construction, and different runs of a + If it is not specified then then the seed is set to a random value, and different runs of a Composition containing the OptimizationControlMechanism will yield different results, which should be roughly comparable if the estimation process is stable. If **initial_seed** is specified, then running the Composition should yield identical results for the estimation process, which can be useful for debugging. @@ -748,6 +915,8 @@ class OptimizationControlMechanism(ControlMechanism): ` attribute. Each sends a `ControlProjection` to the `ParameterPort` for the Parameter it controls when evaluating a `control_allocation `. + .. _OptimizationControlMechanism_Randomization: + .. technical_note:: If `num_estimates ` is specified (that is, it is not None), a `ControlSignal` is added to control_signals, named *RANDOMIZATION_CONTROL_SIGNAL*, to modulate the @@ -762,25 +931,22 @@ class OptimizationControlMechanism(ControlMechanism): ` of the other ControlSignals (i.e., the ones for the parameters being optimized). The *RANDOMIZATION_CONTROL_SIGNAL* is included when constructing the `control_allocation_search_space ` passed to the - OptimizationControlMechanism's `function ` as its - `search_space `, along with the index of - the *RANDOMIZATION_CONTROL_SIGNAL* as its `randomization_dimension <> - - - - The `initial_seed ` and + OptimizationControlMechanism's `function ` constructor as its + **search_space** argument, along with the index of the *RANDOMIZATION_CONTROL_SIGNAL* as its + **randomization_dimension** argument. The `initial_seed ` and `same_seed_for_all_allocations ` Parameters can be used to further refine this behavior. control_allocation_search_space : list of SampleIterators - `search_space ` assigned by default to `function - `, that determines the samples of - `control_allocation ` evaluated by the `evaluate_agent_rep + `search_space ` assigned by default to the + OptimizationControlMechanism's `function `, that determines the + samples of `control_allocation ` evaluated by the `evaluate_agent_rep ` method. This is a proprety that, unless overridden, returns a list of the `SampleIterators ` generated from the `allocation_sample ` specifications for each of the OptimizationControlMechanism's - `control_signals `. - # FIX: 11/3/21 ADD MENTION OF RANDOMIZATION CONTROL SIGNAL AND RAND DIM PASSED TO OPTIMIZAITON FUNCTION + `control_signals `, and includes the + *RANDOMIZATION_CONTROL_SIGNAL* used to randomize estimates of each `control_allocation + ` (see `note ` above). saved_samples : list contains all values of `control_allocation ` sampled by `function @@ -838,8 +1004,8 @@ class Parameters(ControlMechanism.Parameters): :default value: None :type: - state_feature_function - see `state_feature_function ` + state_feature_functions + see `state_feature_functions ` :default value: None :type: @@ -901,7 +1067,7 @@ class Parameters(ControlMechanism.Parameters): """ outcome_input_ports_option = Parameter(CONCATENATE, stateful=False, loggable=False, structural=True) function = Parameter(GridSearch, stateful=False, loggable=False) - state_feature_function = Parameter(None, referdence=True, stateful=False, loggable=False) + state_feature_functions = Parameter(None, reference=True, stateful=False, loggable=False) search_function = Parameter(None, stateful=False, loggable=False) search_space = Parameter(None, read_only=True) search_termination_function = Parameter(None, stateful=False, loggable=False) @@ -930,9 +1096,10 @@ class Parameters(ControlMechanism.Parameters): @tc.typecheck def __init__(self, agent_rep=None, - function=None, state_features: tc.optional(tc.optional(tc.any(Iterable, Mechanism, OutputPort, InputPort))) = None, - state_feature_function: tc.optional(tc.optional(tc.any(is_function_type))) = None, + state_feature_functions: tc.optional(tc.optional(tc.any(dict, is_function_type))) = None, + allow_probes:tc.any(bool, tc.enum(DIRECT)) = False, # FIX: MAKE THIS A PARAMETER AND THEN SET TO None + function=None, num_estimates = None, initial_seed=None, same_seed_for_all_allocations=None, @@ -958,18 +1125,19 @@ def __init__(self, kwargs.pop('features') continue if k == 'feature_function': - if state_feature_function: - warnings.warn(f"Both 'feature_function' and 'state_feature_function' were specified in the " + if state_feature_functions: + warnings.warn(f"Both 'feature_function' and 'state_feature_functions' were specified in the " f"constructor for an {self.__class__.__name__}. Note: 'feature_function' has been " - f"deprecated; 'state_feature_function' ({state_feature_function}) will be used.") + f"deprecated; 'state_feature_functions' ({state_feature_functions}) will be used.") else: warnings.warn(f"'feature_function' was specified in the constructor for an" f"{self.__class__.__name__}; Note: 'feature_function' has been deprecated; " - f"please use 'state_feature_function' in the future.") - state_feature_function = kwargs['feature_function'] + f"please use 'state_feature_functions' in the future.") + state_feature_functions = kwargs['feature_function'] kwargs.pop('feature_function') continue self.state_features = convert_to_list(state_features) + self.allow_probes = allow_probes function = function or GridSearch @@ -992,7 +1160,7 @@ def __init__(self, super().__init__( function=function, - state_feature_function=state_feature_function, + state_feature_functions=state_feature_functions, num_estimates=num_estimates, num_trials_per_estimate = num_trials_per_estimate, initial_seed=initial_seed, @@ -1011,58 +1179,278 @@ def _validate_params(self, request_set, target_set=None, context=None): from psyneulink.core.compositions.composition import Composition if request_set[AGENT_REP] is None: - raise OptimizationControlMechanismError(f"The {repr(AGENT_REP)} arg of an {self.__class__.__name__} must " + raise OptimizationControlMechanismError(f"The '{AGENT_REP}' arg of an {self.__class__.__name__} must " f"be specified and be a {Composition.__name__}") elif not (isinstance(request_set[AGENT_REP], Composition) or (isinstance(request_set[AGENT_REP], type) and issubclass(request_set[AGENT_REP], Composition))): - raise OptimizationControlMechanismError(f"The {repr(AGENT_REP)} arg of an {self.__class__.__name__} " + raise OptimizationControlMechanismError(f"The '{AGENT_REP}' arg of an {self.__class__.__name__} " f"must be either a {Composition.__name__} or a sublcass of one") + elif request_set[STATE_FEATURE_FUNCTIONS]: + state_feats = request_set.pop(STATE_FEATURES, None) + state_feat_fcts = request_set.pop(STATE_FEATURE_FUNCTIONS, None) + # If no or only one item is specified in state_features, only one state_function is allowed + if ((not state_feats or len(convert_to_list(state_feats))==1) + and len(convert_to_list(state_feat_fcts))!=1): + raise OptimizationControlMechanismError(f"Only one function is allowed to be specified for " + f"the '{STATE_FEATURE_FUNCTIONS}' arg of {self.name} " + f"if either no only one items is specified for its " + f"'{STATE_FEATURES}' arg.") + if len(convert_to_list(state_feat_fcts))>1 and not isinstance(state_feat_fcts, dict): + raise OptimizationControlMechanismError(f"The '{STATE_FEATURES}' arg of {self.name} contains more " + f"than one item, so its '{STATE_FEATURE_FUNCTIONS}' arg " + f"must be either only a single function (applied to all " + f"{STATE_FEATURES}) or a dict with entries of the form " + f":.") + if len(convert_to_list(state_feat_fcts))>1: + invalid_fct_specs = [fct_spec for fct_spec in state_feat_fcts if fct_spec not in state_feats] + if invalid_fct_specs: + raise OptimizationControlMechanismError(f"The following entries of the dict specified for " + f"'{STATE_FEATURE_FUNCTIONS} of {self.name} have keys that " + f"do not match any InputPorts specified in its " + f"{STATE_FEATURES} arg: {invalid_fct_specs}.") + + # FIX: CONSIDER GETTING RID OF THIS METHOD ENTIRELY, AND LETTING state_input_ports + # BE HANDLED ENTIRELY BY _update_state_input_ports_for_controller def _instantiate_input_ports(self, context=None): - """Instantiate InputPorts for state_features (with state_feature_function) if specified. + """Instantiate InputPorts for state_features (with state_feature_functions if specified). + + This instantiates the OptimizationControlMechanism's `state_input_ports; + these are used to provide input to the agent_rep when its evaluate method is called + (see Composition._build_predicted_inputs_dict). + The OptimizationCOntrolMechanism's outcome_input_ports are instantiated by + ControlMechanism._instantiate_input_ports in the call to super(). - If **state_features** are specified in the constructor: - - InputPorts are constructed for them by calling _parse_state_feature_specs with **state_features** and - **state_feature_function** arguments of the OptimizationControlMechanism constructor. - - The constructed feature_input_ports are passed to ControlMechanism_instantiate_input_ports(), + InputPorts are constructed for **state_features** by calling _parse_state_feature_specs + with them and **state_feature_functions** arguments of the OptimizationControlMechanism constructor. + The constructed state_input_ports are passed to ControlMechanism_instantiate_input_ports(), which appends them to the InputPort(s) that receive input from the **objective_mechanism* (if specified) or **monitor_for_control** ports (if **objective_mechanism** is not specified). + Also ensures that every state_input_port has only a single Projection. - Ensure that every InputPort has only a single Projection. + If no **state_features** are specified in the constructor, assign ones for INPUT Nodes of owner. + - warn for model-free `model-free optimization <`. + - ignore here for `model-based optimization <` + (handled in _update_state_input_ports_for_controller) + + See`state_features ` and + `OptimizationControlMechanism_State_Features` for additional details. """ + from psyneulink.core.compositions.compositionfunctionapproximator import CompositionFunctionApproximator + # If any state_features were specified parse them and pass to ControlMechanism._instantiate_input_ports() - feature_input_ports = None - # If any state_features were specified (assigned to self.input_ports in __init__): - if self.state_features: - feature_input_ports = self._parse_state_feature_specs(self.state_features, - self.state_feature_function) - super()._instantiate_input_ports(feature_input_ports, context=context) + state_input_ports_specs = None + + # FIX: 11/3/21 : + # ADD CHECK IN _parse_state_feature_specs THAT IF A NODE RATHER THAN InputPort IS SPECIFIED, + # ITS PRIMARY IS USED (SEE SCRATCH PAD FOR EXAMPLES) + if not self.state_features: + # For model-free (agent_rep = CompositionFunctionApproximator), warn if no state_features specified. + # Note: for model-based optimization, state_input_ports and any state_feature_functions specified + # are assigned in _update_state_input_ports_for_controller. + if self.agent_rep_type == MODEL_FREE: + warnings.warn(f"No 'state_features' specified for use with `agent_rep' of {self.name}") - for i in range(1, len(self.input_ports)): + else: + # FIX: 11/29/21: DISALLOW FOR MODEL_BASED + # Implement any specified state_features + state_input_ports_specs = self._parse_state_feature_specs(self.state_features, + self.state_feature_functions) + # Note: + # if state_features were specified for model-free (i.e., agent_rep is a CompositionFunctionApproximator), + # assume they are OK (no way to check their validity for agent_rep.evaluate() method, and skip assignment + + # Pass state_input_ports_sepcs to ControlMechanism for instantiation and addition to OCM's input_ports + super()._instantiate_input_ports(state_input_ports_specs, context=context) + + # Assign to self.state_input_ports attribute + start = self.num_outcome_input_ports # FIX: 11/3/21 NEED TO MODIFY IF OUTCOME InputPorts ARE MOVED + stop = start + len(state_input_ports_specs) if state_input_ports_specs else 0 + # FIX 11/3/21: THIS SHOULD BE MADE A PARAMETER + self.state_input_ports = ContentAddressableList(component_type=InputPort, + list=self.input_ports[start:stop]) + + # Ensure that every state_input_port has no more than one afferent projection + for i in range(1, len(self.state_input_ports)): port = self.input_ports[i] if len(port.path_afferents) > 1: raise OptimizationControlMechanismError(f"Invalid {type(port).__name__} on {self.name}. " f"{port.name} should receive exactly one projection, " f"but it receives {len(port.path_afferents)} projections.") - # def _instantiate_montiored_for_control_input_ports(self, context): - # """Override ControlMechanism to return standard *single* OUTCOOME InputPort that concatenates its inputs""" - # - # monitor_for_control_specs = self.monitor_for_control - # # FIX: 11/3/21 - MOVE THIS BACK TO ControlMechanism ONCE IT HAS THE OPTION TO CONCATENATE OR COMBINE - # # MULTIPLE monitor_for_control InpuPorts - # # FIX: 11/3/21 - MOVE _parse_monitor_specs TO HERE FROM ObjectiveMechanism - # from psyneulink.core.components.mechanisms.processing.objectivemechanism import _parse_monitor_specs - # monitored_ports = _parse_monitor_specs(monitor_for_control_specs) - # outcome_input_port = {PORT_TYPE: InputPort, - # NAME: 'OUTCOME', - # FUNCTION: Concatenate, - # # SIZE: len(self._handle_arg_input_ports(monitor_for_control_specs)[0]) - # PROJECTIONS: monitored_ports} - # # port_value_size, _ = self._handle_arg_input_ports(outcome_input_port) - # return [outcome_input_port], [self._handle_arg_input_ports(monitor_for_control_specs)[0]] + def _parse_monitor_for_control_input_ports(self, context): + """Override ControlMechanism to implement allow_probes=DIRECT option + + If is False (default), simply pass results of super()._parse_monitor_for_control_input_ports(context); + this is restricted to the use of OUTPUT Nodes in nested Compositions, and routes Projections from nodes in + nested Compositions through their respective output_CIMs. + + If allow_probes option is True, any INTERNAL Nodes of nested Compositions specified in monitor_for_control + are assigned NodeRole.OUTPUT, and Projections from them to the OptimizationControlMechanism are routed + from the nested Composition(s) through the respective output_CIM(s). + + If allow_probes option is DIRECT, Projection specifications are added to Port specification dictionaries, + so that the call to super()._instantiate_input_ports in ControlMechanism instantiates Projections from + monitored node to OptimizationControlMechanism. This allows *direct* Projections from monitored nodes in + nested Compositions to the OptimizationControlMechanism, bypassing output_CIMs and preventing inclusion + of their values in the results attribute of those Compositions. + + Return port specification dictionaries (*with* Projection specifications), their value sizes and null list + (to suppress Projection assignment to aux_components in ControlMechanism._instantiate_input_ports) + """ + + outcome_input_port_specs, outcome_value_sizes, monitored_ports \ + = super()._parse_monitor_for_control_input_ports(context) + + if self.allow_probes == DIRECT: + # Add Projection specifications to port specification dictionaries for outcome_input_ports + # and return monitored_ports = [] + + if self.outcome_input_ports_option == SEPARATE: + # Add port spec to to each outcome_input_port_spec (so that a Projection is specified directly to each) + for i in range(self.num_outcome_input_ports): + outcome_input_port_specs[i].update({PROJECTIONS: monitored_ports[i]}) + else: + # Add all ports specs as list to single outcome_input_port + outcome_input_port_specs[0].update({PROJECTIONS: monitored_ports}) + + # Return [] for ports to suppress creation of Projections in _instantiate_input_ports + monitored_ports = [] + + return outcome_input_port_specs, outcome_value_sizes, monitored_ports + + + def _update_state_input_ports_for_controller(self, context=None): + """Check and update state_input_ports for model-based optimization (agent_rep==Composition) + + If no agent_rep has been specified or it is model-free, return + (note: validation of state_features specified for model-free optimization is up to the + CompositionFunctionApproximator) + + For model-based optimization (agent_rep is a Composition): + + - ensure that state_input_ports for all specified state_features are for InputPorts of INPUT Nodes of agent_rep; + raises an error if any receive a Projection that is not a shadow Projection from an INPUT Node of agent_rep + (note: there should already be state_input_ports for any **state_features** specified in the constructor). + + - if no state_features specified, assign a state_input_port for every InputPort of every INPUT Node of agent_rep + (note: shadow Projections for all state_input_ports are created in Composition._update_shadow_projections()). + + - assign state_feature_functions to relevant state_input_ports (same function for all if no state_features + are specified or only one state_function is specified; otherwise, use dict for specifications). + """ + + # FIX: 11/15/21 - REPLACE WITH ContextFlags.PROCESSING ?? + # TRY TESTS WITHOUT THIS + # Don't instantiate unless being called by Composition.run() (which does not use ContextFlags.METHOD) + # This avoids error messages if called prematurely (i.e., before run is complete) + # MODIFIED 11/29/21 OLD: + if context.flags & ContextFlags.METHOD: + return + # MODIFIED 11/29/21 END + + # Don't bother for model-free optimization (see OptimizationControlMechanism_Model_Free) + # since state_input_ports specified or model-free optimization are entirely the user's responsibility; + # this is because they can't be programmatically validated against the agent_rep's evaluate() method. + # (This contrast with model-based optimization, for which there must be a state_input_port for every + # InputPort of every INPUT node of the agent_rep (see OptimizationControlMechanism_Model_Based). + if self.agent_rep_type != MODEL_BASED: + return + + from psyneulink.core.compositions.composition import Composition, NodeRole, CompositionInterfaceMechanism + + def _get_all_input_nodes(comp): + """Return all input_nodes, including those for any Composition nested one level down. + Note: more deeply nested Compositions will either be served by their containing one(s) or own controllers + """ + _input_nodes = comp.get_nodes_by_role(NodeRole.INPUT) + input_nodes = [] + for node in _input_nodes: + if isinstance(node, Composition): + input_nodes.extend(_get_all_input_nodes(node)) + else: + input_nodes.append(node) + return input_nodes + + if self.state_features: + # FIX: 11/26/21 - EXPLAIN THIS BEHAVIOR IN DOSCSTRING; + warnings.warn(f"The 'state_features' argument has been specified for {self.name}, that is being " + f"configured as a model-based {self.__class__.__name__} (i.e, one that uses a " + f"{Composition.componentType} as its agent_rep). This overrides automatic assignment of " + f"all inputs to its agent_rep ({self.agent_rep.name}) as the 'state_features'; only the " + f"ones specified will be used ({self.state_features}), and they must match the shape of the " + f"input to {self.agent_rep.name} when it is run. Remove this specification from the " + f"constructor for {self.name} if automatic assignment is preferred.") + + comp = self.agent_rep + # Ensure that all InputPorts shadowed by specified state_input_ports + # are in agent_rep or one of its nested Compositions + invalid_state_features = [input_port for input_port in self.state_input_ports + if (not (input_port.shadow_inputs.owner in + list(comp.nodes) + [n[0] for n in comp._get_nested_nodes()]) + and (not [input_port.shadow_inputs.owner.composition is x for x in + comp._get_nested_compositions() + if isinstance(input_port.shadow_inputs.owner, + CompositionInterfaceMechanism)]))] + if any(invalid_state_features): + raise OptimizationControlMechanismError(f"{self.name}, being used as controller for model-based " + f"optimization of {self.agent_rep.name}, has 'state_features' " + f"specified ({[d.name for d in invalid_state_features]}) that " + f"are missing from the Composition or any nested within it.") + + # Ensure that all InputPorts shadowed by specified state_input_ports + # reference INPUT Nodes of agent_rep or of a nested Composition + invalid_state_features = [input_port for input_port in self.state_input_ports + if (not (input_port.shadow_inputs.owner in _get_all_input_nodes(self.agent_rep)) + and (isinstance(input_port.shadow_inputs.owner, + CompositionInterfaceMechanism) + and not (input_port.shadow_inputs.owner.composition in + [nested_comp for nested_comp in comp._get_nested_compositions() + if nested_comp in comp.get_nodes_by_role(NodeRole.INPUT)])))] + if any(invalid_state_features): + raise OptimizationControlMechanismError(f"{self.name}, being used as controller for model-based " + f"optimization of {self.agent_rep.name}, has 'state_features' " + f"specified ({[d.name for d in invalid_state_features]}) that " + f"are not INPUT nodes for the Composition or any nested " + f"within it.") + return + + # Model-based agent_rep, but no state_features have been specified, + # so assign a state_input_port to shadow every InputPort of every INPUT node of agent_rep + shadow_input_ports = [] + for node in _get_all_input_nodes(self.agent_rep): + for input_port in node.input_ports: + if input_port.internal_only: + continue + # if isinstance(input_port.owner, CompositionInterfaceMechanism): + # input_port = input_port. + shadow_input_ports.append(input_port) + + local_context = Context(source=ContextFlags.METHOD) + state_input_ports_to_add = [] + # for input_port in input_ports_not_specified: + for input_port in shadow_input_ports: + input_port_name = f"{SHADOW_INPUT_NAME} of {input_port.owner.name}[{input_port.name}]" + # MODIFIED 11/28/21 NEW: + params = {SHADOW_INPUTS: input_port, + INTERNAL_ONLY:True} + # Note: state_feature_functions has been validated _validate_params + # to have only a single function in for model-based agent_rep + if self.state_feature_functions: + params.update({FUNCTION: self._parse_state_feature_function(self.state_feature_functions)}) + # MODIFIED 11/28/21 END + state_input_ports_to_add.append(_instantiate_port(name=input_port_name, + port_type=InputPort, + owner=self, + reference_value=input_port.value, + params=params, + context=local_context)) + self.add_ports(state_input_ports_to_add, + update_variable=False, + context=local_context) + self.state_input_ports.extend(state_input_ports_to_add) def _instantiate_output_ports(self, context=None): """Assign CostFunctions.DEFAULTS as default for cost_option of ControlSignals. @@ -1080,29 +1468,50 @@ def _instantiate_control_signals(self, context): Assign each modulatory_signal sequentially to corresponding item of control_allocation. """ + # MODIFIED 11/21/21 NEW: + # FIX - PURPOSE OF THE FOLLOWING IS TO "CAPTURE" CONTROL SPECS MADE LOCALLY ON MECHANISMS IN THE COMP + # AND INSTANTIATE ControlSignals FOR THEM HERE, ALONG WITH THOSE SPECIFIED IN THE CONSTRUCTOR + # FOR THE OCM. ALSO CAPTURES DUPLICATES (SEE MOD BELOW). + # FIX: WITHOUT THIS, GET THE mod param ERROR; WITH IT, GET FAILURES IN test_control: + # TestModelBasedOptimizationControlMechanisms_Execution + # test_evc + # test_stateful_mechanism_in_simulation + # TestControlMechanisms: + # test_lvoc + # test_lvoc_both_prediction_specs + # test_lvoc_features_function + # if self.agent_rep and self.agent_rep.componentCategory=='Composition': + # control_signals_from_composition = self.agent_rep._get_control_signals_for_composition() + # self.output_ports.extend(control_signals_from_composition) + # MODIFIED 11/21/21 END + if self.num_estimates: - # Construct iterator for seeds used to randomize estimates - def random_integer_generator(): - rng = np.random.RandomState() - rng.seed(self.initial_seed) - return rng.random_integers(self.num_estimates) - random_seeds = SampleSpec(num=self.num_estimates, function=random_integer_generator) - - # FIX: noise PARAM OF TransferMechanism IS MARKED AS SEED WHEN ASSIGNED A DISTRIBUTION FUNCTION, + + randomization_seed_mod_values = SampleSpec(start=1,stop=self.num_estimates,step=1) + + # FIX: 11/3/21 noise PARAM OF TransferMechanism IS MARKED AS SEED WHEN ASSIGNED A DISTRIBUTION FUNCTION, # BUT IT HAS NO PARAMETER PORT BECAUSE THAT PRESUMABLY IS FOR THE INTEGRATOR FUNCTION, # BUT THAT IS NOT FOUND BY model.all_dependent_parameters # Get ParameterPorts for seeds of parameters in agent_rep that use them (i.e., that return a random value) seed_param_ports = [param._port for param in self.agent_rep.all_dependent_parameters('seed').keys()] # Construct ControlSignal to modify seeds over estimates - self.output_ports.append(ControlSignal(name=RANDOMIZATION_CONTROL_SIGNAL_NAME, + self.output_ports.append(ControlSignal(name=RANDOMIZATION_CONTROL_SIGNAL, modulates=seed_param_ports, - allocation_samples=random_seeds)) + allocation_samples=randomization_seed_mod_values)) - for i, spec in enumerate(self.output_ports): + control_signals = [] + for i, spec in list(enumerate(self.output_ports)): control_signal = self._instantiate_control_signal(spec, context=context) control_signal._variable_spec = (OWNER_VALUE, i) + # MODIFIED 11/20/21 NEW: + # FIX - SHOULD MOVE THIS TO WHERE IT IS CALLED IN ControlSignal._instantiate_control_signal + if self._check_for_duplicates(control_signal, control_signals, context): + continue + # MODIFIED 11/20/21 END + # control_signals.append(control_signal) self.output_ports[i] = control_signal + self.defaults.value = np.tile(control_signal.parameters.variable.default_value, (i + 1, 1)) self.parameters.control_allocation._set(copy.deepcopy(self.defaults.value), context) @@ -1119,7 +1528,7 @@ def _instantiate_function(self, function, function_params=None, context=None): super()._instantiate_function(function, function_params, context) def _instantiate_attributes_after_function(self, context=None): - """Instantiate OptimizationControlMechanism's OptimizatonFunction attributes""" + """Instantiate OptimizationControlMechanism's OptimizationFunction attributes""" super()._instantiate_attributes_after_function(context=context) @@ -1145,16 +1554,16 @@ def _instantiate_attributes_after_function(self, context=None): # If there is no randomization_control_signal, but num_estimates is 1 or None, # pass None for randomization_control_signal_index (1 will be used by default by OptimizationFunction) - if RANDOMIZATION_CONTROL_SIGNAL_NAME not in self.control_signals and self.num_estimates in {1, None}: + if RANDOMIZATION_CONTROL_SIGNAL not in self.control_signals and self.num_estimates in {1, None}: randomization_control_signal_index = None # Otherwise, assert that num_estimates and number of seeds generated by randomization_control_signal are equal else: - num_seeds = self.control_signals[RANDOMIZATION_CONTROL_SIGNAL_NAME].allocation_samples.base.num + num_seeds = self.control_signals[RANDOMIZATION_CONTROL_SIGNAL].allocation_samples.base.num assert self.num_estimates == num_seeds, \ f"PROGRAM ERROR: The value of the 'num_estimates' Parameter of {self.name}" \ f"({self.num_estimates}) is not equal to the number of estimates that will be generated by " \ - f"its {RANDOMIZATION_CONTROL_SIGNAL_NAME} ControlSignal ({num_seeds})." - randomization_control_signal_index = self.control_signals.names.index(RANDOMIZATION_CONTROL_SIGNAL_NAME) + f"its {RANDOMIZATION_CONTROL_SIGNAL} ControlSignal ({num_seeds})." + randomization_control_signal_index = self.control_signals.names.index(RANDOMIZATION_CONTROL_SIGNAL) # Assign parameters to function (OptimizationFunction) that rely on OptimizationControlMechanism self.function.reset(**{ @@ -1170,7 +1579,7 @@ def _instantiate_attributes_after_function(self, context=None): self.agent_rep = self.agent_rep() from psyneulink.core.compositions.compositionfunctionapproximator import CompositionFunctionApproximator - if (isinstance(self.agent_rep, CompositionFunctionApproximator)): + if self.agent_rep_type == MODEL_FREE: self._initialize_composition_function_approximator(context) def _execute(self, variable=None, context=None, runtime_params=None): @@ -1529,23 +1938,18 @@ def _gen_llvm_evaluate_function(self, *, ctx:pnlvm.LLVMBuilderContext, assert all(input_initialized), \ "Not all inputs to the simulated composition are initialized: {}".format(input_initialized) - - # FIX: 11/3/21 ??REFACTOR EITHER: - # - AROUND PASSING OF num_estimates IN CALL TO _execute - # - OR TO USE num_trials_per_estimate RATHER THAN num_estimates IF THAT IS WHAT IS INTENDED - # # Determine simulation counts - num_estimates_ptr = pnlvm.helpers.get_param_ptr(builder, self, + num_trials_per_estimate_ptr = pnlvm.helpers.get_param_ptr(builder, self, controller_params, - "num_estimates") + "num_trials_per_estimate") - num_estimates = builder.load(num_estimates_ptr, "num_estimates") + num_trials_per_estimate = builder.load(num_trials_per_estimate_ptr, "num_trials_per_estimate") - # if num_estimates is 0, run 1 trial - param_is_zero = builder.icmp_unsigned("==", num_estimates, + # if num_trials_per_estimate is 0, run 1 trial + param_is_zero = builder.icmp_unsigned("==", num_trials_per_estimate, ctx.int32_ty(0)) num_sims = builder.select(param_is_zero, ctx.int32_ty(1), - num_estimates, "corrected_estimates") + num_trials_per_estimate, "corrected_estimates") num_runs = builder.alloca(ctx.int32_ty, name="num_runs") builder.store(num_sims, num_runs) @@ -1633,56 +2037,72 @@ def _gen_llvm_output_port_parse_variable(self, ctx, builder, params, context, va # else: # return np.array(np.array(self.variable[1:]).tolist()) - # FIX: THE FOLLOWING SHOULD BE MERGED WITH HANDLING OF PredictionMechanisms FOR ORIG MODEL-BASED APPROACH; - # FIX: SHOULD BE GENERALIZED AS SOMETHING LIKE update_feature_values - - @tc.typecheck - @handle_external_context() - def add_state_features(self, features, context=None): - """Add InputPorts and Projections to OptimizationControlMechanism for state_features used to - predict `net_outcome ` - - **state_features** argument can use any of the forms of specification allowed for InputPort(s) - """ + @property + def agent_rep_type(self): + from psyneulink.core.compositions.compositionfunctionapproximator import CompositionFunctionApproximator + if isinstance(self.agent_rep, CompositionFunctionApproximator): + return MODEL_FREE + elif self.agent_rep.componentCategory=='Composition': + return MODEL_BASED + else: + return None - if features: - features = self._parse_state_feature_specs(features=features, - context=context) - self.add_ports(InputPort, features) + def _parse_state_feature_function(self, feature_function): + if isinstance(feature_function, Function): + return copy.deepcopy(feature_function) + else: + return feature_function @tc.typecheck - def _parse_state_feature_specs(self, feature_input_ports, feature_function, context=None): + def _parse_state_feature_specs(self, state_features, feature_functions, context=None): """Parse entries of state_features into InputPort spec dictionaries Set INTERNAL_ONLY entry of params dict of InputPort spec dictionary to True (so that inputs to Composition are not required if the specified state is on an INPUT Mechanism) - Assign functions specified in **state_feature_function** to InputPorts for all state_features + Assign functions specified in **state_feature_functions** to InputPorts for all state_features Return list of InputPort specification dictionaries """ - feature_input_ports = _parse_shadow_inputs(self, convert_to_list(feature_input_ports)) + _state_input_ports = _parse_shadow_inputs(self, state_features) parsed_features = [] - # # FIX: 11/3/21: input_ports IS IGNORED; DELETE?? - # if not isinstance(feature_input_ports, list): - # input_ports = [feature_input_ports] - - for spec in feature_input_ports: - spec = _parse_port_spec(owner=self, port_type=InputPort, port_spec=spec) # returns InputPort dict - spec[PARAMS][INTERNAL_ONLY] = True - spec[PARAMS][PROJECTIONS] = None - if feature_function: - if isinstance(feature_function, Function): - feat_fct = copy.deepcopy(feature_function) + for spec in _state_input_ports: + # MODIFIED 11/29/21 NEW: + # If optimization is model-free, assume that shadowing of a Mechanism spec is for its primary InputPort + if isinstance(spec, Mechanism) and self.agent_rep_type == MODEL_BASED: + # FIX: 11/29/21: MOVE THIS TO _parse_shadow_inputs + # (ADD ARG TO THAT FOR DOING SO, OR RESTRICTING TO INPUTPORTS IN GENERAL) + if len(spec.input_ports)!=1: + raise OptimizationControlMechanismError(f"A Mechanism ({spec.name}) is specified in the " + f"'{STATE_FEATURES}' arg for {self.name} that has " + f"more than one InputPort; a specific one or subset " + f"of them must be specified.") + spec = spec.input_port + # MODIFIED 11/29/21 END + parsed_spec = _parse_port_spec(owner=self, port_type=InputPort, port_spec=spec) # returns InputPort dict + parsed_spec[PARAMS].update({INTERNAL_ONLY:True, + PROJECTIONS:None}) + # MODIFIED 11/28/21 NEW: + if feature_functions: + if isinstance(feature_functions, dict) and spec in feature_functions: + feat_fct = feature_functions.pop(spec) else: - feat_fct = feature_function - spec.update({FUNCTION: feat_fct}) - spec = [spec] # so that extend works below + feat_fct = feature_functions + parsed_spec.update({FUNCTION: self._parse_state_feature_function(feat_fct)}) + # MODIFIED 11/28/21 END + parsed_spec = [parsed_spec] # so that extend works below - parsed_features.extend(spec) + parsed_features.extend(parsed_spec) return parsed_features + @property + def num_state_input_ports(self): + try: + return len(self.state_input_ports) + except: + return 0 + @property def _model_spec_parameter_blacklist(self): # default_variable is hidden in constructor arguments, @@ -1706,3 +2126,19 @@ def _initialize_composition_function_approximator(self, context): self.agent_rep.initialize(features_array=np.array(self.defaults.variable[1:]), control_signals = self.control_signals, context=context) + + # FIX: THE FOLLOWING SHOULD BE MERGED WITH HANDLING OF PredictionMechanisms FOR ORIG MODEL-BASED APPROACH; + # FIX: SHOULD BE GENERALIZED AS SOMETHING LIKE update_feature_values + @tc.typecheck + @handle_external_context() + def add_state_features(self, features, context=None): + """Add InputPorts and Projections to OptimizationControlMechanism for state_features used to + predict `net_outcome ` + + **state_features** argument can use any of the forms of specification allowed for InputPort(s) + """ + + if features: + features = self._parse_state_feature_specs(features=features, + context=context) + self.add_ports(InputPort, features) diff --git a/psyneulink/core/components/ports/inputport.py b/psyneulink/core/components/ports/inputport.py index cf3ce8bd1dc..031e306d8c4 100644 --- a/psyneulink/core/components/ports/inputport.py +++ b/psyneulink/core/components/ports/inputport.py @@ -514,7 +514,8 @@ from psyneulink.core.globals.parameters import Parameter from psyneulink.core.globals.preferences.basepreferenceset import is_pref_set from psyneulink.core.globals.preferences.preferenceset import PreferenceLevel -from psyneulink.core.globals.utilities import append_type_to_name, convert_to_np_array, is_numeric, iscompatible, kwCompatibilityLength +from psyneulink.core.globals.utilities import \ + append_type_to_name, convert_to_np_array, is_numeric, iscompatible, kwCompatibilityLength, convert_to_list __all__ = [ 'InputPort', 'InputPortError', 'port_type_keywords', 'SHADOW_INPUTS', @@ -1211,11 +1212,11 @@ def _parse_self_port_type_spec(self, owner, input_port, context=None): sender_output_ports = [p.sender for p in input_port.path_afferents] port_spec = {NAME: SHADOW_INPUT_NAME + input_port.owner.name, - VARIABLE: np.zeros_like(input_port.variable), - PORT_TYPE: InputPort, - PROJECTIONS: sender_output_ports, - PARAMS: {SHADOW_INPUTS: input_port}, - OWNER: owner} + VARIABLE: np.zeros_like(input_port.variable), + PORT_TYPE: InputPort, + PROJECTIONS: sender_output_ports, + PARAMS: {SHADOW_INPUTS: input_port}, + OWNER: owner} return port_spec @staticmethod @@ -1392,6 +1393,7 @@ def _instantiate_input_ports(owner, input_ports=None, reference_value=None, cont def _parse_shadow_inputs(owner, input_ports): """Parses any {SHADOW_INPUTS:[InputPort or Mechanism,...]} items in input_ports into InputPort specif. dict.""" + input_ports = convert_to_list(input_ports) input_ports_to_shadow_specs=[] for spec_idx, spec in enumerate(input_ports): # If {SHADOW_INPUTS:[InputPort or Mechaism,...]} is found: diff --git a/psyneulink/core/components/ports/port.py b/psyneulink/core/components/ports/port.py index 299a520044c..811bcb49c77 100644 --- a/psyneulink/core/components/ports/port.py +++ b/psyneulink/core/components/ports/port.py @@ -1806,9 +1806,12 @@ def _remove_projection_to_port(self, projection, context=None): else: shape = list(self.defaults.variable.shape) # Reduce outer dimension by one - shape[0]-=1 - self.defaults.variable = np.resize(self.defaults.variable, shape) - self.function.defaults.variable = np.resize(self.function.defaults.variable, shape) + # only if shape is already greater than 1 (ports keep + # default of [0] if no incoming projections) + shape[0] -= 1 + if shape[0] > 0: + self.defaults.variable = np.resize(self.defaults.variable, shape) + self.function.defaults.variable = np.resize(self.function.defaults.variable, shape) del self.path_afferents[self.path_afferents.index(projection)] def _get_primary_port(self, mechanism): diff --git a/psyneulink/core/compositions/composition.py b/psyneulink/core/compositions/composition.py index f8a455014f5..9ac602d5ebd 100644 --- a/psyneulink/core/compositions/composition.py +++ b/psyneulink/core/compositions/composition.py @@ -2400,7 +2400,7 @@ def input_function(env, result): from psyneulink.core.components.projections.modulatory.learningprojection import LearningProjection from psyneulink.core.components.projections.modulatory.modulatoryprojection import ModulatoryProjection_Base from psyneulink.core.components.projections.pathway.mappingprojection import MappingProjection, MappingError -from psyneulink.core.components.projections.projection import ProjectionError, DuplicateProjectionError +from psyneulink.core.components.projections.projection import Projection_Base, ProjectionError, DuplicateProjectionError from psyneulink.core.components.shellclasses import Composition_Base from psyneulink.core.components.shellclasses import Mechanism, Projection from psyneulink.core.compositions.report import Report, \ @@ -2409,12 +2409,13 @@ def input_function(env, result): from psyneulink.core.compositions.showgraph import ShowGraph, INITIAL_FRAME, SHOW_CIM, EXECUTION_SET, SHOW_CONTROLLER from psyneulink.core.globals.context import Context, ContextFlags, handle_external_context from psyneulink.core.globals.keywords import \ - AFTER, ALL, ANY, BEFORE, COMPONENT, COMPOSITION, CONTROLLER, CONTROL_SIGNAL, DEFAULT, \ + AFTER, ALL, ANY, BEFORE, COMPONENT, COMPOSITION, CONTROLLER, CONTROL_SIGNAL, DEFAULT, ERROR, \ FEEDBACK, HARD_CLAMP, IDENTITY_MATRIX, INPUT, INPUT_PORTS, INPUTS, INPUT_CIM_NAME, LEARNED_PROJECTIONS, \ LEARNING_FUNCTION, LEARNING_MECHANISM, LEARNING_MECHANISMS, LEARNING_PATHWAY, \ - MATRIX, MATRIX_KEYWORD_VALUES, MAYBE, MODEL_SPEC_ID_COMPOSITION, MODEL_SPEC_ID_NODES, MODEL_SPEC_ID_PROJECTIONS, \ - MODEL_SPEC_ID_PSYNEULINK, \ - MODEL_SPEC_ID_RECEIVER_MECH, MODEL_SPEC_ID_SENDER_MECH, MONITOR, MONITOR_FOR_CONTROL, NAME, NESTED, NO_CLAMP, \ + MATRIX, MATRIX_KEYWORD_VALUES, MAYBE, \ + MODEL_SPEC_ID_COMPOSITION, MODEL_SPEC_ID_NODES, MODEL_SPEC_ID_PROJECTIONS, MODEL_SPEC_ID_PSYNEULINK, \ + MODEL_SPEC_ID_RECEIVER_MECH, MODEL_SPEC_ID_SENDER_MECH, \ + MONITOR, MONITOR_FOR_CONTROL, NAME, NESTED, NO_CLAMP, NODE, \ OBJECTIVE_MECHANISM, ONLINE, OUTCOME, OUTPUT, OUTPUT_CIM_NAME, OUTPUT_MECHANISM, OUTPUT_PORTS, OWNER_VALUE, \ PARAMETER, PARAMETER_CIM_NAME, PROCESSING_PATHWAY, PROJECTION, PULSE_CLAMP, \ SAMPLE, SHADOW_INPUTS, SOFT_CLAMP, SSE, \ @@ -2450,8 +2451,9 @@ def input_function(env, result): class CompositionError(Exception): - def __init__(self, error_value): + def __init__(self, error_value, **kwargs): self.error_value = error_value + self.return_items = kwargs def __str__(self): return repr(self.error_value) @@ -3002,9 +3004,9 @@ class Composition(Composition_Base, metaclass=ComponentsMeta): ` for additional details). show_graph_attributes : dict : None - specifies state_features of how the Composition is displayed when its `show_graph ` - method is called or **animate** is specified in a call to its `run ` method (see `ShowGraph` - for list of attributes and their values). + specifies features of how the Composition is displayed when its `show_graph ` + method is called or **animate** is specified in a call to its `run ` method + (see `ShowGraph` for list of attributes and their values). name : str : default see `name ` specifies the name of the Composition. @@ -3055,6 +3057,15 @@ class Composition(Composition_Base, metaclass=ComponentsMeta): `; each item is a list of nodes (`Mechanisms ` and/or Compositions) intercolated with the `Projection ` between each pair of nodes. + projections : ContentAddressableList[`Projection`] + a list of all of the `Projections ` activated for the Composition; this includes all of + the Projections among `Nodes ` within the Composition, as well as from its `input_CIM + ` to it *INPUT* Nodes;from its `parameter_CIM ` to + the corresponding `ParameterPorts `; from its *OUTPUT* Nodes to its `output_CIM + `; and, if it is `nested ` in another Composition, then the + Projections to its `input_CIM ` and from its `output_CIM ` + to other Nodes in the Comopsition within which it is nested. + input_CIM : `CompositionInterfaceMechanism` mediates input values for the `INPUT` `Nodes ` of the Composition. If the Composition is `nested `, then the input_CIM and its `InputPorts serve as proxies for the @@ -3134,8 +3145,8 @@ class Composition(Composition_Base, metaclass=ComponentsMeta): single call to `run `. shadows : dict - a dictionary in which the keys are all in the Composition and the values are lists of any Nodes that - `shadow ` the original Node's input. + a dictionary in which the keys are all `Nodes ` in the Composition, + and the values of each is a list of any Nodes that `shadow ` it's input. controller : OptimizationControlMechanism identifies the `OptimizationControlMechanism` used as the Composition's controller @@ -3334,8 +3345,6 @@ def __init__( port_map=self.output_CIM_ports) self.cims = [self.input_CIM, self.parameter_CIM, self.output_CIM] - self.shadows = {} - self.default_execution_id = self.name self.execution_ids = {self.default_execution_id} @@ -3350,7 +3359,8 @@ def __init__( self.graph_consistent = True # Tracks if Composition is in runnable state (no dangling projections (what else?) self.needs_update_graph = True # Tracks if Composition graph has been analyzed to assign roles to components self.needs_update_graph_processing = True # Tracks if the processing graph is current with the full graph - self.needs_update_scheduler = True # Tracks i4f the scheduler needs to be regenerated + self.needs_update_scheduler = True # Tracks if the scheduler needs to be regenerated + self.needs_update_controller = True # Tracks if controller needs to update its state_input_ports self.nodes_to_roles = collections.OrderedDict() self.cycle_vertices = set() @@ -3372,6 +3382,22 @@ def __init__( self.log = CompositionLog(owner=self) self._terminal_backprop_sequences = {} + self.controller = None + + # FIX 4/8/20 [JDC]: WHY NOT CALL add_nodes()? + # Nodes, Projections, and Pathways + if nodes is not None: + nodes = convert_to_list(nodes) + for node in nodes: + self.add_node(node) + + # FIX 4/8/20 [JDC]: TEST THIS + if projections is not None: + projections = convert_to_list(projections) + self.add_projections(projections) + + self.add_pathways(pathways, context=context) + # Controller self.controller = None self._controller_initialization_status = ContextFlags.INITIALIZED @@ -3387,7 +3413,6 @@ def __init__( # `num_trials_per_estimate ` attribute. self.num_trials = None - self._update_parameter_components() self.initialization_status = ContextFlags.INITIALIZED @@ -3398,20 +3423,6 @@ def __init__( # the behavior of components del self.parameters.value - # FIX 4/8/20 [JDC]: WHY NOT CALL add_nodes()? - # Nodes, Projections, and Pathways - if nodes is not None: - nodes = convert_to_list(nodes) - for node in nodes: - self.add_node(node) - - # FIX 4/8/20 [JDC]: TEST THIS - if projections is not None: - projections = convert_to_list(projections) - self.add_projections(projections) - - self.add_pathways(pathways, context=context) - # Call with context = COMPOSITION to avoid calling _check_initialization_status again self._analyze_graph(context=context) @@ -3476,7 +3487,7 @@ def scheduling_mode(self, scheduling_mode: SchedulingMode): self.scheduler.scheduling_mode = scheduling_mode # ****************************************************************************************************************** - # GRAPH + # region -------------------------------------- GRAPH ------------------------------------------------------------- # ****************************************************************************************************************** @handle_external_context(source=ContextFlags.COMPOSITION) @@ -3495,9 +3506,10 @@ def _analyze_graph(self, context=None): nodes are not set to `OUTPUT ` by default. """ - # Instantiate any deferred init components - self._check_projection_initialization_status(context=context) + self._check_controller_initialization_status(context=context) + self._check_nodes_initialization_status(context=context) + # FIX: SHOULDN'T THIS TEST MORE EXPLICITLY IF NODE IS A Composition? # Call _analzye_graph() for any nested Compositions for n in self.nodes: try: @@ -3506,10 +3518,14 @@ def _analyze_graph(self, context=None): pass self._complete_init_of_partially_initialized_nodes(context=context) + # Call before _determine_pathway and _create_CIM_ports so they have updated roles self._determine_node_roles(context=context) self._determine_pathway_roles(context=context) self._create_CIM_ports(context=context) + # Call after above so shadow_projections have relevant organization self._update_shadow_projections(context=context) + # Call again to accomodate any changes from _update_shadow_projections + self._determine_node_roles(context=context) self._check_for_projection_assignments(context=context) self.needs_update_graph = False @@ -3538,12 +3554,12 @@ def remove_vertex(vertex): self._graph_processing.prune_feedback_edges() self.needs_update_graph_processing = False + # endregion GRAPH # ****************************************************************************************************************** - # NODES + # region ---------------------------------------NODES ------------------------------------------------------------- # ****************************************************************************************************************** - @handle_external_context(source = ContextFlags.COMPOSITION) def add_node(self, node, required_roles=None, context=None): """ @@ -3566,18 +3582,11 @@ def add_node(self, node, required_roles=None, context=None): pathway_arg_str = " in " + context.string raise CompositionError(f"Attempt to add Composition as a Node to itself{pathway_arg_str}.") - self._update_shadows_dict(node) - try: node._analyze_graph(context = context) except AttributeError: pass - # # MODIFIED 6/13/20 NEW: - # if any(n is node for nested_comp in self.nodes if isinstance(nested_comp, Composition) for n in nested_comp.nodes): - # return - # MODIFIED 6/13/20 END - node._check_for_composition(context=context) # Add node to Composition's graph @@ -3592,6 +3601,7 @@ def add_node(self, node, required_roles=None, context=None): self.needs_update_graph = True self.needs_update_graph_processing = True self.needs_update_scheduler = True + self.needs_update_controller = True invalid_aux_components = self._add_node_aux_components(node) @@ -3602,16 +3612,6 @@ def add_node(self, node, required_roles=None, context=None): for required_role in required_roles: self._add_required_node_role(node, required_role, context) - # Add projections to node from sender of any shadowed InputPorts - for input_port in node.input_ports: - if hasattr(input_port, SHADOW_INPUTS) and input_port.shadow_inputs is not None: - for proj in input_port.shadow_inputs.path_afferents: - sender = proj.sender - if sender.owner != self.input_CIM: - self.add_projection(projection=MappingProjection(sender=proj.sender, receiver=input_port), - sender=proj.sender.owner, - receiver=node) - # Add ControlSignals to controller and ControlProjections # to any parameter_ports specified for control in node's constructor if self.controller: @@ -3623,36 +3623,6 @@ def add_node(self, node, required_roles=None, context=None): except NameError: pass - def _instantiate_deferred_init_control(self, node, context=None): - """ - If node is a Composition with a controller, activate its nodes' deferred init control specs for its controller. - If it does not have a controller, but self does, activate them for self's controller. - - If node is a Node that has deferred init control specs and self has a controller, activate the deferred init - control specs for self's controller. - - Returns - ------- - - list of hanging control specs that were not able to be assigned for a controller at any level. - - """ - hanging_control_specs = [] - if node.componentCategory == 'Composition': - for nested_node in node.nodes: - hanging_control_specs.extend(node._instantiate_deferred_init_control(nested_node, context=context)) - else: - hanging_control_specs = node._get_parameter_port_deferred_init_control_specs() - if not self.controller: - return hanging_control_specs - else: - for spec in hanging_control_specs: - control_signal = self.controller._instantiate_control_signal(control_signal=spec, - context=context) - self.controller.control.append(control_signal) - self.controller._activate_projections_for_compositions(self) - return [] - def add_nodes(self, nodes, required_roles=None, context=None): """ Add a list of `Nodes ` to the Composition. @@ -3885,15 +3855,6 @@ def _get_input_nodes_by_CIM_input_order(self): """Return a list with the `INPUT` `Nodes ` of the Composition in the same order as their corresponding InputPorts on Composition's `input_CIM `. """ - # input_nodes = [] - # for i, port in enumerate(self.input_CIM.input_ports): - # output_port = next((o for o in self.input_CIM.output_ports - # if o.function.corresponding_input_port.position_in_mechanism == i), None) - # assert output_port - # node = next((p.receiver.owner for p in output_port.efferents if not SHADOW_INPUT_NAME in p.name), None) - # assert node - # input_nodes.append(node) - # return input_nodes return [{cim[0]:n for n, cim in self.input_CIM_ports.items()}[input_port].owner for input_port in self.input_CIM.input_ports] @@ -3902,9 +3863,8 @@ def _get_nested_nodes(self, nested_nodes=NotImplemented, root_composition=NotImplemented, visited_compositions=NotImplemented): - """Recursive search that returns all nodes of all nested compositions in a tuple with the composition they are - embedded in. - + """Recursively search and return all nodes of all nested Compositions + in a tuple with Composition in which they are nested. :return A list of tuples in format (node, composition) containing all nodes of all nested compositions. @@ -3929,7 +3889,7 @@ def _get_nested_nodes(self, def _get_nested_compositions(self, nested_compositions=NotImplemented, visited_compositions=NotImplemented): - """Recursive search that returns all nested compositions. + """Recursive search for and return all nested compositions. :return @@ -3977,28 +3937,30 @@ def _determine_origin_and_terminal_nodes_from_consideration_queue(self): self._add_node_role(node, NodeRole.TERMINAL) def _add_node_aux_components(self, node, context=None): - """ + """Add aux_components of node to Composition. + Returns ------- - list containing references to all invalid aux components - """ + # Implement any components specified in node's aux_components attribute invalid_aux_components = [] if hasattr(node, "aux_components"): - # Collect the node's aux components that are not currently able to be added to the Composition - # we'll ignore these for now and try to activate them again during every call to _analyze_graph - # at runtime if there are still any invalid aux components left, we will issue a warning + # Collect the node's aux components that are not currently able to be added to the Composition; + # ignore these for now and try to activate them again during every call to _analyze_graph + # and, at runtime, if there are still any invalid aux_components left, issue a warning projections = [] # Add all "nodes" to the composition first (in case projections reference them) - for component in node.aux_components: + for i, component in enumerate(node.aux_components): if isinstance(component, (Mechanism, Composition)): if isinstance(component, Composition): component._analyze_graph() self.add_node(component) elif isinstance(component, Projection): - projections.append((component, False)) + proj_tuple = (component, False) + projections.append(proj_tuple) + node.aux_components[i] = proj_tuple elif isinstance(component, tuple): if isinstance(component[0], Projection): if (isinstance(component[1], bool) or component[1] in {EdgeType.FLEXIBLE, MAYBE}): @@ -4035,6 +3997,7 @@ def _add_node_aux_components(self, node, context=None): .format(component.name, node.name)) invalid_aux_components.extend(self._get_invalid_aux_components(node)) + # Add all Projections to the Composition for proj_spec in [i for i in projections if not i[0] in invalid_aux_components]: # The proj_spec assumes a direct connection between sender and receiver, and is therefore invalid if @@ -4056,12 +4019,77 @@ def _add_node_aux_components(self, node, context=None): self.add_projection(sender=proj_spec[0].sender, receiver=proj_spec[0].receiver, feedback=proj_spec[1]) + del node.aux_components[node.aux_components.index(proj_spec)] + return invalid_aux_components + def _get_invalid_aux_components(self, node): + """ + Return any Components in aux_components for a node that references items not (yet) in this Composition + """ + # FIX 11/20/21: THIS APPEARS TO ONLY HANDLE PROJECTIONS AND NOT COMPOSITIONS OR MECHANISMS + # (OTHER THAN THE COMPOSITION'S controller AND ITS objective_mechanism) + + # First get all valid nodes: + # - nodes in Composition + # - nodes in any nested Compositions + # - controller and associated objective_mechanism + valid_nodes = [node for node in self.nodes.data] + \ + [node for node, composition in self._get_nested_nodes()] + \ + [self] + if self.controller: + valid_nodes.append(self.controller) + if hasattr(self.controller,'objective_mechanism'): + valid_nodes.append(self.controller.objective_mechanism) + + # Then get invalid components: + # - Projections that have senders or receivers not in the Composition + # (this includes any in aux_components of node, or associated with any Mechanism listed in aux_components) + invalid_components = [] + for aux in node.aux_components: + component = None + if isinstance(aux, Projection): + component = aux + elif hasattr(aux, '__iter__'): + for i in aux: + if isinstance(i, Projection): + component = i + elif isinstance(i, Mechanism): + if self._get_invalid_aux_components(i): + invalid_components.append(i) + elif isinstance(aux, Mechanism): + if self._get_invalid_aux_components(aux): + invalid_components.append(aux) + if not component: + continue + if isinstance(component, Projection): + if hasattr(component.sender, OWNER_MECH): + sender_node = component.sender.owner_mech + else: + if isinstance(component.sender.owner, CompositionInterfaceMechanism): + sender_node = component.sender.owner.composition + else: + sender_node = component.sender.owner + if hasattr(component.receiver, OWNER_MECH): + receiver_node = component.receiver.owner_mech + else: + if isinstance(component.receiver.owner, CompositionInterfaceMechanism): + receiver_node = component.receiver.owner.composition + else: + receiver_node = component.receiver.owner + # Defer instantiation of all shadow Projections until call to _update_shadow_projections() + if (not all([sender_node in valid_nodes, receiver_node in valid_nodes]) + or (hasattr(component.receiver, SHADOW_INPUTS) and component.receiver.shadow_inputs)): + invalid_components.append(component) + if invalid_components: + return invalid_components + else: + return [] + def _complete_init_of_partially_initialized_nodes(self, context=None): """ - Attempt to complete initialization of aux components for any nodes with - aux components that were not previously compatible with Composition + Attempt to complete initialization of aux_components for any nodes with + aux_components that were not previously compatible with Composition """ completed_nodes = [] for node in self._partially_added_nodes: @@ -4070,6 +4098,19 @@ def _complete_init_of_partially_initialized_nodes(self, context=None): completed_nodes.append(node) self._partially_added_nodes = list(set(self._partially_added_nodes) - set(completed_nodes)) + # Don't instantiate unless flagged for updating (if nodes have been added to the graph); + # this avoids unnecessary calls on repeated calls to run(). + if (self.controller + and self.needs_update_controller + and context.flags & (ContextFlags.COMPOSITION | ContextFlags.COMMAND_LINE)): + if hasattr(self.controller, 'state_input_ports'): + self.controller._update_state_input_ports_for_controller(context=context) + # self._instantiate_controller_shadow_projections(context=context) + self._instantiate_control_projections(context=context) + # FIX: 11/15/21 - CAN'T SET TO FALSE HERE, AS THIS IS CALLED BY _analyze_graph() FROM add_node() + # BEFORE PROJECTIONS TO THE NODE HAS BEEN ADDED (AFTER CALL TO add_node()) + self.needs_update_controller = False + def _determine_node_roles(self, context=None): """Assign NodeRoles to Nodes in Composition @@ -4415,8 +4456,8 @@ def _create_CIM_ports(self, context=None): OutputPort of each OUTPUT node. Connect the OUTPUT node's OutputPort to the output_CIM's corresponding InputPort via a standard MappingProjection. - - create a corresponding InputPort and ControlSignal on the `parameter_CIM ` for each - InputPort of each node in the Composition that receives a modulatory projection from an enclosing + - create a corresponding InputPort and ControlSignal on the `parameter_CIM ` for + each InputPort of each node in the Composition that receives a modulatory projection from an enclosing Composition. Connect the original ControlSignal to the parameter_CIM's corresponding InputPort via a standard MappingProjection, then activate the projections that are created automatically during instantiation of the ControlSignals to carry that signal to the target ParameterPort. @@ -4769,24 +4810,28 @@ def _get_nested_node_CIM_port(self, for nc in nested_comps: nested_nodes = dict(nc._get_nested_nodes()) if node in nested_nodes or node in nc.nodes.data: + owning_composition = nc if node in nc.nodes else nested_nodes[node] # Must be assigned Node.Role of INPUT or OUTPUT (depending on receiver vs sender) # This validation does not apply to ParameterPorts. Externally modulated nodes - # can be in any position within a Composition. They don't need to be INPUT or OUTPUT nodes + # can be in any position within a Composition. They don't need to be INPUT or OUTPUT nodes. if not isinstance(node_port, ParameterPort): - owning_composition = nc if node in nc.nodes.data else nested_nodes[node] if role not in owning_composition.nodes_to_roles[node]: - raise CompositionError("{} found in nested {} of {} ({}) but without required {} ({})". - format(node.name, Composition.__name__, self.name, nc.name, - NodeRole.__name__, repr(role))) + # raise CompositionError(f"{node.name} found in nested {Composition.__name__} of {self.name} " + # f"({nc.name}) but without required {role}.") + raise CompositionError(f"{node.name} found in nested {Composition.__name__} of {self.name} " + f"({nc.name}) but without required {role}.", + ERROR='NOT_OUTPUT_NODE', + COMPOSITION=owning_composition, + NODE=node) # With the current implementation, there should never be multiple nested compositions that contain the # same mechanism -- because all nested compositions are passed the same execution ID + # FIX: 11/15/21: ??WHY IS THIS COMMENTED OUT: # if CIM_port_for_nested_node: # warnings.warn("{} found with {} of {} in more than one nested {} of {}; " # "only first one found (in {}) will be used". # format(node.name, NodeRole.__name__, repr(role), # Composition.__name__, self.name, nested_comp.name)) # continue - if isinstance(node_port, InputPort): if node_port in nc.input_CIM_ports: CIM_port_for_nested_node = owning_composition.input_CIM_ports[node_port][0] @@ -4819,77 +4864,10 @@ def _get_nested_node_CIM_port(self, break return CIM_port_for_nested_node, CIM_port_for_nested_node, nested_comp, CIM - def _update_shadows_dict(self, node): - # Create an empty entry for this node in the Composition's "shadows" dict - # If any other nodes shadow this node, they will be added to the list - if node not in self.shadows: - self.shadows[node] = [] - - nested_nodes = dict(self._get_nested_nodes()) - # If this node is shadowing another node, then add it to that node's entry in the Composition's "shadows" dict - # If the node it's shadowing is a nested node, add it to the entry for the composition it's nested in. - for input_port in node.input_ports: - if hasattr(input_port, SHADOW_INPUTS) and input_port.shadow_inputs is not None: - owner = input_port.shadow_inputs.owner - if isinstance(owner, CompositionInterfaceMechanism): - owner = owner.composition - if owner in nested_nodes: - owner = nested_nodes[owner] - if node is self.controller and self._controller_initialization_status == ContextFlags.DEFERRED_INIT: - if owner not in self.nodes: - continue - if node not in self.shadows[owner]: - self.shadows[owner].append(node) - - def _route_control_projection_through_intermediary_pcims(self, projection, sender, sender_mechanism, receiver, graph_receiver, context): - """ - Takes as input a specification for a projection to a parameter port that is nested n-levels below its sender, - instantiates and activates ports and projections on intermediary pcims, and returns a new - projection specification from the original sender to the relevant input port of the pcim of the Composition - located in the same level of nesting. - """ - for proj in receiver.mod_afferents: - if proj.sender.owner == sender_mechanism: - receiver._remove_projection_to_port(proj) - for proj in sender.efferents: - if proj.receiver == receiver: - sender._remove_projection_from_port(proj) - modulation = sender.modulation - interface_input_port = InputPort(owner=graph_receiver.parameter_CIM, - variable=receiver.defaults.value, - reference_value=receiver.defaults.value, - name=PARAMETER_CIM_NAME + "_" + receiver.owner.name + "_" + receiver.name, - context=context) - graph_receiver.parameter_CIM.add_ports([interface_input_port], context=context) - # control signal for parameter CIM that will project directly to inner Composition's parameter - control_signal = ControlSignal( - modulation=modulation, - variable=(OWNER_VALUE, functools.partial(graph_receiver.parameter_CIM.get_input_port_position, interface_input_port)), - transfer_function=Identity, - modulates=receiver, - name=PARAMETER_CIM_NAME + "_" + receiver.owner.name + "_" + receiver.name, - ) - if receiver.owner not in graph_receiver.nodes.data + graph_receiver.cims: - receiver = interface_input_port - graph_receiver.parameter_CIM.add_ports([control_signal], context=context) - # add sender and receiver to self.parameter_CIM_ports dict - for p in control_signal.projections: - # self.add_projection(p) - graph_receiver.add_projection(p, receiver=p.receiver, sender=control_signal) - try: - sender._remove_projection_to_port(projection) - except ValueError: - pass - try: - receiver._remove_projection_from_port(projection) - except ValueError: - pass - receiver = interface_input_port - return MappingProjection(sender=sender, receiver=receiver) - + # endregion NODES # ****************************************************************************************************************** - # PROJECTIONS + # region ----------------------------------- PROJECTIONS ----------------------------------------------------------- # ****************************************************************************************************************** def add_projections(self, projections=None): @@ -4947,7 +4925,7 @@ def add_projection(self, - if it is in the Composition: - if there is only one, the request is ignored and the existing Projection is returned - if there is more than one, an exception is raised as this should never be the case - - it is NOT in the Composition: + - if it is NOT in the Composition: - if there is only one, that Projection is used; - if there is more than one, the last in the list (presumably the most recent) is used; in either case, processing continues, to activate it for the Composition, @@ -4970,18 +4948,17 @@ def add_projection(self, its `sender ` and `receiver ` a warning is generated and the request is ignored. - COMMENT: - IMPLEMENTATION NOTE: - Duplicates are determined by the **Ports** to which they project, not the Mechanisms (to allow - multiple Projections to exist between the same pair of Mechanisms using different Ports). - - + + .. technical_note:: + Duplicates are determined by the `Ports ` to which they project, not the `Mechanisms ` + (to allow multiple Projections to exist between the same pair of Mechanisms using different Ports). + .. If an already instantiated Projection is passed to add_projection and is a duplicate of an existing one, - it is detected and suppresed, with a warning, in Port._instantiate_projections_to_port. - - + it is detected and suppressed, with a warning, in Port._instantiate_projections_to_port. + .. If a Projection with deferred_init status is a duplicate, it is fully suppressed here, as these are generated by add_linear_processing_pathway if the pathway overlaps with an existing one, and so warnings are unnecessary and would be confusing to users. - COMMENT Arguments --------- @@ -5173,16 +5150,6 @@ def add_projection(self, # Note: do all of the following even if Projection is a existing_projections, # as these conditions should apply to the exisiting one (and it won't hurt to try again if they do) - # Create "shadow" projections to any input ports that are meant to shadow this projection's receiver - # (note: do this even if there is a duplciate and they are not allowed, as still want to shadow that projection) - if receiver_mechanism in self.shadows and len(self.shadows[receiver_mechanism]) > 0: - for shadow in self.shadows[receiver_mechanism]: - for input_port in shadow.input_ports: - if input_port.shadow_inputs is not None: - if input_port.shadow_inputs.owner == receiver: - # TBI: Copy the projection type/matrix value of the projection that is being shadowed - self.add_projection(MappingProjection(sender=sender, receiver=input_port), - sender_mechanism, shadow) # if feedback in {True, FEEDBACK}: # self.feedback_senders.add(sender_mechanism) # self.feedback_receivers.add(receiver_mechanism) @@ -5281,7 +5248,7 @@ def _parse_sender_spec(self, projection, sender): else: sender_name = sender.name - # if the sender is IN a nested Composition AND sender is an OUTPUT Node + # if the sender is in a nested Composition AND sender is an OUTPUT Node # then use the corresponding CIM on the nested comp as the sender going forward sender, sender_output_port, graph_sender, sender_mechanism = \ self._get_nested_node_CIM_port(sender_mechanism, @@ -5300,8 +5267,8 @@ def _parse_sender_spec(self, projection, sender): if projection.sender.owner != sender and \ projection.sender.owner != graph_sender and \ projection.sender.owner != sender_mechanism: - raise CompositionError("The position of {} in {} conflicts with its sender attribute." - .format(projection.name, self.name)) + raise CompositionError(f"The position of {projection.name} in {self.name} " + f"conflicts with its sender ({sender.name}).") return sender, sender_mechanism, graph_sender, nested_compositions @@ -5383,38 +5350,85 @@ def _parse_receiver_spec(self, projection, receiver, sender, learning_projection return receiver, receiver_mechanism, graph_receiver, receiver_input_port, \ nested_compositions, learning_projection - def _get_original_senders(self, input_port, projections): - original_senders = set() - for original_projection in projections: - if original_projection in self.projections: - original_senders.add(original_projection.sender) - correct_sender = original_projection.sender - shadow_found = False - for shadow_projection in input_port.path_afferents: - if shadow_projection.sender == correct_sender: - shadow_found = True - break - if not shadow_found: - # TBI - Shadow projection type? Matrix value? - new_projection = MappingProjection(sender=correct_sender, - receiver=input_port) - self.add_projection(new_projection, sender=correct_sender, receiver=input_port) - return original_senders - def _update_shadow_projections(self, context=None): - for node in self.nodes: - for input_port in node.input_ports: - if input_port.shadow_inputs: - original_senders = self._get_original_senders(input_port, input_port.shadow_inputs.path_afferents) - for shadow_projection in input_port.path_afferents: - if shadow_projection.sender not in original_senders: - self.remove_projection(shadow_projection) + """Instantiate any missing shadow_projections that have been specified in Composition + """ - # MODIFIED 4/4/20 OLD: - # # If the node does not have any roles, it is internal - # if len(self.get_roles_by_node(node)) == 0: - # self._add_node_role(node, NodeRole.INTERNAL) - # MODIFIED 4/4/20 END + # FIX 12/2/21: RENAME input_port -> shadowing_input_port + def _instantiate_missing_shadow_projections(input_port, projections): + """Instantiate shadow Projections that don't yet exist. + + **input_port** is InputPort to receive shadow Projections + **projections** are Projections to be shadowed + + Search recursively (i.e., including in nested Compositions) for receiver(s) of projections. + Instantiate any shadow Projections for them that don't yet exist. + Return actual senders of all shadow Projections. + """ + + def _get_correct_sender(comp, shadowed_projection): + """Search down the hierarchy of nested Compositions for Projection to shadow""" + if shadowed_projection in comp.projections: + return shadowed_projection.sender + else: + # Search for sender in INPUT Nodes of nested Compositions that are themselves INPUT Nodes + nested_input_comps = [nested_comp for nested_comp in comp._get_nested_compositions() + if nested_comp in comp.get_nodes_by_role(NodeRole.INPUT)] + for comp in nested_input_comps: + if shadowed_projection in comp.projections: + return _get_sender_at_right_level(shadowed_projection) + else: + return _get_correct_sender(comp, shadowed_projection) + return None + + def _get_sender_at_right_level(shadowed_proj): + """Search back up hierarchy of nested Compositions for sender at same level as **input_port**""" + if not isinstance(shadowed_proj.sender.owner, CompositionInterfaceMechanism): + raise CompositionError(f"Attempt to shadow the input(s) to a node " + f"({shadowed_proj.receiver.owner.name}) in a nested Composition " + f"(of {self.name}) is not currently supported.") + else: + # WANT THIS ONE'S SENDER + # item[0] item[1,0] item[1,1] + # CIM MAP ENTRIES: [SHADOWED PORT, [input_CIM InputPort, input_CIM OutputPort]] + sender_proj = [entry[1][0] + for entry in list(shadowed_proj.sender.owner.port_map.items()) + if entry[1][1] is shadowed_proj.sender][0].path_afferents[0] + if input_port.owner in sender_proj.sender.owner.composition._all_nodes: + return sender_proj.sender + else: + return _get_sender_at_right_level(sender_proj) + + original_senders = set() + for shadowed_projection in projections: + correct_sender = _get_correct_sender(self, shadowed_projection) + if correct_sender: + original_senders.add(correct_sender) + shadow_found = False + for shadow_projection in input_port.path_afferents: + if shadow_projection.sender == correct_sender: + shadow_found = True + break + if not shadow_found: + # TBI - Shadow projection type? Matrix value? + new_projection = MappingProjection(sender=correct_sender, + receiver=input_port) + self.add_projection(new_projection, sender=correct_sender, receiver=input_port) + return original_senders + + for shadowing_port, shadowed_port in self.shadowing_dict.items(): + senders = _instantiate_missing_shadow_projections(shadowing_port, + shadowed_port.path_afferents) + for shadow_projection in shadowing_port.path_afferents: + if shadow_projection.sender not in senders: + self.remove_projection(shadow_projection) + Projection_Base._delete_projection(shadow_projection) + if not shadow_projection.sender.efferents: + if isinstance(shadow_projection.sender.owner, CompositionInterfaceMechanism): + ports = shadow_projection.sender.owner.port_map.pop(shadow_projection.receiver) + shadow_projection.sender.owner.remove_ports(list(ports)) + else: + shadow_projection.sender.owner.remove_ports(shadow_projection.sender) def _check_for_projection_assignments(self, context=None): """Check that all Projections and Ports with require_projection_in_composition attribute are configured. @@ -5557,12 +5571,13 @@ def _check_for_nesting_with_absolute_conditions(self, scheduler, termination_con if warn: warnings.warn(warn_str) + # endregion PROJECTIONS + # ****************************************************************************************************************** - # PATHWAYS + # region ------------------------------------- PATHWAYS ------------------------------------------------------------ # ****************************************************************************************************************** - - # ----------------------------------------- PROCESSING ----------------------------------------------------------- + # region ---------------------------------- PROCESSING ----------------------------------------------------------- # FIX: REFACTOR TO TAKE Pathway OBJECT AS ARGUMENT def add_pathway(self, pathway): @@ -5865,11 +5880,7 @@ def add_linear_processing_pathway(self, pathway, name:str=None, context=None, *a context=context) self.pathways.append(pathway) - # FIX 4/4/20 [JDC]: Reset to None for now to replicate prior behavior, - # but need to implement proper behavior wrt call to analyze_graph() - # _check_initalization_state() - # 10/22/20 [KDM]: Pass no context instead of setting to None - self._analyze_graph() + self._analyze_graph(context) return pathway @@ -5927,12 +5938,8 @@ def add_pathways(self, pathways, context=None): pathways = convert_to_list(pathways) # Possibility 2 (list is a single pathway spec): - # # MODIFIED 5/17/20 OLD: - # if isinstance(pathways, list) and all(_is_node_spec(p) for p in pathways): - # MODIFIED 5/17/20 NEW: if (isinstance(pathways, list) and _is_node_spec(pathways[0]) and all(_is_pathway_entry_spec(p, ANY) for p in pathways)): - # MODIFIED 5/17/20 END # Place in outter list (to conform to processing of multiple pathways below) pathways = [pathways] # If pathways is not now a list it must be illegitimate @@ -6021,7 +6028,9 @@ def identify_pway_type_and_parse_tuple_prn(pway, tuple_or_dict_str): return added_pathways - # ------------------------------------------ LEARNING ------------------------------------------------------------ + # endregion PROCESSING PATHWAYS + + # region ------------------------------------ LEARNING ------------------------------------------------------------- @handle_external_context() def add_linear_learning_pathway(self, @@ -6030,11 +6039,7 @@ def add_linear_learning_pathway(self, loss_function=None, learning_rate:tc.any(int,float)=0.05, error_function=LinearCombination, - # # MODIFIED 5/25/20 OLD: - # learning_update:tc.any(bool, tc.enum(ONLINE, AFTER))=ONLINE, - # MODIFIED 5/25/20 NEW: learning_update:tc.any(bool, tc.enum(ONLINE, AFTER))=AFTER, - # MODIFIED 5/25/20 END name:str=None, context=None): """Implement learning pathway (including necessary `learning components `. @@ -7079,19 +7084,27 @@ def _get_deeply_nested_aux_projections(self, node): aux_projections[i] = i nested_nodes = self._get_nested_nodes() for spec, proj in aux_projections.items(): - if proj.receiver.owner not in self.nodes and \ - proj.receiver.owner in [i[0] for i in nested_nodes if not i[1] in self.nodes]: + # FIX: TREATMENT OF RECEIVERS SEEMS TO DEAL WITH ONLY RECEIVERS IN COMPS NESTED MORE THAN ON LEVEL DEEP + # REMOVING "if not i[1] in self.nodes" crashes in test_multilevel_control + if ((proj.sender.owner not in self.nodes + and proj.sender.owner in [i[0] for i in nested_nodes]) + or (proj.receiver.owner not in self.nodes + and proj.receiver.owner in [i[0] for i in nested_nodes if not i[1] in self.nodes])): deeply_nested_projections[spec] = proj return deeply_nested_projections + # endregion LEARNING PATHWAYS + + # endregion PATHWAYS + # ****************************************************************************************************************** - # CONTROL + # region ------------------------------------- CONTROL ------------------------------------------------------------- # ****************************************************************************************************************** @handle_external_context() def add_controller(self, controller:ControlMechanism, context=None): """ - Add an `ControlMechanism` as the `controller ` of the Composition. + Add a `ControlMechanism` as the `controller ` of the Composition. This gives the ControlMechanism access to the `Composition`'s `evaluate ` method. This allows subclasses of ControlMechanism that can use this (such as `OptimizationControlMechanism`) to execute @@ -7103,13 +7116,15 @@ def add_controller(self, controller:ControlMechanism, context=None): `, and a `ControlProjection` to its correponding `ParameterPort`. The ControlMechanism is assigned the `NodeRole` `CONTROLLER`. - """ if not isinstance(controller, ControlMechanism): raise CompositionError(f"Specification of {repr(CONTROLLER)} arg for {self.name} " f"must be a {repr(ControlMechanism.__name__)} ") + # Call with context to avoid recursion by analyze_graph -> _check_initialization_status -> add_controller + context.source = ContextFlags.METHOD + # VALIDATE AND ADD CONTROLLER # Note: initialization_status here pertains to controller's own initialization status @@ -7136,80 +7151,70 @@ def add_controller(self, controller:ControlMechanism, context=None): f"for another {COMPOSITION} ({controller.composition.name}); assignment ignored.") return - # Warn if current one is being replaced, and remove Projections for old one + # Remove existing controller if there is one if self.controller: + # Warn if current one is being replaced if self.prefs.verbosePref: warnings.warn(f"The existing {CONTROLLER} for {self.name} ({self.controller.name}) " f"is being replaced by {controller.name}.") - for proj in self.projections: + # Remove Projections for old one + for proj in self.projections.copy(): if (proj in self.controller.afferents or proj in self.controller.efferents): self.remove_projection(proj) + Projection_Base._delete_projection(proj) self.controller.composition=None + # Assign mutual references between Composition and controller controller.composition = self self.controller = controller # Having controller in nodes is not currently supported (due to special handling of scheduling/execution); # its NodeRole assignment is handled directly by the get_nodes_by_role and get_roles_by_node methods. # self._add_node_role(controller, NodeRole.CONTROLLER) - # ADD AUX_COMPONENTS RELEVANT TO CONTROLLER - + # Check aux_components relevant to controller invalid_aux_components = self._get_invalid_aux_components(controller) - if invalid_aux_components: self._controller_initialization_status = ContextFlags.DEFERRED_INIT + return - # FIX: 11/3/21: ISN'T THIS HANDLED IN HANDLING OF aux_components? - if self.controller.objective_mechanism and self.controller.objective_mechanism not in invalid_aux_components: - self.add_node(self.controller.objective_mechanism, required_roles=NodeRole.CONTROLLER_OBJECTIVE) - - self.node_ordering.append(controller) - - self.enable_controller = True + # ADD MONITORING COMPONENTS ----------------------------------------------------- - controller._activate_projections_for_compositions(self) - # Call with context to avoid recursion by analyze_graph -> _check_inialization_status -> add_controller - context.source = ContextFlags.METHOD - self._analyze_graph(context=context) - self._update_shadows_dict(controller) - - # INSTANTIATE SHADOW_INPUT PROJECTIONS - # Skip controller's first (OUTCOME) input_port (that receives the Projection from its objective_mechanism - nested_cims = [comp.input_CIM for comp in self._get_nested_compositions()] - input_cims= [self.input_CIM] + nested_cims - # For the rest of the controller's input_ports if they are marked as receiving SHADOW_INPUTS, - # instantiate the shadowing Projection to them from the sender to the shadowed InputPort - # FIX: 11/3/21: BELOW NEEDS TO BE CORRECTED IF OUTCOME InputPort GETS MOVED - # ALSO, IF Non-OCM IS USED AS CONTROLLER, MAY HAVE MORE THAN ONE Inport FOR MONITORING - for input_port in controller.input_ports[1:]: - if hasattr(input_port, SHADOW_INPUTS) and input_port.shadow_inputs is not None: - for proj in input_port.shadow_inputs.path_afferents: + if self.controller.objective_mechanism: + # If controller has objective_mechanism, then add it and all associated Projections to Composition + if self.controller.objective_mechanism not in invalid_aux_components: + self.add_node(self.controller.objective_mechanism, required_roles=NodeRole.CONTROLLER_OBJECTIVE) + else: + # Otherwise, if controller has any afferent inputs (from items in monitor_for_control), add them + if self.controller.input_ports and self.controller.input_port.path_afferents: + # FIX 11/27/21: THIS IS A HACK TO MAKE INTERNAL NODES OF NESTED COMPOSITIONS AVAILABLE FOR MONITORING + # SHOULD BE REPLACED WITH DEDICATED NodeRole.PROBE and probe_CIM + keep_checking = True + while(keep_checking): try: - sender = proj.sender - if sender.owner not in input_cims: - self.add_projection(projection=MappingProjection(sender=sender, receiver=input_port), - sender=sender.owner, - receiver=controller) - shadow_proj._activate_for_compositions(self) - else: - if not sender.owner.composition == self: - sender_input_cim = sender.owner - proj_index = sender_input_cim.output_ports.index(sender) - sender_corresponding_input_projection = sender_input_cim.input_ports[ - proj_index].path_afferents[0] - input_projection_sender = sender_corresponding_input_projection.sender - if input_projection_sender.owner == self.input_CIM: - shadow_proj = MappingProjection(sender=input_projection_sender, - receiver = input_port) - shadow_proj._activate_for_compositions(self) + self._add_node_aux_components(controller, context) + keep_checking = False + except CompositionError as e: + # If error is because INTERNAL Node has been specified as monitor_for_control on controller + if e.return_items.pop(ERROR,None) == 'NOT_OUTPUT_NODE': + # If controller.allow_probes has also been specified as 'True', assign NodeRole.OUTPUT + if hasattr(self.controller, 'allow_probes') and self.controller.allow_probes is True: + nested_comp = e.return_items.pop(COMPOSITION, None) + node = e.return_items.pop(NODE, None) + nested_comp._add_required_node_role(node, NodeRole.OUTPUT, context) + self._analyze_graph(context) + keep_checking = True + # Otherwise, return usual error else: - shadow_proj = MappingProjection(sender=proj.sender, receiver=input_port) - shadow_proj._activate_for_compositions(self) - except DuplicateProjectionError: - continue - for proj in input_port.path_afferents: - if proj.sender.owner not in nested_cims: - proj._activate_for_compositions(self) + raise CompositionError(e.error_value) + else: + assert False, f"PROGRAM ERROR: Unable to apply NodeRole.OUTPUT to {node} of {nested_comp} "\ + f"specified in 'monitor_for_control' arg for {controller.name} of {self.name}" + # else: + # raise CompositionError(e.error_value) + + # This is set by add_node() automatically if there is an objective_mechanism; + # needs to be set here to insure call at run time (to catch any new nodes that may have been added) + self.needs_update_controller = True # Confirm that controller has input, and if not then disable it if not (isinstance(self.controller.input_ports, ContentAddressableList) @@ -7221,32 +7226,60 @@ def add_controller(self, controller:ControlMechanism, context=None): self.enable_controller = False return - # ADD ANY ControlSignals SPECIFIED BY NODES IN COMPOSITION + # ADD MODULATORY COMPONENTS ----------------------------------------------------- # Get rid of default ControlSignal if it has no ControlProjections controller._remove_default_control_signal(type=CONTROL_SIGNAL) + # Instantiate control specifications locally (on nodes) and/or on controller + self._instantiate_control_projections(context=context) + # Instantiate any + for node in self.nodes: + self._instantiate_deferred_init_control(node, context) - # Add any ControlSignals specified for ParameterPorts of Nodes already in the Composition - control_signal_specs = self._get_control_signals_for_composition() - for ctl_sig_spec in control_signal_specs: - # FIX: 9/14/19: THIS SHOULD BE HANDLED IN _instantiate_projection_to_port - # CALLED FROM _instantiate_control_signal - # SHOULD TRAP THAT ERROR AND GENERATE CONTEXT-APPROPRIATE ERROR MESSAGE - # Don't add any that are already on the ControlMechanism + # ACTIVATE FOR COMPOSITION ----------------------------------------------------- - # FIX: 9/14/19 - IS THE CONTEXT CORRECT (TRY TRACKING IN SYSTEM TO SEE WHAT CONTEXT IS): - ctl_signal = controller._instantiate_control_signal(control_signal=ctl_sig_spec, - context=context) - controller.control.append(ctl_signal) - # FIX: 9/15/19 - WHAT IF NODE THAT RECEIVES ControlProjection IS NOT YET IN COMPOSITON: - # ?DON'T ASSIGN ControlProjection? - # ?JUST DON'T ACTIVATE IT FOR COMPOSITON? - # ?PUT IT IN aux_components FOR NODE? - # ! TRACE THROUGH _activate_projections_for_compositions TO SEE WHAT IT CURRENTLY DOES - controller._activate_projections_for_compositions(self) + self.node_ordering.append(controller) + self.enable_controller = True + # FIX: 11/15/21 - SHOULD THIS METHOD BE MOVED HERE (TO COMPOSITION) FROM ControlMechanism + controller._activate_projections_for_compositions(self) + self._analyze_graph(context=context) if not invalid_aux_components: self._controller_initialization_status = ContextFlags.INITIALIZED - self._analyze_graph(context=context) + + def _instantiate_deferred_init_control(self, node, context=None): + """ + If node is a Composition with a controller, activate its nodes' deferred init control specs for its controller. + If it does not have a controller, but self does, activate them for self's controller. + + If node is a Node that has deferred init control specs and self has a controller, activate the deferred init + control specs for self's controller. + + Called recursively on nodes that are nested Compositions. + + Returns + ------- + + list of hanging control specs that were not able to be assigned for a controller at any level of nesting. + + """ + hanging_control_specs = [] + if node.componentCategory == 'Composition': + nested_comp = node # For readability + for node_in_nested_comp in nested_comp.nodes: + hanging_control_specs.extend(nested_comp._instantiate_deferred_init_control(node_in_nested_comp, + context=context)) + assert True + else: + hanging_control_specs = node._get_parameter_port_deferred_init_control_specs() + if not self.controller: + return hanging_control_specs + else: + for spec in hanging_control_specs: + control_signal = self.controller._instantiate_control_signal(control_signal=spec, + context=context) + self.controller.control.append(control_signal) + self.controller._activate_projections_for_compositions(self) + return [] def _get_control_signals_for_composition(self): """Return list of ControlSignals specified by Nodes in the Composition @@ -7276,19 +7309,188 @@ def _get_control_signals_for_composition(self): control_signal_specs.extend(node._get_parameter_port_deferred_init_control_specs()) return control_signal_specs + def reshape_control_signal(self, arr): + + current_shape = np.shape(arr) + if len(current_shape) > 2: + newshape = (current_shape[0], current_shape[1]) + newarr = np.reshape(arr, newshape) + arr = tuple(newarr[i].item() for i in range(len(newarr))) + + return np.array(arr) + + def _instantiate_control_projections(self, context): + """ + Add any ControlProjections for control specified locally on nodes in Composition + """ + + # Add any ControlSignals specified for ParameterPorts of Nodes already in the Composition + control_signal_specs = self._get_control_signals_for_composition() + for ctl_sig_spec in control_signal_specs: + # FIX: 9/14/19: THIS SHOULD BE HANDLED IN _instantiate_projection_to_port + # CALLED FROM _instantiate_control_signal + # SHOULD TRAP THAT ERROR AND GENERATE CONTEXT-APPROPRIATE ERROR MESSAGE + # Don't add any that are already on the ControlMechanism + + # FIX: 9/14/19 - IS THE CONTEXT CORRECT (TRY TRACKING IN SYSTEM TO SEE WHAT CONTEXT IS): + ctl_signal = self.controller._instantiate_control_signal(control_signal=ctl_sig_spec, context=context) + + self.controller.control.append(ctl_signal) + + # MODIFIED 11/21/21 OLD: FIX: WHY IS THIS INDENTED? WON'T CALL OUTSIDE LOOP ACTIVATE ALL PROJECTIONS? + # FIX: 9/15/19 - WHAT IF NODE THAT RECEIVES ControlProjection IS NOT YET IN COMPOSITION: + # ?DON'T ASSIGN ControlProjection? + # ?JUST DON'T ACTIVATE IT FOR COMPOSITON? + # ?PUT IT IN aux_components FOR NODE? + # ! TRACE THROUGH _activate_projections_for_compositions TO SEE WHAT IT CURRENTLY DOES + self.controller._activate_projections_for_compositions(self) + + def _route_control_projection_through_intermediary_pcims(self, + projection, + sender, + sender_mechanism, + receiver, + graph_receiver, + context): + """ + Takes as input a specification for a projection to a parameter port that is nested n-levels below its sender, + instantiates and activates ports and projections on intermediary pcims, and returns a new + projection specification from the original sender to the relevant input port of the pcim of the Composition + located in the same level of nesting. + """ + for proj in receiver.mod_afferents: + if proj.sender.owner == sender_mechanism: + receiver._remove_projection_to_port(proj) + for proj in sender.efferents: + if proj.receiver == receiver: + sender._remove_projection_from_port(proj) + modulation = sender.modulation + interface_input_port = InputPort(owner=graph_receiver.parameter_CIM, + variable=receiver.defaults.value, + reference_value=receiver.defaults.value, + name=PARAMETER_CIM_NAME + "_" + receiver.owner.name + "_" + receiver.name, + context=context) + graph_receiver.parameter_CIM.add_ports([interface_input_port], context=context) + # control signal for parameter CIM that will project directly to inner Composition's parameter + control_signal = ControlSignal( + modulation=modulation, + variable=(OWNER_VALUE, functools.partial(graph_receiver.parameter_CIM.get_input_port_position, + interface_input_port)), + transfer_function=Identity, + modulates=receiver, + name=PARAMETER_CIM_NAME + "_" + receiver.owner.name + "_" + receiver.name, + ) + if receiver.owner not in graph_receiver.nodes.data + graph_receiver.cims: + receiver = interface_input_port + graph_receiver.parameter_CIM.add_ports([control_signal], context=context) + # add sender and receiver to self.parameter_CIM_ports dict + for p in control_signal.projections: + # self.add_projection(p) + graph_receiver.add_projection(p, receiver=p.receiver, sender=control_signal) + try: + sender._remove_projection_to_port(projection) + except ValueError: + pass + try: + receiver._remove_projection_from_port(projection) + except ValueError: + pass + receiver = interface_input_port + return MappingProjection(sender=sender, receiver=receiver) + + def _check_controller_initialization_status(self, context=None): + """Checks initialization status of controller (if applicable) all Projections or Ports in the Composition + """ + + # Avoid recursion if called from add_controller (by way of analyze_graph) since that is called below + if context and context.source == ContextFlags.METHOD: + return + + # If controller is in deferred init, try to instantiate and add it to Composition + if self.controller and self._controller_initialization_status == ContextFlags.DEFERRED_INIT: + self.add_controller(self.controller, context=context) + + # Don't bother checking any further if from COMMAND_LINE or COMPOSITION (i.e., anything other than Run) + # since no need to detect deferred_init and generate errors until runtime + if context and context.source in {ContextFlags.COMMAND_LINE, ContextFlags.COMPOSITION}: + return + + # Check for Mechanisms and Projections in aux_components + if self._controller_initialization_status == ContextFlags.DEFERRED_INIT: + invalid_aux_components = self._get_invalid_aux_components(self.controller) + for component in invalid_aux_components: + if isinstance(component, Projection): + if hasattr(component.receiver, OWNER_MECH): + owner = component.receiver.owner_mech + else: + owner = component.receiver.owner + warnings.warn( + f"The controller of {self.name} has been specified to project to {owner.name}, " + f"but {owner.name} is not in {self.name} or any of its nested Compositions. " + f"This projection will be deactivated until {owner.name} is added to {self.name} " + f"in a compatible way." + ) + elif isinstance(component, Mechanism): + warnings.warn( + f"The controller of {self.name} has a specification that includes the Mechanism " + f"{component.name}, but {component.name} is not in {self.name} or any of its " + f"nested Compositions. This Mechanism will be deactivated until {component.name} is " + f"added to {self.name} or one of its nested Compositions in a compatible way." + ) + + # If Composition is not preparing to execute, allow deferred_inits to persist without warning + if context and ContextFlags.PREPARING not in context.execution_phase: + return + + # Check for deferred init ControlProjections + for node in self.nodes: + for projection in node.projections: + if projection.initialization_status == ContextFlags.DEFERRED_INIT: + if isinstance(projection, ControlProjection): + warnings.warn(f"The {projection.receiver.name} parameter of {projection.receiver.owner.name} \n" + f"is specified for control, but {self.name} does not have a controller. Please \n" + f"add a controller to {self.name} or the control specification will be \n" + f"ignored.") + + def _check_nodes_initialization_status(self, context=None): + + # Avoid recursion if called from add_controller (by way of analyze_graph) since that is called below. + # Don't bother checking if from COMMAND_LINE or COMPOSITION (i.e., anything other than Run) + # since no need to detect deferred_init and generate errors until runtime. + # If Composition is not preparing to execute, allow deferred_inits to persist without warning + if context and (context.source in {ContextFlags.METHOD, ContextFlags.COMMAND_LINE, ContextFlags.COMPOSITION} + or ContextFlags.PREPARING not in context.execution_phase): + return + + # NOTE: + # May want to add other conditions and warnings here. + # Currently just checking for unresolved projections. + + for node in self._partially_added_nodes: + for proj in self._get_invalid_aux_components(node): + receiver = proj.receiver.owner + warnings.warn( + f"{node.name} has been specified to project to {receiver.name}, " + f"but {receiver.name} is not in {self.name} or any of its nested Compositions. " + f"This projection will be deactivated until {receiver.name} is added to {self.name} " + f"or a composition nested within it." + ) + + # FIX: 11/3/21 ??GET RID OF THIS AND CALL TO IT ONCE PROJECTIONS HAVE BEEN IMPLEMENTED FOR SHADOWED INPUTS + # CHECK WHETHER state_input_ports ADD TO OR REPLACE shadowed_inputs def _build_predicted_inputs_dict(self, predicted_input): - inputs = {} - # ASSUMPTION: input_ports[0] is NOT a feature and input_ports[1:] are state_features - # If this is not a good assumption, we need another way to look up the feature InputPorts - # of the OCM and know which InputPort maps to which predicted_input value + """Get inputs for evaluate method used to execute simulations of Composition. + Get values of state_input_ports which receive projections from items providing relevant input (and any + processing of those values specified + """ + inputs = {} no_predicted_input = (predicted_input is None or not len(predicted_input)) if no_predicted_input: warnings.warn(f"{self.name}.evaluate() called without any inputs specified; default values will be used") - nested_nodes = dict(self._get_nested_nodes()) - # FIX: 11/3/21 NEED TO MODIFY WHEN OUTCOME InputPort IS MOVED + # FIX: 11/3/21 NEED TO MODIFY IF OUTCOME InputPorts ARE MOVED shadow_inputs_start_index = self.controller.num_outcome_input_ports for j in range(len(self.controller.input_ports) - shadow_inputs_start_index): input_port = self.controller.input_ports[j + shadow_inputs_start_index] @@ -7315,64 +7517,6 @@ def _build_predicted_inputs_dict(self, predicted_input): inputs[comp]=np.concatenate([[shadowed_input],inputs[comp][0]]) return inputs - def _get_invalid_aux_components(self, controller): - valid_nodes = \ - [node for node in self.nodes.data] + \ - [node for node, composition in self._get_nested_nodes()] + \ - [self] - if self.controller: - valid_nodes.append(self.controller) - if hasattr(self.controller,'objective_mechanism'): - valid_nodes.append(self.controller.objective_mechanism) - invalid_components = [] - for aux in controller.aux_components: - component = None - if isinstance(aux, Projection): - component = aux - elif hasattr(aux, '__iter__'): - for i in aux: - if isinstance(i, Projection): - component = i - elif isinstance(i, Mechanism): - if self._get_invalid_aux_components(i): - invalid_components.append(i) - elif isinstance(aux, Mechanism): - if self._get_invalid_aux_components(aux): - invalid_components.append(aux) - if not component: - continue - if isinstance(component, Projection): - if hasattr(component.sender, OWNER_MECH): - sender_node = component.sender.owner_mech - else: - if isinstance(component.sender.owner, CompositionInterfaceMechanism): - sender_node = component.sender.owner.composition - else: - sender_node = component.sender.owner - if hasattr(component.receiver, OWNER_MECH): - receiver_node = component.receiver.owner_mech - else: - if isinstance(component.receiver.owner, CompositionInterfaceMechanism): - receiver_node = component.receiver.owner.composition - else: - receiver_node = component.receiver.owner - if not all([sender_node in valid_nodes, receiver_node in valid_nodes]): - invalid_components.append(component) - if invalid_components: - return invalid_components - else: - return [] - - def reshape_control_signal(self, arr): - - current_shape = np.shape(arr) - if len(current_shape) > 2: - newshape = (current_shape[0], current_shape[1]) - newarr = np.reshape(arr, newshape) - arr = tuple(newarr[i].item() for i in range(len(newarr))) - - return np.array(arr) - def _get_total_cost_of_control_allocation(self, control_allocation, context, runtime_params): total_cost = 0. if control_allocation is not None: # using "is not None" in case the control allocation is 0. @@ -7401,71 +7545,11 @@ def _get_total_cost_of_control_allocation(self, control_allocation, context, run total_cost = self.controller.combine_costs(all_costs) return total_cost - def _check_projection_initialization_status(self, context=None): - """Checks initialization status of controller (if applicable) and any projections or ports - """ + # endregion CONTROL - # Avoid recursion if called from add_controller (by way of analyze_graph) since that is called below - if context and context.source == ContextFlags.METHOD: - return - - # Check if controller is in deferred init - if self.controller and self._controller_initialization_status == ContextFlags.DEFERRED_INIT: - self.add_controller(self.controller, context=context) - - # Don't bother checking any further if from COMMAND_LINE or COMPOSITION (i.e., anything other than Run) - # since no need to detect deferred_init and generate errors until runtime - if context and context.source in {ContextFlags.COMMAND_LINE, ContextFlags.COMPOSITION}: - return - - if self._controller_initialization_status == ContextFlags.DEFERRED_INIT: - invalid_aux_components = self._get_invalid_aux_components(self.controller) - for component in invalid_aux_components: - if isinstance(component, Projection): - if hasattr(component.receiver, OWNER_MECH): - owner = component.receiver.owner_mech - else: - owner = component.receiver.owner - warnings.warn( - f"The controller of {self.name} has been specified to project to {owner.name}, " - f"but {owner.name} is not in {self.name} or any of its nested Compositions. " - f"This projection will be deactivated until {owner.name} is added to {self.name} " - f"in a compatible way." - ) - elif isinstance(component, Mechanism): - warnings.warn( - f"The controller of {self.name} has a specification that includes the Mechanism " - f"{component.name}, but {component.name} is not in {self.name} or any of its " - f"nested Compositions. This Mechanism will be deactivated until {component.name} is " - f"added to {self.name} or one of its nested Compositions in a compatible way." - ) - - # If Composition is not preparing to execute, allow deferred_inits to persist without warning - if context and ContextFlags.PREPARING not in context.execution_phase: - return - - for node in self.nodes: - # Check for deferred init projections - for projection in node.projections: - if projection.initialization_status == ContextFlags.DEFERRED_INIT: - # NOTE: - # May want to add other conditions and warnings here. Currently - # just checking for unresolved control projections. - if isinstance(projection, ControlProjection): - warnings.warn(f"The {projection.receiver.name} parameter of {projection.receiver.owner.name} \n" - f"is specified for control, but {self.name} does not have a controller. Please \n" - f"add a controller to {self.name} or the control specification will be \n" - f"ignored.") - - for node in self._partially_added_nodes: - for proj in self._get_invalid_aux_components(node): - receiver = proj.receiver.owner - warnings.warn( - f"{node.name} has been specified to project to {receiver.name}, " - f"but {receiver.name} is not in {self.name} or any of its nested Compositions. " - f"This projection will be deactivated until {receiver.name} is added to {self.name} " - f"or a composition nested within it." - ) + # ****************************************************************************************************************** + # region ------------------------------------ EXECUTION ------------------------------------------------------------ + # ****************************************************************************************************************** @handle_external_context() def evaluate( @@ -7504,8 +7588,8 @@ def evaluate( independently sampled seed for the random number generator. All values are reset to pre-simulation values at the end of the simulation. - Returns the `net_outcome ` of a run of - the `agent_rep `. If **return_results** is True, + Returns the `net_outcome ` of a run of the `agent_rep + `. If **return_results** is True, an array with the results of each run is also returned. """ @@ -7549,7 +7633,7 @@ def evaluate( # EXECUTE run of composition and aggregate results # Use reporting options from Report context created in initial (outer) call to run() - with Report(self, context) as report: + with Report(self, context=context) as report: result = self.run(inputs=inputs, context=context, runtime_params=runtime_params, @@ -7597,7 +7681,6 @@ def evaluate( else: return net_outcome - def _infer_target_nodes(self, targets: dict): """ Maps targets onto target mechanisms (as needed by learning) @@ -8369,18 +8452,6 @@ def run( """ context.source = ContextFlags.COMPOSITION - # FIX 5/28/20 - # context.execution_phase = ContextFlags.PREPARING - # context.replace_flag(ContextFlags.IDLE, ContextFlags.PREPARING) - - if scheduler is None: - scheduler = self.scheduler - - if scheduling_mode is not None: - scheduler.mode = scheduling_mode - - if default_absolute_time_unit is not None: - scheduler.default_absolute_time_unit = default_absolute_time_unit for node in self.nodes: num_execs = node.parameters.num_executions._get(context) @@ -8401,12 +8472,23 @@ def run( # DS 1/7/20: Check to see if any Components are still in deferred init. If so, attempt to initialize them. # If they can not be initialized, raise a warning. self._complete_init_of_partially_initialized_nodes(context=context) + if ContextFlags.SIMULATION_MODE not in context.runmode: - self._check_projection_initialization_status() + self._check_controller_initialization_status() + self._check_nodes_initialization_status() if not skip_analyze_graph: self._analyze_graph(context=context) + if scheduler is None: + scheduler = self.scheduler + + if scheduling_mode is not None: + scheduler.mode = scheduling_mode + + if default_absolute_time_unit is not None: + scheduler.default_absolute_time_unit = default_absolute_time_unit + self._check_for_unnecessary_feedback_projections() self._check_for_nesting_with_absolute_conditions(scheduler, termination_processing) @@ -9985,8 +10067,10 @@ def _delete_contexts(self, *contexts, check_simulation_storage=False, visited=No except AttributeError: self.scheduler._delete_counts(c) + # endregion EXECUTION + # ****************************************************************************************************************** - # LLVM + # region -------------------------------------- LLVM --------------------------------------------------------------- # ****************************************************************************************************************** @property @@ -10150,23 +10234,25 @@ def _dict_summary(self): }] } + # endregion LLVM + # ****************************************************************************************************************** - # PROPERTIES + # region ----------------------------------- PROPERTIES ------------------------------------------------------------ # ****************************************************************************************************************** @property def input_ports(self): - """Returns all InputPorts that belong to the Input CompositionInterfaceMechanism""" + """Return all InputPorts that belong to the Input CompositionInterfaceMechanism""" return self.input_CIM.input_ports @property def input_port(self): - """Returns the index 0 InputPort that belongs to the Input CompositionInterfaceMechanism""" + """Return the index 0 InputPort that belongs to the Input CompositionInterfaceMechanism""" return self.input_CIM.input_ports[0] @property def input_values(self): - """Returns values of all InputPorts that belong to the Input CompositionInterfaceMechanism""" + """Return values of all InputPorts that belong to the Input CompositionInterfaceMechanism""" return self.get_input_values() def get_input_values(self, context=None): @@ -10174,21 +10260,21 @@ def get_input_values(self, context=None): @property def output_ports(self): - """Returns all OutputPorts that belong to the Output CompositionInterfaceMechanism""" + """Return all OutputPorts that belong to the Output CompositionInterfaceMechanism""" return self.output_CIM.output_ports @property def output_values(self): - """Returns values of all OutputPorts that belong to the Output CompositionInterfaceMechanism in the most recently executed context""" + """Return values of all OutputPorts that belong to the Output CompositionInterfaceMechanism in the most recently executed context""" return self.get_output_values(self.most_recent_context) def get_output_values(self, context=None): return [output_port.parameters.value.get(context) for output_port in self.output_CIM.output_ports] - # @property - # def mechanisms(self): - # return MechanismList(self, [mech for mech in self.nodes - # if isinstance(mech, Mechanism)]) + @property + def shadowing_dict(self): + """Return dict with shadowing ports as the keys and the ports they shadow as values.""" + return {port:port.shadow_inputs for node in self._all_nodes for port in node.input_ports if port.shadow_inputs} @property def mechanisms(self): @@ -10224,7 +10310,7 @@ def external_input_values(self): @property def default_external_input_values(self): - """Returns the default values of all external InputPorts that belong to the + """Return the default values of all external InputPorts that belong to the Input CompositionInterfaceMechanism """ @@ -10259,7 +10345,7 @@ def stateful_nodes(self): @property def output_port(self): - """Returns the index 0 OutputPort that belongs to the Output CompositionInterfaceMechanism""" + """Return the index 0 OutputPort that belongs to the Output CompositionInterfaceMechanism""" return self.output_CIM.output_ports[0] @property @@ -10332,6 +10418,12 @@ def _all_nodes(self): if self.controller: yield self.controller + # endregion PROPERTIES + + # ****************************************************************************************************************** + # region ----------------------------------- SHOW_GRAPH ------------------------------------------------------------ + # ****************************************************************************************************************** + def show_graph(self, show_node_structure=False, show_nested=NESTED, @@ -10343,6 +10435,7 @@ def show_graph(self, show_types=False, show_dimensions=False, show_projection_labels=False, + show_projections_not_in_composition=False, active_items=None, output_fmt='pdf', context=None): @@ -10356,6 +10449,7 @@ def show_graph(self, show_types=show_types, show_dimensions=show_dimensions, show_projection_labels=show_projection_labels, + show_projections_not_in_composition=show_projections_not_in_composition, active_items=active_items, output_fmt=output_fmt, context=context) @@ -10366,6 +10460,8 @@ def _set_up_animation(self, context): def _animate_execution(self, active_items, context): self._show_graph._animate_execution(active_items, context) + # endregion SHOW_GRAPH + def get_compositions(): """Return list of Compositions in caller's namespace.""" diff --git a/psyneulink/core/compositions/compositionfunctionapproximator.py b/psyneulink/core/compositions/compositionfunctionapproximator.py index 0b09dde8e03..208dcbf4ac1 100644 --- a/psyneulink/core/compositions/compositionfunctionapproximator.py +++ b/psyneulink/core/compositions/compositionfunctionapproximator.py @@ -54,6 +54,7 @@ """ from psyneulink.core.compositions.composition import Composition +from psyneulink.core.globals.keywords import COMPOSITION_FUNCTION_APPROXIMATOR from psyneulink.core.globals.context import Context __all__ = ['CompositionFunctionApproximator'] @@ -102,6 +103,8 @@ class CompositionFunctionApproximator(Composition): """ + componentCategory = COMPOSITION_FUNCTION_APPROXIMATOR + def __init__(self, name=None, **param_defaults): # self.function = function super().__init__(name=name, **param_defaults) diff --git a/psyneulink/core/compositions/parameterestimationcomposition.py b/psyneulink/core/compositions/parameterestimationcomposition.py index ade8eebb820..5362a4e5804 100644 --- a/psyneulink/core/compositions/parameterestimationcomposition.py +++ b/psyneulink/core/compositions/parameterestimationcomposition.py @@ -117,7 +117,10 @@ * **objective_function** - specifies a function used to evaluate the `values ` of the `outcome_variables `, according to which combinations of - `parameters ` are assessed. + `parameters ` are assessed. The shape of the `variable + ` of the `objective_function (i.e., its first positional argument) must be the same as an + array containing the `value ` of the OutputPort corresponding to each item specified in + `outcome_variables `. * **optimization_function** - specifies the function used to search over values of the `parameters ` in order to optimize the **objective_function**. It can be any @@ -145,6 +148,7 @@ from psyneulink.core.components.mechanisms.processing.objectivemechanism import ObjectiveMechanism from psyneulink.core.components.ports.modulatorysignals.controlsignal import ControlSignal from psyneulink.core.compositions.composition import Composition +from psyneulink.core.globals.context import Context, ContextFlags, handle_external_context from psyneulink.core.globals.keywords import BEFORE from psyneulink.core.globals.parameters import Parameter @@ -185,33 +189,6 @@ def _same_seed_for_all_parameter_combinations_setter(value, owning_component, co return value -class Parameters(Composition.Parameters): - """ - Attributes - ---------- - - initial_seed - see `input_specification ` - - :default value: None - :type: ``int`` - - same_seed_for_all_parameter_combinations - see `input_specification ` - - :default value: False - :type: ``bool`` - - """ - # FIX: 11/32/21 CORRECT INITIAlIZATIONS? - initial_seed = Parameter(None, loggable=False, pnl_internal=True, - getter=_initial_seed_getter, - setter=_initial_seed_setter) - same_seed_for_all_parameter_combinations = Parameter(False, loggable=False, pnl_internal=True, - getter=_same_seed_for_all_parameter_combinations_getter, - setter=_same_seed_for_all_parameter_combinations_setter) - - class ParameterEstimationComposition(Composition): """ Composition( \ @@ -273,7 +250,10 @@ class ParameterEstimationComposition(Composition): specifies the function used to evaluate the `fit to data ` or `optimize ` the parameters of the `model ` according to a specified `objective_function - `. + `; the shape of its `variable ` of the + `objective_function (i.e., its first positional argument) must be the same as an array containing the `value + ` of the OutputPort corresponding to each item specified in `outcome_variables + `. num_estimates : int : default 1 specifies the number of estimates made for a each combination of `parameter ` @@ -424,6 +404,33 @@ class ParameterEstimationComposition(Composition): found to best fit the data. """ + class Parameters(Composition.Parameters): + """ + Attributes + ---------- + + initial_seed + see `input_specification ` + + :default value: None + :type: ``int`` + + same_seed_for_all_parameter_combinations + see `input_specification ` + + :default value: False + :type: ``bool`` + + """ + # FIX: 11/32/21 CORRECT INITIAlIZATIONS? + initial_seed = Parameter(None, loggable=False, pnl_internal=True, + getter=_initial_seed_getter, + setter=_initial_seed_setter) + same_seed_for_all_parameter_combinations = Parameter(False, loggable=False, pnl_internal=True, + getter=_same_seed_for_all_parameter_combinations_getter, + setter=_same_seed_for_all_parameter_combinations_setter) + + @handle_external_context() def __init__(self, parameters, # OCM control_signals outcome_variables, # OCM monitor_for_control @@ -434,8 +441,9 @@ def __init__(self, num_estimates=1, # num seeds per parameter combination (i.e., of OCM allocation_samples) num_trials_per_estimate=None, # num trials per run of model for each combination of parameters initial_seed=None, - same_seed_for_all_parameter_combinations=False, + same_seed_for_all_parameter_combinations=None, name=None, + context=None, **kwargs): self._validate_params(locals()) @@ -454,6 +462,8 @@ def __init__(self, enable_controller=True, **kwargs) + context=Context(source=ContextFlags.COMPOSITION) + # Implement OptimizationControlMechanism and assign as PEC controller # (Note: Implement after Composition itself, so that: # - Composition's components are all available (limits need for deferred_inits) @@ -466,15 +476,17 @@ def __init__(self, num_estimates=num_estimates, num_trials_per_estimate=num_trials_per_estimate, initial_seed=initial_seed, - same_seed_for_all_parameter_combinations=same_seed_for_all_parameter_combinations) - self.add_controller(ocm) + same_seed_for_all_parameter_combinations=same_seed_for_all_parameter_combinations, + context=context) + + self.add_controller(ocm, context) def _validate_params(self, args): kwargs = args.pop('kwargs') pec_name = f"{self.__class__.__name__} '{args.pop('name',None)}'" or f'a {self.__class__.__name__}' - # FIX: 11/3/21 - WRITE TESTS FOR THESE ERRORS IN test_parameterestimationcomposition.py + # FIX: 11/3/21 - WRITE TESTS FOR THESE ERRORS IN test_parameter_estimation_composition.py # Must specify either model or a COMPOSITION_SPECIFICATION_ARGS if not (args['model'] or [arg for arg in kwargs if arg in COMPOSITION_SPECIFICATION_ARGS]): @@ -517,12 +529,13 @@ def _instantiate_ocm(self, num_estimates, num_trials_per_estimate, initial_seed, - same_seed_for_all_parameter_combinations + same_seed_for_all_parameter_combinations, + context=None ): # # Parse **parameters** into ControlSignals specs control_signals = [] - for param,allocation in parameters.items(): + for param, allocation in parameters.items(): control_signals.append(ControlSignal(modulates=param, allocation_samples=allocation)) @@ -537,13 +550,15 @@ def _instantiate_ocm(self, return OptimizationControlMechanism( agent_rep=self, monitor_for_control=outcome_variables, + allow_probes=True, objective_mechanism=objective_mechanism, function=optimization_function, control_signals=control_signals, num_estimates=num_estimates, num_trials_per_estimate=num_trials_per_estimate, initial_seed=initial_seed, - same_seed_for_all_allocations=same_seed_for_all_parameter_combinations + same_seed_for_all_allocations=same_seed_for_all_parameter_combinations, + context=context ) # def run(self): diff --git a/psyneulink/core/compositions/pathway.py b/psyneulink/core/compositions/pathway.py index c30109b8134..210c1f82a9f 100644 --- a/psyneulink/core/compositions/pathway.py +++ b/psyneulink/core/compositions/pathway.py @@ -296,7 +296,7 @@ class Pathway(object): --------- pathway : list[`Node `, <`Projection `,> `Node `...] - specifies list of `Nodes ` and intercolated `Projections ` to be + specifies list of `Nodes ` and intercolated `Projections ` to be created for the Pathway. name : str : default see `name ` diff --git a/psyneulink/core/compositions/report.py b/psyneulink/core/compositions/report.py index cc6be6ee130..8a221d86dbc 100644 --- a/psyneulink/core/compositions/report.py +++ b/psyneulink/core/compositions/report.py @@ -999,7 +999,7 @@ def report_output(self, in the output report. node : Composition or Mechanism : default None - specifies `node ` for which output is being reported. + specifies `Node ` for which output is being reported. """ if self._report_output is ReportOutput.OFF: @@ -1328,7 +1328,7 @@ def node_execution_report(self, is_controller=False ) -> Panel: """ - Generates formatted output report for the `node ` of a `Composition` or a `Mechanism`. + Generates formatted output report for the `Node ` of a `Composition` or a `Mechanism`. Called by `report_output ` for execution of a Composition, and directly by the `execute ` method of a `Mechanism` when executed on its own. @@ -1347,7 +1347,7 @@ def node_execution_report(self, if it is not specified, it is resolved by calling the node's get_input_values() method. params : 'params' or 'parameters' : default None - specifies whether to report the values of the `Parameters` of the `node ` being executed + specifies whether to report the values of the `Parameters` of the `Node ` being executed together with its input and output. output_val : 2d array : default None diff --git a/psyneulink/core/compositions/showgraph.py b/psyneulink/core/compositions/showgraph.py index c345c6051cb..0e29063d4e2 100644 --- a/psyneulink/core/compositions/showgraph.py +++ b/psyneulink/core/compositions/showgraph.py @@ -42,8 +42,8 @@ `learning compnents `. These are listed as the arguments for the show_graph ` method below. -*Display attributes* -- state_features (such as the colors and shapes) in which different types of nodes are displayed can -be modified by assigning a dictionary of attribute:values pairs to the **show_graph_configuration** argument of the +*Display attributes* -- state_features (such as the colors and shapes) in which different types of nodes are displayed +can be modified by assigning a dictionary of attribute:values pairs to the **show_graph_configuration** argument of the Composition's constructor. These are listed as the arguments for the ShowGraph object (used to display the graph) in the `class reference ` below. @@ -216,9 +216,10 @@ PROJECTION, PROJECTIONS, ROLES, SIMULATIONS, VALUES from psyneulink.core.globals.utilities import convert_to_list -__all__ = ['DURATION', 'EXECUTION_SET', 'INITIAL_FRAME', 'MOVIE_DIR', 'MOVIE_NAME', - 'MECH_FUNCTION_PARAMS', 'NUM_TRIALS', 'NUM_RUNS', 'PORT_FUNCTION_PARAMS', - 'SAVE_IMAGES', 'SHOW', 'SHOW_CIM', 'SHOW_CONTROLLER', 'SHOW_LEARNING', 'ShowGraph', 'UNIT',] +__all__ = ['DURATION', 'EXECUTION_SET', 'INITIAL_FRAME', 'MOVIE_DIR', 'MOVIE_NAME', 'MECH_FUNCTION_PARAMS', + 'NUM_TRIALS', 'NUM_RUNS', 'PORT_FUNCTION_PARAMS', 'SAVE_IMAGES', + 'SHOW', 'SHOW_CIM', 'SHOW_CONTROLLER', 'SHOW_LEARNING', 'SHOW_PROJECTIONS_NOT_IN_COMPOSITION', + 'ShowGraph', 'UNIT',] # Arguments passed to each nested Composition @@ -237,6 +238,7 @@ SHOW_TYPES = 'show_types' SHOW_DIMENSIONS = 'show_dimensions' SHOW_PROJECTION_LABELS = 'show_projection_labels' +SHOW_PROJECTIONS_NOT_IN_COMPOSITION = 'show_projections_not_in_composition' ACTIVE_ITEMS = 'active_items' OUTPUT_FMT = 'output_fmt' @@ -353,6 +355,10 @@ class ShowGraph(): when **show_nested** is specified as False or a `Composition is nested ` below the level specified in a call to `show_graph `. + inactive_projection_color : keyword : default 'red' + specifies the color in which `Projections ` not active within the `Composition` are displayed, + when the `show_projections_not_in_composition ` option is True. + default_width : int : default 1 specifies the width to use for the outline of nodes and the body of Projection arrows. @@ -401,6 +407,7 @@ def __init__(self, controller_color='purple', learning_color='orange', composition_color='pink', + inactive_projection_color='red', # Lines: default_width = 1, active_thicker_by = 2, @@ -438,6 +445,7 @@ def __init__(self, self.controller_color =controller_color self.learning_color =learning_color self.composition_color =composition_color + self.inactive_projection_color =inactive_projection_color # Lines: self.default_projection_arrow = default_projection_arrow self.default_width = default_width @@ -463,24 +471,26 @@ def show_graph(self, show_types:bool=False, show_dimensions:bool=False, show_projection_labels:bool=False, + show_projections_not_in_composition=False, active_items=None, output_fmt:tc.optional(tc.enum('pdf','gv','jupyter','gif'))='pdf', context=None, **kwargs): """ - show_graph( \ - show_node_structure=False, \ - show_nested=NESTED, \ - show_nested_args=ALL, \ - show_cim=False, \ - show_controller=True, \ - show_learning=False, \ - show_headers=True, \ - show_types=False, \ - show_dimensions=False, \ - show_projection_labels=False, \ - active_items=None, \ - output_fmt='pdf', \ + show_graph( \ + show_node_structure=False, \ + show_nested=NESTED, \ + show_nested_args=ALL, \ + show_cim=False, \ + show_controller=True, \ + show_learning=False, \ + show_headers=True, \ + show_types=False, \ + show_dimensions=False, \ + show_projection_labels=False, \ + show_projections_not_in_composition=False \ + active_items=None, \ + output_fmt='pdf', \ context=None) Show graphical display of Components in a Composition's graph. @@ -563,6 +573,10 @@ def show_graph(self, show_projection_labels : bool : default False specifies whether or not to show names of projections. + show_projections_not_in_composition : bool : default False + specifies whether or not to show `Projections ` that are not active in the current + `Composition`; these will display in red. This option is for use in debugging. + show_headers : bool : default True specifies whether or not to show headers in the subfields of a Mechanism's node; only takes effect if **show_node_structure** is specified (see above). @@ -751,11 +765,9 @@ def show_graph(self, rcvrs = list(processing_graph.keys()) for rcvr in rcvrs: - # # MODIFIED 6/13/20 NEW: if any(n is rcvr for nested_comp in composition.nodes if isinstance(nested_comp, Composition) for n in nested_comp.nodes): continue - # # MODIFIED 6/13/20 END # If show_controller is true, objective mechanism will be # handled in _assign_controller_components @@ -780,6 +792,7 @@ def show_graph(self, show_types, show_dimensions, show_projection_labels, + show_projections_not_in_composition, nested_args) # Add cim Components to graph if show_cim @@ -793,6 +806,7 @@ def show_graph(self, show_node_structure, node_struct_args, show_projection_labels, + show_projections_not_in_composition, show_controller, comp_hierarchy) @@ -809,6 +823,7 @@ def show_graph(self, show_node_structure, node_struct_args, show_projection_labels, + show_projections_not_in_composition, comp_hierarchy, nesting_level) @@ -827,7 +842,8 @@ def show_graph(self, show_dimensions, show_node_structure, node_struct_args, - show_projection_labels) + show_projection_labels, + show_projections_not_in_composition) return self._generate_output(G, enclosing_comp, @@ -855,6 +871,7 @@ def _assign_processing_components(self, show_types, show_dimensions, show_projection_labels, + show_projections_not_in_composition, nested_args): """Assign nodes to graph""" @@ -976,7 +993,7 @@ def _assign_processing_components(self, rcvr_penwidth = str(self.bold_width) rcvr_rank = self.output_rank - # OUTPUT Node + # CONTROL Node elif isinstance(rcvr, ControlMechanism): if rcvr in active_items: if self.active_color == BOLD: @@ -990,7 +1007,7 @@ def _assign_processing_components(self, rcvr_penwidth = str(self.bold_width) rcvr_rank = self.output_rank - # Composition that is neither an INPUT Node nor an OUTPUT Node + # Composition that is neither INPUT, OUTPUT or CONTROL Node elif isinstance(rcvr, Composition) and show_nested is not NESTED: if rcvr in active_items: if self.active_color == BOLD: @@ -1053,6 +1070,7 @@ def _assign_processing_components(self, show_dimensions, show_node_structure, show_projection_labels, + show_projections_not_in_composition, enclosing_comp=enclosing_comp, comp_hierarchy=comp_hierarchy, nesting_level=nesting_level) @@ -1067,6 +1085,7 @@ def _assign_cim_components(self, show_node_structure, node_struct_args, show_projection_labels, + show_projections_not_in_composition, show_controller, comp_hierarchy): @@ -1116,6 +1135,8 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, # But if any Projection to it is from a controller, use controller_color for input_port in cim.input_ports: for proj in input_port.path_afferents: + if proj not in enclosing_comp.projections and not show_projections_not_in_composition: + continue if self._trace_senders_for_controller(proj, enclosing_comp): cim_type_color = self.controller_color elif cim is composition.output_CIM: @@ -1170,6 +1191,13 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, projs = input_port.path_afferents for proj in projs: + proj_color=self.default_node_color + if proj not in enclosing_comp.projections: + if not show_projections_not_in_composition: + continue + else: + proj_color=self.inactive_projection_color + # Get label for Node that sends the input (sndr_label) sndr_node_output_port = proj.sender # Skip if sender is a CIM (handled by enclosing Composition's call to this method) @@ -1204,13 +1232,21 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, sndr_output_node_proj_label = sndr_label # Render Projection - _render_projection(enclosing_g, proj, sndr_output_node_proj_label, rcvr_cim_proj_label) + _render_projection(enclosing_g, proj, sndr_output_node_proj_label, rcvr_cim_proj_label, + proj_color) # Projections from input_CIM to INPUT nodes for output_port in composition.input_CIM.output_ports: projs = output_port.efferents for proj in projs: + proj_color = self.default_node_color + if proj not in composition.projections: + if not show_projections_not_in_composition: + continue + else: + proj_color=self.inactive_projection_color + # Get label for Node that receives the input (rcvr_label) rcvr_input_node_proj = proj.receiver if (isinstance(rcvr_input_node_proj.owner, CompositionInterfaceMechanism) @@ -1256,7 +1292,7 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, rcvr_input_node_proj_label = rcvr_label # Render Projection - _render_projection(g, proj, sndr_input_cim_proj_label, rcvr_input_node_proj_label) + _render_projection(g, proj, sndr_input_cim_proj_label, rcvr_input_node_proj_label, proj_color) # PARAMETER_CIM ------------------------------------------------------------------------- @@ -1268,6 +1304,13 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, projs = input_port.path_afferents for proj in projs: + proj_color = self.control_color + if proj not in enclosing_comp.projections: + if not show_projections_not_in_composition: + continue + else: + proj_color=self.inactive_projection_color + # Get label for Node that sends the ControlProjection (sndr label) ctl_mech_output_port = proj.sender # Skip if sender is cim (handled by enclosing Composition's call to this method) @@ -1303,14 +1346,23 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, rcvr_param_cim_proj_label = cim_label # Render Projection - _render_projection(enclosing_g, proj, sndr_ctl_sig_proj_label, rcvr_param_cim_proj_label, - self.control_color) + _render_projection(enclosing_g, proj, + sndr_ctl_sig_proj_label, + rcvr_param_cim_proj_label, + proj_color) # Projections from parameter_CIM to Nodes that are being modulated for output_port in composition.parameter_CIM.output_ports: projs = output_port.efferents for proj in projs: + proj_color = None + if proj not in composition.projections: + if not show_projections_not_in_composition: + continue + else: + proj_color=self.inactive_projection_color + # Get label for Node that receives modulation (modulated_mech_label) rcvr_modulated_mech_proj = proj.receiver if (isinstance(rcvr_modulated_mech_proj.owner, CompositionInterfaceMechanism) @@ -1348,9 +1400,9 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, # Render Projection if self._trace_senders_for_controller(proj, enclosing_comp): - ctl_proj_color = self.controller_color + ctl_proj_color = proj_color or self.controller_color else: - ctl_proj_color = self.control_color + ctl_proj_color = proj_color or self.control_color arrowhead = self.default_projection_arrow if isinstance(proj, MappingProjection) else self.control_projection_arrow @@ -1367,6 +1419,13 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, projs = input_port.path_afferents for proj in projs: + proj_color = self.default_node_color + if proj not in composition.projections: + if not show_projections_not_in_composition: + continue + else: + proj_color=self.inactive_projection_color + sndr_output_node_proj = proj.sender if (isinstance(sndr_output_node_proj.owner, CompositionInterfaceMechanism) and show_nested is not NESTED): @@ -1406,27 +1465,45 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, # FIX 6/23/20 PROBLEM POINT: # Render Projection - _render_projection(g, proj, sndr_output_node_proj_label, rcvr_output_cim_proj_label) + _render_projection(g, + proj, + sndr_output_node_proj_label, + rcvr_output_cim_proj_label, + proj_color) # Projections from output_CIM to Node(s) in enclosing Composition for output_port in composition.output_CIM.output_ports: projs = output_port.efferents for proj in projs: + + proj_color = self.default_node_color + if proj not in enclosing_comp.projections: + if not show_projections_not_in_composition: + continue + else: + proj_color=self.inactive_projection_color + rcvr_node_input_port = proj.receiver + + # Skip if receiver is controller of enclosing_comp (handled by _assign_controller_components) + if rcvr_node_input_port.owner is enclosing_comp.controller: + continue + # Skip if receiver is cim (handled by enclosing Composition's call to this method) if isinstance(rcvr_node_input_port.owner, CompositionInterfaceMechanism): continue + # Skip if there is no inner Composition (show_nested!=NESTED) or # or Projections across nested Compositions are not being shown (show_nested=INSET) if not enclosing_g or show_nested is INSET: continue + # Skip if show_controller and the receiver is objective mechanism if show_controller and enclosing_comp.controller \ and getattr(enclosing_comp.controller, 'objective_mechanism', None) \ is rcvr_node_input_port.owner: continue - # Skip if show_controller and the receiver is objective mechanism rcvr_node_input_port_owner = rcvr_node_input_port.owner rcvr_label = self._get_graph_node_label(composition, @@ -1454,7 +1531,11 @@ def _render_projection(_g, proj, sndr_label, rcvr_label, sndr_output_cim_proj_label = cim_label # Render Projection - _render_projection(enclosing_g, proj, sndr_output_cim_proj_label, rcvr_input_node_proj_label) + _render_projection(enclosing_g, + proj, + sndr_output_cim_proj_label, + rcvr_input_node_proj_label, + proj_color) def _assign_controller_components(self, @@ -1469,6 +1550,7 @@ def _assign_controller_components(self, show_node_structure, node_struct_args, show_projection_labels, + show_projections_not_in_composition, comp_hierarchy, nesting_level): """Assign control nodes and edges to graph""" @@ -1736,11 +1818,11 @@ def find_rcvr_comp(r, c, l): g.edge(sndr_proj_label, objmech_proj_label, label=edge_label, color=proj_color, penwidth=proj_width) - # If controller has no objective_mechanism but does have outcome_input_ports, add Projetions from them + # If controller has no objective_mechanism but does have outcome_input_ports, add Projections from them elif controller.num_outcome_input_ports: # incoming edges (from monitored mechs directly to controller) - for input_port in controller.outcome_input_ports: - for projection in input_port.path_afferents: + for outcome_input_port in controller.outcome_input_ports: + for projection in outcome_input_port.path_afferents: if controller in active_items: if self.active_color == BOLD: proj_color = self.controller_color @@ -1756,7 +1838,8 @@ def find_rcvr_comp(r, c, l): projection.sender.owner, show_types, show_dimensions) - if projection.sender.owner not in composition.nodes: + if (projection.sender.owner not in composition.nodes + and not controller.allow_probes): num_nesting_levels = self.num_nesting_levels or 0 nested_comp = projection.sender.owner.composition try: @@ -1768,7 +1851,7 @@ def find_rcvr_comp(r, c, l): sender_visible = True if sender_visible: sndr_proj_label += ':' + controller._get_port_name(projection.sender) - ctlr_input_proj_label = ctlr_label + ':' + controller._get_port_name(input_port) + ctlr_input_proj_label = ctlr_label + ':' + controller._get_port_name(outcome_input_port) else: sndr_proj_label = self._get_graph_node_label(composition, projection.sender.owner, @@ -1813,7 +1896,8 @@ def find_rcvr_comp(r, c, l): # get any other incoming edges to controller (i.e., other than from ObjectiveMechanism) senders = set() - for i in controller.input_ports[1:]: + # FIX: 11/3/21 - NEED TO MODIFY ONCE OUTCOME InputPorts ARE MOVED + for i in controller.input_ports[controller.num_outcome_input_ports:]: for p in i.path_afferents: senders.add(p.sender.owner) self._assign_incoming_edges(g, @@ -1828,6 +1912,7 @@ def find_rcvr_comp(r, c, l): show_dimensions, show_node_structure, show_projection_labels, + show_projections_not_in_composition, proj_color=ctl_proj_color, comp_hierarchy=comp_hierarchy, nesting_level=nesting_level) @@ -1846,7 +1931,8 @@ def _assign_learning_components(self, show_dimensions, show_node_structure, node_struct_args, - show_projection_labels): + show_projection_labels, + show_projections_not_in_composition): """Assign learning nodes and edges to graph""" from psyneulink.core.compositions.composition import NodeRole @@ -1920,6 +2006,7 @@ def _assign_learning_components(self, show_dimensions, show_node_structure, show_projection_labels, + show_projections_not_in_composition, enclosing_comp=enclosing_comp, comp_hierarchy=comp_hierarchy, nesting_level=nesting_level) @@ -1931,6 +2018,7 @@ def _render_projection_as_node(self, show_types, show_dimensions, show_projection_labels, + show_projections_not_in_composition, proj, label, proj_color, @@ -2007,6 +2095,7 @@ def _assign_incoming_edges(self, show_dimensions, show_node_structure, show_projection_labels, + show_projections_not_in_composition, proj_color=None, proj_arrow=None, enclosing_comp=None, @@ -2029,14 +2118,16 @@ def _assign_incoming_edges(self, if show_nested is NESTED: # Add output_CIMs for nested Comps to find sender nodes cims = set([proj.sender.owner for proj in rcvr.afferents - if (isinstance(proj.sender.owner, CompositionInterfaceMechanism) + if (proj in composition.projections + and isinstance(proj.sender.owner, CompositionInterfaceMechanism) and (proj.sender.owner is proj.sender.owner.composition.output_CIM))]) senders.update(cims) # Get sender Node from outer Composition (enclosing_g) if enclosing_g and show_nested is not INSET: # Add input_CIM for current Composition to find senders from enclosing_g cims = set([proj.sender.owner for proj in rcvr.afferents - if (isinstance(proj.sender.owner, CompositionInterfaceMechanism) + if (proj in composition.projections + and isinstance(proj.sender.owner, CompositionInterfaceMechanism) and proj.sender.owner in {composition.input_CIM, composition.parameter_CIM})]) senders.update(cims) # HACK: FIX 6/13/20 - ADD USER-SPECIFIED TARGET NODE FOR INNER COMOSITION (NOT IN processing_graph) @@ -2142,6 +2233,7 @@ def assign_sender_edge(sndr:Union[Mechanism, Composition], show_types, show_dimensions, show_projection_labels, + show_projections_not_in_composition, proj, label=proc_mech_label, rcvr_label=proc_mech_rcvr_label, @@ -2185,10 +2277,11 @@ def assign_sender_edge(sndr:Union[Mechanism, Composition], proj_color = proj_color_default proj_arrowhead = proj_arrow_default - - # Skip Projections not in the Composition if proj not in composition.projections: - continue + if not show_projections_not_in_composition: + continue + else: + proj_color=self.inactive_projection_color assign_proj_to_enclosing_comp = False @@ -2207,29 +2300,6 @@ def assign_sender_edge(sndr:Union[Mechanism, Composition], # and therefore is not passing an afferent Projection from that Composition if not sender.afferents and rcvr is not composition.controller: continue - # # MODIFIED 4/5/21 OLD: - # # Get node(s) from enclosing Comopsition that is/are source(s) of sender(s) - # sndr_spec = self._trace_senders_for_original_sender_mechanism(proj, nesting_level) - # if not sndr_spec: - # continue - # sndr, sndr_port, sndr_nesting_level = sndr_spec - # # if original sender is more than one level above receiver, replace enclosing_g with - # # the g of the original sender composition - # enclosing_comp = comp_hierarchy[sndr_nesting_level] - # enclosing_g = enclosing_comp._show_graph.G - # # Skip: - # # - cims as sources (handled in _assign_cim_componoents) - # # - controller (handled in _assign_controller_components) - # if (isinstance(sndr, CompositionInterfaceMechanism) and - # rcvr is not enclosing_comp.controller - # and rcvr is not composition.controller - # or self._is_composition_controller(sndr, enclosing_comp)): - # continue - # if sender is composition.parameter_CIM: - # proj_color = self.control_color - # proj_arrowhead = self.control_projection_arrow - # assign_proj_to_enclosing_comp = True - # MODIFIED 4/5/21 NEW: # FIX: LOOP HERE OVER sndr_spec IF THERE ARE SEVERAL # Get node(s) from enclosing Comopsition that is/are source(s) of sender(s) sndrs_specs = self._trace_senders_for_original_sender_mechanism(proj, nesting_level) @@ -2269,7 +2339,7 @@ def assign_sender_edge(sndr:Union[Mechanism, Composition], # Get Node from nested Composition that projects to rcvr sndr = [k.owner for k,v in sender.port_map.items() if v[1] is proj.sender][0] # Skip: - # - cims as sources (handled in _assign_cim_compmoents) + # - cims as sources (handled in _assign_cim_components) # - controller (handled in _assign_controller_components) # NOTE 7/20/20: if receiver is a controller, then we need to skip this block or shadow inputs # will not be rendered -DS diff --git a/psyneulink/core/globals/keywords.py b/psyneulink/core/globals/keywords.py index c79f2582541..e3452201995 100644 --- a/psyneulink/core/globals/keywords.py +++ b/psyneulink/core/globals/keywords.py @@ -28,20 +28,21 @@ 'ADAPTIVE', 'ADAPTIVE_INTEGRATOR_FUNCTION', 'ADAPTIVE_MECHANISM', 'ADD_INPUT_PORT', 'ADD_OUTPUT_PORT', 'ADDITIVE', 'ADDITIVE_PARAM', 'AFTER', 'ALL', 'ALLOCATION_SAMPLES', 'ANGLE', 'ANGLE_FUNCTION', 'ANY', 'ARGUMENT_THERAPY_FUNCTION', 'ARRANGEMENT', 'ASSERT', 'ASSIGN', 'ASSIGN_VALUE', 'AUTO','AUTO_ASSIGN_MATRIX', - 'AUTO_ASSOCIATIVE_PROJECTION', 'HAS_INITIALIZERS', 'AUTOASSOCIATIVE_LEARNING_MECHANISM', 'LEARNING_MECHANISMS', + 'AUTO_ASSOCIATIVE_PROJECTION', 'HAS_INITIALIZERS', 'AUTOASSOCIATIVE_LEARNING_MECHANISM', 'AUTODIFF_COMPOSITION', 'BACKPROPAGATION_FUNCTION', 'BEFORE', 'BETA', 'BIAS', 'BOLD', 'BOTH', 'BOUNDS', 'BUFFER_FUNCTION', 'CHANGED', 'CLAMP_INPUT', 'COMBINATION_FUNCTION_TYPE', 'COMBINE', 'COMBINE_MEANS_FUNCTION', 'COMBINE_OUTCOME_AND_COST_FUNCTION', 'COMMAND_LINE', 'comparison_operators', 'COMPARATOR_MECHANISM', 'COMPONENT', - 'COMPONENT_INIT', 'COMPONENT_PREFERENCE_SET', 'COMPOSITION', 'COMPOSITION_INTERFACE_MECHANISM', 'CONCATENATE', - 'CONCATENATE_FUNCTION', 'CONDITION', 'CONDITIONS', 'CONSTANT', 'ContentAddressableMemory_FUNCTION', - 'CONTEXT', 'CONTROL', 'CONTROL_MECHANISM', 'CONTROL_PATHWAY', 'CONTROL_PROJECTION', 'CONTROL_PROJECTION_PARAMS', + 'COMPONENT_INIT', 'COMPONENT_PREFERENCE_SET', 'COMPOSITION', 'COMPOSITION_FUNCTION_APPROXIMATOR', + 'COMPOSITION_INTERFACE_MECHANISM', 'CONCATENATE', 'CONCATENATE_FUNCTION', 'CONDITION', 'CONDITIONS', 'CONSTANT', + 'ContentAddressableMemory_FUNCTION', 'CONTEXT', + 'CONTROL', 'CONTROL_MECHANISM', 'CONTROL_PATHWAY', 'CONTROL_PROJECTION', 'CONTROL_PROJECTION_PARAMS', 'CONTROL_PROJECTIONS', 'CONTROL_SIGNAL', 'CONTROL_SIGNAL_SPECS', 'CONTROL_SIGNALS', 'CONTROLLED_PARAMS', 'CONTROLLER', 'CONTROLLER_OBJECTIVE', 'CORRELATION', 'COSINE', 'COST_FUNCTION', 'COUNT', 'CROSS_ENTROPY', 'CURRENT_EXECUTION_TIME', 'CUSTOM_FUNCTION', 'CYCLE', 'DDM_MECHANISM', 'DECAY', 'DEFAULT', 'DEFAULT_CONTROL_MECHANISM', 'DEFAULT_MATRIX', 'DEFAULT_PREFERENCE_SET_OWNER', 'DEFAULT_PROCESSING_MECHANISM', 'DEFAULT_VARIABLE', 'DEFERRED_ASSIGNMENT', 'DEFERRED_DEFAULT_NAME', 'DEFERRED_INITIALIZATION', 'DictionaryMemory_FUNCTION', - 'DIFFERENCE', 'DIFFERENCE', 'DIFFUSION', 'DISABLE', 'DISABLE_PARAM', 'DIST_FUNCTION_TYPE', 'DIST_MEAN', + 'DIFFERENCE', 'DIFFERENCE', 'DIFFUSION', 'DIRECT', 'DISABLE', 'DISABLE_PARAM', 'DIST_FUNCTION_TYPE', 'DIST_MEAN', 'DIST_SHAPE', 'DISTANCE_FUNCTION', 'DISTANCE_METRICS', 'DISTRIBUTION_FUNCTION_TYPE', 'DIVISION', 'DRIFT_DIFFUSION_INTEGRATOR_FUNCTION', 'DRIFT_ON_A_SPHERE_INTEGRATOR_FUNCTION', 'DUAL_ADAPTIVE_INTEGRATOR_FUNCTION', 'EID_SIMULATION', 'EID_FROZEN', 'EITHER', 'ENABLE_CONTROLLER', 'ENABLED', 'ENERGY', 'ENTROPY', @@ -63,10 +64,10 @@ 'INTEGRATOR_FUNCTION','INTEGRATOR_FUNCTION', 'INTEGRATOR_FUNCTION_TYPE', 'INTEGRATOR_MECHANISM', 'LAST_INTEGRATED_VALUE', 'INTERCEPT', 'INTERNAL', 'INTERNAL_ONLY', 'K_VALUE', 'KOHONEN_FUNCTION', 'KOHONEN_MECHANISM', 'KOHONEN_LEARNING_MECHANISM', 'KWTA_MECHANISM', - 'LABELS', 'LCA_MECHANISM', 'LEAKY_COMPETING_INTEGRATOR_FUNCTION', 'LEAK', 'LEARNED_PARAM', 'LEARNED_PROJECTIONS', - 'LEARNING', 'LEARNING_FUNCTION', 'LEARNING_FUNCTION_TYPE', 'LEARNING_OBJECTIVE', 'LEARNING_MECHANISM', - 'LEARNING_PATHWAY', 'LEARNING_PROJECTION', 'LEARNING_PROJECTION_PARAMS', 'LEARNING_RATE', 'LEARNING_SIGNAL', - 'LEARNING_SIGNAL_SPECS', 'LEARNING_SIGNALS', + 'LABELS', 'LCA_MECHANISM', 'LEAKY_COMPETING_INTEGRATOR_FUNCTION', 'LEAK', + 'LEARNED_PARAM', 'LEARNED_PROJECTIONS', 'LEARNING', 'LEARNING_FUNCTION', 'LEARNING_FUNCTION_TYPE', + 'LEARNING_OBJECTIVE', 'LEARNING_MECHANISM', 'LEARNING_MECHANISMS', 'LEARNING_PATHWAY', 'LEARNING_PROJECTION', + 'LEARNING_PROJECTION_PARAMS', 'LEARNING_RATE', 'LEARNING_SIGNAL', 'LEARNING_SIGNAL_SPECS', 'LEARNING_SIGNALS', 'LESS_THAN', 'LESS_THAN_OR_EQUAL', 'LINEAR', 'LINEAR_COMBINATION_FUNCTION', 'LINEAR_FUNCTION', 'LINEAR_MATRIX_FUNCTION', 'LOG_ENTRIES', 'LOGISTIC_FUNCTION', 'LOW', 'LVOC_CONTROL_MECHANISM', 'L0', 'L1', 'MAPPING_PROJECTION', 'MAPPING_PROJECTION_PARAMS', 'MASKED_MAPPING_PROJECTION', @@ -75,9 +76,9 @@ 'MAX_EXECUTIONS_BEFORE_FINISHED', 'MAX_INDICATOR', 'MAX_VAL', 'MAYBE', 'MEAN', 'MECHANISM', 'MECHANISM_COMPONENT_CATEGORY', 'MECHANISM_DEFAULT', 'MECHANISM_DEFAULTInputValue', 'MECHANISM_DEFAULTParams', 'MECHANISM_EXECUTED_LOG_ENTRY', 'MECHANISM_NAME', 'MECHANISM_PARAM_VALUE', - 'MECHANISM_TYPE', 'MECHANISM_VALUE', 'MEDIAN', 'METRIC', 'MIN_VAL', 'MIN_ABS_VAL', 'MIN_ABS_INDICATOR', 'MODE', - 'MODULATES','MODULATION', 'MODULATORY_PROJECTION', 'MODULATORY_SIGNAL', 'MODULATORY_SIGNALS', - 'MONITOR', 'MONITOR_FOR_CONTROL', 'MONITOR_FOR_LEARNING', 'MONITOR_FOR_MODULATION', + 'MECHANISM_TYPE', 'MECHANISM_VALUE', 'MEDIAN', 'METRIC', 'MIN_VAL', 'MIN_ABS_VAL', 'MIN_ABS_INDICATOR', + 'MODE', 'MODULATES','MODULATION', 'MODULATORY_PROJECTION', 'MODULATORY_SIGNAL', 'MODULATORY_SIGNALS', + 'MONITOR', 'MONITOR_FOR_CONTROL', 'MONITOR_FOR_LEARNING', 'MONITOR_FOR_MODULATION', 'MODEL_FREE', 'MODEL_BASED', 'MODEL_SPEC_ID_GENERIC', 'MODEL_SPEC_ID_INPUT_PORTS', 'MODEL_SPEC_ID_OUTPUT_PORTS', 'MODEL_SPEC_ID_PSYNEULINK', 'MODEL_SPEC_ID_SENDER_MECH', 'MODEL_SPEC_ID_SENDER_PORT', 'MODEL_SPEC_ID_RECEIVER_MECH', 'MODEL_SPEC_ID_RECEIVER_PORT', @@ -335,9 +336,9 @@ def _is_metric(metric): AFTER = 'after' OLDEST = 'oldest' NEWEST = 'newest' - FULL = 'full' TERSE = 'terse' +DIRECT = 'direct' LESS_THAN = '<' LESS_THAN_OR_EQUAL = '<=' @@ -389,7 +390,12 @@ def _is_metric(metric): #region ---------------------------------------------- COMPOSITION ------------------------------------------------- +# 11/15/21: FIX - CHANGE TO LOWER CASE FOR USE WITH componentCategory (OR CHANGE THAT?); MAY NEED TO CHANGE TESTS +# Composition Categories COMPOSITION = 'COMPOSITION' +AUTODIFF_COMPOSITION = 'AutodiffComposition' +COMPOSITION_FUNCTION_APPROXIMATOR = 'CompositionFunctionApproximator' + INPUT_CIM_NAME = 'INPUT_CIM' OUTPUT_CIM_NAME = 'OUTPUT_CIM' PARAMETER_CIM_NAME = 'PARAMETER_CIM' @@ -770,7 +776,8 @@ def _is_metric(metric): SAVE_ALL_VALUES_AND_POLICIES = 'save_all_values_and_policies' EVC_SIMULATION = 'CONTROL SIMULATION' ALLOCATION_SAMPLES = "allocation_samples" - +MODEL_FREE = 'model_free' +MODEL_BASED = 'model_based' # GatingMechanism GATING_SIGNALS = 'gating_signals' diff --git a/psyneulink/core/llvm/builder_context.py b/psyneulink/core/llvm/builder_context.py index 6e397eaada0..42a95aa9fc1 100644 --- a/psyneulink/core/llvm/builder_context.py +++ b/psyneulink/core/llvm/builder_context.py @@ -353,9 +353,10 @@ def _param_struct(p): return ir.LiteralStructType(self.get_param_struct_type(x) for x in val) elif p.name == 'matrix': # Flatten matrix val = np.asfarray(val).flatten() - # FIX: NEED TO ADD num_trials_per_estimate HERE elif p.name == 'num_estimates': # Should always be int val = np.int32(0) if val is None else np.int32(val) + elif p.name == 'num_trials_per_estimate': # Should always be int + val = np.int32(0) if val is None else np.int32(val) elif np.ndim(val) == 0 and component._is_param_modulated(p): val = [val] # modulation adds array wrap return self.convert_python_struct_to_llvm_ir(val) diff --git a/psyneulink/library/compositions/autodiffcomposition.py b/psyneulink/library/compositions/autodiffcomposition.py index 8fe17d232f8..81142b6f4f2 100644 --- a/psyneulink/library/compositions/autodiffcomposition.py +++ b/psyneulink/library/compositions/autodiffcomposition.py @@ -148,7 +148,7 @@ import ReportOutput, ReportParams, ReportProgress, ReportSimulations, ReportDevices, \ LEARN_REPORT, EXECUTE_REPORT, PROGRESS_REPORT from psyneulink.core.globals.context import Context, ContextFlags, handle_external_context -from psyneulink.core.globals.keywords import SOFT_CLAMP +from psyneulink.core.globals.keywords import AUTODIFF_COMPOSITION, SOFT_CLAMP from psyneulink.core.scheduling.scheduler import Scheduler from psyneulink.core.globals.parameters import Parameter from psyneulink.core.scheduling.time import TimeScale @@ -210,6 +210,7 @@ class AutodiffComposition(Composition): """ + componentCategory = AUTODIFF_COMPOSITION class Parameters(Composition.Parameters): """""" optimizer = None diff --git a/psyneulink/library/compositions/gymforagercfa.py b/psyneulink/library/compositions/gymforagercfa.py index 186cc54df1e..64250e035f6 100644 --- a/psyneulink/library/compositions/gymforagercfa.py +++ b/psyneulink/library/compositions/gymforagercfa.py @@ -36,11 +36,11 @@ Parameterizes weights of a `update_weights ` used by its `evaluate ` method to predict the `net_outcome ` - for a `Composition` (or part of one) controlled by an `OptimiziationControlMechanism`, from a set of `state_feature_values + for a `Composition` (or part of one) controlled by an `OptimizationControlMechanism`, from a set of `state_feature_values ` and a `control_allocation ` - provided by the OptimiziationControlMechanism. + provided by the OptimizationControlMechanism. - The `state_feature_values ` and `control_allocation + The `state_feature_values ` and `control_allocation ` passed to the RegressorCFA's `adapt ` method, and provided as the input to its `update_weights `, are represented in the `vector ` attribute of a `PredictionVector` assigned to the RegressorCFA`s @@ -172,7 +172,7 @@ def evaluate(self, feature_values, control_allocation, num_estimates, num_trials Uses the current values of `regression_weights ` together with values of **control_allocation** and **state_feature_values** arguments to generate predicted `net_outcome - `. + `. .. note:: If this method is assigned as the `objective_funtion of a `GradientOptimization` `Function`, diff --git a/psyneulink/library/compositions/regressioncfa.py b/psyneulink/library/compositions/regressioncfa.py index 2432f9b7778..c1430adb009 100644 --- a/psyneulink/library/compositions/regressioncfa.py +++ b/psyneulink/library/compositions/regressioncfa.py @@ -25,34 +25,37 @@ A `RegressionCFA` is a subclass of `CompositionFunctionApproximator` that parameterizes a set of `regression_weights ` over trials to predict the `net_outcome ` for a `Composition` (or part of one) controlled by an `OptimizationControlMechanism`. The `regression_weights -` are updated by its `update_weights ` `LearningFunction` -assigned as its `adapt ` method, which is called by the `evaluate -` method to predict the `net_outcome ` for a -`Composition` (or part of one) controlled by an `OptimiziationControlMechanism`, based on a set of `state_feature_values -`, a `control_allocation `, -and the `net_outcome ` they produced, passed to it from an `OptimizationControlMechanism`. +` are updated by its `update_weights ` +`LearningFunction` assigned as its `adapt ` method, which is called by the +`evaluate ` method to predict the `net_outcome ` +for a `Composition` (or part of one) controlled by an `OptimizationControlMechanism`, based on a set of +`state_feature_values `, a `control_allocation +`, and the `net_outcome ` they produced, +passed to it from an `OptimizationControlMechanism`. COMMENT: Its `evaluate ` method calls its `update_weights ` to generate and return a predicted `net_outcome -` for a given set of `state_feature_values ` -and a `control_allocation ` provided by an `OptimizationControlMechanism`. +` for a given set of `state_feature_values +` and a `control_allocation ` +provided by an `OptimizationControlMechanism`. COMMENT -The `state_feature_values ` and `control_allocation -` passed to the RegressorCFA's `adapt ` method, and provided -as the input to its `update_weights `, are represented in the `vector -` attribute of a `PredictionVector` assigned to the RegressorCFA`s `prediction_vector -` attribute. The `state_feature_values ` are -assigned to the state_features field of the `prediction_vector `, and the `control_allocation +The `state_feature_values ` and `control_allocation +` passed to the RegressionCFA's `adapt ` method, and provided +as the input to its `update_weights `, are represented in the `vector +` attribute of a `PredictionVector` assigned to the RegressionCFA`s `prediction_vector +` attribute. The `state_feature_values +` are assigned to the state_features field of the +`prediction_vector `, and the `control_allocation ` is assigned to the control_allocation field of the `prediction_vector -`. The `prediction_vector ` may also contain fields +`. The `prediction_vector ` may also contain fields for the `costs ControlMechanism.costs` associated with the `control_allocation ` and for interactions among those terms. -The `regression_weights ` returned by the `update_weights -` are used by the RegressorCFA's `evaluate ` method to predict -the `net_outcome ` from the `prediction_vector `. +The `regression_weights ` returned by the `update_weights +` are used by the RegressionCFA's `evaluate ` method to predict +the `net_outcome ` from the `prediction_vector `. COMMENT: @@ -168,16 +171,16 @@ class RegressionCFA(CompositionFunctionApproximator): update_weights : LearningFunction, function or method : default BayesGLM parameterizes the `regression_weights ` used by the `evaluate ` method to improve its prediction of `net_outcome ` - from a given set of `state_feature_values ` and a - `control_allocation ` provided by an `OptimiziationControlMechanism`. + from a given set of `state_feature_values ` and a + `control_allocation ` provided by an `OptimizationControlMechanism`. It must take a 2d array as its first argument, the first item of which is an array the same length of the `vector ` attribute of its `prediction_vector - `, and the second item a 1d array containing a scalar + `, and the second item a 1d array containing a scalar value that it tries predict. prediction_terms : List[PV] : default [PV.F, PV.C, PV.COST] terms to be included in (and thereby determines the length of) the `vector - ` attribute of the `prediction_vector `; + ` attribute of the `prediction_vector `; items are members of the `PV` enum; the default is [`F `, `C ` `FC `, `COST `]. If `None` is specified, the default values will automatically be assigned. @@ -187,25 +190,25 @@ class RegressionCFA(CompositionFunctionApproximator): update_weights : LearningFunction, function or method parameterizes the `regression_weights ` used by the `evaluate ` method to improve prediction of `net_outcome ` - from a given set of `state_feature_values ` and a - `control_allocation ` provided by an `OptimiziationControlMechanism`; - its result is assigned as the value of the `regression_weights ` attribute. + from a given set of `state_feature_values ` and a + `control_allocation ` provided by an `OptimizationControlMechanism`; + its result is assigned as the value of the `regression_weights ` attribute. prediction_terms : List[PV] terms included in `vector ` attribute of the - `prediction_vector `; items are members of the `PV` enum; the + `prediction_vector `; items are members of the `PV` enum; the default is [`F `, `C ` `FC `, `COST `]. prediction_vector : PredictionVector represents and manages values in its `vector ` attribute that are used by - `evaluate `, along with `regression_weights ` to + `evaluate `, along with `regression_weights ` to make its prediction. The values contained in the `vector ` attribute are - determined by `prediction_terms `. + determined by `prediction_terms `. regression_weights : 1d array - result returned by `update_weights , and used by - `evaluate ` method together with `prediction_vector ` - to generate predicted `net_outcome `. + result returned by `update_weights , and used by + `evaluate ` method together with `prediction_vector ` + to generate predicted `net_outcome `. """ @@ -282,9 +285,9 @@ def _instantiate_prediction_terms(self, prediction_terms): # def initialize(self, owner): def initialize(self, features_array, control_signals, context): - """Assign owner and instantiate `prediction_vector ` + """Assign owner and instantiate `prediction_vector ` - Must be called before RegressorCFA's methods can be used. + Must be called before RegressionCFA's methods can be used. """ prediction_terms = self.prediction_terms @@ -300,7 +303,7 @@ def initialize(self, features_array, control_signals, context): self.update_weights.reset({DEFAULT_VARIABLE: update_weights_default_variable}) def adapt(self, feature_values, control_allocation, net_outcome, context=None): - """Update `regression_weights ` so as to improve prediction of + """Update `regression_weights ` so as to improve prediction of **net_outcome** from **state_feature_values** and **control_allocation**. """ prediction_vector = self.parameters.prediction_vector._get(context) @@ -328,15 +331,15 @@ def adapt(self, feature_values, control_allocation, net_outcome, context=None): ) # FIX: RENAME AS _EXECUTE_AS_REP ONCE SAME IS DONE FOR COMPOSITION - # FIX: IMPLEMENT USE OF num_trials_per_estimate? + # FIX: 11/3/21 - IMPLEMENT USE OF num_trials_per_estimate? # def evaluate(self, control_allocation, num_samples, reset_stateful_functions_to, state_feature_values, context): def evaluate(self, feature_values, control_allocation, num_estimates, num_trials_per_estimate, context): - """Update prediction_vector `, + """Update prediction_vector `, then multiply by regression_weights. - Uses the current values of `regression_weights ` together with - values of **control_allocation** and **state_feature_values** arguments to generate predicted `net_outcome - `. + Uses the current values of `regression_weights ` together with + values of **state_feature_values** and **control_allocation** arguments to generate predicted `net_outcome + `. .. note:: If this method is assigned as the `objective_funtion of a `GradientOptimization` `Function`, @@ -388,7 +391,7 @@ class PredictionVector(): Arguments --------- - feature_values : 2d nparray + feature_values : 2d array arrays of state_features to assign as the `PV.F` term of `terms `. control_signals : List[ControlSignal] @@ -587,7 +590,7 @@ def __call__(self, terms:tc.any(PV, list))->tc.any(PV, tuple): def update_vector(self, variable, feature_values=None, context=None): """Update vector with flattened versions of values returned from the `compute_terms ` method of the `prediction_vector - `. + `. Updates `vector ` with current values of variable and, optionally, and state_feature_values. diff --git a/tests/composition/test_composition.py b/tests/composition/test_composition.py index 8f8b51f3027..80d476e1d06 100644 --- a/tests/composition/test_composition.py +++ b/tests/composition/test_composition.py @@ -9,10 +9,10 @@ from psyneulink.core.components.functions.nonstateful.combinationfunctions import LinearCombination from psyneulink.core.components.functions.nonstateful.learningfunctions import Reinforcement, BackPropagation from psyneulink.core.components.functions.nonstateful.optimizationfunctions import GridSearch -from psyneulink.core.components.functions.stateful.integratorfunctions import \ - AdaptiveIntegrator, DriftDiffusionIntegrator, IntegratorFunction, SimpleIntegrator from psyneulink.core.components.functions.nonstateful.transferfunctions import \ Linear, Logistic, INTENSITY_COST_FCT_MULTIPLICATIVE_PARAM +from psyneulink.core.components.functions.stateful.integratorfunctions import \ + AdaptiveIntegrator, DriftDiffusionIntegrator, IntegratorFunction, SimpleIntegrator from psyneulink.core.components.functions.userdefinedfunction import UserDefinedFunction from psyneulink.core.components.mechanisms.modulatory.control.controlmechanism import ControlMechanism from psyneulink.core.components.mechanisms.modulatory.control.optimizationcontrolmechanism import \ @@ -4131,7 +4131,7 @@ def test_invalid_projection_deletion_when_nesting_comps(self): pnl.OptimizationControlMechanism( agent_rep=ocomp, state_features=[oa.input_port], - # state_feature_function=pnl.Buffer(history=2), + # state_feature_functions=pnl.Buffer(history=2), name="Controller", objective_mechanism=ocomp_objective_mechanism, function=pnl.GridSearch(direction=pnl.MINIMIZE), @@ -4151,7 +4151,7 @@ def test_invalid_projection_deletion_when_nesting_comps(self): pnl.OptimizationControlMechanism( agent_rep=icomp, state_features=[ia.input_port], - # state_feature_function=pnl.Buffer(history=2), + # state_feature_functions=pnl.Buffer(history=2), name="Controller", objective_mechanism=icomp_objective_mechanism, function=pnl.GridSearch(direction=pnl.MAXIMIZE), @@ -4653,6 +4653,82 @@ def test_four_level_nested_dual_OCM_control(self): result = c_lvl0.run([5]) assert result == [4500] + @pytest.mark.parametrize('nesting', ("unnested", "nested")) + def test_partially_overlapping_local_and_control_mech_control_specs_in_unnested_and_nested_comp(self, nesting): + pnl.clear_registry() + samples = np.arange(0.1, 1.01, 0.3) + Input = pnl.TransferMechanism(name='Input') + reward = pnl.TransferMechanism(output_ports=[pnl.RESULT, pnl.MEAN, pnl.VARIANCE], + name='reward', + ) + Decision = pnl.DDM(function=pnl.DriftDiffusionAnalytical(drift_rate=(1.0, + pnl.ControlProjection(function=pnl.Linear, + control_signal_params={ + pnl.ALLOCATION_SAMPLES: samples, + })), + threshold=(1.0, + pnl.ControlProjection(function=pnl.Linear, + control_signal_params={ + pnl.ALLOCATION_SAMPLES: samples, + })), + noise=0.5, + starting_point=0, + t0=0.45), + output_ports=[pnl.DECISION_VARIABLE, + pnl.RESPONSE_TIME, + pnl.PROBABILITY_UPPER_THRESHOLD], + name='Decision') + Response = pnl.DDM(function=pnl.DriftDiffusionAnalytical(drift_rate=1.0, + threshold=1.0, + noise=0.5, + starting_point=0, + t0=0.45), + output_ports=[pnl.DECISION_VARIABLE, + pnl.RESPONSE_TIME, + pnl.PROBABILITY_UPPER_THRESHOLD], + name='Response') + + icomp = pnl.Composition(name="EVC (inner comp)", retain_old_simulation_data=True) + icomp.add_node(reward, required_roles=[pnl.NodeRole.OUTPUT]) + icomp.add_node(Decision, required_roles=[pnl.NodeRole.OUTPUT]) + icomp.add_node(Response, required_roles=[pnl.NodeRole.OUTPUT]) + icomp.add_linear_processing_pathway([Input, pnl.IDENTITY_MATRIX, Decision, Response]) + if nesting == 'nested': + comp = Composition(nodes=icomp, name="Outer Composition") + else: + comp = icomp + ocm=OptimizationControlMechanism( + agent_rep=comp, + monitor_for_control=[Decision.output_ports[pnl.DECISION_VARIABLE], + Decision.output_ports[pnl.RESPONSE_TIME]], + num_estimates=1, + function=GridSearch, + control_signals=[ + ControlSignal(modulates=('drift_rate',Decision), # OVERLAPS WITH CONTROL SPEC ON Decision + allocation_samples=[1,2]), + ControlSignal(modulates=('threshold',Response), # ADDS CONTROL SPEC FOR Response + allocation_samples=[1,2]), + ] + ) + comp.add_controller(ocm) + + assert len(comp.controller.input_ports[pnl.OUTCOME].path_afferents) == 2 + if nesting == 'nested': + # All Projections to controller's OUTCOME InputPort should be from input_CIM + assert all(isinstance(comp.controller.input_ports[pnl.OUTCOME].path_afferents[i].sender.owner, + pnl.CompositionInterfaceMechanism) for i in range(2)) + + assert len(comp.controller.control_signals) == 4 # Should be 4: Decision threshold (spec'd locally on mech) + # Decision drift_rate (spec'd on mech and OCM) + # Response threshold (spec'd on OCM) + # RANDOMIZATION + ctl_sig_names = ['Decision[drift_rate] ControlSignal', 'Decision[threshold] ControlSignal', + 'Response[threshold] ControlSignal', 'RANDOMIZATION_CONTROL_SIGNAL'] + assert all([name in ctl_sig_names for name in comp.controller.control_signals.names]) + if nesting == 'nested': + # All of the controller's ControlSignals should project to the ParameterCIM for the nested comp + assert all(isinstance(comp.controller.control_signals[i].efferents[0].receiver.owner, + pnl.CompositionInterfaceMechanism) for i in range(4)) class TestOverloadedCompositions: def test_mechanism_different_inputs(self): @@ -5705,7 +5781,11 @@ def test_two_origins(self): assert A.value == [[1.0]] assert B.value == [[1.0]] - assert comp.shadows[A] == [B] + + # Since B is both an INPUT Node and also shadows A, it should have two afferent Projections, + # one from it own OutputPort of the Composition's input_CIM, and another from the one for A + # assert len(B.path_afferents)==2 + # assert B.input_port.path_afferents[1].sender is A.input_port.path_afferents[0].sender C = ProcessingMechanism(name='C') comp.add_linear_processing_pathway([C, A]) @@ -5720,7 +5800,7 @@ def test_two_origins(self): assert len(B.path_afferents) == 1 assert B.path_afferents[0].sender.owner == C - def test_two_origins_two_input_ports(self): + def test_shadow_internal_projectionstest_two_origins_two_input_ports(self): comp = Composition(name='comp') A = ProcessingMechanism(name='A', function=Linear(slope=2.0)) @@ -5732,15 +5812,20 @@ def test_two_origins_two_input_ports(self): assert A.value == [[2.0]] assert np.allclose(B.value, [[1.0], [2.0]]) - assert comp.shadows[A] == [B] + + assert len(B.input_ports)==2 + assert len(B.input_ports[0].path_afferents)==1 + assert len(B.input_ports[1].path_afferents)==1 + assert B.input_ports[0].path_afferents[0].sender is A.input_ports[0].path_afferents[0].sender + assert B.input_ports[1].path_afferents[0].sender is A.output_ports[0] C = ProcessingMechanism(name='C') comp.add_linear_processing_pathway([C, A]) comp.run(inputs={C: 1.5}) assert A.value == [[3.0]] - assert np.allclose(B.value, [[1.5], [3.0]]) assert C.value == [[1.5]] + assert np.allclose(B.value, [[1.5], [3.0]]) # Since B is shadowing A, its old projection from the CIM should be deleted, # and a new projection from C should be added @@ -5773,12 +5858,58 @@ def test_shadow_internal_projections(self): comp.add_linear_processing_pathway([A2, B]) comp.run(inputs={A: [[1.0]], A2: [[1.0]]}) - assert A.value == [[1.0]] assert A2.value == [[1.0]] assert B.value == [[2.0]] assert C.value == [[2.0]] + + _test_shadow_nested_nodes_arg =\ + [ + ('shadow_nodes_one_and_two_levels_deep', 0), + ('shadow_nested_internal_node', 1), + ], + + @pytest.mark.parametrize( + 'condition', + ['shadow_nodes_one_and_two_levels_deep', + 'shadow_nested_internal_node'], + ) + def test_shadow_nested_nodes(self, condition): + + I = ProcessingMechanism(name='I') + icomp = Composition(nodes=I, name='INNER COMP') + + A = ProcessingMechanism(name='A') + B = ProcessingMechanism(name='B') + C = ProcessingMechanism(name='C') + mcomp = Composition(pathways=[[A,B,C],icomp], name='MIDDLE COMP') + + if condition == 'shadow_nodes_one_and_two_levels_deep': + + # Confirm that B's shadow of I comes from the same ocomp_input_CIM that serves I + O = ProcessingMechanism(name='O',input_ports=[I.input_port, A.input_port]) + ocomp = Composition(nodes=[mcomp,O], name='OUTER COMP') + ocomp._analyze_graph() + assert len(O.afferents)==2 + assert O.input_ports[0].shadow_inputs.owner is I + receiver = icomp.input_CIM.port_map[I.input_port][0] + receiver = receiver.path_afferents[0].sender.owner.port_map[receiver][0] + assert O.input_ports[0].path_afferents[0].sender is \ + ocomp.input_CIM.port_map[receiver][1] + + # Confirm that B's shadow of A comes from the same ocomp_input_CIM that serves A + assert O.input_ports[1].shadow_inputs.owner is A + assert O.input_ports[1].path_afferents[0].sender is \ + mcomp.input_CIM.port_map[A.input_port][0].path_afferents[0].sender + + elif condition == 'shadow_nested_internal_node': + with pytest.raises(CompositionError) as err: + O = ProcessingMechanism(name='O',input_ports=[B.input_port]) + ocomp = Composition(nodes=[mcomp,O], name='OUTER COMP') + assert 'Attempt to shadow the input(s) to a node (B) in a nested Composition ' \ + '(of OUTER COMP) is not currently supported.' in err.value.error_value + def test_monitor_input_ports(self): comp = Composition(name='comp') diff --git a/tests/composition/test_control.py b/tests/composition/test_control.py index 9e42674d202..2a38ef57f79 100644 --- a/tests/composition/test_control.py +++ b/tests/composition/test_control.py @@ -58,6 +58,7 @@ def test_add_controller_in_comp_constructor_then_add_node_with_control_specified ctl_mech = pnl.ControlMechanism() comp = pnl.Composition(controller=ctl_mech) comp.add_node(ddm) + comp._analyze_graph() assert comp.controller.control[0].efferents[0].receiver == ddm.parameter_ports['drift_rate'] assert ddm.parameter_ports['drift_rate'].mod_afferents[0].sender.owner == comp.controller assert np.allclose(comp.controller.control[0].allocation_samples.base(), @@ -147,7 +148,7 @@ def test_deferred_init(self): comp.add_controller(controller=pnl.OptimizationControlMechanism( agent_rep=comp, state_features=[Input.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.5), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.5), objective_mechanism=pnl.ObjectiveMechanism( function=pnl.LinearCombination(operation=pnl.PRODUCT), monitor=[reward, @@ -267,31 +268,22 @@ def test_partial_deferred_init(self): ]) ) - text = 'The controller of ocomp has been specified to project to deferred, but deferred is ' \ - 'not in ocomp or any of its nested Compositions. This projection will be deactivated ' \ - 'until deferred is added to ocomp in a compatible way.' - with pytest.warns(UserWarning, match=text): - # ocomp.show_graph(show_controller=True, show_cim=True) - # results = ocomp.run([5]) - result = ocomp.run({initial_node_a: [1]}) - - # result = 5, the input (1) multiplied by the value of the ControlSignal projecting to Node "ia" - # Control Signal "ia": Maximizes over the search space consisting of ints 1-5 - # Control Signal "deferred_node": disabled - - assert result == [[5]] + expected_text_1 = f"{ocomp.controller.name}, being used as controller for " \ + f"model-based optimization of {ocomp.name}, has 'state_features' specified " + expected_text_2 = f"that are missing from the Composition or any nested within it" + with pytest.raises(pnl.OptimizationControlMechanismError) as error_text: + ocomp.run({initial_node_a: [1]}) + error_text = error_text.value.error_value + assert expected_text_1 in error_text and expected_text_2 in error_text ocomp.add_linear_processing_pathway([deferred_node, initial_node_b]) - result = ocomp.run({ initial_node_a: [1], deferred_node: [1] }) - # result = 10, the sum of the input (1) multiplied by the value of the ControlSignals projecting, respectively, to Node "ia" and Node "deferred_node" # Control Signal "ia": Maximizes over the search space consisting of ints 1-5 # Control Signal "deferred_node": Maximizes over the search space consisting of ints 1-5 - assert result == [[10]] def test_deferred_objective_mech(self): @@ -353,24 +345,37 @@ def test_deferred_objective_mech(self): def test_agent_rep_assignement_as_controller_and_replacement(self): mech = pnl.ProcessingMechanism() comp = pnl.Composition(name='comp', - pathways=[mech], - controller=pnl.OptimizationControlMechanism(agent_rep=None, - control_signals=(pnl.SLOPE, mech), - search_space=[1])) + pathways=[mech], + controller=pnl.OptimizationControlMechanism(name="old_ocm", + agent_rep=None, + control_signals=(pnl.SLOPE, mech), + search_space=[1])) assert comp.controller.composition == comp + comp._analyze_graph() + assert comp.controller.state_input_ports[0].shadow_inputs == mech.input_port + assert comp.controller.state_input_ports[0].path_afferents[0].sender == mech.input_port.path_afferents[0].sender assert any(pnl.SLOPE in p_name for p_name in comp.projections.names) assert not any(pnl.INTERCEPT in p_name for p_name in comp.projections.names) + old_ocm = comp.controller - new_ocm = pnl.OptimizationControlMechanism(agent_rep=None, + new_ocm = pnl.OptimizationControlMechanism(name='new_ocm', + agent_rep=None, control_signals=(pnl.INTERCEPT, mech), search_space=[1]) - old_ocm = comp.controller comp.add_controller(new_ocm) + comp._analyze_graph() + #Confirm that components of new_ocm have been added assert comp.controller == new_ocm + assert any(pnl.INTERCEPT in p_name for p_name in comp.projections.names) + assert comp.controller.state_input_ports[0].shadow_inputs == mech.input_port + assert comp.controller.state_input_ports[0].path_afferents[0].sender == mech.input_port.path_afferents[0].sender + + # Confirm all components of old_ocm have been removed assert old_ocm.composition is None + assert old_ocm.state_input_ports[0].path_afferents == [] assert not any(pnl.SLOPE in p_name for p_name in comp.projections.names) - assert any(pnl.INTERCEPT in p_name for p_name in comp.projections.names) + def test_hanging_control_spec_outer_controller(self): internal_mech = pnl.ProcessingMechanism( @@ -431,6 +436,36 @@ def test_hanging_control_spec_nearest_controller(self): assert result == [[5]] assert internal_mech.mod_afferents[0].sender.owner == inner_comp.controller + + def test_state_input_ports_for_two_input_nodes(self): + # Inner Composition + ia = pnl.TransferMechanism(name='ia') + icomp = pnl.Composition(name='icomp', pathways=[ia]) + + # Outer Composition + oa = pnl.TransferMechanism(name='oa') + ob = pnl.TransferMechanism(name='ob') + oc = pnl.TransferMechanism(name='oc') + ctl_mech = pnl.ControlMechanism(name='ctl_mech', + control_signals=[pnl.ControlSignal(projections=[(pnl.SLOPE, ia)])]) + ocomp = pnl.Composition(name='ocomp', pathways=[[ob],[oa, icomp, oc, ctl_mech]]) + # ocomp.add_nodes(ob) + ocm = pnl.OptimizationControlMechanism(name='ocm', + agent_rep=ocomp, + control_signals=[ + pnl.ControlSignal(projections=[(pnl.NOISE, ia)]), + pnl.ControlSignal(projections=[(pnl.INTERCEPT, ia)]), + pnl.ControlSignal(projections=[(pnl.SLOPE, oa)]), + ], + search_space=[[1],[1],[1]]) + ocomp.add_controller(ocm) + result = ocomp.run({oa: [[1]], ob: [[2]]}) + assert result == [[2.], [1.]] + assert len(ocomp.controller.state_input_ports) == 2 + assert all([node in [input_port.shadow_inputs.owner for input_port in ocomp.controller.state_input_ports] + for node in {oa, ob}]) + + class TestControlMechanisms: def test_modulation_of_control_signal_intensity_cost_function_MULTIPLICATIVE(self): @@ -556,7 +591,7 @@ def test_lvoc_features_function(self): c._analyze_graph() lvoc = pnl.OptimizationControlMechanism(agent_rep=pnl.RegressionCFA, state_features=[m1.input_ports[0], m1.input_ports[1], m2.input_port, m2], - state_feature_function=pnl.LinearCombination(offset=10.0), + state_feature_functions=pnl.LinearCombination(offset=10.0), objective_mechanism=pnl.ObjectiveMechanism( monitor=[m1, m2]), function=pnl.GradientOptimization(max_iterations=1), @@ -598,7 +633,7 @@ def test_multilevel_ocm_gridsearch_conflicting_directions(self, mode, benchmark) pnl.OptimizationControlMechanism( agent_rep=ocomp, state_features=[oa.input_port], - # state_feature_function=pnl.Buffer(history=2), + # state_feature_functions=pnl.Buffer(history=2), name="Controller", objective_mechanism=pnl.ObjectiveMechanism( monitor=ib.output_port, @@ -615,7 +650,7 @@ def test_multilevel_ocm_gridsearch_conflicting_directions(self, mode, benchmark) pnl.OptimizationControlMechanism( agent_rep=icomp, state_features=[ia.input_port], - # state_feature_function=pnl.Buffer(history=2), + # state_feature_functions=pnl.Buffer(history=2), name="Controller", objective_mechanism=pnl.ObjectiveMechanism( monitor=ib.output_port, @@ -661,7 +696,7 @@ def test_multilevel_ocm_gridsearch_maximize(self, mode, benchmark): pnl.OptimizationControlMechanism( agent_rep=ocomp, state_features=[oa.input_port], - # state_feature_function=pnl.Buffer(history=2), + # state_feature_functions=pnl.Buffer(history=2), name="Controller", objective_mechanism=pnl.ObjectiveMechanism( monitor=ib.output_port, @@ -680,7 +715,7 @@ def test_multilevel_ocm_gridsearch_maximize(self, mode, benchmark): pnl.OptimizationControlMechanism( agent_rep=icomp, state_features=[ia.input_port], - # state_feature_function=pnl.Buffer(history=2), + # state_feature_functions=pnl.Buffer(history=2), name="Controller", objective_mechanism=pnl.ObjectiveMechanism( monitor=ib.output_port, @@ -728,8 +763,8 @@ def test_multilevel_ocm_gridsearch_minimize(self, mode, benchmark): pnl.OptimizationControlMechanism( agent_rep=ocomp, state_features=[oa.input_port], - # state_feature_function=pnl.Buffer(history=2), - name="Controller", + # state_feature_functions=pnl.Buffer(history=2), + name="oController", objective_mechanism=pnl.ObjectiveMechanism( monitor=ib.output_port, function=pnl.SimpleIntegrator, @@ -747,12 +782,12 @@ def test_multilevel_ocm_gridsearch_minimize(self, mode, benchmark): pnl.OptimizationControlMechanism( agent_rep=icomp, state_features=[ia.input_port], - # state_feature_function=pnl.Buffer(history=2), - name="Controller", + # state_feature_functions=pnl.Buffer(history=2), + name="iController", objective_mechanism=pnl.ObjectiveMechanism( monitor=ib.output_port, function=pnl.SimpleIntegrator, - name="oController Objective Mechanism" + name="iController Objective Mechanism" ), function=pnl.GridSearch(direction=pnl.MINIMIZE), control_signals=[pnl.ControlSignal(projections=[(pnl.SLOPE, ia)], @@ -886,7 +921,7 @@ def test_two_tier_ocm(self): pnl.OptimizationControlMechanism(agent_rep=stabilityFlexibility, state_features=[taskLayer.input_port, stimulusInfo.input_port], - state_feature_function=pnl.Buffer(history=2), + state_feature_functions=pnl.Buffer(history=2), name="Controller", objective_mechanism=pnl.ObjectiveMechanism( monitor=[(pnl.PROBABILITY_UPPER_THRESHOLD, @@ -912,7 +947,7 @@ def test_two_tier_ocm(self): outerComposition.add_controller( pnl.OptimizationControlMechanism(agent_rep=stabilityFlexibility, state_features=[taskLayer.input_port, stimulusInfo.input_port], - state_feature_function=pnl.Buffer(history=2), + state_feature_functions=pnl.Buffer(history=2), name="OuterController", objective_mechanism=pnl.ObjectiveMechanism( monitor=[(pnl.PROBABILITY_UPPER_THRESHOLD, decisionMaker)], @@ -1202,7 +1237,7 @@ def test_modulation_of_random_state(self, comp_mode, num_generators): assert np.allclose(best_second, comp.results[1]) -class TestModelBasedOptimizationControlMechanisms: +class TestModelBasedOptimizationControlMechanisms_Execution: def test_ocm_default_function(self): a = pnl.ProcessingMechanism() comp = pnl.Composition( @@ -1315,7 +1350,7 @@ def test_evc(self): comp.add_controller(controller=pnl.OptimizationControlMechanism( agent_rep=comp, state_features=[Input.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.5), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.5), objective_mechanism=pnl.ObjectiveMechanism( function=pnl.LinearCombination(operation=pnl.PRODUCT), monitor=[reward, @@ -1454,7 +1489,7 @@ def test_evc_gratton(self): state_features=[target_stim.input_port, flanker_stim.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator( + state_feature_functions=pnl.AdaptiveIntegrator( rate=1.0), objective_mechanism=objective_mech, function=pnl.GridSearch(), @@ -1599,7 +1634,7 @@ def test_laming_validation_specify_control_signals(self): controller=pnl.OptimizationControlMechanism( agent_rep=comp, state_features=[Input.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.5), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.5), objective_mechanism=pnl.ObjectiveMechanism( function=pnl.LinearCombination(operation=pnl.PRODUCT), monitor=[ @@ -1737,7 +1772,7 @@ def test_stateful_mechanism_in_simulation(self): controller=pnl.OptimizationControlMechanism( agent_rep=comp, state_features=[Input.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.5), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.5), objective_mechanism=pnl.ObjectiveMechanism( function=pnl.LinearCombination(operation=pnl.PRODUCT), monitor=[ @@ -1947,7 +1982,7 @@ def test_model_based_ocm_with_buffer(self): objective_mech = pnl.ObjectiveMechanism(monitor=[B]) ocm = pnl.OptimizationControlMechanism(agent_rep=comp, state_features=[A.input_port], - state_feature_function=pnl.Buffer(history=2), + state_feature_functions=pnl.Buffer(history=2), objective_mechanism=objective_mech, function=pnl.GridSearch(), control_signals=[control_signal]) @@ -2147,7 +2182,7 @@ def computeAccuracy(trialInformation): # Sets trial history for simulations over specified signal search parameters metaController = pnl.OptimizationControlMechanism(agent_rep=stabilityFlexibility, state_features=[taskLayer.input_port, stimulusInfo.input_port], - state_feature_function=pnl.Buffer(history=10), + state_feature_functions=pnl.Buffer(history=10), name="Controller", objective_mechanism=objectiveMechanism, function=pnl.GridSearch(), @@ -2166,7 +2201,8 @@ def computeAccuracy(trialInformation): inputs = {taskLayer: taskTrain, stimulusInfo: stimulusTrain} stabilityFlexibility.run(inputs) - def test_model_based_num_estimates(self): + @pytest.mark.parametrize('num_estimates',[None, 1] ) + def test_model_based_num_estimates(self, num_estimates): A = pnl.ProcessingMechanism(name='A') B = pnl.ProcessingMechanism(name='B', @@ -2186,8 +2222,7 @@ def test_model_based_num_estimates(self): state_features=[A.input_port], objective_mechanism=objective_mech, function=pnl.GridSearch(), - # num_estimates=5, - num_estimates=None, + num_estimates=num_estimates, control_signals=[control_signal]) comp.add_controller(ocm) @@ -2197,6 +2232,10 @@ def test_model_based_num_estimates(self): comp.run(inputs=inputs, num_trials=2) + if num_estimates is None: + assert pnl.RANDOMIZATION_CONTROL_SIGNAL not in comp.controller.control_signals # Confirm no estimates + elif num_estimates==1: + assert comp.controller.control_signals[pnl.RANDOMIZATION_CONTROL_SIGNAL].efferents == []# Confirm no noise assert np.allclose(comp.simulation_results, [[np.array([2.25])], [np.array([3.5])], [np.array([4.75])], [np.array([3.])], [np.array([4.25])], [np.array([5.5])]]) assert np.allclose(comp.results, diff --git a/tests/composition/test_parameterestimationcomposition.py b/tests/composition/test_parameterestimationcomposition.py index 8f3b3841d42..da2ae250223 100644 --- a/tests/composition/test_parameterestimationcomposition.py +++ b/tests/composition/test_parameterestimationcomposition.py @@ -23,10 +23,10 @@ # objective_function = {None: 2, Concatenate: 2, LinearCombination: 1} # expected -pec_test_args = [(None, 2, True, False), - (None, 2, False, True), - (Concatenate, 2, True, False), - (LinearCombination, 1, True, False), +pec_test_args = [(None, 2, True, False), # No ObjectiveMechanism (2 inputs), model arg + (None, 2, False, True), # No ObjectiveMechanism (2 inputs), nodes arg + (Concatenate, 2, True, False), # ObjectiveMechanism (2 inputs), model arg + (LinearCombination, 1, True, False), # ObjectiveMechanism (1 input), model arg # (None, 2, True, True), <- USE TO TEST ERROR # (None, 2, False, False), <- USE TO TEST ERROR ] @@ -37,6 +37,7 @@ ids=[f"{x[0]}-{'model' if x[2] else None}-{'nodes' if x[3] else None})" for x in pec_test_args] ) def test_parameter_estimation_composition(objective_function_arg, expected_input_len, model_spec, node_spec): + """Test with and without ObjectiveMechanism specified, and use of model vs. nodes arg of PEC constructor""" samples = np.arange(0.1, 1.01, 0.3) Input = pnl.TransferMechanism(name='Input') reward = pnl.TransferMechanism(output_ports=[pnl.RESULT, pnl.MEAN, pnl.VARIANCE], @@ -60,7 +61,7 @@ def test_parameter_estimation_composition(objective_function_arg, expected_input output_ports=[DECISION_VARIABLE, RESPONSE_TIME, PROBABILITY_UPPER_THRESHOLD], - name='Decision') + name='Decision1') Decision2 = DDM(function=DriftDiffusionAnalytical(drift_rate=1.0, threshold=1.0, noise=0.5, @@ -69,7 +70,7 @@ def test_parameter_estimation_composition(objective_function_arg, expected_input output_ports=[DECISION_VARIABLE, RESPONSE_TIME, PROBABILITY_UPPER_THRESHOLD], - name='Decision') + name='Decision2') comp = pnl.Composition(name="evc", retain_old_simulation_data=True) @@ -84,7 +85,7 @@ def test_parameter_estimation_composition(objective_function_arg, expected_input nodes = comp if node_spec else None, # data = [1,2,3], # For testing error parameters={('drift_rate',Decision):[1,2], - ('threshold',Decision2):[1,2],}, + ('threshold',Decision):[1,2],}, # parameters={('shrimp_boo',Decision):[1,2], # For testing error # ('scripblat',Decision2):[1,2],}, # For testing error outcome_variables=[Decision.output_ports[DECISION_VARIABLE], @@ -96,12 +97,19 @@ def test_parameter_estimation_composition(objective_function_arg, expected_input # enable_controller=False # For testing error ) ctlr = pec.controller + # pec.show_graph(show_node_structure=pnl.ALL) + assert ctlr.num_outcome_input_ports == 1 if objective_function_arg: + # pec.show_graph(show_cim=True) + # pec.show_graph(show_node_structure=pnl.ALL) assert ctlr.objective_mechanism # For objective_function specified else: + # pec.show_graph(show_cim=True) + # pec.show_graph(show_node_structure=pnl.ALL) assert not ctlr.objective_mechanism # For objective_function specified assert len(ctlr.input_ports[pnl.OUTCOME].variable) == expected_input_len assert len(ctlr.control_signals) == 3 - assert pnl.RANDOMIZATION_CONTROL_SIGNAL_NAME in ctlr.control_signals.names - assert ctlr.control_signals[pnl.RANDOMIZATION_CONTROL_SIGNAL_NAME].allocation_samples.base.num == 3 + assert ctlr.function.num_estimates == 3 + assert pnl.RANDOMIZATION_CONTROL_SIGNAL in ctlr.control_signals.names + assert ctlr.control_signals[pnl.RANDOMIZATION_CONTROL_SIGNAL].allocation_samples.base.num == 3 # pec.run() diff --git a/tests/composition/test_report.py b/tests/composition/test_report.py index ad4f7c3fcc8..6e3c753a0ab 100644 --- a/tests/composition/test_report.py +++ b/tests/composition/test_report.py @@ -2,8 +2,8 @@ import io import sys -import pytest import numpy as np +import pytest import psyneulink as pnl from psyneulink.core.compositions.report import ReportOutput, ReportProgress, ReportSimulations, ReportDevices @@ -180,6 +180,7 @@ def test_nested_comps_and_sims_basic(self): """Test output and progress reports for execution of simulations by controller in both an outer and nested composition, using input dictionary, generator instance and generator function. """ + pnl.clear_registry(pnl.FunctionRegistry) # instantiate mechanisms and inner comp ia = pnl.TransferMechanism(name='ia') @@ -441,6 +442,8 @@ def inputs_generator_function(): def test_nested_comps_and_sims_with_modulated_and_monitored_params_and_use_prefs(self): + pnl.clear_registry(pnl.FunctionRegistry) + # instantiate mechanisms and inner comp ia = pnl.TransferMechanism(name='ia') ib = pnl.TransferMechanism(name='ib') diff --git a/tests/composition/test_show_graph.py b/tests/composition/test_show_graph.py index 44d63287e2d..72d2e78f10c 100644 --- a/tests/composition/test_show_graph.py +++ b/tests/composition/test_show_graph.py @@ -2,8 +2,7 @@ import pytest from psyneulink.core.components.functions.nonstateful.learningfunctions import BackPropagation -from psyneulink.core.components.functions.stateful.memoryfunctions import \ - STORAGE_PROB +from psyneulink.core.components.functions.stateful.memoryfunctions import STORAGE_PROB from psyneulink.core.components.functions.nonstateful.transferfunctions import Linear from psyneulink.core.components.functions.stateful.memoryfunctions import DictionaryMemory from psyneulink.core.components.mechanisms.modulatory.control.controlmechanism import ControlMechanism @@ -241,11 +240,11 @@ def test_converging_pathways(self): ), ( {'show_controller': True}, - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tia [color=green penwidth=3 rank=source shape=oval]\n\tia -> ib [label="" arrowhead=normal color=black penwidth=1]\n\t"my ocm" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm" -> ib [label="" arrowhead=box color=purple penwidth=1]\n\tib [color=red penwidth=3 rank=max shape=oval]\n\t"my ocm" [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}' + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tia [color=green penwidth=3 rank=source shape=oval]\n\tia -> ib [label="" arrowhead=normal color=black penwidth=1]\n\t"my ocm" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm" -> ib [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> "my ocm" [label="" arrowhead=normal color=purple penwidth=1]\n\tib [color=red penwidth=3 rank=max shape=oval]\n\t"my ocm" [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}' ), ( {'show_controller': True, 'show_node_structure': True}, - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tia:"OutputPort-RESULT" -> ib:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"my ocm":"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm":"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm":"OutputPort-ib[slope] ControlSignal" -> ib:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\tib [label=<
RESULT
OutputPorts
Mechanism:
ib
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\t"my ocm" [label=<
ia[noise] ControlSignalia[intercept] ControlSignalib[slope] ControlSignal
OutputPorts
Mechanism:
my ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}' + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tia:"OutputPort-RESULT" -> ib:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"my ocm":"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm":"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t"my ocm":"OutputPort-ib[slope] ControlSignal" -> ib:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> "my ocm":"InputPort-Shadowed input of of ia[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\tib [label=<
RESULT
OutputPorts
Mechanism:
ib
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\t"my ocm" [label=<
ia[noise] ControlSignalia[intercept] ControlSignalib[slope] ControlSignal
OutputPorts
Mechanism:
my ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of ia[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}' ) ] @@ -382,35 +381,35 @@ def test_nested_learning(self, show_graph_kwargs, expected_output): _nested_learning_test_with_user_specified_target_in_outer_composition_data = [ ( {'show_nested': False, 'show_cim': False, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> CONTROLLER [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}' ), ( {'show_nested': NESTED, 'show_cim': False, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL -> "INNER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> Target [label="" arrowhead=normal color=orange penwidth=1]\n\t"INNER OUTPUT" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [color=orange penwidth=3 rank=min shape=oval]\n\t\t"INNER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\tComparator [color=orange penwidth=1 rank=min shape=oval]\n\t\t"INNER OUTPUT" -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=orange penwidth=1 rank=min shape=oval]\n\t\tComparator -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL -> "INNER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> Target [label="" arrowhead=normal color=orange penwidth=1]\n\t"INNER OUTPUT" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> CONTROLLER [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [color=orange penwidth=3 rank=min shape=oval]\n\t\t"INNER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\tComparator [color=orange penwidth=1 rank=min shape=oval]\n\t\t"INNER OUTPUT" -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=orange penwidth=1 rank=min shape=oval]\n\t\tComparator -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' ), ( {'show_nested': False, 'show_cim': True, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"COMPOSITION INPUT_CIM" -> "OUTER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> TARGET [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t"OUTER OUTPUT" -> "COMPOSITION OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"COMPOSITION INPUT_CIM" -> "OUTER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> TARGET [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t"OUTER OUTPUT" -> "COMPOSITION OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> CONTROLLER [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}' ), ( {'show_nested': NESTED, 'show_cim': True, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL -> "NESTED COMPOSITION INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> "NESTED COMPOSITION INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION OUTPUT_CIM" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"COMPOSITION INPUT_CIM" -> "OUTER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> TARGET [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t"OUTER OUTPUT" -> "COMPOSITION OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [color=orange penwidth=3 rank=min shape=oval]\n\t\t"INNER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"NESTED COMPOSITION INPUT_CIM" -> "INNER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM" -> Target [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t"INNER OUTPUT" -> "NESTED COMPOSITION OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tComparator [color=orange penwidth=1 rank=min shape=oval]\n\t\t"INNER OUTPUT" -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=orange penwidth=1 rank=min shape=oval]\n\t\tComparator -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [color=green penwidth=3 rank=source shape=oval]\n\t"OUTER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\tINTERNAL [color=black penwidth=1 rank=same shape=oval]\n\t"OUTER INPUT" -> INTERNAL [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL -> "NESTED COMPOSITION INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET -> "NESTED COMPOSITION INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION OUTPUT_CIM" -> "OUTER OUTPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"COMPOSITION INPUT_CIM" -> "OUTER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> TARGET [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t"OUTER OUTPUT" -> "COMPOSITION OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER -> INTERNAL [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [color=purple penwidth=1 rank=min shape=oval]\n\t"OBJECTIVE MECHANISM" -> CONTROLLER [label="" color=purple penwidth=1]\n\t"OUTER INPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" -> "OBJECTIVE MECHANISM" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM" -> CONTROLLER [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\tCONTROLLER [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [color=orange penwidth=3 rank=min shape=oval]\n\t\t"INNER INPUT" [color=green penwidth=3 rank=source shape=oval]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"NESTED COMPOSITION INPUT_CIM" -> "INNER INPUT" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM" -> Target [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t"INNER OUTPUT" -> "NESTED COMPOSITION OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tComparator [color=orange penwidth=1 rank=min shape=oval]\n\t\t"INNER OUTPUT" -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget -> Comparator [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=orange penwidth=1 rank=min shape=oval]\n\t\tComparator -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [color=red penwidth=3 rank=max shape=oval]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' ), ( {'show_nested': False, 'show_cim': False, 'show_node_structure': True, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> CONTROLLER:"InputPort-Shadowed input of of OUTER INPUT[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of OUTER INPUT[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}' ), ( {'show_nested': NESTED, 'show_cim': False, 'show_node_structure': True, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "INNER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> Target:"InputPort-InputPort-0" [label="" arrowhead=normal color=orange penwidth=1]\n\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [label=<
OutputPort-0
OutputPorts
Mechanism:
Target
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=orange penwidth=3 rank=min shape=plaintext]\n\t\t"INNER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT":"InputPort-InputPort-0" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"OutputPort-LearningSignal" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\tComparator [label=<
OUTCOMEMSE
OutputPorts
Mechanism:
Comparator
ParameterPorts
offset
scale
InputPorts
SAMPLETARGET
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> Comparator:"InputPort-SAMPLE" [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget:"OutputPort-OutputPort-0" -> Comparator:"InputPort-TARGET" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label=<
error_signalLearningSignal
OutputPorts
Mechanism:
Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]
ParameterPorts
learning_rate
InputPorts
activation_inputactivation_outputerror_signal
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\tComparator:"OutputPort-OUTCOME" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-error_signal" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_input" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_output" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "INNER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> Target:"InputPort-InputPort-0" [label="" arrowhead=normal color=orange penwidth=1]\n\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> CONTROLLER:"InputPort-Shadowed input of of OUTER INPUT[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of OUTER INPUT[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [label=<
OutputPort-0
OutputPorts
Mechanism:
Target
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=orange penwidth=3 rank=min shape=plaintext]\n\t\t"INNER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT":"InputPort-InputPort-0" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"OutputPort-LearningSignal" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\tComparator [label=<
OUTCOMEMSE
OutputPorts
Mechanism:
Comparator
ParameterPorts
offset
scale
InputPorts
SAMPLETARGET
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> Comparator:"InputPort-SAMPLE" [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget:"OutputPort-OutputPort-0" -> Comparator:"InputPort-TARGET" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label=<
error_signalLearningSignal
OutputPorts
Mechanism:
Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]
ParameterPorts
learning_rate
InputPorts
activation_inputactivation_outputerror_signal
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\tComparator:"OutputPort-OUTCOME" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-error_signal" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_input" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_output" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' ), ( {'show_nested': False, 'show_cim': True, 'show_node_structure': True, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [label=<
INPUT_CIM_OUTER INPUT_InputPort-0INPUT_CIM_TARGET_InputPort-0
OutputPorts
Mechanism:
COMPOSITION Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> "OUTER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_TARGET_InputPort-0" -> TARGET:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [label=<
Mechanism:
COMPOSITION Output_CIM
InputPorts
OUTPUT_CIM_OUTER OUTPUT_OutputPort-0
> color=red penwidth=1 rank=same shape=plaintext]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "COMPOSITION OUTPUT_CIM":"InputPort-OUTPUT_CIM_OUTER OUTPUT_OutputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" [color=pink penwidth=3 rank=same shape=rectangle]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [label=<
INPUT_CIM_OUTER INPUT_InputPort-0INPUT_CIM_TARGET_InputPort-0
OutputPorts
Mechanism:
COMPOSITION Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> "OUTER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_TARGET_InputPort-0" -> TARGET:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [label=<
Mechanism:
COMPOSITION Output_CIM
InputPorts
OUTPUT_CIM_OUTER OUTPUT_OutputPort-0
> color=red penwidth=1 rank=same shape=plaintext]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "COMPOSITION OUTPUT_CIM":"InputPort-OUTPUT_CIM_OUTER OUTPUT_OutputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> CONTROLLER:"InputPort-Shadowed input of of OUTER INPUT[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of OUTER INPUT[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}' ), ( {'show_nested': NESTED, 'show_cim': True, 'show_node_structure': True, 'show_learning': True}, - 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION INPUT_CIM":"InputPort-INPUT_CIM_INNER INPUT_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION INPUT_CIM":"InputPort-INPUT_CIM_Target_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION OUTPUT_CIM":"OutputPort-OUTPUT_CIM_INNER OUTPUT_OutputPort-0" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [label=<
INPUT_CIM_OUTER INPUT_InputPort-0INPUT_CIM_TARGET_InputPort-0
OutputPorts
Mechanism:
COMPOSITION Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> "OUTER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_TARGET_InputPort-0" -> TARGET:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [label=<
Mechanism:
COMPOSITION Output_CIM
InputPorts
OUTPUT_CIM_OUTER OUTPUT_OutputPort-0
> color=red penwidth=1 rank=same shape=plaintext]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "COMPOSITION OUTPUT_CIM":"InputPort-OUTPUT_CIM_OUTER OUTPUT_OutputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [label=<
OutputPort-0
OutputPorts
Mechanism:
Target
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=orange penwidth=3 rank=min shape=plaintext]\n\t\t"INNER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT":"InputPort-InputPort-0" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"OutputPort-LearningSignal" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM" [label=<
INPUT_CIM_INNER INPUT_InputPort-0INPUT_CIM_Target_InputPort-0
OutputPorts
Mechanism:
NESTED COMPOSITION Input_CIM
InputPorts
INPUT_CIM_INNER INPUT_InputPort-0INPUT_CIM_Target_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"NESTED COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_INNER INPUT_InputPort-0" -> "INNER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_Target_InputPort-0" -> Target:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION OUTPUT_CIM" [label=<
OUTPUT_CIM_INNER OUTPUT_OutputPort-0
OutputPorts
Mechanism:
NESTED COMPOSITION Output_CIM
InputPorts
OUTPUT_CIM_INNER OUTPUT_OutputPort-0
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "NESTED COMPOSITION OUTPUT_CIM":"InputPort-OUTPUT_CIM_INNER OUTPUT_OutputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\tComparator [label=<
OUTCOMEMSE
OutputPorts
Mechanism:
Comparator
ParameterPorts
offset
scale
InputPorts
SAMPLETARGET
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> Comparator:"InputPort-SAMPLE" [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget:"OutputPort-OutputPort-0" -> Comparator:"InputPort-TARGET" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label=<
error_signalLearningSignal
OutputPorts
Mechanism:
Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]
ParameterPorts
learning_rate
InputPorts
activation_inputactivation_outputerror_signal
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\tComparator:"OutputPort-OUTCOME" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-error_signal" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_input" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_output" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' + 'digraph COMPOSITION {\n\tgraph [label=COMPOSITION overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\tTARGET [label=<
OutputPort-0
OutputPorts
Mechanism:
TARGET
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t"OUTER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tINTERNAL [label=<
OutputPort-0
OutputPorts
Mechanism:
INTERNAL
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> INTERNAL:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tINTERNAL:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION INPUT_CIM":"InputPort-INPUT_CIM_INNER INPUT_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tTARGET:"OutputPort-OutputPort-0" -> "NESTED COMPOSITION INPUT_CIM":"InputPort-INPUT_CIM_Target_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"NESTED COMPOSITION OUTPUT_CIM":"OutputPort-OUTPUT_CIM_INNER OUTPUT_OutputPort-0" -> "OUTER OUTPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM" [label=<
INPUT_CIM_OUTER INPUT_InputPort-0INPUT_CIM_TARGET_InputPort-0
OutputPorts
Mechanism:
COMPOSITION Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> "OUTER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_TARGET_InputPort-0" -> TARGET:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"COMPOSITION OUTPUT_CIM" [label=<
Mechanism:
COMPOSITION Output_CIM
InputPorts
OUTPUT_CIM_OUTER OUTPUT_OutputPort-0
> color=red penwidth=1 rank=same shape=plaintext]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "COMPOSITION OUTPUT_CIM":"InputPort-OUTPUT_CIM_OUTER OUTPUT_OutputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tCONTROLLER:"OutputPort-INTERNAL[slope] ControlSignal" -> INTERNAL:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"OBJECTIVE MECHANISM" [label=<
OUTCOME
OutputPorts
Mechanism:
OBJECTIVE MECHANISM
ParameterPorts
offset
scale
InputPorts
Value of OUTER INPUT [OutputPort-0]Value of OUTER OUTPUT [OutputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\t"OBJECTIVE MECHANISM":"OutputPort-OUTCOME" -> CONTROLLER:"InputPort-OUTCOME" [label="" color=purple penwidth=1]\n\t"OUTER INPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER INPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"OUTER OUTPUT":"OutputPort-OutputPort-0" -> "OBJECTIVE MECHANISM":"InputPort-Value of OUTER OUTPUT [OutputPort-0]" [label="" color=purple penwidth=1]\n\t"COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_OUTER INPUT_InputPort-0" -> CONTROLLER:"InputPort-Shadowed input of of OUTER INPUT[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"OUTER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
OUTER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tCONTROLLER [label=<
INTERNAL[slope] ControlSignal
OutputPorts
Mechanism:
CONTROLLER
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of OUTER INPUT[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph "cluster_NESTED COMPOSITION" {\n\t\tgraph [label="NESTED COMPOSITION" overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tTarget [label=<
OutputPort-0
OutputPorts
Mechanism:
Target
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=orange penwidth=3 rank=min shape=plaintext]\n\t\t"INNER INPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER INPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [color=black penwidth=1 shape=diamond]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [arrowhead=none color=black penwidth=1]\n\t\t"MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" -> "INNER OUTPUT":"InputPort-InputPort-0" [color=black penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"OutputPort-LearningSignal" -> "MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label="" color=orange penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM" [label=<
INPUT_CIM_INNER INPUT_InputPort-0INPUT_CIM_Target_InputPort-0
OutputPorts
Mechanism:
NESTED COMPOSITION Input_CIM
InputPorts
INPUT_CIM_INNER INPUT_InputPort-0INPUT_CIM_Target_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"NESTED COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_INNER INPUT_InputPort-0" -> "INNER INPUT":"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION INPUT_CIM":"OutputPort-INPUT_CIM_Target_InputPort-0" -> Target:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"NESTED COMPOSITION OUTPUT_CIM" [label=<
OUTPUT_CIM_INNER OUTPUT_OutputPort-0
OutputPorts
Mechanism:
NESTED COMPOSITION Output_CIM
InputPorts
OUTPUT_CIM_INNER OUTPUT_OutputPort-0
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "NESTED COMPOSITION OUTPUT_CIM":"InputPort-OUTPUT_CIM_INNER OUTPUT_OutputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\tComparator [label=<
OUTCOMEMSE
OutputPorts
Mechanism:
Comparator
ParameterPorts
offset
scale
InputPorts
SAMPLETARGET
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> Comparator:"InputPort-SAMPLE" [label="" arrowhead=normal color=orange penwidth=1]\n\t\tTarget:"OutputPort-OutputPort-0" -> Comparator:"InputPort-TARGET" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]" [label=<
error_signalLearningSignal
OutputPorts
Mechanism:
Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]
ParameterPorts
learning_rate
InputPorts
activation_inputactivation_outputerror_signal
> color=orange penwidth=1 rank=min shape=plaintext]\n\t\tComparator:"OutputPort-OUTCOME" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-error_signal" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER INPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_input" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT":"OutputPort-OutputPort-0" -> "Learning Mechanism for MappingProjection from INNER INPUT[OutputPort-0] to INNER OUTPUT[InputPort-0]":"InputPort-activation_output" [label="" arrowhead=normal color=orange penwidth=1]\n\t\t"INNER OUTPUT" [label=<
OutputPort-0
OutputPorts
Mechanism:
INNER OUTPUT
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\t\tlabel="NESTED COMPOSITION"\n\t}\n}' ), ] @@ -497,28 +496,23 @@ def test_nested_learning_test_with_user_specified_target_in_outer_composition( {'show_node_structure': True, 'show_nested': NESTED}, {'show_node_structure': True, 'show_cim': True, 'show_nested': False}, {'show_node_structure': True, 'show_cim': True, 'show_nested': INSET}, - {'show_node_structure': True, 'show_cim': True, 'show_nested': NESTED}, + {'show_node_structure': True, 'show_cim': True, 'show_nested': NESTED} ] # each item corresponds to the same item in _nested_show_graph_kwargs above _of_show_nested_show_cim_and_show_node_structure_expected_outputs = [ - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> ia [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> ia [label="" arrowhead=box color=blue penwidth=1]\n\tia -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> "icomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t"icomp OUTPUT_CIM" -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial ' - 'fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial ' - 'fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial ' - 'fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\tia:"OutputPort-RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial ' - 'fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_ob_InputPort-0INPUT_CIM_oa_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_ob_RESULTOUTPUT_CIM_oc_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial ' - 'fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_ob_InputPort-0INPUT_CIM_oa_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_ob_RESULTOUTPUT_CIM_oc_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [label=<
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> "icomp INPUT_CIM":"InputPort-INPUT_CIM_ia_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_slope" [label="" arrowhead=normal color=blue penwidth=1]\n\t"icomp OUTPUT_CIM":"OutputPort-OUTPUT_CIM_ia_RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_ob_InputPort-0INPUT_CIM_oa_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_ob_RESULTOUTPUT_CIM_oc_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_noise" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_intercept" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
InputPorts
INPUT_CIM_ia_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
InputPorts
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [label=<
OUTPUT_CIM_ia_RESULT
OutputPorts
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}' + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> ia [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> ia [label="" arrowhead=box color=blue penwidth=1]\n\tia -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> "icomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t"icomp OUTPUT_CIM" -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of ob[InputPort-0]Shadowed input of of oa[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of ob[InputPort-0]Shadowed input of of oa[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\tia:"OutputPort-RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of ob[InputPort-0]Shadowed input of of oa[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_ob_InputPort-0INPUT_CIM_oa_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_ob_RESULTOUTPUT_CIM_oc_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of ob[InputPort-0]Shadowed input of of oa[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_ob_InputPort-0INPUT_CIM_oa_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_ob_RESULTOUTPUT_CIM_oc_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of ob[InputPort-0]Shadowed input of of oa[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [label=<
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> "icomp INPUT_CIM":"InputPort-INPUT_CIM_ia_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_slope" [label="" arrowhead=normal color=blue penwidth=1]\n\t"icomp OUTPUT_CIM":"OutputPort-OUTPUT_CIM_ia_RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_ob_InputPort-0INPUT_CIM_oa_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_ob_RESULTOUTPUT_CIM_oc_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_noise" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_intercept" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of ob[InputPort-0]Shadowed input of of oa[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
InputPorts
INPUT_CIM_ia_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
InputPorts
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [label=<
OUTPUT_CIM_ia_RESULT
OutputPorts
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}' ] @pytest.mark.parametrize( @@ -561,18 +555,18 @@ def test_of_show_nested_show_cim_and_show_node_structure( # each item corresponds to the same item in _nested_show_graph_kwargs above _of_show_3_level_nested_show_cim_and_show_node_structure_outputs = [ - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> ma [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> ia [label="" arrowhead=box color=blue penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\tma -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp INPUT_CIM" -> ma [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp PARAMETER_CIM" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\ticomp -> "midcomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> "midcomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> "midcomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t"midcomp OUTPUT_CIM" -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> "midcomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> "midcomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\tma -> "icomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp INPUT_CIM" -> ma [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp PARAMETER_CIM" -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t"icomp OUTPUT_CIM" -> "midcomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> ma:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\tma:"OutputPort-RESULT" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [label=<
INPUT_CIM_ma_InputPort-0
OutputPorts
Mechanism:
midcomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp INPUT_CIM":"OutputPort-INPUT_CIM_ma_InputPort-0" -> ma:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_slopePARAMETER_CIM_ia_noisePARAMETER_CIM_ia_intercept
OutputPorts
Mechanism:
midcomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [label=<
Mechanism:
midcomp Output_CIM
InputPorts
OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\ticomp -> "midcomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [label=<
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> "midcomp INPUT_CIM":"InputPort-INPUT_CIM_ma_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> "midcomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_slope" [label="" arrowhead=normal color=blue penwidth=1]\n\t"midcomp OUTPUT_CIM":"OutputPort-OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> "midcomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_noise" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> "midcomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_intercept" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\tma:"OutputPort-RESULT" -> "icomp INPUT_CIM":"InputPort-INPUT_CIM_ia_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [label=<
INPUT_CIM_ma_InputPort-0
OutputPorts
Mechanism:
midcomp Input_CIM
InputPorts
INPUT_CIM_ma_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp INPUT_CIM":"OutputPort-INPUT_CIM_ma_InputPort-0" -> ma:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_slopePARAMETER_CIM_ia_noisePARAMETER_CIM_ia_intercept
OutputPorts
Mechanism:
midcomp Parameter_CIM
InputPorts
PARAMETER_CIM_ia_slopePARAMETER_CIM_ia_noisePARAMETER_CIM_ia_intercept
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_slope" [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_noise" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_intercept" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [label=<
OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT
OutputPorts
Mechanism:
midcomp Output_CIM
InputPorts
OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t"icomp OUTPUT_CIM":"OutputPort-OUTPUT_CIM_ia_RESULT" -> "midcomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
InputPorts
INPUT_CIM_ia_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
InputPorts
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [label=<
OUTPUT_CIM_ia_RESULT
OutputPorts
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> ma [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> ia [label="" arrowhead=box color=blue penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\tma -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> midcomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp INPUT_CIM" -> ma [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp PARAMETER_CIM" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\ticomp -> "midcomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> "midcomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> "midcomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t"midcomp OUTPUT_CIM" -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> "midcomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> "midcomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [color=green penwidth=3 rank=source shape=oval]\n\t\tma -> "icomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp INPUT_CIM" -> ma [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"midcomp PARAMETER_CIM" -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM" -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t"icomp OUTPUT_CIM" -> "midcomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> ma:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\tma:"OutputPort-RESULT" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\tmidcomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> midcomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> midcomp [label="" arrowhead=normal color=black penwidth=1]\n\tmidcomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> midcomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\ticomp [color=red penwidth=3 rank=max shape=rectangle]\n\t\tma:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [label=<
INPUT_CIM_ma_InputPort-0
OutputPorts
Mechanism:
midcomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp INPUT_CIM":"OutputPort-INPUT_CIM_ma_InputPort-0" -> ma:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_slopePARAMETER_CIM_ia_noisePARAMETER_CIM_ia_intercept
OutputPorts
Mechanism:
midcomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [label=<
Mechanism:
midcomp Output_CIM
InputPorts
OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\ticomp -> "midcomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [label=<
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> "midcomp INPUT_CIM":"InputPort-INPUT_CIM_ma_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> "midcomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_slope" [label="" arrowhead=normal color=blue penwidth=1]\n\t"midcomp OUTPUT_CIM":"OutputPort-OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> "midcomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_noise" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> "midcomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_intercept" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_midcomp {\n\t\tgraph [label=midcomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tma [label=<
RESULT
OutputPorts
Mechanism:
ma
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\t\tma:"OutputPort-RESULT" -> "icomp INPUT_CIM":"InputPort-INPUT_CIM_ia_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp INPUT_CIM" [label=<
INPUT_CIM_ma_InputPort-0
OutputPorts
Mechanism:
midcomp Input_CIM
InputPorts
INPUT_CIM_ma_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp INPUT_CIM":"OutputPort-INPUT_CIM_ma_InputPort-0" -> ma:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"midcomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_slopePARAMETER_CIM_ia_noisePARAMETER_CIM_ia_intercept
OutputPorts
Mechanism:
midcomp Parameter_CIM
InputPorts
PARAMETER_CIM_ia_slopePARAMETER_CIM_ia_noisePARAMETER_CIM_ia_intercept
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_slope" [label="" arrowhead=normal color=blue penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_noise" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> "icomp PARAMETER_CIM":"InputPort-PARAMETER_CIM_ia_intercept" [label="" arrowhead=normal color=purple penwidth=1]\n\t\t"midcomp OUTPUT_CIM" [label=<
OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT
OutputPorts
Mechanism:
midcomp Output_CIM
InputPorts
OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t"icomp OUTPUT_CIM":"OutputPort-OUTPUT_CIM_ia_RESULT" -> "midcomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_icomp_OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tsubgraph cluster_icomp {\n\t\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\t\tedge [fontname=arial fontsize=10]\n\t\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
InputPorts
INPUT_CIM_ia_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
InputPorts
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t\t"icomp OUTPUT_CIM" [label=<
OUTPUT_CIM_ia_RESULT
OutputPorts
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\t\tcolor=red\n\t\t\tlabel=icomp\n\t\t}\n\t\tlabel=midcomp\n\t}\n}', ] @pytest.mark.parametrize( @@ -611,23 +605,26 @@ def test_of_show_3_level_nested_show_cim_and_show_node_structure( ], search_space=[[1],[1],[1]]) ocomp.add_controller(ocm) - gv = ocomp.show_graph(output_fmt='source', **show_graph_kwargs) + assert ocomp.controller.outcome_input_ports[0].path_afferents == [] + assert len(ocomp.controller.state_input_ports) == 2 + assert all([node in [input_port.shadow_inputs.owner for input_port in ocomp.controller.state_input_ports] + for node in {oa, ob}]) assert gv.strip() == expected_output # each item corresponds to the same item in _nested_show_graph_kwargs above _of_show_nested_show_cim_and_show_node_structure_with_singleton_in_outer_comp_added_last_outputs = [ - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> ia [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> ia [label="" arrowhead=box color=blue penwidth=1]\n\tia -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> "icomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t"icomp OUTPUT_CIM" -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\tia:"OutputPort-RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n}', - 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOME
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [label=<
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> ia [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> ia [label="" arrowhead=box color=blue penwidth=1]\n\tia -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> ia [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [color=green penwidth=3 rank=source shape=oval]\n\toa -> "icomp INPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=blue penwidth=1]\n\t"icomp OUTPUT_CIM" -> oc [label="" arrowhead=normal color=black penwidth=1]\n\toc -> ctl_mech [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t"ocomp INPUT_CIM" -> oa [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" -> ob [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\toc -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tob -> "ocomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> "icomp PARAMETER_CIM" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm -> oa [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM" -> ocm [label="" arrowhead=normal color=purple penwidth=1]\n\toc [color=red penwidth=3 rank=max shape=oval]\n\tctl_mech [color=blue penwidth=3 rank=max shape=octagon]\n\tob [color=brown penwidth=3 rank=same shape=oval]\n\tocm [color=purple penwidth=1 rank=min shape=doubleoctagon]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [color=green penwidth=1 rank=same shape=rectangle]\n\t\t"icomp INPUT_CIM" -> ia [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [color=purple penwidth=1 rank=same shape=rectangle]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM" -> ia [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [color=red penwidth=1 rank=same shape=rectangle]\n\t\tia -> "icomp OUTPUT_CIM" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [color=brown penwidth=3 rank=same shape=oval]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\tia:"OutputPort-RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=box color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=box color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n}', + 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\ticomp [color=pink penwidth=3 rank=same shape=rectangle]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> icomp [label="" arrowhead=normal color=blue penwidth=1]\n\toa:"OutputPort-RESULT" -> icomp [label="" arrowhead=normal color=black penwidth=1]\n\ticomp -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT_CIM" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> icomp [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_oa_InputPort-0" -> ocm:"InputPort-Shadowed input of of oa[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\t"ocomp INPUT_CIM":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ocm:"InputPort-Shadowed input of of ob[InputPort-0]" [label="" arrowhead=normal color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
ParameterPorts
seed
InputPorts
OUTCOMEShadowed input of of oa[InputPort-0]Shadowed input of of ob[InputPort-0]
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT_CIM" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"icomp INPUT_CIM":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp PARAMETER_CIM" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp PARAMETER_CIM":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT_CIM" [label=<
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT_CIM":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}', # FIX: NEEDS TO BE CORRECTED ONCE BUG IS FIXED (SEE MESSAGE FOR COMMIT eb61303808ad2a5ba46fdd18d0e583283397915c) # 'digraph ocomp {\n\tgraph [label=ocomp overlap=False rankdir=BT]\n\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\tedge [fontname=arial fontsize=10]\n\toa [label=<
RESULT
OutputPorts
Mechanism:
oa
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]\n\toa:"OutputPort-RESULT" -> "icomp INPUT":"InputPort-INPUT_CIM_ia_InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\tctl_mech:"OutputPort-ia[slope] ControlSignal" -> "icomp CONTROL":"InputPort-PARAMETER_CIM_ia_slope" [label="" arrowhead=normal color=blue penwidth=1]\n\t"icomp OUTPUT":"OutputPort-OUTPUT_CIM_ia_RESULT" -> oc:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\toc:"OutputPort-RESULT" -> ctl_mech:"InputPort-OUTCOME" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT" [label=<
INPUT_CIM_oa_InputPort-0INPUT_CIM_ob_InputPort-0
OutputPorts
Mechanism:
ocomp Input_CIM
> color=green penwidth=1 rank=same shape=plaintext]\n\t"ocomp INPUT":"OutputPort-INPUT_CIM_oa_InputPort-0" -> oa:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp INPUT":"OutputPort-INPUT_CIM_ob_InputPort-0" -> ob:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t"ocomp OUTPUT" [label=<
Mechanism:
ocomp Output_CIM
InputPorts
OUTPUT_CIM_oc_RESULTOUTPUT_CIM_ob_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\toc:"OutputPort-RESULT" -> "ocomp OUTPUT":"InputPort-OUTPUT_CIM_oc_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tob:"OutputPort-RESULT" -> "ocomp OUTPUT":"InputPort-OUTPUT_CIM_ob_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\tocm:"OutputPort-ia[noise] ControlSignal" -> "icomp CONTROL":"InputPort-PARAMETER_CIM_ia_noise" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-ia[intercept] ControlSignal" -> "icomp CONTROL":"InputPort-PARAMETER_CIM_ia_intercept" [label="" arrowhead=normal color=purple penwidth=1]\n\tocm:"OutputPort-oa[slope] ControlSignal" -> oa:"ParameterPort-slope" [label="" arrowhead=box color=purple penwidth=1]\n\toc [label=<
RESULT
OutputPorts
Mechanism:
oc
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]\n\tctl_mech [label=<
ia[slope] ControlSignal
OutputPorts
Mechanism:
ctl_mech
InputPorts
OUTCOME
> color=blue penwidth=3 rank=max shape=plaintext]\n\tob [label=<
RESULT
OutputPorts
Mechanism:
ob
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\tocm [label=<
ia[noise] ControlSignalia[intercept] ControlSignaloa[slope] ControlSignal
OutputPorts
Mechanism:
ocm
InputPorts
OUTCOMEOUTCOME-1
> color=purple penwidth=1 rank=min shape=plaintext]\n\tsubgraph cluster_icomp {\n\t\tgraph [label=icomp overlap=False rankdir=BT]\n\t\tnode [color=black fontname=arial fontsize=12 penwidth=1 shape=record]\n\t\tedge [fontname=arial fontsize=10]\n\t\t"icomp INPUT" [label=<
INPUT_CIM_ia_InputPort-0
OutputPorts
Mechanism:
icomp Input_CIM
InputPorts
INPUT_CIM_ia_InputPort-0
> color=green penwidth=1 rank=same shape=plaintext]\n\t\t"icomp INPUT":"OutputPort-INPUT_CIM_ia_InputPort-0" -> ia:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]\n\t\t"icomp CONTROL" [label=<
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
OutputPorts
Mechanism:
icomp Parameter_CIM
InputPorts
PARAMETER_CIM_ia_interceptPARAMETER_CIM_ia_noisePARAMETER_CIM_ia_slope
> color=purple penwidth=1 rank=same shape=plaintext]\n\t\t"icomp CONTROL":"OutputPort-PARAMETER_CIM_ia_intercept" -> ia:"ParameterPort-intercept" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp CONTROL":"OutputPort-PARAMETER_CIM_ia_noise" -> ia:"ParameterPort-noise" [label="" arrowhead=box color=purple penwidth=1]\n\t\t"icomp CONTROL":"OutputPort-PARAMETER_CIM_ia_slope" -> ia:"ParameterPort-slope" [label="" arrowhead=box color=blue penwidth=1]\n\t\t"icomp OUTPUT" [label=<
OUTPUT_CIM_ia_RESULT
OutputPorts
Mechanism:
icomp Output_CIM
InputPorts
OUTPUT_CIM_ia_RESULT
> color=red penwidth=1 rank=same shape=plaintext]\n\t\tia:"OutputPort-RESULT" -> "icomp OUTPUT":"InputPort-OUTPUT_CIM_ia_RESULT" [label="" arrowhead=normal color=black penwidth=1]\n\t\tia [label=<
RESULT
OutputPorts
Mechanism:
ia
ParameterPorts
intercept
noise
offset
rate
slope
InputPorts
InputPort-0
> color=brown penwidth=3 rank=same shape=plaintext]\n\t\tlabel=icomp\n\t}\n}' ] diff --git a/tests/json/model_with_control.py b/tests/json/model_with_control.py index b432363cc59..17240875340 100644 --- a/tests/json/model_with_control.py +++ b/tests/json/model_with_control.py @@ -48,7 +48,7 @@ controller=pnl.OptimizationControlMechanism( agent_rep=comp, state_features=[Input.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.5), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.5), objective_mechanism=pnl.ObjectiveMechanism( function=pnl.LinearCombination(operation=pnl.PRODUCT), monitor=[ diff --git a/tests/log/test_log.py b/tests/log/test_log.py index 9cb42a1c37f..37e6a50bf06 100644 --- a/tests/log/test_log.py +++ b/tests/log/test_log.py @@ -1165,7 +1165,7 @@ def node_logged_in_simulation(self): controller=pnl.OptimizationControlMechanism( agent_rep=comp, state_features=[Input.input_port, reward.input_port], - state_feature_function=pnl.AdaptiveIntegrator(rate=0.5), + state_feature_functions=pnl.AdaptiveIntegrator(rate=0.5), objective_mechanism=pnl.ObjectiveMechanism( function=pnl.LinearCombination(operation=pnl.PRODUCT), monitor=[