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 double Compare(NetworkAuto genome) { //used in computing the distance int match = 0; int disjoint = 0; double wbar = 0.0; //lists the axons in each of the networks var ittr1 = this.axons.ListItems(); var ittr2 = genome.axons.ListItems(); foreach (Axon ax1 in ittr1) { //tries to find the matching axon Axon ax2 = genome.axons.GetValue(ax1.Index); if (ax2 != null) { //computes the distance bteween the weights double w1 = ax1.Weight; double w2 = ax2.Weight; wbar += Math.Abs(w1 - w2); match += 1; } else { //counts the disjoint nodes disjoint += 1; } } foreach (Axon ax1 in ittr2) { //counts the disjoint edges from the other network bool test = this.axons.HasKey(ax1.Index); if (!test) { disjoint += 1; } } //determins the size of the larger network int size = Math.Max(this.NumAxons, genome.NumAxons); //size = (size > 20) ? size - 20 : 1; //couputes the distance for specisation double dist = (C0 * disjoint) / (double)size; dist += C1 * (wbar / (double)match); return(dist); }
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]; } }
//In this method we assume a standard mutation rate of 1.0; public void Mutate(VRandom rng, double rate) { //makes shure the rate is positive rate = Math.Abs(rate); double selector = rng.NextDouble(); if (selector < P_EXPAND) { //expands the network Expand(rng); } else if (selector < P_TOGGEL) { Axon ax = GetRandomAxon(rng); if (ax.Enabled) { //outright disables the nuron ax.Enabled = false; } else { //resets the neuron to a large weight ax.Weight = rng.RandGauss() * SD_NEW; ax.Enabled = true; } } else { Axon ax = GetRandomAxon(rng); if (ax.Enabled) { //permutes the weight by a small amount double delta = rng.RandGauss() * SD_SHIFT; ax.Weight = ax.Weight + delta; } else { //resets the nuron to a small weight double delta = rng.RandGauss() * SD_SHIFT; ax.Weight = delta; ax.Enabled = true; } } }
/// <summary> /// Initalizes the network, adding axons between all the input and output /// nurons. Usualy this is done when the network is first instanciated. /// At first, the weights of all connections will be one. In order to get /// the network into a random state, you will need to call the Randomize /// function. /// </summary> private void Initialise() { //creates axons betwen all input-output pairs //and randomizes the coneciton weights for (int i = 0; i < inputs.Length; i++) { for (int j = 0; j < outputs.Length; j++) { Axon ax = new Axon(inputs[i], outputs[j], 1.0); axons.Overwrite(ax.Index, ax); //We need to use the overwrite method here, incase Initialse //has been called before, allowing for reinitializaiton } } }
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(); }