public override NEAT.Person crossover(NEAT.Person person1, NEAT.Person person2) { NEAT.Person res = ScriptableObject.CreateInstance <NEAT.Person>(); var dissimilar1 = person1.node_connect.Where(n => !person2.node_connect.Select(n1 => n1.innov).Contains(n.innov)); var dissimilar2 = person2.node_connect.Where(n => !person1.node_connect.Select(n1 => n1.innov).Contains(n.innov)); var similar = person1.node_connect.Where(n => person2.node_connect.Select(n1 => n1.innov).Contains(n.innov)); var innov = similar.Select(n => n.innov); res.node_gene = new List <NEAT.GENES.Nodes>(person1.node_gene.Union(person2.node_gene).ToList()); List <int> id = innov.Union(dissimilar1.Union(dissimilar2).Select(n => n.innov)).OrderBy(n => n).ToList(); for (int i = 0; i < id.Count; ++i) { NEAT.GENES.Connection conn1 = person1.node_connect.Find(n => n.innov == id[i]); NEAT.GENES.Connection conn2 = person2.node_connect.Find(n => n.innov == id[i]); var nbNodes = res.node_gene.Select(n => n.nb); if (conn1 == null) { res.node_connect.Add(conn2); NEAT.GENES.Nodes inN = person2.node_gene[conn2.inNode]; NEAT.GENES.Nodes outN = person2.node_gene[conn2.outNode]; if (!nbNodes.Contains(inN.nb)) { res.node_gene.Add(inN); } if (!nbNodes.Contains(outN.nb)) { res.node_gene.Add(outN); } } else if (conn2 == null) { res.node_connect.Add(conn1); NEAT.GENES.Nodes inN = person1.node_gene[conn1.inNode]; NEAT.GENES.Nodes outN = person1.node_gene[conn1.outNode]; if (!nbNodes.Contains(inN.nb)) { res.node_gene.Add(inN); } if (!nbNodes.Contains(outN.nb)) { res.node_gene.Add(outN); } } else { if (conn1.innov < conn2.innov) { res.node_connect.Add(conn1.Clone()); } else { res.node_connect.Add(conn2.Clone()); } res.node_connect.Last().w = (conn1.w + conn2.w) / 2.0f; if (!conn1.enabled || !conn2.enabled) { res.node_connect.Last().enabled = false; } NEAT.GENES.Nodes inN = person1.node_gene[conn1.inNode]; NEAT.GENES.Nodes outN = person1.node_gene[conn1.outNode]; if (!nbNodes.Contains(inN.nb)) { res.node_gene.Add(inN); } if (!nbNodes.Contains(outN.nb)) { res.node_gene.Add(outN); } } } res.node_gene.OrderBy(n => n.nb); return(res); }
public override NEAT.Person mutation(NEAT.Person person) { NEAT.Person res = person.Clone(); float r = UnityEngine.Random.value; if (r > 0.2f) { List <Tuple <int, int> > innout = new List <Tuple <int, int> >(); for (int i = 0; i < res.node_gene.Count; ++i) { if (res.node_gene[i].property != NEAT.GENES.NODE.OUT) { for (int j = i + 1; j < res.node_gene.Count; ++j) { if (res.node_gene[j].property != NEAT.GENES.NODE.IN) { innout.Add(new Tuple <int, int>(res.node_gene[i].nb, res.node_gene[j].nb)); } } } } List <Tuple <int, int> > connectionsPossible = innout.Where( p => !res.node_connect.Select(n => n.inNode).Contains(p.Item1) || !res.node_connect.Select(n => n.outNode).Contains(p.Item2)).ToList(); if (connectionsPossible.Count > 0) { System.Random random = new System.Random(); int rr = random.Next(connectionsPossible.Count); int nb1 = connectionsPossible[rr].Item1; int nb2 = connectionsPossible[rr].Item2; NEAT.GENES.Connection connection; int indexC = NEAT.GENES.Connection.alreadyExists(nb1, nb2); if (indexC > -1) { connection = NEAT.GENES.Connection.existing_connections[indexC].Clone(); connection.w = UnityEngine.Random.Range(-1f, 1f); connection.enabled = true; } else { connection = ScriptableObject.CreateInstance <NEAT.GENES.Connection>(); connection.init(nb1, nb2, UnityEngine.Random.Range(-1f, 1f), true); NEAT.GENES.Connection.existing_connections.Add(connection); } //NEAT.GENES.Connection connection = new NEAT.GENES.Connection(nb1, nb2, UnityEngine.Random.Range(-1f, 1f), true); res.node_connect.Add(connection); } } else { System.Random random = new System.Random(); int ran = random.Next(res.node_connect.Count); res.node_connect[ran] = res.node_connect[ran].Clone(); res.node_connect[ran].enabled = false; NEAT.GENES.Nodes newn = ScriptableObject.CreateInstance <NEAT.GENES.Nodes>(); newn.activation = (NEAT.GENES.ACTIVATION)random.Next(8); newn.nb = res.node_gene.Select(n => n.nb).Max() + 1; newn.property = NEAT.GENES.NODE.HIDDEN; NEAT.GENES.Connection con1; NEAT.GENES.Connection con2; int indexC = NEAT.GENES.Connection.alreadyExists(res.node_connect[ran].inNode, newn.nb); if (indexC > -1) { con1 = NEAT.GENES.Connection.existing_connections[indexC].Clone(); con1.w = 1f; con1.enabled = true; } else { con1 = ScriptableObject.CreateInstance <NEAT.GENES.Connection>(); con1.init(res.node_connect[ran].inNode, newn.nb, 1f, true); NEAT.GENES.Connection.existing_connections.Add(con1); } indexC = NEAT.GENES.Connection.alreadyExists(newn.nb, res.node_connect[ran].outNode); if (indexC > -1) { con2 = NEAT.GENES.Connection.existing_connections[indexC].Clone(); con1.w = res.node_connect[ran].w; con1.enabled = true; } else { con2 = ScriptableObject.CreateInstance <NEAT.GENES.Connection>(); con2.init(newn.nb, res.node_connect[ran].outNode, res.node_connect[ran].w, true); NEAT.GENES.Connection.existing_connections.Add(con2); } //NEAT.GENES.Connection con1 = new NEAT.GENES.Connection(res.node_connect[ran].inNode, newn.nb, 1f, true); //NEAT.GENES.Connection con2 = new NEAT.GENES.Connection(newn.nb, res.node_connect[ran].outNode, res.node_connect[ran].w, true); res.node_gene.Add(newn); res.node_gene = res.node_gene.OrderBy(n => n.nb).ToList(); res.node_connect.Add(con1); res.node_connect.Add(con2); } return(res); }