tools.descartes.dlim.generator.util.FunctionValueCalculator.java Source code

Java tutorial

Introduction

Here is the source code for tools.descartes.dlim.generator.util.FunctionValueCalculator.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Joakim von Kistowski
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/

package tools.descartes.dlim.generator.util;

import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.eclipse.core.runtime.Status;

import tools.descartes.dlim.AbsoluteSin;
import tools.descartes.dlim.Burst;
import tools.descartes.dlim.DlimGeneratorPlugin;
import tools.descartes.dlim.ExponentialIncreaseAndDecline;
import tools.descartes.dlim.ExponentialIncreaseLogarithmicDecline;
import tools.descartes.dlim.ExponentialTrend;
import tools.descartes.dlim.Function;
import tools.descartes.dlim.LinearIncreaseAndDecline;
import tools.descartes.dlim.LinearTrend;
import tools.descartes.dlim.LogarithmicTrend;
import tools.descartes.dlim.Noise;
import tools.descartes.dlim.NormalNoise;
import tools.descartes.dlim.Polynomial;
import tools.descartes.dlim.PolynomialFactor;
import tools.descartes.dlim.Seasonal;
import tools.descartes.dlim.Sin;
import tools.descartes.dlim.SinTrend;
import tools.descartes.dlim.Trend;
import tools.descartes.dlim.UniformNoise;
import tools.descartes.dlim.generator.IGeneratorConstants;
import tools.descartes.dlim.generator.ModelEvaluatorUtil;

/**
 * Calculates and returns the arrival rate values for all simple Functions.
 * Simple Functions are all children of dlim.Function, that do not nest other
 * Functions.
 *
 * @author Joakim von Kistowski
 *
 */
public class FunctionValueCalculator {

    /**
     *  Random number generation for Noise.
     */
    private JDKRandomGenerator rndGenerator;

    /**
     * Normal Distribution.
     */
    private NormalDistribution nDistribution;

    /**
     *  This is IGeneratorConstants.CALIBRATION, if Noises are to have no effect.
     */
    private String noiseMode = "";

