/// <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; } }
/// <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); // Get the blackbox input and output spans. var inputs = box.Inputs.Span; var outputs = box.Outputs.Span; double[] xArr = _paramSamplingInfo.XArrNetwork; for (int i = 0; i < xArr.Length; i++) { // Reset black box internal state. box.Reset(); // Set bias input, and function input value. inputs[0] = 1.0; inputs[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 = outputs[0]; Clip(ref output); responseArr[i] = ((output - 0.5) * _scale) + _offset; } }
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 black box against the logical XOR task, /// and return its fitness score. /// </summary> /// <param name="box">The black box to evaluate.</param> /// <returns>A new instance of <see cref="FitnessInfo"/>.</returns> public FitnessInfo Evaluate(IBlackBox <double> box) { double fitness = 0.0; bool success = true; // Test case 0, 0. double output = Activate(box, 0.0, 0.0); success &= output <= 0.5; fitness += 1.0 - (output * output); // Test case 1, 1. box.Reset(); output = Activate(box, 1.0, 1.0); success &= output <= 0.5; fitness += 1.0 - (output * output); // Test case 0, 1. box.Reset(); output = Activate(box, 0.0, 1.0); success &= output > 0.5; fitness += 1.0 - ((1.0 - output) * (1.0 - output)); // Test case 1, 0. box.Reset(); output = Activate(box, 1.0, 0.0); success &= output > 0.5; fitness += 1.0 - ((1.0 - output) * (1.0 - output)); // If all four responses were correct then we add 10 to the fitness. if (success) { fitness += 10.0; } return(new FitnessInfo(fitness)); }
public override double Evaluate(IBlackBox net) { if (net.InputCount != 2 || net.OutputCount != 1) { throw new IndexOutOfRangeException(); } var inputs = MutationService.Shuffle(Inputs, RandomizationProvider.Current); double error = 0; foreach (var ins in inputs) { net.Reset(); net.SetInputs(ins); net.Activate(3); double output = net.GetOutput(0); double expected = (ins[0] == ins[1]) ? 0 : 1; double diff = output - expected; error += (diff >= 0) ? diff : -diff; } return(4 - error); }
/// <summary> /// Runs one trial of the provided agent in the world. Returns true if the agent captures the prey within /// the maximum number of timesteps allowed. /// </summary> /// <param name="agent">The agent to run the trail with.</param> /// <returns>True if the agent captured the prey; otherwise false.</returns> public bool RunTrial(IBlackBox <double> agent) { // Initialise world state. InitPositions(); // Clear any prior agent (neural network) state. agent.Reset(); // The prey gets a head start. Here we simulate the world as normal for a number of timesteps, during which // the agent's sensors receive inputs as normal, but the it is prevented from moving. int t = 0; for (; t < _preyInitMoves; t++) { SetAgentInputsAndActivate(agent); MovePrey(); } // Let the chase begin! for (; t < _maxTimesteps; t++) { SetAgentInputsAndActivate(agent); MoveAgent(agent); if (IsPreyCaptured()) { return(true); } MovePrey(); if (IsPreyCaptured()) { // The prey walked directly into the agent. return(true); } } // Agent failed to capture prey in the allotted time. return(false); }
/// <summary> /// Evaluate the provided black box against the Binary 3-Multiplexer task, /// and return its fitness score. /// </summary> /// <param name="box">The black box to evaluate.</param> /// <returns>A new instance of <see cref="FitnessInfo"/>.</returns> public FitnessInfo Evaluate(IBlackBox <double> box) { double fitness = 0.0; bool success = true; Span <double> inputs = box.Inputs.Span; Span <double> outputs = box.Outputs.Span; // 8 test cases. for (int i = 0; i < 8; i++) { // Bias input. inputs[0] = 1.0; // Apply bitmask to i and shift left to generate the input signals. // Note. We could eliminate all the boolean logic by pre-building a table of test // signals and correct responses. for (int tmp = i, j = 1; j < 4; j++) { inputs[j] = tmp & 0x1; tmp >>= 1; } // Activate the black box. box.Activate(); // Read output signal. double output = outputs[0]; Clamp(ref output); Debug.Assert(output >= 0.0, "Unexpected negative output."); bool trueResponse = (output > 0.5); // Determine the correct answer with somewhat cryptic bit manipulation. // The condition is true if the correct answer is true (1.0). if (((1 << (1 + (i & 0x1))) & i) != 0) { // correct answer: true. // Assign fitness on sliding scale between 0.0 and 1.0 based on squared error. // In tests squared error drove evolution significantly more efficiently in this domain than absolute error. // Note. To base fitness on absolute error use: fitness += output; fitness += 1.0 - ((1.0 - output) * (1.0 - output)); // Reset success flag if at least one response is wrong. success &= trueResponse; } else { // correct answer: false. // Assign fitness on sliding scale between 0.0 and 1.0 based on squared error. // In tests squared error drove evolution significantly more efficiently in this domain than absolute error. // Note. To base fitness on absolute error use: fitness += 1.0-output; fitness += 1.0 - (output * output); // Reset success flag if at least one response is wrong. success &= !trueResponse; } // Reset black box ready for next test case. box.Reset(); } // If the correct answer was given in each case then add a bonus value to the fitness. if (success) { fitness += 100.0; } return(new FitnessInfo(fitness)); }
/// <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="poleAngle">Pole angle in radians.</param> /// <returns>Fitness score.</returns> public float RunTrial( IBlackBox <double> box, float cartPos, float poleAngle) { // Reset black box state. box.Reset(); // Reset model state. _physics.ResetState(cartPos, poleAngle); // Get a local variable ref to the internal model state array. float[] state = _physics.State; // Get the blackbox input and output spans. var inputs = box.Inputs.Span; var outputs = box.Outputs.Span; // Run the cart-pole simulation. int timestep = 0; for (; timestep < _maxTimesteps; timestep++) { // Provide model state to the black box inputs (normalised to +-1.0). inputs[0] = 1.0; // Bias input. inputs[1] = state[0] * __TrackLengthHalf_Reciprocal; // Cart X position range is +-__TrackLengthHalf; here we normalize to [-1,1]. inputs[2] = state[2] * __MaxPoleAngle_Reciprocal; // Pole angle range is +-__MaxPoleAngle radians; here we normalize to [-1,1]. // Activate the network. box.Activate(); // Read the output to determine the force to be applied to the cart by the controller. float force = (float)(outputs[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 the pole // angle exceeded the defined threshold. if (MathF.Abs(state[0]) > __TrackLengthHalf || MathF.Abs(state[2]) > __MaxPoleAngle) { break; } } // Fitness is given by the combination of four fitness components: // 1) Amount of simulation time that elapsed before the pole angle and/or cart position threshold was exceeded. Max score is 80 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); // 3) Pole angle component. Max fitness of 9.5 for a pole angle of 0 degrees (vertical pole). // 4) Pole angular velocity component. Maximum fitness 9.5 for a zero velocity. // // Therefore the maximum possible fitness is 100.0, when the pole is perfectly stationary, and the cart is in the middle of the track. float fitness = (timestep * _maxTimesteps_Reciprocal * 80f) + (1f - (MathF.Min(MathF.Abs(state[0]), __TrackLengthHalf) * __TrackLengthHalf_Reciprocal)) + ((1f - (MathF.Min(MathF.Abs(state[2]), __MaxPoleAngle) * __MaxPoleAngle_Reciprocal)) * 9.5f) + ((1f - MathF.Min(MathF.Abs(state[3]), 1f)) * 9.5f); return(fitness); }