From fa9ea6ad05f11740b12d79fc0016442ccd9dca87 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:34:32 -0500 Subject: [PATCH 1/6] removing run duration --- include/respond/simulation.hpp | 10 +++++----- src/background.cpp | 6 +++++- src/overdose.cpp | 6 +++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/respond/simulation.hpp b/include/respond/simulation.hpp index 6e4e41eb..bd16cff6 100644 --- a/include/respond/simulation.hpp +++ b/include/respond/simulation.hpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-05 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-10 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -34,11 +34,11 @@ class Simulation { /// associated with the simulation. /// @param duration The number of steps to take for each model. void Run(const int &duration) { - for (int i = 0; i < duration; ++i) { - for (const auto &model : _models) { - model->RunTransitions(); - } + // for (int i = 0; i < duration; ++i) { + for (const auto &model : _models) { + model->RunTransitions(); } + // } } void AddModel(const std::unique_ptr &model) { diff --git a/src/background.cpp b/src/background.cpp index ca8346d0..518b15cc 100644 --- a/src/background.cpp +++ b/src/background.cpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-05 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-05 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -28,6 +28,10 @@ BackgroundDeath::Execute(const Eigen::VectorXd &state, if (h.find("background_death") != h.end()) { h["background_death"].AddState(deaths); } + if (!(state.array() >= deaths.array()).all()) { + std::runtime_error( + "The state is not larger than the estimated background deaths!"); + } auto new_state = state - deaths; // remove deaths from state return new_state; } diff --git a/src/overdose.cpp b/src/overdose.cpp index 5b667b97..1bd3c802 100644 --- a/src/overdose.cpp +++ b/src/overdose.cpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-05 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-05 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -42,6 +42,10 @@ Eigen::VectorXd Overdose::Execute(const Eigen::VectorXd &state, if (h.find("fatal_overdose") != h.end()) { h["fatal_overdose"].AddState(fods); } + if (!(state.array() >= fods.array()).all()) { + std::runtime_error( + "The state is not larger than the estimated fatal overdoses!"); + } auto new_state = state - fods; // remove fods from state return new_state; } From f13bb567b29f717416f9ccba511d49eaa7c2fe51 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:07:44 -0500 Subject: [PATCH 2/6] Updating create default histories and run --- include/respond/model.hpp | 4 ++- include/respond/simulation.hpp | 25 +------------------ src/internals/markov.hpp | 39 +++++++++++++++++++++++++++++- tests/integration/respond_test.cpp | 21 +++++++++++++--- tests/mocks/model_mock.hpp | 3 ++- tests/unit/simulation_test.cpp | 17 +------------ 6 files changed, 63 insertions(+), 46 deletions(-) diff --git a/include/respond/model.hpp b/include/respond/model.hpp index 2e90c26e..096b8fd7 100644 --- a/include/respond/model.hpp +++ b/include/respond/model.hpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-05 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-09 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -42,6 +42,8 @@ class Model { // History, but let that be the History's responsibility virtual std::map GetHistories() const = 0; + virtual void CreateDefaultHistories() = 0; + virtual void SetHistories(const std::map &h) = 0; // getter for model name virtual std::string GetModelName() const = 0; diff --git a/include/respond/simulation.hpp b/include/respond/simulation.hpp index bd16cff6..79b4e8f8 100644 --- a/include/respond/simulation.hpp +++ b/include/respond/simulation.hpp @@ -33,12 +33,10 @@ class Simulation { /// @brief The core function to run the simulation. Runs all models /// associated with the simulation. /// @param duration The number of steps to take for each model. - void Run(const int &duration) { - // for (int i = 0; i < duration; ++i) { + void Run() { for (const auto &model : _models) { model->RunTransitions(); } - // } } void AddModel(const std::unique_ptr &model) { @@ -89,27 +87,6 @@ class Simulation { return ret; } - /// @brief The default histories are: - /// 1. State - /// 2. Total Overdoses - /// 3. Fatal Overdoses - /// 4. Intervention Admissions - /// 5. Background Mortality - /// @return A vector of the default history objects. - static std::map - CreateDefaultHistories(const std::string &log_name) { - std::vector names = { - "state", "total_overdose", "fatal_overdose", - "intervention_admission", "background_death"}; - - std::map ret; - for (const auto &n : names) { - History h(n, log_name); - ret[n] = h; - } - return ret; - } - std::string GetLogName() const { return _log_name; } // Copying object diff --git a/src/internals/markov.hpp b/src/internals/markov.hpp index fbe879ae..8c1a3808 100644 --- a/src/internals/markov.hpp +++ b/src/internals/markov.hpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-05 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-10 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -78,8 +78,29 @@ class Markov : public virtual Model { return _transition_vector; } + /// @brief The default histories are: + /// 1. State + /// 2. Total Overdoses + /// 3. Fatal Overdoses + /// 4. Intervention Admissions + /// 5. Background Mortality + /// @return A vector of the default history objects. + void CreateDefaultHistories() override { + std::vector names = { + "state", "total_overdose", "fatal_overdose", + "intervention_admission", "background_death"}; + + std::map ret; + for (const auto &n : names) { + History h(n, GetLogName()); + ret[n] = h; + } + SetHistories(ret); + } + // manipulate the state vector void RunTransitions() override { + SetupHistory(); auto histories = GetHistories(); for (const auto &t : _transition_vector) { SetState(t->Execute(GetState(), histories)); @@ -123,6 +144,22 @@ class Markov : public virtual Model { std::string _name; std::string _log_name; std::map _histories; + + void SetupHistory() { + auto histories = GetHistories(); + if (histories.empty()) { + CreateDefaultHistories(); + histories = GetHistories(); + } + histories["state"].AddState(GetState()); + auto size = GetState().size(); + + histories["intervention_admission"].AddState( + Eigen::VectorXd::Zero(size)); + histories["total_overdose"].AddState(Eigen::VectorXd::Zero(size)); + histories["fatal_overdose"].AddState(Eigen::VectorXd::Zero(size)); + histories["background_death"].AddState(Eigen::VectorXd::Zero(size)); + } }; } // namespace respond diff --git a/tests/integration/respond_test.cpp b/tests/integration/respond_test.cpp index ab296a3a..28937765 100644 --- a/tests/integration/respond_test.cpp +++ b/tests/integration/respond_test.cpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-06 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-10 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -86,7 +86,7 @@ TEST_F(RespondTest, RunTransitionsInModel) { } TEST_F(RespondTest, RunSimulationOneStep) { - markov->SetHistories(Simulation::CreateDefaultHistories("test_logger")); + markov->CreateDefaultHistories(); markov->SetState(init_state); @@ -108,7 +108,7 @@ TEST_F(RespondTest, RunSimulationOneStep) { Simulation sim("test_logger"); sim.AddModel(markov); - sim.Run(1); + sim.Run(); auto histories = sim.GetModelHistories(); ASSERT_EQ(histories.size(), 1); @@ -126,5 +126,20 @@ TEST_F(RespondTest, RunSimulationOneStep) { ASSERT_TRUE(state_history[0].isApprox(final_state)); } +TEST_F(RespondTest, CreateDefaultHistories) { + std::vector expected = { + "state", "total_overdose", "fatal_overdose", "intervention_admission", + "background_death"}; + + std::sort(expected.begin(), expected.end()); + + markov->CreateDefaultHistories(); + std::vector results; + for (const auto &kv : markov->GetHistories()) { + results.push_back(kv.first); + } + ASSERT_EQ(results, expected); +} + } // namespace testing } // namespace respond \ No newline at end of file diff --git a/tests/mocks/model_mock.hpp b/tests/mocks/model_mock.hpp index b27edba3..417d35c0 100644 --- a/tests/mocks/model_mock.hpp +++ b/tests/mocks/model_mock.hpp @@ -4,7 +4,7 @@ // Created Date: 2025-08-01 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-09 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center // @@ -45,6 +45,7 @@ class MockModel : public virtual Model { MOCK_METHOD(std::string, GetModelName, (), (const, override)); MOCK_METHOD(std::string, GetLogName, (), (const, override)); MOCK_METHOD((std::unique_ptr), clone, (), (const, override)); + MOCK_METHOD(void, CreateDefaultHistories, (), (override)); }; } // namespace testing } // namespace respond diff --git a/tests/unit/simulation_test.cpp b/tests/unit/simulation_test.cpp index f4f45f50..56ff3928 100644 --- a/tests/unit/simulation_test.cpp +++ b/tests/unit/simulation_test.cpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-09 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-10 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -133,20 +133,5 @@ TEST_F(SimulationTest, GetHistoryNames) { ASSERT_EQ(s.GetModelHistoryNames(), expected); } -TEST_F(SimulationTest, CreateDefaultHistories) { - std::vector expected = { - "state", "total_overdose", "fatal_overdose", "intervention_admission", - "background_death"}; - - std::sort(expected.begin(), expected.end()); - - Simulation s; - auto defaults = s.CreateDefaultHistories("test_logger"); - std::vector results; - for (const auto &kv : defaults) { - results.push_back(kv.first); - } - ASSERT_EQ(results, expected); -} } // namespace testing } // namespace respond \ No newline at end of file From a69740234ea4f3e3811a55c2ab672826eeca1e26 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:16:34 -0500 Subject: [PATCH 3/6] updating histories to record state each background death event --- src/background.cpp | 4 ++++ src/internals/markov.hpp | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/background.cpp b/src/background.cpp index 518b15cc..dcf679ea 100644 --- a/src/background.cpp +++ b/src/background.cpp @@ -33,6 +33,10 @@ BackgroundDeath::Execute(const Eigen::VectorXd &state, "The state is not larger than the estimated background deaths!"); } auto new_state = state - deaths; // remove deaths from state + + if (h.find("background_death") != h.end()) { + h["state"].AddState(new_state); + } return new_state; } diff --git a/src/internals/markov.hpp b/src/internals/markov.hpp index 8c1a3808..94d7a4ff 100644 --- a/src/internals/markov.hpp +++ b/src/internals/markov.hpp @@ -105,9 +105,6 @@ class Markov : public virtual Model { for (const auto &t : _transition_vector) { SetState(t->Execute(GetState(), histories)); } - if (histories.find("state") != histories.end()) { - histories["state"].AddState(GetState()); - } SetHistories(histories); } // assume ownership of the Transition From 7dd329fbdc137c19f190af802f82f598e9afe099 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:20:31 -0500 Subject: [PATCH 4/6] setting history initial values --- src/internals/markov.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/internals/markov.hpp b/src/internals/markov.hpp index 94d7a4ff..f827de5f 100644 --- a/src/internals/markov.hpp +++ b/src/internals/markov.hpp @@ -156,6 +156,7 @@ class Markov : public virtual Model { histories["total_overdose"].AddState(Eigen::VectorXd::Zero(size)); histories["fatal_overdose"].AddState(Eigen::VectorXd::Zero(size)); histories["background_death"].AddState(Eigen::VectorXd::Zero(size)); + SetHistories(histories); } }; } // namespace respond From 6bfcfcbbf4a00cfba6428e1deb0292d1d37c51ac Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:27:55 -0500 Subject: [PATCH 5/6] fixing migration zero stop --- src/migration.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/migration.cpp b/src/migration.cpp index e2070ff3..5a1cab55 100644 --- a/src/migration.cpp +++ b/src/migration.cpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-05 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-05 // +// Last Modified: 2026-02-12 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -26,8 +26,10 @@ Eigen::VectorXd Migration::Execute(const Eigen::VectorXd &state, throw std::runtime_error("Unable to add Migration Transition Vector to " "State Vector, mismatched sizes."); } - auto new_state = state + GetTransitionMatrices()[0]; - return new_state; + auto subtracted = state + GetTransitionMatrices()[0]; + auto zero_stop = subtracted.array().max( + Eigen::VectorXd::Zero(subtracted.size()).array()); + return zero_stop; } std::unique_ptr Migration::Create(const std::string &name, From e8b01fac98a798205c43408a6396c8493d5d8825 Mon Sep 17 00:00:00 2001 From: Matthew Carroll <28577806+MJC598@users.noreply.github.com> Date: Fri, 13 Feb 2026 11:08:36 -0500 Subject: [PATCH 6/6] fixing test errors for CI --- tests/integration/respond_test.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/integration/respond_test.cpp b/tests/integration/respond_test.cpp index 28937765..ce576615 100644 --- a/tests/integration/respond_test.cpp +++ b/tests/integration/respond_test.cpp @@ -4,7 +4,7 @@ // Created Date: 2026-02-06 // // Author: Matthew Carroll // // ----- // -// Last Modified: 2026-02-12 // +// Last Modified: 2026-02-13 // // Modified By: Matthew Carroll // // ----- // // Copyright (c) 2026 Syndemics Lab at Boston Medical Center // @@ -119,11 +119,13 @@ TEST_F(RespondTest, RunSimulationOneStep) { } auto state_history = mm_histories.at("state"); - ASSERT_EQ(state_history.size(), 1); + // 2 because it carries the initial state and 1 step + ASSERT_EQ(state_history.size(), 2); Eigen::Vector3d final_state; + ASSERT_TRUE(state_history[0].isApprox(init_state)); final_state << 0.76715528791564891, 0.72320370216816077, 1.037712429738102; - ASSERT_TRUE(state_history[0].isApprox(final_state)); + ASSERT_TRUE(state_history[1].isApprox(final_state)); } TEST_F(RespondTest, CreateDefaultHistories) {