private Gene mutateLink(NEATLinkGene mutatee) { double perturbRandVal = perturbRand.nextDouble(); double disableRandVal = disableRand.nextDouble(); double newWeight; NEATLinkGene mutated = mutatee; if (perturbRandVal < this.pPerturb) { if (this.pWeightReplaced > perturbRand.nextDouble()) { newWeight = MathUtils.nextPlusMinusOne(); } else { newWeight = mutatee.getWeight() + MathUtils.nextClampedDouble(-perturb, perturb); } // newWeight = mutatee.getWeight() + MathUtils.nextClampedDouble(-PERTURB, PERTURB); mutated = new NEATLinkGene( mutatee.getInnovationNumber(), mutatee.isEnabled(), mutatee.getFromId(), mutatee.getToId(), newWeight); } if (disableRandVal < this.pToggle) { if (this.featureSelection) { mutated.setEnabled(!mutated.isEnabled()); } } return (mutated); }
private int findChosenIndex(NEATLinkGene chosen, Chromosome mutatee) { int idx = -1; int i = 0; Gene[] genes = mutatee.genes(); int mutateeSize = genes.length; while (i < mutateeSize && idx == -1) { if (genes[i] instanceof NEATLinkGene && ((NEATLinkGene) genes[i]).getFromId() == chosen.getFromId() && ((NEATLinkGene) genes[i]).getToId() == chosen.getToId()) { idx = i; } else { i++; } } return (idx); }
private boolean linkIllegal(NEATNodeGene from, NEATNodeGene to, ArrayList links) { boolean illegal = false; int idx = 0; NEATLinkGene linkGene; if ((to.getType() == NEATNodeGene.INPUT)) { illegal = true; } else { while (!illegal && (idx < links.size())) { linkGene = (NEATLinkGene) links.get(idx); // if ((linkGene.getFromId() == from.id() && linkGene.getToId() == to.id()) || // ((to.getDepth() <= from.getDepth()) && !this.recurrencyAllowed)) { if ((linkGene.getFromId() == from.id() && linkGene.getToId() == to.id())) { illegal = true; } idx++; } } return (illegal); }
private Gene[] findSourceNodes(int nodeId, Gene[] genes) { Gene[] sourceNodes = null; ArrayList links = this.candidateLinks(genes, true); NEATLinkGene link; ArrayList sources = new ArrayList(); int i; for (i = 0; i < links.size(); i++) { link = (NEATLinkGene) links.get(i); if (nodeId == link.getToId()) { // add from Id sources.add(this.findNode(link.getFromId(), genes)); } } sourceNodes = new NEATNodeGene[sources.size()]; for (i = 0; i < sourceNodes.length; i++) { sourceNodes[i] = (NEATNodeGene) sources.get(i); } return (sourceNodes); }
private void mutateAddNode(Chromosome mutatee) { double nodeRandVal = nodeRand.nextDouble(); ArrayList nodeLinks; // ArrayList nodes; NEATLinkGene chosen; NEATNodeGene newNode; NEATLinkGene newLower; NEATLinkGene newUpper; int newChromoIdx = mutatee.genes().length; // Gene[] newChromo = new Gene[newChromoIdx + 3]; Gene[] newChromo = new Gene[newChromoIdx + 2]; System.arraycopy(mutatee.genes(), 0, newChromo, 0, newChromoIdx); int linkIdx; if (nodeRandVal < this.pAddNode) { // add a node on an existing enabled connection // find an existing connection to intercept nodeLinks = this.candidateLinks(mutatee.genes(), true); if (nodeLinks.size() > 0) { // ensure there is a link to split linkIdx = nodeRand.nextInt(nodeLinks.size()); chosen = (NEATLinkGene) nodeLinks.get(linkIdx); // disable old link chosen.setEnabled(false); newNode = InnovationDatabase.database().submitNodeInnovation(chosen); // newNode.setBias(MathUtils.nextPlusMinusOne()); newLower = InnovationDatabase.database().submitLinkInnovation(chosen.getFromId(), newNode.id()); newUpper = InnovationDatabase.database().submitLinkInnovation(newNode.id(), chosen.getToId()); // set weights according to Stanley et al's NEAT document newLower.setWeight(1); newUpper.setWeight(chosen.getWeight()); // now update the chromosome with new node and 2 new links newChromo[this.findChosenIndex(chosen, mutatee)] = newNode; // newChromo[newChromoIdx++] = newNode; newChromo[newChromoIdx++] = newLower; newChromo[newChromoIdx] = newUpper; mutatee.updateChromosome(newChromo); } } }
private Gene[] ensureLegalLinks(Gene[] genes) { ArrayList links; NEATLinkGene link; NEATNodeGene from; NEATNodeGene to; Gene[] newGenes = null; ArrayList tmpGenes = new ArrayList(); int i; // only need to prune if recurrency not allowed if (!this.recurrencyAllowed) { // only return enabled links links = this.candidateLinks(genes, false); for (i = 0; i < genes.length; i++) { if (genes[i] instanceof NEATLinkGene) { link = (NEATLinkGene) genes[i]; from = this.findNode(link.getFromId(), genes); to = this.findNode(link.getToId(), genes); if (from.getDepth() > to.getDepth()) { // not recurrent - so keep tmpGenes.add(genes[i]); } } else { tmpGenes.add(genes[i]); } } newGenes = new Gene[tmpGenes.size()]; for (i = 0; i < newGenes.length; i++) { newGenes[i] = (Gene) tmpGenes.get(i); } } else { newGenes = genes; } return (newGenes); }
private void mutateAddLink(Chromosome mutatee) { double linkRandVal = linkRand.nextDouble(); NEATNodeGene from; NEATNodeGene to; int rIdx; int i = 0; ArrayList links; ArrayList nodes; Gene[] genes = new Gene[mutatee.size() + 1]; System.arraycopy(mutatee.genes(), 0, genes, 0, mutatee.genes().length); Gene newLink = null; if (linkRandVal < this.pAddLink) { nodes = this.candidateNodes(mutatee.genes()); links = this.candidateLinks(mutatee.genes(), false); // find a new available link while (newLink == null && i < MAX_LINK_ATTEMPTS) { rIdx = linkRand.nextInt(nodes.size()); from = ((NEATNodeGene) nodes.get(rIdx)); rIdx = linkRand.nextInt(nodes.size()); to = ((NEATNodeGene) nodes.get(rIdx)); // TODO Remove if (from.getInnovationNumber() == 2 && to.getInnovationNumber() == 5) { System.out.println("a"); } if (!this.linkIllegal(from, to, links)) { // set it to a random value newLink = InnovationDatabase.database().submitLinkInnovation(from.id(), to.id()); ((NEATLinkGene) newLink).setWeight(MathUtils.nextPlusMinusOne()); // add link between 2 unconnected nodes genes[genes.length - 1] = newLink; mutatee.updateChromosome(genes); } i++; } } }