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
22 changes: 19 additions & 3 deletions include/respond/model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
// Created Date: 2026-02-05 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-07-14 //
// Modified By: Matthew Carroll //
// Last Modified: 2026-09-14 //
// Modified By: Dimitri Baptiste //
// ----- //
// Copyright (c) 2026 Syndemics Lab at Boston Medical Center //
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -49,6 +49,22 @@ class Model {
const std::string &log_name = RESPOND_DEFAULT_LOG,
const std::string &log_filepath = RESPOND_DEFAULT_LOG_FILE);

/// @brief Alternate factory method to create a Model instance.
/// @details This method creates a new instance of a Model subclass based on
/// the provided name. It sets the number of threads to be used by the
/// model, initializes logging for the model, and returns a unique_ptr to
/// the created instance. Throws an exception if the model name is
/// unsupported.
/// @param name The name identifier for the model to create.
/// @param processor_count The number of threads to be used by the model.
/// @param log_name Name of the logger for this model (default: "console").
/// @param log_filepath File path for the log file (default: "respond.log").
/// @return A unique_ptr to the newly created Model instance.
static std::unique_ptr<Model>
Create(const std::string &name, const unsigned int processor_count,
const std::string &log_name = RESPOND_DEFAULT_LOG,
const std::string &log_filepath = RESPOND_DEFAULT_LOG_FILE);

/// @brief Virtual destructor for proper polymorphic cleanup.
virtual ~Model() = default;

Expand Down Expand Up @@ -188,4 +204,4 @@ inline std::ostream &operator<<(std::ostream &os, const Model &model) {

} // namespace respond

#endif // RESPOND_MODEL_HPP_
#endif // RESPOND_MODEL_HPP_
20 changes: 14 additions & 6 deletions src/internals/markov.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
// Created Date: 2026-02-05 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-07-14 //
// Modified By: Matthew Carroll //
// Last Modified: 2026-09-18 //
// Modified By: Dimitri Baptiste //
// ----- //
// Copyright (c) 2026 Syndemics Lab at Boston Medical Center //
////////////////////////////////////////////////////////////////////////////////
Expand All @@ -15,6 +15,7 @@
#include <respond/model.hpp>

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

Expand Down Expand Up @@ -48,14 +49,21 @@ class Markov : public virtual Model {
/// @param log_name The logger name for error reporting.
/// @param log_filepath The file path for the log file to be used by this
/// model.
/// @param processor_count The number of threads to use when running this
/// model.
Markov(const std::string &name, const std::string &log_name,
const std::string &log_filepath)
const std::string &log_filepath,
const unsigned int processor_count =
std::thread::hardware_concurrency())
: _name(name), _log_name(log_name), _current_timestep(0),
_history_capture_interval(1), _final_timestep(-1),
_initial_history_recorded(false) {
CreateFileLogger(log_name, log_filepath);
const auto processor_count = std::thread::hardware_concurrency();
Eigen::setNbThreads(processor_count);
// ensure that the number of threads cannot exceed the hardware capacity
const unsigned int thread_limit = std::thread::hardware_concurrency();
const unsigned int threads =
processor_count > thread_limit ? thread_limit : processor_count;
Eigen::setNbThreads(threads);
}

/// @brief Destructor for Markov model. Default implementation.
Expand Down Expand Up @@ -361,4 +369,4 @@ class Markov : public virtual Model {
};
} // namespace respond

#endif // RESPOND_INTERNALS_MARKOV_HPP_
#endif // RESPOND_INTERNALS_MARKOV_HPP_
12 changes: 10 additions & 2 deletions src/model_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
// Created Date: 2025-07-07 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-07-07 //
// Modified By: Matthew Carroll //
// Last Modified: 2026-09-14 //
// Modified By: Dimitri Baptiste //
// ----- //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
////////////////////////////////////////////////////////////////////////////////
Expand All @@ -25,4 +25,12 @@ std::unique_ptr<Model> Model::Create(const std::string &name,
const std::string &log_filepath) {
return std::make_unique<Markov>(name, log_name, log_filepath);
}

std::unique_ptr<Model> Model::Create(const std::string &name,
const unsigned int processor_count,
const std::string &log_name,
const std::string &log_filepath) {
return std::make_unique<Markov>(name, log_name, log_filepath,
processor_count);
}
} // namespace respond
16 changes: 14 additions & 2 deletions tests/unit/markov_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
// Created Date: 2025-06-06 //
// Author: Matthew Carroll //
// ----- //
// Last Modified: 2026-07-09 //
// Modified By: Matthew Carroll //
// Last Modified: 2026-09-14 //
// Modified By: Dimitri Baptiste //
// ----- //
// Copyright (c) 2025-2026 Syndemics Lab at Boston Medical Center //
////////////////////////////////////////////////////////////////////////////////
Expand All @@ -14,6 +14,7 @@

#include <fstream>
#include <memory>
#include <thread>

#include <Eigen/Dense>
#include <gtest/gtest.h>
Expand Down Expand Up @@ -88,6 +89,17 @@ TEST_F(MarkovTest, CreateMarkovModel) {
CreationStatus::kExists);
}

TEST_F(MarkovTest, CreateMarkovModelProcessorCount) {
unsigned int processor_count =
std::thread::hardware_concurrency() > 1
? (std::thread::hardware_concurrency() / 2)
: 1;
auto markov = Model::Create("markov", processor_count);
ASSERT_NE(markov, nullptr);
ASSERT_EQ(CreateFileLogger(RESPOND_DEFAULT_LOG, ""),
CreationStatus::kExists);
}

TEST_F(MarkovTest, MoveConstructor) {
Markov markov("markov_source", RESPOND_DEFAULT_LOG);
markov.SetState(state);
Expand Down
Loading