Skip to content
Merged
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
4 changes: 0 additions & 4 deletions benchmarks/src/classic_problems_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,6 @@ class ClassicHMMProblems {
};

class ComparativeBenchmark {
private:
ClassicHMMProblems problems;

public:
template <typename ProblemType>
BenchmarkResults runProblemComparison(ProblemType &problem, int sequence_length) {
Expand Down Expand Up @@ -427,7 +424,6 @@ int main() {
cout << "Fixed random seed (42) for reproducibility" << endl;

ComparativeBenchmark benchmark;
ClassicHMMProblems problems;
vector<BenchmarkResults> results;

// Test different sequence lengths for each problem
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/src/libhmm_vs_hmmlib_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ class HMMLibBenchmark {
// Benchmark Viterbi
vector<unsigned int> hidden_sequence(obs_sequence.size());
start = high_resolution_clock::now();
double viterbi_likelihood = hmm.viterbi(obs_sequence, hidden_sequence);
(void)hmm.viterbi(obs_sequence, hidden_sequence);
end = high_resolution_clock::now();
results.viterbi_time = duration_cast<microseconds>(end - start).count() / 1000.0;

Expand Down
2 changes: 1 addition & 1 deletion benchmarks/src/simple_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ void benchmarkDistributions() {
if (x > 20)
x = 20; // Limit for discrete distributions
}
distributions[i]->getProbability(x);
static_cast<void>(distributions[i]->getProbability(x));
}

double time_ms = timer.stop();
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/src/threeway_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class HMMLibBenchmark {
// Benchmark Viterbi
vector<unsigned int> hidden_sequence(obs_sequence.size());
start = high_resolution_clock::now();
double viterbi_likelihood = hmm.viterbi(obs_sequence, hidden_sequence);
(void)hmm.viterbi(obs_sequence, hidden_sequence);
end = high_resolution_clock::now();
results.viterbi_time = duration_cast<microseconds>(end - start).count() / 1000.0;

Expand Down
2 changes: 1 addition & 1 deletion include/libhmm/calculators/calculator.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include "libhmm/common/common.h"
#include "libhmm/linalg/linalg_types.h"
#include "libhmm/hmm.h"
#include <stdexcept>
#include <memory>
Expand Down
256 changes: 14 additions & 242 deletions include/libhmm/common/common.h
Original file line number Diff line number Diff line change
@@ -1,271 +1,43 @@
#pragma once

/*
* Standard Library includes - C++17 only, no external dependencies
* Consolidated to reduce duplicate includes across the project
*/
// Core C++ standard library headers used throughout the library.
// Lean version: linalg types (Matrix, Vector, ObservationSet, etc.) and XML
// serialization helpers now live in separate headers:
// libhmm/linalg/linalg_types.h — type aliases and clear_* helpers
// libhmm/common/serialization.h — MatrixSerializer / VectorSerializer
// Include those headers from files that need them.

// Core C++ standard library headers
#include <vector>
#include <memory>
#include <string>
#include <iostream>
#include <fstream>
#include <iomanip> // std::setprecision, std::fixed, std::put_time — used in toString()
// and file I/O throughout the library. Must be explicit: MSVC and
// libstdc++ do not include <iomanip> transitively through <iostream>.
#include <sstream>
#include <stdexcept>
#include <algorithm>
#include <functional>
#include <utility>
#include <type_traits>

// Mathematical and numerical headers
#include <cmath>
// MSVC does not define M_PI by default; guard here once for all consumers.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#include <cfloat>
#include <climits>
#include <cstddef>
#include <limits>
#include <cassert>

// Platform/SIMD headers are in libhmm/platform/ (moved from performance/ in Phase 1 refactor)
// Include libhmm/platform/simd_platform.h if you need SIMD intrinsics
// Constants (includes M_PI guard)
#include "libhmm/math/constants.h"

namespace libhmm {

/*
* If we make all observations as double, we can truncate as needed and still
* retain tons of precision for most of the operations.
*/
/// Scalar observation type. Using double gives sufficient precision for all
/// currently supported distributions while keeping the linalg types concrete.
typedef double Observation;

/*
* We know that a state is an integral value, so...
*/
/// State index type.
typedef int StateIndex;

} // namespace libhmm

// linalg types live in libhmm/linalg/ (Phase 1 refactor).
// Must be included after basic typedefs to avoid naming conflicts.
#include "libhmm/linalg/basic_matrix.h"
#include "libhmm/linalg/basic_vector.h"
#include "libhmm/linalg/basic_matrix3d.h"

// Constants extracted to their own header in Phase 1 refactor
#include "libhmm/math/constants.h"

namespace libhmm {

// Type aliases
using Matrix = BasicMatrix<Observation>;
using Vector = BasicVector<Observation>;
using ObservationSet = BasicVector<Observation>;
using StateSequence = BasicVector<StateIndex>;
using ObservationMatrix3D = BasicMatrix3D<Observation>;

template <typename T>
using Matrix3DTemplate = BasicMatrix3D<T>;

typedef std::vector<ObservationSet> ObservationLists;

void clear_matrix(Matrix &m);
void clear_vector(Vector &v);
void clear_vector(StateSequence &v);

} // namespace libhmm

/*
* Custom C++17 serialization functions for matrices and vectors.
* These replace the Boost serialization functionality with lightweight,
* standards-compliant serialization using simple XML format.
*
* Design Goals:
* - Zero external dependencies (pure C++17)
* - Backward compatibility with existing XML format where possible
* - Simple, human-readable XML output
* - Efficient parsing for HMM-specific use cases
*/
namespace libhmm {
namespace serialization {

/**
* Simple XML serialization for BasicMatrix objects
* Replaces boost::serialization with lightweight implementation
*/
template <typename T>
class MatrixSerializer {
public:
// Save matrix to XML format
static void save(std::ostream &os, const BasicMatrix<T> &matrix,
const std::string &name = "matrix") {
os << "<" << name << ">\n";
os << " <rows>" << matrix.size1() << "</rows>\n";
os << " <cols>" << matrix.size2() << "</cols>\n";
os << " <data>\n";

for (std::size_t i = 0; i < matrix.size1(); ++i) {
os << " <row>";
for (std::size_t j = 0; j < matrix.size2(); ++j) {
os << matrix(i, j);
if (j < matrix.size2() - 1)
os << " ";
}
os << "</row>\n";
}

os << " </data>\n";
os << "</" << name << ">\n";
}

// Load matrix from XML format
static void load(std::istream &is, BasicMatrix<T> &matrix, const std::string &name = "matrix") {
std::string line;
std::size_t rows = 0, cols = 0;

// Simple XML parsing - find opening tag
while (std::getline(is, line)) {
if (line.find("<" + name + ">") != std::string::npos) {
break;
}
}

// Read dimensions
if (std::getline(is, line)) {
std::size_t start = line.find("<rows>") + 6;
std::size_t end = line.find("</rows>");
if (start != std::string::npos && end != std::string::npos) {
rows = std::stoull(line.substr(start, end - start));
}
}

if (std::getline(is, line)) {
std::size_t start = line.find("<cols>") + 6;
std::size_t end = line.find("</cols>");
if (start != std::string::npos && end != std::string::npos) {
cols = std::stoull(line.substr(start, end - start));
}
}

// Resize matrix
matrix.resize(rows, cols);

// Skip <data> tag
std::getline(is, line);

// Read matrix data
for (std::size_t i = 0; i < rows; ++i) {
if (std::getline(is, line)) {
std::size_t start = line.find("<row>") + 5;
std::size_t end = line.find("</row>");
if (start != std::string::npos && end != std::string::npos) {
std::string data_str = line.substr(start, end - start);
std::istringstream row_stream(data_str);

for (std::size_t j = 0; j < cols; ++j) {
T value;
row_stream >> value;
matrix(i, j) = value;
}
}
}
}
}
};

/**
* Simple XML serialization for BasicVector objects
* Replaces boost::serialization with lightweight implementation
*/
template <typename T>
class VectorSerializer {
public:
// Save vector to XML format
static void save(std::ostream &os, const BasicVector<T> &vector,
const std::string &name = "vector") {
os << "<" << name << ">\n";
os << " <size>" << vector.size() << "</size>\n";
os << " <data>";

for (std::size_t i = 0; i < vector.size(); ++i) {
os << vector[i];
if (i < vector.size() - 1)
os << " ";
}

os << "</data>\n";
os << "</" << name << ">\n";
}

// Load vector from XML format
static void load(std::istream &is, BasicVector<T> &vector, const std::string &name = "vector") {
std::string line;
std::size_t size = 0;

// Simple XML parsing - find opening tag
while (std::getline(is, line)) {
if (line.find("<" + name + ">") != std::string::npos) {
break;
}
}

// Read size
if (std::getline(is, line)) {
std::size_t start = line.find("<size>") + 6;
std::size_t end = line.find("</size>");
if (start != std::string::npos && end != std::string::npos) {
size = std::stoull(line.substr(start, end - start));
}
}

// Resize vector
vector.resize(size);

// Read data
if (std::getline(is, line)) {
std::size_t start = line.find("<data>") + 6;
std::size_t end = line.find("</data>");
if (start != std::string::npos && end != std::string::npos) {
std::string data_str = line.substr(start, end - start);
std::istringstream data_stream(data_str);

for (std::size_t i = 0; i < size; ++i) {
T value;
data_stream >> value;
vector[i] = value;
}
}
}
}
};

/**
* Convenience functions to match the old boost::serialization style
*/

// Matrix serialization convenience functions
template <typename Archive, typename T>
void save(Archive &ar, const BasicMatrix<T> &matrix, const std::string &name = "matrix") {
MatrixSerializer<T>::save(ar, matrix, name);
}

template <typename Archive, typename T>
void load(Archive &ar, BasicMatrix<T> &matrix, const std::string &name = "matrix") {
MatrixSerializer<T>::load(ar, matrix, name);
}

// Vector serialization convenience functions
template <typename Archive, typename T>
void save(Archive &ar, const BasicVector<T> &vector, const std::string &name = "vector") {
VectorSerializer<T>::save(ar, vector, name);
}

template <typename Archive, typename T>
void load(Archive &ar, BasicVector<T> &vector, const std::string &name = "vector") {
VectorSerializer<T>::load(ar, vector, name);
}

} // namespace serialization
} // namespace libhmm
Loading
Loading