Skip to content

Commit aabefef

Browse files
authored
Merge pull request #1915 from PrincetonUniversity/devel
Devel
2 parents 5bc0cf5 + 53363f7 commit aabefef

File tree

26 files changed

+723
-399
lines changed

26 files changed

+723
-399
lines changed

.github/workflows/pnl-ci-docs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
echo ::set-output name=pip_cache_dir::$(python -m pip cache dir)
4747
4848
- name: Wheels cache
49-
uses: actions/cache@v2.1.3
49+
uses: actions/cache@v2.1.4
5050
with:
5151
path: ${{ steps.pip_cache.outputs.pip_cache_dir }}/wheels
5252
key: ${{ runner.os }}-python-${{ matrix.python-version }}-${{ matrix.python-architecture }}-pip-wheels-v2-${{ github.sha }}

.github/workflows/pnl-ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
echo ::set-output name=pip_cache_dir::$(python -m pip cache dir)
4747
4848
- name: Wheels cache
49-
uses: actions/cache@v2.1.3
49+
uses: actions/cache@v2.1.4
5050
with:
5151
path: ${{ steps.pip_cache.outputs.pip_cache_dir }}/wheels
5252
key: ${{ runner.os }}-python-${{ matrix.python-version }}-${{ matrix.python-architecture }}-pip-wheels-v2-${{ github.sha }}

Scripts/Debug/Hebbian_Simon.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import psyneulink as pnl
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
#sample Hebb
5+
6+
FeatureNames=['small','medium','large','red','yellow','blue','circle','rectangle','triangle']
7+
8+
# create a variable that corresponds to the size of our feature space
9+
sizeF = len(FeatureNames)
10+
small_red_circle = [1,0,0,1,0,0,1,0,0]
11+
src = small_red_circle
12+
13+
14+
Hebb_comp = pnl.Composition()
15+
16+
Hebb_mech=pnl.RecurrentTransferMechanism(
17+
size=sizeF,
18+
function=pnl.Linear,
19+
#integrator_mode = True,
20+
#integration_rate = 0.5,
21+
enable_learning = True,
22+
learning_rate = .1,
23+
name='Hebb_mech',
24+
#matrix=pnl.AutoAssociativeProjection,
25+
auto=0,
26+
hetero=0
27+
)
28+
29+
Hebb_comp.add_node(Hebb_mech)
30+
31+
Hebb_comp.execution_id = 1
32+
33+
# Use print_info to show numerical values and vis_info to show graphs of the changing values
34+
35+
def print_info():
36+
print('\nWeight matrix:\n', Hebb_mech.matrix.base, '\nActivity: ', Hebb_mech.value)
37+
38+
39+
def vis_info():
40+
ub=1#np.amax(np.amax(np.abs(Hebb_mech.matrix.modulated)))
41+
lb=-ub
42+
plt.figure()
43+
plt.imshow(Hebb_mech.matrix.modulated,cmap='RdBu_r',vmin=lb,vmax=ub)
44+
plt.title('PNL Hebbian Matrix')
45+
plt.xticks(np.arange(0,sizeF),FeatureNames,rotation=35)
46+
plt.yticks(np.arange(0,sizeF),FeatureNames,rotation=35)
47+
48+
plt.colorbar()
49+
plt.show()
50+
51+
plt.figure()
52+
plt.stem(Hebb_mech.value[0])
53+
plt.title('Activation from Stimulus with PNL Hebbian Matrix')
54+
plt.xticks(np.arange(0,sizeF),FeatureNames,rotation=35)
55+
plt.xlabel('Feature')
56+
plt.ylabel('Activation')
57+
plt.show()
58+
59+
inputs_dict = {Hebb_mech:np.array(src)}
60+
out=Hebb_comp.learn(num_trials=5,
61+
# call_after_trial=vis_info,
62+
inputs=inputs_dict)
63+
64+
print_info()

