def __init__( self, system: tc.optional(System_Base) = None, monitored_output_states=None, function=None, # control_signals:tc.optional(list) = None, control_signals=None, modulation: tc.optional( _is_modulation_param) = ModulationParam.MULTIPLICATIVE, params=None, name=None, prefs: is_pref_set = None): # Assign args to params and functionParams dicts params = self._assign_args_to_param_dicts( function=function, control_signals=control_signals, params=params) super().__init__( system=system, objective_mechanism=ObjectiveMechanism( monitored_output_states=monitored_output_states, function=DualAdaptiveIntegrator), control_signals=control_signals, modulation=modulation, params=params, name=name, prefs=prefs, ) self.objective_mechanism.name = self.name + '_ObjectiveMechanism' self.objective_mechanism._role = CONTROL
def test_converging_pathways(self): a = TransferMechanism(name="a", default_variable=[0, 0, 0]) b = TransferMechanism(name="b") c = TransferMechanism(name="c", default_variable=[0, 0, 0, 0, 0]) LC = LCControlMechanism(modulated_mechanisms=[a,b], objective_mechanism=ObjectiveMechanism(function=Linear, monitor=[b], name='lc_om'), name="lc" ) p = Process(name="p", pathway=[a, c]) p2 = Process(name="p2", pathway=[b, c]) s = System(name="s", processes=[p, p2]) a_label = s._get_label(a, ALL) b_label = s._get_label(b, ALL) c_label = s._get_label(c, ALL) assert "out (3)" in a_label and "in (3)" in a_label assert "out (1)" in b_label and "in (1)" in b_label assert "out (5)" in c_label and "in (5)" in c_label
def __init__( self, system: tc.optional(System_Base) = None, monitored_output_ports=None, function=None, # control_signals:tc.optional(list) = None, control_signals=None, modulation: tc.optional(str) = MULTIPLICATIVE, params=None, name=None, prefs: is_pref_set = None): super().__init__( system=system, objective_mechanism=ObjectiveMechanism( monitored_output_ports=monitored_output_ports, function=DualAdaptiveIntegrator), control_signals=control_signals, modulation=modulation, params=params, name=name, prefs=prefs, ) self.objective_mechanism.name = self.name + '_ObjectiveMechanism' self.objective_mechanism._role = CONTROL
def test_objective_mech_inputs_list_of_ints(self, benchmark, mech_mode): O = ObjectiveMechanism( name='O', default_variable=[0 for i in range(VECTOR_SIZE)], ) EX = pytest.helpers.get_mech_execution(O, mech_mode) val = benchmark(EX, [10.0 for i in range(VECTOR_SIZE)]) assert np.allclose(val, [[10.0 for i in range(VECTOR_SIZE)]])
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_objective_mech_inputs_list_of_ints(self, benchmark, mode): O = ObjectiveMechanism( name='O', default_variable=[0 for i in range(VECTOR_SIZE)], ) if mode == 'Python': EX = O.execute elif mode == 'LLVM': e = pnlvm.execution.MechExecution(O) EX = e.execute elif mode == 'PTX': e = pnlvm.execution.MechExecution(O) EX = e.cuda_execute val = benchmark(EX, [10.0 for i in range(VECTOR_SIZE)]) assert np.allclose(val, [[10.0 for i in range(VECTOR_SIZE)]])
def __init__(self, monitored_output_ports=None, function=None, # control_signals:tc.optional(tc.optional(list)) = None, control_signals= None, modulation:tc.optional(str)=None, params=None, name=None, prefs:is_pref_set=None): super().__init__( objective_mechanism=ObjectiveMechanism( monitored_output_ports=monitored_output_ports, function=DualAdaptiveIntegrator ), control_signals=control_signals, modulation=modulation, params=params, name=name, prefs=prefs, ) self.objective_mechanism.name = self.name + '_ObjectiveMechanism'
def test_predator_prey(benchmark, mode, samples): if len(samples) > 10 and mode not in {"LLVM", "LLVMRun", "Python-PTX"}: pytest.skip("This test takes too long") # OCM default mode is Python mode, ocm_mode = (mode + "-Python").split('-')[0:2] benchmark.group = "Predator-Prey " + str(len(samples)) obs_len = 3 obs_coords = 2 player_idx = 0 player_obs_start_idx = player_idx * obs_len player_value_idx = player_idx * obs_len + obs_coords player_coord_slice = slice(player_obs_start_idx,player_value_idx) predator_idx = 1 predator_obs_start_idx = predator_idx * obs_len predator_value_idx = predator_idx * obs_len + obs_coords predator_coord_slice = slice(predator_obs_start_idx,predator_value_idx) prey_idx = 2 prey_obs_start_idx = prey_idx * obs_len prey_value_idx = prey_idx * obs_len + obs_coords prey_coord_slice = slice(prey_obs_start_idx,prey_value_idx) player_len = prey_len = predator_len = obs_coords # Perceptual Mechanisms player_obs = ProcessingMechanism(size=prey_len, function=GaussianDistort, name="PLAYER OBS") prey_obs = ProcessingMechanism(size=prey_len, function=GaussianDistort, name="PREY OBS") predator_obs = TransferMechanism(size=predator_len, function=GaussianDistort, name="PREDATOR OBS") # Action Mechanism # Use ComparatorMechanism to compute direction of action as difference of coordinates between player and prey: # note: unitization is done in main loop, to allow compilation of LinearCombination function) (TBI) greedy_action_mech = ComparatorMechanism(name='ACTION',sample=player_obs,target=prey_obs) # Create Composition agent_comp = Composition(name='PREDATOR-PREY COMPOSITION') agent_comp.add_node(player_obs) agent_comp.add_node(predator_obs) agent_comp.add_node(prey_obs) agent_comp.add_node(greedy_action_mech) agent_comp.exclude_node_roles(predator_obs, NodeRole.OUTPUT) ocm = OptimizationControlMechanism(features={SHADOW_INPUTS: [player_obs, predator_obs, prey_obs]}, agent_rep=agent_comp, function=GridSearch(direction=MINIMIZE, save_values=True), objective_mechanism=ObjectiveMechanism(function=Distance(metric=NORMED_L0_SIMILARITY), monitor=[ player_obs, prey_obs ]), control_signals=[ControlSignal(modulates=(VARIANCE,player_obs), allocation_samples=samples), ControlSignal(modulates=(VARIANCE,predator_obs), allocation_samples=samples), ControlSignal(modulates=(VARIANCE,prey_obs), allocation_samples=samples) ], ) agent_comp.add_controller(ocm) agent_comp.enable_controller = True ocm.comp_execution_mode = ocm_mode input_dict = {player_obs:[[1.1576537, 0.60782117]], predator_obs:[[-0.03479106, -0.47666293]], prey_obs:[[-0.60836214, 0.1760381 ]], } run_results = agent_comp.run(inputs=input_dict, num_trials=2, bin_execute=mode) if len(samples) == 2: # KDM 12/4/19: modified results due to global seed offset of # GaussianDistort assignment. # to produce old numbers, run get_global_seed once before creating # each Mechanism with GaussianDistort above assert np.allclose(run_results[0], [[-10.06333025, 2.4845505 ]]) if mode == 'Python': assert np.allclose(ocm.feature_values, [[ 1.1576537, 0.60782117], [-0.03479106, -0.47666293], [-0.60836214, 0.1760381 ]]) if benchmark.enabled: benchmark(agent_comp.run, inputs=input_dict, bin_execute=mode)
def test_predator_prey(benchmark, mode, samples): benchmark.group = "Predator-Prey " + str(len(samples)) # These should probably be replaced by reference to ForagerEnv constants: obs_len = 3 obs_coords = 2 action_len = 2 player_idx = 0 player_obs_start_idx = player_idx * obs_len player_value_idx = player_idx * obs_len + obs_coords player_coord_slice = slice(player_obs_start_idx, player_value_idx) predator_idx = 1 predator_obs_start_idx = predator_idx * obs_len predator_value_idx = predator_idx * obs_len + obs_coords predator_coord_slice = slice(predator_obs_start_idx, predator_value_idx) prey_idx = 2 prey_obs_start_idx = prey_idx * obs_len prey_value_idx = prey_idx * obs_len + obs_coords prey_coord_slice = slice(prey_obs_start_idx, prey_value_idx) player_len = prey_len = predator_len = obs_coords # Perceptual Mechanisms player_obs = ProcessingMechanism(size=prey_len, function=GaussianDistort, name="PLAYER OBS") prey_obs = ProcessingMechanism(size=prey_len, function=GaussianDistort, name="PREY OBS") predator_obs = TransferMechanism(size=predator_len, function=GaussianDistort, name="PREDATOR OBS") # Action Mechanism # Use ComparatorMechanism to compute direction of action as difference of coordinates between player and prey: # note: unitization is done in main loop, to allow compilation of LinearCombination function) (TBI) greedy_action_mech = ComparatorMechanism(name='ACTION', sample=player_obs, target=prey_obs) # Create Composition agent_comp = Composition(name='PREDATOR-PREY COMPOSITION') agent_comp.add_node(player_obs) agent_comp.add_node(predator_obs) agent_comp.add_node(prey_obs) agent_comp.add_node(greedy_action_mech) # ControlMechanism ocm = OptimizationControlMechanism( features={SHADOW_INPUTS: [player_obs, predator_obs, prey_obs]}, agent_rep=agent_comp, function=GridSearch(direction=MINIMIZE, save_values=True), objective_mechanism=ObjectiveMechanism( function=Distance(metric=NORMED_L0_SIMILARITY), monitor=[player_obs, predator_obs, prey_obs]), control_signals=[ ControlSignal(modulates=(VARIANCE, player_obs), allocation_samples=samples), ControlSignal(modulates=(VARIANCE, predator_obs), allocation_samples=samples), ControlSignal(modulates=(VARIANCE, prey_obs), allocation_samples=samples), ], ) agent_comp.add_controller(ocm) agent_comp.enable_controller = True ocm.comp_execution_mode = mode input_dict = { player_obs: [[1.1576537, 0.60782117]], predator_obs: [[-0.03479106, -0.47666293]], prey_obs: [[-0.60836214, 0.1760381]], } run_results = agent_comp.run(inputs=input_dict, num_trials=2, bin_execute=mode) if len(samples) == 2: assert np.allclose(run_results[0], [[-19.06547277, 5.47274121]]) if mode == 'Python': assert np.allclose( ocm.feature_values, [[1.1576537, 0.60782117], [-0.03479106, -0.47666293], [-0.60836214, 0.1760381]]) benchmark(agent_comp.run, inputs=input_dict, bin_execute=mode)
def test_moving_average(mode): # Set an arbitrary seed and a global random state to keep the randomly generated quantities the same between runs seed = 20170530 # this will be separately given to ELFI np.random.seed(seed) # true parameters t1_true = 0.6 t2_true = 0.2 # Define a function that simulates a 2nd order moving average, assuming mean zero: # y_t = w_t + t1*w_t-1 + t2*w_t-2 # where t1 and t2 are real and w_k is i.i.d sequence white noise with N(0,1) def MA2(input=[0], t1=0.5, t2=0.5, n_obs=100, batch_size=1, random_state=None): # FIXME: Convert arguments to scalar if they are not. Why is this nescessary? # PsyNeuLink, when creating a user defined function, seems to expect the function # to support inputs of type np.ndarray even when they are only allowed to be # scalars. n_obs = n_obs[0] if (type(n_obs) is np.ndarray) else n_obs batch_size = batch_size[0] if ( type(batch_size) is np.ndarray) else batch_size # Make inputs 2d arrays for numpy broadcasting with w t1 = np.asanyarray(t1).reshape((-1, 1)) t2 = np.asanyarray(t2).reshape((-1, 1)) random_state = random_state or np.random w = random_state.randn(int(batch_size), int(n_obs) + 2) # i.i.d. sequence ~ N(0,1) x = w[:, 2:] + t1 * w[:, 1:-1] + t2 * w[:, :-2] return x # Lets make some observed data. This will be the data we try to fit parameters for. y_obs = MA2(t1=t1_true, t2=t2_true) # Make a processing mechanism out of our simulator. ma_mech = ProcessingMechanism(function=MA2, size=1, name='Moving Average (2nd Order)') # Now lets add it to a composition comp = Composition(name="Moving_Average") comp.add_node(ma_mech) # Now lets setup some control signals for the parameters we want to # infer. This is where we would like to specify priors. signalSearchRange = SampleSpec(start=0.1, stop=2.0, step=0.2) t1_control_signal = ControlSignal(projections=[('t1', ma_mech)], allocation_samples=signalSearchRange, cost_options=[], modulation=OVERRIDE) t2_control_signal = ControlSignal(projections=[('t2', ma_mech)], allocation_samples=signalSearchRange, cost_options=[], modulation=OVERRIDE) # A function to calculate the auto-covariance with specific lag for a # time series. We will use this function to compute the summary statistics # for generated and observed data so that we can compute a metric between the # two. In PsyNeuLink terms, this will be part of an ObjectiveMechanism. def autocov(agent_rep, x=None, lag=1): if x is None: return np.asarray(0.0) C = np.mean(x[:, lag:] * x[:, :-lag], axis=1) return C # # Lets make one function that computes all the summary stats in one go because PsyNeuLink # # objective mechanism expect a single function. # def objective_function(x): # return np.concatenate((autocov(x), autocov(x, lag=2))) # # # Objective Mechanism and its function currently need to be specified in the script. # # (In future versions, this will be set up automatically) # objective_mech = ObjectiveMechanism(function=objective_function, # monitor=[ma_mech]) # Setup the controller with the ParamEstimationFunction if mode == 'elfi': comp.add_controller(controller=OptimizationControlMechanism( agent_rep=comp, function=ParamEstimationFunction( priors={ 't1': (scipy.stats.uniform, 0, 2), 't2': (scipy.stats.uniform, 0, 2) }, observed=y_obs, summary=[(autocov, 1), (autocov, 2)], discrepancy='euclidean', n_samples=3, quantile=0.01, # Set very small now cause things are slow. seed=seed), objective_mechanism=False, control_signals=[t1_control_signal, t2_control_signal])) elif mode == 'GridSearch': observed_C = np.array( [autocov(None, y_obs, 1), autocov(None, y_obs, 2)]) def objective_f(val): C = np.array([autocov(None, val, 1), autocov(None, val, 2)]) ret = np.linalg.norm(C - observed_C) return ret objective_mech = ObjectiveMechanism(function=objective_f, size=len(y_obs[0]), monitor=[ma_mech], name='autocov - observed autocov') comp.add_controller(controller=OptimizationControlMechanism( agent_rep=comp, function=GridSearch(save_values=True, direction=MINIMIZE), objective_mechanism=objective_mech, control_signals=[t1_control_signal, t2_control_signal])) comp.disable_all_history() # Lets setup some input to the mechanism, not that it uses it for anything. stim_list_dict = {ma_mech: [0]} # # FIXME: Show graph fails when the controller doesn't have an objective mechanism. # comp.show_graph(show_controller=True, # show_projection_labels=True, # show_node_structure=True, # show_cim=True, # show_dimensions=True) comp.run(inputs=stim_list_dict) if mode == 'elfi': assert np.allclose(comp.controller.value, [[0.5314349], [0.19140103]]) if mode == 'GridSearch': assert np.allclose(comp.controller.value, [[0.5], [0.3]])