diff --git a/examples/starter/starter.cc b/examples/starter/starter.cc index b177b66..8538775 100644 --- a/examples/starter/starter.cc +++ b/examples/starter/starter.cc @@ -30,6 +30,8 @@ #include #include +#include + #include #include diff --git a/include/kami/agent.h b/include/kami/agent.h index 6ae7a3a..c34997f 100644 --- a/include/kami/agent.h +++ b/include/kami/agent.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. diff --git a/include/kami/grid1d.h b/include/kami/grid1d.h index 5d9d382..9d1e4a6 100644 --- a/include/kami/grid1d.h +++ b/include/kami/grid1d.h @@ -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; }; diff --git a/include/kami/grid2d.h b/include/kami/grid2d.h index 0629a44..ad1ef22 100644 --- a/include/kami/grid2d.h +++ b/include/kami/grid2d.h @@ -49,25 +49,11 @@ namespace kami { * @brief Two-dimensional coordinates */ class LIBKAMI_EXPORT GridCoord2D : public GridCoord { - protected: - inline double distance_chebyshev(std::shared_ptr &p) const { - return static_cast(fmax(abs(_x_coord - p->_x_coord), abs(_x_coord - p->_x_coord))); - }; - - inline double distance_euclidean(std::shared_ptr &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 &p) const { - return static_cast(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(lhs._x_coord * rhs), static_cast(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(rhs._x_coord * lhs), static_cast(rhs._y_coord * lhs)}; - } + inline friend GridCoord2D operator*(const double lhs, const GridCoord2D &rhs); + + protected: + inline double distance_chebyshev(std::shared_ptr &p) const; + + inline double distance_euclidean(std::shared_ptr &p) const; + + inline double distance_manhattan(std::shared_ptr &p) const; private: int _x_coord, _y_coord; diff --git a/include/kami/hexgrid.h b/include/kami/hexgrid.h index d111813..02d9b6f 100644 --- a/include/kami/hexgrid.h +++ b/include/kami/hexgrid.h @@ -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 diff --git a/include/kami/multigrid1d.h b/include/kami/multigrid1d.h index 0afb4f0..20edd2d 100644 --- a/include/kami/multigrid1d.h +++ b/include/kami/multigrid1d.h @@ -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. diff --git a/include/kami/multigrid2d.h b/include/kami/multigrid2d.h index d6fdeeb..2f91b6e 100644 --- a/include/kami/multigrid2d.h +++ b/include/kami/multigrid2d.h @@ -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. diff --git a/include/kami/population.h b/include/kami/population.h index 127dbf2..7c31130 100644 --- a/include/kami/population.h +++ b/include/kami/population.h @@ -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> _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> 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> _agent_map; }; } // namespace kami diff --git a/include/kami/random.h b/include/kami/random.h index 1e366f4..6bc64ed 100644 --- a/include/kami/random.h +++ b/include/kami/random.h @@ -48,9 +48,6 @@ namespace kami { * but is not guaranteed not to repeat. */ class LIBKAMI_EXPORT RandomScheduler : public SequentialScheduler, std::enable_shared_from_this { - private: - std::shared_ptr _rng = nullptr; - public: /** * @brief Constructor. @@ -102,6 +99,10 @@ namespace kami { * the order of agent stepping. */ std::shared_ptr get_rng(); + + private: + std::shared_ptr _rng = nullptr; + }; } // namespace kami diff --git a/include/kami/reporter.h b/include/kami/reporter.h index 59bfe5b..d457124 100644 --- a/include/kami/reporter.h +++ b/include/kami/reporter.h @@ -79,9 +79,7 @@ namespace kami { private: // This should be uncallable, but knocks out the inherited method. - AgentID step(std::shared_ptr model) override { - return get_agent_id(); - }; + AgentID step(std::shared_ptr 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 diff --git a/include/kami/scheduler.h b/include/kami/scheduler.h index ac32648..ef9fc41 100644 --- a/include/kami/scheduler.h +++ b/include/kami/scheduler.h @@ -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>> step(std::shared_ptr model, std::unique_ptr> agent_list) = 0; + + protected: + /** + * Counter to increment on each step + */ + int _step_counter = 0; }; } // namespace kami diff --git a/include/kami/sologrid1d.h b/include/kami/sologrid1d.h index dc167a8..5ceeeba 100644 --- a/include/kami/sologrid1d.h +++ b/include/kami/sologrid1d.h @@ -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. diff --git a/include/kami/sologrid2d.h b/include/kami/sologrid2d.h index 7cab84d..7c688c7 100644 --- a/include/kami/sologrid2d.h +++ b/include/kami/sologrid2d.h @@ -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. diff --git a/include/kami/staged.h b/include/kami/staged.h index 376cca6..324243c 100644 --- a/include/kami/staged.h +++ b/include/kami/staged.h @@ -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>> + step(std::shared_ptr model, std::unique_ptr> agent_list) override; + + std::optional>> + step(std::shared_ptr model, std::unique_ptr> agent_list) override; + private: /** * @brief Advance a single time step. @@ -83,26 +103,6 @@ namespace kami { std::optional>> advance(std::shared_ptr model, std::unique_ptr> 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>> - step(std::shared_ptr model, std::unique_ptr> agent_list) override; - - std::optional>> - step(std::shared_ptr model, std::unique_ptr> agent_list) override; }; } // namespace kami diff --git a/src/libkami/agent.cc b/src/libkami/agent.cc index 33ccbf5..7cd442e 100644 --- a/src/libkami/agent.cc +++ b/src/libkami/agent.cc @@ -23,13 +23,17 @@ * SOFTWARE. */ -#include - #include #include +#include + 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; } diff --git a/src/libkami/grid1d.cc b/src/libkami/grid1d.cc index f7700d2..08be7c0 100644 --- a/src/libkami/grid1d.cc +++ b/src/libkami/grid1d.cc @@ -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(lhs._x_coord * rhs)); + } + + GridCoord1D operator*(const double lhs, const GridCoord1D &rhs) { + return GridCoord1D(static_cast(rhs._x_coord * lhs)); + } + + Grid1D::Grid1D(unsigned int maximum_x, bool wrap_x) { _maximum_x = maximum_x; _wrap_x = wrap_x; diff --git a/src/libkami/grid2d.cc b/src/libkami/grid2d.cc index 264aaab..98a12d9 100644 --- a/src/libkami/grid2d.cc +++ b/src/libkami/grid2d.cc @@ -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 &p) const { + return static_cast(fmax(abs(_x_coord - p->_x_coord), abs(_x_coord - p->_x_coord))); + } + + double GridCoord2D::distance_euclidean(std::shared_ptr &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 &p) const { + return static_cast(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(lhs._x_coord * rhs), static_cast(lhs._y_coord * rhs)}; + } + + GridCoord2D operator*(const double lhs, const GridCoord2D &rhs) { + return {static_cast(rhs._x_coord * lhs), static_cast(rhs._y_coord * lhs)}; + } + Grid2D::Grid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y) { _maximum_x = maximum_x; diff --git a/src/libkami/hexgrid.cc b/src/libkami/hexgrid.cc index f7ee0f6..a05d6c7 100644 --- a/src/libkami/hexgrid.cc +++ b/src/libkami/hexgrid.cc @@ -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 diff --git a/src/libkami/multigrid1d.cc b/src/libkami/multigrid1d.cc index eefe2b5..7c3f45d 100644 --- a/src/libkami/multigrid1d.cc +++ b/src/libkami/multigrid1d.cc @@ -30,6 +30,9 @@ namespace kami { + MultiGrid1D::MultiGrid1D(unsigned int maximum_x, bool wrap_x) + : Grid1D(maximum_x, wrap_x) {} + std::optional MultiGrid1D::add_agent(const AgentID agent_id, const GridCoord1D &coord) { if (!is_location_valid(coord)) return std::nullopt; diff --git a/src/libkami/multigrid2d.cc b/src/libkami/multigrid2d.cc index 087d353..f051840 100644 --- a/src/libkami/multigrid2d.cc +++ b/src/libkami/multigrid2d.cc @@ -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 MultiGrid2D::add_agent(const AgentID agent_id, const GridCoord2D &coord) { if (!is_location_valid(coord)) return std::nullopt; diff --git a/src/libkami/reporter.cc b/src/libkami/reporter.cc index 7b5a2bd..a6760bd 100644 --- a/src/libkami/reporter.cc +++ b/src/libkami/reporter.cc @@ -54,6 +54,10 @@ namespace kami { return std::move(_rpt->report(std::static_pointer_cast(shared_from_this()))); } + inline unsigned int ReporterModel::get_step_id() { + return _step_count; + } + Reporter::Reporter() { _report_data = std::make_unique>(); } @@ -116,4 +120,9 @@ namespace kami { return std::move(json_data); } + AgentID ReporterAgent::step(std::shared_ptr model) { + return get_agent_id(); + } + + } // namespace kami diff --git a/src/libkami/sologrid1d.cc b/src/libkami/sologrid1d.cc index a9ad568..0447509 100644 --- a/src/libkami/sologrid1d.cc +++ b/src/libkami/sologrid1d.cc @@ -28,6 +28,9 @@ namespace kami { + SoloGrid1D::SoloGrid1D(unsigned int maximum_x, bool wrap_x) + : Grid1D(maximum_x, wrap_x) {} + std::optional SoloGrid1D::add_agent(const AgentID agent_id, const GridCoord1D &coord) { if (!is_location_valid(coord)) return std::nullopt; diff --git a/src/libkami/sologrid2d.cc b/src/libkami/sologrid2d.cc index d83714f..da2bf61 100644 --- a/src/libkami/sologrid2d.cc +++ b/src/libkami/sologrid2d.cc @@ -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 SoloGrid2D::add_agent(const AgentID agent_id, const GridCoord2D &coord) { if (!is_location_valid(coord)) return std::nullopt;