public NeuronNEAT(int nodeID, GeneNodeNEAT.GeneNodeType type, TransferFunctions.TransferFunction function) { id = nodeID; nodeType = type; currentValue = new float[1]; incomingConnectionsList = new List<ConnectionNEAT>(); activationFunction = function; }
/// Ticks state of brain forward 1 time-step public void BrainMasterFunction() { // NAIVE APPROACH: // run through all links and save sum values in target neurons foreach (var axon in axons) { float curVal = axon.from.currentValue; // Find input neuron, multiply its value by the axon weight, and add that to output neuron total: //neurons[axon.to].inputTotal += axon.weight * neurons[axon.from].currentValue[0]; axon.to.inputTotal += axon.weight * curVal; } // Once all axons are calculated, process the neurons foreach (var neuron in neurons) { // Save previous state neuron.previousValue = neuron.currentValue; if (neuron.io != NeuronType.In) { neuron.currentValue = TransferFunctions.Evaluate(TransferFunctions.TransferFunction.RationalSigmoid, neuron.inputTotal); } // Zero out inputSum neuron.inputTotal = 0f; } }
private void CalculateNodeInputs(NeuronNEAT currentNeuron) // recursive function { numNodesVisited++; if (numNodesVisited >= 100) { Debug.Log("CalculateNodeInputs() HIT MAX NODE COUNT!"); return; } visitedNodes.Add(currentNeuron); // to avoid infinite recursion for (int i = 0; i < currentNeuron.incomingConnectionsList.Count; i++) { //Debug.Log("CalculateNodeInputs! [" + currentNeuron.id.ToString() + "] incoming: " + currentNeuron.incomingConnectionsList[i].fromNodeID.ToString() + " -> " + currentNeuron.incomingConnectionsList[i].toNodeID.ToString()); //if (outputNeuronList.Contains(currentNeuron)) { //Debug.Log("CalculateNodeInputs! visitedNodes.Clear();"); //} currentNeuron.currentValue[0] += neuronList[currentNeuron.incomingConnectionsList[i].fromNodeID].previousValue * currentNeuron.incomingConnectionsList[i].weight[0]; if (neuronList[currentNeuron.incomingConnectionsList[i].fromNodeID].nodeType != GeneNodeNEAT.GeneNodeType.In) // if incoming connection isn't an Input Neuron { if (visitedNodes.Contains(neuronList[currentNeuron.incomingConnectionsList[i].fromNodeID])) { if (completedNodes.Contains(neuronList[currentNeuron.incomingConnectionsList[i].fromNodeID])) { // done } else { Debug.Log("Incoming connection has already been visited! RECURSION?? nodeID: " + currentNeuron.id.ToString() + ", fromNode: " + neuronList[currentNeuron.incomingConnectionsList[i].fromNodeID].id.ToString()); } } else { CalculateNodeInputs(neuronList[currentNeuron.incomingConnectionsList[i].fromNodeID]); } } else { // if it IS an input neuron: visitedNodes.Clear(); } } if (currentNeuron.nodeType == GeneNodeNEAT.GeneNodeType.Out) { currentNeuron.currentValue[0] = TransferFunctions.Evaluate(TransferFunctions.TransferFunction.RationalSigmoid, currentNeuron.currentValue[0]); } else { currentNeuron.currentValue[0] = TransferFunctions.Evaluate(TransferFunctions.TransferFunction.Linear, currentNeuron.currentValue[0]); } completedNodes.Add(currentNeuron); //processedNodes.Add(currentNeuron); //return allInputsProcessed; }
public GeneNodeNEAT(int id, GeneNodeType nodeType, TransferFunctions.TransferFunction function, int inno, int recurse, bool mirror, int channelNum) { this.id = id; this.nodeType = nodeType; this.activationFunction = function; sourceAddonInno = inno; sourceAddonRecursionNum = recurse; if (mirror) { sourceAddonRecursionNum += 10; } sourceAddonChannelNum = channelNum; }
// WPP: replaced with reflection /*float[] GetNeuralValue(string neuronID) * { * switch (neuronID) * { * case "enemyPosX": return enemyPosX; * case "enemyPosY": return enemyPosY; * case "enemyVelX": return enemyVelX; * case "enemyVelY": return enemyVelY; * case "enemyDirX": return enemyDirX; * case "enemyDirY": return enemyDirY; * case "enemyRelSize": return enemyRelSize; * case "enemyHealth": return enemyHealth; * case "enemyGrowthStage": return enemyGrowthStage; * case "enemyThreatRating": return enemyThreatRating; * default: return null; * } * }*/ public void Tick(Agent agent) { Vector2 enemyPos = Vector2.zero; Vector2 enemyDir = Vector2.zero; Vector2 enemyVel = Vector2.zero; if (agent.coreModule.nearestEnemyAgent) { enemyPos = new Vector2(agent.coreModule.nearestEnemyAgent.bodyRigidbody.transform.localPosition.x - agent.ownPos.x, agent.coreModule.nearestEnemyAgent.bodyRigidbody.transform.localPosition.y - agent.ownPos.y); enemyDir = enemyPos.normalized; enemyVel = new Vector2(agent.coreModule.nearestEnemyAgent.bodyRigidbody.velocity.x, agent.coreModule.nearestEnemyAgent.bodyRigidbody.velocity.y); float ownSize = 1f; // currentBodySize.x; float enemySize = 1f; // nearestEnemyAgent.coreModule.currentBodySize.x; if (ownSize != 0f && enemySize != 0) { float sizeRatio = enemySize / ownSize - 1f; if (enemySize < ownSize) { sizeRatio = -1f * (ownSize / enemySize - 1f); } enemyRelSize[0] = TransferFunctions.Evaluate(TransferFunctions.TransferFunction.RationalSigmoid, sizeRatio); // smaller creatures negative values, larger creatures positive, 0 = same size } enemyHealth[0] = 0f; enemyGrowthStage[0] = 0f; if (agent.coreModule != null && agent.coreModule.nearestEnemyAgent) { if (agent.coreModule.nearestEnemyAgent.coreModule != null) { enemyHealth[0] = agent.coreModule.nearestEnemyAgent.coreModule.hitPoints[0]; } enemyGrowthStage[0] = agent.coreModule.nearestEnemyAgent.sizePercentage; } //float threat = 1f; //if(agent.coreModule.nearestEnemyAgent.mouthRef.isPassive) { // threat = 0f; //} enemyThreatRating[0] = 0f; // threat; } enemyPosX[0] = enemyPos.x / 20f; enemyPosY[0] = enemyPos.y / 20f; enemyVelX[0] = (enemyVel.x - agent.ownVel.x) / 15f; enemyVelY[0] = (enemyVel.y - agent.ownVel.y) / 15f; enemyDirX[0] = enemyDir.x; enemyDirY[0] = enemyDir.y; }
public override void BrainMasterFunction(ref float[][] inputArray, ref float[][] outputArray) { // Make sure we have enough data //Dimension //output = new float[layerSize[layerCount - 1]]; // set output size to that of last layer (output) // Run the network! for (int l = 0; l < layerCount; l++) { for (int j = 0; j < layerSize[l]; j++) // for each node in the current layer l, { float sum = 0.0f; for (int i = 0; i < (l == 0 ? inputSize : layerSize[l - 1]); i++) // for each node in the previous layer l-1, { sum += weight[l][i][j] * (l == 0 ? inputArray[i][0] : layerOutput[l - 1][i]); // sum for that node is the sum of all inputs multiplied by weights from previous layer //float value = weight[l][i][j] * (l == 0 ? inputArray[i][0] : layerOutput[l - 1][i]); //Debug.Log("BrainANN_FF_Layers_A2A() BrainMasterFunction! inputArray[" + i.ToString() + "][0]= " + inputArray[i][0].ToString () + " weight= " + weight[l][i][j].ToString () + " value= " + value.ToString() + " sum= " + sum.ToString ()); } sum += bias[l][j]; // add bias value to this node layerInput[l][j] = sum; // store layerInput values for this layer layerOutput[l][j] = TransferFunctions.Evaluate(transferFunctions[l][j], sum); // pass the sum into the transferFunction for that layer //Debug.Log("BrainANN_FF_Layers_A2A() BrainMasterFunction! bias= " + bias[l][j].ToString () + " weight= " + weight[l][0][j].ToString () + " sum= " + sum.ToString () + " layerOutput[][]= " + layerOutput[l][j].ToString()); } } //Copy the output to the output array string outputString = ""; for (int m = 0; m < layerSize[layerCount - 1]; m++) { outputArray[m][0] = layerOutput[layerCount - 1][m]; // check for value-type pass problems outputString += outputArray[m][0].ToString() + ", "; } string inputString = ""; for (int n = 0; n < inputSize; n++) { inputString += inputArray[n][0].ToString() + ", "; } //Debug.Log("BrainANN_FF_Layers_A2A() BrainMasterFunction! inputArray= " + inputString + " -- outputArray= " + outputString); }
public void BrainMasterFunction() { // ticks state of brain forward 1 timestep // NAIVE APPROACH: // run through all links and save sum values in target neurons for (int i = 0; i < axonList.Count; i++) { // Find input neuron and multiply its value by the axon weight --- add that to output neuron total: neuronList[axonList[i].toID].inputTotal += axonList[i].weight * neuronList[axonList[i].fromID].currentValue[0]; } // Once all axons are calculated, process the neurons: for (int j = 0; j < neuronList.Count; j++) { //Debug.Log(neuronList[j].ToString()); neuronList[j].previousValue = neuronList[j].currentValue[0]; // Save previous state if (neuronList[j].neuronType != NeuronGenome.NeuronType.In) { neuronList[j].currentValue[0] = TransferFunctions.Evaluate(TransferFunctions.TransferFunction.RationalSigmoid, neuronList[j].inputTotal); } // now zero out inputSum: neuronList[j].inputTotal = 0f; } }
public GeneNodeNEAT(int id, GeneNodeType nodeType, TransferFunctions.TransferFunction function) { this.id = id; this.nodeType = nodeType; this.activationFunction = function; }
public void BrainMasterFunction(ref List <float[]> inputList, ref List <float[]> outputList) { string inputString = "inputList: "; string outputString = "outputList: "; for (int i = 0; i < inputList.Count; i++) { //Debug.Log("BrainMasterFunction inputList[" + i.ToString() + "] " + inputList.Count.ToString()); inputString += "[" + i.ToString() + "]: " + inputList[i][0].ToString() + ", "; } //============================================================================================ // How to run the network?? // 1) start with input nodes, calculate values one step down the tree // 2) start with output nodes, do a depth-first search to find all required calculations -- might run into trouble with recursion? // 3) start with inputs, keep going forward until all outputs are taken care of // 2) /*numNodesVisited = 0; * visitedNodes.Clear(); * completedNodes.Clear(); * // First, zero out values for all current nodes and save previous states: * for (int n = 0; n < neuronList.Count; n++) { * neuronList[n].previousValue = neuronList[n].currentValue[0]; // save current status (which is the state of the brain in the previous timeStep * neuronList[n].currentValue[0] = 0f; // clear currentValue * } * // Fill in input node values: * for(int m = 0; m < inputNeuronList.Count; m++) { * inputNeuronList[m].currentValue[0] = inputList[m][0]; // revisit! might be better to do a reference pointer only once when agent is built rather than every time step value-write * //processedNodes.Add(inputNeuronList[m]); // if it's an inputNode, it's ready to be used, so mark as processed * } * for(int endNode = 0; endNode < outputNeuronList.Count; endNode++) { * // loop through all output nodes, if all their inputs are processed and ready to go, add weights and run transfer function, else, dive deeper into unprocessed nodes * //Debug.Log("CalculateNodeInputs endNode(" + endNode.ToString() + ")"); * * CalculateNodeInputs(outputNeuronList[endNode]); * } * for (int o = 0; o < outputList.Count; o++) { * outputList[o][0] = outputNeuronList[o].currentValue[0]; * outputString += "[" + o.ToString() + "]: " + outputList[o][0].ToString() + ", "; * }*/ //============================================================================================ //@@@@@@@@@@ One-step should support recursion // go through every node and calculate its value from each of its inputs' PREVIOUS values // populate list of nodes to process // First, zero out values for all current nodes and save previous states: for (int n = 0; n < neuronList.Count; n++) { neuronList[n].previousValue = neuronList[n].currentValue[0]; // save current status (which is the state of the brain in the previous timeStep neuronList[n].currentValue[0] = 0f; // clear currentValue } // Fill in input node values: for (int m = 0; m < inputNeuronList.Count; m++) { inputNeuronList[m].currentValue[0] = inputList[m][0]; // revisit! might be better to do a reference pointer only once when agent is built rather than every time step value-write //processedNodes.Add(inputNeuronList[m]); // if it's an inputNode, it's ready to be used, so mark as processed } for (int node = 0; node < neuronList.Count; node++) { // loop through all nodes, if all their inputs are processed and ready to go, add weights and run transfer function, else, dive deeper into unprocessed nodes //Debug.Log("CalculateNodeInputs endNode(" + endNode.ToString() + ")"); for (int inputs = 0; inputs < neuronList[node].incomingConnectionsList.Count; inputs++) { neuronList[node].currentValue[0] += neuronList[neuronList[node].incomingConnectionsList[inputs].fromNodeID].previousValue * neuronList[node].incomingConnectionsList[inputs].weight[0]; } neuronList[node].currentValue[0] = TransferFunctions.Evaluate(neuronList[node].activationFunction, neuronList[node].currentValue[0]); // OLD BELOW: /*if (neuronList[node].nodeType == GeneNodeNEAT.GeneNodeType.Out) { * neuronList[node].currentValue[0] = TransferFunctions.Evaluate(TransferFunctions.TransferFunction.RationalSigmoid, neuronList[node].currentValue[0]); * } * else if (neuronList[node].nodeType == GeneNodeNEAT.GeneNodeType.Hid) { * neuronList[node].currentValue[0] = TransferFunctions.Evaluate(TransferFunctions.TransferFunction.RationalSigmoid, neuronList[node].currentValue[0]); * }*/ } //============================================================================================ for (int o = 0; o < outputList.Count; o++) { outputList[o][0] = outputNeuronList[o].currentValue[0]; outputString += "[" + o.ToString() + "]: " + outputList[o][0].ToString() + ", "; } //Debug.Log("BrainNEAT: BrainMasterFunction!" + inputString); //Debug.Log("BrainNEAT: BrainMasterFunction!" + outputString); }