Пример #1
0
    /// <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;
        }
    }
Пример #2
0
    /// <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]);
        }
    }
Пример #4
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));
    }
Пример #5
0
        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);
    }