using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BCMToolbox { public class SynchronousOjaNetwork : FixedTraceableNetwork { double[] __intermediaryOutputs = null; double __inertia = 0.005; public SynchronousOjaNetwork(int neuronCount, int newID) : base(neuronCount, newID) { __intermediaryOutputs = new double[neuronCount]; } public override string Identification { get { return String.Format("Oja Layer #{0}", this.UID); } } public double Inertia { get { return __inertia; } set { __inertia = value; } } public override void ApplyInputs(double[] inputs) { lock (SyncRoot) { if (inputs == null) throw new ArgumentNullException(); if (inputs.Length != this.Count) throw new ArgumentException("Invalid input size. Expected: ", this.Count.ToString()); for (int i = 0; i < this.Count; i++) __potentials[i] += inputs[i]; } base.ApplyInputs(inputs); } public override void Propagate() { // calculate outputs for (int i = 0; i < this.Count; i++) { __intermediaryOutputs[i] = 0.0; for (int j = 0; j < this.Count; j++) if ((i != j) && !double.IsNaN(__weights[j, i])) __intermediaryOutputs[i] += __weights[j, i] * __potentials[j]; } // update weights and lock outputs lock (SyncRoot) { for (int i = 0; i < this.Count; i++) for (int j = 0; j < this.Count; j++) { if ((i == j) || double.IsNaN(__weights[i, j])) continue; double delta = __intermediaryOutputs[j]; delta *= __inertia; delta *= __potentials[i] - __intermediaryOutputs[j] * __weights[i, j]; System.Diagnostics.Debug.Assert(!double.IsNaN(delta)); System.Diagnostics.Debug.Assert(!double.IsInfinity(delta)); __weights[i, j] += delta; } //NormalizeWeights(2.0); for (int i = 0; i < this.Count; i++) __potentials[i] = __intermediaryOutputs[i]; } base.Propagate(); } public override void Initialize(Func initializerWeights, Func initializerPotentials) { base.Initialize(initializerWeights, initializerPotentials); NormalizeWeights(2.0); } } }