    /**
     * Create a new FunctionValueCalculator.
     *
     * @param rndGenerator
     *            The random number generator for Noises.
     * @param noiseMode
     *            Set this to IGeneratorConstants.CALIBRATION if Noises are to
     *            return 0.
     */
    public FunctionValueCalculator(JDKRandomGenerator rndGenerator, String noiseMode) {
        this.rndGenerator = rndGenerator;
        nDistribution = new NormalDistribution(rndGenerator, 0, 1,
                NormalDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
        this.noiseMode = noiseMode;
    }

    /**
     * Returns the value of a Function f with input x.
     *
     * @param f the Function f
     * @param x the double x
     * @return f(x)
     */
    public double getSimpleFunctionValue(Function f, double x) {
        if (f instanceof Polynomial) {
            return getPolynomialValue((Polynomial) f, x);
        } else if (f instanceof Noise) {
            return getNoiseValue((Noise) f, x);
        } else if (f instanceof Seasonal) {
            return getSeasonalValue((Seasonal) f, x);
        } else if (f instanceof Burst) {
            return getBurstValue((Burst) f, x);
        } else if (f instanceof Trend) {
            return getTrendValue((Trend) f, x);
        } else {
            DlimGeneratorPlugin.INSTANCE.log(new Status(Status.ERROR, DlimGeneratorPlugin.PLUGIN_ID,
                    "Function matches no Category: " + f.toString()));
            return 0.0;
        }
    }

    /**
     * Sets the noise mode.
     *
     * @param noiseMode the new noise mode
     */
    public void setNoiseMode(String noiseMode) {
        this.noiseMode = noiseMode;
    }

    private double getPolynomialValue(Polynomial f, double x) {
        int index = f.getFactors().size() - 1;
        double value = 0;
        for (PolynomialFactor factor : f.getFactors()) {
            if (index == 0) {
                value += factor.getFactor();
            } else {
                value += factor.getFactor() * Math.pow(x + factor.getOffset(), index);
            }
            index--;
        }
        return value;
    }

    private double getNoiseValue(Noise f, double x) {
        if (noiseMode.contains(IGeneratorConstants.CALIBRATION)) {
            return 0.0;
        }
        if (f instanceof UniformNoise) {
            UniformNoise noise = (UniformNoise) f;
            return noise.getMin() + (noise.getMax() - noise.getMin()) * rndGenerator.nextDouble();
        } else if (f instanceof NormalNoise) {
            NormalNoise noise = (NormalNoise) f;
            return noise.getMean() + noise.getStandardDeviation() * nDistribution.sample();
        } else {
            DlimGeneratorPlugin.INSTANCE
                    .log(new Status(Status.ERROR, DlimGeneratorPlugin.PLUGIN_ID, "Unknown Noise: " + f.toString()));
            return 0.0;
        }
    }

    private double getSeasonalValue(Seasonal f, double x) {
        if (f instanceof Sin) {
            Sin sin = (Sin) f;
            if (f instanceof AbsoluteSin) {
                return sin.getMin() + (sin.getMax() - sin.getMin())
                        * Math.abs(Math.sin((x + sin.getPhase()) * 2 * Math.PI / sin.getPeriod()));
            } else {
                return sin.getMin() + ((sin.getMax() - sin.getMin()) / 2.0) + ((sin.getMax() - sin.getMin()) / 2.0)
                        * Math.sin((x + sin.getPhase()) * 2 * Math.PI / sin.getPeriod());
            }
        } else {
            DlimGeneratorPlugin.INSTANCE.log(
                    new Status(Status.ERROR, DlimGeneratorPlugin.PLUGIN_ID, "Unknown Seasonal: " + f.toString()));
            return 0.0;
        }
    }

    private double getBurstValue(Burst f, double x) {
        if (f instanceof LinearIncreaseAndDecline) {
            LinearIncreaseAndDecline burst = (LinearIncreaseAndDecline) f;
            return calculateLinearIncreaseAndDeclineValue(x, burst.getBase(), burst.getPeak(), burst.getPeakTime(),
                    ModelEvaluatorUtil.getFunctionDuration(f));
        } else if (f instanceof ExponentialIncreaseAndDecline) {
            ExponentialIncreaseAndDecline burst = (ExponentialIncreaseAndDecline) f;
            return calculateExponentialIncreaseAndDeclineValue(x, burst.getBase(), burst.getPeak(),
                    burst.getPeakTime(), ModelEvaluatorUtil.getFunctionDuration(f));
        } else if (f instanceof ExponentialIncreaseLogarithmicDecline) {
            ExponentialIncreaseLogarithmicDecline burst = (ExponentialIncreaseLogarithmicDecline) f;
            return calculateExponentialIncreaseLogarthmicDeclineValue(x, burst.getBase(), burst.getPeak(),
                    burst.getPeakTime(), burst.getLogarithmicOrder(), ModelEvaluatorUtil.getFunctionDuration(f));
        } else {
            DlimGeneratorPlugin.INSTANCE
                    .log(new Status(Status.ERROR, DlimGeneratorPlugin.PLUGIN_ID, "Unknown Burst: " + f.toString()));
            return 0.0;
        }
    }

    private double getTrendValue(Trend f, double x) {
        if (f instanceof LinearTrend) {
            LinearTrend trend = (LinearTrend) f;
            return trend.getFunctionOutputAtStart()
                    + x * (trend.getFunctionOutputAtEnd() - trend.getFunctionOutputAtStart())
                            / ModelEvaluatorUtil.getFunctionDuration(f);
        } else if (f instanceof ExponentialTrend) {
            ExponentialTrend trend = (ExponentialTrend) f;
            return calculateExponentialTrendValue(x, trend.getFunctionOutputAtEnd(),
                    trend.getFunctionOutputAtStart(), ModelEvaluatorUtil.getFunctionDuration(f));
        } else if (f instanceof LogarithmicTrend) {
            LogarithmicTrend trend = (LogarithmicTrend) f;
            return calculateLogarithmicTrendValue(x, trend.getFunctionOutputAtEnd(),
                    trend.getFunctionOutputAtStart(), trend.getOrder(), ModelEvaluatorUtil.getFunctionDuration(f));
        } else if (f instanceof SinTrend) {
            SinTrend trend = (SinTrend) f;
            return calculateSinTrendValue(x, trend.getFunctionOutputAtEnd(), trend.getFunctionOutputAtStart(),
                    ModelEvaluatorUtil.getFunctionDuration(f));
        } else {
            DlimGeneratorPlugin.INSTANCE
                    .log(new Status(Status.ERROR, DlimGeneratorPlugin.PLUGIN_ID, "Unknown Trend: " + f.toString()));
            return 1.0;
        }
    }

    private double calculateLogarithmicTrendValue(double x, double endValue, double startValue, double order,
            double duration) {
        if (startValue > endValue) {
            double tmpX = Math.abs(x - duration);
            return endValue + (startValue - endValue) * (1 / order)
                    * Math.log((tmpX * (Math.exp(order) - 1) / duration) + 1);
        }
        return startValue
                + (endValue - startValue) * (1 / order) * Math.log((x * (Math.exp(order) - 1) / duration) + 1);
    }

    private double calculateSinTrendValue(double x, double endValue, double startValue, double duration) {
        double minValue = startValue;
        double maxValue = endValue;
        double phase = -(Math.PI / 2);
        if (startValue > endValue) {
            minValue = endValue;
            maxValue = startValue;
            phase = (Math.PI / 2);
        }
        return minValue + ((maxValue - minValue) / 2)
                + ((maxValue - minValue) / 2) * Math.sin(phase + x * Math.PI / duration);
    }

    private double calculateExponentialTrendValue(double x, double endValue, double startValue, double duration) {
        double offset = 0;
        double start = startValue;
        double end = endValue;
        double minValue = Math.min(startValue, endValue);
        if (minValue <= 0) {
            offset = minValue - 0.5;
            start = start + 0.5 - minValue;
            end = end + 0.5 - minValue;
        }
        return offset + Math.exp(Math.log(start) + ((Math.log(end) - Math.log(start)) * (x / duration)));
    }

    private double calculateLinearIncreaseAndDeclineValue(double x, double baseValue, double peakValue,
            double peakTime, double duration) {
        double tmpX = x;
        if (x > peakTime) {
            tmpX = peakTime - ((x - peakTime) * peakTime / (duration - peakTime));
        }
        return baseValue + ((peakValue - baseValue) / peakTime) * tmpX;
    }

    private double calculateExponentialIncreaseAndDeclineValue(double x, double baseValue, double peakValue,
            double peakTime, double duration) {
        double tmpX = x;
        if (x > peakTime) {
            tmpX = peakTime - ((x - peakTime) * peakTime / (duration - peakTime));
        }
        return calculateExponentialTrendValue(tmpX, peakValue, baseValue, peakTime);
    }

    private double calculateExponentialIncreaseLogarthmicDeclineValue(double x, double baseValue, double peakValue,
            double peakTime, double order, double duration) {
        double tmpX = x;
        if (x > peakTime) {
            tmpX = peakTime - ((x - peakTime) * peakTime / (duration - peakTime));
            // return baseValue +
            // (peakValue-baseValue)*(1/order)*Math.log((tmpX*(Math.exp(order)-1)/peakTime)
            // + 1);
            return calculateLogarithmicTrendValue(tmpX, peakValue, baseValue, order, peakTime);
        } else {
            return calculateExponentialTrendValue(tmpX, peakValue, baseValue, peakTime);
        }
    }
}