private static void SingleInput_WeightOne_Inner( IBlackBox <double> net, IActivationFunction <double> actFn) { // Activate and test. net.InputVector[0] = 0.0; for (int i = 0; i < 10; i++) { net.Activate(); Assert.Equal(0.5, net.OutputVector[0]); } // Activate and test. net.InputVector[0] = 1.0; for (int i = 0; i < 10; i++) { net.Activate(); Assert.Equal(actFn.Fn(1), net.OutputVector[0]); } // Activate and test. net.InputVector[0] = 10.0; for (int i = 0; i < 10; i++) { net.Activate(); Assert.Equal(actFn.Fn(10), net.OutputVector[0]); } }
private static void TwoInputs_WeightHalf_Inner( IBlackBox <double> net, IActivationFunction <double> actFn) { double x; var inputs = net.Inputs.Span; var outputs = net.Outputs.Span; // Activate and test. inputs[0] = 0.0; inputs[1] = 0.0; net.Activate(); Assert.Equal(0.5, outputs[0]); // Activate and test. inputs[0] = 1.0; inputs[1] = 2.0; net.Activate(); x = 1.5; actFn.Fn(ref x); Assert.Equal(x, outputs[0]); // Activate and test. inputs[0] = 10.0; inputs[1] = 20.0; net.Activate(); x = 15.0; actFn.Fn(ref x); Assert.Equal(x, outputs[0]); }
private static void TwoInputs_WeightHalf_Inner( IBlackBox <double> net, IActivationFunction <double> actFn) { double x; // Activate and test. net.InputVector[0] = 0.0; net.InputVector[1] = 0.0; net.Activate(); Assert.Equal(0.5, net.OutputVector[0]); // Activate and test. net.InputVector[0] = 1.0; net.InputVector[1] = 2.0; net.Activate(); x = 1.5; actFn.Fn(ref x); Assert.Equal(x, net.OutputVector[0]); // Activate and test. net.InputVector[0] = 10.0; net.InputVector[1] = 20.0; net.Activate(); x = 15.0; actFn.Fn(ref x); Assert.Equal(x, net.OutputVector[0]); }
private static void ComplexCyclic_Inner( IBlackBox <double> net, IActivationFunction <double> actFn) { // Simulate network in C# and compare calculated outputs with actual network outputs. double[] preArr = new double[3]; double[] postArr = new double[3]; var inputs = net.Inputs.Span; var outputs = net.Outputs.Span; postArr[0] = 3.0; inputs[0] = 3.0; for (int i = 0; i < 10; i++) { preArr[1] = postArr[0] * -2.0 + postArr[2]; preArr[2] = postArr[0] + postArr[1]; actFn.Fn(ref preArr[1], ref postArr[1]); actFn.Fn(ref preArr[2], ref postArr[2]); net.Activate(); Assert.Equal(postArr[1], outputs[0]); } // Rest the network's internal state. net.Reset(); Assert.Equal(0.0, outputs[0]); // Run the test again. Array.Clear(preArr, 0, preArr.Length); Array.Clear(postArr, 0, postArr.Length); postArr[0] = 3.0; inputs[0] = 3.0; for (int i = 0; i < 10; i++) { preArr[1] = postArr[0] * -2.0 + postArr[2]; preArr[2] = postArr[0] + postArr[1]; actFn.Fn(ref preArr[1], ref postArr[1]); actFn.Fn(ref preArr[2], ref postArr[2]); net.Activate(); Assert.Equal(postArr[1], outputs[0]); } }
/// <summary> /// Evaluate the provided IBlackBox against the MNIST problem domain and return its fitness/novlety score. /// </summary> public FitnessInfo Evaluate(IBlackBox box) { //just keep track of evals //_evalCount++; double fitness, altFitness; //these are our inputs and outputs ISignalArray inputArr = box.InputSignalArray; ISignalArray outputArr = box.OutputSignalArray; List <Sample> sampleList = LEEAParams.DOMAIN.getSamples(); int sampleCount = sampleList.Count; fitness = sampleList.Count; foreach (Sample sample in sampleList) { inputArr.CopyFrom(sample.Inputs, 0); box.ResetState(); box.Activate(); fitness -= Math.Abs(outputArr[0] - sample.Outputs[0]) * Math.Abs(outputArr[0] - sample.Outputs[0]); } // set alternate fitness to fitness measured against all samples if (SharedParams.SharedParams.PERFORMFULLEVAL) { sampleList = LEEAParams.DOMAIN.getValidationSamples(); altFitness = sampleList.Count; foreach (Sample sample in sampleList) { inputArr.CopyFrom(sample.Inputs, 0); box.ResetState(); box.Activate(); altFitness -= Math.Abs(outputArr[0] - sample.Outputs[0]) * Math.Abs(outputArr[0] - sample.Outputs[0]); } } else { altFitness = 0; } fitness = Math.Max(fitness, LEEAParams.MINFITNESS) + LEEAParams.FITNESSBASE; return(new FitnessInfo(fitness, altFitness)); }
// Update is called once per frame void FixedUpdate() { /* * //Calculate Y Range: * float yWidth = 4.5f; * float yStart = -4.5f; * * //XRange * float xWidth = 9; * float xStart = -9; * * var tempPos = ball.transform.localPosition; * inputSignals[0] = (tempPos.x) / xWidth; * inputSignals[1] = (tempPos.y) / yWidth; * // Debug.Log(inputSignals[0]); * tempPos = transform.localPosition; * inputSignals[2] = (tempPos.x) / xWidth; * inputSignals[3] = (tempPos.y) / yWidth; * * tempPos = opponent.transform.localPosition; * inputSignals[4] = (tempPos.x) / xWidth; * inputSignals[5] = (tempPos.y) / yWidth; * * //tempPos = ball.velocity.normalized; * //inputSignals[6] = tempPos.x; * //inputSignals[7] = tempPos.y; * brain.InputSignalArray.CopyFrom(inputSignals, 0);*/ OriginalInputs(); brain.Activate(); OriginalInputs(); brain.Activate(); float xDirection = Mathf.Clamp((float)(brain.OutputSignalArray[0] - 0.5) * 2, -1, 1); float yDirection = Mathf.Clamp((float)(brain.OutputSignalArray[1] - 0.5) * 2, -1, 1); if (Mathf.Abs(xDirection) < 0.2f) { xDirection = 0; } if (Mathf.Abs(yDirection) < 0.2f) { yDirection = 0; } Vector2 targetTranslation = (Vector2)(parent.transform.localToWorldMatrix * new Vector3(xDirection, yDirection)); rb.velocity = ((targetTranslation * MaxMovementSpeed)); }
private double[] activate(IBlackBox box, IList <double> inputs, double[] outputs) { box.ResetState(); // Give inputs to the network var nodeId = 0; foreach (var input in inputs) { box.InputSignalArray[nodeId++] = input; } // Activate the network and get outputs back box.Activate(); box.OutputSignalArray.CopyTo(outputs, 0); // Normalize outputs when using NEAT if (phenotype == Phenotype.Neat) { NormalizeOutputs(outputs); } else { Debug.Assert(outputs.All(x => x >= 0.0 && x <= 1.0)); } return(outputs); }
public FitnessInfo Test(IBlackBox box) { double fitness, altFitness; //these are our inputs and outputs ISignalArray inputArr = box.InputSignalArray; ISignalArray outputArr = box.OutputSignalArray; List <Sample> sampleList = LEEAParams.DOMAIN.getTestSamples(); int sampleCount = sampleList.Count; fitness = sampleList.Count; foreach (Sample sample in sampleList) { inputArr.CopyFrom(sample.Inputs, 0); box.ResetState(); box.Activate(); fitness -= Math.Abs(outputArr[0] - sample.Outputs[0]) * Math.Abs(outputArr[0] - sample.Outputs[0]); } fitness = Math.Max(fitness, LEEAParams.MINFITNESS) + LEEAParams.FITNESSBASE; return(new FitnessInfo(fitness, 0)); }
/// <summary> /// Perform one simulation timestep; provide inputs to the neural net, activate it, read its outputs and assign them to the /// relevant motors (leg joints). /// </summary> public override void Step() { //---- Feed input signals into black box. // Torso state. _box.InputSignalArray[0] = _iface.TorsoPosition.Y; // Torso Y pos. _box.InputSignalArray[1] = _iface.TorsoAngle; _box.InputSignalArray[2] = _iface.TorsoVelocity.X; _box.InputSignalArray[3] = _iface.TorsoVelocity.Y; // Left leg state. _box.InputSignalArray[4] = _iface.LeftLegIFace.HipJointAngle; _box.InputSignalArray[5] = _iface.LeftLegIFace.KneeJointAngle; // Right leg state. _box.InputSignalArray[6] = _iface.RightLegIFace.HipJointAngle; _box.InputSignalArray[7] = _iface.RightLegIFace.KneeJointAngle; // Sine wave inputs (one is a 180 degree phase shift of the other). double sinWave0 = (Math.Sin(_timestep * _sineWaveIncr) + 1.0) * 0.5; double sinWave180 = (Math.Sin((_timestep + 30) * _sineWaveIncr) + 1.0) * 0.5; _box.InputSignalArray[8] = sinWave0; _box.InputSignalArray[9] = sinWave180; _timestep++; //---- Activate black box. _box.Activate(); //---- Read joint torque outputs (proportion of max torque). // Here we assume neuron activation function with output range [0,1]. _iface.LeftLegIFace.SetHipJointTorque((float)((_box.OutputSignalArray[0] - 0.5) * 2.0) * _iface.JointMaxTorque); _iface.RightLegIFace.SetHipJointTorque((float)((_box.OutputSignalArray[1] - 0.5) * 2.0) * _iface.JointMaxTorque); _iface.LeftLegIFace.SetKneeJointTorque((float)((_box.OutputSignalArray[2] - 0.5) * 2.0) * _iface.JointMaxTorque); _iface.RightLegIFace.SetKneeJointTorque((float)((_box.OutputSignalArray[3] - 0.5) * 2.0) * _iface.JointMaxTorque); }
/// <summary> /// Refresh/update the view with the provided genome. /// </summary> public override void RefreshView(object genome) { NeatGenome neatGenome = genome as NeatGenome; if (null == neatGenome) { return; } // Decode genome. IBlackBox box = _genomeDecoder.Decode(neatGenome); // Probe the black box. _blackBoxProbe.Probe(box, _yArrTarget); // Update plot points. double[] xArr = _paramSamplingInfo._xArr; for (int i = 0; i < xArr.Length; i++) { if (!_generativeMode) { box.ResetState(); box.InputSignalArray[0] = xArr[i]; } box.Activate(); _plotPointListResponse[i].Y = _yArrTarget[i]; } // Trigger graph to redraw. zed.AxisChange(); Refresh(); }
/// <summary> /// Probe the given black box, and record the responses in <paramref name="responseArr"/>. /// </summary> /// <param name="box">The black box to probe.</param> /// <param name="responseArr">Response array.</param> public void Probe(IBlackBox <double> box, double[] responseArr) { Debug.Assert(responseArr.Length == _sampleCount); // Reset black box internal state. box.Reset(); // Get the blackbox input and output spans. var inputs = box.Inputs.Span; var outputs = box.Outputs.Span; // Take the required number of samples. for (int i = 0; i < _sampleCount; i++) { // Set bias input. inputs[0] = 1.0; // Activate the black box. box.Activate(); // Get the black box's output value. // TODO: Review this scheme. This replicates the behaviour in SharpNEAT 2.x but not sure if it's ideal, // for one it depends on the output range of the neural net activation function in use. double output = outputs[0]; Clip(ref output); responseArr[i] = ((output - 0.5) * _scale) + _offset; } }
private double[] activate(IBlackBox box, IEnumerable <double> inputs, double[] outputs) { box.ResetState(); // Give inputs to the network var nodeId = 0; foreach (var input in inputs) { box.InputSignalArray[nodeId++] = input; } // Activate the network and get outputs back box.Activate(); box.OutputSignalArray.CopyTo(outputs, 0); // Normalize outputs when using NEAT if (phenotype == Phenotype.Neat) { for (var i = 0; i < outputs.Count(); i++) { outputs[i] = (outputs[i] + 1.0) / 2.0; } } return(outputs); }
void FixedUpdate() { if (isRunning) { // Set up inputs as array and feed it to the network ISignalArray inputArr = neat.InputSignalArray; double x = NormalizeValues(max, min, transform.position.x); double z = NormalizeValues(max, min, transform.position.z); inputArr[0] = x; inputArr[1] = z; neat.Activate(); // Get outputs //TODO: Make outputs be able to have negative values as well ISignalArray outputArr = neat.OutputSignalArray; outputArr[0] = (outputArr[0] < 0.5f) ? outputArr[0] * -1 : outputArr[0]; outputArr[1] = (outputArr[1] < 0.5f) ? outputArr[0] * -1 : outputArr[1]; float outputX = (float)outputArr[0] * 10.0f; float outputZ = (float)outputArr[1] * 10.0f; rb.AddForce(new Vector3(outputX, 0.0f, outputZ)); //DebugNetwork(inputArr, outputArr); } }
private void FixedUpdate() { if (IsRunning) { target = GameObject.FindGameObjectWithTag("Target"); targetx = target.transform.position.x; targety = target.transform.position.y; // initialize input and output signal arrays ISignalArray inputArr = box.InputSignalArray; ISignalArray outputArr = box.OutputSignalArray; inputArr[0] = target.transform.position.x; inputArr[1] = target.transform.position.y; inputArr[3] = fitness; if (b == false) { box.Activate(); force.x = (float)outputArr[0] * 2000; force.y = (float)outputArr[1] * 2000; //Rotate(angle); Shoot(force); b = true; } distance = GetDistance(); if (distance > 0) {//cannot divide by zero and cannot be closer to something than 0 AddFitness(Mathf.Abs(1 / distance)); } } }
private void FixedUpdate() { if (isRunning) { // Pass sensor inputs to neural network ISignalArray inputArr = box.InputSignalArray; int i = 0; foreach (SectorSensor sectorSensor in sectorSensors) { for (int j = 0; j < sectorSensor.NumSenses; ++j) { inputArr[i] = sectorSensor.GetSectorSense(j); ++i; } } foreach (DistanceSensor distanceSensor in distanceSensors) { for (int j = 0; j < distanceSensor.numSensors; ++j) { inputArr[i] = distanceSensor.GetSense(j); ++i; } } if (attributes.needsFood) { // Response high at low energy inputArr[i] = 1 - attributes.Energy / attributes.maxEnergy; ++i; } if (attributes.needsWater) { // Response high at low hydration inputArr[i] = 1 - attributes.Hydration / attributes.maxHydration; ++i; } if (movementController.senseSpeed) { inputArr[i] = rb.velocity.magnitude / movementController.moveSpeed; ++i; } if (movementController.senseSwimming) { inputArr[i] = movementController.IsSwimming ? 1 : 0; ++i; } // Activate neural network box.Activate(); // Read outputs from neural network into movement input. ISignalArray outputArr = box.OutputSignalArray; xInput = (float)outputArr[0] * 2 - 1; yInput = (float)outputArr[1] * 2 - 1; } }
private static void HiddenNode_Inner( IBlackBox <double> net, IActivationFunction <double> actFn) { // Activate and test. net.InputVector[0] = 0.0; net.InputVector[1] = 0.0; net.Activate(); Assert.AreEqual(actFn.Fn(1.0), net.OutputVector[0]); // Activate and test. net.InputVector[0] = 0.5; net.InputVector[1] = 0.25; net.Activate(); Assert.AreEqual(actFn.Fn(actFn.Fn(0.375) * 2.0), net.OutputVector[0]); }
/// <summary> /// Refresh/update the view with the provided genome. /// </summary> public override void RefreshView(object genome) { NeatGenome neatGenome = genome as NeatGenome; if (null == neatGenome) { return; } // Decode genome. IBlackBox box = _genomeDecoder.Decode(neatGenome); // Update plot points. double x = _xMin; for (int i = 0; i < _sampleCount; i++, x += _xIncr) { box.ResetState(); box.InputSignalArray[0] = x; box.Activate(); _plotPointListResponse[i].Y = box.OutputSignalArray[0]; } // Trigger graph to redraw. zed.AxisChange(); Refresh(); }
public double[] GetChampOutput(int nodeDepth, int nodeSiblingNum, int maxDepth, int maxBranching) { IGenomeDecoder <NeatGenome, IBlackBox> decoder = experiment.CreateGenomeDecoder(); IBlackBox box = decoder.Decode(contentEA.CurrentChampGenome); // Normalize nodeDepth and nodeSiblingNum to range of 0-1. This may affect outputs? double normDepth = (double)nodeDepth / (double)maxDepth; double normSib; if (nodeDepth == 0) { normSib = 0; // Only one node at depth 0, prevent a divide by 0 error } else { normSib = (double)nodeSiblingNum / (double)(Mathf.Pow(maxBranching, nodeDepth) - 1); } box.InputSignalArray[0] = normDepth; box.InputSignalArray[1] = normSib; box.ResetState(); box.Activate(); //Debug.Log("(" + normDepth + "," + normSib + ") -> (" + box.OutputSignalArray[0] + "," + box.OutputSignalArray[1] + "," + box.OutputSignalArray[2] + "," //+ box.OutputSignalArray[3] + "," + box.OutputSignalArray[4] + "," + box.OutputSignalArray[5] + ")"); double[] outputs = new double[box.OutputCount]; for (int i = 0; i < box.OutputCount; i++) { outputs[i] = box.OutputSignalArray[i]; } return(outputs); }
private void FixedUpdate() { if (IsRunning) { // initialize input and output signal arrays ISignalArray inputArr = box.InputSignalArray; ISignalArray outputArr = box.OutputSignalArray; inputArr[0] = red; inputArr[1] = green; inputArr[2] = blue; inputArr[3] = fitness; distance = Mathf.Sqrt((red - t_red) * (red - t_red) + (green - t_green) * (green - t_green) + (blue - t_blue) * (blue - t_blue)); box.Activate(); red = (float)outputArr[0]; green = (float)outputArr[1]; blue = (float)outputArr[2]; if (distance > 0) {//cannot divide by zero and cannot be closer to something than 0 AddFitness(Mathf.Abs(1 / distance)); } ChangeColor(red, green, blue); } }
public override IPDGame.Choices Choice(IPDGame game) { if (game.T == 0) { return(FIRST_CHOICE); } int i = 0; for (int k = 1; k <= _phenome.InputSignalArray.Length / 2; k++) { IPDGame.Past p = game.GetPast(this, game.T - k); //My choice (0 == C, 1 == D) _phenome.InputSignalArray[i++] = (p == IPDGame.Past.R || p == IPDGame.Past.S) ? 0 : 1; //Opponent choice _phenome.InputSignalArray[i++] = (p == IPDGame.Past.T || p == IPDGame.Past.R) ? 0 : 1; } _phenome.Activate(); if (!_phenome.IsStateValid) { // Any black box that gets itself into an invalid state is unlikely to be // any good, so lets just bail out here. return(IPDGame.Choices.R); } return((_phenome.OutputSignalArray[0] > _phenome.OutputSignalArray[1]) ? IPDGame.Choices.C : IPDGame.Choices.D); }
public override void Step() { //---- Feed input signals into black box. // Torso state. _box.InputSignalArray[0] = _iface.TorsoPosition.Y; // Torso Y pos. _box.InputSignalArray[1] = _iface.TorsoAngle; _box.InputSignalArray[2] = _iface.TorsoAnglularVelocity; _box.InputSignalArray[3] = _iface.TorsoVelocity.X; _box.InputSignalArray[4] = _iface.TorsoVelocity.Y; // Left leg state. _box.InputSignalArray[5] = _iface.LeftLegIFace.HipJointAngle; _box.InputSignalArray[6] = _iface.LeftLegIFace.HipJointVelocity; _box.InputSignalArray[7] = _iface.LeftLegIFace.KneeJointAngle; _box.InputSignalArray[8] = _iface.LeftLegIFace.KneeJointVelocity; // Right leg state. _box.InputSignalArray[9] = _iface.RightLegIFace.HipJointAngle; _box.InputSignalArray[10] = _iface.RightLegIFace.HipJointVelocity; _box.InputSignalArray[11] = _iface.RightLegIFace.KneeJointAngle; _box.InputSignalArray[12] = _iface.RightLegIFace.KneeJointVelocity; //---- Activate black box. _box.Activate(); //---- Read joint torque outputs (proportion of max torque). // Here we assume neuron activation function with output range [0,1]. _iface.LeftLegIFace.SetHipJointTorque((float)((_box.OutputSignalArray[0] - 0.5) * 2.0) * _iface.JointMaxTorque); _iface.RightLegIFace.SetHipJointTorque((float)((_box.OutputSignalArray[1] - 0.5) * 2.0) * _iface.JointMaxTorque); _iface.LeftLegIFace.SetKneeJointTorque((float)((_box.OutputSignalArray[2] - 0.5) * 2.0) * _iface.JointMaxTorque); _iface.RightLegIFace.SetKneeJointTorque((float)((_box.OutputSignalArray[3] - 0.5) * 2.0) * _iface.JointMaxTorque); }
/// <summary> /// Probe the given black box, and record the responses in <paramref name="responseArr"/> /// </summary> /// <param name="box">The black box to probe.</param> /// <param name="responseArr">Response array.</param> public void Probe(IBlackBox <double> box, double[] responseArr) { Debug.Assert(responseArr.Length == _paramSamplingInfo.SampleResolution); double[] xArr = _paramSamplingInfo.XArrNetwork; for (int i = 0; i < xArr.Length; i++) { // Reset black box internal state. box.ResetState(); // Set bias input, and function input value. box.InputVector[0] = 1.0; box.InputVector[1] = xArr[i]; // Activate the black box. box.Activate(); // Get the black box's output value. // TODO: Review this scheme. This replicates the behaviour in SharpNEAT 2.x but not sure if it's ideal, // for one it depends on the output range of the neural net activation function in use. double output = box.OutputVector[0]; Clip(ref output); responseArr[i] = ((output - 0.5) * _scale) + _offset; } }
/// <summary> /// Run a single cart-pole simulation/trial on the given black box, and with the given initial model state. /// </summary> /// <param name="box">The black box (neural net) to evaluate.</param> /// <param name="cartPos">Cart position on the track.</param> /// <param name="poleAngle1">Pole 1 angle in radians.</param> /// <param name="poleAngle2">Pole 2 angle in radians.</param> /// <returns>Fitness score.</returns> public float RunTrial( IBlackBox <double> box, float cartPos, float poleAngle1, float poleAngle2) { // Reset black box state. box.ResetState(); // Reset model state. _physics.ResetState(cartPos, poleAngle1, poleAngle2); // Get a local variable ref to the internal model state array. float[] state = _physics.State; // Run the cart-pole simulation. int timestep = 0; for (; timestep < _maxTimesteps; timestep++) { // Provide model state to the black box inputs (normalised to +-1.0). box.InputVector[0] = 1.0; // Bias input. box.InputVector[1] = state[0] * __TrackLengthHalf_Reciprocal; // Cart X position range is +-__TrackLengthHalf; here we normalize to [-1,1]. box.InputVector[2] = state[1]; // Cart velocity. Typical range is approx. +-10. box.InputVector[3] = state[2] * __MaxPoleAngle_Reciprocal; // Pole 1 angle. Range is +-__MaxPoleAngle radians; here we normalize to [-1,1]. box.InputVector[4] = state[3] * 0.2; // Pole 1 angular velocity. Typical range is approx. +-5. box.InputVector[5] = state[4] * __MaxPoleAngle_Reciprocal; // Pole 2 angle. box.InputVector[6] = state[5] * 0.2; // Pole 2 angular velocity. // Activate the network. box.Activate(); // Read the output to determine the force to be applied to the cart by the controller. float force = (float)(box.OutputVector[0] - 0.5) * 2f; ClipForce(ref force); force *= __MaxForce; // Update model state, i.e. move the model forward by one timestep. _physics.Update(force); // Check for failure state. I.e. has the cart run off the ends of the track, or has either of the pole // angles exceeded the defined threshold. if (MathF.Abs(state[0]) > __TrackLengthHalf || MathF.Abs(state[2]) > __MaxPoleAngle || MathF.Abs(state[4]) > __MaxPoleAngle) { break; } } // Fitness is given by the combination of two fitness components: // 1) Amount of simulation time that elapsed before the pole angle and/or cart position threshold was exceeded. Max score is 99 if the // end of the trial is reached without exceeding any thresholds. // 2) Cart position component. Max fitness of 1.0 for a cart position of zero (i.e. the cart is in the middle of the track range); // // Therefore the maximum possible fitness is 100.0. float fitness = (timestep * _maxTimesteps_Reciprocal * 99f) + (1f - (MathF.Min(MathF.Abs(state[0]), __TrackLengthHalf) * __TrackLengthHalf_Reciprocal)); return(fitness); }
public void Step() { phenome.ResetState(); foreach (int typeID in NeatConsts.typeIds) { for (int y = 0; y < NeatConsts.ViewY; y++) { for (int x = 0; x < NeatConsts.ViewX; x++) { var xpos = game.player.position.x + x; var ypos = game.player.position.y + (NeatConsts.ViewY / 2) - y; var index = typeID * (y * NeatConsts.ViewX + x); if (ypos < 0 || xpos < 0 || ypos >= game.map.map.GetLength(0) || xpos >= game.map.map.GetLength(1)) { phenome.InputSignalArray[index] = 0; } else { phenome.InputSignalArray[index] = (game.map.map[ypos, xpos]) == typeID ? 1 : 0; } } } } phenome.Activate(); game.Step(phenome.OutputSignalArray[0] > 0.5); }
float ProcessInputPair(Renderer quadrant) { float output = 0f; //Input signals are used in the neural controller ISignalArray inputArr = box.InputSignalArray; inputArr[0] = input_1; inputArr[1] = input_2; //The neural network is activated box.Activate(); //And produces output signals (also in an array) ISignalArray outputArr = box.OutputSignalArray; //Output is between 0 and 1 output = (float)outputArr[0]; /* ISignalArray inputArr = box.InputSignalArray; * inputArr[0] = 0.88f; * inputArr[1] = 0.99f; * //inputArr[0] = input_1; * //inputArr[1] = input_2; * //The neural network is activated * box.Activate(); * //And produces output signals (also in an array) * ISignalArray outputArr = box.OutputSignalArray; * //Output is between 0 and 1 * output = (float)outputArr[0]; * Debug.Log(" "); * Debug.Log("Input array: " + inputArr[0] + " " + inputArr[1]); * Debug.Log("Output: " + output); * UnityEditor.EditorApplication.isPlaying = false;*/ return(output); }
private void RedrawGraph(NeatGenome genome) { IBlackBox box = _experiment.GetBlackBox(genome); Color trueColor = panPlot.TrueColor; Color falseColor = panPlot.FalseColor; var samples = Enumerable.Range(0, 1000). Select(o => { Vector3D pos = Math3D.GetRandomVector(new Vector3D(0, 0, 0), new Vector3D(1, 1, 1)); box.ResetState(); //box.InputSignalArray.CopyFrom() box.InputSignalArray[0] = pos.X; box.InputSignalArray[1] = pos.Y; box.InputSignalArray[2] = pos.Z; box.Activate(); double percent = box.OutputSignalArray[0]; Color color = UtilityWPF.AlphaBlend(trueColor, falseColor, percent); return(Tuple.Create(pos.ToPoint(), color)); }); panPlot.ClearFrame(); panPlot.AddDots(samples, .01, false); }
/// <summary> /// Invoke any required control logic in the Box2D world. /// </summary> protected override void InvokeController() { // Provide state info to the black box inputs. InvertedDoublePendulumWorld simWorld = (InvertedDoublePendulumWorld)_simWorld; // _box is updated by other threads so copy the reference so that we know we are workign with the same IBlackBox within this method. IBlackBox box = _box; box.InputSignalArray[0] = simWorld.CartPosX / __TrackLengthHalf; // CartPosX range is +-trackLengthHalf. Here we normalize it to [-1,1]. box.InputSignalArray[1] = simWorld.CartVelocityX; // Cart track velocity x is typically +-0.75. box.InputSignalArray[2] = simWorld.CartJointAngle / __TwelveDegrees; // Rescale angle to match range of values during balancing. box.InputSignalArray[3] = simWorld.CartJointAngularVelocity; // Pole angular velocity is typically +-1.0 radians. No scaling required. box.InputSignalArray[4] = simWorld.ElbowJointAngle / __TwelveDegrees; box.InputSignalArray[5] = simWorld.ElbowJointAngularVelocity; // Activate the network. box.Activate(); // Read the network's force signal output. // FIXME: Force mag should be configurable somewhere. float force = (float)(box.OutputSignalArray[0] - 0.5f) * __MaxForceNewtonsX2; simWorld.SetCartForce(force); }
void ObservationsToCommands(JsonObservations observations) { xPos = observations.XPos; zPos = observations.ZPos; try { UpdateTilesInfo(observations); } catch (IndexOutOfRangeException e) { System.Diagnostics.Debug.WriteLine(e.Message); return; } /* * System.Diagnostics.Debug.WriteLine("Far ahead: " + neighbourTiles.Level0.farAhead + * ". Ahead: " + neighbourTiles.Level0.ahead + * ". Far left: " + neighbourTiles.Level0.farLeft + * ". Left: " + neighbourTiles.Level0.left + * ". Right: " + neighbourTiles.Level0.right + * ". Far right: " + neighbourTiles.Level0.farRight + * ". Back: " + neighbourTiles.Level0.back + * ". Far back: " + neighbourTiles.Level0.farBack);*/ if (IsGoalMet()) { return; } ObservationsToBrainInputs(); brain.Activate(); OutputsToCommands(); }
/// <summary> /// Determine the agent's position in the world relative to the prey and walls, and set its sensor inputs accordingly. /// </summary> /// <param name="agent"></param> public void SetAgentInputsAndActivate(IBlackBox agent) { // Calc prey's position relative to the agent (in polar coordinate system). PolarPoint relPos = CartesianToPolar(_preyPos - _agentPos); // Determine agent sensor input values. // Reset all inputs. agent.InputSignalArray.Reset(); // Test if prey is in sensor range. if (relPos.RadialSquared <= _sensorRangeSquared) { // Determine which sensor segment the prey is within - [0,7]. There are eight segments and they are tilted 22.5 degrees (half a segment) // such that due North, East South and West are each in the centre of a sensor segment (rather than on a segment boundary). double thetaAdjusted = relPos.Theta - PiDiv8; if (thetaAdjusted < 0.0) { thetaAdjusted += 2.0 * Math.PI; } int segmentIdx = (int)Math.Floor(thetaAdjusted / PiDiv4); // Set sensor segment's input. agent.InputSignalArray[segmentIdx] = 1.0; } // Prey closeness detector. agent.InputSignalArray[8] = relPos.RadialSquared <= 4.0 ? 1.0 : 0.0; // Wall detectors - N,E,S,W. // North. int d = (_gridSize - 1) - _agentPos._y; if (d <= 4) { agent.InputSignalArray[9] = (4 - d) / 4.0; } // East. d = (_gridSize - 1) - _agentPos._x; if (d <= 4) { agent.InputSignalArray[10] = (4 - d) / 4.0; } // South. if (_agentPos._y <= 4) { agent.InputSignalArray[11] = (4 - _agentPos._y) / 4.0; } // West. if (_agentPos._x <= 4) { agent.InputSignalArray[12] = (4 - _agentPos._x) / 4.0; } // Activate agent. agent.Activate(); }
void FixedUpdate() { if (IsRunning) { // input array assained to constant because without it output is constantly 0.5f ISignalArray inputArr = box.InputSignalArray; for (var i = 0; i < 21; i++) { inputArr[i] = 0.5f; } box.Activate(); ISignalArray outputArr = box.OutputSignalArray; JointCount = (int)Mathf.Round((float)outputArr[0] * 5 + 1); /* * string tests = ""; * for(var i = 0; i < 21; i++) * { * tests += i + ": " + (float)outputArr[i] + " "; * } * Debug.Log(tests); */ for (int i = 0; i < JointCount; i++) // spawning joints { // get joint position float JointPositionX = Mathf.Cos(i * 2f * Mathf.PI / JointCount); float JointPositionY = Mathf.Sin(i * 2f * Mathf.PI / JointCount); Vector3 JointPosition = new Vector3(JointPositionX, JointPositionY, 0f); // get joint rotation float JointRotationZ = 90f + i * (360 / JointCount); Quaternion JointRotation = Quaternion.Euler(new Vector3(transform.rotation.x, transform.rotation.y, JointRotationZ)); //create joint GameObject obj = Instantiate(JointPrefab, JointPosition, JointRotation, transform); //change joint scale obj.transform.localScale = new Vector3(transform.localScale.x, transform.localScale.y + (float)outputArr[i + 1], transform.localScale.z); //fix position based on scale float newObjPositionX = obj.transform.position.x + Mathf.Cos(i * 2f * Mathf.PI / JointCount) * obj.transform.localScale.y / 3; float newObjPositionY = obj.transform.position.y + Mathf.Sin(i * 2f * Mathf.PI / JointCount) * obj.transform.localScale.y / 3; obj.transform.position = new Vector3(newObjPositionX, newObjPositionY, obj.transform.position.z); //send wheel radius to joint obj.GetComponent <JointScript>().SetWheelRadius((float)outputArr[i + 11]); SetupHingeJointComponent(obj); } Stop(); } }
/// <summary> /// Evaluate the provided IBlackBox. /// </summary> public override FitnessInfo Evaluate(IBlackBox box) { _evalCount++; // [0] - Cart Position (meters). // [1] - Cart velocity (m/s). // [2] - Pole 1 angle (radians) // [3] - Pole 1 angular velocity (radians/sec). // [4] - Pole 2 angle (radians) // [5] - Pole 2 angular velocity (radians/sec). double[] state = new double[6]; state[2] = FourDegrees; // Run the pole-balancing simulation. int timestep = 0; for(; timestep < _maxTimesteps; timestep++) { // Provide state info to the network (normalised to +-1.0). // Markovian (With velocity info) box.InputSignalArray[0] = state[0] / _trackLengthHalf; // Cart Position is +-trackLengthHalfed box.InputSignalArray[1] = state[2] / ThirtySixDegrees; // Pole Angle is +-thirtysix_degrees. Values outside of this range stop the simulation. box.InputSignalArray[2] = state[4] / ThirtySixDegrees; // Pole Angle is +-thirtysix_degrees. Values outside of this range stop the simulation. // Activate the black box. box.Activate(); // Get black box response and calc next timestep state. performAction(state, box.OutputSignalArray[0]); // Check for failure state. Has the cart run off the ends of the track or has the pole // angle gone beyond the threshold. if( (state[0]< -_trackLengthHalf) || (state[0]> _trackLengthHalf) || (state[2] > _poleAngleThreshold) || (state[2] < -_poleAngleThreshold) || (state[4] > _poleAngleThreshold) || (state[4] < -_poleAngleThreshold)) { break; } } if(timestep == _maxTimesteps) { _stopConditionSatisfied = true; } // The controller's fitness is defined as the number of timesteps that elapse before failure. double fitness = timestep; return new FitnessInfo(fitness, fitness); }
public override void RefreshView(object genome) { currentBox = decoder.Decode(genome as NeatGenome); plotChart.Series.Clear(); for (var cluster = 0; cluster < nbClusters; cluster++) { var serie = plotChart.Series.Add("Cluster #" + cluster); serie.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Point; } var outputs = new double[nbClusters]; double xmin = double.PositiveInfinity; double xmax = 0; double ymin = double.PositiveInfinity; double ymax = 0; for (var i = 0; i < dataset.InputSamples.Count(); i++) { for (var j = 0; j < dataset.InputCount; j++) { currentBox.InputSignalArray[j] = dataset.InputSamples[i][j]; } currentBox.Activate(); currentBox.OutputSignalArray.CopyTo(outputs, 0); var x = dataset.InputSamples[i][0]; var y = dataset.InputSamples[i][1]; var cluster = outputs.MaxIndex(); if (x < xmin) xmin = x; if (x > xmax) xmax = x; if (y < ymin) ymin = y; if (y > ymax) ymax = y; plotChart.Series[cluster].Points.AddXY(x, y); } plotChart.ChartAreas[0].AxisX.Minimum = xmin; plotChart.ChartAreas[0].AxisX.Maximum = xmax; plotChart.ChartAreas[0].AxisY.Minimum = ymin; plotChart.ChartAreas[0].AxisY.Maximum = xmax; }
private void PaintView(IBlackBox box) { if(_initializing) { return; } Graphics g = Graphics.FromImage(_image); g.FillRectangle(_brushBackground, 0, 0, _image.Width, _image.Height); g.SmoothingMode = SmoothingMode.AntiAlias; // Get control width and height. int width = Width; int height = Height; // Determine smallest dimension. Use that as the edge length of the square grid. width = height = Math.Min(width, height); // Pixel size is calculated using integer division to produce cleaner lines when drawing. // The inherent rounding down may produce a grid 1 pixel smaller then the determined edge length. // Also make room for a combo box above the grid. This will be used allow the user to change the grid resolution. int visualFieldPixelSize = (height-GridTop) / _visualFieldResolution; width = height = visualFieldPixelSize * _visualFieldResolution; // Paint pixel outline grid. // Vertical lines. int x = GridLeft; for(int i=0; i<=_visualFieldResolution; i++, x+=visualFieldPixelSize) { g.DrawLine(__penGrey, x, GridTop, x, GridTop+height); } // Horizontal lines. int y = GridTop; for(int i=0; i<=_visualFieldResolution; i++, y+=visualFieldPixelSize) { g.DrawLine(__penGrey, GridLeft, y, GridLeft+width, y); } // Apply test case to black box's visual field sensor inputs. BoxesVisualDiscriminationEvaluator.ApplyVisualFieldToBlackBox(_testCaseField, box, _visualFieldResolution, _visualOriginPixelXY, _visualPixelSize); // Activate the black box. box.ResetState(); box.Activate(); // Read output responses and paint them to the pixel grid. // Also, we determine the range of values so that we can normalize the range of pixel shades used. double low, high; low = high = box.OutputSignalArray[0]; for(int i=1; i<box.OutputSignalArray.Length; i++) { double val = box.OutputSignalArray[i]; if(val > high) { high = val; } else if(val <low) { low = val; } } double colorScaleFactor; if(0.0 == (high-low)) { colorScaleFactor = 1.0; } else { colorScaleFactor = 1.0 / (high-low); } IntPoint maxActivationPoint = new IntPoint(0,0); double maxActivation = -1.0; int outputIdx = 0; y = GridTop; for(int i=0; i<_visualFieldResolution; i++, y+=visualFieldPixelSize) { x = GridLeft; for(int j=0; j<_visualFieldResolution; j++, x+=visualFieldPixelSize, outputIdx++) { double output = box.OutputSignalArray[outputIdx]; if(output > maxActivation) { maxActivation = output; maxActivationPoint._x = j; maxActivationPoint._y = i; } Color color = GetResponseColor((output-low)*colorScaleFactor); Brush brush = new SolidBrush(color); g.FillRectangle(brush, x+1, y+1, visualFieldPixelSize-2, visualFieldPixelSize-2); } } // Paint lines around the small and large test case boxes to highlight them. // Small box. int testFieldPixelSize = (_visualFieldResolution / TestCaseField.TestFieldResolution) * visualFieldPixelSize; g.DrawRectangle(__penBoxOutline, GridLeft + (_testCaseField.SmallBoxTopLeft._x * testFieldPixelSize), GridTop + (_testCaseField.SmallBoxTopLeft._y * testFieldPixelSize), testFieldPixelSize, testFieldPixelSize); // Large box. g.DrawRectangle(__penBoxOutline, GridLeft + (_testCaseField.LargeBoxTopLeft._x * testFieldPixelSize), GridTop + (_testCaseField.LargeBoxTopLeft._y * testFieldPixelSize), testFieldPixelSize*3, testFieldPixelSize*3); // Draw red line around pixel with highest activation. g.DrawRectangle(__penSelectedPixel, GridLeft + (maxActivationPoint._x * visualFieldPixelSize), GridTop + (maxActivationPoint._y * visualFieldPixelSize), visualFieldPixelSize, visualFieldPixelSize); Refresh(); }
public static Mesh Evaluate(IBlackBox phenome, VoxelVolume volume, out EvaluationInfo evaluationInfo) { var processedOutput = new float[volume.width, volume.height, volume.length]; var cleanOutput = new float[volume.width, volume.height, volume.length]; var distanceToCenter = new float[volume.width, volume.height, volume.length]; var minOutputValue = 1f; var maxOutputValue = -1f; float r = 0, g = 0, b = 0; for (int x = 0; x < volume.width; x++) { for (int y = 0; y < volume.height; y++) { for (int z = 0; z < volume.length; z++) { AssingInput(phenome, volume, x, y, z); // activate phenome phenome.Activate(); // store output values ISignalArray outputArr = phenome.OutputSignalArray; processedOutput[x, y, z] = phenome.OutputSignalArray.Length >= 4 ? (float)outputArr[3] : (float)outputArr[0]; cleanOutput[x, y, z] = processedOutput[x, y, z]; if (phenome.OutputSignalArray.Length >= 4) { r += (float)outputArr[0]; g += (float)outputArr[1]; b += (float)outputArr[2]; } // store min and max output values if (processedOutput[x, y, z] < minOutputValue) minOutputValue = processedOutput[x, y, z]; if (processedOutput[x, y, z] > maxOutputValue) maxOutputValue = processedOutput[x, y, z]; // Clamps the final shape within a sphere //distanceToCenter[x, y, z] = DistanceFunctions.DistanceToCenter(x, y, z, volume); //if (DistanceFunctions.DistanceToCenter(x, y, z, volume) > -0.5f) //{ // cleanOutput[x, y, z] = -1; // processedOutput[x, y, z] = -1; //} // border should have negative values if (x == 0 || x == volume.width - 1 || y == 0 || y == volume.height - 1 || z == 0 || z == volume.length - 1) processedOutput[x, y, z] = -1f; } } } r /= volume.width*volume.width*volume.width; g /= volume.width*volume.width*volume.width; b /= volume.width*volume.width*volume.width; artefactColor = new Color((r + 1f) / 2f, (g + 1f) / 2f, (b + 1f) / 2f); //Debug.Log(artefactColor); //Debug.Log("Output in range [" + minOutputValue + ", " + maxOutputValue + "]"); // TODO: need to find a workaround for this. It results in cubes. In multiplayer we don't want to spawn cubes as seeds. // Either save network to disk, look and see what's wrong or maybe if this happens on the client it could request another regeneration. if (Mathf.Approximately(minOutputValue, maxOutputValue)) { //Debug.LogWarning("All output values are the same! Min equals max!"); } for (int index00 = 1; index00 < processedOutput.GetLength(0) - 1; index00++) for (int index01 = 1; index01 < processedOutput.GetLength(1) - 1; index01++) for (int index02 = 1; index02 < processedOutput.GetLength(2) - 1; index02++) { // if initially, border value at 0,0,0 was maxFill, we invert all values so minFill is on the border if (Mathf.Approximately(cleanOutput[0, 0, 0], maxOutputValue)) processedOutput[index00, index01, index02] = minOutputValue + (maxOutputValue - processedOutput[index00, index01, index02]); // based on a threshold ( middle value between min and max) we change the value to either 0 or 1. This give a blocky look instead of smooth details processedOutput[index00, index01, index02] = processedOutput[index00, index01, index02] < minOutputValue + (maxOutputValue - minOutputValue) / 2f ? 0f : 1f; } // fill evaluation info struct with data evaluationInfo = new EvaluationInfo(); evaluationInfo.cleanOutput = cleanOutput.Clone() as float[,,]; evaluationInfo.processedOutput = processedOutput.Clone() as float[,,]; evaluationInfo.distanceToCenter = distanceToCenter.Clone() as float[,,]; evaluationInfo.minOutputValue = minOutputValue; evaluationInfo.maxOutputValue = maxOutputValue; // Apply marching cubes on processed output and return Mesh Profiler.BeginSample("MarchingCubes"); var mesh = MarchingCubes.CreateMesh(processedOutput); Profiler.EndSample(); return mesh; }
/// <summary> /// Evaluate the provided IBlackBox. /// </summary> public override FitnessInfo Evaluate(IBlackBox box) { _evalCount++; // [0] - Cart Position (meters). // [1] - Cart velocity (m/s). // [2] - Pole 1 angle (radians) // [3] - Pole 1 angular velocity (radians/sec). // [4] - Pole 2 angle (radians) // [5] - Pole 2 angular velocity (radians/sec). double[] state = new double[6]; state[2] = FourDegrees; JiggleBuffer jiggleBuffer1 = new JiggleBuffer(100); JiggleBuffer jiggleBuffer2 = new JiggleBuffer(100); // Run the pole-balancing simulation. int timestep = 0; for(; timestep < _maxTimesteps; timestep++) { // Provide state info to the network (normalised to +-1.0). // Markovian (With velocity info) box.InputSignalArray[0] = state[0] / _trackLengthHalf; // Cart Position is +-trackLengthHalfed box.InputSignalArray[1] = state[2] / ThirtySixDegrees; // Pole Angle is +-thirtysix_degrees. Values outside of this range stop the simulation. box.InputSignalArray[2] = state[4] / ThirtySixDegrees; // Pole Angle is +-thirtysix_degrees. Values outside of this range stop the simulation. // Activate the black box. box.Activate(); // Get black box response and calc next timestep state. performAction(state, box.OutputSignalArray[0]); // Jiggle buffer updates.. if(100 == jiggleBuffer1.Length) { // Feed an old value from buffer 1 into buffer2. jiggleBuffer2.Enqueue(jiggleBuffer1.Dequeue()); } // Place the latest jiggle value into buffer1. jiggleBuffer1.Enqueue( Math.Abs(state[0]) + Math.Abs(state[1]) + Math.Abs(state[2]) + Math.Abs(state[3])); // Check for failure state. Has the cart run off the ends of the track or has the pole // angle gone beyond the threshold. if( (state[0]< -_trackLengthHalf) || (state[0]> _trackLengthHalf) || (state[2] > _poleAngleThreshold) || (state[2] < -_poleAngleThreshold) || (state[4] > _poleAngleThreshold) || (state[4] < -_poleAngleThreshold)) { break; } // Give the simulation at least 500 timesteps(5secs) to stabilise before penalising instability. if(timestep > 499 && jiggleBuffer2.Total > 30.0) { // Too much wiggling. Stop simulation early (30 was an experimentally determined value). break; } } double fitness; if(timestep > 499 && timestep < 600) { // For the 100(1 sec) steps after the 500(5 secs) mark we punish wiggling based // on the values from the 1 sec just gone. This is on the basis that the values // in jiggleBuffer2 (from 2 to 1 sec ago) will refelct the large amount of // wiggling that occurs at the start of the simulation when the system is still stabilising. fitness = timestep + (10.0 / Math.Max(1.0, jiggleBuffer1.Total)); } else if(timestep > 599) { // After 600 steps we use jiggleBuffer2 to punsih wiggling, this contains data from between // 2 and 1 secs ago. This is on the basis that when the system becomes unstable and causes // the simulation to terminate prematurely, the immediately prior 1 secs data will reflect that // instability, which may not be indicative of the overall stability of the system up to that time. fitness = timestep + (10.0 / Math.Max(1.0, jiggleBuffer2.Total)); } else { // Return just the currentTimestep without any extra fitness component. fitness = timestep; } // Max fitness is # of timesteps + max antiwiggle factor of 10 (which is actually impossible - some wiggle is necessary to balance the poles). if(timestep == _maxTimesteps + 10.0) { _stopConditionSatisfied = true; } return new FitnessInfo(fitness, fitness); }
private double[] activate(IBlackBox box, IList<double> inputs, double[] outputs) { box.ResetState(); // Give inputs to the network var nodeId = 0; foreach (var input in inputs) { box.InputSignalArray[nodeId++] = input; } // Activate the network and get outputs back box.Activate(); box.OutputSignalArray.CopyTo(outputs, 0); // Normalize outputs when using NEAT if (phenotype == Phenotype.Neat) { NormalizeOutputs(outputs); } else { Debug.Assert(outputs.All(x => x >= 0.0 && x <= 1.0)); } return outputs; }
/// <summary> /// Create a network definition by querying the provided IBlackBox (typically a CPPN) with the /// substrate connection endpoints. /// </summary> /// <param name="blackbox">The HyperNEAT CPPN that defines the strength of connections between nodes on the substrate.</param> /// <param name="lengthCppnInput">Optionally we provide a connection length input to the CPPN.</param> public INetworkDefinition CreateNetworkDefinition(IBlackBox blackbox, bool lengthCppnInput) { // Get the sequence of substrate connections. Either a pre-built list or a dynamically // generated sequence. IEnumerable<SubstrateConnection> connectionSequence = _connectionList ?? GetConnectionSequence(); // Iterate over substrate connections. Determine each connection's weight and create a list // of network definition connections. ISignalArray inputSignalArr = blackbox.InputSignalArray; ISignalArray outputSignalArr = blackbox.OutputSignalArray; ConnectionList networkConnList = new ConnectionList(_connectionCountHint); int lengthInputIdx = inputSignalArr.Length - 1; foreach(SubstrateConnection substrateConn in connectionSequence) { int layerToLayerAdder = ((int)substrateConn._tgtNode._position[2] * 3); // Assign the connection's endpoint position coords to the CPPN/blackbox inputs. Note that position dimensionality is not fixed. for(int i=0; i<_dimensionality - 1; i++) { inputSignalArr[i] = substrateConn._srcNode._position[i]; inputSignalArr[i + _dimensionality - 1] = substrateConn._tgtNode._position[i]; inputSignalArr[i + 2 * (_dimensionality - 1)] = Math.Abs(substrateConn._srcNode._position[i] - substrateConn._tgtNode._position[i]); } // Optional connection length input. if(lengthCppnInput) { inputSignalArr[lengthInputIdx] = CalculateConnectionLength(substrateConn._srcNode._position, substrateConn._tgtNode._position); } // Reset blackbox state and activate it. blackbox.ResetState(); blackbox.Activate(); // Read connection weight from output 0. double weight = outputSignalArr[0 + layerToLayerAdder]; // Skip connections with a weight magnitude less than _weightThreshold. double weightAbs = Math.Abs(weight); if (outputSignalArr[2 + layerToLayerAdder] >= 0) { // For weights over the threshold we re-scale into the range [-_maxWeight,_maxWeight], // assuming IBlackBox outputs are in the range [-1,1]. weight = (weightAbs) * _weightRescalingCoeff * Math.Sign(weight); // Create network definition connection and add to list. networkConnList.Add(new NetworkConnection(substrateConn._srcNode._id, substrateConn._tgtNode._id, weight)); } } // Additionally we create connections from each hidden and output node to a bias node that is not defined at any // position on the substrate. The motivation here is that a each node's input bias is independent of any source // node (and associated source node position on the substrate). That we refer to a bias 'node' is a consequence of how input // biases are handled in NEAT - with a specific bias node that other nodes can be connected to. int setCount = _nodeSetList.Count; for(int i=1; i<setCount; i++) { SubstrateNodeSet nodeSet = _nodeSetList[i]; foreach(SubstrateNode node in nodeSet.NodeList) { // Assign the node's position coords to the blackbox inputs. The CPPN inputs for source node coords are set to zero when obtaining bias values. for(int j=0; j<_dimensionality - 1; j++) { inputSignalArr[j] = 0.0; inputSignalArr[j + _dimensionality - 1] = node._position[j]; } // Optional connection length input. if(lengthCppnInput) { inputSignalArr[lengthInputIdx] = CalculateConnectionLength(node._position); } // Reset blackbox state and activate it. blackbox.ResetState(); blackbox.Activate(); // Read bias connection weight from output 1. double weight = outputSignalArr[1+ (i- 1) * 3]; // Skip connections with a weight magnitude less than _weightThreshold. double weightAbs = Math.Abs(weight); if(weightAbs > _weightThreshold) { // For weights over the threshold we re-scale into the range [-_maxWeight,_maxWeight], // assuming IBlackBox outputs are in the range [-1,1]. weight = (weightAbs - _weightThreshold) * _weightRescalingCoeff * Math.Sign(weight); // Create network definition connection and add to list. Bias node is always ID 0. networkConnList.Add(new NetworkConnection(0, node._id, weight)); } } } // Check for no connections. // If no connections were generated then there is no point in further evaulating the network. // However, null is a valid response when decoding genomes to phenomes, therefore we do that here. if(networkConnList.Count == 0) { return null; } // Construct and return a network definition. NetworkDefinition networkDef = new NetworkDefinition(_inputNodeCount, _outputNodeCount, _activationFnLibrary, _netNodeList, networkConnList); // Check that the definition is valid and return it. Debug.Assert(networkDef.PerformIntegrityCheck()); return networkDef; }
/// <summary> /// Determine the agent's position in the world relative to the prey and walls, and set its sensor inputs accordingly. /// </summary> /// <param name="agent"></param> public void SetAgentInputsAndActivate(IBlackBox agent) { // Calc prey's position relative to the agent (in polar coordinate system). PolarPoint relPos = PolarPoint.FromCartesian(_preyPos - _agentPos); // Determine agent sensor input values. // Reset all inputs. agent.InputSignalArray.Reset(); // Test if prey is in sensor range. if(relPos.Radial <= _sensorRange) { // Determine which sensor segment the prey is within - [0,7]. There are eight segments and they are tilted 22.5 degrees (half a segment) // such that due North, East South and West are each in the center of a sensor segment (rather than on a segment boundary). int segmentIdx = (int)Math.Floor((relPos.Theta / PiDiv4) + PiDiv8); if(8==segmentIdx) { segmentIdx = 0; } // Set sensor segment's input. agent.InputSignalArray[segmentIdx] = 1.0; } // Prey closeness detector. agent.InputSignalArray[8] = relPos.Radial > 2.0 ? 0.0 : 1.0; // Wall detectors - N,E,S,W. // North. int d = (_gridSize-1) - _agentPos._y; if(d < 4) { agent.InputSignalArray[9] = (4-d) / 4.0; } // East. d = (_gridSize-1) - _agentPos._x; if(d < 4) { agent.InputSignalArray[10] = (4-d) / 4.0; } // South. if(_agentPos._y < 4) { agent.InputSignalArray[11] = (4 - _agentPos._y) / 4.0; } // West. if(_agentPos._x < 4) { agent.InputSignalArray[12] = (4 - _agentPos._x) / 4.0; } // Activate agent. agent.Activate(); }
private double[] activate(IBlackBox box, IEnumerable<double> inputs, double[] outputs) { box.ResetState(); // Give inputs to the network var nodeId = 0; foreach (var input in inputs) { box.InputSignalArray[nodeId++] = input; } // Activate the network and get outputs back box.Activate(); box.OutputSignalArray.CopyTo(outputs, 0); // Normalize outputs when necessary if (phenotype == Phenotype.Neat) { for (var i = 0; i < outputs.Count(); i++) { outputs[i] = (outputs[i] + 1.0) / 2.0; } } else { Debug.Assert(outputs.All(x => x >= 0.0 && x <= 1.0)); } return outputs; }