public void InitShaderTexture(BrainNEAT brain) { if (neuronPositionsTexture == null) { neuronPositionsTexture = new Texture2D(brain.neuronList.Count, 1, TextureFormat.RGBAHalf, false); } else { neuronPositionsTexture.Resize(brain.neuronList.Count, 1); } }
public void UpdateVertexColors(BrainNEAT brain) { //Debug.Log("UpdateVertexColors(BrainNEAT brain) " + GetColorFromValue(brain.neuronList[0].currentValue[0]).ToString()); for (int i = 0; i < brain.neuronList.Count; i++) { ChangeNodeColor(i, GetColorFromNeuron(brain.neuronList[i])); } for (int j = 0; j < brain.connectionList.Count; j++) { //ChangeConnectionColor(j, GetColorFromConnection(brain.connectionList[j], brain)); } meshBuilder.UpdateMeshColors(); }
public void UpdateNodeVertexPositions(BrainNEAT brain) { for (int i = 0; i < nodeVertexList.Count; i++) { // for all neurons: //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString()); //float size = neuronRadius + Mathf.Abs(brain.neuronList[i].previousValue) * neuronRadius * 0.12f; float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); meshBuilder.Vertices[nodeVertexList[i][0]] = nodePositionsList[i]; meshBuilder.Vertices[nodeVertexList[i][1]] = nodePositionsList[i] + new Vector3(0f, size, 0f); meshBuilder.Vertices[nodeVertexList[i][2]] = nodePositionsList[i] + new Vector3(size, 0f, 0f) + new Vector3(0f, size, 0f); meshBuilder.Vertices[nodeVertexList[i][3]] = nodePositionsList[i] + new Vector3(size, 0f, 0f); } meshBuilder.UpdateMeshVertices(); }
private Color GetColorFromConnection(ConnectionNEAT connection, BrainNEAT brain) { //black = -1, white = 1 //float val01 = connection.weight[0] * 0.5f + 0.5f; float val01 = brain.neuronList[connection.fromNodeID].currentValue[0] * connection.weight[0] * 0.2f + 0.5f; Color newColor = new Color(val01, val01, val01); newColor = Color.Lerp(newColor, new Color(0f, 0f, 1f), 0f); //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.In) { // newColor = Color.Lerp(newColor, new Color(0f, 1f, 0f), 0.75f); //} //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.Out) { // newColor = Color.Lerp(newColor, new Color(1f, 0f, 0f), 0.75f); //} //Debug.Log(val01.ToString()); return(newColor); }
//TODO: In more complete evaluators, take in an arena manager that lets you check out a room. That will return the bot/brain that was //created for that room (request a room each time StartNewEvaluation is called, or if no rooms available at that moment, each tick until //a room is free - then start evaluating from that moment) public Evaluator1_FAIL(Bot bot, BrainNEAT brainPart, SensorHoming[] homingParts, Point3D homePoint, ExperimentInitArgs_Activation activation, HyperNEAT_Args hyperneatArgs = null) { _bot = bot; _brainPart = brainPart; _homingParts = homingParts; _homePoint = homePoint; _activation = activation; _hyperneatArgs = hyperneatArgs; foreach (SensorHoming homingPart in homingParts) { homingPart.HomePoint = homePoint; homingPart.HomeRadius = _maxDistance * 1.25; } }
public void UpdateConnectionVertexPositions(BrainNEAT brain) { //for (int c = 0; c < brain.connectionList.Count; c++) { //BuildLink(meshBuilder, nodePositionsList[brain.connectionList[c].fromNodeID] + offset, nodePositionsList[brain.connectionList[c].toNodeID] + offset, connectionWidth, GetColorFromValue(brain.connectionList[c].weight[0])); //Debug.Log("BuildNew BrainMesh: from: " + nodePositionsList[brain.connectionList[c].fromNodeID].ToString() + ", to: " + nodePositionsList[brain.connectionList[c].toNodeID].ToString()); //} for (int i = 0; i < connectionVertexList.Count; i++) { // for all connections: Vector3 linkVector = new Vector3(nodePositionsList[brain.connectionList[i].toNodeID].x - nodePositionsList[brain.connectionList[i].fromNodeID].x, nodePositionsList[brain.connectionList[i].toNodeID].y - nodePositionsList[brain.connectionList[i].fromNodeID].y, nodePositionsList[brain.connectionList[i].toNodeID].z - nodePositionsList[brain.connectionList[i].fromNodeID].z); Vector3 widthVector = new Vector3(new Vector2(linkVector.y, -linkVector.x).normalized.x, new Vector2(linkVector.y, -linkVector.x).normalized.y, 0f) * (connectionWidthMin + Mathf.Abs(brain.connectionList[i].weight[0]) * connectionWidthMin * 0.62f); Vector3 cornerPos = new Vector3(nodePositionsList[brain.connectionList[i].fromNodeID].x - widthVector.x * 0.5f + neuronRadiusMin * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].y - widthVector.y * 0.5f + neuronRadiusMin * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].z); //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString()); meshBuilder.Vertices[connectionVertexList[i][0]] = cornerPos; meshBuilder.Vertices[connectionVertexList[i][1]] = cornerPos + linkVector; meshBuilder.Vertices[connectionVertexList[i][2]] = cornerPos + linkVector + widthVector; meshBuilder.Vertices[connectionVertexList[i][3]] = cornerPos + widthVector; } meshBuilder.UpdateMeshVertices(); }
public Mesh BuildNewMesh(BrainNEAT brain) { if(sourceCritter == null) { Debug.Log("BuildNewMesh(BrainNEAT brain) SOURCE CRITTER NULL!!!"); } else { SetNeuronSegmentPositions(brain); } if (nodeVertexList == null) { nodeVertexList = new List<List<int>>(); } else { nodeVertexList.Clear(); } if (connectionVertexList == null) { connectionVertexList = new List<List<int>>(); } else { connectionVertexList.Clear(); } if(nodePositionsList == null) { nodePositionsList = new List<Vector3>(); } else { nodePositionsList.Clear(); } if(bezierCurveList == null) { bezierCurveList = new List<BezierCurve>(); } else { bezierCurveList.Clear(); } if(hiddenNodeIndicesList == null) { hiddenNodeIndicesList = new List<int>(); // keep track of hidden nodes for later use } else { hiddenNodeIndicesList.Clear(); } meshBuilder = new MeshBuilder(); //Debug.Log("PRE ERROR: brain: " + brain.ToString()); //neuronRadius = 1.4f / Mathf.Max((float)brain.inputNeuronList.Count, (float)brain.outputNeuronList.Count); //Vector3 offset = new Vector3(neuronRadius * 0.5f, neuronRadius * 0.5f, 0f); int currentInputIndex = 0; int currentOutputIndex = 0; for(int i = 0; i < brain.neuronList.Count; i++) { // go through all nodes and place them in proper spot float xpos = 0f; float ypos = 0f; float zpos = 0f; //float size = Mathf.Min((neuronRadius * brain.neuronList[i].currentValue[0] * 0.2f + 0.02f), 2.0f); float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); if (brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.In) { xpos = (float)(currentInputIndex + 1) / (float)(brain.inputNeuronList.Count + 1) - 0.5f; ypos = 0f; zpos = UnityEngine.Random.Range(-0.5f, 0.5f); currentInputIndex++; BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i])); } else if(brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.Hid) { xpos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f; ypos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f; zpos = UnityEngine.Random.Range(-0.5f, 0.5f); hiddenNodeIndicesList.Add(i); //BuildNode(meshBuilder, new Vector3(xpos, ypos, 0f), new Vector3(radius, 0f, 0f), new Vector3(0f, radius, 0f), GetColorFromValue(brain.neuronList[i].currentValue[0])); } else { // output xpos = (float)(currentOutputIndex + 1) / (float)(brain.outputNeuronList.Count + 1) - 0.5f; ypos = 1f - neuronRadiusMax; zpos = UnityEngine.Random.Range(-0.5f, 0.5f); currentOutputIndex++; BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i])); } nodePositionsList.Add(new Vector3(xpos, ypos, zpos)); } // position HiddenNodes!! // BUILD hidden nodes: for (int h = 0; h < hiddenNodeIndicesList.Count; h++) { float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[hiddenNodeIndicesList[h]].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); BuildNodeSphere(meshBuilder, new Vector3(nodePositionsList[hiddenNodeIndicesList[h]].x, nodePositionsList[hiddenNodeIndicesList[h]].y, nodePositionsList[hiddenNodeIndicesList[h]].z), size, GetColorFromNeuron(brain.neuronList[hiddenNodeIndicesList[h]])); } // CONNECTIONS! //connectionWidth = Mathf.Max(neuronRadius * 0.1f, 0.01f); //Debug.Log("BuildNew BrainMesh: numConnections: " + brain.connectionList.Count); for(int c = 0; c < brain.connectionList.Count; c++) { BezierCurve connectionBezier = new BezierCurve(); connectionBezier.points[0] = nodePositionsList[brain.connectionList[c].fromNodeID]; connectionBezier.points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f); connectionBezier.points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f); connectionBezier.points[3] = nodePositionsList[brain.connectionList[c].toNodeID]; bezierCurveList.Add(connectionBezier); float startWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0]) * connectionWidthMax * 0.4f), connectionWidthMax), connectionWidthMin); float endWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * connectionWidthMax * 0.4f, connectionWidthMax), connectionWidthMin); BuildLinkBezier(meshBuilder, connectionBezier, startWidth, endWidth, GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]), GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID])); //Debug.Log("BuildNew BrainMesh: from: " + nodePositionsList[brain.connectionList[c].fromNodeID].ToString() + ", to: " + nodePositionsList[brain.connectionList[c].toNodeID].ToString()); } //MoveHiddenNodes(brain, 1); return meshBuilder.CreateMesh(); }
public Mesh BuildNewMesh(BrainNEAT brain) { if (sourceCritter == null) { Debug.Log("BuildNewMesh(BrainNEAT brain) SOURCE CRITTER NULL!!!"); } else { SetNeuronSegmentPositions(brain); } if (nodeVertexList == null) { nodeVertexList = new List <List <int> >(); } else { nodeVertexList.Clear(); } if (connectionVertexList == null) { connectionVertexList = new List <List <int> >(); } else { connectionVertexList.Clear(); } if (nodePositionsList == null) { nodePositionsList = new List <Vector3>(); } else { nodePositionsList.Clear(); } if (bezierCurveList == null) { bezierCurveList = new List <BezierCurve>(); } else { bezierCurveList.Clear(); } if (hiddenNodeIndicesList == null) { hiddenNodeIndicesList = new List <int>(); // keep track of hidden nodes for later use } else { hiddenNodeIndicesList.Clear(); } meshBuilder = new MeshBuilder(); //Debug.Log("PRE ERROR: brain: " + brain.ToString()); //neuronRadius = 1.4f / Mathf.Max((float)brain.inputNeuronList.Count, (float)brain.outputNeuronList.Count); //Vector3 offset = new Vector3(neuronRadius * 0.5f, neuronRadius * 0.5f, 0f); int currentInputIndex = 0; int currentOutputIndex = 0; for (int i = 0; i < brain.neuronList.Count; i++) { // go through all nodes and place them in proper spot float xpos = 0f; float ypos = 0f; float zpos = 0f; //float size = Mathf.Min((neuronRadius * brain.neuronList[i].currentValue[0] * 0.2f + 0.02f), 2.0f); float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); if (brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.In) { xpos = (float)(currentInputIndex + 1) / (float)(brain.inputNeuronList.Count + 1) - 0.5f; ypos = 0f; zpos = UnityEngine.Random.Range(-0.5f, 0.5f); currentInputIndex++; BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i])); } else if (brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.Hid) { xpos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f; ypos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f; zpos = UnityEngine.Random.Range(-0.5f, 0.5f); hiddenNodeIndicesList.Add(i); //BuildNode(meshBuilder, new Vector3(xpos, ypos, 0f), new Vector3(radius, 0f, 0f), new Vector3(0f, radius, 0f), GetColorFromValue(brain.neuronList[i].currentValue[0])); } else // output { xpos = (float)(currentOutputIndex + 1) / (float)(brain.outputNeuronList.Count + 1) - 0.5f; ypos = 1f - neuronRadiusMax; zpos = UnityEngine.Random.Range(-0.5f, 0.5f); currentOutputIndex++; BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i])); } nodePositionsList.Add(new Vector3(xpos, ypos, zpos)); } // position HiddenNodes!! // BUILD hidden nodes: for (int h = 0; h < hiddenNodeIndicesList.Count; h++) { float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[hiddenNodeIndicesList[h]].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); BuildNodeSphere(meshBuilder, new Vector3(nodePositionsList[hiddenNodeIndicesList[h]].x, nodePositionsList[hiddenNodeIndicesList[h]].y, nodePositionsList[hiddenNodeIndicesList[h]].z), size, GetColorFromNeuron(brain.neuronList[hiddenNodeIndicesList[h]])); } // CONNECTIONS! //connectionWidth = Mathf.Max(neuronRadius * 0.1f, 0.01f); //Debug.Log("BuildNew BrainMesh: numConnections: " + brain.connectionList.Count); for (int c = 0; c < brain.connectionList.Count; c++) { BezierCurve connectionBezier = new BezierCurve(); connectionBezier.points[0] = nodePositionsList[brain.connectionList[c].fromNodeID]; connectionBezier.points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f); connectionBezier.points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f); connectionBezier.points[3] = nodePositionsList[brain.connectionList[c].toNodeID]; bezierCurveList.Add(connectionBezier); float startWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0]) * connectionWidthMax * 0.4f), connectionWidthMax), connectionWidthMin); float endWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * connectionWidthMax * 0.4f, connectionWidthMax), connectionWidthMin); BuildLinkBezier(meshBuilder, connectionBezier, startWidth, endWidth, GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]), GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID])); //Debug.Log("BuildNew BrainMesh: from: " + nodePositionsList[brain.connectionList[c].fromNodeID].ToString() + ", to: " + nodePositionsList[brain.connectionList[c].toNodeID].ToString()); } //MoveHiddenNodes(brain, 1); return(meshBuilder.CreateMesh()); }
/// <summary> /// Once the world is created on the worker thread, maps and bots need to be created for each room /// NOTE: This is called from the worker thread /// </summary> private void Arena_WorldCreated(object sender, EventArgs e) { World world = Arena.WorldAccessor.World; #region materials MaterialManager = new MaterialManager(world); MaterialIDs = new MaterialIDs(); // Wall Game.Newt.v2.NewtonDynamics.Material material = new Game.Newt.v2.NewtonDynamics.Material(); material.Elasticity = ItemOptionsArco.ELASTICITY_WALL; MaterialIDs.Wall = MaterialManager.AddMaterial(material); // Bot material = new Game.Newt.v2.NewtonDynamics.Material(); MaterialIDs.Bot = MaterialManager.AddMaterial(material); // Bot Ram material = new Game.Newt.v2.NewtonDynamics.Material(); material.Elasticity = ItemOptionsArco.ELASTICITY_BOTRAM; MaterialIDs.BotRam = MaterialManager.AddMaterial(material); // Exploding Bot material = new Game.Newt.v2.NewtonDynamics.Material(); material.IsCollidable = false; MaterialIDs.ExplodingBot = MaterialManager.AddMaterial(material); // Weapon material = new Game.Newt.v2.NewtonDynamics.Material(); MaterialIDs.Weapon = MaterialManager.AddMaterial(material); // Treasure Box material = new Game.Newt.v2.NewtonDynamics.Material(); MaterialIDs.TreasureBox = MaterialManager.AddMaterial(material); //TODO: Uncomment these // Collisions //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Bot, Collision_BotBot); //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Weapon, Collision_BotWeapon); //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.Weapon, Collision_WeaponWeapon); ////_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Wall, Collision_BotWall); //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.Wall, Collision_WeaponWall); //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.TreasureBox, Collision_WeaponTreasureBox); //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.TreasureBox, Collision_BotTreasureBox); #endregion List <KeepItems2D> keep2Ds = new List <KeepItems2D>(); foreach (var(room, _) in Arena.AllRooms) { #region keep 2D //TODO: drag plane should either be a plane or a large cylinder, based on the current (level|scene|stage|area|arena|map|place|region|zone) // This game is 3D emulating 2D, so always have the mouse go to the XY plane DragHitShape dragPlane = new DragHitShape(); dragPlane.SetShape_Plane(new Triangle(new Point3D(-1, -1, room.Center.Z), new Point3D(1, -1, room.Center.Z), new Point3D(0, 1, room.Center.Z))); // This will keep objects onto that plane using forces (not velocities) KeepItems2D keep2D = new KeepItems2D { SnapShape = dragPlane, }; //keep2D.Add(room.Bot, false); keep2Ds.Add(keep2D); #endregion #region bot ShipCoreArgs core = new ShipCoreArgs() { World = world, Material_Ship = MaterialIDs.Bot, Map = room.Map, }; //BotConstructor_Events events = new BotConstructor_Events(); //events. // Create the bot Bot bot = null; if (RequestCustomBot != null) { bot = RequestCustomBot(core, keep2D, dragPlane, MaterialIDs); } else { BotConstruction_Result construction = BotConstructor.ConstructBot(DNA, core, ShipExtraArgs); bot = new Bot(construction); } // Find some parts BrainNEAT brainPart = bot.Parts.FirstOrDefault(o => o is BrainNEAT) as BrainNEAT; if (brainPart == null) { throw new ApplicationException("Didn't find BrainNEAT part"); } SensorHoming[] homingParts = bot.Parts. Where(o => o is SensorHoming). Select(o => (SensorHoming)o). ToArray(); if (homingParts.Length == 0) { throw new ApplicationException("Didn't find SensorHoming part"); } #endregion room.Bot = bot; room.BrainPart = brainPart; room.HomingParts = homingParts; foreach (SensorHoming homing in homingParts) { homing.HomePoint = room.Center; homing.HomeRadius = (ROOMSIZE / 2d) * Evaluator3.MULT_HOMINGSIZE; } room.Map.AddItem(bot); keep2D.Add(room.Bot, false); } Keep2D = keep2Ds.ToArray(); world.Updated += World_Updated; }
public void BuildBrainMesh(BrainNEAT brain) { MiniGameManager currentGameManager = PlayerList[playingCurPlayer].masterTrialsList[playingCurTrialIndex].miniGameManager; if (brainNetworkGO == null) { brainNetworkGO = new GameObject("brainNetworkGO"); brainNetworkGO.AddComponent<MeshFilter>(); //Material brainNetworkMat = new Material(Shader.Find("Custom/SimpleBrainNetworkShader")); brainNetworkGO.AddComponent<MeshRenderer>().material = brainNetworkMat; networkVisualizer = brainNetworkGO.AddComponent<BrainNetworkVisualizer>(); if (currentGameManager.miniGameInstance.critterBeingTested != null) { networkVisualizer.sourceCritter = currentGameManager.miniGameInstance.critterBeingTested; } //currentGameManager.miniGameInstance.critterBeingTested.critterSegmentMaterial.SetTexture("_NeuronPosTex", networkVisualizer.neuronPositionsTexture); } MiniGameCritterWalkBasic minigame = (MiniGameCritterWalkBasic)currentGameManager.miniGameInstance as MiniGameCritterWalkBasic; networkVisualizer.InitShaderTexture(brain); minigame.SetShaderTextures(networkVisualizer); brainNetworkGO.GetComponent<MeshFilter>().sharedMesh = networkVisualizer.BuildNewMesh(brain); }
public void UpdateNodeVertexPositions(BrainNEAT brain) { for(int i = 0; i < nodeVertexList.Count; i++) { // for all neurons: //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString()); //float size = neuronRadius + Mathf.Abs(brain.neuronList[i].previousValue) * neuronRadius * 0.12f; float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); meshBuilder.Vertices[nodeVertexList[i][0]] = nodePositionsList[i]; meshBuilder.Vertices[nodeVertexList[i][1]] = nodePositionsList[i] + new Vector3(0f, size, 0f); meshBuilder.Vertices[nodeVertexList[i][2]] = nodePositionsList[i] + new Vector3(size, 0f, 0f) + new Vector3(0f, size, 0f); meshBuilder.Vertices[nodeVertexList[i][3]] = nodePositionsList[i] + new Vector3(size, 0f, 0f); } meshBuilder.UpdateMeshVertices(); }
private Color GetColorFromConnection(ConnectionNEAT connection, BrainNEAT brain) { //black = -1, white = 1 //float val01 = connection.weight[0] * 0.5f + 0.5f; float val01 = brain.neuronList[connection.fromNodeID].currentValue[0] * connection.weight[0] * 0.2f + 0.5f; Color newColor = new Color(val01, val01, val01); newColor = Color.Lerp(newColor, new Color(0f, 0f, 1f), 0f); //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.In) { // newColor = Color.Lerp(newColor, new Color(0f, 1f, 0f), 0.75f); //} //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.Out) { // newColor = Color.Lerp(newColor, new Color(1f, 0f, 0f), 0.75f); //} //Debug.Log(val01.ToString()); return newColor; }
public void MoveNeurons(BrainNEAT brain, int numIter) { // position HiddenNodes!! int numIterations = numIter; List<Vector3> newNodePositionsList = new List<Vector3>(); for(int i = 0; i < nodePositionsList.Count; i++) { // Initialize new positions list Vector3 newPositionVector = new Vector3(); newPositionVector = nodePositionsList[i]; newNodePositionsList.Add(newPositionVector); } //float attract = 0.007f; //float repel = 0.0025f; for (int phase = 0; phase < numIterations; phase++) { // Attract NEURONS: for (int c = 0; c < brain.connectionList.Count; c++) { // go trhough all connections and treat them as springs int fromNode = brain.connectionList[c].fromNodeID; int toNode = brain.connectionList[c].toNodeID; Vector3 linkVector = nodePositionsList[toNode] - nodePositionsList[fromNode]; if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.In) { //linkVector += new Vector2(0f, -attract * 2.7f); } else if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.Out) { //linkVector += new Vector2(0f, attract * 2.7f); } float dist = Mathf.Max(linkVector.sqrMagnitude, 0.02f); newNodePositionsList[fromNode] += linkVector * attractByConnections * dist; // move fromNode towards toNode proportionally based on its distance newNodePositionsList[toNode] -= linkVector * attractByConnections * dist; // move fromNode towards toNode proportionally based on its distance } // REPEL NEURONS: for (int j = 0; j < nodePositionsList.Count; j++) { // for all nodes for (int k = 0; k < nodePositionsList.Count; k++) { // go through all nodes if (j != k) { // if not comparing to itself Vector3 vectorToNode = (nodePositionsList[k] - nodePositionsList[j]); float dist = Mathf.Max(vectorToNode.magnitude, 0.01f); // repel from each node: if (dist < neuronRepelMaxDistance) { newNodePositionsList[j] -= vectorToNode * neuronRepelForce / dist; newNodePositionsList[k] += vectorToNode * neuronRepelForce / dist; } } } // For each node, if not hidden, move towards its worldPos: if (brain.neuronList[j].nodeType != GeneNodeNEAT.GeneNodeType.Hid) { Vector3 vectorToSegmentPos = (brain.neuronList[j].worldPos - nodePositionsList[j]); float dist = Mathf.Max(vectorToSegmentPos.sqrMagnitude, 0.01f); newNodePositionsList[j] += vectorToSegmentPos * attractToCritterPos; //Debug.Log("brain.neuronList[" + j.ToString() + "] worldPos: " + brain.neuronList[j].worldPos.ToString() + ", nodePos: " + nodePositionsList[j].ToString()); } // build texture to pass to shader: Vector3 position = nodePositionsList[j]; neuronPositionsTexture.SetPixel(j, 1, new Color(position.x, position.y, position.z, brain.neuronList[j].currentValue[0])); } // Apply new Neuron positions to master list: for (int p = 0; p < nodePositionsList.Count; p++) { // Initialize new positions list //Vector3 newPositionVector = new Vector3(); nodePositionsList[p] = newNodePositionsList[p]; } // BEZIER CURVES: for (int c = 0; c < brain.connectionList.Count; c++) { bezierCurveList[c].points[0] = nodePositionsList[brain.connectionList[c].fromNodeID]; //bezierCurveList[c].points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f); //bezierCurveList[c].points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f); bezierCurveList[c].points[3] = nodePositionsList[brain.connectionList[c].toNodeID]; for (int b = 0; b < bezierCurveList.Count; b++) { // Go through all other bezierCurves and repel from others if (b != c) { // if not comparing to itself: for (int control = 0; control < 4; control++) { // go through each of the 4 points in the other bezierCurve connection: Vector3 vectorToControlPoint1 = bezierCurveList[b].points[control] - bezierCurveList[c].points[1]; float distance = Mathf.Max(vectorToControlPoint1.sqrMagnitude, 0.02f); // The middle control points in the current Beziercurve are repelled from ALL OTHER bezier curve control points! if (distance < neuronRepelMaxDistance) { bezierCurveList[c].points[1] -= vectorToControlPoint1 * bezierRepelForce * distance; bezierCurveList[c].points[2] -= vectorToControlPoint1 * bezierRepelForce * distance; } } } } // ATTRACT to rest position! Vector3 vectorControl1ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.333f) - bezierCurveList[c].points[1]; float dist1 = Mathf.Max(vectorControl1ToRest.sqrMagnitude, 0.02f); Vector3 vectorControl2ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.667f) - bezierCurveList[c].points[2]; float dist2 = Mathf.Max(vectorControl2ToRest.sqrMagnitude, 0.02f); bezierCurveList[c].points[1] += vectorControl1ToRest * attractToControlPoints * dist1; bezierCurveList[c].points[2] += vectorControl2ToRest * attractToControlPoints * dist2; } neuronPositionsTexture.Apply(); } //meshBuilder.UpdateMeshVertices(); }
public void MoveNeurons(BrainNEAT brain, int numIter) { // position HiddenNodes!! int numIterations = numIter; List <Vector3> newNodePositionsList = new List <Vector3>(); for (int i = 0; i < nodePositionsList.Count; i++) // Initialize new positions list { Vector3 newPositionVector = new Vector3(); newPositionVector = nodePositionsList[i]; newNodePositionsList.Add(newPositionVector); } //float attract = 0.007f; //float repel = 0.0025f; for (int phase = 0; phase < numIterations; phase++) { // Attract NEURONS: for (int c = 0; c < brain.connectionList.Count; c++) { // go trhough all connections and treat them as springs int fromNode = brain.connectionList[c].fromNodeID; int toNode = brain.connectionList[c].toNodeID; Vector3 linkVector = nodePositionsList[toNode] - nodePositionsList[fromNode]; if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.In) { //linkVector += new Vector2(0f, -attract * 2.7f); } else if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.Out) { //linkVector += new Vector2(0f, attract * 2.7f); } float dist = Mathf.Max(linkVector.sqrMagnitude, 0.02f); newNodePositionsList[fromNode] += linkVector * attractByConnections * dist; // move fromNode towards toNode proportionally based on its distance newNodePositionsList[toNode] -= linkVector * attractByConnections * dist; // move fromNode towards toNode proportionally based on its distance } // REPEL NEURONS: for (int j = 0; j < nodePositionsList.Count; j++) // for all nodes { for (int k = 0; k < nodePositionsList.Count; k++) // go through all nodes { if (j != k) // if not comparing to itself { Vector3 vectorToNode = (nodePositionsList[k] - nodePositionsList[j]); float dist = Mathf.Max(vectorToNode.magnitude, 0.01f); // repel from each node: if (dist < neuronRepelMaxDistance) { newNodePositionsList[j] -= vectorToNode * neuronRepelForce / dist; newNodePositionsList[k] += vectorToNode * neuronRepelForce / dist; } } } // For each node, if not hidden, move towards its worldPos: if (brain.neuronList[j].nodeType != GeneNodeNEAT.GeneNodeType.Hid) { Vector3 vectorToSegmentPos = (brain.neuronList[j].worldPos - nodePositionsList[j]); float dist = Mathf.Max(vectorToSegmentPos.sqrMagnitude, 0.01f); newNodePositionsList[j] += vectorToSegmentPos * attractToCritterPos; //Debug.Log("brain.neuronList[" + j.ToString() + "] worldPos: " + brain.neuronList[j].worldPos.ToString() + ", nodePos: " + nodePositionsList[j].ToString()); } // build texture to pass to shader: Vector3 position = nodePositionsList[j]; neuronPositionsTexture.SetPixel(j, 1, new Color(position.x, position.y, position.z, brain.neuronList[j].currentValue[0])); } // Apply new Neuron positions to master list: for (int p = 0; p < nodePositionsList.Count; p++) // Initialize new positions list //Vector3 newPositionVector = new Vector3(); { nodePositionsList[p] = newNodePositionsList[p]; } // BEZIER CURVES: for (int c = 0; c < brain.connectionList.Count; c++) { bezierCurveList[c].points[0] = nodePositionsList[brain.connectionList[c].fromNodeID]; //bezierCurveList[c].points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f); //bezierCurveList[c].points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f); bezierCurveList[c].points[3] = nodePositionsList[brain.connectionList[c].toNodeID]; for (int b = 0; b < bezierCurveList.Count; b++) { // Go through all other bezierCurves and repel from others if (b != c) // if not comparing to itself: { for (int control = 0; control < 4; control++) // go through each of the 4 points in the other bezierCurve connection: { Vector3 vectorToControlPoint1 = bezierCurveList[b].points[control] - bezierCurveList[c].points[1]; float distance = Mathf.Max(vectorToControlPoint1.sqrMagnitude, 0.02f); // The middle control points in the current Beziercurve are repelled from ALL OTHER bezier curve control points! if (distance < neuronRepelMaxDistance) { bezierCurveList[c].points[1] -= vectorToControlPoint1 * bezierRepelForce * distance; bezierCurveList[c].points[2] -= vectorToControlPoint1 * bezierRepelForce * distance; } } } } // ATTRACT to rest position! Vector3 vectorControl1ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.333f) - bezierCurveList[c].points[1]; float dist1 = Mathf.Max(vectorControl1ToRest.sqrMagnitude, 0.02f); Vector3 vectorControl2ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.667f) - bezierCurveList[c].points[2]; float dist2 = Mathf.Max(vectorControl2ToRest.sqrMagnitude, 0.02f); bezierCurveList[c].points[1] += vectorControl1ToRest * attractToControlPoints * dist1; bezierCurveList[c].points[2] += vectorControl2ToRest * attractToControlPoints * dist2; } neuronPositionsTexture.Apply(); } //meshBuilder.UpdateMeshVertices(); }
public void SetNeuronSegmentPositions(BrainNEAT brain) { int currentInputIndex = 0; int currentOutputIndex = 0; // Check for ANGLE SENSORS: for (int i = 0; i < sourceCritter.segaddonJointAngleSensorList.Count; i++) { if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].GetComponent <CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY) { // Add an extra one if it's a dual Joint brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position; currentInputIndex++; } brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonContactSensorList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonContactSensorList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonRaycastSensorList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRaycastSensorList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonCompassSensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonCompassSensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonPositionSensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonPositionSensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonRotationSensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonRotationSensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonVelocitySensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonVelocitySensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonAltimeterList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonAltimeterList[i].segmentID].transform.position; currentInputIndex++; } // Outputs: for (int i = 0; i < sourceCritter.segaddonJointMotorList.Count; i++) { if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].GetComponent <CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY) { // Add an extra one if it's a dual Joint brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f; currentOutputIndex++; } brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonThrusterEffector1DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector1DList[i].segmentID].transform.position; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonThrusterEffector3DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector3DList[i].segmentID].transform.position; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonTorqueEffector1DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector1DList[i].segmentID].transform.position; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonTorqueEffector3DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector3DList[i].segmentID].transform.position; currentOutputIndex++; } // More Inputs: for (int i = 0; i < sourceCritter.segaddonOscillatorInputList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonOscillatorInputList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonValueInputList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonValueInputList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonTimerInputList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTimerInputList[i].segmentID].transform.position; currentInputIndex++; } }
public void UpdateNodeVertexPositionsSphere(BrainNEAT brain) { for (int n = 0; n < nodeVertexList.Count; n++) { // for all neurons: //float size = Mathf.Min((neuronRadius * brain.neuronList[n].currentValue[0] * 0.2f + 0.02f), 2.0f); float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[n].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); int currentVertexIndex = 0; if (nodePositionsList == null) { //Debug.Log("if(nodePositionsList == null) {"); } else { //Debug.Log("if(nodePositionsList != null) {" + nodePositionsList.Count.ToString() + ", n: " + n.ToString() + ", fromNode: " + brain.connectionList[n].fromNodeID.ToString()); } Vector3 offset = nodePositionsList[n] - new Vector3(0f, size, 0f); int m_HeightSegmentCount = 4; int m_RadialSegmentCount = 4; float m_VerticalScale = 1f; Quaternion rotation = Quaternion.identity; //the angle increment per height segment: float angleInc = Mathf.PI / m_HeightSegmentCount; //the vertical (scaled) radius of the sphere: float verticalRadius = size * m_VerticalScale; //build the rings: for (int i = 0; i <= m_HeightSegmentCount; i++) { Vector3 centrePos = Vector3.zero; //calculate a height offset and radius based on a vertical circle calculation: centrePos.y = -Mathf.Cos(angleInc * i); float radius = Mathf.Sin(angleInc * i); //calculate the slope of the shpere at this ring based on the height and radius: Vector2 slope = new Vector3(-centrePos.y / m_VerticalScale, radius); slope.Normalize(); //multiply the unit height by the vertical radius, and then add the radius to the height to make this sphere originate from its base rather than its centre: centrePos.y = centrePos.y * verticalRadius + verticalRadius; //scale the radius by the one stored in the partData: radius *= size; //calculate the final position of the ring centre: Vector3 finalRingCentre = rotation * centrePos + offset; //V coordinate: float v = (float)i / m_HeightSegmentCount; //build the ring: //BuildRing(meshBuilder, m_RadialSegmentCount, finalRingCentre, radius, v, i > 0, rotation, slope); float angleIncrement = (Mathf.PI * 2.0f) / m_RadialSegmentCount; for (int j = 0; j <= m_RadialSegmentCount; j++) { float angle = angleIncrement * j; Vector3 unitPosition = Vector3.zero; unitPosition.x = Mathf.Cos(angle); unitPosition.z = Mathf.Sin(angle); float normalVertical = -slope.x; float normalHorizontal = slope.y; Vector3 normal = unitPosition * normalHorizontal; normal.y = normalVertical; normal = rotation * normal; unitPosition = rotation * unitPosition; meshBuilder.Vertices[nodeVertexList[n][currentVertexIndex]] = finalRingCentre + unitPosition * radius; currentVertexIndex++; } } } meshBuilder.UpdateMeshVertices(); }
public void SetNeuronSegmentPositions(BrainNEAT brain) { int currentInputIndex = 0; int currentOutputIndex = 0; // Check for ANGLE SENSORS: for(int i = 0; i < sourceCritter.segaddonJointAngleSensorList.Count; i++) { if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].GetComponent<CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY) { // Add an extra one if it's a dual Joint brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position; currentInputIndex++; } brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position; currentInputIndex++; } for(int i = 0; i < sourceCritter.segaddonContactSensorList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonContactSensorList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonRaycastSensorList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRaycastSensorList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonCompassSensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonCompassSensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonPositionSensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonPositionSensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonRotationSensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonRotationSensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonVelocitySensor1DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor1DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonVelocitySensor3DList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor3DList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonAltimeterList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonAltimeterList[i].segmentID].transform.position; currentInputIndex++; } // Outputs: for (int i = 0; i < sourceCritter.segaddonJointMotorList.Count; i++) { if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].GetComponent<CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY) { // Add an extra one if it's a dual Joint brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f; currentOutputIndex++; } brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonThrusterEffector1DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector1DList[i].segmentID].transform.position; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonThrusterEffector3DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector3DList[i].segmentID].transform.position; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonTorqueEffector1DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector1DList[i].segmentID].transform.position; currentOutputIndex++; } for (int i = 0; i < sourceCritter.segaddonTorqueEffector3DList.Count; i++) { brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector3DList[i].segmentID].transform.position; currentOutputIndex++; } // More Inputs: for (int i = 0; i < sourceCritter.segaddonOscillatorInputList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonOscillatorInputList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonValueInputList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonValueInputList[i].segmentID].transform.position; currentInputIndex++; } for (int i = 0; i < sourceCritter.segaddonTimerInputList.Count; i++) { brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTimerInputList[i].segmentID].transform.position; currentInputIndex++; } }
public void UpdateConnectionVertexPositionsBezier(BrainNEAT brain) { for (int c = 0; c < connectionVertexList.Count; c++) { // for all connections: /*Vector3 linkVector = new Vector3(nodePositionsList[brain.connectionList[i].toNodeID].x - nodePositionsList[brain.connectionList[i].fromNodeID].x, nodePositionsList[brain.connectionList[i].toNodeID].y - nodePositionsList[brain.connectionList[i].fromNodeID].y, nodePositionsList[brain.connectionList[i].toNodeID].z - nodePositionsList[brain.connectionList[i].fromNodeID].z); * Vector3 widthVector = new Vector3(new Vector2(linkVector.y, -linkVector.x).normalized.x, new Vector2(linkVector.y, -linkVector.x).normalized.y, 0f) * (connectionWidth + Mathf.Abs(brain.connectionList[i].weight[0]) * connectionWidth * 0.62f); * Vector3 cornerPos = new Vector3(nodePositionsList[brain.connectionList[i].fromNodeID].x - widthVector.x * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].y - widthVector.y * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].z); * //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString()); * meshBuilder.Vertices[connectionVertexList[i][0]] = cornerPos; * meshBuilder.Vertices[connectionVertexList[i][1]] = cornerPos + linkVector; * meshBuilder.Vertices[connectionVertexList[i][2]] = cornerPos + linkVector + widthVector; * meshBuilder.Vertices[connectionVertexList[i][3]] = cornerPos + widthVector; */ int currentVertexIndex = 0; //float width = connectionWidth; // brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0]; Color colorStart = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]); Color colorEnd = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID]); float startWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin); float endWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin); float m_splineStartRadius = startWidth; float m_splineEndRadius = endWidth; int m_splineHeightSegmentCount = 8; int m_splineRadialSegmentCount = 4; float tInc = 1f / m_splineHeightSegmentCount; // How many subdivisions along the length of the spline for (int i = 0; i <= m_splineHeightSegmentCount; i++) { float t = tInc * (float)i; Vector3 ringCenter = bezierCurveList[c].GetPoint(t); Vector3 dir = bezierCurveList[c].GetDirection(t); Quaternion rot = Quaternion.identity; if (dir != Vector3.zero) { rot.SetLookRotation(dir); } float radius = ((1f - t) * m_splineStartRadius) + (t * m_splineEndRadius); // Construct the mesh Ring! //BuildBezierCurveRing(meshBuilder, m_splineRadialSegmentCount, ringCenter, radius, t, i > 0, rot); //protected void BuildBezierCurveRing(MeshBuilder meshBuilder, int segmentCount, Vector3 center, float radius, float v, bool buildTriangles, Quaternion rotation) { float angleInc = (Mathf.PI * 2.0f) / m_splineRadialSegmentCount; for (int j = 0; j <= m_splineRadialSegmentCount; j++) { float angle = angleInc * j; Vector3 unitPosition = Vector3.zero; unitPosition.x = Mathf.Cos(angle); unitPosition.y = Mathf.Sin(angle); unitPosition = rot * unitPosition; Vector3 normal = unitPosition; //meshBuilder.Vertices[] = ringCenter + unitPosition * radius; meshBuilder.Vertices[connectionVertexList[c][currentVertexIndex]] = ringCenter + unitPosition * radius; meshBuilder.Colors[connectionVertexList[c][currentVertexIndex]] = Color.Lerp(colorStart, colorEnd, t); currentVertexIndex++; //meshBuilder.Vertices.Add(ringCenter + unitPosition * radius); //meshBuilder.Normals.Add(normal); //meshBuilder.UVs.Add(new Vector2((float)i / segmentCount, v)); //meshBuilder.UVs.Add(new Vector2((float)j / m_splineRadialSegmentCount, t)); //verticesList.Add(meshBuilder.Vertices.Count - 1); //meshBuilder.Colors.Add(color); /*if (j > 0 && i > 0) { * //Debug.Log ("buildTriangles!"); * int baseIndex = meshBuilder.Vertices.Count - 1; * * int vertsPerRow = m_splineRadialSegmentCount + 1; * * int index0 = baseIndex; * int index1 = baseIndex - 1; * int index2 = baseIndex - vertsPerRow; * int index3 = baseIndex - vertsPerRow - 1; * * meshBuilder.AddTriangle(index1, index2, index0); * meshBuilder.AddTriangle(index1, index3, index2); * }*/ } } } meshBuilder.UpdateMeshVertices(); }
public void UpdateNodeVertexPositionsSphere(BrainNEAT brain) { for (int n = 0; n < nodeVertexList.Count; n++) { // for all neurons: //float size = Mathf.Min((neuronRadius * brain.neuronList[n].currentValue[0] * 0.2f + 0.02f), 2.0f); float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[n].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin); int currentVertexIndex = 0; if(nodePositionsList == null) { //Debug.Log("if(nodePositionsList == null) {"); } else { //Debug.Log("if(nodePositionsList != null) {" + nodePositionsList.Count.ToString() + ", n: " + n.ToString() + ", fromNode: " + brain.connectionList[n].fromNodeID.ToString()); } Vector3 offset = nodePositionsList[n] - new Vector3(0f, size, 0f); int m_HeightSegmentCount = 4; int m_RadialSegmentCount = 4; float m_VerticalScale = 1f; Quaternion rotation = Quaternion.identity; //the angle increment per height segment: float angleInc = Mathf.PI / m_HeightSegmentCount; //the vertical (scaled) radius of the sphere: float verticalRadius = size * m_VerticalScale; //build the rings: for (int i = 0; i <= m_HeightSegmentCount; i++) { Vector3 centrePos = Vector3.zero; //calculate a height offset and radius based on a vertical circle calculation: centrePos.y = -Mathf.Cos(angleInc * i); float radius = Mathf.Sin(angleInc * i); //calculate the slope of the shpere at this ring based on the height and radius: Vector2 slope = new Vector3(-centrePos.y / m_VerticalScale, radius); slope.Normalize(); //multiply the unit height by the vertical radius, and then add the radius to the height to make this sphere originate from its base rather than its centre: centrePos.y = centrePos.y * verticalRadius + verticalRadius; //scale the radius by the one stored in the partData: radius *= size; //calculate the final position of the ring centre: Vector3 finalRingCentre = rotation * centrePos + offset; //V coordinate: float v = (float)i / m_HeightSegmentCount; //build the ring: //BuildRing(meshBuilder, m_RadialSegmentCount, finalRingCentre, radius, v, i > 0, rotation, slope); float angleIncrement = (Mathf.PI * 2.0f) / m_RadialSegmentCount; for (int j = 0; j <= m_RadialSegmentCount; j++) { float angle = angleIncrement * j; Vector3 unitPosition = Vector3.zero; unitPosition.x = Mathf.Cos(angle); unitPosition.z = Mathf.Sin(angle); float normalVertical = -slope.x; float normalHorizontal = slope.y; Vector3 normal = unitPosition * normalHorizontal; normal.y = normalVertical; normal = rotation * normal; unitPosition = rotation * unitPosition; meshBuilder.Vertices[nodeVertexList[n][currentVertexIndex]] = finalRingCentre + unitPosition * radius; currentVertexIndex++; } } } meshBuilder.UpdateMeshVertices(); }
public Population BreedPopulation(ref Population sourcePopulation, int currentGeneration) { #region Pre-Crossover, Figuring out how many agents to breed etc. int LifetimeGeneration = currentGeneration + sourcePopulation.trainingGenerations; int totalNumWeightMutations = 0; //float totalWeightChangeValue = 0f; // go through species list and adjust fitness List<SpeciesBreedingPool> childSpeciesPoolsList = new List<SpeciesBreedingPool>(); // will hold agents in an internal list to facilitate crossover for (int s = 0; s < sourcePopulation.speciesBreedingPoolList.Count; s++) { SpeciesBreedingPool newChildSpeciesPool = new SpeciesBreedingPool(sourcePopulation.speciesBreedingPoolList[s].templateGenome, sourcePopulation.speciesBreedingPoolList[s].speciesID); // create Breeding Pools // copies the existing breeding pools but leaves their agentLists empty for future children childSpeciesPoolsList.Add(newChildSpeciesPool); // Add to list of pools } sourcePopulation.RankAgentArray(); // based on modified species fitness score, so compensated for species sizes Agent[] newAgentArray = new Agent[sourcePopulation.masterAgentArray.Length]; // Calculate total fitness score: float totalScore = 0f; if (survivalByRaffle) { for (int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents totalScore += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies; } } // Figure out How many Agents survive int numSurvivors = Mathf.RoundToInt(survivalRate * (float)sourcePopulation.populationMaxSize); //Depending on method, one at a time, select an Agent to survive until the max Number is reached int newChildIndex = 0; // For ( num Agents ) { for (int i = 0; i < numSurvivors; i++) { // If survival is by fitness score ranking: if (survivalByRank) { // Pop should already be ranked, so just traverse from top (best) to bottom (worst) newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[newChildIndex]; SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID); survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]); //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species' newChildIndex++; } // if survival is completely random, as a control: if (survivalStochastic) { int randomAgent = UnityEngine.Random.Range(0, numSurvivors - 1); // Set next newChild slot to a randomly-chosen agent within the survivor faction -- change to full random? newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[randomAgent]; SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID); survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]); //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species' newChildIndex++; } // if survival is based on a fitness lottery: if (survivalByRaffle) { // Try when Fitness is normalized from 0-1 float randomSlicePosition = UnityEngine.Random.Range(0f, totalScore); float accumulatedFitness = 0f; for (int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents accumulatedFitness += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies; // if accum fitness is on slicePosition, copy this Agent //Debug.Log("NumSurvivors: " + numSurvivors.ToString() + ", Surviving Agent " + a.ToString() + ": AccumFitness: " + accumulatedFitness.ToString() + ", RafflePos: " + randomSlicePosition.ToString() + ", TotalScore: " + totalScore.ToString() + ", newChildIndex: " + newChildIndex.ToString()); if (accumulatedFitness >= randomSlicePosition) { newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[a]; // add to next gen's list of agents SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID); survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]); //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species' newChildIndex++; break; } } } } // Figure out how many new agents must be created to fill up the new population: int numNewChildAgents = sourcePopulation.populationMaxSize - numSurvivors; int numEligibleBreederAgents = Mathf.RoundToInt(breedingRate * (float)sourcePopulation.populationMaxSize); int currentRankIndex = 0; // Once the agents are ranked, trim the BreedingPools of agents that didn't make the cut for mating: if(useSpeciation) { for (int s = 0; s < sourcePopulation.speciesBreedingPoolList.Count; s++) { int index = 0; int failsafe = 0; int numAgents = sourcePopulation.speciesBreedingPoolList[s].agentList.Count; while (index < numAgents) { if (index < sourcePopulation.speciesBreedingPoolList[s].agentList.Count) { if (sourcePopulation.speciesBreedingPoolList[s].agentList[index].fitnessRank >= numEligibleBreederAgents) { sourcePopulation.speciesBreedingPoolList[s].agentList.RemoveAt(index); } else { index++; } } else { break; } failsafe++; if (failsafe > 500) { Debug.Log("INFINITE LOOP! hit failsafe 500 iters -- Trimming BreedingPools!"); break; } } //Debug.Log("BreedPopulation -- TRIMSpeciesPool# " + s.ToString() + ", id: " + sourcePopulation.speciesBreedingPoolList[s].speciesID.ToString() + ", Count: " + sourcePopulation.speciesBreedingPoolList[s].agentList.Count.ToString()); // } } float totalScoreBreeders = 0f; if (breedingByRaffle) { // calculate total fitness scores to determine lottery weights for (int a = 0; a < numEligibleBreederAgents; a++) { // iterate through all agents totalScoreBreeders += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies; } } #endregion // Iterate over numAgentsToCreate : int newChildrenCreated = 0; while (newChildrenCreated < numNewChildAgents) { // Find how many parents random number btw min/max: int numParentAgents = 2; // UnityEngine.Random.Range(minNumParents, maxNumParents); int numChildAgents = 1; // defaults to one child, but: if (numNewChildAgents - newChildrenCreated >= 2) { // room for two more! numChildAgents = 2; } Agent[] parentAgentsArray = new Agent[numParentAgents]; // assume 2 for now? yes, so far.... List<GeneNodeNEAT>[] parentNodeListArray = new List<GeneNodeNEAT>[numParentAgents]; List<GeneLinkNEAT>[] parentLinkListArray = new List<GeneLinkNEAT>[numParentAgents]; Agent firstParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex); parentAgentsArray[0] = firstParentAgent; List<GeneNodeNEAT> firstParentNodeList = firstParentAgent.brainGenome.nodeNEATList; List<GeneLinkNEAT> firstParentLinkList = firstParentAgent.brainGenome.linkNEATList; //List<GeneNodeNEAT> firstParentNodeList = new List<GeneNodeNEAT>(); //List<GeneLinkNEAT> firstParentLinkList = new List<GeneLinkNEAT>(); //firstParentNodeList = firstParentAgent.brainGenome.nodeNEATList; //firstParentLinkList = firstParentAgent.brainGenome.linkNEATList; parentNodeListArray[0] = firstParentNodeList; parentLinkListArray[0] = firstParentLinkList; Agent secondParentAgent; SpeciesBreedingPool parentAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(sourcePopulation.speciesBreedingPoolList, firstParentAgent.speciesID); if (useSpeciation) { //parentAgentBreedingPool float randBreedOutsideSpecies = UnityEngine.Random.Range(0f, 1f); if (randBreedOutsideSpecies < interspeciesBreedingRate) { // Attempts to Found a new species // allowed to breed outside its own species: secondParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex); } else { // Selects mate only from within its own species: secondParentAgent = SelectAgentFromPoolForBreeding(parentAgentBreedingPool); } } else { secondParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex); } parentAgentsArray[1] = secondParentAgent; List<GeneNodeNEAT> secondParentNodeList = secondParentAgent.brainGenome.nodeNEATList; List<GeneLinkNEAT> secondParentLinkList = secondParentAgent.brainGenome.linkNEATList; //List<GeneNodeNEAT> secondParentNodeList = new List<GeneNodeNEAT>(); //List<GeneLinkNEAT> secondParentLinkList = new List<GeneLinkNEAT>(); //secondParentNodeList = secondParentAgent.brainGenome.nodeNEATList; //secondParentLinkList = secondParentAgent.brainGenome.linkNEATList; parentNodeListArray[1] = secondParentNodeList; parentLinkListArray[1] = secondParentLinkList; // Iterate over ChildArray.Length : // how many newAgents created for (int c = 0; c < numChildAgents; c++) { // for number of child Agents in floatArray[][]: Agent newChildAgent = new Agent(); List<GeneNodeNEAT> childNodeList = new List<GeneNodeNEAT>(); List<GeneLinkNEAT> childLinkList = new List<GeneLinkNEAT>(); GenomeNEAT childBrainGenome = new GenomeNEAT(); childBrainGenome.nodeNEATList = childNodeList; childBrainGenome.linkNEATList = childLinkList; int numEnabledLinkGenes = 0; if (useCrossover) { int nextLinkInnoA = 0; int nextLinkInnoB = 0; //int nextBodyNodeInno = 0; //int nextBodyAddonInno = 0; int failsafeMax = 500; int failsafe = 0; int parentListIndexA = 0; int parentListIndexB = 0; //int parentBodyNodeIndex = 0; bool parentDoneA = false; bool parentDoneB = false; bool endReached = false; int moreFitParent = 0; // which parent is more Fit if (parentAgentsArray[0].fitnessScoreSpecies < parentAgentsArray[1].fitnessScoreSpecies) { moreFitParent = 1; } else if (parentAgentsArray[0].fitnessScoreSpecies == parentAgentsArray[1].fitnessScoreSpecies) { moreFitParent = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 1f)); } // MATCH UP Links between both agents, if they have a gene with matching Inno#, then mixing can occur while (!endReached) { failsafe++; if(failsafe > failsafeMax) { Debug.Log("failsafe reached!"); break; } // inno# of next links: if(parentLinkListArray[0].Count > parentListIndexA) { nextLinkInnoA = parentLinkListArray[0][parentListIndexA].innov; } else { parentDoneA = true; } if (parentLinkListArray[1].Count > parentListIndexB) { nextLinkInnoB = parentLinkListArray[1][parentListIndexB].innov; } else { parentDoneB = true; } int innoDelta = nextLinkInnoA - nextLinkInnoB; // 0=match, neg= Aextra, pos= Bextra if (parentDoneA && !parentDoneB) { innoDelta = 1; } if (parentDoneB && !parentDoneA) { innoDelta = -1; } if (parentDoneA && parentDoneB) { // reached end of both parent's linkLists endReached = true; break; } if (innoDelta < 0) { // Parent A has an earlier link mutation //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta < 0 (" + innoDelta.ToString() + ") -- moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString()); if (moreFitParent == 0) { // Parent A is more fit: GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, parentLinkListArray[0][parentListIndexA].weight, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen); childLinkList.Add(newChildLink); if (parentLinkListArray[0][parentListIndexA].enabled) numEnabledLinkGenes++; } else { if(CheckForMutation(crossoverRandomLinkChance)) { // was less fit parent, but still passed on a gene!: GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, parentLinkListArray[0][parentListIndexA].weight, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen); childLinkList.Add(newChildLink); } } parentListIndexA++; } if (innoDelta > 0) { // Parent B has an earlier link mutation //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta > 0 (" + innoDelta.ToString() + ") -- moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString()); if (moreFitParent == 1) { // Parent B is more fit: GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[1][parentListIndexB].fromNodeID, parentLinkListArray[1][parentListIndexB].toNodeID, parentLinkListArray[1][parentListIndexB].weight, parentLinkListArray[1][parentListIndexB].enabled, parentLinkListArray[1][parentListIndexB].innov, parentLinkListArray[1][parentListIndexB].birthGen); childLinkList.Add(newChildLink); if (parentLinkListArray[1][parentListIndexB].enabled) numEnabledLinkGenes++; } else { if (CheckForMutation(crossoverRandomLinkChance)) { // was less fit parent, but still passed on a gene!: GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[1][parentListIndexB].fromNodeID, parentLinkListArray[1][parentListIndexB].toNodeID, parentLinkListArray[1][parentListIndexB].weight, parentLinkListArray[1][parentListIndexB].enabled, parentLinkListArray[1][parentListIndexB].innov, parentLinkListArray[1][parentListIndexB].birthGen); childLinkList.Add(newChildLink); } } parentListIndexB++; } if (innoDelta == 0) { // Match! float randParentIndex = UnityEngine.Random.Range(0f, 1f); float newWeightValue; if (randParentIndex < 0.5) { // ParentA wins: newWeightValue = parentLinkListArray[0][parentListIndexA].weight; } else { // ParentB wins: newWeightValue = parentLinkListArray[1][parentListIndexB].weight; } //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta == 0 (" + innoDelta.ToString() + ") -- moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString() + ", randParent: " + randParentIndex.ToString() + ", weight: " + newWeightValue.ToString()); GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, newWeightValue, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen); childLinkList.Add(newChildLink); if (parentLinkListArray[0][parentListIndexA].enabled) numEnabledLinkGenes++; parentListIndexA++; parentListIndexB++; } } // once childLinkList is built -- use nodes of the moreFit parent: for (int i = 0; i < parentNodeListArray[moreFitParent].Count; i++) { // iterate through all nodes in the parent List and copy them into fresh new geneNodes: GeneNodeNEAT clonedNode = new GeneNodeNEAT(parentNodeListArray[moreFitParent][i].id, parentNodeListArray[moreFitParent][i].nodeType, parentNodeListArray[moreFitParent][i].activationFunction, parentNodeListArray[moreFitParent][i].sourceAddonInno, parentNodeListArray[moreFitParent][i].sourceAddonRecursionNum, false, parentNodeListArray[moreFitParent][i].sourceAddonChannelNum); childNodeList.Add(clonedNode); } if (useMutation) { // BODY MUTATION: //PerformBodyMutation(ref childBodyGenome, ref childBrainGenome); // NEED TO ADJUST BRAINS IF MUTATION CHANGES #NODES!!!! // BRAIN MUTATION: if (numEnabledLinkGenes < 1) numEnabledLinkGenes = 1; for (int k = 0; k < childLinkList.Count; k++) { float mutateChance = mutationBlastModifier * masterMutationRate / (1f + (float)numEnabledLinkGenes * 0.15f); if (LifetimeGeneration - childLinkList[k].birthGen < newLinkBonusDuration) { float t = 1 - ((LifetimeGeneration - childLinkList[k].birthGen) / (float)newLinkBonusDuration); // t=0 means age of gene is same as bonusDuration, t=1 means it is brand new mutateChance = Mathf.Lerp(mutateChance, mutateChance * newLinkMutateBonus, t); } if (CheckForMutation(mutateChance)) { // Weight Mutation! //Debug.Log("Weight Mutation Link[" + k.ToString() + "] weight: " + childLinkList[k].weight.ToString() + ", mutate: " + MutateFloat(childLinkList[k].weight).ToString()); childLinkList[k].weight = MutateFloat(childLinkList[k].weight); totalNumWeightMutations++; } } if (CheckForMutation(mutationBlastModifier * mutationRemoveLinkChance)) { //Debug.Log("Remove Link Mutation Agent[" + newChildIndex.ToString() + "]"); childBrainGenome.RemoveRandomLink(); } if (CheckForMutation(mutationBlastModifier * mutationAddNodeChance)) { // Adds a new node //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]"); childBrainGenome.AddNewRandomNode(LifetimeGeneration, GetNextAddonInnov()); } if (CheckForMutation(mutationBlastModifier * mutationRemoveNodeChance)) { // Adds a new node //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]"); childBrainGenome.RemoveRandomNode(); } if (CheckForMutation(mutationBlastModifier * mutationAddLinkChance)) { // Adds new connection //Debug.Log("Add Link Mutation Agent[" + newChildIndex.ToString() + "]"); if (CheckForMutation(existingNetworkBias)) { childBrainGenome.AddNewExtraLink(existingFromNodeBias, LifetimeGeneration); } else { childBrainGenome.AddNewRandomLink(LifetimeGeneration); } } if (CheckForMutation(mutationBlastModifier * mutationActivationFunctionChance)) { TransferFunctions.TransferFunction newFunction; int randIndex = Mathf.RoundToInt(UnityEngine.Random.Range(0f, childNodeList.Count - 1)); int randomTF = (int)UnityEngine.Random.Range(0f, 12f); switch (randomTF) { case 0: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; case 1: newFunction = TransferFunctions.TransferFunction.Linear; break; case 2: newFunction = TransferFunctions.TransferFunction.Gaussian; break; case 3: newFunction = TransferFunctions.TransferFunction.Abs; break; case 4: newFunction = TransferFunctions.TransferFunction.Cos; break; case 5: newFunction = TransferFunctions.TransferFunction.Sin; break; case 6: newFunction = TransferFunctions.TransferFunction.Tan; break; case 7: newFunction = TransferFunctions.TransferFunction.Square; break; case 8: newFunction = TransferFunctions.TransferFunction.Threshold01; break; case 9: newFunction = TransferFunctions.TransferFunction.ThresholdNegPos; break; case 10: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; case 11: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; case 12: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; default: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; } if (childNodeList[randIndex].nodeType != GeneNodeNEAT.GeneNodeType.Out) { // keep outputs -1 to 1 range Debug.Log("ActivationFunction Mutation Node[" + randIndex.ToString() + "] prev: " + childNodeList[randIndex].activationFunction.ToString() + ", new: " + newFunction.ToString()); childNodeList[randIndex].activationFunction = newFunction; } } } else { Debug.Log("Mutation Disabled!"); } // THE BODY ==========!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!====================================================================================== CritterGenome childBodyGenome = new CritterGenome(); // create new body genome for Child // This creates the ROOT NODE!!!! // Clone Nodes & Addons from more fit parent to create new child body genome // crossover is on, so check for matching Nodes and Add-ons (based on Inno#'s) to determine when to mix Settings/Attributes: // Iterate over the nodes of the more fit parent: for (int i = 0; i < parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList.Count; i++) { int currentNodeInno = parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[i].innov; if (i == 0) { // if this is the ROOT NODE: childBodyGenome.CritterNodeList[0].CopySettingsFromNode(parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[0]); // The root node was already created during the Constructor method of the CritterGenome, // ... so instead of creating a new one, just copy the settings } else { // NOT the root node, proceed normally: // Create new cloned node defaulted to the settings of the source( more-fit parent's) Node: CritterNode clonedCritterNode = parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[i].CloneThisCritterNode(); // Check other parent for same node: for (int j = 0; j < parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList.Count; j++) { if (parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList[j].innov == currentNodeInno) { // CROSSOVER NODE SETTINGS HERE!!! ---- If random dice roll > 0.5, use less fit parent's settings, otherwise leave as default BodyCrossover(ref clonedCritterNode, parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList[j]); } } childBodyGenome.CritterNodeList.Add(clonedCritterNode); } } // ADD-ONS!!!!!!!!!!!!!!!!!!!!!! BreedCritterAddons(ref childBodyGenome, ref parentAgentsArray[moreFitParent].bodyGenome, ref parentAgentsArray[1 - moreFitParent].bodyGenome); newChildAgent.bodyGenome = childBodyGenome; // ????? if (useMutation) { // BODY MUTATION: PerformBodyMutation(ref childBodyGenome, ref childBrainGenome); } } else { // no crossover: //=============================================================================================== for (int i = 0; i < parentNodeListArray[0].Count; i++) { // iterate through all nodes in the parent List and copy them into fresh new geneNodes: GeneNodeNEAT clonedNode = new GeneNodeNEAT(parentNodeListArray[0][i].id, parentNodeListArray[0][i].nodeType, parentNodeListArray[0][i].activationFunction, parentNodeListArray[0][i].sourceAddonInno, parentNodeListArray[0][i].sourceAddonRecursionNum, false, parentNodeListArray[0][i].sourceAddonChannelNum); childNodeList.Add(clonedNode); } for (int j = 0; j < parentLinkListArray[0].Count; j++) { //same thing with connections GeneLinkNEAT clonedLink = new GeneLinkNEAT(parentLinkListArray[0][j].fromNodeID, parentLinkListArray[0][j].toNodeID, parentLinkListArray[0][j].weight, parentLinkListArray[0][j].enabled, parentLinkListArray[0][j].innov, parentLinkListArray[0][j].birthGen); childLinkList.Add(clonedLink); if (parentLinkListArray[0][j].enabled) numEnabledLinkGenes++; } // MUTATION: if (useMutation) { // BODY MUTATION: //childBrainGenome.nodeNEATList = childNodeList //PerformBodyMutation(ref childBodyGenome, ref childBrainGenome); // BRAIN MUTATION: if (numEnabledLinkGenes < 1) numEnabledLinkGenes = 1; for (int k = 0; k < childLinkList.Count; k++) { float mutateChance = mutationBlastModifier * masterMutationRate / (1f + (float)numEnabledLinkGenes * 0.15f); if (LifetimeGeneration - childLinkList[k].birthGen < newLinkBonusDuration) { float t = 1 - ((LifetimeGeneration - childLinkList[k].birthGen) / (float)newLinkBonusDuration); // t=0 means age of gene is same as bonusDuration, t=1 means it is brand new mutateChance = Mathf.Lerp(mutateChance, mutateChance * newLinkMutateBonus, t); } if (CheckForMutation(mutateChance)) { // Weight Mutation! //Debug.Log("Weight Mutation Link[" + k.ToString() + "] weight: " + childLinkList[k].weight.ToString() + ", mutate: " + MutateFloat(childLinkList[k].weight).ToString()); childLinkList[k].weight = MutateFloat(childLinkList[k].weight); totalNumWeightMutations++; } } if (CheckForMutation(mutationBlastModifier * mutationRemoveLinkChance)) { //Debug.Log("Remove Link Mutation Agent[" + newChildIndex.ToString() + "]"); childBrainGenome.RemoveRandomLink(); } if (CheckForMutation(mutationBlastModifier * mutationAddNodeChance)) { // Adds a new node //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]"); childBrainGenome.AddNewRandomNode(LifetimeGeneration, GetNextAddonInnov()); } if (CheckForMutation(mutationBlastModifier * mutationAddLinkChance)) { // Adds new connection //Debug.Log("Add Link Mutation Agent[" + newChildIndex.ToString() + "]"); if(CheckForMutation(existingNetworkBias)) { childBrainGenome.AddNewExtraLink(existingFromNodeBias, LifetimeGeneration); } else { childBrainGenome.AddNewRandomLink(LifetimeGeneration); } } if (CheckForMutation(mutationBlastModifier * mutationActivationFunctionChance)) { TransferFunctions.TransferFunction newFunction; int randIndex = Mathf.RoundToInt(UnityEngine.Random.Range(0f, childNodeList.Count - 1)); int randomTF = (int)UnityEngine.Random.Range(0f, 12f); switch (randomTF) { case 0: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; case 1: newFunction = TransferFunctions.TransferFunction.Linear; break; case 2: newFunction = TransferFunctions.TransferFunction.Gaussian; break; case 3: newFunction = TransferFunctions.TransferFunction.Abs; break; case 4: newFunction = TransferFunctions.TransferFunction.Cos; break; case 5: newFunction = TransferFunctions.TransferFunction.Sin; break; case 6: newFunction = TransferFunctions.TransferFunction.Tan; break; case 7: newFunction = TransferFunctions.TransferFunction.Square; break; case 8: newFunction = TransferFunctions.TransferFunction.Threshold01; break; case 9: newFunction = TransferFunctions.TransferFunction.ThresholdNegPos; break; case 10: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; case 11: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; case 12: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; default: newFunction = TransferFunctions.TransferFunction.RationalSigmoid; break; } if (childNodeList[randIndex].nodeType != GeneNodeNEAT.GeneNodeType.Out) { // keep outputs -1 to 1 range Debug.Log("ActivationFunction Mutation Node[" + randIndex.ToString() + "] prev: " + childNodeList[randIndex].activationFunction.ToString() + ", new: " + newFunction.ToString()); childNodeList[randIndex].activationFunction = newFunction; } } //for (int t = 0; t < childNodeList.Count; t++) { //} } else { Debug.Log("Mutation Disabled!"); } // THE BODY!!!!! ++++++++++++++++++++++================+++++++++++++++++++===============+++++++++++++++++++===================+++++++++++++++++============== CritterGenome childBodyGenome = new CritterGenome(); // create new body genome for Child // Iterate over the nodes of the more fit parent: for (int i = 0; i < parentAgentsArray[0].bodyGenome.CritterNodeList.Count; i++) { int currentNodeInno = parentAgentsArray[0].bodyGenome.CritterNodeList[i].innov; if (i == 0) { // if this is the ROOT NODE: childBodyGenome.CritterNodeList[0].CopySettingsFromNode(parentAgentsArray[0].bodyGenome.CritterNodeList[0]); // The root node was already created during the Constructor method of the CritterGenome, // ... so instead of creating a new one, just copy the settings } else { // NOT the root node, proceed normally: // Create new cloned node defaulted to the settings of the source( more-fit parent's) Node: CritterNode clonedCritterNode = parentAgentsArray[0].bodyGenome.CritterNodeList[i].CloneThisCritterNode(); childBodyGenome.CritterNodeList.Add(clonedCritterNode); } } // ADD-ONS!!!!!!!!!!!!!!!!!!!!!! BreedCritterAddons(ref childBodyGenome, ref parentAgentsArray[0].bodyGenome, ref parentAgentsArray[0].bodyGenome); newChildAgent.bodyGenome = childBodyGenome; if (useMutation) { // BODY MUTATION: PerformBodyMutation(ref childBodyGenome, ref childBrainGenome); } } newChildAgent.brainGenome = childBrainGenome; //newChildAgent.brainGenome.nodeNEATList = childNodeList; //newChildAgent.brainGenome.linkNEATList = childLinkList; BrainNEAT childBrain = new BrainNEAT(newChildAgent.brainGenome); childBrain.BuildBrainNetwork(); newChildAgent.brain = childBrain; //Debug.Log("NEW CHILD numNodes: " + newChildAgent.brainGenome.nodeNEATList.Count.ToString() + ", #Neurons: " + newChildAgent.brain.neuronList.Count.ToString()); //newChildAgent.bodyGenome.PreBuildCritter(0.8f); // Species: if (useSpeciation) { float randAdoption = UnityEngine.Random.Range(0f, 1f); if (randAdoption < adoptionRate) { // Attempts to Found a new species bool speciesGenomeMatch = false; for (int s = 0; s < childSpeciesPoolsList.Count; s++) { float geneticDistance = GenomeNEAT.MeasureGeneticDistance(newChildAgent.brainGenome, childSpeciesPoolsList[s].templateGenome, neuronWeight, linkWeight, weightWeight, normalizeExcess, normalizeDisjoint, normalizeLinkWeight); if (geneticDistance < speciesSimilarityThreshold) { speciesGenomeMatch = true; //agent.speciesID = speciesBreedingPoolList[s].speciesID; // this is done inside the AddNewAgent method below v v v childSpeciesPoolsList[s].AddNewAgent(newChildAgent); //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") SortAgentIntoBreedingPool dist: " + geneticDistance.ToString() + ", speciesIDs: " + newChildAgent.speciesID.ToString() + ", " + childSpeciesPoolsList[s].speciesID.ToString() + ", speciesCount: " + childSpeciesPoolsList[s].agentList.Count.ToString()); break; } } if (!speciesGenomeMatch) { SpeciesBreedingPool newSpeciesBreedingPool = new SpeciesBreedingPool(newChildAgent.brainGenome, sourcePopulation.GetNextSpeciesID()); // creates new speciesPool modeled on this agent's genome newSpeciesBreedingPool.AddNewAgent(newChildAgent); // add this agent to breeding pool childSpeciesPoolsList.Add(newSpeciesBreedingPool); // add new speciesPool to the population's list of all active species //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") SortAgentIntoBreedingPool NO MATCH!!! -- creating new BreedingPool " + newSpeciesBreedingPool.speciesID.ToString() + ", newChildAgentSpeciesID: " + newChildAgent.speciesID.ToString()); } } else { // joins parent species automatically: SpeciesBreedingPool newSpeciesBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, parentAgentBreedingPool.speciesID); newSpeciesBreedingPool.AddNewAgent(newChildAgent); // add this agent to breeding pool //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") NO ADOPTION SortAgentIntoBreedingPool speciesIDs: " + newChildAgent.speciesID.ToString() + ", " + newSpeciesBreedingPool.speciesID.ToString() + ", speciesCount: " + newSpeciesBreedingPool.agentList.Count.ToString()); } } else { // joins parent species automatically: SpeciesBreedingPool newSpeciesBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, parentAgentBreedingPool.speciesID); newSpeciesBreedingPool.AddNewAgent(newChildAgent); // add this agent to breeding pool } newChildAgent.parentFitnessScoreA = sourcePopulation.masterAgentArray[newChildIndex].fitnessScore; newAgentArray[newChildIndex] = newChildAgent; newChildIndex++; // new child created! newChildrenCreated++; } } /*Debug.Log("Finished Crossover! childSpeciesPoolsList:"); for (int i = 0; i < sourcePopulation.speciesBreedingPoolList.Count; i++) { string poolString = " Child Species ID: " + sourcePopulation.speciesBreedingPoolList[i].speciesID.ToString(); for (int j = 0; j < sourcePopulation.speciesBreedingPoolList[i].agentList.Count; j++) { poolString += ", member# " + j.ToString() + ", species: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].speciesID.ToString() + ", fitRank: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].fitnessRank.ToString(); } Debug.Log(poolString); }*/ // Clear out extinct species: int listIndex = 0; for (int s = 0; s < childSpeciesPoolsList.Count; s++) { if (listIndex >= childSpeciesPoolsList.Count) { Debug.Log("end childSpeciesPoolsList " + childSpeciesPoolsList.Count.ToString() + ", index= " + listIndex.ToString()); break; } else { if (childSpeciesPoolsList[listIndex].agentList.Count == 0) { // if empty: //Debug.Log("Species " + childSpeciesPoolsList[listIndex].speciesID.ToString() + " WENT EXTINCT!!! --- childSpeciesPoolsList[" + listIndex.ToString() + "] old Count: " + childSpeciesPoolsList.Count.ToString() + ", s: " + s.ToString()); childSpeciesPoolsList.RemoveAt(listIndex); //s--; // see if this works } else { listIndex++; } } } Debug.Log("Finished Crossover! totalNumWeightMutations: " + totalNumWeightMutations.ToString() + ", mutationBlastModifier: " + mutationBlastModifier.ToString() + ", bodyMutationBlastModifier: " + bodyMutationBlastModifier.ToString() + ", LifetimeGeneration: " + LifetimeGeneration.ToString() + ", currentGeneration: " + currentGeneration.ToString() + ", sourcePopulation.trainingGenerations: " + sourcePopulation.trainingGenerations.ToString()); sourcePopulation.masterAgentArray = newAgentArray; sourcePopulation.speciesBreedingPoolList = childSpeciesPoolsList; /*Debug.Log("Finished Crossover! sourcePopulation.speciesBreedingPoolList:"); for (int i = 0; i < sourcePopulation.speciesBreedingPoolList.Count; i++) { string poolString = "New Species ID: " + sourcePopulation.speciesBreedingPoolList[i].speciesID.ToString(); for (int j = 0; j < sourcePopulation.speciesBreedingPoolList[i].agentList.Count; j++) { poolString += ", member# " + j.ToString() + ", species: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].speciesID.ToString() + ", fitRank: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].fitnessRank.ToString(); } Debug.Log(poolString); }*/ return sourcePopulation; }
public void UpdateConnectionVertexPositionsBezier(BrainNEAT brain) { for (int c = 0; c < connectionVertexList.Count; c++) { // for all connections: /*Vector3 linkVector = new Vector3(nodePositionsList[brain.connectionList[i].toNodeID].x - nodePositionsList[brain.connectionList[i].fromNodeID].x, nodePositionsList[brain.connectionList[i].toNodeID].y - nodePositionsList[brain.connectionList[i].fromNodeID].y, nodePositionsList[brain.connectionList[i].toNodeID].z - nodePositionsList[brain.connectionList[i].fromNodeID].z); Vector3 widthVector = new Vector3(new Vector2(linkVector.y, -linkVector.x).normalized.x, new Vector2(linkVector.y, -linkVector.x).normalized.y, 0f) * (connectionWidth + Mathf.Abs(brain.connectionList[i].weight[0]) * connectionWidth * 0.62f); Vector3 cornerPos = new Vector3(nodePositionsList[brain.connectionList[i].fromNodeID].x - widthVector.x * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].y - widthVector.y * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].z); //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString()); meshBuilder.Vertices[connectionVertexList[i][0]] = cornerPos; meshBuilder.Vertices[connectionVertexList[i][1]] = cornerPos + linkVector; meshBuilder.Vertices[connectionVertexList[i][2]] = cornerPos + linkVector + widthVector; meshBuilder.Vertices[connectionVertexList[i][3]] = cornerPos + widthVector; */ int currentVertexIndex = 0; //float width = connectionWidth; // brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0]; Color colorStart = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]); Color colorEnd = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID]); float startWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin); float endWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin); float m_splineStartRadius = startWidth; float m_splineEndRadius = endWidth; int m_splineHeightSegmentCount = 8; int m_splineRadialSegmentCount = 4; float tInc = 1f / m_splineHeightSegmentCount; // How many subdivisions along the length of the spline for (int i = 0; i <= m_splineHeightSegmentCount; i++) { float t = tInc * (float)i; Vector3 ringCenter = bezierCurveList[c].GetPoint(t); Vector3 dir = bezierCurveList[c].GetDirection(t); Quaternion rot = Quaternion.identity; if(dir != Vector3.zero) { rot.SetLookRotation(dir); } float radius = ((1f - t) * m_splineStartRadius) + (t * m_splineEndRadius); // Construct the mesh Ring! //BuildBezierCurveRing(meshBuilder, m_splineRadialSegmentCount, ringCenter, radius, t, i > 0, rot); //protected void BuildBezierCurveRing(MeshBuilder meshBuilder, int segmentCount, Vector3 center, float radius, float v, bool buildTriangles, Quaternion rotation) { float angleInc = (Mathf.PI * 2.0f) / m_splineRadialSegmentCount; for (int j = 0; j <= m_splineRadialSegmentCount; j++) { float angle = angleInc * j; Vector3 unitPosition = Vector3.zero; unitPosition.x = Mathf.Cos(angle); unitPosition.y = Mathf.Sin(angle); unitPosition = rot * unitPosition; Vector3 normal = unitPosition; //meshBuilder.Vertices[] = ringCenter + unitPosition * radius; meshBuilder.Vertices[connectionVertexList[c][currentVertexIndex]] = ringCenter + unitPosition * radius; meshBuilder.Colors[connectionVertexList[c][currentVertexIndex]] = Color.Lerp(colorStart, colorEnd, t); currentVertexIndex++; //meshBuilder.Vertices.Add(ringCenter + unitPosition * radius); //meshBuilder.Normals.Add(normal); //meshBuilder.UVs.Add(new Vector2((float)i / segmentCount, v)); //meshBuilder.UVs.Add(new Vector2((float)j / m_splineRadialSegmentCount, t)); //verticesList.Add(meshBuilder.Vertices.Count - 1); //meshBuilder.Colors.Add(color); /*if (j > 0 && i > 0) { //Debug.Log ("buildTriangles!"); int baseIndex = meshBuilder.Vertices.Count - 1; int vertsPerRow = m_splineRadialSegmentCount + 1; int index0 = baseIndex; int index1 = baseIndex - 1; int index2 = baseIndex - vertsPerRow; int index3 = baseIndex - vertsPerRow - 1; meshBuilder.AddTriangle(index1, index2, index0); meshBuilder.AddTriangle(index1, index3, index2); }*/ } } } meshBuilder.UpdateMeshVertices(); }
private void BrainNEAT_Click(object sender, RoutedEventArgs e) { try { if (_experiment == null || _ea == null) { //NOTE: Just doing this for laziness. I don't want to write a bunch of logic to train a phenome up front MessageBox.Show("Need to have a running experiment", this.Title, MessageBoxButton.OK, MessageBoxImage.Warning); return; } // Get a genome NeatGenome genome = _ea.CurrentChampGenome; // Create a phenome IBlackBox phenome = ExperimentNEATBase.GetBlackBox(genome, _experimentArgs.Activation, _hyperneatArgs); // Instantiate a BrainNEAT EditorOptions options = new EditorOptions(); ItemOptions itemOptions = new ItemOptions(); Container energy = new Container() { QuantityMax = 1000, QuantityCurrent = 1000, }; BrainNEATDNA dnaBrain = new BrainNEATDNA() { PartType = BrainNEAT.PARTTYPE, Position = new Point3D(0, 0, 0), Orientation = Quaternion.Identity, Scale = new Vector3D(1, 1, 1) }; BrainNEAT brain = new BrainNEAT(options, itemOptions, dnaBrain, energy); brain.SetPhenome(phenome, genome, _experimentArgs.Activation, _hyperneatArgs); for (int cntr = 0; cntr < 100; cntr++) { foreach (INeuron neuron in brain.Neruons_Writeonly) { neuron.SetValue(StaticRandom.NextDouble(-2.5, 2.5)); } brain.Update_AnyThread(1); } #region save/load test2 // let BrainNEAT do the save/load BrainNEATDNA dna2 = (BrainNEATDNA)brain.GetNewDNA(); string dna2Text = XamlServices.Save(dna2).Replace('"', '\''); BrainNEAT brain2 = new BrainNEAT(options, itemOptions, dna2, energy); for (int cntr = 0; cntr < 100; cntr++) { foreach (INeuron neuron in brain2.Neruons_Writeonly) { neuron.SetValue(StaticRandom.NextDouble(-2.5, 2.5)); } brain2.Update_AnyThread(1); } BrainNEATDNA dna3 = (BrainNEATDNA)brain2.GetNewDNA(); BrainNEAT brain3 = new BrainNEAT(options, itemOptions, dna3, energy); for (int cntr = 0; cntr < 100; cntr++) { foreach (INeuron neuron in brain3.Neruons_Writeonly) { neuron.SetValue(StaticRandom.NextDouble(-2.5, 2.5)); } brain3.Update_AnyThread(1); } #endregion #region save/load test1 // initial test, building minimum necessary dna BrainNEATDNA brainDNA = new BrainNEATDNA() { Activation = _experimentArgs.Activation, Hyper = _hyperneatArgs, NEATPositions_Input = brain.Neruons_Readonly.Select(o => o.Position).ToArray(), NEATPositions_Output = brain.Neruons_Writeonly.Select(o => o.Position).ToArray(), Genome = ExperimentNEATBase.SavePopulation(new[] { genome }), }; // Make sure this can be serialized/deserialized string testString = XamlServices.Save(brainDNA); brainDNA = UtilityCore.Clone(brainDNA); List <NeatGenome> genomeList = null; if (_hyperneatArgs == null) { genomeList = ExperimentNEATBase.LoadPopulation(brainDNA.Genome, brainDNA.Activation, brainDNA.NEATPositions_Input.Length, brainDNA.NEATPositions_Output.Length); } else { genomeList = ExperimentNEATBase.LoadPopulation(brainDNA.Genome, brainDNA.Activation, _hyperneatArgs); } #endregion } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }