// -- END OF: Feed forward -- // HOW BREEDING WORKS: // 1. Two parents // 2. If both have connection then random // 3. If one have then take from strongest public GNNNet Breed(GNNNet parthner) { GNNNet child = new GNNNet(); int[] range = UTYL.InnovRange(connections, parthner.connections); bool isAsFit = fitnessScore == parthner.fitnessScore; GNNNet[] parents = new GNNNet[] { this, parthner }; Connect?[,] table = new Connect?[2, range[1] - range[0]]; for (int i = 0; i < 2; i++) { for (int c = 0; c < parents[i].connections.Count; c++) { table[i, parents[i].connections[c].innov - range[0]] = parents[i].connections[c]; } } for (int c = 0; c < range[1] - range[0]; c++) { // If both cells are empty, or parhner is less fit then skip connection if ((table[0, c] == null && table[1, c] == null) || (!isAsFit && table[0, c] == null)) { continue; } // If both have same fitness adds parthners connection if (table[0, c] == null) { child.connections.Add(table[1, c].Value); } // Adds my connection if prev is empty else if (table[1, c] == null) { child.connections.Add(table[0, c].Value); } // If both have connections select random else { child.connections.Add(table[Random.Range(0, 2), c].Value); } } child.BuildNodes(); return(child); }
private double[,] GetSensorData() { double[,] output = new double[2, DIR_COUNT]; RaycastHit2D hit; for (int i = 0; i < DIR_COUNT; i++) { Vector3 to = transform.TransformDirection(sensorDir[i]); hit = Physics2D.Raycast(transform.position, to); output[0, i] = -1; output[1, i] = 1; if (hit.collider != null) { string hitTag = hit.collider.tag; output[1, i] = hit.distance / 430.0; if (hitTag == "Food") { output[0, i] = 1; if (hit.distance < 2) { UTYL.RemoveFood(hit.collider.gameObject); Destroy(hit.collider.gameObject); score++; health += 10; if (health > 100) { health = 100; } } } else if (hitTag == "AI") { output[0, i] = 0.5; } else if (hitTag == "Box") { output[0, i] = -0.5; } } } return(output); }
void InitGeneration() { // Step 0: Cleanup after prev GEN CleanUp(); // STEP 0.25 Backup SaveLoadManager.Save(GEN, unisignedNet); // STEP 0.5: Init food UTYL.InitBox(); // Step 1: Sort unisigned networks into spiecies // Step 2: Build simulations SpieciefyNetworks(); // Step 3: Run simmulations StartCoroutine("UpdateSimulation"); }
private void SpieciefyNetworks() { activeSimulations = new List <GNNSimulation>(); spiecies = new List <GNNSpiecies>(); foreach (GNNNet net in unisignedNet) { activeSimulations.Add(new GNNSimulation() { agent = UTYL.InitAgent(), network = net }); activeSimulations.Last().SetName(); bool isNewSpiecies = true; for (int i = 0; i < spiecies.Count; i++) { double dist = UTYL.GetDistance(spiecies[i].head, net); //Debug.Log("Dist:" + dist); if (dist <= 3) { spiecies[i].family.Add(net); isNewSpiecies = false; break; } } if (isNewSpiecies) { spiecies.Add(new GNNSpiecies(net)); } } for (int i = spiecies.Count - 1; i >= 0; i--) { if (spiecies[i].family.Count == 0) { spiecies.RemoveAt(i); } } }
private void Start() { UTYL.agentPrefab = Resources.Load("prefabs/AI") as GameObject; UTYL.foodPrefab = Resources.Load("prefabs/Food") as GameObject; UTYL.boxPrefab = Resources.Load("prefabs/Box") as GameObject; unisignedNet = new List <GNNNet>(); SaveObject so = SaveLoadManager.Load(); if (so == null) // No save file new sim { DB.SendData("clean_up", new Dictionary <string, string>()); for (int i = 0; i < CONFIG.POPULATION; i++) { GNNNet net = new GNNNet(); for (ushort o = 0; o < 4; o++) { net.MutateLink(); } net.connections = net.connections.OrderBy(x => x.innov).ToList(); unisignedNet.Add(net); } } else { unisignedNet.AddRange(so.networks); GEN = so.GEN; InnovController.innovations = new List <Innovation>(so.innovations); unisignedNet.RemoveAt(0); InnovController.innov = so.innovID; } UTYL.InitFood(); InitGeneration(); }
// δ = E/N + D/N + W/M | + U/N, where U - is count of difrence in disabled public static double GetDistance(GNNNet a, GNNNet b) { if (a.connections.Count == 0 && b.connections.Count == 0) { return(0); } double W; int M, D, E, N, U; M = 1; W = D = E = U = 0; N = a.connections.Count; if (N < b.connections.Count) { N = b.connections.Count; } if (N < 10) { N = 3; } GNNNet[] nets = new GNNNet[] { a, b }; int[] range = UTYL.InnovRange(a.connections, b.connections); Connect?[,] table = new Connect?[2, range[1] - range[0]]; for (int i = 0; i < 2; i++) { for (int c = 0; c < nets[i].connections.Count; c++) { table[i, nets[i].connections[c].innov - range[0]] = nets[i].connections[c]; } } bool isDisjoint = true; for (int c = range[1] - range[0] - 1; c >= 0; c--) { // End of if (table[0, c] != null || table[1, c] != null) { isDisjoint = false; } if (isDisjoint) { D++; continue; } if (table[0, c] == null && table[1, c] != null || table[0, c] != null && table[1, c] == null) { E++; continue; } if (table[0, c] != null && table[1, c] != null) { if (table[0, c].Value.isDisabled != table[1, c].Value.isDisabled) { U++; } M++; W += System.Math.Abs(table[0, c].Value.weight - table[1, c].Value.weight); } } return((double)E / (double)N + (double)D / (double)N + (double)U / (double)N + W / M); }
private void Update() { UTYL.KeepFood(); }