package za.redbridge.experiment.MMNEAT.training.opp;

import org.encog.engine.network.activation.ActivationFunction;
import org.encog.mathutil.randomize.RangeRandomizer;
import org.encog.ml.ea.genome.Genome;
import org.encog.neural.neat.NEATNeuronType;
import org.encog.neural.neat.NEATPopulation;
import org.encog.neural.neat.training.NEATGenome;
import org.encog.neural.neat.training.NEATInnovation;
import org.encog.neural.neat.training.NEATLinkGene;
import org.encog.neural.neat.training.opp.NEATMutation;

import java.util.Random;

import za.redbridge.experiment.MMNEAT.training.MMNEATNeuronGene;

/**
 * Created by jamie on 2014/09/20.
 */
public class MMNEATMutateAddNode extends NEATMutation {

    @Override
    public void performOperation(Random rnd, Genome[] parents, int parentIndex, Genome[] offspring,
            int offspringIndex) {
        final NEATGenome target = obtainGenome(parents, parentIndex, offspring,
                offspringIndex);
        int countTrysToFindOldLink = getOwner().getMaxTries();

        final NEATPopulation pop = ((NEATPopulation) target.getPopulation());

        // the link to split
        NEATLinkGene splitLink = null;

        final int sizeBias = ((NEATGenome)parents[0]).getInputCount()
                + ((NEATGenome)parents[0]).getOutputCount() + 10;

        // if there are not at least
        int upperLimit;
        if (target.getLinksChromosome().size() < sizeBias) {
            upperLimit = target.getNumGenes() - 1
                    - (int) Math.sqrt(target.getNumGenes());
        } else {
            upperLimit = target.getNumGenes() - 1;
        }

        while ((countTrysToFindOldLink--) > 0) {
            // choose a link, use the square root to prefer the older links
            final int i = RangeRandomizer.randomInt(0, upperLimit);
            final NEATLinkGene link = target.getLinksChromosome().get(i);

            // get the from neuron
            final long fromNeuron = link.getFromNeuronID();

            if ((link.isEnabled())
                    && (target.getNeuronsChromosome()
                    .get(getElementPos(target, fromNeuron))
                    .getNeuronType() != NEATNeuronType.Bias)) {
                splitLink = link;
                break;
            }
        }

        if (splitLink == null) {
            return;
        }

        splitLink.setEnabled(false);

        final long from = splitLink.getFromNeuronID();
        final long to = splitLink.getToNeuronID();

        final NEATInnovation innovation = ((NEATPopulation)getOwner().getPopulation()).getInnovations()
                .findInnovationSplit(from, to);

        // add the splitting neuron
        final ActivationFunction af = ((NEATPopulation)getOwner().getPopulation())
                .getActivationFunctions().pick(new Random());

        target.getNeuronsChromosome().add(
                new MMNEATNeuronGene(NEATNeuronType.Hidden, af, innovation
                        .getNeuronID(), innovation.getInnovationID()));

        // add the other two sides of the link
        createLink(target, from, innovation.getNeuronID(),
                splitLink.getWeight());
        createLink(target, innovation.getNeuronID(), to, pop.getWeightRange());

        target.sortGenes();
    }

}

@@ -114,61 +114,8 @@
 on;%0A
-import org.encog.mathutil.randomize.RangeRandomizer;%0A
 impo
@@ -394,16 +394,70 @@
 nkGene;%0A
+import org.encog.neural.neat.training.NEATNeuronGene;%0A
 import o
@@ -924,32 +924,16 @@
 fspring,
-%0A               
  offspri
@@ -1188,32 +1188,33 @@
  = ((NEATGenome)
+ 
 parents%5B0%5D).getI
@@ -1256,16 +1256,17 @@
 TGenome)
+ 
 parents%5B
@@ -1464,36 +1464,16 @@
 es() - 1
-%0A                   
  - (int)
@@ -1599,17 +1599,16 @@
   while 
-(
 (countTr
@@ -1624,17 +1624,16 @@
 ldLink--
-)
  %3E 0) %7B%0A
@@ -1738,36 +1738,33 @@
 i = 
-RangeRandomizer.randomInt(0,
+(int) (rnd.nextDouble() *
  upp
@@ -1959,17 +1959,16 @@
      if 
-(
 (link.is
@@ -1977,16 +1977,18 @@
 abled())
+ %7B
 %0A       
@@ -2000,108 +2000,149 @@
     
-    && (target.getNeuronsChromosome()%0A                    .get(getElementPos(target, fromNeuron))%0A  
+int genePosition = getElementPos(target, fromNeuron);%0A                NEATNeuronGene gene = target.getNeuronsChromosome().get(genePosition);%0A
     
@@ -2145,34 +2145,40 @@
                 
-  
+if (gene
 .getNeuronType()
@@ -2201,17 +2201,16 @@
 pe.Bias)
-)
  %7B%0A     
@@ -2212,32 +2212,36 @@
                 
+    
 splitLink = link
@@ -2262,15 +2262,37 @@
     
+    
 break;%0A
+                %7D%0A
     
@@ -2611,25 +2611,8 @@
 n())
-.getInnovations()
 %0A   
@@ -2624,16 +2624,33 @@
         
+.getInnovations()
 .findInn
@@ -2843,21 +2843,14 @@
 pick
-(new Random()
+First(
 );%0A%0A
@@ -2891,33 +2891,16 @@
 e().add(
-%0A                
 new MMNE
@@ -2938,27 +2938,16 @@
 den, af,
- innovation
 %0A       
@@ -2951,32 +2951,34 @@
             
-        
+innovation
 .getNeuronID

Clean up MMNEATMutateAddNode