model.utilities.pid.decorator.AutotunerTest.java Source code

Java tutorial

Introduction

Here is the source code for model.utilities.pid.decorator.AutotunerTest.java

Source

/*
 * Copyright (c) 2014 by Ernesto Carrella
 * Licensed under MIT license. Basically do what you want with it but cite me and don't sue me. Which is just politeness, really.
 * See the file "LICENSE" for more information
 */

package model.utilities.pid.decorator;

import ec.util.MersenneTwisterFast;
import model.MacroII;
import model.scenario.RegressionStatics;
import model.utilities.ActionOrder;
import model.utilities.pid.ControllerInput;
import model.utilities.pid.PIDController;
import model.utilities.stats.processes.DynamicProcess;
import model.utilities.stats.processes.FirstOrderIntegratingPlusDeadTime;
import model.utilities.stats.processes.FirstOrderPlusDeadTime;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.junit.Assert;
import org.junit.Test;

import java.io.FileNotFoundException;
import java.util.function.Supplier;

import static org.mockito.Mockito.mock;

public class AutotunerTest {

    @Test
    public void tuneFOPDT() throws FileNotFoundException {
        MacroII model = new MacroII(0);
        final PIDAutotuner autotuner = runLearningExperimentWithUnknownDeadTime(model.getRandom(),
                model.drawProportionalGain(), model.drawIntegrativeGain(), null,
                new FirstOrderPlusDeadTime(0, 1.5f, 0.3f, 5));
        System.out.println(
                autotuner.getDelay() + "-----" + autotuner.getGain() + " ----" + autotuner.getTimeConstant());
        System.out.println(autotuner.describeRegression());

    }

    @Test
    public void tuneFOIPDT() throws Exception {

        MacroII model = model = new MacroII(0);
        final PIDAutotuner autotuner = runLearningExperimentWithUnknownDeadTime(model.getRandom(),
                model.drawProportionalGain(), model.drawIntegrativeGain(), null,
                new FirstOrderIntegratingPlusDeadTime(-10, 1.5f, 0.3f, 5));
        System.out.println(
                autotuner.getDelay() + "-----" + autotuner.getGain() + " ----" + autotuner.getTimeConstant());
        System.out.println(autotuner.describeRegression());

    }

    //new FirstOrderPlusDeadTime(intercept,gain,timeConstant, deadTime)
    private PIDAutotuner runLearningExperimentWithUnknownDeadTime(MersenneTwisterFast random,
            float proportionalParameter, float integrativeParameter, Supplier<Double> noiseMaker,
            DynamicProcess systemDynamic) throws FileNotFoundException {
        PIDAutotuner controller = new PIDAutotuner(
                new PIDController(proportionalParameter, integrativeParameter, 0));
        controller.setAfterHowManyDaysShouldTune(1001);
        int target = 10;
        if (noiseMaker != null)
            systemDynamic.setRandomNoise(noiseMaker);

        //create the regression too

        //output starts at intercept
        float output = 0;
        //delayed input, useful for learning

        SummaryStatistics errorBeforeTuning = new SummaryStatistics();

        SummaryStatistics errorAfterTuning = new SummaryStatistics();
        SummaryStatistics finalError = new SummaryStatistics();

        for (int step = 0; step < 2000; step++) {

            //PID step
            controller.adjust(new ControllerInput(target, output), true, mock(MacroII.class), null,
                    ActionOrder.DAWN);

            //process reacts
            float input = controller.getCurrentMV();
            assert !Float.isNaN(input);
            assert !Float.isInfinite(input);
            output = (float) systemDynamic.newStep(input);

            if (step <= 1000)
                errorBeforeTuning.addValue(Math.pow(target - output, 2));
            else
                errorAfterTuning.addValue(Math.pow(target - output, 2));
            if (step > 1900)
                finalError.addValue(Math.pow(target - output, 2));

            //shock target with 10%
            if (random.nextBoolean(.10)) {
                if (random.nextBoolean())
                    target++;
                else
                    target = Math.max(target - 1, 0);
            }

        }
        System.out.println("errors: " + errorBeforeTuning.getMean() + " --- " + errorAfterTuning.getMean());
        System.out.println("final error: " + finalError.getMean());
        System.out.println("regression: " + controller.getRegression());

        RegressionStatics.tracksAcceptably(controller.getRegression(), systemDynamic,
                RegressionStatics.MAXIMUM_ABS_ERROR, 100,
                Math.max(controller.getCurrentMV(), RegressionStatics.FIXED_INPUT));
        Assert.assertTrue(errorAfterTuning.getMean() < errorBeforeTuning.getMean());
        //either have a very low error, or at least have improved by a factor of over 100
        Assert.assertTrue(finalError.getMean() < 10 || finalError.getMean() < errorBeforeTuning.getMean() / 100);

        return controller;

    }

}