docs/source/Core.rst

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ Core
1212
- `CompositionFunctionApproximator`
1313

1414
* `Services`
15-
- `Visualization`
16-
- `Log`
1715
- `Registry`
1816
- `Preferences`
19-
- `json`
17+
- `Visualization`
18+
- `Scheduling`
2019
- `Compilation`
20+
- `Log`
21+
- `json`

docs/source/Mechanisms.rst

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
Mechanisms
22
==========
33

4-
.. toctree::
5-
:maxdepth: 3
6-
74
.. container:: subclasses
8-
*Subclasses*
9-
ProcessingMechanisms
10-
ModulatoryMechanisms
5+
6+
.. toctree::
7+
:maxdepth: 3
8+
9+
*Subclasses:*
10+
ProcessingMechanisms
11+
ModulatoryMechanisms

docs/source/Preferences.rst

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ Standard prefereces:
77

88
- paramValidation (bool): enables/disables run-time validation of the execute method of a Function object
99

10-
- reportOutput ([bool, str]): enables/disables reporting of execution of execute method:
11-
True prints input/output, 'params' or 'parameters' includes parameter values
10+
- reportOutput ([bool, str]): enables/disables reporting execution of `Component`\'s `execute <Component_Execution>`
11+
method to console:
12+
- ``True``: prints record of execution, including the input and output of the Component;
13+
- 'params' or 'parameters': includes report of the Component's `parameter <Parameters>` values.
14+
- 'terse': (Composition only) restricts output to just a listing of `trials <TimeScale.TRIAL>`, `time_steps
15+
<TimeScale.TIME_STEP>` and `nodes <Composition_Nodes>` executed.
1216

1317
- log (bool): sets LogCondition for a given Component
1418

psyneulink/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
from .core import *
3232
from .library import *
3333

34+
# from rich import print, box
35+
# print("Initializing...")
36+
3437
_pnl_global_names = [
3538
'primary_registries', 'System', 'Process'
3639
]

psyneulink/core/components/component.py

+10-18
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@
338338
Execution
339339
---------
340340
341-
A Component is executed when its `execute` method is called, which in turn calls its `function <Component_Function>`.
341+
A Component is executed when its `execute <Component.execute>` method is called, which in turn calls its `function
342+
<Component_Function>`.
342343
343344
.. _Component_Lazy_Updating:
344345
@@ -486,7 +487,6 @@
486487
import itertools
487488
import logging
488489
import numbers
489-
import toposort
490490
import types
491491
import warnings
492492

@@ -2024,7 +2024,7 @@ def _is_user_specified(parameter):
20242024
else:
20252025
param_defaults[p.source.name] = param_defaults[p.name]
20262026

