Skip to content
Closed
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ target_sources(respond_model
include/respond/logging.hpp
include/respond/markov.hpp
include/respond/respond.hpp
include/respond/transition.hpp
include/respond/types.hpp
include/respond/version.hpp
)
Expand Down
19 changes: 6 additions & 13 deletions include/respond/markov.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Created Date: 2025-08-05 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-01-26 //
// Last Modified: 2026-02-02 //
// Modified By: Matthew Carroll //
// ----- //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
Expand All @@ -15,21 +15,14 @@

#include <memory>
#include <string>
#include <vector>

#include <Eigen/Dense>

#include <respond/types.hpp>
#include <respond/transition.hpp>

namespace respond {

/// @brief type for a general function to apply a transition to the model state.
using transition_function = std::function<Eigen::VectorXd(
const Eigen::VectorXd &, const std::vector<Eigen::MatrixXd> &,
HistoryStamp &)>;

/// @brief The pair of functions and transition matrices.
using transition = std::pair<transition_function, std::vector<Eigen::MatrixXd>>;

/// @brief Class describing the Respond model simulation.
class Markov {
public:
Expand All @@ -46,15 +39,15 @@ class Markov {

/// @brief Setter for the transition operations.
/// @param transitions A vector of transition operations and matrices.
virtual void SetTransitions(const std::vector<transition> &transitions) = 0;
virtual void SetTransitions(const std::vector<Transition> &transitions) = 0;

/// @brief Getter for the transition operations.
/// @return Vector of transition operations and matrices.
virtual std::vector<transition> GetTransitions() const = 0;
virtual std::vector<Transition> GetTransitions() const = 0;

/// @brief Add a single transition operation to the vector.
/// @param transition A transition operation and the matrices.
virtual void AddTransition(const transition &transition) = 0;
virtual void AddTransition(const Transition &transition) = 0;

/// @brief Core function to Run the Markov model.
/// @param num_steps The number of steps to run through the model.
Expand Down
57 changes: 57 additions & 0 deletions include/respond/transition.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
////////////////////////////////////////////////////////////////////////////////
// File: transition.hpp //
// Project: respond //
// Created Date: 2026-02-02 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-02-02 //
// Modified By: Matthew Carroll //
// ----- //
// Copyright (c) 2026 Syndemics Lab at Boston Medical Center //
////////////////////////////////////////////////////////////////////////////////

#ifndef RESPOND_TRANSITION_HPP_
#define RESPOND_TRANSITION_HPP_

#include <functional>
#include <vector>

#include <Eigen/Dense>

#include <respond/types.hpp>

namespace respond {

/// @brief A helper class to hold Transitions
class Transition {
public:
/// @brief A vector of matrices containing the transition matrices to
/// multiply.
std::vector<Eigen::MatrixXd> transition_matrices;

void SetCallback(std::function<Eigen::VectorXd(
const Eigen::VectorXd &,
const std::vector<Eigen::MatrixXd> &, HistoryStamp &)>
cb) {
_callback = std::move(cb);
}

Eigen::VectorXd Execute(const Eigen::VectorXd &a,
const std::vector<Eigen::MatrixXd> &b,
HistoryStamp &c) {
if (_callback) {
return _callback(a, b, c);
}
return a;
}

private:
/// @brief The callback function to apply.
std::function<Eigen::VectorXd(const Eigen::VectorXd &,
const std::vector<Eigen::MatrixXd> &,
HistoryStamp &)>
_callback;
};
} // namespace respond

#endif
10 changes: 1 addition & 9 deletions include/respond/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Created Date: 2025-08-05 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-01-26 //
// Last Modified: 2026-02-02 //
// Modified By: Matthew Carroll //
// ----- //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
Expand All @@ -23,14 +23,6 @@
/// @brief General Namespace for all RESPOND repo related code.
namespace respond {

/// @brief Type alias for a string map
/// @tparam T Type of key for the map
template <typename T> using StringMap = std::map<std::string, T>;

/// @brief Type alias for a string unordered map
/// @tparam T Type of key for the unordered map
template <typename T> using StringUOMap = std::unordered_map<std::string, T>;

/// @brief Struct grouping together matrices containing run history
struct HistoryStamp {
Eigen::VectorXd state = Eigen::VectorXd::Zero(0);
Expand Down
12 changes: 6 additions & 6 deletions src/internals/markov_internals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Created Date: 2025-08-05 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-01-26 //
// Last Modified: 2026-02-02 //
// Modified By: Matthew Carroll //
// ----- //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
Expand Down Expand Up @@ -50,18 +50,18 @@ class MarkovImpl : public virtual Markov {
}
Eigen::VectorXd GetState() const override { return _state; }

void SetTransitions(const std::vector<transition> &tr) override {
void SetTransitions(const std::vector<Transition> &transitions) override {
_transitions.clear();
// This is required for a deep copy of the matrices from the vector
for (const auto &t : tr) {
for (const auto &t : transitions) {
_transitions.push_back(t);
}
}
std::vector<transition> GetTransitions() const override {
std::vector<Transition> GetTransitions() const override {
return _transitions;
}

void AddTransition(const transition &transition) override {
void AddTransition(const Transition &transition) override {
_transitions.push_back(transition);
}

Expand All @@ -74,7 +74,7 @@ class MarkovImpl : public virtual Markov {
private:
std::string _logger_name;
Eigen::VectorXd _state;
std::vector<transition> _transitions = {};
std::vector<Transition> _transitions = {};
int _time = 0;
HistoryOverTime _history = {};

Expand Down
7 changes: 3 additions & 4 deletions src/markov.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Created Date: 2025-07-07 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-01-26 //
// Last Modified: 2026-02-02 //
// Modified By: Matthew Carroll //
// ----- //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
Expand Down Expand Up @@ -63,9 +63,8 @@ void MarkovImpl::LogDebugPoint(const std::string &message,
}

void MarkovImpl::Step(HistoryStamp &hs) {
for (int i = 0; i < _transitions.size(); ++i) {
transition t = _transitions[i];
_state = (t.first)(_state, t.second, hs);
for (Transition t : _transitions) {
_state = t.Execute(_state, t.transition_matrices, hs);
}
}

Expand Down
24 changes: 14 additions & 10 deletions tests/markov_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Created Date: 2025-06-06 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-01-26 //
// Last Modified: 2026-02-02 //
// Modified By: Matthew Carroll //
// ----- //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
Expand All @@ -26,6 +26,12 @@ class MarkovTest : public ::testing::Test {
void TearDown() override {}
};

Eigen::VectorXd test_func(const Eigen::VectorXd &s,
const std::vector<Eigen::MatrixXd> &t,
HistoryStamp &h) {
return s + t[0];
}

TEST_F(MarkovTest, ZeroDuration) {
auto markov = Markov::Create("test_logger");
markov->Run(0);
Expand All @@ -41,10 +47,9 @@ TEST_F(MarkovTest, SingleStep) {
auto markov = Markov::Create("test_logger");
markov->SetState(Eigen::VectorXd::Ones(5));

transition t = {[](const Eigen::VectorXd &state,
const std::vector<Eigen::MatrixXd> &transitions,
HistoryStamp &hs) { return state + transitions[0]; },
{Eigen::VectorXd::Ones(5)}};
Transition t;
t.SetCallback(test_func);
t.transition_matrices = {Eigen::VectorXd::Ones(5)};
markov->SetTransitions({t});

markov->Run(1);
Expand All @@ -57,12 +62,11 @@ TEST_F(MarkovTest, MultipleTransitions) {
auto markov = Markov::Create("test_logger");
markov->SetState(Eigen::VectorXd::Ones(5));

transition t = {[](const Eigen::VectorXd &state,
const std::vector<Eigen::MatrixXd> &transitions,
HistoryStamp &hs) { return state + transitions[0]; },
{Eigen::VectorXd::Ones(5)}};
markov->SetTransitions({t, t, t, t, t});
Transition t;
t.SetCallback(test_func);
t.transition_matrices = {Eigen::VectorXd::Ones(5)};

markov->SetTransitions({t, t, t, t, t});
markov->Run(1);
auto results = markov->GetRunResults();

Expand Down
12 changes: 6 additions & 6 deletions tests/mocks/markov_mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
// Created Date: 2025-08-01 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2025-08-01 //
// Last Modified: 2026-02-02 //
// Modified By: Matthew Carroll //
// ----- //
// Copyright (c) 2025 Syndemics Lab at Boston Medical Center //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
////////////////////////////////////////////////////////////////////////////////
#ifndef RESPOND_TESTS_MARKOVMOCK_HPP_
#define RESPOND_TESTS_MARKOVMOCK_HPP_
Expand All @@ -19,18 +19,18 @@
#include <Eigen/Dense>
#include <gmock/gmock.h>

#include <respond/types.hpp>
#include <respond/transition.hpp>

namespace respond {
class MockMarkov : public virtual Markov {
public:
MOCK_METHOD(void, SetState, (const Eigen::VectorXd &), (override));
MOCK_METHOD(Eigen::VectorXd, GetState, (), (const, override));
MOCK_METHOD(void, SetTransitions, (const std::vector<transition> &),
MOCK_METHOD(void, SetTransitions, (const std::vector<Transition> &),
(override));
MOCK_METHOD((std::vector<transition>), GetTransitions, (),
MOCK_METHOD((std::vector<Transition>), GetTransitions, (),
(const, override));
MOCK_METHOD(void, AddTransition, (const transition &), (override));
MOCK_METHOD(void, AddTransition, (const Transition &), (override));
MOCK_METHOD(void, Run, (const int &), (override));
MOCK_METHOD(HistoryOverTime, GetRunResults, (), (const, override));
};
Expand Down