def test_valid_only_one_node_provides_input_spec(self): A = ProcessingMechanism(name="A", default_variable=[[ 1.5 ]]) # default variable will be used as input to this INPUT node B = ProcessingMechanism(name="B") C = ProcessingMechanism(name="C") comp = Composition(name="COMP") comp.add_linear_processing_pathway([A, C]) comp.add_linear_processing_pathway([B, C]) inputs_to_B = [[1.0], [2.0], [3.0], [4.0]] # increment on every trial results_A = [] results_B = [] results_C = [] def call_after_trial(): results_A.append(A.parameters.value.get(comp)) results_B.append(B.parameters.value.get(comp)) results_C.append(C.parameters.value.get(comp)) comp.run(inputs={B: inputs_to_B}, call_after_trial=call_after_trial) assert np.allclose(results_A, [[[1.5]], [[1.5]], [[1.5]], [[1.5]]]) assert np.allclose(results_B, [[[1.0]], [[2.0]], [[3.0]], [[4.0]]]) assert np.allclose(results_C, [[[2.5]], [[3.5]], [[4.5]], [[5.5]]])
def test_equivalance_of_threshold_and_when_finished_condition(self): # Note: This tests the equivalence of results when: # execute_until_finished is True for the LCAMechanism (by default) # and the call to execution loops until it reaches threshold (1st test) # vs. when execute_until_finished is False and a condition is added to the scheduler # that causes the LCAMechanism it to execute until it reaches threshold (2nd test). # loop Mechanism's call to execute lca_until_thresh = LCAMechanism( size=2, leak=0.5, threshold=0.7) # Note: , execute_to_threshold=True by default response = ProcessingMechanism(size=2) comp = Composition() comp.add_linear_processing_pathway([lca_until_thresh, response]) result1 = comp.run(inputs={lca_until_thresh: [1, 0]}) # loop Composition's call to Mechanism lca_single_step = LCAMechanism(size=2, leak=0.5, threshold=0.7, execute_until_finished=False) comp2 = Composition() response2 = ProcessingMechanism(size=2) comp2.add_linear_processing_pathway([lca_single_step, response2]) comp2.scheduler.add_condition(response2, WhenFinished(lca_single_step)) result2 = comp2.run(inputs={lca_single_step: [1, 0]}) assert np.allclose(result1, result2)
def test_connect_outer_composition_to_all_input_nodes_in_inner_comp(self): inner1 = Composition(name="inner") A1 = TransferMechanism(name="A1", function=Linear(slope=2.0)) B1 = TransferMechanism(name="B1", function=Linear(slope=3.0)) inner1.add_linear_processing_pathway([A1, B1]) inner2 = Composition(name="inner2") A2 = TransferMechanism(name="A2") B2 = TransferMechanism(name="B2") C2 = TransferMechanism(name="C2") inner2.add_nodes([A2, B2, C2]) outer1 = Composition(name="outer1") outer1.add_nodes([inner1, inner2]) # Spec 1: add projection *node in* inner1 --> inner 2 (implies first InputPort -- corresponding to A2) outer1.add_projection(sender=B1, receiver=inner2) # Spec 2: add projection *node in* inner1 --> *node in* inner2 outer1.add_projection(sender=B1, receiver=B2) # Spec 3: add projection inner1 --> *node in* inner2 outer1.add_projection(sender=inner1, receiver=C2) eid = "eid" outer1.run(inputs={inner1: [[1.]]}, context=eid) assert np.allclose(A1.parameters.value.get(eid), [[2.0]]) assert np.allclose(B1.parameters.value.get(eid), [[6.0]]) for node in [A2, B2, C2]: assert np.allclose(node.parameters.value.get(eid), [[6.0]])
def test_equivalance_of_threshold_and_termination_specifications_just_threshold( self, comp_mode): # Note: This tests the equivalence of using LCAMechanism-specific threshold arguments and # generic TransferMechanism termination_<*> arguments lca_thresh = LCAMechanism( size=2, leak=0.5, threshold=0.7) # Note: , execute_to_threshold=True by default response = ProcessingMechanism(size=2) comp = Composition() comp.add_linear_processing_pathway([lca_thresh, response]) result1 = comp.run(inputs={lca_thresh: [1, 0]}, execution_mode=comp_mode) lca_termination = LCAMechanism(size=2, leak=0.5, termination_threshold=0.7, termination_measure=max, termination_comparison_op='>=') comp2 = Composition() response2 = ProcessingMechanism(size=2) comp2.add_linear_processing_pathway([lca_termination, response2]) result2 = comp2.run(inputs={lca_termination: [1, 0]}, execution_mode=comp_mode) assert np.allclose(result1, result2)
def test_valid_mismatched_input_lens(self): A = ProcessingMechanism(name="A") B = ProcessingMechanism(name="B") C = ProcessingMechanism(name="C") comp = Composition(name="COMP") comp.add_linear_processing_pathway([A, C]) comp.add_linear_processing_pathway([B, C]) inputs_to_A = [[1.0]] # same (1.0) on every trial inputs_to_B = [[1.0], [2.0], [3.0], [4.0]] # increment on every trial results_A = [] results_B = [] results_C = [] def call_after_trial(): results_A.append(A.parameters.value.get(comp)) results_B.append(B.parameters.value.get(comp)) results_C.append(C.parameters.value.get(comp)) comp.run(inputs={ A: inputs_to_A, B: inputs_to_B }, call_after_trial=call_after_trial) assert np.allclose(results_A, [[[1.0]], [[1.0]], [[1.0]], [[1.0]]]) assert np.allclose(results_B, [[[1.0]], [[2.0]], [[3.0]], [[4.0]]]) assert np.allclose(results_C, [[[2.0]], [[3.0]], [[4.0]], [[5.0]]])
def test_LCAMechanism_length_2(self, benchmark, mode): # Note: since the LCAMechanism's threshold is not specified in this test, each execution only updates # the Mechanism once. T = TransferMechanism(function=Linear(slope=1.0), size=2) L = LCAMechanism(function=Linear(slope=2.0), size=2, self_excitation=3.0, leak=0.5, competition=1.0, time_step_size=0.1) C = Composition() C.add_linear_processing_pathway([T,L]) L.reset_stateful_function_when = Never() # - - - - - - - Equations to be executed - - - - - - - # new_transfer_input = # previous_transfer_input # + (leak * previous_transfer_input_1 + self_excitation * result1 + competition * result2 + outside_input1) * dt # + noise # result = new_transfer_input*2.0 # recurrent_matrix = [[3.0]] # - - - - - - - - - - - - - - - - - - - - - - - - - - C.run(inputs={T: [1.0, 2.0]}, num_trials=3, bin_execute=mode) # - - - - - - - TRIAL 1 - - - - - - - # new_transfer_input_1 = 0.0 + ( 0.5 * 0.0 + 3.0 * 0.0 - 1.0*0.0 + 1.0)*0.1 + 0.0 = 0.1 # f(new_transfer_input_1) = 0.1 * 2.0 = 0.2 # new_transfer_input_2 = 0.0 + ( 0.5 * 0.0 + 3.0 * 0.0 - 1.0*0.0 + 2.0)*0.1 + 0.0 = 0.2 # f(new_transfer_input_2) = 0.2 * 2.0 = 0.4 # - - - - - - - TRIAL 2 - - - - - - - # new_transfer_input = 0.1 + ( 0.5 * 0.1 + 3.0 * 0.2 - 1.0*0.4 + 1.0)*0.1 + 0.0 = 0.225 # f(new_transfer_input) = 0.265 * 2.0 = 0.45 # new_transfer_input_2 = 0.2 + ( 0.5 * 0.2 + 3.0 * 0.4 - 1.0*0.2 + 2.0)*0.1 + 0.0 = 0.51 # f(new_transfer_input_2) = 0.1 * 2.0 = 1.02 # - - - - - - - TRIAL 3 - - - - - - - # new_transfer_input = 0.225 + ( 0.5 * 0.225 + 3.0 * 0.45 - 1.0*1.02 + 1.0)*0.1 + 0.0 = 0.36925 # f(new_transfer_input) = 0.36925 * 2.0 = 0.7385 # new_transfer_input_2 = 0.51 + ( 0.5 * 0.51 + 3.0 * 1.02 - 1.0*0.45 + 2.0)*0.1 + 0.0 = 0.9965 # f(new_transfer_input_2) = 0.9965 * 2.0 = 1.463 assert np.allclose(C.results, [[[0.2, 0.4]], [[0.43, 0.98]], [[0.6705, 1.833]]]) if benchmark.enabled: benchmark(C.run, inputs={T: [1.0, 2.0]}, num_trials=3, bin_execute=mode)
def test_non_origin_partial_input_spec(self): A = ProcessingMechanism(name='A', function=Linear(slope=2.0)) B = ProcessingMechanism(name='B', input_states=[[0.], A.input_state]) comp = Composition(name='comp') comp.add_linear_processing_pathway([A, B]) comp.run(inputs={A: [[1.23]]}) assert np.allclose(B.get_input_values(comp), [[2.46], [1.23]])
def test_LCAMechanism_length_1(self): T = TransferMechanism(function=Linear(slope=1.0)) L = LCAMechanism( function=Linear(slope=2.0), self_excitation=3.0, leak=0.5, competition= 1.0, # competition does not matter because we only have one unit time_step_size=0.1) C = Composition() C.add_linear_processing_pathway([T, L]) L.reinitialize_when = Never() # - - - - - - - Equations to be executed - - - - - - - # new_transfer_input = # previous_transfer_input # + (leak * previous_transfer_input_1 + self_excitation * result1 + competition * result2 + outside_input1) * dt # + noise # result = new_transfer_input*2.0 # recurrent_matrix = [[3.0]] # - - - - - - - - - - - - - - - - - - - - - - - - - - results = [] def record_execution(): results.append(L.parameters.value.get(C)[0][0]) C.run(inputs={T: [1.0]}, num_trials=3, call_after_trial=record_execution) # - - - - - - - TRIAL 1 - - - - - - - # new_transfer_input = 0.0 + ( 0.5 * 0.0 + 3.0 * 0.0 + 0.0 + 1.0)*0.1 + 0.0 = 0.1 # f(new_transfer_input) = 0.1 * 2.0 = 0.2 # - - - - - - - TRIAL 2 - - - - - - - # new_transfer_input = 0.1 + ( 0.5 * 0.1 + 3.0 * 0.2 + 0.0 + 1.0)*0.1 + 0.0 = 0.265 # f(new_transfer_input) = 0.265 * 2.0 = 0.53 # - - - - - - - TRIAL 3 - - - - - - - # new_transfer_input = 0.265 + ( 0.5 * 0.265 + 3.0 * 0.53 + 0.0 + 1.0)*0.1 + 0.0 = 0.53725 # f(new_transfer_input) = 0.53725 * 2.0 = 1.0745 assert np.allclose(results, [0.2, 0.53, 1.0745])
def test_nested_composition_run_trials_inputs(benchmark, executions, mode): benchmark.group = "Nested Composition mutliple trials/inputs multirun {}".format( executions) # mechanisms A = ProcessingMechanism(name="A", function=AdaptiveIntegrator(rate=0.1)) B = ProcessingMechanism(name="B", function=Logistic) inner_comp = Composition(name="inner_comp") inner_comp.add_linear_processing_pathway([A, B]) inner_comp._analyze_graph() sched = Scheduler(composition=inner_comp) outer_comp = Composition(name="outer_comp") outer_comp.add_node(inner_comp) outer_comp._analyze_graph() sched = Scheduler(composition=outer_comp) # The input dict should assign inputs origin nodes (inner_comp in this case) var = {inner_comp: [[[2.0]], [[3.0]]]} expected = [[[0.549833997312478]], [[0.617747874769249]], [[0.6529428177055896]], [[0.7044959416252289]]] if executions > 1: var = [var for _ in range(executions)] if mode == 'Python': def f(v, num_trials, res=False): results = [] for i in range(executions): outer_comp.run(v[i], execution_id=i, num_trials=num_trials) if res: # copy the results immediately, otherwise it's empty results.append(outer_comp.results.copy()) return results res = f(var, 4, True) if executions > 1 else f([var], 4, True) benchmark(f if executions > 1 else outer_comp.run, var, num_trials=4) elif mode == 'LLVM': e = pnlvm.execution.CompExecution(outer_comp, [None for _ in range(executions)]) res = e.run(var, 4, 2) benchmark(e.run, var, 4, 2) elif mode == 'PTX': e = pnlvm.execution.CompExecution(outer_comp, [None for _ in range(executions)]) res = e.cuda_run(var, 4, 2) benchmark(e.cuda_run, var, 4, 2) assert np.allclose(res, [expected for _ in range(executions)]) assert len(res) == executions or executions == 1
def test_origin_input_source_true_no_input(self): A = ProcessingMechanism(name='A') B = ProcessingMechanism(name='B') C = ProcessingMechanism(name='C', default_variable=[[4.56]]) comp = Composition(name='comp') comp.add_linear_processing_pathway([A, B]) comp.add_node(C) comp.run(inputs={A: [[1.23]]}) assert np.allclose(A.parameters.value.get(comp), [[1.23]]) assert np.allclose(B.parameters.value.get(comp), [[1.23]]) assert np.allclose(C.parameters.value.get(comp), [[4.56]])
def test_one_to_two(self): A = ProcessingMechanism(name='A') B = ProcessingMechanism(name='B') C = ProcessingMechanism(name='C', input_states=[A.input_state]) comp = Composition(name='comp') comp.add_linear_processing_pathway([A, B]) comp.add_node(C) comp.run(inputs={A: [[1.23]]}) assert np.allclose(A.parameters.value.get(comp), [[1.23]]) assert np.allclose(B.parameters.value.get(comp), [[1.23]]) assert np.allclose(C.parameters.value.get(comp), [[1.23]])
def test_AtTrialStart(self): comp = Composition() A = TransferMechanism(name='A') B = TransferMechanism(name='B') comp.add_linear_processing_pathway([A, B]) sched = Scheduler(composition=comp) sched.add_condition(B, AtTrialStart()) termination_conds = {TimeScale.TRIAL: AtPass(3)} output = list(sched.run(termination_conds=termination_conds)) expected_output = [A, B, A, A] assert output == pytest.helpers.setify_expected_output( expected_output)
def test_LCAMechanism_length_1(self, benchmark, comp_mode): T = TransferMechanism(function=Linear(slope=1.0)) L = LCAMechanism( function=Linear(slope=2.0), self_excitation=3.0, leak=0.5, competition= 1.0, # competition does not matter because we only have one unit time_step_size=0.1) C = Composition() C.add_linear_processing_pathway([T, L]) L.reset_stateful_function_when = Never() # - - - - - - - Equations to be executed - - - - - - - # new_transfer_input = # previous_transfer_input # + (leak * previous_transfer_input_1 + self_excitation * result1 + competition * result2 + outside_input1) * dt # + noise # result = new_transfer_input*2.0 # recurrent_matrix = [[3.0]] # - - - - - - - - - - - - - - - - - - - - - - - - - - C.run(inputs={T: [1.0]}, num_trials=3, execution_mode=comp_mode) # - - - - - - - TRIAL 1 - - - - - - - # new_transfer_input = 0.0 + ( 0.5 * 0.0 + 3.0 * 0.0 + 0.0 + 1.0)*0.1 + 0.0 = 0.1 # f(new_transfer_input) = 0.1 * 2.0 = 0.2 # - - - - - - - TRIAL 2 - - - - - - - # new_transfer_input = 0.1 + ( 0.5 * 0.1 + 3.0 * 0.2 + 0.0 + 1.0)*0.1 + 0.0 = 0.265 # f(new_transfer_input) = 0.265 * 2.0 = 0.53 # - - - - - - - TRIAL 3 - - - - - - - # new_transfer_input = 0.265 + ( 0.5 * 0.265 + 3.0 * 0.53 + 0.0 + 1.0)*0.1 + 0.0 = 0.53725 # f(new_transfer_input) = 0.53725 * 2.0 = 1.0745 assert np.allclose(C.results, [[[0.2]], [[0.51]], [[0.9905]]]) if benchmark.enabled: benchmark(C.run, inputs={T: [1.0]}, num_trials=3, execution_mode=comp_mode)
def test_accumulator_as_function_of_matrix_param_of_mapping_projection(self): # Test that accumulator is function of parameter_port of mapping project, # and that its increment param works properly (used as modulatory param by LearningProjetion) T1 = TransferMechanism(size=3) T2 = TransferMechanism(size=3) M = MappingProjection(sender=T1, receiver=T2) C = Composition() C.add_linear_processing_pathway([T1, M, T2]) C.run(inputs={T1: [1.0, 1.0, 1.0]}) assert np.allclose(M.matrix.base, [[ 1., 0., 0.], [ 0., 1., 0.],[ 0., 0., 1.]]) M.parameter_ports[MATRIX].function.parameters.increment.set(2, C) C.run(inputs={T1: [1.0, 1.0, 1.0]}) assert np.allclose(M.matrix.base, [[ 3., 2., 2.], [ 2., 3., 2.], [ 2., 2., 3.]]) C.run(inputs={T1: [1.0, 1.0, 1.0]}) assert np.allclose(M.matrix.base, [[ 5., 4., 4.], [ 4., 5., 4.], [ 4., 4., 5.]])
def test_array_mode(self): input_mech = ProcessingMechanism(size=2) ddm = DDM(input_format=ARRAY, function=DriftDiffusionAnalytical(), output_ports=[SELECTED_INPUT_ARRAY, DECISION_VARIABLE_ARRAY], name='DDM') comp = Composition() comp.add_linear_processing_pathway(pathway=[input_mech, ddm]) result = comp.run(inputs={input_mech: [1, 0]}) assert np.allclose(ddm.output_ports[0].value, [1, 0]) assert np.allclose(ddm.output_ports[1].value, [1, 0]) assert np.allclose( ddm.value, [[1.00000000e+00], [1.19932930e+00], [9.99664650e-01], [3.35350130e-04], [1.19932930e+00], [2.48491374e-01], [1.48291009e+00], [1.19932930e+00], [2.48491374e-01], [1.48291009e+00]]) assert np.allclose(result, [[1., 0.]])
def test_invalid_mismatched_input_lens(self): A = ProcessingMechanism(name="A") B = ProcessingMechanism(name="B") C = ProcessingMechanism(name="C") comp = Composition(name="COMP") comp.add_linear_processing_pathway([A, C]) comp.add_linear_processing_pathway([B, C]) inputs_to_A = [[1.0], [2.0]] # 2 input specs inputs_to_B = [[1.0], [2.0], [3.0], [4.0]] # 4 input specs with pytest.raises(CompositionError) as error_text: comp.run(inputs={A: inputs_to_A, B: inputs_to_B}) assert "input dictionary for COMP contains input specifications of different lengths" in str( error_text.value)
def test_nested_composition_execution(benchmark, executions, mode): benchmark.group = "Nested Composition execution multirun {}".format( executions) # mechanisms A = ProcessingMechanism(name="A", function=AdaptiveIntegrator(rate=0.1)) B = ProcessingMechanism(name="B", function=Logistic) inner_comp = Composition(name="inner_comp") inner_comp.add_linear_processing_pathway([A, B]) inner_comp._analyze_graph() sched = Scheduler(composition=inner_comp) outer_comp = Composition(name="outer_comp") outer_comp.add_node(inner_comp) outer_comp._analyze_graph() sched = Scheduler(composition=outer_comp) # The input dict should assign inputs origin nodes (inner_comp in this case) var = {inner_comp: [[1.0]]} expected = [[0.52497918747894]] if executions > 1: var = [var for _ in range(executions)] if mode == 'Python': f = lambda x: [ outer_comp.execute(x[i], execution_id=i) for i in range(executions) ] res = f(var) if executions > 1 else outer_comp.execute(var) benchmark(f if executions > 1 else outer_comp.execute, var) elif mode == 'LLVM': e = pnlvm.execution.CompExecution(outer_comp, [None for _ in range(executions)]) e.execute(var) res = e.extract_node_output(outer_comp.output_CIM) benchmark(e.execute, var) elif mode == 'PTX': e = pnlvm.execution.CompExecution(outer_comp, [None for _ in range(executions)]) e.cuda_execute(var) res = e.extract_node_output(outer_comp.output_CIM) benchmark(e.cuda_execute, var) assert np.allclose(res, [expected for _ in range(executions)]) assert len(res) == executions
def test_parameter_CIM_routing_from_ControlMechanism(self): # Inner Composition ia = TransferMechanism(name='ia') ib = TransferMechanism(name='ib') icomp = Composition(name='icomp', pathways=[ia]) # Outer Composition ocomp = Composition(name='ocomp', pathways=[icomp]) cm = ControlMechanism( name='control_mechanism', control_signals=ControlSignal(projections=[(SLOPE, ib)])) icomp.add_linear_processing_pathway([ia, ib]) ocomp.add_linear_processing_pathway([cm, icomp]) res = ocomp.run([[2], [2], [2]]) assert np.allclose(res, [[4], [4], [4]]) assert len(ib.mod_afferents) == 1 assert ib.mod_afferents[0].sender == icomp.parameter_CIM.output_port assert icomp.parameter_CIM_ports[ib.parameter_ports['slope']][ 0].path_afferents[0].sender == cm.output_port
def test_accumulator_as_function_of_matrix_param_of_mapping_projection(self): # Test that accumulator is function of parameter_state of mapping project, # and that its increment param works properly (used as modulatory param by LearningProjetion) from psyneulink.core.components.projections.modulatory.learningprojection import LearningProjection # Note: use different sizes for T1 & T2 so as not to be assigned an IDENTITY_MATRIX, which doesn't use a matrix T1 = TransferMechanism(size=3) T2 = TransferMechanism(size=2) M = MappingProjection(sender=T1, receiver=T2) C = Composition() C.add_linear_processing_pathway([T1, M, T2]) C.run(inputs={T1: [1.0, 1.0, 1.0]}) assert np.allclose(M.matrix, [[ 1., 1.], [ 1., 1.], [1., 1.]]) M.parameter_states[MATRIX].function.parameters.increment.set(2, C) C.run(inputs={T1: [1.0, 1.0, 1.0]}) assert np.allclose(M.matrix, [[ 3., 3.], [ 3., 3.], [3., 3.]]) C.run(inputs={T1: [1.0, 1.0, 1.0]}) assert np.allclose(M.matrix, [[ 5., 5.], [ 5., 5.], [ 5., 5.]])
def test_alias_equivalence_for_modulates_and_projections(self): inputs = [1123, 941, 43, 311, 21] Tx1 = TransferMechanism() Ty1 = TransferMechanism() G1 = GatingMechanism(gating_signals=[GatingSignal(modulates=Tx1)]) comp1 = Composition() comp1.add_nodes([Tx1, Ty1, G1]) comp1.add_linear_processing_pathway([Tx1, Ty1, G1, Tx1]) comp1.run(inputs={Tx1: inputs}) Tx2 = TransferMechanism() Ty2 = TransferMechanism() G2 = GatingMechanism(gating_signals=[GatingSignal(projections=Tx2)]) comp2 = Composition() comp2.add_nodes([Tx2, Ty2, G2]) comp2.add_linear_processing_pathway([Tx2, Ty2, G2, Tx2]) comp2.run(inputs={Tx2: inputs}) assert comp1.results == comp2.results
def test_TimeInterval_linear_everynms(self, conditions, termination_conds): comp = Composition() comp.add_linear_processing_pathway([self.A, self.B, self.C]) comp.scheduler.add_condition_set(conditions) list(comp.scheduler.run(termination_conds=termination_conds)) for node, cond in conditions.items(): executions = [ comp.scheduler.execution_timestamps[ comp.default_execution_id][i].absolute for i in range( len(comp.scheduler.execution_list[ comp.default_execution_id])) if node in comp.scheduler.execution_list[comp.default_execution_id][i] ] for i in range(1, len(executions)): assert (executions[i] - executions[i - 1]) == cond.repeat
def test_equivalance_of_threshold_and_termination_specifications_max_vs_next(self): # Note: This tests the equivalence of using LCAMechanism-specific threshold arguments and # generic TransferMechanism termination_<*> arguments lca_thresh = LCAMechanism(size=3, leak=0.5, threshold=0.1, threshold_criterion=MAX_VS_NEXT) response = ProcessingMechanism(size=3) comp = Composition() comp.add_linear_processing_pathway([lca_thresh, response]) result1 = comp.run(inputs={lca_thresh:[1,0.5,0]}) lca_termination = LCAMechanism(size=3, leak=0.5, termination_threshold=0.1, termination_measure=max_vs_next, termination_comparison_op='>=') comp2 = Composition() response2 = ProcessingMechanism(size=3) comp2.add_linear_processing_pathway([lca_termination,response2]) result2 = comp2.run(inputs={lca_termination:[1,0.5,0]}) assert np.allclose(result1, result2)
def test_alias_equivalence_for_modulates_and_projections(self): inputs = [1, 9, 4, 3, 2] comp1 = Composition() tMech1 = TransferMechanism() tMech2 = TransferMechanism() cMech1 = ControlMechanism( control_signals=ControlSignal(modulates=(SLOPE, tMech2)), objective_mechanism=ObjectiveMechanism(monitor=(RESULT, tMech2))) comp1.add_nodes([tMech1, tMech2, cMech1]) comp1.add_linear_processing_pathway([cMech1, tMech1, tMech2]) comp1.run(inputs=inputs) comp2 = Composition() tMech3 = TransferMechanism() tMech4 = TransferMechanism() cMech2 = ControlMechanism( control_signals=ControlSignal(projections=(SLOPE, tMech4)), objective_mechanism=ObjectiveMechanism(monitor=(RESULT, tMech4))) comp2.add_nodes([tMech3, tMech4, cMech2]) comp2.add_linear_processing_pathway([cMech2, tMech3, tMech4]) comp2.run(inputs=inputs) assert comp1.results == comp2.results
def test_connect_outer_composition_to_only_input_node_in_inner_comp_option2( self): inner1 = Composition(name="inner") A1 = TransferMechanism(name="A1", function=Linear(slope=2.0)) B1 = TransferMechanism(name="B1", function=Linear(slope=3.0)) inner1.add_linear_processing_pathway([A1, B1]) inner2 = Composition(name="inner2") A2 = TransferMechanism(name="A2", function=Linear(slope=2.0)) B2 = TransferMechanism(name="B2", function=Linear(slope=3.0)) inner2.add_linear_processing_pathway([A2, B2]) outer = Composition(name="outer") outer.add_nodes([inner1, inner2]) outer.add_projection(sender=inner1, receiver=A2) # CRASHING WITH: FIX 6/1/20 # subprocess.CalledProcessError: Command '['dot', '-Tpdf', '-O', 'outer']' returned non-zero exit status 1. # outer.show_graph(show_node_structure=True, # show_nested=True) # comp1: input = 5.0 | mechA: 2.0*5.0 = 10.0 | mechB: 3.0*10.0 = 30.0 | output = 30.0 # comp2: input = 30.0 | mechA2: 2.0*30.0 = 60.0 | mechB2: 3.0*60.0 = 180.0 | output = 180.0 # comp3: input = 5.0 | output = 180.0 res = outer.run(inputs={inner1: [[5.]]}) assert np.allclose(res, [[[180.0]]]) assert np.allclose(inner1.output_port.parameters.value.get(outer), [30.0]) assert np.allclose(inner2.output_port.parameters.value.get(outer), [180.0]) assert np.allclose(outer.output_port.parameters.value.get(outer), [180.0])
def test_debug_comp(mode, debug_env): # save old debug env var old_env = os.environ.get("PNL_LLVM_DEBUG") if debug_env is not None: os.environ["PNL_LLVM_DEBUG"] = debug_env pnlvm.debug._update() comp = Composition() A = IntegratorMechanism(default_variable=1.0, function=Linear(slope=5.0)) B = TransferMechanism(function=Linear(slope=5.0), integrator_mode=True) comp.add_linear_processing_pathway([A, B]) inputs_dict = {A: [5]} output1 = comp.run(inputs=inputs_dict, execution_mode=mode) output2 = comp.run(inputs=inputs_dict, execution_mode=mode) # restore old debug env var and cleanup the debug configuration if old_env is None: del os.environ["PNL_LLVM_DEBUG"] else: os.environ["PNL_LLVM_DEBUG"] = old_env pnlvm.debug._update() assert len(comp.results) == 2 if "const_input=" in debug_env: expected1 = 87.5 expected2 = 131.25 elif "const_input" in debug_env: expected1 = 12.5 expected2 = 18.75 else: expected1 = 62.5 expected2 = 93.75 if "const_state" in debug_env: expected2 = expected1 assert np.allclose(expected1, output1[0][0]) assert np.allclose(expected2, output2[0][0])
def test_connect_outer_composition_to_only_input_node_in_inner_comp_option3( self): inner1 = Composition(name="inner") A1 = TransferMechanism(name="A1", function=Linear(slope=2.0)) B1 = TransferMechanism(name="B1", function=Linear(slope=3.0)) inner1.add_linear_processing_pathway([A1, B1]) inner2 = Composition(name="inner2") A2 = TransferMechanism(name="A2", function=Linear(slope=2.0)) B2 = TransferMechanism(name="B2", function=Linear(slope=3.0)) inner2.add_linear_processing_pathway([A2, B2]) outer = Composition(name="outer") outer.add_nodes([inner1, inner2]) outer.add_projection(sender=B1, receiver=A2) # comp1: input = 5.0 | mechA: 2.0*5.0 = 10.0 | mechB: 3.0*10.0 = 30.0 | output = 30.0 # comp2: input = 30.0 | mechA2: 2.0*30.0 = 60.0 | mechB2: 3.0*60.0 = 180.0 | output = 180.0 # comp3: input = 5.0 | output = 180.0 res = outer.run(inputs={inner1: [[5.]]}) assert np.allclose(res, [[[180.0]]]) assert np.allclose(inner1.output_port.parameters.value.get(outer), [30.0]) assert np.allclose(inner2.output_port.parameters.value.get(outer), [180.0]) assert np.allclose(outer.output_port.parameters.value.get(outer), [180.0])
def test_gating_with_UDF_with_composition(): def my_linear_fct(x, m=2.0, b=0.0, params={ pnl.ADDITIVE_PARAM: 'b', pnl.MULTIPLICATIVE_PARAM: 'm' }): return m * x + b def my_simple_linear_fct(x, m=1.0, b=0.0): return m * x + b def my_exp_fct( x, r=1.0, # b=pnl.CONTROL, b=0.0, params={ pnl.ADDITIVE_PARAM: 'b', pnl.MULTIPLICATIVE_PARAM: 'r' }): return x**r + b def my_sinusoidal_fct(input, phase=0, amplitude=1, params={ pnl.ADDITIVE_PARAM: 'phase', pnl.MULTIPLICATIVE_PARAM: 'amplitude' }): frequency = input[0] t = input[1] return amplitude * np.sin(2 * np.pi * frequency * t + phase) Input_Layer = pnl.TransferMechanism( name='Input_Layer', default_variable=np.zeros((2, )), function=psyneulink.core.components.functions.nonstateful. transferfunctions.Logistic) Output_Layer = pnl.TransferMechanism( name='Output_Layer', default_variable=[0, 0, 0], function=psyneulink.core.components.functions.nonstateful. transferfunctions.Linear, # function=pnl.Logistic, # output_ports={pnl.NAME: 'RESULTS USING UDF', # pnl.VARIABLE: [(pnl.OWNER_VALUE,0), pnl.TIME_STEP], # pnl.FUNCTION: my_sinusoidal_fct} output_ports={ pnl.NAME: 'RESULTS USING UDF', # pnl.VARIABLE: (pnl.OWNER_VALUE, 0), pnl.FUNCTION: psyneulink.core.components.functions.nonstateful.transferfunctions. Linear(slope=pnl.GATING) }) Gating_Mechanism = pnl.GatingMechanism( size=[1], gating_signals=[ # Output_Layer Output_Layer.output_port, ]) comp = Composition() comp.add_linear_processing_pathway(pathway=[Input_Layer, Output_Layer]) comp.add_node(Gating_Mechanism) stim_list = { Input_Layer: [[-1, 30], [-1, 30], [-1, 30], [-1, 30]], Gating_Mechanism: [[0.0], [0.5], [1.0], [2.0]] } comp.run(num_trials=4, inputs=stim_list) expected_results = [[np.array([0., 0., 0.])], [np.array([0.63447071, 0.63447071, 0.63447071])], [np.array([1.26894142, 1.26894142, 1.26894142])], [np.array([2.53788284, 2.53788284, 2.53788284])]] np.testing.assert_allclose(comp.results, expected_results)
def test_LCAMechanism_length_2(self): # Note: since the LCAMechanism's threshold is not specified in this test, each execution only updates # the Mechanism once. T = TransferMechanism(function=Linear(slope=1.0), size=2) L = LCAMechanism(function=Linear(slope=2.0), size=2, self_excitation=3.0, leak=0.5, competition=1.0, time_step_size=0.1) C = Composition() C.add_linear_processing_pathway([T, L]) L.reinitialize_when = Never() # - - - - - - - Equations to be executed - - - - - - - # new_transfer_input = # previous_transfer_input # + (leak * previous_transfer_input_1 + self_excitation * result1 + competition * result2 + outside_input1) * dt # + noise # result = new_transfer_input*2.0 # recurrent_matrix = [[3.0]] # - - - - - - - - - - - - - - - - - - - - - - - - - - results = [] def record_execution(): results.append(L.parameters.value.get(C)[0]) C.run(inputs={T: [1.0, 2.0]}, num_trials=3, call_after_trial=record_execution) # - - - - - - - TRIAL 1 - - - - - - - # new_transfer_input_1 = 0.0 + ( 0.5 * 0.0 + 3.0 * 0.0 - 1.0*0.0 + 1.0)*0.1 + 0.0 = 0.1 # f(new_transfer_input_1) = 0.1 * 2.0 = 0.2 # new_transfer_input_2 = 0.0 + ( 0.5 * 0.0 + 3.0 * 0.0 - 1.0*0.0 + 2.0)*0.1 + 0.0 = 0.2 # f(new_transfer_input_2) = 0.2 * 2.0 = 0.4 # - - - - - - - TRIAL 2 - - - - - - - # new_transfer_input = 0.1 + ( 0.5 * 0.1 + 3.0 * 0.2 - 1.0*0.4 + 1.0)*0.1 + 0.0 = 0.225 # f(new_transfer_input) = 0.265 * 2.0 = 0.45 # new_transfer_input_2 = 0.2 + ( 0.5 * 0.2 + 3.0 * 0.4 - 1.0*0.2 + 2.0)*0.1 + 0.0 = 0.51 # f(new_transfer_input_2) = 0.1 * 2.0 = 1.02 # - - - - - - - TRIAL 3 - - - - - - - # new_transfer_input = 0.225 + ( 0.5 * 0.225 + 3.0 * 0.45 - 1.0*1.02 + 1.0)*0.1 + 0.0 = 0.36925 # f(new_transfer_input) = 0.36925 * 2.0 = 0.7385 # new_transfer_input_2 = 0.51 + ( 0.5 * 0.51 + 3.0 * 1.02 - 1.0*0.45 + 2.0)*0.1 + 0.0 = 0.9965 # f(new_transfer_input_2) = 0.9965 * 2.0 = 1.463 assert np.allclose(results, [[0.2, 0.4], [0.45, 1.02], [0.7385, 1.993]])