Skip to content

Commit

Permalink
Merge pull request #1970 from PrincetonUniversity/devel
Browse files Browse the repository at this point in the history
Devel
  • Loading branch information
kmantel authored Mar 26, 2021
2 parents d105add + dc9b662 commit 0d56d0f
Show file tree
Hide file tree
Showing 20 changed files with 723 additions and 366 deletions.
2 changes: 1 addition & 1 deletion dev_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ jupyter<=1.0.0
pytest<6.2.3
pytest-benchmark<=3.2.3
pytest-cov<2.11.2
pytest-helpers-namespace<=2019.1.8
pytest-helpers-namespace<2021.3.25
pytest-profiling<=1.7.0
pytest-pycodestyle<=2.2.0
pytest-pydocstyle<=2.2.0
Expand Down
16 changes: 16 additions & 0 deletions psyneulink/core/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,9 @@ def __init__(self,
# - assign function's output to self.defaults.value (based on call of self.execute)
self._instantiate_function(function=function, function_params=function_params, context=context)

# FIX TIME 3/18/21
if '(RESULT) to (OUTPUT_CIM_TransferMechanism-1_RESULT)' in self.name:
assert True
self._instantiate_value(context=context)

# INSTANTIATE ATTRIBUTES AFTER FUNCTION
Expand Down Expand Up @@ -3196,6 +3199,10 @@ def fill_recursively(arr, value, indices=()):

var = convert_all_elements_to_np_array(copy.deepcopy(var), cast_from=int, cast_to=float)

# ignore zero-length variables (e.g. empty Buffer)
if var.shape == (0, ):
return var

# handle simple wrapping of a Component (e.g. from ParameterPort in
# case of set after Component instantiation)
if (
Expand Down Expand Up @@ -3223,6 +3230,15 @@ def fill_recursively(arr, value, indices=()):
except AttributeError:
pass

try:
# try to broadcast param to variable if param is numeric and regular
param_arr = np.asarray(param)
if param_arr.dtype != object:
return np.broadcast_to(param_arr, var.shape)
except ValueError:
# param not directly compatible with variable, continue elementwise
pass

fill_recursively(var, param)
return var

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
MULTIPLICATIVE_PARAM, NOISE, OFFSET, OPERATION, ORNSTEIN_UHLENBECK_INTEGRATOR_FUNCTION, OUTPUT_PORTS, PRODUCT, \
RATE, REST, SIMPLE_INTEGRATOR_FUNCTION, SUM, TIME_STEP_SIZE, THRESHOLD, VARIABLE
from psyneulink.core.globals.parameters import Parameter
from psyneulink.core.globals.utilities import parameter_spec, all_within_range, iscompatible, get_global_seed
from psyneulink.core.globals.utilities import parameter_spec, all_within_range, iscompatible, get_global_seed, convert_all_elements_to_np_array
from psyneulink.core.globals.context import Context, ContextFlags, handle_external_context
from psyneulink.core.globals.preferences.basepreferenceset import is_pref_set

Expand Down Expand Up @@ -372,7 +372,11 @@ def _gen_llvm_function_body(self, ctx, builder, params, state, arg_in, arg_out,
# Get rid of 2d array.
# When part of a Mechanism, the input and output are 2d arrays.
arg_in = pnlvm.helpers.unwrap_2d_array(builder, arg_in)
arg_out = pnlvm.helpers.unwrap_2d_array(builder, arg_out)

# output may be 2d with multiple items (e.g. DriftDiffusionIntegrator,
# FitzHughNagumoIntegrator)
if arg_out.type.pointee.count == 1:
arg_out = pnlvm.helpers.unwrap_2d_array(builder, arg_out)

with pnlvm.helpers.array_ptr_loop(builder, arg_in, "integrate") as args:
self._gen_llvm_integrate(*args, ctx, arg_in, arg_out, params, state)
Expand Down Expand Up @@ -2377,6 +2381,12 @@ class Parameters(IntegratorFunction.Parameters):
read_only=True
)

def _parse_initializer(self, initializer):
if initializer.ndim > 1:
return np.atleast_1d(initializer.squeeze())
else:
return initializer

@tc.typecheck
def __init__(self,
default_variable=None,
Expand Down Expand Up @@ -2419,6 +2429,9 @@ def _validate_noise(self, noise):
"Invalid noise parameter for {}: {}. DriftDiffusionIntegrator requires noise parameter to be a float or float array."
" Noise parameter is used to construct the standard DDM noise distribution".format(self.name, type(noise)))

def _initialize_previous_value(self, initializer, context=None):
return super()._initialize_previous_value(self.parameters._parse_initializer(initializer), context)

def _function(self,
variable=None,
context=None,
Expand Down Expand Up @@ -2451,7 +2464,8 @@ def _function(self,
time_step_size = self._get_current_parameter_value(TIME_STEP_SIZE, context)
random_state = self._get_current_parameter_value("random_state", context)

previous_value = np.atleast_2d(self.parameters.previous_value._get(context))
variable = self.parameters._parse_initializer(variable)
previous_value = self.parameters.previous_value._get(context)

random_draw = np.array([random_state.normal() for _ in list(variable)])
value = previous_value + rate * variable * time_step_size \
Expand All @@ -2466,16 +2480,11 @@ def _function(self,
if not self.is_initializing:
previous_value = adjusted_value
previous_time = previous_time + time_step_size
if not np.isscalar(variable):
previous_time = np.broadcast_to(
previous_time,
variable.shape
).copy()

self.parameters.previous_time._set(previous_time, context)

self.parameters.previous_value._set(previous_value, context)
return previous_value, previous_time
return convert_all_elements_to_np_array([previous_value, previous_time])

def _gen_llvm_integrate(self, builder, index, ctx, vi, vo, params, state):
# Get parameter pointers
Expand All @@ -2502,8 +2511,7 @@ def _gen_llvm_integrate(self, builder, index, ctx, vi, vo, params, state):

# value = previous_value + rate * variable * time_step_size \
# + np.sqrt(time_step_size * noise) * random_state.normal()
prev_val_ptr = builder.gep(prev_ptr, [ctx.int32_ty(0),
ctx.int32_ty(0), index])
prev_val_ptr = builder.gep(prev_ptr, [ctx.int32_ty(0), index])
prev_val = builder.load(prev_val_ptr)
val = builder.load(builder.gep(vi, [ctx.int32_ty(0), index]))
if isinstance(val.type, pnlvm.ir.ArrayType):
Expand All @@ -2526,7 +2534,7 @@ def _gen_llvm_integrate(self, builder, index, ctx, vi, vo, params, state):
val = pnlvm.helpers.fclamp(builder, val, neg_threshold, threshold)

# Store value result
data_vo_ptr = builder.gep(vo, [ctx.int32_ty(0), ctx.int32_ty(0),
data_vo_ptr = builder.gep(vo, [ctx.int32_ty(0),
ctx.int32_ty(0), index])
builder.store(val, data_vo_ptr)
builder.store(val, prev_val_ptr)
Expand Down
23 changes: 11 additions & 12 deletions psyneulink/core/components/mechanisms/mechanism.py
Original file line number Diff line number Diff line change
Expand Up @@ -2540,19 +2540,18 @@ def execute(self,
# Use report_output and report_params options passed to execute from Composition or command line;
# otherwise try to get from Mechanism's reportOutputPref
report_output = report_output or next((pref for pref in convert_to_list(self.prefs.reportOutputPref)
if isinstance(pref, ReportOutput)), None)
if isinstance(pref, ReportOutput)), ReportOutput.OFF)
report_params = report_params or next((pref for pref in convert_to_list(self.prefs.reportOutputPref)
if isinstance(pref, ReportParams)), None)
if report_output is not ReportOutput.OFF:
with Report(self, context=context) as report:
report.report_output(caller=self,
report_num=run_report,
scheduler=None,
report_output=report_output,
report_params=report_params,
content='node',
context=context,
node=self)
if isinstance(pref, ReportParams)), ReportParams.OFF)
with Report(self, context=context) as report:
report.report_output(caller=self,
report_num=run_report,
scheduler=None,
report_output=report_output,
report_params=report_params,
content='node',
context=context,
node=self)

return value

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@
import numpy as np
import threading
import typecheck as tc
import uuid
import warnings

from psyneulink.core import llvm as pnlvm
Expand Down Expand Up @@ -1758,7 +1759,7 @@ def _sim_count_lock(self):
self.__sim_count_lock = threading.Lock()
return self.__sim_count_lock

def get_next_sim_id(self, context):
def get_next_sim_id(self, context, allocation=None):
with self._sim_count_lock:
try:
sim_num = self._sim_counts[context.execution_id]
Expand All @@ -1767,7 +1768,20 @@ def get_next_sim_id(self, context):
sim_num = 0
self._sim_counts[context.execution_id] = 1

return '{0}{1}-{2}'.format(context.execution_id, EID_SIMULATION, sim_num)
try:
# should always be called when a composition defined here,
# but just in case
composition = context.composition.name
except AttributeError:
composition = None

# NOTE: anything in square brackets is removed from
# rich/console/reporting Report.report_output
return (
f'{context.execution_id}{EID_SIMULATION}'
f'{{simulator: {composition}, num: {sim_num},'
f' allocation: {allocation}, uuid: {uuid.uuid4()}}}'
)

@property
def _dependent_components(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
**Expected Value of Control**
The `net_outcome <ControlMechanism.net_outcome>` of an OptmizationControlMechanism, like any `ControlMechanism`
The `net_outcome <ControlMechanism.net_outcome>` of an OptimizationControlMechanism, like any `ControlMechanism`
is computed as the difference between the `outcome <ControlMechanism.outcome>` computed by its `objective_mechanism
<ControlMechanism.objective_mechanism>` and the `costs <ControlMechanism.costs>` of its `control_signals
<ControlMechanism.control_signals>` for a given `state <OptimizationControlMechanism_State>` (i.e.,
Expand Down Expand Up @@ -971,10 +971,7 @@ def _get_frozen_context(self, context=None):

def _set_up_simulation(self, base_context=Context(execution_id=None), control_allocation=None):
sim_context = copy.copy(base_context)
sim_context.execution_id = self.get_next_sim_id(base_context)

if control_allocation is not None:
sim_context.execution_id += f'-{control_allocation}'
sim_context.execution_id = self.get_next_sim_id(base_context, control_allocation)

try:
self.parameters.simulation_ids._get(base_context).append(sim_context.execution_id)
Expand Down
Loading

0 comments on commit 0d56d0f

Please sign in to comment.