/
TODO List.py
2862 lines (2680 loc) · 166 KB
/
TODO List.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# NEW COMMENT
# ************************************************** ToDo *************************************************************
#region CURRENT: -------------------------------------------------------------------------------------------------------
# Bryn:
# 1) Programmatic creation of @property
# 2) Plug & play
# HIGH LEVEL / DESIGN / CONVENTION ISSUES:
# 1) MANAGEMENT OF RETURN_VALUE FOR MECHANISMS (AS LIST VS. 2d NP.ARRAY)
# 2) ASSIGNMENT AND NAMING OF FUNCTION_PARAMS FOR AN OBJECT;
# PROBLEMS:
# - CONFUSION AS TO OBJECT TO WHICH THEY BELONG (OBJECT ITSELF OR ITS FUNCTION_OBJECT)
# - NAMING CONFLICTS
# OPTIONS:
# - MAKE A SPECIAL CLASS, OR KEEP function_params DICT BUT DON'T ASSIGN AS PARAMS OF OBJECT?
# - RENAME ANY CONFLICTS WITH PREFIX "function_<param_name>" (E.G., function_learning_rate)
# - RENAME ALL FUNCTION_PARAMS WITH PREFIX "function_<param_name>"
# - DISALLOW CONFLICTING NAMES AND THROW EXCPETION WHEN THEY ARE DETECTED IN _instantiate_parameter_state()
# * MAKE @property ATTRIBUTES THAT POINT TO FUNCTION'S PARAM(S)
# 3) MONITORING SPECIFICATION SYNTAX: Restrict specification to ObjectiveMechanism and possibly ControlMechanism,
# or also allow "locally" on OutputStates, Mechanisms, Processes and Systems?
# 4) SPECIFICATION OF LEARNING USING A PROJECTION SPEC VS. A DEDICATED KEYWORD (THAT ALLOWS FCT AND LEARNING_RATE)
# PRO: CONSISTENT WITH CONTROL
# CON: AKWARD TO HAVE TO GIVE THE PROJECTION THE FUNCTION AND LEARNING RATE THAT ARE PASSED TO LearningMech
# 5) SHOULD ATTRIBUTES OF PARENT CLASSED BE DOCUMENTED ON CHILD CLASSES?
# (E.G., PREFS, NAME, FUNCTION, FUNCTON_PARAMS, USER_PARAMS, ETC.)
# 6) SHOULD WE SUPPORT >2D VALUES (PASSED ALONG PROJECTIONS, USED AS STATE VALUES, ETC.; INPUTS TO TRANSFER FCT, ETC.)
# 7) SHOULD OVERRIDE OF ATTRIBUTE SETTERS BE @PROPERTY IN CLASS DEFINITION, OR SETTER PASSED TO make_property?
# 8) DOCUMENTATION: SHOULD WE INCLUDE COMPONENT ATTRIBUTES IN DOCSTRING FOR SUBCLASSES (E.G., params, prefs, etc.)
# 9) DOCUMENTATION: SHOULD EXAMPLES BE GENERIC (SEE COMPONENT FUNCTION) OR SPECIFIC (USING ACTUAL PSYNEULINK OBJECTS)
# 10) DOCUMENTATION: INCLUDE EXAMPLES "INLINE" OR IN THEIR OWN SECTION AT THE END?
# 11) SHOULD COMPONENT NAMES HAVE SPACES OF UNDERSCORES?
# TASKS:
# 1) BREAK UP FUNCTION INTO SEPARATE MODULES
# 2) IMPLEMENT CLASSES FOR ALL KEYWORDS (SIMILAR TO MatrixKeywords)
# 3) IMPLEMENT gating projections
# 4) IMPLEMENT ABC
# 4a) IMPLEMENT Swap execute (on Mechanism) and _execute (on its subclasses)
# 5) IMPLEMENT Compilation / paralleliztion of execution
# 6) IMPLEMENT Recurrent layer / KWTA??
# 7) IMPLEMENT TD learning
# 8) IMPLEMENT CLS / NMPH
# 9) IMPLEMENT Conflict (energy / entropy)
# 10) IMPLEMENT TensorFLow wrapper
# 11) IMPLEMENT Production System model (using scheduler??)
# 12) IMPLEMENT LEABRA
# 13) IMPLEMENT Model fitting
# COMPOSITION IMPLEMENTATION NOTE:
# add_projection_to and add_projection_from methods
# methods in LearningAuxilliary
# search for "Composition" in LearningProjection, LearningMechanism and LearningAuxlliary
# specification of ProcessingMechanism that should be associated with TARGET ObjectiveMechanism:
# one that either has either no outgoing projections, or none that receive LearningProjections
# got rid of special cases for Objective function altogether (since comparator is just special case of derivative = 0)
# added attribute to Projections: has_learning_projection
# FIX: Function, derivatives: change output to input??
#
# IMPLEMENT: Deferred init for control.
# FIX: Flip names of Xxxx() and Xxxx_Base()
# IMPLEMENT: NAME FOR FUNCTIONS (INCLUDING REGISTRY?)
# IMPLEMENT: function{} and owner_name IN exception messages (as for SoftMax derivative exception)
# DOCUMENTATION: items in paramClassDefaults are created as attributes (not properties), and are thus not validated
# when assignments are made to them; items in user_params are created as properties, and are
# validated (via assign_params) when assignments are made to them.
# DOCUMENTATION: assign_args_to_params_dicts should be used for any attributes for which parameterStates can be created
# DOCUMENTATION: Now that attribute assignment calls:
# _assign_params, which in turn calls _instantiate_params, which in turn calls _validate_params
# therefore _validate params may only get a subset of the params for a component
# in which case it can't be used to insure that a give param has been implemented,
# only that its value is a syntactically legal one.
# enforcement of assignment should be done using required_params
# in general, _validate_params should now check that the parameter being validated
# is in the target_set
# DOCUMENTATION: Component._validate_params: if testing before call to super, use request_set
# if testing after call to super, use target_set
# DOCUMENTATION: RESTORE runtime_params DOCUMENTATION
# DOCUMENTATION: FUNCTION_PARAMS in runtime_params example
# DOCUMENTATION: ?? MOVE `parameter specification dictionary <Mechanism_Creation>` TO Component??
# TEST: learning_rate is assignable and "sticks" at function, mech, process and system levels
# FIX: ADD XOR 2 PROCESS TO META TEST SCRIPT (ONCE VALIDATED)
# FIX: FUNCTION DOCUMENTATION: variable VS. variable_default
# FIX: OUTPUT TEMPLATE SPECIFICATION FOR LinearMatrix FUNCTION
# FIX: DERIVATIVE FOR SoftMax Function
# FIX: ADD owner ARG TO Function CONSTRUCTOR (DEFAULT = NONE)
# FIX: SEARCH FOR AND PURGE: monitoringMechanism and monitoring_mechanism AND monitoring_mech
# FIX: GET STRAIGHT target, self.target, self.targets and self.current_targets IN Process AND System
# FIX: GET STRAIGHT THE HANDLING OF learning_rate for:
# LearningMechanism
# its function
# LearningProjection
# Processs
# System
# IMPLEMENT: runtime_params FOR learning mechanisms in system (CURRENTLY ONLY SUPPORTS learning_rate);
# NEED TO IMPLEMENT SOME WAY OF SPECIFYING A LearningMechanism IN A mech_tuple,
# (SINCE LearningMechanisms ARE NOT CURRENTLY SPECIFIABLE IN A PROCESS' pathway ATTRIBUTE)
# [OR DOCUMENT THAT THIS IS NOT SUPPORTED]
# IMPLEMENT: MONITORED_OUTPUT_STATES param for Mechanism --
# make this a general form of MONITOR_FOR_CONTROL, that can be used by ObjectiveMechanism
# [SEE `monitoring_status` in ObjectiveMechanism]
# IMPLEMENT: MonitoredOutputStatesOption in string for MONITORED_VALUES specification of ObjectiveMechanism
#
# DOCUMENTATION:
# search for "specification dictionary" and replace with: `specification dictionary <Mechanism_Creation>`
#
# CONFIRM (IN ObjectiveMechanism):
# elif isinstance(monitored_value, InputState): [~616]
# if isinstance(state_spec, dict): [~753]
# if isinstance(state_spec, MonitoredOutputStatesOption): [~759]
# FIX: LearningComponents CLASS:
# ADD GENERIC CHECK (FOLLOWING IMPLEMENTATION IN error_signal_mech) THAT CHECKS THAT ANY RETURNED VALUE
# BELONGS TO AN OBJECT IN THE SAME PROCESS TO WHICH THE activation_mech BELONGS
# DOCUMENT THAT activation_mech IS THE "ROOT OBJECT" FOR THE CLASS (I.E., THE ONE FROM THE
# SEARCH/IDENTIFICATION OF ALL OBJECTS PROCEEDS
# IMPLEMENT: WRITE PARSER THAT CONVERTS matrix.shape "(#, #, #)" INTO "(#x#x#)
# FIX: WHY DOES weights SPECIFICATION FOR LINEARCOMBINATION FUNCTION HAVE TO BE [[-1],[1]] RATHER THAN JUST [-1, 1]
#
# FIX:
# MAKE SURE THAT WHEREVER variableClassDefaults OR paramClassDefaults ARE CHANGED IT IS LEGIT
# I.E., THAT THIS BE OK FOR ALL OTHER INSTANCES OF THAT CLASS
# FOR EXAMPLE, IN assign_params_to_dicts, WHERE A DEFAULT IS SPECIFIED IN THE ARG RATHER THAN classDefaults
#
#
# FIX: WHY DOESN"T THIS WORK: [ASSIGNMENT OF LEARNING_RATE TO SLOPE OF LEARNING FUNCTION]
# FIX: HANDLE THIS AS runtime_param??
# if self.learning_rate:
# params.update({SLOPE:self.learning_rate})
# FIX:
# 0) Deal with function parameter assignment in update() of ParameterState
# - move assignment of function params (Lines 714 and 742 in ParameterState)
# into @property for value (Line 756) [DEBUG CRASH]
# - assign params for function to owner in _instantiate_parameter_states (currently in assign_params_to_dicts??)
# ?? use user_params from function?
# 1) Once function param assignment is fixed, add test that it is working to jenkins suite
# (i.e., that assigning a value to the attribute for the parameter on the object (e.g., mechanism)
# changes its value for the Function
# 3) For system vs. process learning:
# Figure out why calling update_state for the matrix ParameterState works,
# but executing the LearningProjection to it does not
# 4) ObjectiveMechanisms: MODIFY TO:
# d) Revise EVCMechanism._get_monitored_states() to NOT direclty assign weights
# and exponents, but rather assign
# (see RE-WRITE TO INDICATE: (SEE ATTRIBUTE DESCRIPTION FOR monitored_values)
# f) parse MonitoredOUtputStates specification for monitored_values arg
# g) Fix EVC use of ObjectiveMechanism (needs to now call for Mapping Projection
# 4.5): LearningMechanism:
# Name inputStates using input_state_names (or create them explicitly using the values of variable?)
# Instantiate the MappingProjection from its ObjectiveMechanism
# (as ObjectiveMechanism does, by calling module function if not None)
# Need to change how learning function is specified, since no longer belongs in LearningProjection
# use new keyword or tuple type for specification of Learning (instead of using LearningProjection)
# Re-implement instantiation of receiver and sender for LearningProjection (in case they are created
# on their own)
# 5) Purge DefaultMonitoringMechanism
# 7) DDM weights for EVC mechanism: Handle better in ObjectiveMechanism
# 8) EVCMechanism: add objective_mechanism arg (as per LearningMechanism)
# 9) Reorganize:
# Add to _validate_params that their receivers are parameterStates
# MappingProjection under ProcessingProjection
# Add to _validate_params that receiver must be an inputState
# 10) Get .status == CHANGED straight
# 11) Change monitoringMechanism attribute of Projection to objectiveMechanism or something else?
# or change assignment to LearningMechanism??
# 12) Return values immediately in lc.component helper methods (see error_matrix and error_mech for examples)
# then get rid of x = lc.error_matrix
# DOCUMENT: Projection (vs. Mechanism): single input/oputput, and single parameter (matrix); no execution_id
#
# FIX: PUT ERROR HERE IF EVC AND/OR EVC_MAX ARE EMPTY (E.G., WHEN EXECUTION_ID IS WRONG)
# if EVC == EVC_max: (LINE 289 IN EVCAuxilliary)
# FIX: execution_token asynchrony:
# * Since learning and controller execute after processing mechanisms:
# - on the first pass, they ignore learning and control projections (since their excxecution_tokens == None
# - on subsequent passes, they have the new (current) execution_token, while learning and control mechanisms
# still have the last one
# SOLUTION: HAVE LEARNING AND CONTROL MECHANISMS GET THEIR execution_tokens FROM THEIR SYSTEM?
# OR HAVE SYSTEM ASSIGN ITS LEARNING AND CONTROL MECHANISMS THE CURRENT execution_token??
# SOLUTION: ASSIGN execution_token TO ALL MECHANISMS IN SYSTEM GRAPH AND LEARNING GRAPH AT TIME OF SYSTEM EXEC.
#
# * Same issue for learning in Process??
#
# * Also, which execution_token should be used for simulations (while simulation uses actual system rather than copy)
#
# FIX:
# Finish Run:
# assignment of inputs (for both Process and System): consolidation from process and system execute methods
#
# Rename INPUTS -> STIMULI
# FIX: process.run crashes if stimuli are in dict format and there is more than one execution set
# (see Multilayer Learning Script)
#
# FIX: MAKE SURE SAME ORIGIN FOR DIFFERENT PROCESSES IS NOT ASSIGNED DIFFERENT PHASES
#
# FIX:
#
# System:
# Finish implementing SystemStimulusInputs
# ObjectiveMechanism:
# Add matrix assignments (and allow None to suppress it)
# Add input assignments
# LearningProjection:
# Finish implementing Comparator version of ObjectiveMechanmism
# FIX: EVC Gratton Script_Bug5: Can't assign Linear() directly to intensity_cost_function (had to assign .function)
# FIX: When running a process with a TERMINAL mechanism that is also in another process, it gets input from that
# process even if it is not running
# FIX: Can't specify parameter as ControlProjection (StroopEVCforDST)
# DOCUMENTATION COMPLETION/CLEAN-UP:
# Component
# √ Function
# √ System
# √ Process
# √ Mechanism
# √ ProcessingMechanism
# DefaultProcessingMechanism
# √ DDM
# √ IntegratorMechanism
# √ TransferMechanism
# √ ControlMechanism
# DefaultControlMechanism
# √ EVCMechanism
# √ ControlSignal
# √ Projection
# √ MappingProjection
# √ ControlProjection
# √ LearningProjection
# √ State
# √ InputState
# √ ParameterState
# √ OutputState
# √ Run
# Preferences
# Log
# TimeScale
# Registry
#
# FIX: MAKE SURE SAME ORIGIN FOR DIFFERENT PROCESSES IS NOT ASSIGNED DIFFERENT PHASES
# DOCUMENT: targets argunment in system() and System_Base.__init__()
# DOCUMENT: ADD CHAIN EXAMPLE TO System AND Mechanism DOCSTRINGS
#
# DOCUMENT: FINISH DOCUMENTING:
# .. _ControlMechanism_Specifying_Control:
#
# Specifying control for a parameter
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DOCUMENT: it`s -> its (unless contraction)
# DOCUMENT: ControlSignal/ControlProjection:
# not just mechanism or its function, but also a mapping projection; reword referent as ``owner``
# `ORIGIN` -> 'ORIGIN'
# DOCUMENT: MONITOR_FOR_CONTROL -> EVALUATE_FOR_CONTROL
# DOCUMENT: MonitoredOutputStates -> EvaluatedOutputStates
# DOCUMENT: Component: under assign_params, document that parameter must be reference using a string that is the name
# of the argunent used for the parameter in the component's constructor (or the corresponding
# keyword, which is a capitlizaed version of its name, including any underscore separators )
# GIVE EXAMPLES.
# DOCUMENT: EVCMechanism NOTES ON API FOR CUSTOM VERSIONS:
# FROM EVCMechanism.control_signal_grid_search:
# Gets controller as argument (along with any standard params specified in call)
# Must include **kwargs to receive standard args (variable, params, time_scale, and context)
# Must return an allocation policy compatible with controller.allocation_policy:
# 2d np.array with one 1d array for each allocation value
#
# Following attributes are available:
# controller.run: executes a specified number of trials with the simulation inputs
# controller.predicted_inputs: ndarray of current value of outputState
# for each predictionMechanism in self.system.prediction_mechanisms
# controller.monitored_states: list of the mechanism outputStates being monitored for outcomes
# controller.inputValue: list of current outcome values for monitored_states
# controller.controlSignals: list of controlSignal objects
# controlSignal.allocation_samples: set of samples specified for that controlSignal
# [TBI:] controlSignal.allocation_range: range that the controlSignal value can take
# controller.allocation_policy: current allocation_policy
# controller.outputValue: list of current controlSignal values
# controller.value_function: calls the three following functions (done explicitly, so each can be specified)
# controller.outcome_aggregation function: aggregates outcomes (using specified weights and exponentiation)
# controller.cost_function: aggregate costs of control signals
# controller.combine_outcome_and_cost_function: combines outcomes and costs
# DOCUMENT: Learning and Control in System
# DOCUMENTATION: go through DDM; update refs, and add attributes for params (drift rate, starting_point, etc.)
# DOCUMENT: TO IMPOSE A DEFAULT PARAMETER CONDITIONALLY, NEED TO OVERRIDE _instantiate_parameter_states
# (EXAMPLE: TransferMechanism: impose default range if function is Logistic)
# DOCUMENTATION: replace ``variable`` with
# :py:data:`variable <Module.variable>` or
# :py:data:`variable <Component.variable>`
# same for ``function`` and ``value``
# DOCUMENTATION: Update LearningProjection_TERMINAL_vs_TARGET_fig
# DOCUMENT: LearningProjection.monitoringMechanism attribute
# DOCUMENT: Targets are checked against range of source mechanism (by Comaprator)
# Full set of targets and inputs are generated by run??
# *******************************************************************************************************************
#
# DOCUMENTATION: params dictionary -> ``params`` dictionary
# parameter dictionary -> ``params`` dictionary
# System -> Agent?
# Mechanism -> Process? [Representation? Transformation?]
# phase -> event
# MappingProjection matrix -> weightMatrix; make corresponding changes in learningSignal
# DOCUMENT: In Components, document use of params dictionaries and/or assign_params methods for modifying
# the parameters of a component "permanently"; describe relatinoshipo of keywords for parameters
# which are simply convenience string constants that are the same as the name of the argument
# for the parameter in the component's constructor. (see :ref:`EVCMechanism_Creation` for text)
# DOCUMENT: inputValue and outputValue are lists for convenience of user access, whereas
# variable and value are 2d np.arrays that are used as internal datastructures
#
# DOCUMENT: Explain better the relationship of an inputStates variable to its value, and of thes to the
# to the potential for multiple items of a mechanism's variable (with an example: ComparatorMechanism)
# DOCUMENT: FIGURES FOR:
# inputState: inputValue vs. variable
# OutputState: function vs. calculate, value vs. outputState.value vs. outputValue
# DOCUMENT: IN MECHANISM, CLARIFY:
# DISTINCTION BETWEEN THE RESULT OF ITS FUNCTION,
# AND ITS ``value`` ATTRIBUTE, WHICH IS WHAT IS RETURNED BY ITS EXECUTE METHOD
# DISTINCTION BETWEEN ``value``, WHICH IS THE RESULT OF THE MECHANISM'S EXECUTION,
# AND ``outputValue``, WHICH IS A SUMMARY OF THE ``value`` OF EACH OF ITS outputStates
#
# DOCUMENTATION: add show to Systsem and Process
#
# DOCUMENT:
# - Clean up documentation at top of module
# - change relevant references to "function" to "execute method"
# - note that run time params must be in FUNCTION_PARAMS
# - Add the following somewhere (if it is not already there):
# Parameters:
# + Parameters can be assigned and/or changed individually or in sets, by:
# including them in the initialization call (see above)
# calling the adjust method (which changes the default values for that instance)
# including them in a call the execute method (which changes their values for just for that call)
# + Parameters must be specified in a params dictionary:
# the key for each entry should be the name of the parameter (used to name its state and projections)
# the value for each entry can be a:
# + State object: it will be validated
# + State subclass: a default state will be implemented using a default value
# + dict with specifications for a State object to create:
# + ParamValueProjection tuple: a state will be implemented using the value and assigned the projection
# + projection object or class: a default state will be implemented and assigned the projection
# + value: a default state will be implemented using the value
# DOCUMENT:
# README.md -> README.rst AND/OR Index.rst:
# Features: graph support, logging, hierarchical preferences
#
# System: Control and Learning under Structure
# OutputStates: INDEX argument, customizability, balance between customized outputStates and dedicated mechanisms
# DOCUMENT: Component: :keyword:`NotImplemented` can be assigned to a parameter in the definition of paramClassDefaults
# to allow it to pass _validate_params without having to make an assignment (i.e., to
# suppress type checking.
# `None` is used to suppress its use by higher level assignments
# DOCUMENT UNDER ParameterStates
# If parameter default value is set to None (or a non-numeric value),
# either in paramClassDefaults, as default in constructor argument, or specified as such,
# then no parameter state is created and can't be used either for Control, Learning or runtime assignment
# Instantiate parameterState for each param in owner.user_params
# - including ones in owner.user_params[FUNCTION_PARAMS]
# - exclude if it is:
# assigned a non-numeric value (including None, NotImplemented, False or True)
# unless it is:
# a tuple (could be on specifying ControlProjection, LearningProjection or ModulationOperation)
# a dict with the name FUNCTION_PARAMS (otherwise exclude)
# a function
# IMPLEMENTATION NOTE: FUNCTION_RUNTIME_PARAM_NOT_SUPPORTED
# (this is because paramInstanceDefaults[FUNCTION] could be a class rather than an bound method;
# i.e., not yet instantiated; could be rectified by assignment in _instantiate_function)
# IMPLEMENT / DOCUMENT:
# IMPLEMENTATION NOTE: Process._execute_learning - ~line 1909
# This implementation restricts learning to parameterStates of projections to inputStates
# That means that other parameters (e.g. object or function parameters) are not currenlty learnable
# ADD LEARNING TO OF OTHER PARAMETER STATES (E.G., OBJECT ITSELF AND/OR ITS FUNCTION)
# DOCUMENTATION: direct call to run or execute for mechanism executes its function in isolation
# (i.e., does not do any state updating), so can't use run_time params
#
# DOCUMENTATION: runtime_param specification can use tuple, which specifies modulation operation for runtime param
# (including override)
# DOCUMENTATION: runtime_param can be specified for the parameters of an object or of its function,
# but *NOT* the function itself (COMMENT: problem is the possible need to re-instantiate the function;
# paramInstanceDefaults may have just has the class, not an instance; could rectify by assigning that to
# paramInstanceDefaults (see 11/27/16 in Component.instantiate_function)
# DOCUMENTATION: for now, only numeric parameters can be subject to control (may change in the future)
# COMMENT: will need to:
# allow all params to be assigned in Mechanism.execute (line 1336-7):
# for param in self.function_params:
# runtime_params[param] = self.parameterStates[param].value
# return keyword values (cf. commented out keyword method for Function.Integrator
# handle management of contraints in State._instantiate_state (line 1869):
# constraint_value = convert_to_np_array(constraint_value,1)
#
# DOCUMENTATION: TAKE CARE OF THE FOLLOWING:
# COMMENT:
# MOVE THE BULK OF THIS TO THE DESCRIPTION OF RUNTIME PARAMS ABOVE, AND REFERENCE THAT.
# COMMENT
# DOCUMENTATION: singularize first statement in overview of all objects
#
# DOCUMENTATION: SEARCH FOR :class: AND REPLACE WITH :py:class:
# DOCUMENTATION: check that, for DDM in TIME_STEP mode, parameter values not specified in params dict will assume
# any value assigned in the function arg; otherwise, default will be used
# DOCUMENTATION: FROM DDM: PUT FULL EXPLANATION IN MECHANISM AND THEN ADD LINK TO BELOW
# since any parameters specified in the ``params`` argument when
# creating a mechanism override any corresponding ones specified as arguments to its ``function``).[LINK]
# DOCUMENTATION: MONITOR_FOR_LEARNING (in LearningProjection AND ??WHERE ELSE:
# Mechanism?? Paralleling MONITOR_FOR_CONTROL
# OutputState??
# MonitoringMechanism??
# DOCUMENTATION: THESE NEED TO BE ADDED:
# (see :ref:`ControlMechanisms_Monitored_OutputStates` for details of specification).
# (see :ref:`MonitoringMechanisms_Monitored_For_Learning` for details of specification).
# DOCUMENTATION: MOVE DESCRIPTION OF PARAMETER SPECIFICATION DICTIONARY FROM UNDER MECHANISM TO UNDER COMPONENT
# AND ADJUST ALL REFERENCES OF THE FOLLOWING TYPE ACCORDINGLY:
# (see :doc:`Mechanism` for specification of a parms dict)
# DOCUMENTATION: NEED GENERAL INTRO, INCLUDING COMMENT ABOUT SPECIFYING ARGUMENTS/PARAMETERS:
# FOR ARGUMENTS OF __init__ , THERE IS USUALLY AN ATTRIBUTE OF THE OBJECT THAT CAN BE ASSIGNED A
# VALUE AFTER IT IS CREATED. (PUT THIS WHEREVER PARAMS, PARAMSCURRENT, INSTANCE DEFAULTS ETC.
# ARE DISCUSSED.
# DOCUMENTATION: ControlMechanism -> controlMechanism or control mechanism (in appropriate places)
# DOCUMENTATION: Call subclass -> "Constructor"
# DOCUMENTATION: Learning -> LearningProjection (name of doc)
#
# DOCUMENTATION: add the following to attributes of class:
# object-specific params to list of
# function_params
# consider adding the following (paralleling Projection):
# params : Dict[param arg, parm value]
# set currently in effect
#
# paramsCurrent : Dict[param arg, parm value]
# current value of all params for instance
#
# paramInstanceDefaults : Dict[param arg, parm value]
# defaults for instance (created and validated in Components init)
# DOCUMENT:
# If the sender outputState and/or the receiver inputState are not specified:
# - a mapping will be created for only sender.outputState and receiver inputState (i.e., first state of each)
# - the length of value for these states must match
#
# - DOCUMENT: Finish editing Description:
# UPDATE TO INCLUDE Mechanism, Projection, Mechanism FORMAT, AND (Mechanism, Cycle) TUPLE
#
# DOCUMENT:
# SHOULD ALSO BE INCLUDED IN DOCUMENTATION OF EXECUTE METHOD FOR PROCESS AND SYSTEM:
# *Number of phases (time_steps) per trial.* Processes have only one phase per trial, but systems can have
# more than one. If the mechanisms in a system use more than a single phase, then the next level of
# nesting of a lists, or next higher axis of an ndarrays is used for the sequence of phases.
# DOCUMENT: update System docstring for MechanismList and mech_tuple attributes (following format of Process)
# DOCUMENT parsing of (paramValue, projection_spec) tuples:
# DOCUMENT:
# ORDER OF INSTANTIATION OF PARAMETER STATES AND EXECUTE METHODS
# ORDER OF INSTANTIATION OF LEARNING PROJECTION COMPONENTS:
# _deferred_init FOR LEARNING PROJECTIONS, MAPPING_PROJECTIONS W/O RECEIEVERS, ETC.
# DOCUMENT:
# ComparatorMechanisms ARE INCLUDED FOR EXECUTION DURING LEARNING,
# BUT NOT FOR REPORTING, AND SHOULD NOT BE CONSIDERED TERMINALS FOR EVC MONITORING
# FOR OPTIONAL INPUT, AND ADD ARGUMENT TO SYSTEM FOR ASSIGNING INPUT AT EXECUTE TIME
#endregion
#
# DOCUMENT: Add links throughout for time_step and trial
#region DEVELOPMENT
# time_step DDM integration
#
# system.graph -> NetworkX, graphViz, or the like.
#
# API for "wrappers"
#
# IMPLEMENT: Demos of Functions that plots each Function
# (use new "demoRange" attribute that specifies range of inputs for Function for demo)
#
# GUI (using QT)
#
# FIGURE OUT HOW TO GET DILL WORKING TO CACHE SYSTEM IN System._cache_state, OR STORE AS BINARY OBJECT
#
# function format for inputs in Run (e.g., for simulating staircasing):
# needs to be coordinated with validation of num_targets (if it is not a function);
# then document (paralleling targets, and maybe moving much of that to inputs function format)
#
# Filter Warnings
#
# TEST run(inputs) dict format FOR SITUATION IN WHICH TWO PROCESSES HAVE THE SAME INPUT,
# OR ONE PROCESS BRANCHES OUT FROM ANOTHER
# ISSUE IS WHETHER THE RIGHT NUMBER OF INPUTS ARE ASSIGNED, AND WHETHER SYSTEM KNOWS NOT TO
# CREATE AN INPUT FOR THE BRANCHING PROCESS (SEE RUN line 688 and SYSTEM line 1388
#
# README.md -> README.rst AND/OR Index.rst:
#endregion
#
#region PY QUESTIONS: --------------------------------------------------------------------------------------------------
# QUESTION: how to initialize a numpy array with a null value, and then assign in for loop: np.empty
#endregion
# -------------------------------------------------------------------------------------------------
#region PYCHARM QUESTIONS: ---------------------------------------------------------------------------------------------
# QUESTION: how to identify method in which breakpoint has occurred (or where execution has paused/stopped)
# QUESTION: how to share breakpoints across installations?
# QUESTION: how to set default for expanded vs. collapsed Favorites window/pane
#endregion
# -------------------------------------------------------------------------------------------------
#region DEPENDENCIES: -----------------------------------------------------------------------------------------------
#
# toposort.py
# wfpt.py
# mpi4py.py
#
#region BRYN: -------------------------------------------------------------------------------------------------------
# Documentation (from code -> HTML/MD -> website
# Jupyter and matplotlib
# - QUESTION: Better way to do this (check for a number or 0D np value and convert to 1D?):
# if isinstance(target, numbers.Number) or (isinstance(target, ndarray) and target.ndim == 0):
# target = [COMPARATOR_TARGET]
# # If input is a simple list of numbers (corresponding to 0D), wrap in an outer list (i.e., make 1D)
# if all(isinstance(i, numbers.Number) for i in target):
# target = [COMPARATOR_TARGET]
# - QUESTION: OK to have mutable objects in arguments to init?? (e.g., System)
# - QUESTION:
# How to avoid implementing DefaultController (for ControlSignals) and DefaultTrainingMechanism (for LearningSignals)
# and then overriding them later??
# - ABC
# - params dict vs. args vs. **kwargs: FIX: LOOK AT BRYN'S CHANGES TO isCompatible
# - FIX: LOOK AT HIS IMPLEMENTATION OF SETTER FOR @ClassProperty
# - QUESTION: CAN ERRORS IN TypeVar CHECKING BE CAPTURED AND CUSTOMIZED?
# (TO PROVIDE MORE INFO THAN JUST THE ERROR AND WHERE IT OCCURRED (E.G., OTHER OBJECTS INVOLVED)
# - Revert all files to prior commit in PyCharm (VCS/Git/Revert command?)
# It’s helpful if methods that mutate object state have names that suggest they will do so.
# For example, it was confusing to me that _validate_variable assigns self.variable and self.variableClassDefault
# (at least it does in Mechanism, I’m not sure about other subclasses). I was expecting it simply to validate,
# as in do nothing if the variable was OK, and throw an exception if it wasn’t.
# It may sound kooky, but even a clunky name like “validate_and_set_variable” would be better,
# or better still would be to make validate really just validate,
# and have another method like “assign_variable” or something.
# In general, every assignment statement changes the behavior of the program in ways that are non-local,
# and thus hard to understand and debug. So you want as few of them as you can possibly get away with,
# and you want them clearly identified.
# NotImplemented is used a lot for missing arguments. Usually people use None for that.
# This also allows for a nice idiom. Given a parameter foo = None, you can do defaulting like this:
# myval = foo or “some default value”
# So you get myval = foo if foo is truthy (not None, [], (), 0, 0.0, “”, or False), and your default value otherwise
# I don’t think you have to worry quite so much about people implementing classes wrongly or subversively.
# This is Python - if they want to do bad things, you’ll be hard pressed to stop them.
# All you can do is guide them in the right direction.
# In Function there’s a test to make sure there’s a registry - this probably ought to be handled by having
# a base class “Category” or something, that ensures there is one in its __init__, and just insisting that
# every category class extends that “Category” class. We can talk more about this.
# Normally when implementing __init__, it’s a good idea for base classes to call super().__init__ first,
# before doing anything else. In some languages, e.g. C++ and Java, it’s actually required to be the first thing.
# There were some comments in Function.__init__ that made me think you’re expecting people to do some setup before
# calling super().__init__.
# Automated type checking (like typecheck-decorator) would reduce code size noticeably.
# PEP8
# Rename packages lowercase, Components -> functions
# Mechanism_Base -> MechanismBase
# Method names, e.g. verbosePref -> verbose_pref in ComponentPreferenceSet
# Aim for methods that fit on a single screen, e.g. Function.__init__ is about 150 lines,
# but you want something like 50 lines for a method for it to be comprehensible.
# Along the same lines, too many #regions, and too much SHOUTING. Breaks up the reader’s flow.
# Single line comments in normal case are fine.
# No need for #regions around 1-2 lines of code, especially if your region name almost exactly matches
# the name of the method you’re calling in the region (e.g. Function, around the end of __init__)
# For each #region more than 2-3 lines long, consider whether it would be better to extract that code to
# a small helper method or function.
# Commenting style:
# Want comments on each method, not one block at the class level that lists all the methods.
# Documentation generators like sphinx will generate those class summaries from component parts,
# no need to synthesize them yourself
# Guiding principle: docs as physically close to the code as possible, so less likely to get out of sync.
# No point in listing things like “:param level: and :return:” if they’re not actually going to be documented,
# it’s just taking up space.
# Lots of code commented out. Just delete it, git will get it back for you if you decide you need it again.
# Use doc strings to document class members, not comments
# (e.g. Function.py line ~207 doc for variableClassDefault_Locked)
#endregion
#region PNL JAMBOREE
#
# DEVELOPMENT:
# TimeStep time scale (DDM & TransferMechanism Mechanisms)
# Implement single centralized registry
# Learning execution sequence
# Cyclic system
# API / extensibility
#
# ACTION ITEMS:
#
# Flatten params (and add kwArgs handling) to Functions
# - function -> function
# - functionParams -> args and/or params dict inside Function specification
# - if functionParams are now all handled inside specification of a Function for function param:
# - need to make sure all parses of function can now handle this
# - instantiation of parameterStates needs to extract any params specified as args and/or in a params dict
# - add @property for all params, so they can be addressed directly as attributes
# setter method should call _instantiate_defaults
#
#endregion
#region EVC MEETING: ---------------------------------------------------------------------------------------------------
# -------------------
#
# QUESTION: Should ControlSignal "intelligence" (e.g., intensity, costs, etc.)
# be in EVC mechanism rather than ControlProjection?
# EVCMechanism makes more sense theoretically
# e.g., seems better to talk about the cost of a control signal, rather than ControlProjection
# Projection is easier to manage (as it is its own object, can be parameterized, etc.)
# Maybe they should be assigned to OutputStates of the EVCMechanism?
#
# QUESTION: DDM:
# MULTIPLE PROCESSES AND AVERAGED OUTPUT VALUES IDEA
# t0 BUISINESS (ms or secs?)
# DOES NAVARRO AND FUSS ACTUALLY RETURN ER (I ASSUMED IT DID)
# DOES NAVARRO AND FUSS ACTUALLY RETURN MEAN RT FOR CORRECT RESPONSE? SHOULD THIS TOO BE UPPER BOUND??
# HOW TO DESCRIBE RESULTS OF INTERROGATOIN PROTOCOL (IN TIME_STEP MODE)
# IS t0 MS OR SECONDS?
# -------------------------------------------
# FIX: PROCESS INPUT, AND TARGET INPUT TO ComparatorMechanism, ARE RESTRICTED TO PROCESS TO WHICH MECHANISM BELONGS
# ?SHOULD SAME BE TRUE FOR ALL PROJECTIONS: ONLY UPDATE THOSE BELONGING TO MECHANISMS WITHIN THE PROCESS?
# QUESTION: When executing a mechanism, and updating its projections (to get their input),
# should update only those from mechanisms that belong to the process currently being executed?
# or should all projections be updated (irrespective of source) when executing a mechanism?
# This issue includes Process inputs, as well as target inputs
# Inclined to only restrict Process and target inputs
# (since those are process-specific) but not other projections
#
# QUESTION: RL:
# Option 1 - Provide Process with reward for option selected: more natural, but introduces timing problems:
# - how to provide reward for outcome of first trial, if it is selected probabilistically
# - must process trial, get reward from environment, then execute learning
# SOLUTION: use lambda function to assign reward to outputState of terminal mechanism
# Option 2 - Provide Process with reward vector, and let targetMechanism choose reward based on action vector
# - softamx should pass vector with one non-zero element, that is the one rewarded by comoparator
# SOLUTION: use this for Process, and implement Option 1 at System level (which can control timing):
# - system should be take functions that specify values to use as inputs based on outputs
# as per SOLUTION to Option 1 using lambda functions
# QUESTION: Default object (e.g., default_projection for Process): should they be templates or objects?
# or signify (e.g., class = template)
#
# QUESTION: ??OPTION (reshapedWeightMatrixOption for MappingProjection) TO SUPPRESS RESHAPING (FOR FULL CONNECTIVITY)
#
# QUESTION: WHICH CLASS SHOULD HANDLE THE EXECUTION OF LEARNING: PROCESS OR SYSTEM
# Process:
# - it manages the instantiation of LearningSignals
# - part of the definition of a Process: output is where supervised training signals are provided
# - may want to build a model that can learn and only has a Process
# System:
# - need to manage execution of learning in systems anyhow (same as for mechanisms)
# - learning that needs to straddle Processes
# (e.g., error-signals that need to be passed from the first layer of one Process
# to the last layer of a preceding Process) - but then make them one Process (per definition above)?
#
# FIX: HOW IS THIS DIFFERENT THAN LENGTH OF self.variable
# + kwTransfer_NUnits (float): (default: Transfer_DEFAULT_NUNITS
# specifies number of units (length of input array)
#
# NEED FOR EVC MODEL:
# - Sequential adjust effects:
# "Reactive": simple controlMechanism that maps input values into ControlProjection intensities
# "Simple Exhaustive Search": find optimal policy for stimulus/reward values
# "Feature-based model learning" (Falk & Tom)
# "Exhaustive Search + learning":
# searches through all ControlSignals to find the optimal one
# stimulus prediction
# reward prediction
# automatic component of the drift for each stimulus (== weight matrix)
# * d(parameter_value)/d(control signal intensity) for each control signal ==
# differential of the parameterModulationFunction
# NOTE:
# THIS IS DISTINCT FROM THE ControlProjection.function
# (== intensity_function) WHICH MAPS ALLCATION -> ControlProjection Intensity
# BUT IS ISOMORPHIC IF ControlProjection.function IS Linear with slope = 1 and offsent 0 (i.e,. its default)
# QUESTION: DO WE CARE ABOUT THE DIFFERENTIAL ON ALLOCATION -> parameter_value (.e., ControlSiganl.function)
# OR ControlProjection Intensity -> parameter_value (i.e., parameterModulation function)??
# SEBASTIAN FAVORS LEAVING IT AS DIFFERENTIAL ON parameterModulation function
# * Parameters of parameterModulation function should be accessible
#endregion
#region GENERAL: -------------------------------------------------------------------------------------------------------
#
# - Register name:
# PsyNeuLink
# [PsyPy? PsyPyScope? PyPsyScope? PsyScopePy? NeuroPsyPy? NeuroPsySpy]
#
# Search & Replace:
# show() -> show()
# ControlProjection -> ControlProjection
# LearningSignal -> LearningProjection
# "execute method" -> function: BUT NEED TO BE CAREFUL, SINCE "<object>.execute method" SHOULD *NOT* BE REPLACED
# <>.paramsCurrent = <>.params
# kwXxxYyy -> XXX_YYY
# MATRIX -> kwWeightMatrix; matrix -> weightMatrix in MappingProjection
# item -> element for any array/vector/matrix contexts
# function (and execute Method) -> executeFunction (since it can be standalone (e.g., provided as param)
# PARAMETER_STATE -> PARAMETER_STATES
# MechanismParamValueparamModulationOperation -> MechanismParamValueParamModulationOperation
# functionParams -> ParameterStates
# InputStateParams, OutputStateParams and ParameterStateParams => <*>Specs
# KwDDM_StartingPoint -> DDM_StartingPoint
# CHANGE ALL VARIABLES FROM THEIR LOCAL NAMES (E.G., Allocation_Source, Input_value, etc) to variable
# Projections: sendsTo and sendsFrom
# "or isinstance(" -> use tuple
# Change "baseValue" -> "instanceValue" for prefs
# super(<class name>, self) -> super() [CHECK FUNCTIONALITY IN EACH CASE]
# NotImplemented -> None (and adjust tests accordingly)
#
# FIX: execute VS. update
# SUTBTYPES DON'T CURRENTLY IMPLEMENT update(); THEY USE execute() for both housekeeping and function
# WOULD BE BETTER AND MORE CONSISTENT TO HAVE THEM IMPLEMENT update() WHICH CALLS .execute
# PROBLEM with implementing update() in subclasses of Mechanism:
# 1) it would override Mechanism.update so must call super().update
# 2) no obvious place to do so, since execute() (which MUST be implemented by subclass)
# is called in the MIDDLE of Mechanism.update
# 3) could name subclass.update() something else, but that gets more complicated
# PROBLEM with NOT implementing update() in subclasses of Mechanism:
# 1) they are now special (i.e., not treated like all other classes in Function hierarchy)
# 2) all of the "housekeeping" for execution must be done in subclass.execute()
# 3) that means that kwExecute can't be used to override self.execute (i.e., defeats plug and play)
# CURRENT SOLUTION:
# use FUNCTION as scripting interface
# intercept specification of FUNCTION before _instantiate_function (e.g., in _validate_params),
# reassign to instance attribute, and del FUNCTION from paramsCurrent
#
# - FIX: get rid of type/class passing
# - replace all type/class specifications of params with kw string specifications for each type
# - implement global and/ or local lookup table(s) of types (locally for each (set of) types)
# - reserve a special keyword (e.g, CLASS_NAME or kwClassName or kwDEFAULT) for specifying default of instance
#
# FIX: NotImplemented STILL LINGERING FOR:
# MONITOR_FOR_CONTROL (see Mechanism line 696)
# needed to distinguish between suppress and ignore MONITOR_FOR_CONTROL
# variableClassDefault (see Component line 408)
# needed to allow Process and System to set their variableClassDefault values to None
#
# - FIX: GET RID OFF '-1' SUFFIX FOR CUSTOM NAMES (ONLY ADD SUFFIX FOR TWO OR MORE OF SAME NAME, OR FOR DEFAULT NAMES)
# - FIX: MAKE ORDER CONSISTENT OF params AND time_scale ARGS OF update() and execute()
#
# TEST: RUN TIMING TESTS FOR paramValidationPref TURNED OFF
#
# TEST warnings.warn
# IMPLEMENT: Replace class checking (isclass) with:
# if any(i in {None, Mechanism, OutputState, ObjectiveMechanism} for
# i in {self.objective_mechanism, type(self.objective_mechanism)}):
#
# IMPLEMENT: typecheck name arg in constructors to be a str
#
# IMPLEMENT: REFACTOR EVC and LEARNING:
#
# EVC: 1) MonitoringMechanism - new one that implements current EVCMechanism's objective function (i.e.,
# (i.e., using LinearCombination).
# 2) EVCMechanism - new version that takes output of MonitoringMechanism, and just handles search.
# 3) ControlProjection - as it is now.
#
# Learning: 1) MonitoringMechanism - use relevant one, as it does now.
# 2) LearningMechanism - move BP and RL implementations from LearningProjection to this/these;
# takes output of MonitoringMechanism (as errorSignal)
# as well as an errorSource as its input
# (rather than figuring it out, as it does now);
# BP version calculates gradient on that; RL does its thing;
# generates modification specification for LearningProjection.
# 3) LearningProjection - simplified version (paralleling ControlProjection implementation):
# * takes modification specification from LearningMechanism and
# formats it for item being modified (learned);
# * can be used for MappingProjection or ProcessingMechanism.
#
#
# - IMPLEMENT: Config (that locally stashes default values for user)
#
# - IMPLEMENT: integrate logging and verbose using BrainIAK model:
# no printing allowed in extensions
# verbose statements are logged
# log goes to screen by default
# can define file to which log will go
#
# - IMPLEMENT: master registry of all Function objects
# - IMPLEMENT TYPE REGISTRIES (IN ADDITION TO CATEGORY REGISTRIES)
#
# - IMPLEMENT switch in __init__.py to suppress processing for scratch pad, etc.
#
# IMPLEMENT: Quote names of objects in report output
#
# IMPLEMENT: Change all enum values to keywords (make read_only?? by using @getters and setters)
# (follow design pattern in SoftMax)
#
# - IMPLEMENT Testing:
# use instantiation sequence (in Utilities) to create test for each step
#
# - Fully implement logging
# For both of the above:
# use @property to determine whether current value should be set to local value, type, category or class default
# - Implement timing
# - implement **args (per State init)
# - MAKE SURE _check_args IS CALLED IN execute
#
# - iscompatible:
# - # MAKE SURE / i IN iscompatible THAT IF THE REFERENCE HAS ONLY NUMBERS, THEN numbers_only SHOULD BE SET
# - Deal with int vs. float business in iscompatible (and Function_Base functionOutputTypeConversion)
# - Fix: Allow it to allow numbers and strings (as well as lists) by default
# and then relax constraint to be numeric for InputState, OutputState and ParameterState
# in Mechanism._validate_params
# - Implement: # IMPLEMENTATION NOTE: modified to allow numeric type mismatches; should be added as option in future
#
# IMPLEMENT: add params as args in calls to __init__() for Function objects (as alternative to using params[])
#
# MAKE CONSISTENT: variable, value, and input
#
# - Registry:
# why is LinearCombination Function Components registering an instanceCount of 12 but only 2 entries?
# why is DDM registering as subclass w/o any instances?
# why are SLOPE and INTERCEPT in same registry as Statess and Parameters?
# IMPLEMENT: Registry class, and make <*>Registry dicts instances of it, and include prefs attribute
#
# IMPLEMENT: change context to Context namedtuple (declared in Globals.Keywords or Utilities): (str, object)
#
#endregion
#region SCRIPTS: -----------------------------------------------------------------------------------------------
# IMPLEMENT: Extend Multilayer Learning Test script to use multiple forms of parameter specification
#endregion
# region DEPENDENCIES:
# - toposort
# - mpi4py
# - wfpt.py
# endregion
# region OPTIMIZATION:
# - get rid of tests for PROGRAM ERROR
# endregion
#region DOCUMENTATION: -------------------------------------------------------------------------------------------------
# QUESTION: should attributes that are common to different subclasses be documented there, or only in the base classes?
# DOC LIST:
# IntegratorMechanism
# √ ComparatorMechanism
# ~ ControlMechanism
# √ ControlProjection
# ! DDM
# DefaultControlMechanism
# √ EVCMechanism
# Function
# ~ InputState
# √ LearningProjection
# Log
# √ MappingProjection
# ! Mechanism
# √ MonitoringMechanism
# ~ OutputState
# ~ ParameterState - NEED TO ADD RUNTIME SPECIFICATION
# Preferences
# √ Process
# ProcessingMechanism
# ~ Projection
# ! Run
# √ State
# ! System
# ! TransferMechanism
# Utilities
# √ WeightedErrorMechanism
# SPHINX / RST ***********************************************************
# Convention for names of arguments, attributes, methods and keywords:
# =====================================================================
# argument_attribute -> argument and user-accessible attribute derived from a constructor argument
# nonArgumentAttribue -> user-accesible attribute that is not an argument in the constructor
# _internal_atttribute or _method -> not user accessible, and not to be included in rst docs
# KEY_OR_KEYWORD -> name of a str used as a key for a dict or as a PsyNeuLink keyword
# Main documentation of params/attributes should be in module docstring; Arguments and Attributes should refer to that
# rST formatting for tokens:
# =========================
# None:
# `None`
# Keywords:
# :keyword:`<KEYWORD>`
# Arguments, parameters, attributes, methods and functions:
# ``argument``, ``parameter``, ``attribute``, ``method``, or ``function``
# Section reference:
# _<DOCUMENT>_<SECTION>_<SUBSECTION>:
# rST formatting for Headings:
# ===========================
# SECTION: -------
# SUB SECTION: ~~~~~~~
# SUB SUB SECTION: ..........
# EXCLUDE FROM DOCS: COMMENT:
# Text to be excluded
# COMMENT
# Arguments [SECTION]
# ---------
# <argument> : <type> : default <default>
# description. <- Note, first line of description is not capitalized (since it is prepended with hyphenation)
# More description.
# Attributes [SECTION]
# ----------
# <attribute> : <type> : default <default>
# Description. <- Note, first line of description IS capitalized (since it is NOT prepended with hyphenation)
# More description.
#
# .. _<attribute> <- Internal attribute is commented out (by prepending dots and indentation)
# Description.
# More description.
# ?? ADD TO FUNCTION OR GENERAL DESCRIPTION SOMEWHERE:
# Notes:
# * params can be set in the standard way for any Function subclass:
# - params provided in param_defaults at initialization will be assigned as paramInstanceDefaults
# and used for paramsCurrent unless and until the latter are changed in a function call
# - paramInstanceDefaults can be later modified using _instantiate_defaults
# - params provided in a function call (to execute or adjust) will be assigned to paramsCurrent
# FIX: Figures: need higher rez
# FIX:
# Where is this coming from: