Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

.DS_STORE
/wekiLib/

# Created by https://www.gitignore.io/api/emacs
Expand Down
17 changes: 14 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ else()
add_compile_options(-std=c++20 -O2)
endif()

option(RAPIDLIB_DISABLE_JSONCPP "Disable jsoncpp integration." OFF)
if(EMSCRIPTEN)
set(RAPIDLIB_DISABLE_JSONCPP ON)
endif()

# Threads
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
Expand All @@ -28,16 +33,21 @@ file(GLOB JSON_SRC "${PROJECT_SOURCE_DIR}/dependencies/jsoncpp.cpp")
file(GLOB BAYES_SRC "${PROJECT_SOURCE_DIR}/dependencies/bayesfilter/src/*.cpp")

# Set the source for the main library, using the groups defined above
set(RAPIDLIB_FULL_SRC
set(RAPIDLIB_FULL_SRC
${RAPIDLIB_SRC}
${RAPIDLIB_DEP}
${JSON_SRC}
${BAYES_SRC}
)
)

add_library(${PROJECT_NAME} SHARED ${RAPIDLIB_FULL_SRC})
add_executable(rapidLibTest test/rapidLibTest.cpp)

if(RAPIDLIB_DISABLE_JSONCPP)
target_compile_definitions(${PROJECT_NAME} PUBLIC RAPIDLIB_DISABLE_JSONCPP)
else()
target_sources(${PROJECT_NAME} PRIVATE ${JSON_SRC})
endif()

#include(GenerateExportHeader)
#generate_export_header(${PROJECT_NAME})

Expand All @@ -46,3 +56,4 @@ target_link_libraries(rapidLibTest Threads::Threads)

enable_testing()
add_test(rapidLibTest rapidLibTest)

