using System; using System.Collections.Generic; using System.Collections; using System.Linq; using System.Text; namespace BCMToolbox { public interface INetwork : IEnumerable { int Count { get; } object SyncRoot { get; } double this[int indexer] { get; } double this[int from, int to] { get; } string Identification { get; } int UID { get; } int Ticks { get; } void Initialize(Func initializerWeights, Func initializerPotentials); void Initialize(double hiBoundaryWeights, double hiBoundaryPotentials); void ApplyInputs(double[] inputs); void Propagate(); event EventHandler WeightsChanged; event EventHandler PotentialsChanged; event EventHandler TickProgress; } public interface INetworkMonitor { Func KernelFunction { get; } void RegisterNorm(double[] newNorm); } [Serializable] public class NetworkState : INetwork { double[,] __weights = null; double[] __outputs = null; object __syncRoot = new object(); int __uid = 0; int __ticks = 0; string __ident = null; public NetworkState(INetwork copyFrom) { __weights = new double[copyFrom.Count, copyFrom.Count]; __outputs = new double[copyFrom.Count]; __uid = copyFrom.UID; __ident = copyFrom.Identification; lock (copyFrom.SyncRoot) { __ticks = copyFrom.Ticks; for (int i = 0; i < copyFrom.Count; i++) { __outputs[i] = copyFrom[i]; for (int j = 0; j < copyFrom.Count; j++) __weights[i, j] = copyFrom[i, j]; } } } #region INetwork Members public int Count { get { return __outputs.Length; } } public object SyncRoot { get { return __syncRoot; } } public double this[int indexer] { get { return __outputs[indexer]; } } public double this[int from, int to] { get { return __weights[from, to]; } } public string Identification { get { return __ident; } } public int UID { get { return __uid; } } public int Ticks { get { return __ticks; } } public void Initialize(Func initializerWeights, Func initializerPotentials) { throw new NotSupportedException("This is but a lifeless clone."); } public void Initialize(double hiBoundaryWeights, double hiBoundaryPotentials) { throw new NotSupportedException("This is but a lifeless clone."); } public void ApplyInputs(double[] inputs) { throw new NotSupportedException("This is but a lifeless clone."); } public void Propagate() { throw new NotSupportedException("This is but a lifeless clone."); } public event EventHandler WeightsChanged; public event EventHandler PotentialsChanged; public event EventHandler TickProgress; #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { return __outputs.GetEnumerator(); } #endregion } public abstract class TraceableNetwork : INetwork { object __syncRoot = new object(); int __uid = 0; int __ticks = 0; protected TraceableNetwork(int newUID) { __uid = newUID; } public override string ToString() { StringBuilder toRet = new StringBuilder(); for (int i = 0; i < this.Count; i++) { toRet.AppendLine(""); toRet.AppendFormat("{0} -> ", this[i].ToString("#0.0000")); for (int j = 0; j < this.Count; j++) toRet.AppendFormat("{0} ", this[i, j].ToString("#0.0000")); } toRet.AppendLine(""); return toRet.ToString(); } #region Network State Duplicates NetworkState __lastState = null; public NetworkState BuildNetworkState() { __lastState = new NetworkState(this); if (this.NetworkStateRefreshed != null) this.NetworkStateRefreshed(this, EventArgs.Empty); return __lastState; } public NetworkState GetLastNetworkState() { return __lastState; } public event EventHandler NetworkStateRefreshed; #endregion #region INetwork Members public abstract int Count { get; } public object SyncRoot { get { return __syncRoot; } } public abstract double this[int indexer] { get; internal set; } public abstract double this[int from, int to] { get; internal set; } public abstract string Identification { get; } public int UID { get { return __uid; } } public int Ticks { get { return __ticks; } } public virtual void Initialize(Func initializerWeights, Func initializerPotentials) { lock (SyncRoot) { for (int i = 0; i < this.Count; i++) for (int j = 0; j < Count; j++) if (!double.IsNaN(this[i, j])) this[i, j] = initializerWeights(i, j); for (int i = 0; i < this.Count; i++) this[i] = initializerPotentials(i); } __ticks = 0; if (this.PotentialsChanged != null) this.PotentialsChanged(this, EventArgs.Empty); if (this.WeightsChanged != null) this.WeightsChanged(this, EventArgs.Empty); } // Initializes using a uniform random number distribution with two boundaries public void Initialize(double hiBoundaryWeights, double hiBoundaryPotentials) { Random r = new Random(); Initialize( // (i, j) => (r.NextDouble() * 2 * hiBoundaryWeights - hiBoundaryWeights), i => (r.NextDouble() * hiBoundaryPotentials)); (i, j) => (r.NextDouble() * hiBoundaryWeights), i => (r.NextDouble() * hiBoundaryPotentials)); } public virtual void ApplyInputs(double[] inputs) { this.OnPotentialsChanged(); } public virtual void Propagate() { __ticks++; this.OnPotentialsChanged(); this.OnWeightsChanged(); this.OnTickProgress(); UpdateMonitors(); } protected void OnPotentialsChanged() { if (this.PotentialsChanged != null) this.PotentialsChanged(this, EventArgs.Empty); } protected void OnWeightsChanged() { if (this.WeightsChanged != null) this.WeightsChanged(this, EventArgs.Empty); } protected void OnTickProgress() { if (this.TickProgress != null) this.TickProgress(this, EventArgs.Empty); } public event EventHandler WeightsChanged; public event EventHandler PotentialsChanged; public event EventHandler TickProgress; #endregion #region IEnumerable Members public abstract IEnumerator GetEnumerator(); #endregion #region Graphing With Kernels List __monitors = new List(); public void RegisterMonitor(INetworkMonitor newMonitor) { lock (__syncRoot) __monitors.Add(newMonitor); } void UpdateMonitors() { foreach (INetworkMonitor inm in __monitors) { double[] norm = inm.KernelFunction(this); inm.RegisterNorm(norm); } } #endregion #region Utilities public void NormalizeWeights(double degree) { double sum = 0.0; if (degree != 2.0) { for (int i = 0; i < Count; i++) for (int j = 0; j < Count; j++) if ((i != j) && !double.IsNaN(this[i, j])) sum += Math.Pow(this[i, j], degree); sum = Math.Pow(sum, 1 / degree); } else { for (int i = 0; i < Count; i++) for (int j = 0; j < Count; j++) if ((i != j) && !double.IsNaN(this[i, j])) sum += this[i,j]*this[i,j]; sum = Math.Sqrt(sum); } for (int i = 0; i < Count; i++) for (int j = 0; j < Count; j++) if ((i != j) && !double.IsNaN(this[i, j])) this[i, j] = this[i, j] / sum; } public void NormalizePotentials(double degree) { double sum = 0.0; if (degree != 2.0) { for (int i = 0; i < Count; i++) sum += Math.Pow(this[i], degree); sum = Math.Pow(sum, 1 / degree); } else { for (int i = 0; i < Count; i++) sum += this[i] * this[i]; sum = Math.Sqrt(sum); } for (int i = 0; i < Count; i++) this[i] = this[i] / sum; } #endregion } public abstract class FixedTraceableNetwork : TraceableNetwork { protected double[,] __weights = null; protected double[] __potentials = null; protected FixedTraceableNetwork(int neuronCount, int newUID) : base(newUID) { __weights = new double[neuronCount, neuronCount]; __potentials = new double[neuronCount]; } public override int Count { get { return __potentials.Length; } } public override double this[int indexer] { get { return __potentials[indexer]; } internal set { __potentials[indexer] = value; } } public override double this[int from, int to] { get { return __weights[from, to]; } internal set { __weights[from, to] = value; } } public override System.Collections.IEnumerator GetEnumerator() { return __potentials.GetEnumerator(); } } }