SimpleTimeSeries class
package com.sleptons.common;
public class SimpleTimeSeries {
/**
* these are the maximum raw values you may send for time and value of a
* time series. a maxRawValue of 100,000 means don't you have time series
* value more than 100,000 if you have, we set it to 100,000 a maxRawTime of
* 1339 for a period means your period has data samples from 0 to 1339 or
* 1440 sample data. so if you consider the period as a day, then 1440
* sample per day means one sample per minute.
*/
private double maxRawValue = 100000;
private int maxRawTime = 1439;
/**
* these are the maximum model values for you need your model use to build
* the network. a maxModelValue of 9 for time series values means the model
* maps the maxRawValue to 9, in another words it divides the y axis to 10
* unit. a maximum value of 23 means your model time axis resolution is
* hour. note that you don't need a high resolution for both time and value
* axes.
*/
private int maxModelValue = 9;
private int maxMoldeTime = 23;
/**
* since the model is simple we keep the network's edge scores in a two
* dimensional array.
*/
private double[][] scores = null;
/**
* setMaxRawValue sets the maximum raw value of the time series
*
* @param maxRawValue
* is the model's maximum raw value of the time series
* @return the object itself
*/
public SimpleTimeSeries setMaxRawValue(double maxRawValue) {
this.maxRawValue = maxRawValue;
return this;
}
/**
* sets the maximum raw value of the time series value for the model
*
* @param maxRawTime
* is the model's maximum raw value of the time
* @return the object itself
*/
public SimpleTimeSeries setMaxRawTime(int maxRawTime) {
this.maxRawTime = maxRawTime;
return this;
}
/**
* sets the maximum value of the time series value for the model
*
* @param maxModelValue
* is the model's maximum value of the time series
* @return the object itself
*/
public SimpleTimeSeries setMaxModelValue(int maxModelValue) {
this.maxModelValue = maxModelValue;
return this;
}
/**
* sets the maximum value of time for the model
*
* @param maxMoldeTime
* is the model's maximum value of the time
* @return the object itself
*/
public SimpleTimeSeries setMaxMoldeTimePoints(int maxMoldeTime) {
this.maxMoldeTime = maxMoldeTime;
return this;
}
/**
* trains the network by increasing the score of the given point by one
*
* @param rawTimePoint
* is the time index in period
* @param rawValue
* is the value of the time series at the given time
* @return the object itself
*/
public SimpleTimeSeries train(int rawTimePoint, double rawValue) {
if (this.scores == null) {
initNetwork();
}
int modelValue = getModeValue(rawValue);
int modelTime = getModelTime(rawTimePoint);
this.scores[modelTime][modelValue] += 1;
return this;
}
/**
* trains the network form the given complete period of sample data, if you
* send wrong number of sample data it doesn't train the network
*
* @param rawValuesOfAPeriod
* is the an array of doubles for whole period data
* @return the object itself
*/
public SimpleTimeSeries train(double[] rawValuesOfAPeriod) {
if (rawValuesOfAPeriod.length == (this.maxMoldeTime + 1)) {
for (int i = 0; i < rawValuesOfAPeriod.length; i++) {
this.train(i, rawValuesOfAPeriod[i]);
}
}
return this;
}
/**
* returns the probability of having the given point in the stored network
*
* @param rawTime
* is the raw time index in period
* @param rawValue
* is the raw value of the time series at the given time
* @return the probability of having the point in network
*/
public double getProbability(int rawTime, double rawValue) {
if (this.scores == null || rawTime < 0 || rawValue < 0) {
return 0;
}
int modelValue = getModeValue(rawValue);
int modelTime = getModelTime(rawTime);
double p = 0;
int sum = 0;
for (int i = 0; i < this.maxModelValue; i++) {
sum += this.scores[modelTime][i];
}
if (sum != 0) {
p = this.scores[modelTime][modelValue] / sum;
}
return p;
}
/**
* gets the probability of having the given point in the stored network
*
* @param modelTime
* is the model time index in period
* @param modelValue
* is the model value of the time series at the given time
* @return the probability of having the point in network
*/
private double getModelProbability(int modelTime, int modelValue) {
if (this.scores == null || modelTime < 0 || modelTime > this.maxMoldeTime || modelValue < 0
|| modelValue > this.maxModelValue) {
return 0;
}
double p = 0;
int sum = 0;
for (int i = 0; i < this.maxModelValue; i++) {
sum += this.scores[modelTime][i];
}
if (sum != 0) {
p = this.scores[modelTime][modelValue] / sum;
}
return p;
}
/**
* returns all possible model points for the given raw time
*
* @param rawTime
* is the raw time index in period
* @return the possible model values as an array
*/
public ModelPoint[] getAllPossibleValues(int rawTime) {
int modelTime = getModelTime(rawTime);
int count = 0;
for (int i = 0; i < this.maxModelValue; i++) {
if (this.scores[modelTime][i] > 0) {
count += 1;
}
}
ModelPoint[] possibleValues = null;
if (count > 0) {
possibleValues = new ModelPoint[count];
count = 0;
for (int i = 0; i < this.maxModelValue; i++) {
if (this.scores[modelTime][i] > 0) {
possibleValues[count] = new ModelPoint();
possibleValues[count].time = modelTime;
possibleValues[count].value = i;
possibleValues[count].probability = this.getModelProbability(modelTime, i);
count += 1;
}
}
}
return possibleValues;
}
/**
* initialize the network and sets all scores to zero
*
* @param rawValue
* is the value of the time series
* @return the model value index
*/
private void initNetwork() {
this.scores = new double[this.maxMoldeTime + 1][this.maxModelValue + 1];
for (int i = 0; i < this.maxMoldeTime + 1; i++) {
for (int j = 0; j < this.maxModelValue; j++) {
this.scores[i][j] = 0;
}
}
}
/**
* converts the given raw value to the model value to put it in network
*
* @param rawValue
* is the value of the time series
* @return the model value index
*/
private int getModeValue(double rawValue) {
if (rawValue > this.maxRawValue) {
rawValue = this.maxRawValue;
}
if (rawValue < 0) {
rawValue = 0;
}
return (int) (rawValue * (this.maxModelValue) / this.maxRawValue);
}
/**
* converts the given raw time to model time to put it in network
*
* @param rawTimePoint
* is the time index in period
* @return the model time index
*/
private int getModelTime(int rawTime) {
rawTime = rawTime % this.maxRawTime;
return (rawTime * this.maxMoldeTime) / this.maxRawTime;
}
/**
* a class to hold a model point time, value and probability
*
*/
public class ModelPoint {
int time;
int value;
double probability;
public String toString() {
return "[ time:" + this.time + " , value:" + this.value + " , probability: " + this.probability + " ]";
}
}
}
package com.sleptons.common;
import com.sleptons.common.SimpleTimeSeries.ModelPoint;
public class Test {
// simply set sampleCountPerHour to the number of the samples you want in an
// hour, defiantly not more than 60. if you set it to 60 the maxRawTime will
// be 1439 or 1440 sample per day. you can manually set maxRawTime to any
// value, there is no need to consider it as a day.
private final static int sampleCountPerHour = 12;
private final static int maxRawTime = 24 * sampleCountPerHour - 1;
// it should be the maximum value your time series may take
private final static double maxRawValue = 200;
private SimpleTimeSeries simpleTimeSeries = new SimpleTimeSeries();
// this is just a function that generates data for training the network, you
// can consider it as your time series function. it is a simple sinusoidal
// function, the first parameter is the raw time index and the second one is
// for making some modification the out put of the function.
private double myTimeSeriesFunction(int rawTime, int timeShift) {
return 100 + 80 * Math.sin(2 * Math.PI * (rawTime + timeShift) / Test.maxRawTime);
}
void testPoint(int testTime, double testValue) {
System.out.print("time: " + testTime + " , value: " + testValue + " => ");
System.out.println("probability: " + simpleTimeSeries.getProbability(testTime, testValue));
}
public static void main(String[] args) {
Test test = new Test();
test.simpleTimeSeries.setMaxRawTime(Test.maxRawTime).setMaxRawValue(Test.maxRawValue);
// train the first period
for (int t = 0; t < Test.maxRawTime + 1; t++) {
test.simpleTimeSeries.train(t, test.myTimeSeriesFunction(t, 0));
}
// train the second period
for (int t = 0; t < Test.maxRawTime + 1; t++) {
test.simpleTimeSeries.train(t, test.myTimeSeriesFunction(t, 5));
}
// train the third period
for (int t = 0; t < Test.maxRawTime + 1; t++) {
test.simpleTimeSeries.train(t, test.myTimeSeriesFunction(t, -5));
}
// matched points with the stored network
test.testPoint(20, test.myTimeSeriesFunction(20, 0));
test.testPoint(20, test.myTimeSeriesFunction(20, 3));
test.testPoint(20, test.myTimeSeriesFunction(20, 5));
test.testPoint(20, test.myTimeSeriesFunction(20, 0) + 10);
// not matched points with the stored network
test.testPoint(20, 0);
test.testPoint(20, test.myTimeSeriesFunction(20, 30));
test.testPoint(20, test.myTimeSeriesFunction(20, 0) * 2);
ModelPoint[] modelPointes = test.simpleTimeSeries.getAllPossibleValues(20);
for (ModelPoint mp : modelPointes) {
System.out.println(mp.toString());
}
}
}