2027-
for p in filter(lambda x: not isinstance(x, (ParameterAlias, SharedParameter)), self.parameters):
2027+
for p in filter(lambda x: not isinstance(x, (ParameterAlias, SharedParameter)), self.parameters._in_dependency_order):
20282028
# copy spec so it is not overwritten later
20292029
# TODO: check if this is necessary
20302030
p.spec = copy_parameter_value(p.spec)
@@ -2085,19 +2085,8 @@ def _instantiate_parameter_classes(self, context=None):
20852085
"""
20862086
from psyneulink.core.components.shellclasses import Function
20872087

2088-
parameter_function_ordering = list(toposort.toposort({
2089-
p.name: p.dependencies for p in self.parameters if p.dependencies is not None
2090-
}))
2091-
parameter_function_ordering = list(itertools.chain.from_iterable(parameter_function_ordering))
2092-
2093-
def ordering(p):
2094-
try:
2095-
return parameter_function_ordering.index(p.name)
2096-
except ValueError:
2097-
return -1
2098-
20992088
# (this originally occurred in _validate_params)
2100-
for p in sorted(self.parameters, key=ordering):
2089+
for p in self.parameters._in_dependency_order:
21012090
if p.getter is None:
21022091
val = p._get(context)
21032092
if (
@@ -2188,7 +2177,7 @@ def _create_justified_line(k, v, error_line_len=110):
21882177
self._override_unspecified_shared_parameters(context)
21892178

21902179
def _override_unspecified_shared_parameters(self, context):
2191-
for param_name, param in self.parameters.values(show_all=True).items():
2180+
for param in self.parameters._in_dependency_order:
21922181
if (
21932182
isinstance(param, SharedParameter)
21942183
and not isinstance(param.source, ParameterAlias)
@@ -2984,7 +2973,7 @@ def _update_default_variable(self, new_default_variable, context=None):
29842973
)
29852974
self._instantiate_value(context)
29862975

2987-
for p in self.parameters:
2976+
for p in self.parameters._in_dependency_order:
29882977
val = p._get(context)
29892978
if (
29902979
not p.reference
@@ -3028,6 +3017,9 @@ def reset(self, *args, context=None, **kwargs):
30283017

30293018
@handle_external_context()
30303019
def execute(self, variable=None, context=None, runtime_params=None):
3020+
"""Executes Component's `function <Component_Function>`. See Component-specific execute method for details.
3021+
"""
3022+
30313023
if context is None:
30323024
try:
30333025
context = self.owner.most_recent_context
@@ -3102,7 +3094,7 @@ def _execute(self, variable=None, context=None, runtime_params=None, **kwargs):
31023094

31033095
def is_finished(self, context=None):
31043096
"""
3105-
set by a Component to signal completion of its `execution <Component_Execution>` in a `TRIAL
3097+
Set by a Component to signal completion of its `execution <Component_Execution>` in a `TRIAL
31063098
<TimeScale.TRIAL>`; used by `Component-based Conditions <Conditions_Component_Based>` to predicate the
31073099
execution of one or more other Components on a Component.
31083100
"""

psyneulink/core/components/functions/optimizationfunctions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ def _gen_llvm_select_min_function(self, *, ctx:pnlvm.LLVMBuilderContext, tags:fr
14591459

14601460
# KDM 8/22/19: nonstateful direction here - OK?
14611461
direction = "<" if self.direction == MINIMIZE else ">"
1462-
replace_ptr = builder.alloca(pnlvm.ir.IntType(1))
1462+
replace_ptr = builder.alloca(ctx.bool_ty)
14631463

14641464
# Check the value against current min
14651465
with pnlvm.helpers.for_loop_zero_inc(builder, count, "compare_loop") as (b, idx):

psyneulink/core/components/functions/statefulfunctions/memoryfunctions.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ def _gen_llvm_function_body(self, ctx, builder, params, state, arg_in, arg_out,
780780
out_val_ptr = builder.gep(arg_out, [ctx.int32_ty(0), ctx.int32_ty(1)])
781781

782782
# Check retrieval probability
783-
retr_ptr = builder.alloca(pnlvm.ir.IntType(1))
783+
retr_ptr = builder.alloca(ctx.bool_ty)
784784
builder.store(retr_ptr.type.pointee(1), retr_ptr)
785785
retr_prob_ptr = pnlvm.helpers.get_param_ptr(builder, self, params, RETRIEVAL_PROB)
786786

@@ -844,7 +844,7 @@ def _gen_llvm_function_body(self, ctx, builder, params, state, arg_in, arg_out,
844844
builder.store(selected_val, out_val_ptr)
845845

846846
# Check storage probability
847-
store_ptr = builder.alloca(pnlvm.ir.IntType(1))
847+
store_ptr = builder.alloca(ctx.bool_ty)
848848
builder.store(store_ptr.type.pointee(1), store_ptr)
849849
store_prob_ptr = pnlvm.helpers.get_param_ptr(builder, self, params, STORAGE_PROB)
850850

@@ -866,14 +866,14 @@ def _gen_llvm_function_body(self, ctx, builder, params, state, arg_in, arg_out,
866866
with builder.if_then(store, likely=True):
867867

868868
# Check if such key already exists
869-
is_new_key_ptr = builder.alloca(pnlvm.ir.IntType(1))
869+
is_new_key_ptr = builder.alloca(ctx.bool_ty)
870870
builder.store(is_new_key_ptr.type.pointee(1), is_new_key_ptr)
871871
with pnlvm.helpers.for_loop_zero_inc(builder, entries, "distance_loop") as (b,idx):
872872
cmp_key_ptr = b.gep(keys_ptr, [ctx.int32_ty(0), idx])
873873

874874
# Vector compare
875875
# TODO: move this to helpers
876-
key_differs_ptr = b.alloca(pnlvm.ir.IntType(1))
876+
key_differs_ptr = b.alloca(ctx.bool_ty)
877877
b.store(key_differs_ptr.type.pointee(0), key_differs_ptr)
878878
with pnlvm.helpers.array_ptr_loop(b, cmp_key_ptr, "key_compare") as (b2, idx2):
879879
var_key_element = b2.gep(var_key_ptr, [ctx.int32_ty(0), idx2])

psyneulink/core/components/mechanisms/mechanism.py

+15-79
Original file line numberDiff line numberDiff line change
@@ -2532,13 +2532,18 @@ def execute(self,
25322532
if not self.parameters.execute_until_finished._get(context):
25332533
break
25342534

2535-
# REPORT EXECUTION
2536-
if self.prefs.reportOutputPref and (context.execution_phase & ContextFlags.PROCESSING | ContextFlags.LEARNING):
2537-
self._report_mechanism_execution(
2538-
self.get_input_values(context),
2539-
output=self.output_port.parameters.value._get(context),
2540-
context=context
2541-
)
2535+
# REPORT EXECUTION if called from command line
2536+
# If called by a Composition, it handles reporting.
2537+
if context.source == ContextFlags.COMMAND_LINE:
2538+
if self.prefs.reportOutputPref and (context.execution_phase & ContextFlags.PROCESSING | ContextFlags.LEARNING):
2539+
from psyneulink.core.compositions.composition import _report_node_execution
2540+
from rich import print
2541+
print(
2542+
_report_node_execution(self,
2543+
input_val=self.get_input_values(context),
2544+
output_val=self.output_port.parameters.value._get(context),
2545+
context=context)
2546+
)
25422547

25432548
return value
25442549

@@ -2965,7 +2970,7 @@ def _gen_llvm_invoke_function(self, ctx, builder, function, params, state, varia
29652970
return fun_out, builder
29662971

29672972
def _gen_llvm_is_finished_cond(self, ctx, builder, params, state):
2968-
return pnlvm.ir.IntType(1)(1)
2973+
return ctx.bool_ty(1)
29692974

29702975
def _gen_llvm_mechanism_functions(self, ctx, builder, params, state, arg_in,
29712976
ip_output, *, tags:frozenset):
@@ -3043,8 +3048,7 @@ def _gen_llvm_function(self, *, extra_args=[], ctx:pnlvm.LLVMBuilderContext, tag
30433048
ctx.get_input_struct_type(self).as_pointer(),
30443049
ctx.get_output_struct_type(self).as_pointer()]
30453050

3046-
builder = ctx.create_llvm_function(args, self,
3047-
return_type=pnlvm.ir.IntType(1),
3051+
builder = ctx.create_llvm_function(args, self, return_type=ctx.bool_ty,
30483052
tags=tags)
30493053
params, state = builder.function.args[:2]
30503054
finished = self._gen_llvm_is_finished_cond(ctx, builder, params, state)
@@ -3083,7 +3087,7 @@ def _gen_llvm_function_body(self, ctx, builder, params, state, arg_in, arg_out,
30833087
args_t = [a.type for a in builder.function.args]
30843088
internal_builder = ctx.create_llvm_function(args_t, self,
30853089
name=builder.function.name + "_internal",
3086-
return_type=pnlvm.ir.IntType(1))
3090+
return_type=ctx.bool_ty)
30873091
iparams, istate, iin, iout = internal_builder.function.args[:4]
30883092
internal_builder, is_finished = self._gen_llvm_function_internal(ctx, internal_builder,
30893093
iparams, istate, iin, iout, tags=tags)
@@ -3131,74 +3135,6 @@ def _gen_llvm_function_body(self, ctx, builder, params, state, arg_in, arg_out,
31313135

31323136
return builder
31333137

3134-
def _report_mechanism_execution(self, input_val=None, params=None, output=None, context=None):
3135-
3136-
if input_val is None:
3137-
input_val = self.get_input_values(context)
3138-
if output is None:
3139-
output = self.output_port.parameters.value._get(context)
3140-
params = params or {p.name: p._get(context) for p in self.parameters}
3141-
3142-
if 'mechanism' in self.name or 'Mechanism' in self.name:
3143-
mechanism_string = ' '
3144-
else:
3145-
mechanism_string = ' mechanism'
3146-
3147-
# FIX: kmantel: previous version would fail on anything but iterables of things that can be cast to floats
3148-
# if you want more specific output, you can add conditional tests here
3149-
try:
3150-
input_string = [float("{:0.3}".format(float(i))) for i in input_val].__str__().strip("[]")
3151-
except TypeError:
3152-
input_string = input_val
3153-
3154-
print("\n\'{}\'{} executed:\n- input: {}".format(self.name, mechanism_string, input_string))
3155-
3156-
try:
3157-
include_params = re.match('param(eter)?s?', self.reportOutputPref, flags=re.IGNORECASE)
3158-
except TypeError:
3159-
include_params = False
3160-
3161-
if include_params:
3162-
print("- params:")
3163-
# Sort for consistency of output
3164-
params_keys_sorted = sorted(params.keys())
3165-
for param_name in params_keys_sorted:
3166-
# No need to report:
3167-
# function_params here, as they will be reported for the function itself below;
3168-
# input_ports or output_ports, as these are inherent in the structure
3169-
if param_name in {FUNCTION_PARAMS, INPUT_PORTS, OUTPUT_PORTS}:
3170-
continue
3171-
param_is_function = False
3172-
param_value = params[param_name]
3173-
if isinstance(param_value, Function):
3174-
param = param_value.name
3175-
param_is_function = True
3176-
elif isinstance(param_value, type(Function)):
3177-
param = param_value.__name__
3178-
param_is_function = True
3179-
elif isinstance(param_value, (types.FunctionType, types.MethodType)):
3180-
param = param_value.__self__.__class__.__name__
3181-
param_is_function = True
3182-
else:
3183-
param = param_value
3184-
print("\t{}: {}".format(param_name, str(param).__str__().strip("[]")))
3185-
if param_is_function:
3186-
# Sort for consistency of output
3187-
func_params_keys_sorted = sorted(self.function.parameters.names())
3188-
for fct_param_name in func_params_keys_sorted:
3189-
print("\t\t{}: {}".
3190-
format(fct_param_name,
3191-
str(getattr(self.function.parameters, fct_param_name)._get(context)).__str__().strip("[]")))
3192-
3193-
# FIX: kmantel: previous version would fail on anything but iterables of things that can be cast to floats
3194-
# if you want more specific output, you can add conditional tests here
3195-
try:
3196-
output_string = re.sub(r'[\[,\],\n]', '', str([float("{:0.3}".format(float(i))) for i in output]))
3197-
except TypeError:
3198-
output_string = output
3199-
3200-
print("- output: {}".format(output_string))
3201-
32023138
@tc.typecheck
32033139
def _show_structure(self,
32043140
show_functions:bool=False,

0 commit comments

Comments
 (0)