eu.cassandra.training.activity.Histogram.java Source code

Java tutorial

Introduction

Here is the source code for eu.cassandra.training.activity.Histogram.java

Source

/*   
   Copyright 2011-2012 The Cassandra Consortium (cassandra-fp7.eu)
    
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
    
   http://www.apache.org/licenses/LICENSE-2.0
    
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package eu.cassandra.training.activity;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.TreeMap;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

import eu.cassandra.training.response.Incentive;
import eu.cassandra.training.response.IncentiveVector;
import eu.cassandra.training.response.Pricing;
import eu.cassandra.training.response.PricingVector;
import eu.cassandra.training.utils.Constants;

/**
 * This class is used for implementing a Histogram distribution to use
 * in the activity models that are created in the Training Module of
 * Cassandra Project. The same class has been used, with small alterations in
 * the main Cassandra Platform.
 * 
 * @author Christos Diou, Antonios Chrysopoulos
 * @version 0.9, Date: 29.07.2013
 */
public class Histogram implements ProbabilityDistribution {

    /**
     * The name of the Histogram distribution.
     */
    private String name = "";

    /**
     * The type of the Normal distribution.
     */
    private String type = "";
    /**
     * A variable presenting the number of bins that are created for the histogram
     * containing the values of the Normal distribution.
     */
    protected int numberOfBins;

    /**
     * An array containing the probabilities of each bin precomputed for the
     * Normal distribution.
     */
    protected double[] values;

    /**
     * This is an array that contains the probabilities that the distribution has
     * value over a threshold.
     */
    private double[] greaterProbability;

    /** The id of the distribution as given by the Cassandra server. */
    private String distributionID = "";

    /**
     * 
     * Constructor of a Histogram distribution with given parameters.
     * 
     * @param name
     *          The name of the distribution
     * @param values
     *          The values for the array of values
     */
    public Histogram(String name, double[] values) {
        this.name = name;
        type = "Histogram";
        numberOfBins = values.length;
        this.values = values;

    }

