datatypes/time_series_strategies.hpp¶
Namespaces¶
Name |
---|
datatypes |
datatypes::timeseries |
Classes¶
Name | |
---|---|
class | datatypes::timeseries::StoragePolicy An interface for classes that can handle the storage of data for time series. |
class | datatypes::timeseries::MissingValuePolicy An interface for classes that define missing values in time series. |
class | datatypes::timeseries::DefaultMissingFloatingPointPolicy |
class | datatypes::timeseries::NullPointerIsMissingPolicy |
class | datatypes::timeseries::NegativeIsMissingFloatingPointPolicy |
class | datatypes::timeseries::StlVectorStorage Storage policy; data items are stored in standard template library std::vector. |
class | datatypes::timeseries::SharedVectorStorage A storage strategy for time serie such that data is a shared state amongst several time series. |
class | datatypes::timeseries::MemoryCachingStorageWriter |
class | datatypes::timeseries::EnsembleStoragePolicy An interface for classes that can handle the storage of data for ensemble time series. |
class | datatypes::timeseries::StdVectorEnsembleStoragePolicy std::vector based storage policy |
Source code¶
#pragma once
//#include "boost/date_time/posix_time/posix_time.hpp"
#include <boost/function.hpp>
#include "datatypes/common.h"
#include "datatypes/exception_utilities.h"
#include <iterator>
namespace datatypes
{
namespace timeseries
{
template <typename T>
class StoragePolicy :
public TimeSeriesInfoProvider
{
protected:
StoragePolicy(const StoragePolicy& src)
{
}
StoragePolicy() {}
public:
virtual ~StoragePolicy() {}
virtual void CopyTo(vector<T>& dest, size_t from = 0, size_t to = -1) const = 0;
virtual size_t Size() const = 0;
virtual void Allocate(size_t length, T value) = 0;
virtual void AllocateValues(size_t length, const T* values) = 0;
virtual void AllocateValues(const vector<T>& values) = 0;
virtual const T& operator[](const size_t i) const = 0;
virtual T& operator[](const size_t i) = 0;
virtual StoragePolicy* Clone() const = 0;
virtual void CopyTo(StoragePolicy<T>& dest)
{
vector<T> x;
this->CopyTo(x);
dest.SetStart(this->GetStart());
dest.SetTimeStep(this->GetTimeStep());
dest.AllocateValues(x);
}
virtual bool ReadOnly() { return false; }
virtual TimeStep GetTimeStep() const = 0;
virtual ptime GetStart() const = 0;
virtual void SetTimeStep(const TimeStep& tStep) = 0;
virtual void SetStart(const ptime & start) = 0;
};
template <typename T>
class MissingValuePolicy
{
public:
virtual ~MissingValuePolicy() {}
virtual bool IsMissingValue(const T& a) const = 0;
virtual T GetMissingValue() const = 0;
virtual MissingValuePolicy* Clone() const = 0;
};
template <typename T = double>
class DefaultMissingFloatingPointPolicy
: public MissingValuePolicy<T>
{
private:
const T missingValue = (T)(DEFAULT_MISSING_DATA_VALUE);
public:
inline bool IsMissingValue(const T& a) const { return (a == missingValue); };
inline T GetMissingValue() const { return missingValue; };
MissingValuePolicy<T>* Clone() const { return new DefaultMissingFloatingPointPolicy<T>(); };
};
template <typename T>
class NullPointerIsMissingPolicy
: public MissingValuePolicy<T>
{
public:
inline bool IsMissingValue(const T& a) const { return (a == nullptr); };
inline T GetMissingValue() const { return nullptr; };
MissingValuePolicy<T>* Clone() const { return new NullPointerIsMissingPolicy<T>(); };
};
template <typename T = double>
class NegativeIsMissingFloatingPointPolicy
: public MissingValuePolicy<T>
{
private:
const T missingValue = (T)(DEFAULT_MISSING_DATA_VALUE);
public:
inline bool IsMissingValue(const T& a) const { return (a < T()); };
inline T GetMissingValue() const { return missingValue; };
MissingValuePolicy<T>* Clone() const { return new NegativeIsMissingFloatingPointPolicy<T>(); };
};
template <typename T = double>
class StlVectorStorage
: public StoragePolicy<T>
{
private:
StlVectorStorage(const StlVectorStorage& src) :
StoragePolicy<T>(src)
{
data = src.data;
startDate = src.startDate;
timeStep = src.timeStep;
}
vector<T> data;
void CheckIntervalBounds(const size_t& from, size_t& to) const
{
size_t tsLen = this->Size();
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesInterval(from, to, tsLen);
}
private:
// the temporal information for the time series must be stored here
// to support time series with shared storages. Conceptually not quite satisfying,
// but preferable to shared values with different time series with different temporal
// characteristics, for now.
ptime startDate;
TimeStep timeStep;
public:
StlVectorStorage()
{
}
size_t Size() const { return data.size(); }
size_t GetLength() const
{
return Size();
}
void Allocate(size_t length, T value)
{
data.clear();
data.reserve(length);
data.assign(length, value);
}
void AllocateValues(size_t length, const T* values)
{
data.clear();
data.reserve(length);
data.assign(values, values + length);
}
void AllocateValues(const vector<T>& values)
{
data.clear();
data.reserve(values.size());
data.assign(values.begin(), values.end());
}
void CopyTo(vector<T>& dest, size_t from = 0, size_t to = -1) const
{
CheckIntervalBounds(from, to);
size_t len = (to - from) + 1;
if (dest.size() != len)
{
dest.clear();
dest.resize(len);
};
std::copy(data.begin() + from, data.begin() + to + 1, dest.begin());
}
T& operator[](const size_t i) {
// Add a check on index bounds.
// If performance requires it, we might restrict this check based on whether T is a class or a numeric type
// in a manner similar to DefaultMissingValuePolicyTypeFactory. But prefer safety.
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesIndex(i, data.size(), "i");
T& vRef = data[i];
return vRef;
}
const T& operator[](const size_t i) const {
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesIndex(i, data.size(), "i");
return data[i];
}
StoragePolicy<T>* Clone() const { return new StlVectorStorage<T>(*this); }
TimeStep GetTimeStep() const override
{
return timeStep;
}
ptime GetStart() const override
{
return startDate;
}
void SetTimeStep(const TimeStep& tStep) override
{
timeStep = tStep;
}
void SetStart(const ptime & start) override
{
startDate = start;
}
};
template <typename T = double>
class SharedVectorStorage
: public StoragePolicy<T>
{
private:
SharedVectorStorage(const SharedVectorStorage& src)
{
d = src.d;
}
class SharedData
{
public:
vector<T> data;
ptime startDate;
TimeStep timeStep;
};
using SD = typename SharedVectorStorage<T>::SharedData;
std::shared_ptr<SD> d;
void CheckIntervalBounds(const size_t& from, size_t& to) const
{
size_t tsLen = this->Size();
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesInterval(from, to, tsLen);
}
public:
SharedVectorStorage()
{
d = std::shared_ptr<SD>(new SD());
}
size_t Size() const { return d->data.size(); }
void Allocate(size_t length, T value)
{
d->data.clear();
d->data.reserve(length);
d->data.assign(length, value);
}
void AllocateValues(size_t length, const T* values)
{
d->data.clear();
d->data.reserve(length);
d->data.assign(values, values + length);
}
void AllocateValues(const vector<T>& values)
{
d->data.clear();
d->data.reserve(values.size());
d->data.assign(values.begin(), values.end());
}
void CopyTo(vector<T>& dest, size_t from = 0, size_t to = -1) const
{
size_t tsLen = this->Size();
if (tsLen == 0)
return;
CheckIntervalBounds(from, to);
size_t len = (to - from) + 1;
if (dest.size() != len)
{
dest.clear();
dest.resize(len);
};
std::copy(d->data.begin() + from, d->data.begin() + to + 1, dest.begin());
}
T& operator[](const size_t i) {
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesIndex(i, (d->data).size(), "i");
T& vRef = (d->data)[i];
return vRef;
}
const T& operator[](const size_t i) const {
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesIndex(i, (d->data).size(), "i");
return (d->data)[i];
}
StoragePolicy<T>* Clone() const { return new SharedVectorStorage<T>(*this); }
size_t GetLength() const
{
return Size();
}
TimeStep GetTimeStep() const override
{
return d->timeStep;
}
ptime GetStart() const override
{
return d->startDate;
}
void SetTimeStep(const TimeStep& tStep) override
{
d->timeStep = tStep;
}
void SetStart(const ptime & start) override
{
d->startDate = start;
}
};
template <typename T = double>
class MemoryCachingStorageWriter
: public StoragePolicy<T>
{
protected:
MemoryCachingStorageWriter(const MemoryCachingStorageWriter& src) :
StoragePolicy<T>(src)
{
datatypes::exceptions::ExceptionUtilities::ThrowNotSupported("MemoryCachingStorageWriter", "copy ctor");
}
private:
vector<T> buffer;
size_t bufferSize;
size_t bufferPosition;
void CheckIntervalBounds(const size_t& from, size_t& to) const
{
size_t tsLen = this->Size();
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesInterval(from, to, tsLen);
}
StoragePolicy<T>* wrappedStorage;
public:
MemoryCachingStorageWriter(size_t bufferSize, StoragePolicy<T>* wrappedStorage) :
StoragePolicy<T>(),
bufferSize(bufferSize)
{
if (wrappedStorage == nullptr) datatypes::exceptions::ExceptionUtilities::ThrowInvalidArgument("wrappedStorage must not be a nullptr");
buffer = vector<T>(bufferSize);
bufferPosition = 0;
this->wrappedStorage = wrappedStorage;
}
T& GetWindowItem(size_t i)
{
return buffer[i];
}
T& GetBackendItem(size_t i)
{
return (*wrappedStorage).operator[](i);
}
size_t Size() const { return wrappedStorage->Size(); }
size_t GetLength() const
{
return Size();
}
TimeStep GetTimeStep() const override
{
return wrappedStorage->GetTimeStep();
}
ptime GetStart() const override
{
return wrappedStorage->GetStart();
}
void SetTimeStep(const TimeStep& tStep) override
{
wrappedStorage->SetTimeStep(tStep);
}
void SetStart(const ptime & start) override
{
wrappedStorage->SetStart(start);
}
void ResetBuffer()
{
using U = typename datatypes::utils::DisposeVectorTypeFactory<T>::type;
U::Dispose(buffer);
}
void Allocate(size_t length, T value)
{
ResetBuffer();
buffer = vector<T>(bufferSize);
bufferPosition = 0;
wrappedStorage->Allocate(length, value);
}
void AllocateValues(size_t length, const T* values)
{
//datatypes::exceptions::ExceptionUtilities::ThrowNotSupported("MemoryCachingStorageWriter", "AllocateValues(size_t length, const T* values)");
ResetBuffer();
buffer = vector<T>(bufferSize);
bufferPosition = 0;
wrappedStorage->AllocateValues(length, values);
}
void AllocateValues(const vector<T>& values)
{
ResetBuffer();
buffer = vector<T>(bufferSize);
bufferPosition = 0;
wrappedStorage->AllocateValues(values);
}
void CopyTo(vector<T>& dest, size_t from = 0, size_t to = -1) const
{
wrappedStorage->CopyTo(dest, from, to);
}
private:
void shiftWindow(size_t i)
{
size_t n = std::min(bufferSize, wrappedStorage->Size() - bufferPosition);
for (size_t j = 0; j < bufferSize; j++)
{
(*wrappedStorage).operator[](bufferPosition + j) = buffer[j];
}
//std::copy(buffer.begin(), buffer.begin() + n, data.begin() + bufferPosition);
buffer = vector<T>(bufferSize);
bufferPosition = i / bufferSize;
}
public:
T& operator[](const size_t i) {
// Add a check on index bounds.
// If performance requires it, we might restrict this check based on whether T is a class or a numeric type
// in a manner similar to DefaultMissingValuePolicyTypeFactory. But prefer safety.
datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesIndex(i, wrappedStorage->Size(), "i");
if (i > (this->bufferPosition + this->bufferSize - 1))
shiftWindow(i);
T& vRef = buffer[i % bufferSize];
return vRef;
}
const T& operator[](const size_t i) const {
datatypes::exceptions::ExceptionUtilities::ThrowNotSupported("MemoryCachingStorageWriter", "AllocateValues(size_t length, const T* values)");
//datatypes::exceptions::RangeCheck<size_t>::CheckTimeSeriesIndex(i, wrappedStorage->Size(), "i");
//return data[i];
return buffer[-1];
}
StoragePolicy<T>* Clone() const { return new MemoryCachingStorageWriter<T>(*this); }
};
template <typename TsType>
class EnsembleStoragePolicy
{
public:
typedef typename std::remove_pointer<TsType>::type Type;
typedef typename std::add_pointer<Type>::type PtrType;
typedef typename Type::ElementType ElementType;
EnsembleStoragePolicy() {}
virtual ~EnsembleStoragePolicy() {}
virtual void Reset(const vector<PtrType>& values, const ptime& startDate, const TimeStep& timeStep) = 0;
EnsembleStoragePolicy& operator=(const EnsembleStoragePolicy& src) {
if (&src == this) {
return *this;
}
OperatorEqualImpl(src);
return *this;
}
// ?? virtual EnsembleStoragePolicy& operator=(EnsembleStoragePolicy&& src) = 0;
virtual void ResetSeries(const size_t& numSeries, const size_t& lengthSeries, const ptime& startDate, const TimeStep& timeStep) = 0;
virtual TsType Get(size_t i) = 0;
virtual ElementType Get(size_t i, size_t tsIndex) = 0;
virtual void Set(size_t i, size_t tsIndex, ElementType val) = 0;
virtual void Set(size_t i, const Type& val) = 0;
virtual vector<ElementType*>* GetValues() const = 0;
virtual void CopyTo(ElementType ** dest) const = 0;
virtual size_t Size() const = 0;
virtual size_t GetLength(size_t i) const = 0;
//virtual ptime GetStartDate() const = 0;
//virtual TimeStep GetTimeStep() const = 0;
virtual void Clear() = 0;
virtual const vector<PtrType>& AsReadonlyVector() const = 0;
virtual EnsembleStoragePolicy<TsType>* Clone() const = 0;
protected:
virtual void OperatorEqualImpl(const EnsembleStoragePolicy<TsType>& src) = 0;
};
template <typename TsType>
class StdVectorEnsembleStoragePolicy : public EnsembleStoragePolicy<TsType>
{
public:
typedef typename std::remove_pointer<TsType>::type Type;
typedef typename std::add_pointer<Type>::type PtrType;
typedef typename Type::ElementType ElementType;
private:
vector<PtrType> series;
public:
void Reset(const vector<PtrType>& values, const ptime& startDate, const TimeStep& timeStep)
{
Clear();
for (const PtrType d : values)
{
series.push_back(new Type(*d));
}
}
StdVectorEnsembleStoragePolicy(const StdVectorEnsembleStoragePolicy<TsType>& src)
{
DeepCopyFrom(src);
}
StdVectorEnsembleStoragePolicy()
{
}
~StdVectorEnsembleStoragePolicy()
{
Clear();
}
StdVectorEnsembleStoragePolicy& operator=(StdVectorEnsembleStoragePolicy&& src) {
if (&src == this) {
return *this;
}
std::swap(series, src.series);
return *this;
}
void ResetSeries(const size_t& numSeries, const size_t& lengthSeries, const ptime& startDate, const TimeStep& timeStep)
{
Clear();
for (size_t i = 0; i < numSeries; i++)
{
series.push_back(new Type(lengthSeries, startDate, timeStep));
}
}
TsType Get(size_t i)
{
return TsType(series.at(i));
}
Type Get(size_t i) const
{
return Type(series.at(i));
}
ElementType Get(size_t i, size_t tsIndex)
{
return (*series[i])[tsIndex];
}
void Set(size_t i, size_t tsIndex, ElementType val)
{
PtrType a = series.at(i);
(*a)[tsIndex] = val;
}
void Set(size_t i, const Type& val)
{
PtrType ts = series[i];
*ts = val; // overloaded operator= should do this as expected - tbc
}
vector<ElementType*>* GetValues() const
{
vector<ElementType*>* result = new vector<ElementType*>();
for (auto& d : series)
{
result->push_back(d->GetValues());
}
return result;
}
void CopyTo(ElementType ** dest) const
{
for (size_t i = 0; i < series.size(); i++)
{
dest[i] = series[i]->GetValues();
}
}
size_t Size() const
{
return this->series.size();
}
size_t GetLength(size_t i) const
{
return this->series[i]->GetLength();
}
void Clear()
{
for (auto& d : series)
{
if (d != nullptr) delete d;
}
series.clear();
}
const vector<PtrType>& AsReadonlyVector() const
{
return series;
}
EnsembleStoragePolicy<TsType>* Clone() const { return new StdVectorEnsembleStoragePolicy<TsType>(*this); }
private:
void DeepCopyFrom(const EnsembleStoragePolicy<TsType>& src)
{
Clear();
auto v = src.AsReadonlyVector();
for (size_t i = 0; i < v.size(); i++)
{
Type* copy = new Type(*(v.at(i)));
this->series.push_back(copy);
}
}
protected:
void OperatorEqualImpl(const EnsembleStoragePolicy<TsType>& src)
{
DeepCopyFrom(src);
}
};
}
}
Updated on 2022-08-21 at 18:10:33 +1000