4 changes: 2 additions & 2 deletions dependencies/jsoncpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1767,8 +1767,8 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
++current;
// TODO: Help the compiler do the div and mod at compile time or get rid of them.
Value::LargestUInt maxIntegerValue =
isNegative ? Value::LargestUInt(-Value::minLargestInt)
: Value::maxLargestUInt;
isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
: Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
while (current < token.end_) {
Expand Down
4 changes: 2 additions & 2 deletions src/baseModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <vector>
#include "trainingExample.h"

#ifndef EMSCRIPTEN
#ifndef RAPIDLIB_DISABLE_JSONCPP
#include "../dependencies/json/json.h"
#endif

Expand Down Expand Up @@ -49,7 +49,7 @@ class baseModel
virtual size_t getNumInputs() const = 0;
virtual std::vector<size_t> getWhichInputs() const = 0;

#ifndef EMSCRIPTEN
#ifndef RAPIDLIB_DISABLE_JSONCPP
virtual void getJSONDescription(Json::Value& currentModel) = 0;

protected:
Expand Down
35 changes: 20 additions & 15 deletions src/classification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
// Copyright © 2016 Goldsmiths. All rights reserved.
//

#include "classification.h"

#include <stdexcept>
#include <vector>
#include "classification.h"
#ifdef EMSCRIPTEN
#include "emscripten/classificationEmbindings.h"
#endif
Expand Down Expand Up @@ -69,36 +70,39 @@ bool classificationTemplate<T>::train(const std::vector<trainingExampleTemplate<
if (training_set.size() > 0)
{
//create model(s) here
modelSet<T>::numInputs = int(training_set[0].input.size());
modelSet<T>::numOutputs = int(training_set[0].output.size());
for (int i = 0; i < modelSet<T>::numInputs; ++i)
modelSet<T>::numInputs = static_cast<int>(training_set[0].input.size());
modelSet<T>::numOutputs = static_cast<int>(training_set[0].output.size());

for (int i {}; i < modelSet<T>::numInputs; ++i)
{
modelSet<T>::inputNames.push_back("inputs-" + std::to_string(i + 1));
}
modelSet<T>::numOutputs = int(training_set[0].output.size());

for ( auto example : training_set)

modelSet<T>::numOutputs = static_cast<int>(training_set[0].output.size());

for (const auto& example : training_set)
{
if (example.input.size() != modelSet<T>::numInputs)
{
throw std::length_error("unequal feature vectors in input.");
return false;
}

if (example.output.size() != modelSet<T>::numOutputs)
{
throw std::length_error("unequal output vectors.");
return false;
}
}
std::vector<size_t> whichInputs;

for (int j = 0; j < modelSet<T>::numInputs; ++j)

std::vector<size_t> whichInputs {};

for (int inputNum {}; inputNum < modelSet<T>::numInputs; ++inputNum)
{
whichInputs.push_back(j);
whichInputs.push_back(inputNum);
}

for (int i = 0; i < modelSet<T>::numOutputs; ++i)
for (int outputNum {}; outputNum < modelSet<T>::numOutputs; ++outputNum)
{
if (classificationType == svm)
{
Expand All @@ -118,12 +122,13 @@ bool classificationTemplate<T>::train(const std::vector<trainingExampleTemplate<
template<typename T>
std::vector<int> classificationTemplate<T>::getK()
{
std::vector<int> kVector;
std::vector<int> kVector {};

for (const baseModel<T>* model : modelSet<T>::myModelSet)
{
kVector.push_back(dynamic_cast<const knnClassification<T>*>(model)->getK()); //FIXME: I really dislike this design
}

return kVector;
}

Expand Down
96 changes: 54 additions & 42 deletions src/dtw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,28 @@ dtw<T>::~dtw() {};
template<typename T>
inline T dtw<T>::distanceFunction(const std::vector<T> &x, const std::vector<T> &y)
{
double euclidianDistance = 0;
double euclidianDistance {};

if (x.size() != y.size())
{
throw std::length_error("comparing different length series");
}
else
{
for (std::size_t i = 0; i < x.size(); ++i)
for (std::size_t i {}; i < x.size(); ++i)
{
euclidianDistance = euclidianDistance + pow((x[i] - y[i]), 2);
euclidianDistance += std::pow((x[i] - y[i]), 2);
}

euclidianDistance = sqrt(euclidianDistance);
}
return (T)euclidianDistance;

return static_cast<T>(euclidianDistance);
};

/* Just returns the cost, doesn't calculate the path */
template<typename T>
T dtw<T>::getCost(const std::vector<std::vector<T> > &seriesX, const std::vector<std::vector<T> > &seriesY)
T dtw<T>::getCost(const std::vector<std::vector<T>>& seriesX, const std::vector<std::vector<T>>& seriesY)
{
if (seriesX.size() < seriesY.size()) return getCost(seriesY, seriesX);

Expand All @@ -53,71 +55,73 @@ T dtw<T>::getCost(const std::vector<std::vector<T> > &seriesX, const std::vector

//Calculate values for the first column
costMatrix[0][0] = distanceFunction(seriesX[0], seriesY[0]);
for (int j = 1; j <= maxY; ++j)
for (int y { 1 }; y <= maxY; ++y)
{
costMatrix[0][j] = costMatrix[0][j - 1] + distanceFunction(seriesX[0], seriesY[j]);
costMatrix[0][y] = costMatrix[0][y - 1] + distanceFunction(seriesX[0], seriesY[y]);
}

for (std::size_t i = 1; i <= maxX; ++i)
for (std::size_t x { 1 }; x <= maxX; ++x)
{
//Bottom row of current column
costMatrix[i][0] = costMatrix[i - 1][0] + distanceFunction(seriesX[i], seriesY[0]);
for (std::size_t j = 1; j <= maxY; ++j)
costMatrix[x][0] = costMatrix[x - 1][0] + distanceFunction(seriesX[x], seriesY[0]);

for (std::size_t y { 1 }; y <= maxY; ++y)
{
T minGlobalCost = fmin(costMatrix[i-1][j-1], costMatrix[i][j-1]);
costMatrix[i][j] = minGlobalCost + distanceFunction(seriesX[i], seriesY[j]);
T minGlobalCost { (std::min(costMatrix[x - 1][y - 1], costMatrix[x][y - 1])) };
costMatrix[x][y] = minGlobalCost + distanceFunction(seriesX[x], seriesY[y]);
}
}

return costMatrix[maxX][maxY];
};

template<typename T>
warpPath dtw<T>::calculatePath(std::size_t seriesXsize, std::size_t seriesYsize) const
{
warpPath warpPath;
std::size_t i { seriesXsize - 1 };
std::size_t j { seriesYsize - 1 };
warpPath.add(i, j);
while ((i > 0) || (j > 0))
std::size_t x { seriesXsize - 1 };
std::size_t y { seriesYsize - 1 };
warpPath.add(x, y);

while ((x > 0) || (y > 0))
{
T diagonalCost = ((i > 0) && (j > 0)) ? costMatrix[i - 1][j - 1] : std::numeric_limits<T>::infinity();
T leftCost = (i > 0) ? costMatrix[i - 1][j] : std::numeric_limits<T>::infinity();
T downCost = (j > 0) ? costMatrix[i][j - 1] : std::numeric_limits<T>::infinity();
T diagonalCost { ((x > 0) && (y > 0)) ? costMatrix[x - 1][y - 1] : std::numeric_limits<T>::infinity() };
T leftCost { (x > 0) ? costMatrix[x - 1][y] : std::numeric_limits<T>::infinity() };
T downCost { (y > 0) ? costMatrix[x][y - 1] : std::numeric_limits<T>::infinity() };

if ((diagonalCost <= leftCost) && (diagonalCost <= downCost))
{
if (i > 0) --i;
if (j > 0) --j;
if (x > 0) --x;
if (y > 0) --y;
}
else if ((leftCost < diagonalCost) && (leftCost < downCost))
{
--i;
--x;
}
else if ((downCost < diagonalCost) && (downCost < leftCost))
{
--j;
--y;
}
else if (i <= j)
else if (x <= y)
{
--j;
--y;
}
else
{
--i;
--x;
}
warpPath.add(i, j);
warpPath.add(x, y);
}

return warpPath;
};

/* calculates both the cost and the warp path*/
template<typename T>
warpInfo<T> dtw<T>::dynamicTimeWarp(const std::vector<std::vector<T> > &seriesX, const std::vector<std::vector<T> > &seriesY)
warpInfo<T> dtw<T>::dynamicTimeWarp(const std::vector<std::vector<T>>& seriesX, const std::vector<std::vector<T>>& seriesY)
{
warpInfo<T> info;
warpInfo<T> info {};

//calculate cost matrix
info.cost = getCost(seriesX, seriesY);
info.path = calculatePath(seriesX.size(), seriesY.size());
Expand All @@ -132,26 +136,34 @@ warpInfo<T> dtw<T>::constrainedDTW(const std::vector<std::vector<T> > &seriesX,
costMatrix.clear();
std::vector<T> tempVector(seriesY.size(), std::numeric_limits<T>::max());
costMatrix.assign(seriesX.size(), tempVector); //TODO: this could be smaller, since most cells are unused
std::size_t maxX = seriesX.size() - 1;
std::size_t maxY = seriesY.size() - 1;
std::size_t maxX { seriesX.size() - 1 };
std::size_t maxY { seriesY.size() - 1 };

//fill cost matrix cells based on window
for (std::size_t currentX = 0; currentX < window.minMaxValues.size(); ++currentX)
for (std::size_t currentX {}; currentX < window.minMaxValues.size(); ++currentX)
{
for (std::size_t currentY = window.minMaxValues[currentX].first; currentY <= window.minMaxValues[currentX].second; ++currentY) //FIXME: should be <= ?
for (std::size_t currentY { window.minMaxValues[currentX].first }; currentY <= window.minMaxValues[currentX].second; ++currentY) //FIXME: should be <= ?
{
if (currentX == 0 && currentY == 0) { //bottom left cell
if (currentX == 0 && currentY == 0) //bottom left cell
{
costMatrix[0][0] = distanceFunction(seriesX[0], seriesY[0]);
} else if (currentX == 0) { //first column
}
else if (currentX == 0) //first column
{
costMatrix[0][currentY] = distanceFunction(seriesX[0], seriesY[currentY]) + costMatrix[0][currentY - 1];
} else if (currentY == 0) { //first row
}
else if (currentY == 0) //first row
{
costMatrix[currentX][0] = distanceFunction(seriesX[currentX], seriesY[0]) + costMatrix[currentX - 1][0];
} else {
T minGlobalCost = fmin(costMatrix[currentX - 1][currentY], fmin(costMatrix[currentX-1][currentY-1], costMatrix[currentX][currentY-1]));
}
else
{
T minGlobalCost { std::min(costMatrix[currentX - 1][currentY], std::min(costMatrix[currentX-1][currentY-1], costMatrix[currentX][currentY-1])) };
costMatrix[currentX][currentY] = distanceFunction(seriesX[currentX], seriesY[currentY]) + minGlobalCost;
}
}
}

warpInfo<T> info;
info.cost = costMatrix[maxX][maxY];
info.path = calculatePath(seriesX.size(), seriesY.size());
Expand Down
Loading