    /**
     * Constructor of a Histogram distribution with parameters parsed from a file.
     * 
     * @param filename
     *          The file name of the input file.
     */
    public Histogram(String filename) throws FileNotFoundException {
        name = filename;
        type = "Histogram";
        Map<Integer, Double> histogram = new HashMap<Integer, Double>();
        File file = new File(filename);
        Scanner input = new Scanner(file);
        String nextLine = input.nextLine();
        String[] line = new String[2];

        // System.out.println(nextLine);

        while (input.hasNext()) {
            nextLine = input.nextLine();
            line = nextLine.split("-");
            // System.out.println(line[0] + " " + line[1]);

            line[1] = line[1].replace(",", ".");

            histogram.put(Integer.parseInt(line[0]), Double.parseDouble(line[1]));

        }

        numberOfBins = (Integer.parseInt(line[0])) + 1;
        values = new double[numberOfBins];

        for (int i = 0; i < numberOfBins; i++) {

            if (histogram.containsKey(i))
                values[i] = histogram.get(i);
            else
                values[i] = 0;
        }

        input.close();
        file.deleteOnExit();

        estimateGreaterProbability();
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDistributionID() {
        return distributionID;
    }

    @Override
    public void setDistributionID(String id) {
        distributionID = id;
    }

    @Override
    public int getNumberOfParameters() {
        return 1;
    }

    @Override
    public double getParameter(int index) {

        return numberOfBins;
    }

    @Override
    public void setParameter(int index, double value) {
    }

    @Override
    public void precompute(int startValue, int endValue, int nBins) {
    }

    @Override
    public String getDescription() {
        String description = "Histogram probability Frequency function";
        return description;
    }

    @Override
    public double getProbability(int x) {
        if (x < 0)
            return 0;
        else
            return values[x];
    }

    @Override
    public double getPrecomputedProbability(int x) {
        if (x < 0)
            return 0;
        else
            return values[x];
    }

    @Override
    public int getPrecomputedBin() {
        Random random = new Random();
        double dice = random.nextDouble();
        double sum = 0;
        for (int i = 0; i < numberOfBins; i++) {
            sum += values[i];

            if (dice < sum)
                return i;
        }
        return -1;
    }

    @Override
    public double[] getGreaterProbability() {
        return greaterProbability;
    }

    @Override
    public void status() {
        System.out.println("Histogram Distribution");
        System.out.println("Number of Beans: " + numberOfBins);
        System.out.println("Values:");

        for (int i = 0; i < values.length; i++) {
            System.out.println("Index: " + i + " Value: " + values[i]);
        }

    }

    @Override
    public double[] getHistogram() {
        return values;
    }

    @Override
    public double getProbabilityGreater(int x) {
        double prob = 0;

        int start = (int) x;

        for (int i = start + 1; i < values.length; i++)
            prob += values[i];

        return prob;
    }

    @Override
    public double getProbabilityLess(int x) {
        return 1 - getProbabilityGreater(x);
    }

    private void estimateGreaterProbability() {
        greaterProbability = new double[values.length];

        for (int i = 0; i < values.length; i++)
            greaterProbability[i] = getProbabilityGreater(i);

    }

    @Override
    public double[] movingAverage(double[] values, Incentive incentive, float awareness, float sensitivity) {
        // Initialize the auxiliary variables.
        int side = -1;
        int startIndex = incentive.getStartMinute();
        int endIndex = incentive.getEndMinute();
        double overDiff = 0, overDiffTemp = 0;
        double temp = 0;
        String type = "";
        // double sum = 0;

        // First, the incentive type is checked (penalty or reward) and then the
        // before and after values are checked to see how the residual percentage
        // will be distributed.
        if (incentive.isPenalty()) {

            if (incentive.getBeforeDifference() > 0 && incentive.getAfterDifference() < 0)
                type = "Both";

            if (incentive.getBeforeDifference() > 0 && incentive.getAfterDifference() >= 0)
                type = "Left";

            if (incentive.getBeforeDifference() <= 0 && incentive.getAfterDifference() < 0)
                type = "Right";

            if (incentive.getBeforeDifference() < 0 && incentive.getAfterDifference() > 0)
                type = "None";
        } else {

            if (incentive.getBeforeDifference() < 0 && incentive.getAfterDifference() > 0)
                type = "Both";

            if (incentive.getBeforeDifference() < 0 && incentive.getAfterDifference() <= 0)
                type = "Left";

            if (incentive.getBeforeDifference() >= 0 && incentive.getAfterDifference() > 0)
                type = "Right";

            if (incentive.getBeforeDifference() > 0 && incentive.getAfterDifference() < 0)
                type = "None";

        }

        // System.out.println("Penalty: " + incentive.isPenalty() + " Type: " +
        // type);

        if (!type.equalsIgnoreCase("None")) {
            // In case of penalty the residual percentage is moved out of the window
            // to close distance, either on one or both sides accordingly
            if (incentive.isPenalty()) {

                for (int i = startIndex; i < endIndex; i++) {

                    temp = incentive.getBase() * values[i] / incentive.getPrice();
                    // System.out.println("Temp = " + temp);
                    overDiffTemp = (values[i] - temp) * awareness * sensitivity;
                    overDiff += overDiffTemp;
                    values[i] -= overDiffTemp;

                    // overDiff += values[i] - temp;
                    // values[i] = temp;

                }
                // System.out.println("Over Difference = " + overDiff);
                double additive = overDiff / Constants.SHIFTING_WINDOW_IN_MINUTES;

                switch (type) {

                case "Both":

                    side = Constants.SHIFTING_WINDOW_IN_MINUTES / 2;

                    for (int i = 0; i < side; i++) {

                        int before = startIndex - i;
                        if (before < 0)
                            before += Constants.MINUTES_PER_DAY;
                        int after = endIndex + i;
                        if (after > Constants.MINUTES_PER_DAY - 1)
                            after %= Constants.MINUTES_PER_DAY;

                        values[before] += additive;
                        values[after] += additive;

                    }
                    break;

                case "Left":

                    side = Constants.SHIFTING_WINDOW_IN_MINUTES;

                    for (int i = 0; i < side; i++) {

                        int before = startIndex - i;
                        if (before < 0)
                            before += Constants.MINUTES_PER_DAY;
                        values[before] += additive;

                    }
                    break;

                case "Right":

                    side = Constants.SHIFTING_WINDOW_IN_MINUTES;

                    for (int i = 0; i < side; i++) {

                        int after = endIndex + i;
                        if (after > Constants.MINUTES_PER_DAY - 1)
                            after %= Constants.MINUTES_PER_DAY;

                        values[after] += additive;
                    }
                }
            }
            // In case of reward a percentage of the close distances are moved in the
            // window, either from one or both sides accordingly.
            else {
                side = Constants.SHIFTING_WINDOW_IN_MINUTES * 2;
                switch (type) {

                case "Both":

                    for (int i = startIndex - side; i < startIndex; i++) {

                        int index = i;

                        if (index < 0)
                            index += Constants.MINUTES_PER_DAY;

                        temp = incentive.getPrice() * values[index] / incentive.getBase();
                        overDiffTemp = (values[index] - temp) * awareness * sensitivity;
                        overDiff += overDiffTemp;
                        values[index] -= overDiffTemp;

                        // overDiff += values[index] - temp;
                        // values[index] = temp;
                    }

                    for (int i = endIndex; i < endIndex + side; i++) {

                        int index = i;

                        if (index > Constants.MINUTES_PER_DAY - 1)
                            index %= Constants.MINUTES_PER_DAY;

                        temp = incentive.getPrice() * values[index] / incentive.getBase();
                        overDiffTemp = (values[index] - temp) * awareness * sensitivity;
                        overDiff += overDiffTemp;
                        values[index] -= overDiffTemp;

                        // temp = incentive.getPrice() * values[index] /
                        // incentive.getBase();
                        // overDiff += values[index] - temp;
                        // values[index] = temp;
                    }
                    break;

                case "Left":

                    for (int i = startIndex - 2 * side; i < startIndex; i++) {

                        int index = i;

                        if (index < 0)
                            index += Constants.MINUTES_PER_DAY;

                        temp = incentive.getPrice() * values[index] / incentive.getBase();
                        overDiffTemp = (values[index] - temp) * awareness * sensitivity;
                        overDiff += overDiffTemp;
                        values[index] -= overDiffTemp;

                        // temp = incentive.getPrice() * values[index] /
                        // incentive.getBase();
                        // overDiff += values[index] - temp;
                        // values[index] = temp;
                    }
                    break;

                case "Right":

                    for (int i = endIndex; i < endIndex + 2 * side; i++) {

                        int index = i;

                        if (index > Constants.MINUTES_PER_DAY - 1)
                            index %= Constants.MINUTES_PER_DAY;

                        temp = incentive.getPrice() * values[index] / incentive.getBase();
                        overDiffTemp = (values[index] - temp) * awareness * sensitivity;
                        overDiff += overDiffTemp;
                        values[index] -= overDiffTemp;

                        // temp = incentive.getPrice() * values[index] /
                        // incentive.getBase();
                        // overDiff += values[index] - temp;
                        // values[index] = temp;
                    }

                }
                // System.out.println("Over Difference = " + overDiff);

                double additive = overDiff / (endIndex - startIndex);

                for (int i = startIndex; i < endIndex; i++)
                    values[i] += additive;

            }

        }
        // for (int i = 0; i < values.length; i++)
        // sum += values[i];
        // System.out.println("Summary: " + sum);

        return values;
    }

    @Override
    public double[] discreteOptimal(double[] values, PricingVector pricing, float awareness, float sensitivity) {
        // Initialize the auxiliary variables.
        double temp = 0, additive = 0, overDiff = 0, overDiffTemp = 0, sum = 0;
        Pricing tempPricing;
        // double sum = 0;

        int start, start2, end, end2, duration;
        double previousPrice, newPrice;

        if (pricing.getNumberOfPenalties() > 0) {

            Map<Integer, Double> percentageMap = new TreeMap<Integer, Double>();
            ArrayList<Integer> tempList = new ArrayList<Integer>(pricing.getBases());
            tempList.addAll(pricing.getRewards());

            for (Integer index : tempList)
                sum += pricing.getPricings(index).getGainRatio();

            for (Integer index : tempList)
                percentageMap.put(index, pricing.getPricings(index).getGainRatio() / sum);

            // System.out.println("Percentage Map: " + percentageMap.toString());

            for (Integer index : pricing.getPenalties()) {
                overDiff = 0;
                sum = 0;

                tempPricing = pricing.getPricings(index);
                start = tempPricing.getStartMinute();
                end = tempPricing.getEndMinute();
                previousPrice = tempPricing.getPreviousPrice();
                newPrice = tempPricing.getCurrentPrice();

                for (int i = start; i <= end; i++) {

                    temp = ((previousPrice * values[i]) / newPrice);
                    // System.out.println("Temp = " + temp);
                    overDiffTemp = (values[i] - temp) * awareness * sensitivity;
                    overDiff += overDiffTemp;
                    values[i] -= overDiffTemp;
                }

                // System.out.println("OverDiff for index " + index + ": " + overDiff);

                for (Integer index2 : tempList) {
                    start2 = pricing.getPricings(index2).getStartMinute();
                    end2 = pricing.getPricings(index2).getEndMinute();
                    duration = end2 - start2;
                    additive = overDiff * percentageMap.get(index2) / duration;
                    // System.out.println("Additive for index " + index2 + ": " +
                    // additive);
                    for (int i = start2; i < end2; i++)
                        values[i] += additive;
                }

                for (int i = 0; i < values.length; i++)
                    sum += values[i];

                // System.out.println("Summary: " + sum);

            }

        } else if (pricing.getNumberOfRewards() > 0) {

            Pricing tempPricing2 = null;
            ArrayList<Pricing> tempList = new ArrayList<Pricing>();

            for (Integer index : pricing.getRewards())
                tempList.add(pricing.getPricings(index));

            Collections.sort(tempList, comp);

            // System.out.println("Rewards List: " + tempList.toString());

            for (int i = 0; i < tempList.size(); i++) {

                tempPricing2 = tempList.get(i);
                newPrice = tempPricing2.getCurrentPrice();
                start2 = tempPricing2.getStartMinute();
                end2 = tempPricing2.getEndMinute();
                duration = end2 - start2;

                for (Integer index : pricing.getBases()) {
                    overDiff = 0;
                    sum = 0;

                    tempPricing = pricing.getPricings(index);
                    start = tempPricing.getStartMinute();
                    end = tempPricing.getEndMinute();
                    previousPrice = tempPricing.getCurrentPrice();

                    for (int j = start; j <= end; j++) {

                        temp = newPrice * values[j] / previousPrice;
                        overDiffTemp = (values[j] - temp) * awareness * sensitivity;
                        overDiff += overDiffTemp;
                        values[j] -= overDiffTemp;

                    }

                    // System.out.println("OverDiff for index " + index + ": " +
                    // overDiff);

                    additive = overDiff / duration;
                    // System.out.println("Additive for index " + i + ": " + additive);

                    for (int j = start2; j < end2; j++)
                        values[j] += additive;
                }

                for (int j = 0; j < values.length; j++)
                    sum += values[j];

                // System.out.println("Summary: " + sum);

            }

        }

        return values;
    }

    @Override
    public double[] discreteAverage(double[] values, PricingVector pricing, float awareness, float sensitivity) {

        // Initialize the auxiliary variables.
        double temp = 0;
        double sum = 0;
        double overDiff = 0, overDiffTemp = 0;
        int start, end;
        double newPrice;
        int durationCheapest = 0;

        // Finding the cheapest window in the day.
        ArrayList<Integer> cheapest = pricing.getCheapest();

        for (Integer index : cheapest) {
            int startCheapest = pricing.getPricings(index).getStartMinute();
            int endCheapest = pricing.getPricings(index).getEndMinute();
            durationCheapest += endCheapest - startCheapest;
        }

        double cheapestPrice = pricing.getPricings(pricing.getCheapest().get(0)).getCurrentPrice();

        // Moving from all the available vectors residual percentages to the
        // cheapest one.
        for (int i = 0; i < pricing.getPricings().size(); i++) {

            if (cheapest.contains(i) == false) {
                sum = 0;
                overDiff = 0;
                start = pricing.getPricings(i).getStartMinute();
                end = pricing.getPricings(i).getEndMinute();
                newPrice = pricing.getPricings(i).getCurrentPrice();

                for (int j = start; j <= end; j++) {

                    temp = cheapestPrice * values[j] / newPrice;
                    overDiffTemp = (values[j] - temp) * awareness * sensitivity;
                    overDiff += overDiffTemp;
                    values[j] -= overDiffTemp;

                }

                double additive = overDiff / durationCheapest;

                for (Integer index : cheapest) {
                    int startCheapest = pricing.getPricings(index).getStartMinute();
                    int endCheapest = pricing.getPricings(index).getEndMinute();

                    for (int j = startCheapest; j <= endCheapest; j++)
                        values[j] += additive;

                }

                for (int j = 0; j < values.length; j++)
                    sum += values[j];
                System.out.println("Summary after index " + i + ": " + sum);

            }

        }

        return values;
    }

    @Override
    public void shifting(int shiftingCase, double[] basicScheme, double[] newScheme, float awareness,
            float sensitivity) {

        if (shiftingCase == 0) {

            values = shiftingOptimal(basicScheme, newScheme, awareness, sensitivity);
        } else if (shiftingCase == 1) {

            values = shiftingNormal(basicScheme, newScheme, awareness, sensitivity);
        } else if (shiftingCase == 2) {

            values = shiftingDiscrete(basicScheme, newScheme, awareness, sensitivity);
        } else {
            System.out.println("ERROR in shifting function");
        }

    }

    @Override
    public double[] shiftingPreview(int shiftingCase, double[] basicScheme, double[] newScheme, float awareness,
            float sensitivity) {

        double[] result = new double[Constants.MINUTES_PER_DAY];

        if (shiftingCase == 0) {

            result = shiftingOptimal(basicScheme, newScheme, awareness, sensitivity);
        } else if (shiftingCase == 1) {

            result = shiftingNormal(basicScheme, newScheme, awareness, sensitivity);
        } else if (shiftingCase == 2) {

            result = shiftingDiscrete(basicScheme, newScheme, awareness, sensitivity);
        } else {
            System.out.println("ERROR in shifting function");
        }

        return result;

    }

    @Override
    public void shiftingDaily(double energyRatio, float awareness, float sensitivity) {
        values = shiftingDailyPreview(energyRatio, awareness, sensitivity);
    }

    @Override
    public double[] shiftingDailyPreview(double energyRatio, float awareness, float sensitivity) {
        double[] temp = Arrays.copyOf(values, values.length);

        double diff = (energyRatio - 1) * (awareness * sensitivity);

        System.out.println("Diff: " + diff);

        double[] result;
        if (diff > 0) {

            if (diff > 1) {
                result = new double[1];
                result[0] = 1;
            } else
                result = reduceUse(temp, diff);

        } else
            result = increaseUse(temp, Math.abs(diff));

        System.out.println("Final:" + Arrays.toString(result));

        return result;

    }

    private double[] reduceUse(double[] result, double diff) {
        int index = result.length - 1;
        double diffTemp = diff;
        double sum = 0;

        System.out.println("Before:" + Arrays.toString(result));

        while (diffTemp > 0) {

            double reduction = Math.min(result[index], diffTemp);

            result[index] -= reduction;
            diffTemp -= reduction;

            System.out.println("Index: " + index + " Reduction: " + reduction + " DiffTemp: " + diffTemp);

            index--;

        }

        // Fixes out of bounds error
        index = Math.max(0, index);

        System.out.println("After:" + Arrays.toString(result));

        for (int i = 0; i <= index; i++)
            sum += result[i];

        for (int i = 0; i <= index; i++)
            result[i] += (result[i] / sum) * diff;

        sum = 0;

        for (int i = 0; i < result.length; i++)
            sum += result[i];

        System.out.println("After Normalization:" + Arrays.toString(result));

        System.out.println("Summary: " + sum);

        index = result.length - 1;

        while (result[index] == 0)
            index--;

        return Arrays.copyOfRange(result, 0, index + 1);

    }

    private double[] increaseUse(double[] result, double diff) {
        int index = 0;
        double diffTemp = diff;
        double sum = 0;

        System.out.println("Before:" + Arrays.toString(result));

        while (diffTemp > 0) {

            double reduction = Math.min(result[index], diffTemp);

            result[index] -= reduction;
            diffTemp -= reduction;

            System.out.println("Index: " + index + " Reduction: " + reduction + " DiffTemp: " + diffTemp);

            index++;

        }

        index = Math.min(index, result.length - 1);

        System.out.println("After:" + Arrays.toString(result));

        for (int i = index; i < result.length; i++)
            sum += result[i];

        for (int i = index; i < result.length; i++)
            result[i] += (result[i] / sum) * diff;

        sum = 0;

        for (int i = 0; i < result.length; i++)
            sum += result[i];

        System.out.println("After Normalization:" + Arrays.toString(result));

        System.out.println("Summary: " + sum);

        return Arrays.copyOf(result, result.length);
    }

    @Override
    public double[] shiftingOptimal(double[] basicScheme, double[] newScheme, float awareness, float sensitivity) {

        double[] result = Arrays.copyOf(this.values, this.values.length);

        PricingVector pricingVector = new PricingVector(basicScheme, newScheme);

        if (pricingVector.getPricings().size() > 1)
            result = discreteOptimal(result, pricingVector, awareness, sensitivity);

        return result;

    }

    @Override
    public double[] shiftingNormal(double[] basicScheme, double[] newScheme, float awareness, float sensitivity) {
        double[] result = Arrays.copyOf(this.values, this.values.length);

        PricingVector pricingVector = new PricingVector(basicScheme, newScheme);

        IncentiveVector inc = new IncentiveVector(basicScheme, newScheme);

        if (pricingVector.getPricings().size() > 1)
            for (Incentive incentive : inc.getIncentives())
                result = movingAverage(result, incentive, awareness, sensitivity);

        return result;

    }

    @Override
    public double[] shiftingDiscrete(double[] basicScheme, double[] newScheme, float awareness, float sensitivity) {
        double[] result = Arrays.copyOf(this.values, this.values.length);

        PricingVector pricingVector = new PricingVector(basicScheme, newScheme);

        if (pricingVector.getPricings().size() > 1)
            result = discreteAverage(result, pricingVector, awareness, sensitivity);

        return result;
    }

    @Override
    public DBObject toJSON(String activityModelID) {
        BasicDBList param = new BasicDBList();
        DBObject temp = new BasicDBObject();

        temp.put("name", name);
        temp.put("type", type);
        temp.put("description", name + " " + type);
        temp.put("distrType", type);
        temp.put("actmod_id", activityModelID);
        temp.put("values", values);
        temp.put("parameters", param);
        return temp;

    }
}