/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package automenta.spacenet.run.old.graph.neural; import automenta.spacenet.run.old.DefaultGraphBuilder; import automenta.spacenet.plugin.neural.NeuralGraph; import automenta.spacenet.run.ArdorSpacetime; import automenta.spacenet.space.Repeat; import automenta.spacenet.space.Space; import automenta.spacenet.space.geom.Box; import automenta.spacenet.space.geom.Line3D; import automenta.spacenet.space.geom.ProcessBox; import automenta.spacenet.space.geom.graph.GraphBox; import automenta.spacenet.space.geom.graph.arrange.forcedirect.ForceDirecting; import automenta.spacenet.space.geom.graph.arrange.forcedirect.ForceDirecting.ForceDirectedParameters; import com.ardor3d.framework.Canvas; import com.ardor3d.input.Key; import com.ardor3d.input.logical.InputTrigger; import com.ardor3d.input.logical.KeyPressedCondition; import com.ardor3d.input.logical.TriggerAction; import com.ardor3d.input.logical.TwoInputStates; import com.ardor3d.math.Vector3; import com.ardor3d.scenegraph.Spatial; import org.neuroph.core.Connection; import org.neuroph.core.Neuron; import org.neuroph.core.Weight; import org.neuroph.contrib.neat.gen.Evolver; import org.neuroph.contrib.neat.gen.NeuronGene; import org.neuroph.contrib.neat.gen.NeuronType; import org.neuroph.contrib.neat.gen.Organism; import org.neuroph.contrib.neat.experiment.xor.XorFitnessFunction; import java.util.Arrays; import org.neuroph.contrib.neat.gen.impl.SimpleNeatParameters; import org.neuroph.contrib.neat.gen.operations.selector.NaturalSelectionOrganismSelector; import org.neuroph.contrib.neat.gen.operations.speciator.DynamicThresholdSpeciator; import org.neuroph.contrib.neat.gen.persistence.PersistenceException; import org.neuroph.core.NeuralNetwork; import java.util.Observable; import java.util.Observer; /** visualizes a Neuroph NEAT */ // we should add NEAT XOR simulation here and then display winner after each generation // with method like setNeatGenerationWinner public class DemoNeat extends ProcessBox implements Observer { final public static double redrawUpdatePeriod = 4.0; final public static double testUpdatePeriod = 0.25; final public static double weightUpdatePeriod = 0.25; int maxGenerations = 500; private NeuralGraph netGraph; private SimpleNeatParameters neatParams; private Evolver evolver; NeuralNetwork currentNetwork = null; private NeuralNetwork shownNetwork; private GraphBox gb; double rotSpeed = 2.0; double rotHor = 0; double rotVert = 0; private ForceDirecting fd; protected void showNetwork(NeuralNetwork n) { if (shownNetwork != n) { shownNetwork = n; netGraph.setNetwork(n); //fd.forward(5.0); } } @Override public void start() { netGraph = new NeuralGraph(); int substeps = 8; ForceDirectedParameters params = new ForceDirectedParameters(new Vector3(50, 50, 50), 0.003, 0.05, 3.0); fd = new ForceDirecting(params, 0.1, substeps, 0.25) { protected void updateNode(Object n, Box nBox, Vector3 nextSize) { if (n instanceof Neuron) { double v = getNeuronScale((Neuron) n); nextSize.set(v, v, v); //nBox.color(getNeuronColor((Neuron) n)); } } @Override protected void updateEdge(Object e, Space s) { super.updateEdge(e, s); if (e instanceof Connection) { Connection c = (Connection) e; ((Line3D) s).getRadius().set(getConnectionRadius(c.getWeight())); } } }; final DefaultGraphBuilder sp = new DefaultGraphBuilder(); gb = add(new GraphBox(netGraph, sp, fd)); add(new Repeat(redrawUpdatePeriod) { @Override public void update(double t, double dt, Spatial s) { NeuralNetwork nn = currentNetwork; if (nn != null) { showNetwork(nn); } } }); startEvolution(); initControls(); } public void randomInputs(NeuralNetwork ann) { System.out.println("randomizing inputs"); for (Neuron n : ann.getInputNeurons()) { n.setInput((-0.5 + Math.random()) * 2.0); } ann.calculate(); } // public Color getNeuronColor(Neuron n) { // if (!n.hasInputConnections()) { // return Color.Purple; // } // else if (n.getOutConnections().size() == 0) { // return Color.White; // } // else { // return Color.Orange; // } //// float v = (float) ((n.getOutput())); //// return Color.hsb(v, 0.5, 0.5).alpha(0.1); // } public double getNeuronScale(Neuron n) { float v = (float) (0.5f * (n.getOutput() + 1.0)); //return Math.pow(v / 1.3, 2.0); return v; } public double getConnectionRadius(Weight weight) { double w = Math.abs(weight.getValue()); return Math.log10(1.0 + w / 20.0); } protected void finishedEvolving() { if (shownNetwork == null) { return; } add(new Repeat(testUpdatePeriod) { int cycle = 0; @Override public void update(double t, double dt, Spatial s) { if (cycle % 8 == 0) { // randomInputs(shownNetwork); } else { // System.out.println("updating"); // shownNetwork.calculate(); } cycle++; } }); } protected void startEvolution() { neatParams = new SimpleNeatParameters(); neatParams.setFitnessFunction(new XorFitnessFunction()); neatParams.setPopulationSize(300); neatParams.setMaximumFitness(XorFitnessFunction.MAXIMUM_FITNESS); // as NN's only approximate functions there is no chance that we will generate the maximum // fitness, so enforce a number of generations limit to stop us running forever. neatParams.setMaximumGenerations(maxGenerations); NaturalSelectionOrganismSelector selector = new NaturalSelectionOrganismSelector(); selector.setKillUnproductiveSpecies(true); neatParams.setOrganismSelector(selector); DynamicThresholdSpeciator speciator = new DynamicThresholdSpeciator(); speciator.setMaxSpecies(4); neatParams.setSpeciator(speciator); NeuronGene inputOne = new NeuronGene(NeuronType.INPUT, neatParams); NeuronGene inputTwo = new NeuronGene(NeuronType.INPUT, neatParams); NeuronGene output = new NeuronGene(NeuronType.OUTPUT, neatParams); // create the evolver and run. evolver = Evolver.createNew(neatParams, Arrays.asList(inputOne, inputTwo), Arrays.asList(output)); evolver.addObserver(this); Thread evolutionThread = new Thread(new Runnable() { @Override public void run() { try { Organism best = evolver.evolve(); finishedEvolving(); } catch (PersistenceException ex) { ex.printStackTrace(); } } }); evolutionThread.setPriority(Thread.MIN_PRIORITY); evolutionThread.start(); } @Override public void update(Observable o, Object arg) { NeuralNetwork nn = neatParams.getNeuralNetworkBuilder().createNeuralNetwork((Organism) arg); // System.out.println("inputs=" + nn.getInputNeurons()); // System.out.println("outputs=" + nn.getOutputNeurons()); // System.out.println("layers=" + nn.getLayers()); // for (Layer l : nn.getLayers()) { // System.out.println(" " + l.getNeuronsCount()); // } currentNetwork = nn; } public static void main(String[] args) { ArdorSpacetime.newWindow(new DemoNeat()); } private void initControls() { getSpacetime().addCondition(new InputTrigger(new KeyPressedCondition(Key.F), new TriggerAction() { public void perform(final Canvas source, final TwoInputStates inputState, final double tpf) { rotateGraph(tpf * rotSpeed, 0); } })); getSpacetime().addCondition(new InputTrigger(new KeyPressedCondition(Key.H), new TriggerAction() { public void perform(final Canvas source, final TwoInputStates inputState, final double tpf) { rotateGraph(-tpf * rotSpeed, 0); } })); getSpacetime().addCondition(new InputTrigger(new KeyPressedCondition(Key.V), new TriggerAction() { public void perform(final Canvas source, final TwoInputStates inputState, final double tpf) { rotateGraph(0, tpf * rotSpeed); } })); getSpacetime().addCondition(new InputTrigger(new KeyPressedCondition(Key.G), new TriggerAction() { public void perform(final Canvas source, final TwoInputStates inputState, final double tpf) { rotateGraph(0, -tpf * rotSpeed); } })); } protected void rotateGraph(double rotHorDelta, double rotVertDelta) { rotHor += rotHorDelta; rotVert += rotVertDelta; gb.rotate(rotHor, rotVert, 0); } }