This repository was archived by the owner on May 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathInputEncoder.cs
697 lines (654 loc) · 30.7 KB
/
InputEncoder.cs
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
using RCNet.Extensions;
using RCNet.MathTools;
using RCNet.Neural.Data;
using RCNet.Neural.Data.Generators;
using RCNet.Neural.Data.Transformers;
using RCNet.Neural.Network.SM.Preprocessing.Neuron.Predictor;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace RCNet.Neural.Network.SM.Preprocessing.Input
{
/// <summary>
/// Implements a mediation layer between the external input data and the internal reservoirs of the neural preprocessor.
/// </summary>
/// <remarks>
/// <para>
/// Processes the external input data in the natural form and provides it's representation on analog and spiking input neurons for the next processing in the reservoirs.
/// </para>
/// <para>
/// Allows to create new computed input fields using chainable transformations of existing external input fields, as well as adding independently generated input fields using various generators.
/// </para>
/// <para>
/// Supports two input feeding modes: Continuous and Patterned.
/// The Continuous feeding mode processes an input vector as the variable(s) values at the single time-point T.
/// The Patterned feeding mode processes an input vector as an alone input pattern consisting of a time series of the variable(s) values.
/// </para>
/// Supports three ways how to represent an analog value as the spikes: Horizontal, Vertical or Forbidden.
/// The Horizontal way of coding means a simultaneous activity of the neuronal population where every input field is coded by several spiking input neurons (a horizontal spike-train). It is fast, it leads to a single computation cycle of the reservoirs per the input field value.
/// The Vertical way of coding means that the input field value is coded as a spike-train on a single spiking input neuron. It is slower, it leads to multiple computation cycles of the reservoirs according to the spike-train length.
/// The Forbidden way of coding means there is no coding of an analog value as the spikes. It is fast, it leads to a single computation cycle of the reservoirs per the input field value and it does not utilize any spiking input neuron(s).
/// </remarks>
[Serializable]
public class InputEncoder
{
//Constants
/// <summary>
/// Identifies that there is a variable number of time-points to be processed in the reservoirs.
/// </summary>
public const int VariableNumOfTimePoints = -1;
/// <summary>
/// Identifies the variable length of an external input data vector.
/// </summary>
private const int NonFixedVaryingDataVectorLength = -1;
/// <summary>
/// The ID of the input encoder's fictive reservoir.
/// </summary>
public const int ReservoirID = -1;
/// <summary>
/// The ID of the input encoder's fictive pool.
/// </summary>
public const int PoolID = -1;
//Enumerations
/// <summary>
/// The type of input feeding.
/// </summary>
public enum InputFeedingType
{
/// <summary>
/// The continuous input feeding mode.
/// </summary>
Continuous,
/// <summary>
/// The patterned input feeding mode.
/// </summary>
Patterned
}
/// <summary>
/// The way of input spikes coding.
/// </summary>
public enum InputSpikesCoding
{
/// <summary>
/// The horizontal coding.
/// </summary>
Horizontal,
/// <summary>
/// The vertical coding.
/// </summary>
Vertical,
/// <summary>
/// The coding of input spikes is not allowed.
/// </summary>
Forbidden
}
//Attribute properties
/// <summary>
/// The number of fixed time-points per one instance of processed external input vector or VariableNumOfTimePoints (-1).
/// </summary>
public int NumOfTimePoints { get; private set; }
/// <summary>
/// The number of values being routed to readout layer.
/// </summary>
public int NumOfRoutedValues { get; private set; }
//Attributes
/// <summary>
/// The configuration.
/// </summary>
private readonly InputEncoderSettings _encoderCfg;
/// <summary>
/// The collection of the internal input transformers associated with the transformed input fields.
/// </summary>
private readonly List<ITransformer> _internalInputTransformerCollection;
/// <summary>
/// The collection of the internal generators associated with the generated input fields.
/// </summary>
private readonly List<IGenerator> _internalInputGeneratorCollection;
/// <summary>
/// The collection of varying input fields.
/// </summary>
private readonly List<InputField> _varyingFields;
/// <summary>
/// The number of steady input fields (relevant only in case of patterned feeding).
/// </summary>
private readonly int _numOfSteadyFields;
/// <summary>
/// The indexes of steady input fields being routed to the readout layer.
/// </summary>
private readonly List<int> _routedSteadyFieldIndexCollection;
/// <summary>
/// The collection of the varying input fields being routed to the readout layer.
/// </summary>
private readonly List<InputField> _routedVaryingFieldCollection;
/// <summary>
/// The constant length of the external varying data vector or NonFixedVaryingDataVectorLength (-1). (no constraint)
/// </summary>
private int _varyingDataVectorLength;
/// <summary>
/// The steady input data to be processed.
/// </summary>
private double[] _steadyData;
/// <summary>
/// The varying input data to be processed.
/// </summary>
private readonly List<double[]> _inputDataQueue;
/// <summary>
/// The number of already processed inputs from the queue.
/// </summary>
private int _numOfProcessedInputs;
/// <summary>
/// Indicates the reverse mode of input data processing.
/// </summary>
private bool _reverseMode;
//Constructor
/// <summary>
/// Creates an initialized instance.
/// </summary>
/// <param name="inputEncoderCfg">The configuration of the input encoder.</param>
public InputEncoder(InputEncoderSettings inputEncoderCfg)
{
_encoderCfg = (InputEncoderSettings)inputEncoderCfg.DeepClone();
//Steady fields
_numOfSteadyFields = 0;
_routedSteadyFieldIndexCollection = new List<int>();
if (_encoderCfg.FeedingCfg.FeedingType == InputFeedingType.Patterned)
{
FeedingPatternedSettings fps = (FeedingPatternedSettings)_encoderCfg.FeedingCfg;
if (fps.SteadyFieldsCfg != null)
{
_numOfSteadyFields = fps.SteadyFieldsCfg.FieldCfgCollection.Count;
for (int i = 0; i < fps.SteadyFieldsCfg.FieldCfgCollection.Count; i++)
{
if (fps.SteadyFieldsCfg.FieldCfgCollection[i].RouteToReadout)
{
_routedSteadyFieldIndexCollection.Add(i);
}
}
}
}
//Varying fields
_varyingFields = new List<InputField>(_encoderCfg.VaryingFieldsCfg.TotalNumOfFields);
int[] coordinates = _encoderCfg.CoordinatesCfg.GetCoordinates();
int fieldIdx = _numOfSteadyFields;
int inputNeuronStartIdx = 0;
//External fields
foreach (ExternalFieldSettings fieldCfg in _encoderCfg.VaryingFieldsCfg.ExternalFieldsCfg.FieldCfgCollection)
{
_varyingFields.Add(new InputField(fieldCfg.Name,
fieldIdx++,
coordinates,
Interval.IntN1P1,
fieldCfg.FeatureFilterCfg,
_encoderCfg.VaryingFieldsCfg.InputSpikesCoderCfg,
(fieldCfg.RouteToReadout && _encoderCfg.VaryingFieldsCfg.RouteToReadout),
inputNeuronStartIdx
));
inputNeuronStartIdx += _varyingFields[(fieldIdx - _numOfSteadyFields) - 1].NumOfInputNeurons;
}
//Internal input transformers and fields
_internalInputTransformerCollection = new List<ITransformer>();
if (_encoderCfg.VaryingFieldsCfg.TransformedFieldsCfg != null)
{
List<string> names = _encoderCfg.VaryingFieldsCfg.GetNames();
foreach (TransformedFieldSettings fieldCfg in _encoderCfg.VaryingFieldsCfg.TransformedFieldsCfg.FieldCfgCollection)
{
_internalInputTransformerCollection.Add(TransformerFactory.Create(names, fieldCfg.TransformerCfg));
_varyingFields.Add(new InputField(fieldCfg.Name,
fieldIdx++,
coordinates,
Interval.IntN1P1,
fieldCfg.FeatureFilterCfg,
_encoderCfg.VaryingFieldsCfg.InputSpikesCoderCfg,
(fieldCfg.RouteToReadout && _encoderCfg.VaryingFieldsCfg.RouteToReadout),
inputNeuronStartIdx
));
inputNeuronStartIdx += _varyingFields[(fieldIdx - _numOfSteadyFields) - 1].NumOfInputNeurons;
}
}
//Internal input generators and fields
_internalInputGeneratorCollection = new List<IGenerator>();
if (_encoderCfg.VaryingFieldsCfg.GeneratedFieldsCfg != null)
{
foreach (GeneratedFieldSettings fieldCfg in _encoderCfg.VaryingFieldsCfg.GeneratedFieldsCfg.FieldCfgCollection)
{
_internalInputGeneratorCollection.Add(GeneratorFactory.Create(fieldCfg.GeneratorCfg));
_varyingFields.Add(new InputField(fieldCfg.Name,
fieldIdx++,
coordinates,
Interval.IntN1P1,
fieldCfg.FeatureFilterCfg,
_encoderCfg.VaryingFieldsCfg.InputSpikesCoderCfg,
(fieldCfg.RouteToReadout && _encoderCfg.VaryingFieldsCfg.RouteToReadout),
inputNeuronStartIdx
));
inputNeuronStartIdx += _varyingFields[(fieldIdx - _numOfSteadyFields) - 1].NumOfInputNeurons;
}
}
_routedVaryingFieldCollection = new List<InputField>(_varyingFields.Count);
foreach (InputField field in _varyingFields)
{
if (field.RouteToReadout)
{
_routedVaryingFieldCollection.Add(field);
}
}
_varyingDataVectorLength = NonFixedVaryingDataVectorLength;
NumOfTimePoints = VariableNumOfTimePoints;
NumOfRoutedValues = 0;
//Input processing queue
_inputDataQueue = new List<double[]>();
ResetInputProcessingQueue();
return;
}
//Properties
/// <summary>
/// The number of remaining stored inputs to be processed.
/// </summary>
public int NumOfRemainingInputs { get { return _inputDataQueue.Count - _numOfProcessedInputs; } }
//Methods
/// <summary>
/// Gets the varying input field object by name.
/// </summary>
/// <param name="name">The varying input field name.</param>
/// <returns>An InputField instance when found or null when not found.</returns>
public InputField GetVaryingInputField(string name)
{
foreach (InputField field in _varyingFields)
{
if (field.Name == name)
{
return field;
}
}
return null;
}
/// <summary>
/// Resets the internal input buffers.
/// </summary>
private void ResetInputProcessingQueue()
{
_steadyData = null;
_inputDataQueue.Clear();
_numOfProcessedInputs = 0;
_reverseMode = false;
return;
}
/// <summary>
/// Resets all internal transformers and generators to their initial state.
/// </summary>
private void ResetTransformersAndGenerators()
{
//Reset transformers
foreach (ITransformer transformer in _internalInputTransformerCollection)
{
transformer.Reset();
}
//Reset generators
foreach (IGenerator generator in _internalInputGeneratorCollection)
{
generator.Reset();
}
return;
}
/// <summary>
/// Resets all input neurons to their initial state.
/// </summary>
/// <param name="resetStatistics">Specifies whether to reset also neurons' internal statistics.</param>
private void ResetInputNeurons(bool resetStatistics)
{
//Reset input neurons in all input fields
foreach (InputField field in _varyingFields)
{
field.ResetNeurons(resetStatistics);
}
return;
}
/// <summary>
/// Resets all feature filters to their initial state.
/// </summary>
private void ResetFeatureFilters()
{
foreach (InputField field in _varyingFields)
{
field.ResetFilter();
}
return;
}
/// <summary>
/// Resets the input encoder to its initial state.
/// </summary>
public void Reset()
{
ResetInputProcessingQueue();
ResetTransformersAndGenerators();
ResetInputNeurons(true);
ResetFeatureFilters();
_varyingDataVectorLength = NonFixedVaryingDataVectorLength;
NumOfTimePoints = VariableNumOfTimePoints;
NumOfRoutedValues = 0;
return;
}
/// <summary>
/// Adds inputs from internal transformers and generators.
/// </summary>
/// <param name="externalInputVector">An external input vector.</param>
private double[] AddInternalInputs(double[] externalInputVector)
{
if (_encoderCfg.VaryingFieldsCfg.TotalNumOfFields == externalInputVector.Length)
{
//Defined no internal fields
return externalInputVector;
}
double[] inputVector = new double[_encoderCfg.VaryingFieldsCfg.TotalNumOfFields];
inputVector.Populate(double.NaN);
//Original external data
externalInputVector.CopyTo(inputVector, 0);
int index = externalInputVector.Length;
//Transformed fields
foreach (ITransformer transformer in _internalInputTransformerCollection)
{
inputVector[index++] = transformer.Transform(inputVector);
}
//Generated fields
foreach (IGenerator generator in _internalInputGeneratorCollection)
{
inputVector[index++] = generator.Next();
}
return inputVector;
}
/// <summary>
/// Adds inputs from internal transformers and generators.
/// </summary>
/// <param name="inputVectors">The collection of external input vectors</param>
private List<double[]> AddInternalInputs(List<double[]> inputVectors)
{
List<double[]> outputVectors = new List<double[]>(inputVectors.Count);
for (int i = 0; i < inputVectors.Count; i++)
{
outputVectors.Add(AddInternalInputs(inputVectors[i]));
}
return outputVectors;
}
/// <summary>
/// Adds inputs from internal transformers and generators and converts an input pattern to series of vectors.
/// </summary>
/// <param name="inputPattern">An input pattern.</param>
private List<double[]> CompleteInputPattern(InputPattern inputPattern)
{
//Reset transformers and generators
ResetTransformersAndGenerators();
//Convert pattern to completed vectors having added internal inputs from transformers and generators
int inputPatternTimePoints = inputPattern.VariablesDataCollection[0].Length;
List<double[]> completedVectors = new List<double[]>(inputPatternTimePoints);
for (int timePointIndex = 0; timePointIndex < inputPatternTimePoints; timePointIndex++)
{
double[] externalInputVector = inputPattern.GetDataAtTimePoint(timePointIndex);
double[] completedVector = AddInternalInputs(externalInputVector);
completedVectors.Add(completedVector);
}
return completedVectors;
}
/// <summary>
/// Updates the input feature filters.
/// </summary>
/// <param name="inputVectorCollection">The collection of input vectors.</param>
private void UpdateFeatureFilters(List<double[]> inputVectorCollection)
{
Parallel.For(0, _varyingFields.Count, i =>
{
//Update filter
foreach (double[] vector in inputVectorCollection)
{
_varyingFields[i].UpdateFilter(vector[i]);
}
});
return;
}
/// <summary>
/// Validates the length of the external input vector.
/// </summary>
/// <param name="extInputVectorLength">The length of the external input vector.</param>
private void ValidateExtInputVectorLength(int extInputVectorLength)
{
//Check the length
if (_varyingDataVectorLength != NonFixedVaryingDataVectorLength && extInputVectorLength != _varyingDataVectorLength)
{
throw new InvalidOperationException($"The number of the time-points must be constant ({_varyingDataVectorLength}).");
}
return;
}
/// <summary>
/// Splits an external input vector to a steady part and a varying part.
/// </summary>
/// <param name="extInputVector">An external input vector.</param>
/// <param name="steadyVector">An output steady data vector.</param>
/// <param name="varyingVector">An output varying data vector.</param>
private void SplitSteadyAndVaryingInputData(double[] extInputVector, out double[] steadyVector, out double[] varyingVector)
{
//Separate steady and varying data
if (_numOfSteadyFields > 0)
{
//Steady data
steadyVector = new double[_numOfSteadyFields];
for (int i = 0; i < _numOfSteadyFields; i++)
{
steadyVector[i] = extInputVector[i];
}
//Varying data
varyingVector = new double[extInputVector.Length - _numOfSteadyFields];
for (int i = 0; i < varyingVector.Length; i++)
{
varyingVector[i] = extInputVector[_numOfSteadyFields + i];
}
}
else
{
//Steady data
steadyVector = null;
//Varying data
varyingVector = extInputVector;
}
return;
}
/// <summary>
/// Initializes the input encoder and its feature filters from the specified samples data bundle.
/// </summary>
/// <param name="inputBundle">Sample input data</param>
public void Initialize(VectorBundle inputBundle)
{
//Full reset
Reset();
if (_encoderCfg.FeedingCfg.FeedingType == InputFeedingType.Continuous)
{
//Continuous feeding
//Fixed lengths
_varyingDataVectorLength = inputBundle.InputVectorCollection[0].Length;
NumOfTimePoints = 1;
//Add internal inputs and initialize feature filters
UpdateFeatureFilters(AddInternalInputs(inputBundle.InputVectorCollection));
}
else
{
//Patterned feeding
FeedingPatternedSettings feedingPatternedCfg = (FeedingPatternedSettings)_encoderCfg.FeedingCfg;
//Input pattern length constraint and number of time-points
NumOfTimePoints = feedingPatternedCfg.UnificationCfg.ResamplingCfg.TargetTimePoints != ResamplingSettings.AutoTargetTimePointsNum ? feedingPatternedCfg.UnificationCfg.ResamplingCfg.TargetTimePoints : VariableNumOfTimePoints;
if (NumOfTimePoints == VariableNumOfTimePoints && (_routedVaryingFieldCollection.Count > 0 || feedingPatternedCfg.Slices > 1))
{
//because no resampling, length of external input vector must be fixed to keep consistent data
_varyingDataVectorLength = inputBundle.InputVectorCollection[0].Length - _numOfSteadyFields;
//Number of time-points must be also fixed
NumOfTimePoints = _varyingDataVectorLength / _varyingFields.Count;
}
//Convert input vectors to InputPatterns
foreach (double[] orgVector in inputBundle.InputVectorCollection)
{
//Split steady and varying data
SplitSteadyAndVaryingInputData(orgVector, out double[] steadyVector, out double[] varyingVector);
//Check length of the external varying data vector
ValidateExtInputVectorLength(varyingVector.Length);
//Convert external vector to pattern
FeedingPatternedSettings feedingCfg = (FeedingPatternedSettings)_encoderCfg.FeedingCfg;
InputPattern inputPattern = new InputPattern(varyingVector,
_encoderCfg.VaryingFieldsCfg.ExternalFieldsCfg.FieldCfgCollection.Count,
feedingCfg.VarSchema,
feedingCfg.UnificationCfg.Detrend,
feedingCfg.UnificationCfg.UnifyAmplitude,
feedingCfg.UnificationCfg.ResamplingCfg.SignalBeginThreshold,
feedingCfg.UnificationCfg.ResamplingCfg.SignalEndThreshold,
feedingCfg.UnificationCfg.ResamplingCfg.UniformTimeScale,
NumOfTimePoints == VariableNumOfTimePoints ? ResamplingSettings.AutoTargetTimePointsNum : NumOfTimePoints
);
List<double[]> inputPatternVectors = CompleteInputPattern(inputPattern);
UpdateFeatureFilters(inputPatternVectors);
}
}
//Number of routed input values
NumOfRoutedValues = _routedSteadyFieldIndexCollection.Count;
if (_routedVaryingFieldCollection.Count > 0)
{
NumOfRoutedValues += _routedVaryingFieldCollection.Count * NumOfTimePoints;
}
return;
}
/// <summary>
/// Stores new input data to be processed.
/// </summary>
/// <param name="inputVector">An external input vector.</param>
public void StoreNewData(double[] inputVector)
{
//Reset input data
ResetInputProcessingQueue();
//Store new data
if (_encoderCfg.FeedingCfg.FeedingType == InputFeedingType.Continuous)
{
//Add single vector into the processing queue
_inputDataQueue.Add(AddInternalInputs(inputVector));
}
else
{
//Split steady and varying data
SplitSteadyAndVaryingInputData(inputVector, out _steadyData, out double[] varyingVector);
//Check length of the external varying data vector
ValidateExtInputVectorLength(varyingVector.Length);
//Reset input neurons to initial state
ResetInputNeurons(false);
//Prepare input pattern
FeedingPatternedSettings feedingCfg = (FeedingPatternedSettings)_encoderCfg.FeedingCfg;
InputPattern inputPattern = new InputPattern(varyingVector,
_encoderCfg.VaryingFieldsCfg.ExternalFieldsCfg.FieldCfgCollection.Count,
feedingCfg.VarSchema,
feedingCfg.UnificationCfg.Detrend,
feedingCfg.UnificationCfg.UnifyAmplitude,
feedingCfg.UnificationCfg.ResamplingCfg.SignalBeginThreshold,
feedingCfg.UnificationCfg.ResamplingCfg.SignalEndThreshold,
feedingCfg.UnificationCfg.ResamplingCfg.UniformTimeScale,
NumOfTimePoints == VariableNumOfTimePoints ? ResamplingSettings.AutoTargetTimePointsNum : NumOfTimePoints
);
_inputDataQueue.AddRange(CompleteInputPattern(inputPattern));
}
return;
}
/// <summary>
/// Initializes input fields by the next piece of stored input data (if available).
/// </summary>
public bool EncodeNextInputData()
{
if (_numOfProcessedInputs < _inputDataQueue.Count)
{
for (int i = 0; i < _varyingFields.Count; i++)
{
_varyingFields[i].SetNewData(_inputDataQueue[_numOfProcessedInputs][i]);
}
++_numOfProcessedInputs;
return true;
}
return false;
}
/// <summary>
/// Fetches the encoded data from the input fields into the input neurons.
/// </summary>
/// <param name="collectStatistics">Specifies whether to update internal statistics of the input neurons.</param>
public bool Fetch(bool collectStatistics)
{
foreach (InputField field in _varyingFields)
{
if (!field.Fetch(collectStatistics))
{
return false;
}
}
return true;
}
/// <summary>
/// Changes an order of input data and resets the counter of processed inputs.
/// </summary>
public void SetReverseMode()
{
//Checks
if (_reverseMode)
{
throw new InvalidOperationException($"Can't set reverse mode. Input encoder is already in reverse mode.");
}
if (_encoderCfg.FeedingCfg.FeedingType != InputFeedingType.Patterned)
{
throw new InvalidOperationException($"Illegal call to set reverse mode. Reverse mode is relevant only for patterned feeding regime.");
}
//Reset input neurons to initial state
ResetInputNeurons(false);
//Reverse processing queue
_inputDataQueue.Reverse();
_numOfProcessedInputs = 0;
_reverseMode = true;
return;
}
/// <summary>
/// Gets the collection of predictor descriptor objects of the inputs being routed to readout layer.
/// </summary>
public List<PredictorDescriptor> GetPredictorsDescriptorsOfRoutedInputs()
{
//Build descriptors
List<PredictorDescriptor> result = new List<PredictorDescriptor>(_routedSteadyFieldIndexCollection.Count + _routedVaryingFieldCollection.Count * NumOfTimePoints);
//Steady fields
foreach (int idx in _routedSteadyFieldIndexCollection)
{
result.Add(new PredictorDescriptor(((FeedingPatternedSettings)_encoderCfg.FeedingCfg).SteadyFieldsCfg.FieldCfgCollection[idx].Name));
}
//Varying fields
foreach (InputField field in _routedVaryingFieldCollection)
{
for (int i = 0; i < NumOfTimePoints; i++)
{
result.Add(new PredictorDescriptor(field.Name));
}
}
return result;
}
/// <summary>
/// Copies all routed inputs into a buffer.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="fromOffset">The zero-based position within the buffer where to start copying to.</param>
/// <returns>The number of copied values.</returns>
public int CopyRoutedInputsTo(double[] buffer, int fromOffset)
{
int count = 0;
//Steady fields
foreach (int idx in _routedSteadyFieldIndexCollection)
{
buffer[fromOffset++] = _steadyData[idx];
++count;
}
//Varying fields
foreach (InputField field in _routedVaryingFieldCollection)
{
for (int i = 0; i < _inputDataQueue.Count; i++)
{
buffer[fromOffset++] = _inputDataQueue[i][field.Idx];
++count;
}
}
return count;
}
}//InputEncoder
}//Namespace