mirror of
https://github.com/JHUAPL/kami.git
synced 2026-01-08 14:33:53 -05:00
Separate all method declarations from definitions
This commit is contained in:
@@ -30,6 +30,8 @@
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
|
||||
@@ -64,14 +64,14 @@ namespace kami {
|
||||
/**
|
||||
* @brief Constructs a new unique identifier.
|
||||
*/
|
||||
AgentID() : _id(_id_next++) {};
|
||||
AgentID();
|
||||
|
||||
/**
|
||||
* @brief Convert the identifier to a human-readable string.
|
||||
*
|
||||
* @return a human-readable form of the `AgentID` as `std::string`.
|
||||
*/
|
||||
[[nodiscard]] std::string to_string() const { return std::to_string(_id); }
|
||||
[[nodiscard]] std::string to_string() const;
|
||||
|
||||
/**
|
||||
* @brief Test if two `AgentID` instances are equal.
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace kami {
|
||||
/**
|
||||
* @brief Constructor for one-dimensional coordinates
|
||||
*/
|
||||
explicit GridCoord1D(int x_coord) : _x_coord(x_coord){};
|
||||
explicit GridCoord1D(int x_coord);;
|
||||
|
||||
/**
|
||||
* @brief Return the `x` coordinate
|
||||
@@ -102,6 +102,32 @@ namespace kami {
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &lhs, const GridCoord1D &rhs);
|
||||
|
||||
/**
|
||||
* @brief Add two coordinates together
|
||||
*/
|
||||
inline friend GridCoord1D operator+(const GridCoord1D &lhs, const GridCoord1D &rhs);
|
||||
|
||||
/**
|
||||
* @brief Subtract one coordinate from another
|
||||
*/
|
||||
inline friend GridCoord1D operator-(const GridCoord1D &lhs, const GridCoord1D &rhs);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
*
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord1D operator*(const GridCoord1D &lhs, const double rhs);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
*
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord1D operator*(const double lhs, const GridCoord1D &rhs);
|
||||
|
||||
private:
|
||||
int _x_coord;
|
||||
};
|
||||
|
||||
@@ -49,25 +49,11 @@ namespace kami {
|
||||
* @brief Two-dimensional coordinates
|
||||
*/
|
||||
class LIBKAMI_EXPORT GridCoord2D : public GridCoord {
|
||||
protected:
|
||||
inline double distance_chebyshev(std::shared_ptr<GridCoord2D> &p) const {
|
||||
return static_cast<double>(fmax(abs(_x_coord - p->_x_coord), abs(_x_coord - p->_x_coord)));
|
||||
};
|
||||
|
||||
inline double distance_euclidean(std::shared_ptr<GridCoord2D> &p) const {
|
||||
return sqrt(pow(_x_coord - p->_x_coord, 2) + pow(_x_coord - p->_x_coord, 2));
|
||||
};
|
||||
|
||||
inline double distance_manhattan(std::shared_ptr<GridCoord2D> &p) const {
|
||||
return static_cast<double>(abs(_x_coord - p->_x_coord) + abs(_x_coord - p->_x_coord));
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for two-dimensional coordinates
|
||||
*/
|
||||
GridCoord2D(int x_coord, int y_coord)
|
||||
: _x_coord(x_coord), _y_coord(y_coord) {};
|
||||
GridCoord2D(int x_coord, int y_coord);;
|
||||
|
||||
/**
|
||||
* @brief Get the coordinate in the first dimension or `x`.
|
||||
@@ -123,16 +109,12 @@ namespace kami {
|
||||
/**
|
||||
* @brief Add two coordinates together
|
||||
*/
|
||||
inline friend GridCoord2D operator+(const GridCoord2D &lhs, const GridCoord2D &rhs) {
|
||||
return {lhs._x_coord + rhs._x_coord, lhs._y_coord + rhs._y_coord};
|
||||
}
|
||||
inline friend GridCoord2D operator+(const GridCoord2D &lhs, const GridCoord2D &rhs);
|
||||
|
||||
/**
|
||||
* @brief Subtract one coordinate from another
|
||||
*/
|
||||
inline friend GridCoord2D operator-(const GridCoord2D &lhs, const GridCoord2D &rhs) {
|
||||
return {lhs._x_coord - rhs._x_coord, lhs._y_coord - rhs._y_coord};
|
||||
}
|
||||
inline friend GridCoord2D operator-(const GridCoord2D &lhs, const GridCoord2D &rhs);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
@@ -140,9 +122,7 @@ namespace kami {
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord2D operator*(const GridCoord2D &lhs, const double rhs) {
|
||||
return {static_cast<int>(lhs._x_coord * rhs), static_cast<int>(lhs._y_coord * rhs)};
|
||||
}
|
||||
inline friend GridCoord2D operator*(const GridCoord2D &lhs, const double rhs);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
@@ -150,9 +130,14 @@ namespace kami {
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord2D operator*(const double lhs, const GridCoord2D &rhs) {
|
||||
return {static_cast<int>(rhs._x_coord * lhs), static_cast<int>(rhs._y_coord * lhs)};
|
||||
}
|
||||
inline friend GridCoord2D operator*(const double lhs, const GridCoord2D &rhs);
|
||||
|
||||
protected:
|
||||
inline double distance_chebyshev(std::shared_ptr<GridCoord2D> &p) const;
|
||||
|
||||
inline double distance_euclidean(std::shared_ptr<GridCoord2D> &p) const;
|
||||
|
||||
inline double distance_manhattan(std::shared_ptr<GridCoord2D> &p) const;
|
||||
|
||||
private:
|
||||
int _x_coord, _y_coord;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
|
||||
@@ -53,8 +53,7 @@ namespace kami {
|
||||
* @param[in] maximum_x the length of the grid.
|
||||
* @param[in] wrap_x should the grid wrap around on itself.
|
||||
*/
|
||||
MultiGrid1D(unsigned int maximum_x, bool wrap_x)
|
||||
: Grid1D(maximum_x, wrap_x) {}
|
||||
MultiGrid1D(unsigned int maximum_x, bool wrap_x);
|
||||
|
||||
/**
|
||||
* @brief Place agent on the grid at the specified location.
|
||||
|
||||
@@ -57,8 +57,7 @@ namespace kami {
|
||||
* @param[in] wrap_y should the grid wrap around on itself in the second
|
||||
* dimension
|
||||
*/
|
||||
MultiGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y)
|
||||
: Grid2D(maximum_x, maximum_y, wrap_x, wrap_y) {};
|
||||
MultiGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y);
|
||||
|
||||
/**
|
||||
* @brief Place agent on the grid at the specified location.
|
||||
|
||||
@@ -41,17 +41,6 @@ namespace kami {
|
||||
* @brief An abstract for generic models
|
||||
*/
|
||||
class LIBKAMI_EXPORT Population {
|
||||
protected:
|
||||
/**
|
||||
* @brief A mapping of `AgentID` to `Agent` pointers
|
||||
*
|
||||
* @details This is the mapping of all `AgentID`s to
|
||||
* pointers to the corresponding `Agent` in this population.
|
||||
* This is left exposed as protected should any subclass
|
||||
* wish to manipulate this mapping directly.
|
||||
*/
|
||||
std::map<kami::AgentID, std::shared_ptr<Agent>> _agent_map;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get a reference to an `Agent` by `AgentID`
|
||||
@@ -86,6 +75,17 @@ namespace kami {
|
||||
* @returns a `std::vector` of all the `AgentID`'s in the `Population`
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<AgentID>> get_agent_list() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief A mapping of `AgentID` to `Agent` pointers
|
||||
*
|
||||
* @details This is the mapping of all `AgentID`s to
|
||||
* pointers to the corresponding `Agent` in this population.
|
||||
* This is left exposed as protected should any subclass
|
||||
* wish to manipulate this mapping directly.
|
||||
*/
|
||||
std::map<kami::AgentID, std::shared_ptr<Agent>> _agent_map;
|
||||
};
|
||||
} // namespace kami
|
||||
|
||||
|
||||
@@ -48,9 +48,6 @@ namespace kami {
|
||||
* but is not guaranteed not to repeat.
|
||||
*/
|
||||
class LIBKAMI_EXPORT RandomScheduler : public SequentialScheduler, std::enable_shared_from_this<RandomScheduler> {
|
||||
private:
|
||||
std::shared_ptr<std::mt19937> _rng = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
@@ -102,6 +99,10 @@ namespace kami {
|
||||
* the order of agent stepping.
|
||||
*/
|
||||
std::shared_ptr<std::mt19937> get_rng();
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::mt19937> _rng = nullptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
@@ -79,9 +79,7 @@ namespace kami {
|
||||
|
||||
private:
|
||||
// This should be uncallable, but knocks out the inherited method.
|
||||
AgentID step(std::shared_ptr<Model> model) override {
|
||||
return get_agent_id();
|
||||
};
|
||||
AgentID step(std::shared_ptr<Model> model) override;;
|
||||
|
||||
int _step_counter = 0;
|
||||
};
|
||||
@@ -113,9 +111,7 @@ namespace kami {
|
||||
* @details The step_id should probably be a monotonically
|
||||
* incrementing integer.
|
||||
*/
|
||||
inline virtual unsigned int get_step_id() {
|
||||
return _step_count;
|
||||
};
|
||||
virtual unsigned int get_step_id();
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step of the model
|
||||
|
||||
@@ -46,12 +46,6 @@ namespace kami {
|
||||
* the step function for each agent based on the type of scheduling implemented.
|
||||
*/
|
||||
class LIBKAMI_EXPORT Scheduler {
|
||||
protected:
|
||||
/**
|
||||
* Counter to increment on each step
|
||||
*/
|
||||
int _step_counter = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Execute a single time step.
|
||||
@@ -87,6 +81,12 @@ namespace kami {
|
||||
|
||||
virtual std::optional<std::unique_ptr<std::vector<AgentID>>>
|
||||
step(std::shared_ptr<ReporterModel> model, std::unique_ptr<std::vector<AgentID>> agent_list) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Counter to increment on each step
|
||||
*/
|
||||
int _step_counter = 0;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
@@ -52,8 +52,7 @@ namespace kami {
|
||||
* @param[in] maximum_x the length of the grid.
|
||||
* @param[in] wrap_x should the grid wrap around on itself.
|
||||
*/
|
||||
SoloGrid1D(unsigned int maximum_x, bool wrap_x)
|
||||
: Grid1D(maximum_x, wrap_x) {}
|
||||
SoloGrid1D(unsigned int maximum_x, bool wrap_x);
|
||||
|
||||
/**
|
||||
* @brief Place agent on the grid at the specified location.
|
||||
|
||||
@@ -54,8 +54,7 @@ namespace kami {
|
||||
* @param[in] wrap_x should the grid wrap around on itself in the first dimension
|
||||
* @param[in] wrap_y should the grid wrap around on itself in the second dimension
|
||||
*/
|
||||
SoloGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y)
|
||||
: Grid2D(maximum_x, maximum_y, wrap_x, wrap_y) {};
|
||||
SoloGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y);;
|
||||
|
||||
/**
|
||||
* @details Place agent on the grid at the specified location.
|
||||
|
||||
@@ -48,6 +48,26 @@ namespace kami {
|
||||
* `delete_agent()`.
|
||||
*/
|
||||
class LIBKAMI_EXPORT StagedScheduler : public SequentialScheduler {
|
||||
public:
|
||||
/**
|
||||
* @brief Execute a single time step
|
||||
*
|
||||
* @details This method will step through the list of Agents in the scheduler's
|
||||
* internal queue and execute the `Agent::step()` method for each `Agent`
|
||||
* in the same order. Finally, it will execute the `Agent::advance()`
|
||||
* method for each Agent in the same order.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::optional<std::unique_ptr<std::vector<AgentID>>>
|
||||
step(std::shared_ptr<Model> model, std::unique_ptr<std::vector<AgentID>> agent_list) override;
|
||||
|
||||
std::optional<std::unique_ptr<std::vector<AgentID>>>
|
||||
step(std::shared_ptr<ReporterModel> model, std::unique_ptr<std::vector<AgentID>> agent_list) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Advance a single time step.
|
||||
@@ -83,26 +103,6 @@ namespace kami {
|
||||
|
||||
std::optional<std::unique_ptr<std::vector<AgentID>>>
|
||||
advance(std::shared_ptr<ReporterModel> model, std::unique_ptr<std::vector<AgentID>> agent_list);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Execute a single time step
|
||||
*
|
||||
* @details This method will step through the list of Agents in the scheduler's
|
||||
* internal queue and execute the `Agent::step()` method for each `Agent`
|
||||
* in the same order. Finally, it will execute the `Agent::advance()`
|
||||
* method for each Agent in the same order.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::optional<std::unique_ptr<std::vector<AgentID>>>
|
||||
step(std::shared_ptr<Model> model, std::unique_ptr<std::vector<AgentID>> agent_list) override;
|
||||
|
||||
std::optional<std::unique_ptr<std::vector<AgentID>>>
|
||||
step(std::shared_ptr<ReporterModel> model, std::unique_ptr<std::vector<AgentID>> agent_list) override;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
@@ -23,13 +23,17 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <kami/agent.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <kami/agent.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
AgentID::AgentID() : _id(_id_next++) {}
|
||||
|
||||
std::string AgentID::to_string() const { return std::to_string(_id); }
|
||||
|
||||
bool operator==(const AgentID &lhs, const AgentID &rhs) {
|
||||
return lhs._id == rhs._id;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
namespace kami {
|
||||
|
||||
GridCoord1D::GridCoord1D(int x_coord) : _x_coord(x_coord) {}
|
||||
|
||||
int GridCoord1D::get_x_location() const {
|
||||
return _x_coord;
|
||||
}
|
||||
@@ -65,6 +67,23 @@ namespace kami {
|
||||
return lhs << rhs.to_string();
|
||||
}
|
||||
|
||||
GridCoord1D operator+(const GridCoord1D &lhs, const GridCoord1D &rhs) {
|
||||
return GridCoord1D(lhs._x_coord + rhs._x_coord);
|
||||
}
|
||||
|
||||
GridCoord1D operator-(const GridCoord1D &lhs, const GridCoord1D &rhs) {
|
||||
return GridCoord1D(lhs._x_coord - rhs._x_coord);
|
||||
}
|
||||
|
||||
GridCoord1D operator*(const GridCoord1D &lhs, const double rhs) {
|
||||
return GridCoord1D(static_cast<int>(lhs._x_coord * rhs));
|
||||
}
|
||||
|
||||
GridCoord1D operator*(const double lhs, const GridCoord1D &rhs) {
|
||||
return GridCoord1D(static_cast<int>(rhs._x_coord * lhs));
|
||||
}
|
||||
|
||||
|
||||
Grid1D::Grid1D(unsigned int maximum_x, bool wrap_x) {
|
||||
_maximum_x = maximum_x;
|
||||
_wrap_x = wrap_x;
|
||||
|
||||
@@ -74,6 +74,37 @@ namespace kami {
|
||||
return lhs << rhs.to_string();
|
||||
}
|
||||
|
||||
GridCoord2D::GridCoord2D(int x_coord, int y_coord)
|
||||
: _x_coord(x_coord), _y_coord(y_coord) {}
|
||||
|
||||
double GridCoord2D::distance_chebyshev(std::shared_ptr<GridCoord2D> &p) const {
|
||||
return static_cast<double>(fmax(abs(_x_coord - p->_x_coord), abs(_x_coord - p->_x_coord)));
|
||||
}
|
||||
|
||||
double GridCoord2D::distance_euclidean(std::shared_ptr<GridCoord2D> &p) const {
|
||||
return sqrt(pow(_x_coord - p->_x_coord, 2) + pow(_x_coord - p->_x_coord, 2));
|
||||
}
|
||||
|
||||
double GridCoord2D::distance_manhattan(std::shared_ptr<GridCoord2D> &p) const {
|
||||
return static_cast<double>(abs(_x_coord - p->_x_coord) + abs(_x_coord - p->_x_coord));
|
||||
}
|
||||
|
||||
GridCoord2D operator+(const GridCoord2D &lhs, const GridCoord2D &rhs) {
|
||||
return {lhs._x_coord + rhs._x_coord, lhs._y_coord + rhs._y_coord};
|
||||
}
|
||||
|
||||
GridCoord2D operator-(const GridCoord2D &lhs, const GridCoord2D &rhs) {
|
||||
return {lhs._x_coord - rhs._x_coord, lhs._y_coord - rhs._y_coord};
|
||||
}
|
||||
|
||||
GridCoord2D operator*(const GridCoord2D &lhs, const double rhs) {
|
||||
return {static_cast<int>(lhs._x_coord * rhs), static_cast<int>(lhs._y_coord * rhs)};
|
||||
}
|
||||
|
||||
GridCoord2D operator*(const double lhs, const GridCoord2D &rhs) {
|
||||
return {static_cast<int>(rhs._x_coord * lhs), static_cast<int>(rhs._y_coord * lhs)};
|
||||
}
|
||||
|
||||
Grid2D::Grid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x,
|
||||
bool wrap_y) {
|
||||
_maximum_x = maximum_x;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
|
||||
namespace kami {
|
||||
|
||||
MultiGrid1D::MultiGrid1D(unsigned int maximum_x, bool wrap_x)
|
||||
: Grid1D(maximum_x, wrap_x) {}
|
||||
|
||||
std::optional<AgentID> MultiGrid1D::add_agent(const AgentID agent_id, const GridCoord1D &coord) {
|
||||
if (!is_location_valid(coord))
|
||||
return std::nullopt;
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
|
||||
namespace kami {
|
||||
|
||||
MultiGrid2D::MultiGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y)
|
||||
: Grid2D(maximum_x, maximum_y, wrap_x, wrap_y) {}
|
||||
|
||||
std::optional<AgentID> MultiGrid2D::add_agent(const AgentID agent_id, const GridCoord2D &coord) {
|
||||
if (!is_location_valid(coord))
|
||||
return std::nullopt;
|
||||
|
||||
@@ -54,6 +54,10 @@ namespace kami {
|
||||
return std::move(_rpt->report(std::static_pointer_cast<ReporterModel>(shared_from_this())));
|
||||
}
|
||||
|
||||
inline unsigned int ReporterModel::get_step_id() {
|
||||
return _step_count;
|
||||
}
|
||||
|
||||
Reporter::Reporter() {
|
||||
_report_data = std::make_unique<std::vector<nlohmann::json>>();
|
||||
}
|
||||
@@ -116,4 +120,9 @@ namespace kami {
|
||||
return std::move(json_data);
|
||||
}
|
||||
|
||||
AgentID ReporterAgent::step(std::shared_ptr<Model> model) {
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
|
||||
} // namespace kami
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
|
||||
namespace kami {
|
||||
|
||||
SoloGrid1D::SoloGrid1D(unsigned int maximum_x, bool wrap_x)
|
||||
: Grid1D(maximum_x, wrap_x) {}
|
||||
|
||||
std::optional<AgentID> SoloGrid1D::add_agent(const AgentID agent_id, const GridCoord1D &coord) {
|
||||
if (!is_location_valid(coord))
|
||||
return std::nullopt;
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
|
||||
namespace kami {
|
||||
|
||||
SoloGrid2D::SoloGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y)
|
||||
: Grid2D(maximum_x, maximum_y, wrap_x, wrap_y) {}
|
||||
|
||||
std::optional<AgentID> SoloGrid2D::add_agent(const AgentID agent_id, const GridCoord2D &coord) {
|
||||
if (!is_location_valid(coord))
|
||||
return std::nullopt;
|
||||
|
||||
Reference in New Issue
Block a user