/// <summary> /// Creates a prototype network, with the given number of inputs and /// outputs. The network starts out maximily connected with axons between /// each pair of input and output nurons. There are no hidden nurons. /// The weight of each axon is initialy set to one. /// </summary> /// <param name="inputs">Number of input nurons</param> /// <param name="outputs">Number of output nurons</param> public NetworkAuto(int inputs, int outputs) { ////initialises the tables for the nurons and axons //nurons = new TableOpen<Int32, Nuron>(256); //axons = new TableOpen<Int32, Axon>(1024); //initialises the tables for the nurons and axons nurons = new TableSystem <Int32, Nuron>(256); axons = new TableSystem <Int32, Axon>(1024); //creates arrays to remember the inputs and outputs this.inputs = new int[inputs]; this.outputs = new int[outputs]; //creates all the input nurons for (int i = 0; i < inputs; i++) { Nuron n = new Nuron(this, ActFunc.Input, i, 0); nurons.Add(n.Index, n); this.inputs[i] = n.Index; //i } //creates all the output nurons for (int i = 0; i < outputs; i++) { Nuron n = new Nuron(this, ActFunc.Sigmoid, MAX_ID - i, MAX_LV); nurons.Add(n.Index, n); this.outputs[i] = n.Index; //MAX_ID - i } //adds conecitons between all the nodes Initialise(); }
/// <summary> /// Helper mehtod: Selects a pair of nurons at random from diffrent /// levels of the network. The nurons are always listed in order. It /// returns false if it was ubale to generate a valid pair. /// </summary> /// <param name="rng">A random number generator</param> /// <param name="n1">The lower level nuron</param> /// <param name="n2">The upper level nuron</param> /// <returns>True if a vaild pair was generated</returns> private bool GetRandomPair(VRandom rng, out Nuron n1, out Nuron n2) { //generates two random nurons n1 = GetRandomNuron(rng); n2 = GetRandomNuron(rng); int count = 0; Nuron n3 = null; //keeps searching while the nurons are on the same level while (n1.Level == n2.Level && count < MAX_TRY) { n3 = GetRandomNuron(rng); n1 = n2; n2 = n3; count++; } //swaps the nurons if they are out of order if (n1.Level > n2.Level) { n3 = n1; n1 = n2; n2 = n3; } //indicates if we found a valid pair return(n1.Level != n2.Level); }
public void Overwrite(NetworkAuto genome) { //NOTE: Need to assert that the inputs and outputs match this.axons.Clear(); this.nurons.Clear(); //used in itterating all the axons and nurons var g_axons = genome.axons.ListItems(); var g_nurons = genome.nurons.ListItems(); foreach (Nuron n1 in g_nurons) { //nurons.Overwrite(n1.Index, n1); Nuron temp = new Nuron(this, n1); nurons.Add(temp.Index, temp); } foreach (Axon a1 in g_axons) { //axons.Overwrite(a1.Index, a1); Axon temp = new Axon(a1); axons.Add(temp.Index, temp); } }
/// <summary> /// Removes unused Nurons and Axons from the network, reducing the overall /// size of the network without effecting it's functionality. /// </summary> public void ReduceNetwork() { var ittr1 = axons.ListItems(); var trash1 = new Stack <Axon>(); foreach (Axon ax in ittr1) { if (ax.Enabled) { continue; } else { trash1.Push(ax); } } while (trash1.Count > 0) { Axon ax = trash1.Pop(); axons.Remove(ax.Index); } var ittr2 = nurons.ListItems(); var trash2 = new Stack <Nuron>(); foreach (Nuron n in ittr2) { var ittr3 = axons.ListItems(); bool clear = false; foreach (Axon ax in ittr3) { if (ax.Source == n.Index || ax.Target == n.Index) { clear = true; break; } } if (clear) { continue; } else { trash2.Push(n); } } while (trash2.Count > 0) { Nuron n = trash2.Pop(); nurons.Remove(n.Index); } }
public void SetInput(Vector data) { //fills each of the input nurons with the vector data for (int i = 0; i < inputs.Length; i++) { Nuron n = nurons.GetValue(inputs[i]); n.Value = data.GetExtended(i); n.Prev = n.Value; } }
public Vector ReadOutput() { //creates a new vector to hold the result Vector result = new Vector(outputs.Length); //copies the output nurons into the result vector for (int i = 0; i < outputs.Length; i++) { Nuron n = nurons.GetValue(outputs[i]); result[i] = n.Value; } //returns the result return(result); }
public NetworkAuto(NetworkAuto other) { //copies the global settings this.recurent = other.recurent; //obtains the raw statistics of the opposing network int ninputs = other.inputs.Length; int noutputs = other.outputs.Length; int nnurons = other.nurons.Count; int naxons = other.axons.Count; //makes tables large enough to hold the nurons and axons nurons = new TableSystem <Int32, Nuron>(nnurons); axons = new TableSystem <Int32, Axon>(naxons); //dose the same for the inputs and outputs inputs = new int[ninputs]; outputs = new int[noutputs]; //makes copies of all the nurons in the original network var ittr1 = other.nurons.ListItems(); foreach (Nuron n in ittr1) { Nuron temp = new Nuron(this, n); nurons.Add(temp.Index, temp); } //makes copies of all the axons in the original network var ittr2 = other.axons.ListItems(); foreach (Axon ax in ittr2) { Axon temp = new Axon(ax); axons.Add(temp.Index, temp); } //copies the input and output indicies for (int i = 0; i < inputs.Length; i++) { this.inputs[i] = other.inputs[i]; } for (int i = 0; i < outputs.Length; i++) { this.outputs[i] = other.outputs[i]; } }
public void WriteOutputTo(Vector result) { //enshures that the result vector can hold the output if (result.Length != outputs.Length) { throw new ArgumentException ("Reslut vector dose not match network topology.", "result"); } //copies the output nurons into the result vector for (int i = 0; i < outputs.Length; i++) { Nuron n = nurons.GetValue(outputs[i]); result[i] = n.Value; } }
public void Propergate() { var ittr0 = nurons.ListItems(); foreach (Nuron nx in ittr0) { //Skips input nurons if (nx.IsInput) { continue; } //clears the value and updates the previous value nx.Prev = nx.Value; nx.Value = 0.0; } var ittr1 = axons.ListItems(); foreach (Axon ax in ittr1) { //skips disabled nurons if (!ax.Enabled) { continue; } //obtains both nurons from the axon Nuron n1 = nurons.GetValue(ax.Source); Nuron n2 = nurons.GetValue(ax.Target); //updates the target based on the input n2.Value += (n1.Prev * ax.Weight); } var ittr2 = nurons.ListItems(); foreach (Nuron nx in ittr2) { //activates each of the nurons nx.Activate(); } }
private void Expand(VRandom rng) { Nuron n1, n2; //generates a pair of random nurons on diffrent levels bool pass = GetRandomPair(rng, out n1, out n2); if (!pass) { return; } //determins if this should be a recurent conneciton bool testrec = recurent; testrec = testrec && !n1.IsInput; testrec = testrec && rng.RandBool(P_Recur); if (testrec) { Nuron nx = n1; n1 = n2; n2 = nx; } //creates a temporary axon between the two nurons double w = rng.RandGauss() * SD_NEW; Axon temp = new Axon(n1.Index, n2.Index, w); //atempts to gain the actual axon if it exists Axon actual = axons.GetValue(temp.Index); if (actual == null) { //adds the new axon into the network axons.Add(temp.Index, temp); } else if (actual.Enabled == false) { //reneables the axon and updates it weight actual.Enabled = true; actual.Weight = temp.Weight; } else { //determins if we are able to insert a new node int nid1 = GetRandomIndex(rng); if (nid1 < 0) { return; } //sets the level of the new node in the middle if (Math.Abs(n1.Level - n2.Level) < 3) { return; } int level = (n1.Level + n2.Level) / 2; //adds a new node to the network ActFunc act = GetRandomActivation(rng); Nuron n3 = new Nuron(this, act, nid1, level); nurons.Add(n3.Index, n3); //inserts two new axons where the old one used to be int nid0 = actual.Source; int nid2 = actual.Target; //Axon ax1 = new Axon(nid0, nid1, actual.Weight); //Axon ax2 = new Axon(nid1, nid2, temp.Weight); Axon ax1 = new Axon(nid0, nid1, actual.Weight); Axon ax2 = new Axon(nid1, nid2, 1.0); //we use the overwitre comand because there may be hash collisions axons.Overwrite(ax1.Index, ax1); axons.Overwrite(ax2.Index, ax2); //deactivates the old axon actual.Enabled = false; } }
public void Crossover(VRandom rng, NetworkAuto genome) { //throw new NotImplementedException(); //determins weather or not to do liniar crossover bool liniar = rng.RandBool(P_Linear); double a = rng.NextDouble(); //lists all the axons and nurons in the mate var ittr1 = genome.nurons.ListItems(); var ittr2 = genome.axons.ListItems(); foreach (Nuron n in ittr1) { //obtains the matching child nuron Nuron nc = nurons.GetValue(n.Index); if (nc == null) { //adds the missing nuron nc = new Nuron(this, n); nurons.Add(nc.Index, nc); } //else //{ // //determins the activation based on crossover // bool cross = rng.RandBool(); // if (cross) nc.Func = n.Func; //} } foreach (Axon ax in ittr2) { //obtains the matching child axon Axon axc = axons.GetValue(ax.Index); if (axc == null) { //adds the missing axon, but disabled axc = new Axon(ax); axc.Enabled = false; axons.Add(axc.Index, axc); } else { if (liniar) { //chooses a value between the two weights double weight = axc.Weight * (1.0 - a); axc.Weight = weight + (ax.Weight * a); } else { //determins the new weight based on crossover bool cross = rng.RandBool(); if (cross) { axc.Weight = ax.Weight; } } //if the axon is present in both networks, it has a //strong chance of becoming enabled bool en = ax.Enabled && axc.Enabled; axc.Enabled = en || rng.RandBool(0.25); } } }
public void Overwrite2(NetworkAuto genome) { //used in itterating all the axons and nurons var g_axons = genome.axons.ListItems(); var g_nurons = genome.nurons.ListItems(); foreach (Nuron n1 in g_nurons) { //tries to find the matching nuron in the current network Nuron n0 = nurons.GetValue(n1.Index); if (n0 != null) { ////copies the genome data if it finds a match //n0.Func = n1.Func; } else { //creates a copy of the first nurons and adds it n0 = new Nuron(this, n1); nurons.Add(n0.Index, n0); } } foreach (Axon a1 in g_axons) { //tries to find the matching axon in the current network Axon a0 = axons.GetValue(a1.Index); if (a0 != null) { //copies the genome data if it finds a match a0.Weight = a1.Weight; a0.Enabled = a1.Enabled; } else { //creates a copy of the first axon and adds it a0 = new Axon(a1); axons.Add(a0.Index, a0); } } //////////////////////////////////////////////////////////////////// //used to clean up the remaining Axons int count1 = genome.axons.Count - axons.Count; count1 = Math.Min(count1, 0) + 8; var trash1 = new DequeArray <Axon>(count1); var ittr1 = axons.ListItems(); //marks missing Axons for deletion foreach (Axon a in ittr1) { if (genome.axons.HasKey(a.Index)) { continue; } else { trash1.PushFront(a); } } //deletes the missing Axons while (!trash1.Empty) { Axon del = trash1.PopFront(); axons.Remove(del.Index); } //used to clean up the remaining Nurons int count2 = genome.nurons.Count - nurons.Count; count2 = Math.Min(count2, 0) + 8; var trash2 = new DequeArray <Nuron>(count2); var ittr2 = nurons.ListItems(); //marks missing Nurons for deletion foreach (Nuron n in ittr2) { if (genome.nurons.HasKey(n.Index)) { continue; } else { trash2.PushFront(n); } } //deletes the missing Nurons while (!trash2.Empty) { Nuron del = trash2.PopFront(); nurons.Remove(del.Index); del.ClearData(); } trash1.Dispose(); trash2.Dispose(); }