Commit a5837706 authored by Nikolay's avatar Nikolay

* Removed the dependency on the flanagan library. It is now replaced with Apache Math.

* The minimal time between events is now configurable
parent 60e69f4a
#!/bin/sh
wget http://www.ee.ucl.ac.uk/~mflanaga/java/flanagan.jar
mvn install:install-file -DgroupId=org.flanagan -DartifactId=flanagan -Dversion=1.0 -Dfile=flanagan.jar -Dpackaging=jar -DgeneratePom=true
rm flanagan.jar
...@@ -12,6 +12,8 @@ import java.util.HashMap; ...@@ -12,6 +12,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.cloudbus.cloudsim.core.CloudSim;
/** /**
* CloudletSchedulerDynamicWorkload implements a policy of scheduling performed by a virtual machine * CloudletSchedulerDynamicWorkload implements a policy of scheduling performed by a virtual machine
* assuming that there is just one cloudlet which is working as an online service. * assuming that there is just one cloudlet which is working as an online service.
...@@ -81,8 +83,8 @@ public class CloudletSchedulerDynamicWorkload extends CloudletSchedulerTimeShare ...@@ -81,8 +83,8 @@ public class CloudletSchedulerDynamicWorkload extends CloudletSchedulerTimeShare
continue; continue;
} else { // not finish: estimate the finish time } else { // not finish: estimate the finish time
double estimatedFinishTime = getEstimatedFinishTime(rcl, currentTime); double estimatedFinishTime = getEstimatedFinishTime(rcl, currentTime);
if (estimatedFinishTime - currentTime < 0.1) { if (estimatedFinishTime - currentTime < CloudSim.getMinTimeBetweenEvents()) {
estimatedFinishTime = currentTime + 0.1; estimatedFinishTime = currentTime + CloudSim.getMinTimeBetweenEvents();
} }
if (estimatedFinishTime < nextEvent) { if (estimatedFinishTime < nextEvent) {
nextEvent = estimatedFinishTime; nextEvent = estimatedFinishTime;
......
...@@ -136,8 +136,8 @@ public class CloudletSchedulerSpaceShared extends CloudletScheduler { ...@@ -136,8 +136,8 @@ public class CloudletSchedulerSpaceShared extends CloudletScheduler {
for (ResCloudlet rcl : getCloudletExecList()) { for (ResCloudlet rcl : getCloudletExecList()) {
double remainingLength = rcl.getRemainingCloudletLength(); double remainingLength = rcl.getRemainingCloudletLength();
double estimatedFinishTime = currentTime + (remainingLength / (capacity * rcl.getNumberOfPes())); double estimatedFinishTime = currentTime + (remainingLength / (capacity * rcl.getNumberOfPes()));
if (estimatedFinishTime - currentTime < 0.1) { if (estimatedFinishTime - currentTime < CloudSim.getMinTimeBetweenEvents()) {
estimatedFinishTime = currentTime + 0.1; estimatedFinishTime = currentTime + CloudSim.getMinTimeBetweenEvents();
} }
if (estimatedFinishTime < nextEvent) { if (estimatedFinishTime < nextEvent) {
nextEvent = estimatedFinishTime; nextEvent = estimatedFinishTime;
......
...@@ -90,8 +90,8 @@ public class CloudletSchedulerTimeShared extends CloudletScheduler { ...@@ -90,8 +90,8 @@ public class CloudletSchedulerTimeShared extends CloudletScheduler {
for (ResCloudlet rcl : getCloudletExecList()) { for (ResCloudlet rcl : getCloudletExecList()) {
double estimatedFinishTime = currentTime double estimatedFinishTime = currentTime
+ (rcl.getRemainingCloudletLength() / (getCapacity(mipsShare) * rcl.getNumberOfPes())); + (rcl.getRemainingCloudletLength() / (getCapacity(mipsShare) * rcl.getNumberOfPes()));
if (estimatedFinishTime - currentTime < 0.1) { if (estimatedFinishTime - currentTime < CloudSim.getMinTimeBetweenEvents()) {
estimatedFinishTime = currentTime + 0.1; estimatedFinishTime = currentTime + CloudSim.getMinTimeBetweenEvents();
} }
if (estimatedFinishTime < nextEvent) { if (estimatedFinishTime < nextEvent) {
......
...@@ -440,7 +440,7 @@ public class Datacenter extends SimEntity { ...@@ -440,7 +440,7 @@ public class Datacenter extends SimEntity {
} else { } else {
data[2] = CloudSimTags.FALSE; data[2] = CloudSimTags.FALSE;
} }
send(vm.getUserId(), 0.1, CloudSimTags.VM_CREATE_ACK, data); send(vm.getUserId(), CloudSim.getMinTimeBetweenEvents(), CloudSimTags.VM_CREATE_ACK, data);
} }
if (result) { if (result) {
...@@ -866,7 +866,7 @@ public class Datacenter extends SimEntity { ...@@ -866,7 +866,7 @@ public class Datacenter extends SimEntity {
// if some time passed since last processing // if some time passed since last processing
// R: for term is to allow loop at simulation start. Otherwise, one initial // R: for term is to allow loop at simulation start. Otherwise, one initial
// simulation step is skipped and schedulers are not properly initialized // simulation step is skipped and schedulers are not properly initialized
if (CloudSim.clock() < 0.111 || CloudSim.clock() > getLastProcessTime() + 0.1) { if (CloudSim.clock() < 0.111 || CloudSim.clock() > getLastProcessTime() + CloudSim.getMinTimeBetweenEvents()) {
List<? extends Host> list = getVmAllocationPolicy().getHostList(); List<? extends Host> list = getVmAllocationPolicy().getHostList();
double smallerTime = Double.MAX_VALUE; double smallerTime = Double.MAX_VALUE;
// for each host... // for each host...
...@@ -880,8 +880,8 @@ public class Datacenter extends SimEntity { ...@@ -880,8 +880,8 @@ public class Datacenter extends SimEntity {
} }
} }
// gurantees a minimal interval before scheduling the event // gurantees a minimal interval before scheduling the event
if (smallerTime < CloudSim.clock() + 0.11) { if (smallerTime < CloudSim.clock() + CloudSim.getMinTimeBetweenEvents() + 0.01) {
smallerTime = CloudSim.clock() + 0.11; smallerTime = CloudSim.clock() + CloudSim.getMinTimeBetweenEvents() + 0.01;
} }
if (smallerTime != Double.MAX_VALUE) { if (smallerTime != Double.MAX_VALUE) {
schedule(getId(), (smallerTime - CloudSim.clock()), CloudSimTags.VM_DATACENTER_EVENT); schedule(getId(), (smallerTime - CloudSim.clock()), CloudSimTags.VM_DATACENTER_EVENT);
......
...@@ -62,6 +62,9 @@ public class CloudSim { ...@@ -62,6 +62,9 @@ public class CloudSim {
/** The termination time. */ /** The termination time. */
private static double terminateAt = -1; private static double terminateAt = -1;
/** The minimal time between events. Events within shorter periods after the last event are discarded. */
private static double minTimeBetweenEvents = 0.1;
/** /**
* Initialises all the common attributes. * Initialises all the common attributes.
* *
...@@ -131,6 +134,40 @@ public class CloudSim { ...@@ -131,6 +134,40 @@ public class CloudSim {
} }
} }
/**
* Initialises CloudSim parameters. This method should be called before creating any entities.
* <p>
* Inside this method, it will create the following CloudSim entities:
* <ul>
* <li>CloudInformationService.
* <li>CloudSimShutdown
* </ul>
* <p>
*
* @param numUser the number of User Entities created. This parameters indicates that
* {@link gridsim.CloudSimShutdown} first waits for all user entities's
* END_OF_SIMULATION signal before issuing terminate signal to other entities
* @param cal starting time for this simulation. If it is <tt>null</tt>, then the time will be
* taken from <tt>Calendar.getInstance()</tt>
* @param traceFlag <tt>true</tt> if CloudSim trace need to be written
* @param periodBetweenEvents - the minimal period between events. Events within shorter periods
* after the last event are discarded.
* @see gridsim.CloudSimShutdown
* @see CloudInformationService.CloudInformationService
* @pre numUser >= 0
* @post $none
*/
public static void init(int numUser, Calendar cal, boolean traceFlag, double periodBetweenEvents) {
if (periodBetweenEvents <= 0) {
throw new IllegalArgumentException("The minimal time between events should be positive, but is:" + periodBetweenEvents);
}
init(numUser, cal, traceFlag);
minTimeBetweenEvents = periodBetweenEvents;
}
/** /**
* Starts the execution of CloudSim simulation. It waits for complete execution of all entities, * Starts the execution of CloudSim simulation. It waits for complete execution of all entities,
* i.e. until all entities threads reach non-RUNNABLE state or there are no more events in the * i.e. until all entities threads reach non-RUNNABLE state or there are no more events in the
...@@ -212,6 +249,15 @@ public class CloudSim { ...@@ -212,6 +249,15 @@ public class CloudSim {
return true; return true;
} }
/**
* Returns the minimum time between events. Events within shorter periods after the last event are discarded.
* @return the minimum time between events.
*/
public static double getMinTimeBetweenEvents() {
return minTimeBetweenEvents;
}
/** /**
* Gets a new copy of initial simulation Calendar. * Gets a new copy of initial simulation Calendar.
* *
......
...@@ -218,8 +218,8 @@ public class NetworkCloudletSpaceSharedScheduler extends CloudletScheduler { ...@@ -218,8 +218,8 @@ public class NetworkCloudletSpaceSharedScheduler extends CloudletScheduler {
for (ResCloudlet rcl : getCloudletExecList()) { for (ResCloudlet rcl : getCloudletExecList()) {
double remainingLength = rcl.getRemainingCloudletLength(); double remainingLength = rcl.getRemainingCloudletLength();
double estimatedFinishTime = currentTime + (remainingLength / (capacity * rcl.getNumberOfPes())); double estimatedFinishTime = currentTime + (remainingLength / (capacity * rcl.getNumberOfPes()));
if (estimatedFinishTime - currentTime < 0.1) { if (estimatedFinishTime - currentTime < CloudSim.getMinTimeBetweenEvents()) {
estimatedFinishTime = currentTime + 0.1; estimatedFinishTime = currentTime + CloudSim.getMinTimeBetweenEvents();
} }
if (estimatedFinishTime < nextEvent) { if (estimatedFinishTime < nextEvent) {
nextEvent = estimatedFinishTime; nextEvent = estimatedFinishTime;
......
...@@ -16,8 +16,6 @@ import org.cloudbus.cloudsim.Vm; ...@@ -16,8 +16,6 @@ import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.core.CloudSim; import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.util.MathUtil; import org.cloudbus.cloudsim.util.MathUtil;
import flanagan.analysis.Stat;
/** /**
* The class of a VM that stores its CPU utilization history. The history is used by VM allocation * The class of a VM that stores its CPU utilization history. The history is used by VM allocation
* and selection policies. * and selection policies.
...@@ -63,17 +61,17 @@ public class PowerVm extends Vm { ...@@ -63,17 +61,17 @@ public class PowerVm extends Vm {
* @param schedulingInterval the scheduling interval * @param schedulingInterval the scheduling interval
*/ */
public PowerVm( public PowerVm(
int id, final int id,
int userId, final int userId,
double mips, final double mips,
int pesNumber, final int pesNumber,
int ram, final int ram,
long bw, final long bw,
long size, final long size,
int priority, final int priority,
String vmm, final String vmm,
CloudletScheduler cloudletScheduler, final CloudletScheduler cloudletScheduler,
double schedulingInterval) { final double schedulingInterval) {
super(id, userId, mips, pesNumber, ram, bw, size, vmm, cloudletScheduler); super(id, userId, mips, pesNumber, ram, bw, size, vmm, cloudletScheduler);
setSchedulingInterval(schedulingInterval); setSchedulingInterval(schedulingInterval);
} }
...@@ -91,7 +89,7 @@ public class PowerVm extends Vm { ...@@ -91,7 +89,7 @@ public class PowerVm extends Vm {
* @post $none * @post $none
*/ */
@Override @Override
public double updateVmProcessing(double currentTime, List<Double> mipsShare) { public double updateVmProcessing(final double currentTime, final List<Double> mipsShare) {
double time = super.updateVmProcessing(currentTime, mipsShare); double time = super.updateVmProcessing(currentTime, mipsShare);
if (currentTime > getPreviousTime() && (currentTime - 0.1) % getSchedulingInterval() == 0) { if (currentTime > getPreviousTime() && (currentTime - 0.1) % getSchedulingInterval() == 0) {
double utilization = getTotalUtilizationOfCpu(getCloudletScheduler().getPreviousTime()); double utilization = getTotalUtilizationOfCpu(getCloudletScheduler().getPreviousTime());
...@@ -120,7 +118,7 @@ public class PowerVm extends Vm { ...@@ -120,7 +118,7 @@ public class PowerVm extends Vm {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
deviationSum[i] = Math.abs(median - getUtilizationHistory().get(i)); deviationSum[i] = Math.abs(median - getUtilizationHistory().get(i));
} }
mad = Stat.median(deviationSum); mad = MathUtil.median(deviationSum);
} }
return mad; return mad;
} }
...@@ -172,7 +170,7 @@ public class PowerVm extends Vm { ...@@ -172,7 +170,7 @@ public class PowerVm extends Vm {
* *
* @param utilization the utilization * @param utilization the utilization
*/ */
public void addUtilizationHistoryValue(double utilization) { public void addUtilizationHistoryValue(final double utilization) {
getUtilizationHistory().add(0, utilization); getUtilizationHistory().add(0, utilization);
if (getUtilizationHistory().size() > HISTORY_LENGTH) { if (getUtilizationHistory().size() > HISTORY_LENGTH) {
getUtilizationHistory().remove(HISTORY_LENGTH); getUtilizationHistory().remove(HISTORY_LENGTH);
...@@ -202,7 +200,7 @@ public class PowerVm extends Vm { ...@@ -202,7 +200,7 @@ public class PowerVm extends Vm {
* *
* @param previousTime the new previous time * @param previousTime the new previous time
*/ */
public void setPreviousTime(double previousTime) { public void setPreviousTime(final double previousTime) {
this.previousTime = previousTime; this.previousTime = previousTime;
} }
...@@ -220,7 +218,7 @@ public class PowerVm extends Vm { ...@@ -220,7 +218,7 @@ public class PowerVm extends Vm {
* *
* @param schedulingInterval the schedulingInterval to set * @param schedulingInterval the schedulingInterval to set
*/ */
protected void setSchedulingInterval(double schedulingInterval) { protected void setSchedulingInterval(final double schedulingInterval) {
this.schedulingInterval = schedulingInterval; this.schedulingInterval = schedulingInterval;
} }
......
...@@ -11,9 +11,9 @@ package org.cloudbus.cloudsim.power; ...@@ -11,9 +11,9 @@ package org.cloudbus.cloudsim.power;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.cloudbus.cloudsim.Vm; import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.util.MathUtil;
import flanagan.analysis.Regression;
/** /**
* The Maximum Correlation (MC) VM selection policy. * The Maximum Correlation (MC) VM selection policy.
...@@ -39,19 +39,19 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo ...@@ -39,19 +39,19 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo
* *
* @param fallbackPolicy the fallback policy * @param fallbackPolicy the fallback policy
*/ */
public PowerVmSelectionPolicyMaximumCorrelation(PowerVmSelectionPolicy fallbackPolicy) { public PowerVmSelectionPolicyMaximumCorrelation(final PowerVmSelectionPolicy fallbackPolicy) {
super(); super();
setFallbackPolicy(fallbackPolicy); setFallbackPolicy(fallbackPolicy);
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see *
* org.cloudbus.cloudsim.experiments.power.PowerVmSelectionPolicy#getVmsToMigrate(org.cloudbus * @see org.cloudbus.cloudsim.experiments.power.PowerVmSelectionPolicy#
* .cloudsim.power.PowerHost) * getVmsToMigrate(org.cloudbus .cloudsim.power.PowerHost)
*/ */
@Override @Override
public Vm getVmToMigrate(PowerHost host) { public Vm getVmToMigrate(final PowerHost host) {
List<PowerVm> migratableVms = getMigratableVms(host); List<PowerVm> migratableVms = getMigratableVms(host);
if (migratableVms.isEmpty()) { if (migratableVms.isEmpty()) {
return null; return null;
...@@ -80,7 +80,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo ...@@ -80,7 +80,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo
* @param vmList the host * @param vmList the host
* @return the utilization matrix * @return the utilization matrix
*/ */
protected double[][] getUtilizationMatrix(List<PowerVm> vmList) { protected double[][] getUtilizationMatrix(final List<PowerVm> vmList) {
int n = vmList.size(); int n = vmList.size();
int m = getMinUtilizationHistorySize(vmList); int m = getMinUtilizationHistorySize(vmList);
double[][] utilization = new double[n][m]; double[][] utilization = new double[n][m];
...@@ -99,7 +99,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo ...@@ -99,7 +99,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo
* @param vmList the vm list * @param vmList the vm list
* @return the min utilization history size * @return the min utilization history size
*/ */
protected int getMinUtilizationHistorySize(List<PowerVm> vmList) { protected int getMinUtilizationHistorySize(final List<PowerVm> vmList) {
int minSize = Integer.MAX_VALUE; int minSize = Integer.MAX_VALUE;
for (PowerVm vm : vmList) { for (PowerVm vm : vmList) {
int size = vm.getUtilizationHistory().size(); int size = vm.getUtilizationHistory().size();
...@@ -116,7 +116,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo ...@@ -116,7 +116,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo
* @param data the data * @param data the data
* @return the correlation coefficients * @return the correlation coefficients
*/ */
protected List<Double> getCorrelationCoefficients(double[][] data) { protected List<Double> getCorrelationCoefficients(final double[][] data) {
int n = data.length; int n = data.length;
int m = data[0].length; int m = data[0].length;
List<Double> correlationCoefficients = new LinkedList<Double>(); List<Double> correlationCoefficients = new LinkedList<Double>();
...@@ -129,9 +129,12 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo ...@@ -129,9 +129,12 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo
} }
} }
Regression reg = new Regression(x, data[i]); // Transpose the matrix so that it fits the linear model
reg.linear(); double[][] xT = new Array2DRowRealMatrix(x).transpose().getData();
correlationCoefficients.add(reg.getCoefficientOfDetermination());
// RSquare is the "coefficient of determination"
correlationCoefficients.add(MathUtil.createLinearRegression(xT,
data[i]).calculateRSquared());
} }
return correlationCoefficients; return correlationCoefficients;
} }
...@@ -150,7 +153,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo ...@@ -150,7 +153,7 @@ public class PowerVmSelectionPolicyMaximumCorrelation extends PowerVmSelectionPo
* *
* @param fallbackPolicy the new fallback policy * @param fallbackPolicy the new fallback policy
*/ */
public void setFallbackPolicy(PowerVmSelectionPolicy fallbackPolicy) { public void setFallbackPolicy(final PowerVmSelectionPolicy fallbackPolicy) {
this.fallbackPolicy = fallbackPolicy; this.fallbackPolicy = fallbackPolicy;
} }
......
...@@ -11,14 +11,12 @@ package org.cloudbus.cloudsim.util; ...@@ -11,14 +11,12 @@ package org.cloudbus.cloudsim.util;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import flanagan.analysis.Regression; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import flanagan.analysis.Stat; import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
import org.apache.commons.math3.stat.regression.SimpleRegression;
/** /**
* A class containing multiple convenient math functions. To use some of the function you must * A class containing multiple convenient math functions.
* download Michael Thomas Flanagan's Java Scientific Library:
*
* http://www.ee.ucl.ac.uk/~mflanaga/java/
* *
* @author Anton Beloglazov * @author Anton Beloglazov
* @since CloudSim Toolkit 3.0 * @since CloudSim Toolkit 3.0
...@@ -31,7 +29,7 @@ public class MathUtil { ...@@ -31,7 +29,7 @@ public class MathUtil {
* @param list the list * @param list the list
* @return the double * @return the double
*/ */
public static double sum(List<? extends Number> list) { public static double sum(final List<? extends Number> list) {
double sum = 0; double sum = 0;
for (Number number : list) { for (Number number : list) {
sum += number.doubleValue(); sum += number.doubleValue();
...@@ -45,7 +43,7 @@ public class MathUtil { ...@@ -45,7 +43,7 @@ public class MathUtil {
* @param list the list * @param list the list
* @return the double[] * @return the double[]
*/ */
public static double[] listToArray(List<? extends Number> list) { public static double[] listToArray(final List<? extends Number> list) {
double[] array = new double[list.size()]; double[] array = new double[list.size()];
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
array[i] = list.get(i).doubleValue(); array[i] = list.get(i).doubleValue();
...@@ -59,8 +57,54 @@ public class MathUtil { ...@@ -59,8 +57,54 @@ public class MathUtil {
* @param list the list * @param list the list
* @return the median * @return the median
*/ */
public static double median(List<Double> list) { public static double median(final List<Double> list) {
return Stat.median(listToArray(list)); return getStatistics(list).getPercentile(50);
}
/**
* Gets the median.
*
* @param list the list
*
* @return the median
*/
public static double median(final double[] list) {
return getStatistics(list).getPercentile(50);
}
/**
* Returns descriptive statistics for the list of numbers.
*
* @param list
* - the list of numbers. Must not be null.
* @return - descriptive statistics for the list of numbers.
*/
public static DescriptiveStatistics getStatistics(final List<Double> list) {
// Get a DescriptiveStatistics instance
DescriptiveStatistics stats = new DescriptiveStatistics();
// Add the data from the array
for (Double d : list) {
stats.addValue(d);
}
return stats;
}
/**
* Returns descriptive statistics for the array of numbers.
*
* @param list - the array of numbers. Must not be null.
* @return - descriptive statistics for the array of numbers.
*/
public static DescriptiveStatistics getStatistics(final double[] list) {
// Get a DescriptiveStatistics instance
DescriptiveStatistics stats = new DescriptiveStatistics();
// Add the data from the array
for (int i = 0; i < list.length; i++) {
stats.addValue(list[i]);
}
return stats;
} }
/** /**
...@@ -70,7 +114,7 @@ public class MathUtil { ...@@ -70,7 +114,7 @@ public class MathUtil {
* *
* @return the average * @return the average
*/ */
public static double mean(List<Double> list) { public static double mean(final List<Double> list) {
double sum = 0; double sum = 0;
for (Double number : list) { for (Double number : list) {
sum += number; sum += number;
...@@ -84,7 +128,7 @@ public class MathUtil { ...@@ -84,7 +128,7 @@ public class MathUtil {
* @param list the list * @param list the list
* @return the double * @return the double
*/ */
public static double variance(List<Double> list) { public static double variance(final List<Double> list) {
long n = 0; long n = 0;
double mean = mean(list); double mean = mean(list);
double s = 0.0; double s = 0.0;
...@@ -106,7 +150,7 @@ public class MathUtil { ...@@ -106,7 +150,7 @@ public class MathUtil {
* @param list the list * @param list the list
* @return the double * @return the double
*/ */
public static double stDev(List<Double> list) { public static double stDev(final List<Double> list) {
return Math.sqrt(variance(list)); return Math.sqrt(variance(list));
} }
...@@ -116,15 +160,15 @@ public class MathUtil { ...@@ -116,15 +160,15 @@ public class MathUtil {
* @param data the data * @param data the data
* @return the mad * @return the mad
*/ */
public static double mad(double[] data) { public static double mad(final double[] data) {
double mad = 0; double mad = 0;
if (data.length > 0) { if (data.length > 0) {
double median = Stat.median(data); double median = median(data);
double[] deviationSum = new double[data.length]; double[] deviationSum = new double[data.length];
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
deviationSum[i] = Math.abs(median - data[i]); deviationSum[i] = Math.abs(median - data[i]);
} }
mad = Stat.median(deviationSum); mad = median(deviationSum);
} }
return mad; return mad;
} }
...@@ -135,7 +179,7 @@ public class MathUtil { ...@@ -135,7 +179,7 @@ public class MathUtil {
* @param data the data * @param data the data
* @return the IQR * @return the IQR
*/ */
public static double iqr(double[] data) { public static double iqr(final double[] data) {
Arrays.sort(data); Arrays.sort(data);
int q1 = (int) Math.round(0.25 * (data.length + 1)) - 1; int q1 = (int) Math.round(0.25 * (data.length + 1)) - 1;
int q3 = (int) Math.round(0.75 * (data.length + 1)) - 1; int q3 = (int) Math.round(0.75 * (data.length + 1)) - 1;
...@@ -148,7 +192,7 @@ public class MathUtil { ...@@ -148,7 +192,7 @@ public class MathUtil {
* @param data the data * @param data the data
* @return the int * @return the int
*/ */
public static int countNonZeroBeginning(double[] data) { public static int countNonZeroBeginning(final double[] data) {
int i = data.length - 1; int i = data.length - 1;
while (i >= 0) { while (i >= 0) {
if (data[i--] != 0) { if (data[i--] != 0) {
...@@ -164,7 +208,7 @@ public class MathUtil { ...@@ -164,7 +208,7 @@ public class MathUtil {
* @param data the data * @param data the data
* @return the int * @return the int
*/ */
public static int countShortestRow(double[][] data) { public static int countShortestRow(final double[][] data) {
int minLength = 0; int minLength = 0;
for (double[] row : data) { for (double[] row : data) {
if (row.length < minLength) { if (row.length < minLength) {
...@@ -180,7 +224,7 @@ public class MathUtil { ...@@ -180,7 +224,7 @@ public class MathUtil {
* @param data the data * @param data the data
* @return the double[] * @return the double[]
*/ */
public static double[] trimZeroTail(double[] data) { public static double[] trimZeroTail(final double[] data) {
return Arrays.copyOfRange(data, 0, countNonZeroBeginning(data)); return Arrays.copyOfRange(data, 0, countNonZeroBeginning(data));
} }
...@@ -190,19 +234,58 @@ public class MathUtil { ...@@ -190,19 +234,58 @@ public class MathUtil {
* @param y the y * @param y the y
* @return the loess parameter estimates * @return the loess parameter estimates
*/ */
public static double[] getLoessParameterEstimates(double[] y) { public static double[] getLoessParameterEstimates(final double[] y) {
int n = y.length; int n = y.length;
double[] x = new double[n]; double[] x = new double[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] = i + 1; x[i] = i + 1;
} }
Regression regression = new Regression(x, y, getTricubeWeigts(n)); return createWeigthedLinearRegression(x, y, getTricubeWeigts(n))
regression.linear(); .regress().getParameterEstimates();
double[] estimates = regression.getBestEstimates();
if (estimates[0] == Double.NaN || estimates[1] == Double.NaN) {
return regression.getBestEstimates();
} }
return estimates;
public static SimpleRegression createLinearRegression(final double[] x,
final double[] y) {
SimpleRegression regression = new SimpleRegression();
for (int i = 0; i < x.length; i++) {
regression.addData(x[i], y[i]);
}
return regression;
}
public static OLSMultipleLinearRegression createLinearRegression(
final double[][] x, final double[] y) {
OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
regression.newSampleData(y, x);
return regression;
}
public static SimpleRegression createWeigthedLinearRegression(
final double[] x, final double[] y, final double[] weigths) {
double[] xW = new double[x.length];
double[] yW = new double[y.length];
// As to Flanagan's documentation they perform weigthed regression if the
// number or non-zero weigths is more than 40%
int numZeroWeigths = 0;
for (int i = 0; i < weigths.length; i++) {
if (weigths[i] <= 0) {
numZeroWeigths++;
}
}
for (int i = 0; i < x.length; i++) {
if (numZeroWeigths >= 0.4 * weigths.length) {
// See: http://www.ncsu.edu/crsc/events/ugw07/Presentations/Crooks_Qiao/Crooks_Qiao_Alt_Presentation.pdf
xW[i] = Math.sqrt(weigths[i]) * x[i];
yW[i] = Math.sqrt(weigths[i]) * y[i];
} else {
xW[i] = x[i];
yW[i] = y[i];
}
}
return createLinearRegression(xW, yW);
} }
/** /**
...@@ -211,19 +294,25 @@ public class MathUtil { ...@@ -211,19 +294,25 @@ public class MathUtil {
* @param y the y * @param y the y
* @return the robust loess parameter estimates * @return the robust loess parameter estimates
*/ */
public static double[] getRobustLoessParameterEstimates(double[] y) { public static double[] getRobustLoessParameterEstimates(final double[] y) {
int n = y.length; int n = y.length;
double[] x = new double[n]; double[] x = new double[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] = i + 1; x[i] = i + 1;
} }
Regression regression = new Regression(x, y, getTricubeWeigts(n)); SimpleRegression tricubeRegression = createWeigthedLinearRegression(x,
regression.linear(); y, getTricubeWeigts(n));
Regression regression2 = new Regression(x, y, getTricubeBisquareWeigts(regression.getResiduals())); double[] residuals = new double[n];
regression2.linear(); for (int i = 0; i < n; i++) {
double[] estimates = regression2.getBestEstimates(); residuals[i] = y[i] - tricubeRegression.predict(x[i]);
}
SimpleRegression tricubeBySquareRegression = createWeigthedLinearRegression(
x, y, getTricubeBisquareWeigts(residuals));
double[] estimates = tricubeBySquareRegression.regress()
.getParameterEstimates();
if (estimates[0] == Double.NaN || estimates[1] == Double.NaN) { if (estimates[0] == Double.NaN || estimates[1] == Double.NaN) {
return regression.getBestEstimates(); return tricubeRegression.regress().getParameterEstimates();
} }
return estimates; return estimates;
} }
...@@ -234,7 +323,7 @@ public class MathUtil { ...@@ -234,7 +323,7 @@ public class MathUtil {
* @param n the n * @param n the n
* @return the tricube weigts * @return the tricube weigts
*/ */
public static double[] getTricubeWeigts(int n) { public static double[] getTricubeWeigts(final int n) {
double[] weights = new double[n]; double[] weights = new double[n];
double top = n - 1; double top = n - 1;
double spread = top; double spread = top;
...@@ -256,11 +345,11 @@ public class MathUtil { ...@@ -256,11 +345,11 @@ public class MathUtil {
* @param residuals the residuals * @param residuals the residuals
* @return the tricube bisquare weigts * @return the tricube bisquare weigts
*/ */
public static double[] getTricubeBisquareWeigts(double[] residuals) { public static double[] getTricubeBisquareWeigts(final double[] residuals) {
int n = residuals.length; int n = residuals.length;
double[] weights = getTricubeWeigts(n); double[] weights = getTricubeWeigts(n);
double[] weights2 = new double[n]; double[] weights2 = new double[n];
double s6 = Stat.median(abs(residuals)) * 6; double s6 = median(abs(residuals)) * 6;
for (int i = 2; i < n; i++) { for (int i = 2; i < n; i++) {
double k = Math.pow(1 - Math.pow(residuals[i] / s6, 2), 2); double k = Math.pow(1 - Math.pow(residuals[i] / s6, 2), 2);
if (k > 0) { if (k > 0) {
...@@ -279,7 +368,7 @@ public class MathUtil { ...@@ -279,7 +368,7 @@ public class MathUtil {
* @param data the data * @param data the data
* @return the double[] * @return the double[]
*/ */
public static double[] abs(double[] data) { public static double[] abs(final double[] data) {
double[] result = new double[data.length]; double[] result = new double[data.length];
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
result[i] = Math.abs(data[i]); result[i] = Math.abs(data[i]);
......
...@@ -17,6 +17,16 @@ ...@@ -17,6 +17,16 @@
<build> <build>
<plugins> <plugins>
<!-- Sets the version of the code -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin> <plugin>
<inherited>true</inherited> <inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
...@@ -49,10 +59,11 @@ ...@@ -49,10 +59,11 @@
<artifactId>easymockclassextension</artifactId> <artifactId>easymockclassextension</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.flanagan</groupId> <groupId>org.apache.commons</groupId>
<artifactId>flanagan</artifactId> <artifactId>commons-math3</artifactId>
<version>1.0</version> <version>3.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment