The CLion linter is a beast

This commit is contained in:
James P. Howard, II
2021-09-25 12:15:36 -04:00
parent b02efaae07
commit 584c2b94d8
32 changed files with 1294 additions and 1449 deletions

View File

@@ -1,6 +1,7 @@
Changelog
=========
- :bug:`0` Cleaned up numerous issues found by CLion's linter
- :feature:`0` Added a new overview to the documents
- :feature:`0` Added basic installation instructions
- :bug:`0` Retagged previous versions using pure Semantic Versioning

View File

@@ -23,25 +23,23 @@
* SOFTWARE.
*/
#include "boltzmann1d.h"
#include <map>
#include <memory>
#include <random>
#include <kami/agent.h>
#include <kami/grid1d.h>
#include <kami/kami.h>
#include <kami/multigrid1d.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <spdlog/stopwatch.h>
#include <stdlib.h>
#include <CLI/App.hpp>
#include <CLI/Config.hpp>
#include <CLI/Formatter.hpp>
#include <iostream>
#include <map>
#include <memory>
#include <random>
#include <string>
#include "boltzmann1d.h"
using namespace kami;
using namespace std;
@@ -53,14 +51,14 @@ shared_ptr<mt19937> rng = nullptr;
template <>
struct fmt::formatter<AgentID> : fmt::formatter<string> {
auto format(AgentID agent_id, format_context &ctx) {
[[maybe_unused]] static auto format(AgentID agent_id, format_context &ctx) {
return format_to(ctx.out(), "{}", agent_id.to_string());
}
};
template <>
struct fmt::formatter<GridCoord1D> : fmt::formatter<string> {
auto format(GridCoord1D coord, format_context &ctx) {
[[maybe_unused]] static auto format(const GridCoord1D& coord, format_context &ctx) {
return format_to(ctx.out(), "{}", coord.to_string());
}
};
@@ -82,7 +80,7 @@ void MoneyAgent1D::move_agent() {
console->trace("Entering move_agent");
auto agent_id = get_agent_id();
auto move_list = _world->get_neighborhood(agent_id, false);
std::uniform_int_distribution<int> dist(0, move_list.size() - 1);
std::uniform_int_distribution<int> dist(0, (int)move_list.size() - 1);
auto new_location = move_list[dist(*rng)];
console->trace("Moving Agent {} to location {}", agent_id, new_location);
@@ -90,29 +88,23 @@ void MoneyAgent1D::move_agent() {
console->trace("Exiting move_agent");
}
int MoneyAgent1D::get_wealth() { return _agent_wealth; }
void MoneyAgent1D::set_wealth(int wealth) { _agent_wealth = wealth; }
void MoneyAgent1D::give_money() {
AgentID agent_id = get_agent_id();
GridCoord1D location = _world->get_location_by_agent(agent_id);
vector<AgentID> *cell_mates = _world->get_location_contents(location);
if (cell_mates->size() > 1) {
std::uniform_int_distribution<int> dist(0, cell_mates->size() - 1);
std::uniform_int_distribution<int> dist(0, (int)cell_mates->size() - 1);
AgentID other_agent_id = cell_mates->at(dist(*rng));
auto other_agent = _model->get_agent_by_id(other_agent_id);
console->trace("Agent {} giving unit of wealth to agent {}", agent_id,
other_agent_id);
console->trace("Agent {} giving unit of wealth to agent {}", agent_id, other_agent_id);
other_agent->_agent_wealth += 1;
_agent_wealth -= 1;
}
}
BoltzmannWealthModel1D::BoltzmannWealthModel1D(unsigned int number_agents,
unsigned int length_x) {
BoltzmannWealthModel1D::BoltzmannWealthModel1D(unsigned int number_agents, unsigned int length_x) {
_world = new MultiGrid1D(length_x, true);
_sched = new RandomScheduler(this, rng);
@@ -120,23 +112,20 @@ BoltzmannWealthModel1D::BoltzmannWealthModel1D(unsigned int number_agents,
MoneyAgent1D::set_world(_world);
MoneyAgent1D::set_model(this);
std::uniform_int_distribution<int> dist(0, length_x - 1);
std::uniform_int_distribution<int> dist(0, (int)length_x - 1);
for (unsigned int i = 0; i < number_agents; i++) {
MoneyAgent1D *new_agent = new MoneyAgent1D();
auto *new_agent = new MoneyAgent1D();
_agent_list.insert(pair<AgentID, MoneyAgent1D *>(
new_agent->get_agent_id(), new_agent));
_agent_list.insert(pair<AgentID, MoneyAgent1D *>(new_agent->get_agent_id(), new_agent));
_sched->add_agent(new_agent->get_agent_id());
_world->add_agent(new_agent->get_agent_id(), GridCoord1D(dist(*rng)));
}
}
BoltzmannWealthModel1D::~BoltzmannWealthModel1D() {
for (auto agent_pair = _agent_list.begin(); agent_pair != _agent_list.end();
agent_pair++) {
delete agent_pair->second;
}
for (auto & agent_pair : _agent_list)
delete agent_pair.second;
delete _sched;
delete _world;
@@ -161,29 +150,19 @@ int main(int argc, char **argv) {
string ident = "boltzmann1d";
CLI::App app{ident};
string log_level_option = "info";
unsigned int x_size = 16, agent_count = x_size, max_steps = 100,
initial_seed = 42;
unsigned int x_size = 16, agent_count = x_size, max_steps = 100, initial_seed = 42;
app.add_option("-c", agent_count, "Set the number of agents")
->check(CLI::PositiveNumber);
app.add_option("-l", log_level_option, "Set the logging level")
->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
app.add_option("-n", max_steps, "Set the number of steps to run the model")
->check(CLI::PositiveNumber);
app.add_option("-s", initial_seed, "Set the initial seed")
->check(CLI::Number);
app.add_option("-x", x_size, "Set the number of colums")
->check(CLI::PositiveNumber);
app.add_option("-c", agent_count, "Set the number of agents")->check(CLI::PositiveNumber);
app.add_option("-l", log_level_option, "Set the logging level")->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
app.add_option("-n", max_steps, "Set the number of steps to run the model")->check(CLI::PositiveNumber);
app.add_option("-s", initial_seed, "Set the initial seed")->check(CLI::Number);
app.add_option("-x", x_size, "Set the number of columns")->check(CLI::PositiveNumber);
CLI11_PARSE(app, argc, argv);
console = spdlog::stdout_color_st(ident);
console->set_level(spdlog::level::from_str(log_level_option));
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING,
log_level_option);
console->info(
"Starting Boltzmann Wealth Model with {} agents on a {}-unit grid for "
"{} steps",
agent_count, x_size, max_steps);
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING, log_level_option);
console->info("Starting Boltzmann Wealth Model with {} agents on a {}-unit grid for {} steps",agent_count, x_size, max_steps);
rng = make_shared<mt19937>(initial_seed);
BoltzmannWealthModel1D model(agent_count, x_size);
@@ -193,6 +172,5 @@ int main(int argc, char **argv) {
console->trace("Initiating model step {}", i);
model.step();
}
console->info(
"Boltzman Wealth Model simulation complete, requiring {} seconds", sw);
console->info("Boltzmann Wealth Model simulation complete, requiring {} seconds", sw);
}

View File

@@ -24,17 +24,16 @@
*/
#pragma once
#ifndef BOLTZMAN1D_H
#define BOLTZMAN1D_H
#ifndef BOLTZMANN1D_H
#define BOLTZMANN1D_H
#include <iostream>
#include <map>
#include <kami/agent.h>
#include <kami/kami.h>
#include <kami/multigrid1d.h>
#include <kami/random.h>
#include <spdlog/spdlog.h>
#include <iostream>
#include <map>
using namespace kami;
using namespace std;
@@ -43,7 +42,7 @@ using namespace std;
* A sample agent for a one-dimensional Boltzmann wealth model
*/
class MoneyAgent1D : public Agent {
public:
public:
/**
* Create the agent
*/
@@ -52,7 +51,7 @@ class MoneyAgent1D : public Agent {
/**
* Execute a single time-step for the agent
*/
void step();
void step() override;
/**
* Give the agent a reference copy of the domain it is expected to work in
@@ -69,22 +68,12 @@ class MoneyAgent1D : public Agent {
*/
void move_agent();
/**
* Return the wealth of the agent
*/
int get_wealth();
/**
* Set the wealth of the agent
*/
void set_wealth(int wealth);
/**
* Give money to a random agent
*/
void give_money();
private:
private:
static MultiGrid1D *_world;
static BoltzmannWealthModel1D *_model;
int _step_counter;
@@ -95,16 +84,15 @@ class MoneyAgent1D : public Agent {
* The one-dimensional Boltzmann wealth model
*/
class BoltzmannWealthModel1D : public Model {
public:
public:
/**
* Create an instance of the one-dimensional Boltzman wealth model.
* Create an instance of the one-dimensional Boltzmann wealth model.
*
* @param[in] number_agents the number of agents to assign to the model.
* @param[in] length_x the length of the one-dimensional world the agents
* occupy.
*/
BoltzmannWealthModel1D(unsigned int number_agents = 10,
unsigned int length_x = 10);
explicit BoltzmannWealthModel1D(unsigned int number_agents = 10, unsigned int length_x = 10);
/**
* Destroy the instance
@@ -114,27 +102,27 @@ class BoltzmannWealthModel1D : public Model {
/**
* Execute a single time-step for the model.
*/
void step();
void step() override;
/**
* Execute a number of time-steps for the model.
*
*
* @param[in] n the number of steps to execute.
*/
void run(unsigned int n);
void run(unsigned int n) override;
/**
* Get the MoneyAgent instance associated with the given `AgentID`
*
*
* @returns an pointer to the `MoneyAgent` that was requested.
*/
MoneyAgent1D *get_agent_by_id(AgentID agent_id) const;
[[nodiscard]] MoneyAgent1D *get_agent_by_id(AgentID agent_id) const override;
private:
private:
map<AgentID, MoneyAgent1D *> _agent_list;
RandomScheduler *_sched;
MultiGrid1D *_world;
unsigned int _step_count;
};
#endif // BOLTZMAN1D_H
#endif // BOLTZMANN1D_H

View File

@@ -23,23 +23,21 @@
* SOFTWARE.
*/
#include <map>
#include <memory>
#include <random>
#include <kami/agent.h>
#include <kami/grid2d.h>
#include <kami/kami.h>
#include <kami/multigrid1d.h>
#include <kami/multigrid2d.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <spdlog/stopwatch.h>
#include <stdlib.h>
#include <CLI/App.hpp>
#include <CLI/Config.hpp>
#include <CLI/Formatter.hpp>
#include <iostream>
#include <map>
#include <memory>
#include <random>
#include <string>
#include "boltzmann2d.h"
@@ -53,14 +51,14 @@ shared_ptr<mt19937> rng = nullptr;
template <>
struct fmt::formatter<AgentID> : fmt::formatter<string> {
auto format(AgentID agent_id, format_context &ctx) {
[[maybe_unused]] static auto format(AgentID agent_id, format_context &ctx) {
return format_to(ctx.out(), "{}", agent_id.to_string());
}
};
template <>
struct fmt::formatter<GridCoord2D> : fmt::formatter<string> {
auto format(GridCoord2D coord, format_context &ctx) {
[[maybe_unused]] static auto format(const GridCoord2D& coord, format_context &ctx) {
return format_to(ctx.out(), "{}", coord.to_string());
}
};
@@ -82,7 +80,7 @@ void MoneyAgent2D::move_agent() {
console->trace("Entering move_agent");
auto agent_id = get_agent_id();
auto move_list = _world->get_neighborhood(agent_id, GridNeighborhoodType::Moore, false);
std::uniform_int_distribution<int> dist(0, move_list.size() - 1);
std::uniform_int_distribution<int> dist(0, (int) move_list.size() - 1);
auto new_location = move_list[dist(*rng)];
console->trace("Moving Agent {} to location {}", agent_id, new_location);
@@ -90,31 +88,23 @@ void MoneyAgent2D::move_agent() {
console->trace("Exiting move_agent");
}
int MoneyAgent2D::get_wealth() { return _agent_wealth; }
void MoneyAgent2D::set_wealth(int newWealth) { _agent_wealth = newWealth; }
void MoneyAgent2D::give_money() {
AgentID agent_id = get_agent_id();
GridCoord2D location = _world->get_location_by_agent(agent_id);
vector<AgentID> *cell_mates = _world->get_location_contents(location);
if (cell_mates->size() > 1) {
std::uniform_int_distribution<int> dist(0, cell_mates->size() - 1);
std::uniform_int_distribution<int> dist(0, (int)cell_mates->size() - 1);
AgentID other_agent_id = cell_mates->at(dist(*rng));
auto other_agent = _model->get_agent_by_id(other_agent_id);
console->trace("Agent {} giving unit of wealth to agent {}", agent_id,
other_agent_id);
console->trace("Agent {} giving unit of wealth to agent {}", agent_id, other_agent_id);
other_agent->_agent_wealth += 1;
_agent_wealth -= 1;
}
}
BoltzmannWealthModel2D::BoltzmannWealthModel2D(unsigned int number_agents,
unsigned int length_x,
unsigned int length_y,
unsigned int new_seed) {
BoltzmannWealthModel2D::BoltzmannWealthModel2D(unsigned int number_agents, unsigned int length_x, unsigned int length_y, unsigned int new_seed) {
rng = make_shared<mt19937>();
rng->seed(new_seed);
@@ -127,25 +117,21 @@ BoltzmannWealthModel2D::BoltzmannWealthModel2D(unsigned int number_agents,
MoneyAgent2D::set_world(_world);
MoneyAgent2D::set_model(this);
std::uniform_int_distribution<int> dist_x(0, length_x - 1);
std::uniform_int_distribution<int> dist_y(0, length_y - 1);
std::uniform_int_distribution<int> dist_x(0, (int)length_x - 1);
std::uniform_int_distribution<int> dist_y(0, (int)length_y - 1);
for (unsigned int i = 0; i < number_agents; i++) {
MoneyAgent2D *new_agent = new MoneyAgent2D();
auto *new_agent = new MoneyAgent2D();
_agent_list.insert(pair<AgentID, MoneyAgent2D *>(
new_agent->get_agent_id(), new_agent));
_agent_list.insert(pair<AgentID, MoneyAgent2D *>(new_agent->get_agent_id(), new_agent));
_sched->add_agent(new_agent->get_agent_id());
_world->add_agent(new_agent->get_agent_id(),
GridCoord2D(dist_x(*rng), dist_x(*rng)));
_world->add_agent(new_agent->get_agent_id(), GridCoord2D(dist_x(*rng), dist_x(*rng)));
}
}
BoltzmannWealthModel2D::~BoltzmannWealthModel2D() {
for (auto agent_pair = _agent_list.begin(); agent_pair != _agent_list.end();
agent_pair++) {
delete agent_pair->second;
}
for (auto & agent_pair : _agent_list)
delete agent_pair.second;
delete _sched;
delete _world;
@@ -169,31 +155,20 @@ int main(int argc, char **argv) {
std::string ident = "boltzmann2d";
CLI::App app{ident};
string log_level_option = "info";
unsigned int x_size = 16, y_size = 16, agent_count = x_size * y_size,
max_steps = 100, initial_seed = 42;
unsigned int x_size = 16, y_size = 16, agent_count = x_size * y_size, max_steps = 100, initial_seed = 42;
app.add_option("-c", agent_count, "Set the number of agents")
->check(CLI::PositiveNumber);
app.add_option("-l", log_level_option, "Set the logging level")
->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
app.add_option("-n", max_steps, "Set the number of steps to run the model")
->check(CLI::PositiveNumber);
app.add_option("-s", initial_seed, "Set the initial seed")
->check(CLI::Number);
app.add_option("-x", x_size, "Set the number of colums")
->check(CLI::PositiveNumber);
app.add_option("-y", y_size, "Set the number of rows")
->check(CLI::PositiveNumber);
app.add_option("-c", agent_count, "Set the number of agents")->check(CLI::PositiveNumber);
app.add_option("-l", log_level_option, "Set the logging level")->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
app.add_option("-n", max_steps, "Set the number of steps to run the model")->check(CLI::PositiveNumber);
app.add_option("-s", initial_seed, "Set the initial seed")->check(CLI::Number);
app.add_option("-x", x_size, "Set the number of columns")->check(CLI::PositiveNumber);
app.add_option("-y", y_size, "Set the number of rows")->check(CLI::PositiveNumber);
CLI11_PARSE(app, argc, argv);
console = spdlog::stdout_color_st(ident);
console->set_level(spdlog::level::from_str(log_level_option));
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING,
log_level_option);
console->info(
"Starting Boltzmann Wealth Model with {} agents on a {}x{}-unit grid "
"for {} steps",
agent_count, x_size, y_size, max_steps);
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING, log_level_option);
console->info("Starting Boltzmann Wealth Model with {} agents on a {}x{}-unit grid for {} steps", agent_count, x_size, y_size, max_steps);
BoltzmannWealthModel2D model(agent_count, x_size, y_size, initial_seed);
@@ -202,6 +177,5 @@ int main(int argc, char **argv) {
console->trace("Initiating model step {}", i);
model.step();
}
console->info(
"Boltzman Wealth Model simulation complete, requiring {} seconds", sw);
console->info("Boltzmann Wealth Model simulation complete, requiring {} seconds", sw);
}

View File

@@ -24,8 +24,8 @@
*/
#pragma once
#ifndef BOLTZMAN2D_H
#define BOLTZMAN2D_H
#ifndef BOLTZMANN2D_H
#define BOLTZMANN2D_H
#include <kami/agent.h>
#include <kami/kami.h>
@@ -42,7 +42,7 @@ using namespace std;
* A sample agent for a two-dimensional Boltzmann wealth model
*/
class MoneyAgent2D : public Agent {
public:
public:
/**
* Create the agent
*/
@@ -51,7 +51,7 @@ class MoneyAgent2D : public Agent {
/**
* Execute a single time-step for the agent
*/
void step();
void step() override;
/**
* Give the agent a reference copy of the domain it is expected to work in
@@ -68,22 +68,12 @@ class MoneyAgent2D : public Agent {
*/
void move_agent();
/**
* Return the wealth of the agent
*/
int get_wealth();
/**
* Set the wealth of the agent
*/
void set_wealth(int wealth);
/**
* Give money to a random agent
*/
void give_money();
private:
private:
static MultiGrid2D *_world;
static BoltzmannWealthModel2D *_model;
int _step_counter;
@@ -94,9 +84,9 @@ class MoneyAgent2D : public Agent {
* The two-dimensional Boltzmann wealth model
*/
class BoltzmannWealthModel2D : public Model {
public:
public:
/**
* Create an instance of the two-dimensional Boltzman wealth model.
* Create an instance of the two-dimensional Boltzmann wealth model.
*
* @param[in] number_agents the number of agents to assign to the model.
* @param[in] length_x the length of the two-dimensional world the agents
@@ -106,10 +96,7 @@ class BoltzmannWealthModel2D : public Model {
* @param[in] new_seed the initial seed used for the random number
* generator.
*/
BoltzmannWealthModel2D(unsigned int number_agents = 10,
unsigned int length_x = 10,
unsigned int length_y = 10,
unsigned int new_seed = 42);
explicit BoltzmannWealthModel2D(unsigned int number_agents = 10, unsigned int length_x = 10, unsigned int length_y = 10, unsigned int new_seed = 42);
/**
* Destroy the instance
@@ -119,32 +106,27 @@ class BoltzmannWealthModel2D : public Model {
/**
* Execute a single time-step for the model.
*/
void step();
void step() override;
/**
* Execute a number of time-steps for the model.
*
* @param[in] n the number of steps to execute.
*/
void run(unsigned int n);
/**
* Return the seed used to initialize the model.
*/
int get_seed() const;
void run(unsigned int n) override;
/**
* Get the MoneyAgent2D instance associated with the given `AgentID`
*
* @returns an pointer to the `MoneyAgent2D` that was requested.
*/
MoneyAgent2D *get_agent_by_id(AgentID agent_id) const;
[[nodiscard]] MoneyAgent2D *get_agent_by_id(AgentID agent_id) const override;
private:
private:
map<AgentID, MoneyAgent2D *> _agent_list;
RandomScheduler *_sched;
MultiGrid2D *_world;
unsigned int _step_count;
};
#endif // BOLTZMAN2D_H
#endif // BOLTZMANN2D_H

View File

@@ -27,11 +27,12 @@
#ifndef KAMI_AGENT_H
#define KAMI_AGENT_H
#include <kami/kami.h>
#include <iostream>
#include <string>
#include <kami/kami.h>
namespace kami {
/**
@@ -43,77 +44,77 @@ namespace kami {
*
* @see Agent
*/
class LIBKAMI_EXPORT AgentID {
public:
/**
* Constructs a new unique identifier.
*/
AgentID() : _id(_id_next++){};
class LIBKAMI_EXPORT AgentID {
public:
/**
* Constructs a new unique identifier.
*/
AgentID() : _id(_id_next++){};
/**
* Convert the identifier to a human-readable string.
*
* @return a human-readable form of the `AgentID` as `std::string`.
*/
std::string to_string() const { return std::to_string(_id); }
/**
* 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); }
/**
* Test if two `AgentID` instances are equal.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are equal and false if not.
*/
friend bool operator==(const AgentID &lhs, const AgentID &rhs);
/**
* Test if two `AgentID` instances are equal.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are equal and false if not.
*/
friend bool operator==(const AgentID &lhs, const AgentID &rhs);
/**
* Test if two `AgentID` instances are not equal.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are not equal and false if they are.
*/
friend bool operator!=(const AgentID &lhs, const AgentID &rhs);
/**
* Test if two `AgentID` instances are not equal.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are not equal and false if they are.
*/
friend bool operator!=(const AgentID &lhs, const AgentID &rhs);
/**
* Test if one AgentID is less than another.
*
* Due to the way AgentID instances are used internally,
* the AgentID must be orderable. The `<` operator provides a
* basic ordering sufficient for `std::map`.
*
* @param lhs is the left-hand side of the ordering test.
* @param rhs is the right-hand side of the ordering test.
* @return true if `lhs` is "less than" `rhs` as determined by the
* underlying implementation of the `AgentID`.
*/
friend bool operator<(const AgentID &lhs, const AgentID &rhs);
/**
* Test if one AgentID is less than another.
*
* Due to the way AgentID instances are used internally,
* the AgentID must be orderable. The `<` operator provides a
* basic ordering sufficient for `std::map`.
*
* @param lhs is the left-hand side of the ordering test.
* @param rhs is the right-hand side of the ordering test.
* @return true if `lhs` is "less than" `rhs` as determined by the
* underlying implementation of the `AgentID`.
*/
friend bool operator<(const AgentID &lhs, const AgentID &rhs);
/**
* Output an AgentID to the specified output stream
*
* The form of the output will be the same as that produced by the
* `to_string()` member function.
*
* @param lhs is the stream to output the `AgentID` to
* @param rhs is the `AgentID` to output
* @return the output stream for reuse
*/
friend std::ostream &operator<<(std::ostream &lhs, const AgentID &rhs);
/**
* Output an AgentID to the specified output stream
*
* The form of the output will be the same as that produced by the
* `to_string()` member function.
*
* @param lhs is the stream to output the `AgentID` to
* @param rhs is the `AgentID` to output
* @return the output stream for reuse
*/
friend std::ostream &operator<<(std::ostream &lhs, const AgentID &rhs);
private:
inline static long long _id_next = 1;
private:
inline static long long _id_next = 1;
/**
* The unique identifier is a `long long`.
*
* The unique identifier is an unsigned integer that increments
* monotonically with each new `AgentID` instantiated. This is
* substantially faster than other potential identifiers, such
* as MD5 hashes or UUID objects.
*/
long long _id;
};
/**
* The unique identifier is a `long long`.
*
* The unique identifier is an unsigned integer that increments
* monotonically with each new `AgentID` instantiated. This is
* substantially faster than other potential identifiers, such
* as MD5 hashes or UUID objects.
*/
long long _id;
};
/**
* A superclass for all agents.
@@ -124,58 +125,58 @@ class LIBKAMI_EXPORT AgentID {
*
* @see `StagedAgent`
*/
class LIBKAMI_EXPORT Agent {
public:
/**
* Get the `Agent`'s `AgentID`.
*
* @return the `AgentID`
*/
AgentID get_agent_id() const;
class LIBKAMI_EXPORT Agent {
public:
/**
* Get the `Agent`'s `AgentID`.
*
* @return the `AgentID`
*/
[[nodiscard]] AgentID get_agent_id() const;
/**
* Execute a time-step for the agent
*
* This function should step the agent instance. Any activities that the
* agent should perform as part of its time step should be in this function.
*/
virtual void step() = 0;
/**
* Execute a time-step for the agent
*
* This function should step the agent instance. Any activities that the
* agent should perform as part of its time step should be in this function.
*/
virtual void step() = 0;
/**
* Compare if two `Agent`s are the same `Agent`.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are equal and false if not.
*
* @note This does not compare that two Agent instances are
* identical. Accordingly, this can be used to compare two instances
* of the same Agent at different points in its time stream.
*
* Subclasses of Agent may chose to extend this operator to tighten
* the restrictioons on the comparison.
*/
friend bool operator==(const Agent &lhs, const Agent &rhs);
/**
* Compare if two `Agent`s are the same `Agent`.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are equal and false if not.
*
* @note This does not compare that two Agent instances are
* identical. Accordingly, this can be used to compare two instances
* of the same Agent at different points in its time stream.
*
* Subclasses of Agent may chose to extend this operator to tighten
* the restrictions on the comparison.
*/
friend bool operator==(const Agent &lhs, const Agent &rhs);
/**
* Compare if two `Agent`s are not the same `Agent`.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are not equal and false if they are.
*
* @note This does not compare that two Agent instances are
* identical. Accordingly, this can be used to compare two instances
* of the same `Agent` at different points in its time stream.
*
* Subclasses of `Agent` may chose to extend this operator to tighten
* the restrictioons on the comparison.
*/
friend bool operator!=(const Agent &lhs, const Agent &rhs);
/**
* Compare if two `Agent`s are not the same `Agent`.
*
* @param lhs is the left-hand side of the equality test.
* @param rhs is the right-hand side of the equality test.
* @return true is they are not equal and false if they are.
*
* @note This does not compare that two Agent instances are
* identical. Accordingly, this can be used to compare two instances
* of the same `Agent` at different points in its time stream.
*
* Subclasses of `Agent` may chose to extend this operator to tighten
* the restrictions on the comparison.
*/
friend bool operator!=(const Agent &lhs, const Agent &rhs);
private:
const AgentID _agent_id;
};
private:
const AgentID _agent_id;
};
/**
* A superclass for all staged agents.
@@ -189,17 +190,17 @@ class LIBKAMI_EXPORT Agent {
*
* `StagedAgents` must implement both the `step()` and `advance()` functions.
*/
class LIBKAMI_EXPORT StagedAgent : public Agent {
public:
/**
* Post-step advance the agent
*
* This method should be called after `step()`. Any updates or cleanups to
* the agent that must happen for the `StagedAgent` to complete its step must
* happen here.
*/
virtual void advance() = 0;
};
class LIBKAMI_EXPORT StagedAgent : public Agent {
public:
/**
* Post-step advance the agent
*
* This method should be called after `step()`. Any updates or cleanups to
* the agent that must happen for the `StagedAgent` to complete its step must
* happen here.
*/
virtual void advance() = 0;
};
} // namespace kami

View File

@@ -27,10 +27,10 @@
#ifndef KAMI_DOMAIN_H
#define KAMI_DOMAIN_H
#include <kami/kami.h>
#include <string>
#include <kami/kami.h>
namespace kami {
/**
@@ -38,7 +38,7 @@ namespace kami {
*
* Implementations of virtual environments are expected to subclass `Domain`.
*/
class LIBKAMI_EXPORT Domain {};
class LIBKAMI_EXPORT Domain {};
/**
* Provides a coordinate system for each `Domain`.
@@ -52,27 +52,27 @@ class LIBKAMI_EXPORT Domain {};
*
* @see GridCoord
*/
class LIBKAMI_EXPORT Coord {
public:
/**
* Convert the coordinate to a human-readable string.
*
* @return a human-readable form of the `Coord` as `std::string`.
*/
virtual std::string to_string() const = 0;
class LIBKAMI_EXPORT Coord {
public:
/**
* Convert the coordinate to a human-readable string.
*
* @return a human-readable form of the `Coord` as `std::string`.
*/
[[nodiscard]] virtual std::string to_string() const = 0;
/**
* Output a `Coord` to the specified output stream
*
* The form of the output will be the same as that produced by the
* `to_string()` member function.
*
* @param lhs is the stream to output the `Coord` to
* @param rhs is the `Coord` to output
* @return the output stream for reuse
*/
friend std::ostream &operator<<(std::ostream &lhs, const Coord &rhs);
};
/**
* Output a `Coord` to the specified output stream
*
* The form of the output will be the same as that produced by the
* `to_string()` member function.
*
* @param lhs is the stream to output the `Coord` to
* @param rhs is the `Coord` to output
* @return the output stream for reuse
*/
friend std::ostream &operator<<(std::ostream &lhs, const Coord &rhs);
};
} // namespace kami

View File

@@ -27,11 +27,11 @@
#ifndef KAMI_GRID_H
#define KAMI_GRID_H
#include <string>
#include <kami/domain.h>
#include <kami/kami.h>
#include <string>
namespace kami {
/**
@@ -42,47 +42,47 @@ namespace kami {
* distinction between those neighborhoods that include those cells touching on
* the corners or diagonally and those neighborhoods that do not.
*/
enum class GridNeighborhoodType {
/**
* @brief Moore neighborhood
*
* @details Moore neighborhood types include diagonally-adjacent cells as
* neighbors.
*/
Moore,
enum class GridNeighborhoodType {
/**
* @brief Moore neighborhood
*
* @details Moore neighborhood types include diagonally-adjacent cells as
* neighbors.
*/
Moore [[maybe_unused]],
/**
* @brief Von Neumann neighborhood
*
* @details Von Neumann neighborhood types do not include
* diagonally-adjacent cells as neighbors.
*/
VonNeumann
};
/**
* @brief Von Neumann neighborhood
*
* @details Von Neumann neighborhood types do not include
* diagonally-adjacent cells as neighbors.
*/
VonNeumann [[maybe_unused]]
};
/**
* @brief Distance types for orthogonal grid domains
*/
enum class GridDistanceType {
/**
* @brief Euclidean distance.
*
* @details The Euclidean distance is the length of the line segment
* connecting two points. This is commonly called a "beeline" or
* "as the crow flies."
*/
Euclidean,
enum class GridDistanceType {
/**
* @brief Euclidean distance.
*
* @details The Euclidean distance is the length of the line segment
* connecting two points. This is commonly called a "beeline" or
* "as the crow flies."
*/
Euclidean [[maybe_unused]],
/**
* @brief Manhattan distance.
*
* @details The Manhattan distance is the sum of the absolute value of the
* differences of the elements. This is commonly called the
* "taxicab distance," "rectilinear distance," or many other [formal
* names](https://en.wikipedia.org/wiki/Taxicab_geometry).
*/
Manhattan
};
/**
* @brief Manhattan distance.
*
* @details The Manhattan distance is the sum of the absolute value of the
* differences of the elements. This is commonly called the
* "taxicab distance," "rectilinear distance," or many other [formal
* names](https://en.wikipedia.org/wiki/Taxicab_geometry).
*/
Manhattan [[maybe_unused]]
};
/**
* @brief An abstract domain based on a gridded environment.
@@ -91,15 +91,15 @@ enum class GridDistanceType {
* rectilinear grid where the cells are equal size and laid out in an ordered
* fashion.
*/
class LIBKAMI_EXPORT GridDomain : public Domain {};
class LIBKAMI_EXPORT GridDomain : public Domain {};
/**
* @brief An abstract for gridded coordinates.
*
* @details All gridded coordinates are expected to subclass `GridCoord`.
*/
class LIBKAMI_EXPORT GridCoord : public Coord {};
class LIBKAMI_EXPORT GridCoord : public Coord {};
} // namespace kami
#endif // KAMI_DOMAIN_H
#endif // KAMI_GRID_H

View File

@@ -27,223 +27,221 @@
#ifndef KAMI_GRID1D_H
#define KAMI_GRID1D_H
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/kami.h>
#include <iostream>
#include <map>
#include <vector>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/kami.h>
namespace kami {
/**
* One-dimensional coordinates
*/
class LIBKAMI_EXPORT GridCoord1D : public GridCoord {
public:
/**
* Constructor for one-dimensional coordinates
*/
GridCoord1D(int x_coord) : _x_coord(x_coord){};
class LIBKAMI_EXPORT GridCoord1D : public GridCoord {
public:
/**
* Constructor for one-dimensional coordinates
*/
explicit GridCoord1D(int x_coord) : _x_coord(x_coord){};
/**
* Return the `x` coordinate
*/
int get_x_location(void) const;
/**
* Return the `x` coordinate
*/
[[nodiscard]] int get_x_location() const;
/**
* Convert the coordinate to a human-readable string.
*
* @return a human-readable form of the `Coord` as `std::string`.
*/
std::string to_string() const;
/**
* Convert the coordinate to a human-readable string.
*
* @return a human-readable form of the `Coord` as `std::string`.
*/
[[nodiscard]] std::string to_string() const override;
/**
* Test if two coordinates are equal
*/
friend bool operator==(const GridCoord1D &lhs, const GridCoord1D &rhs);
/**
* Test if two coordinates are equal
*/
friend bool operator==(const GridCoord1D &lhs, const GridCoord1D &rhs);
/**
* Test if two coordinates are not equal
*/
friend bool operator!=(const GridCoord1D &lhs, const GridCoord1D &rhs);
/**
* Test if two coordinates are not equal
*/
friend bool operator!=(const GridCoord1D &lhs, const GridCoord1D &rhs);
/**
* Output a given coordinate to the specified stream
*/
friend std::ostream &operator<<(std::ostream &lhs, const GridCoord1D &rhs);
/**
* Output a given coordinate to the specified stream
*/
friend std::ostream &operator<<(std::ostream &lhs, const GridCoord1D &rhs);
private:
int _x_coord;
};
private:
int _x_coord;
};
/**
* A one-dimensional grid where each cell may contain agents
*
* The grid is linear and may wrap around in its only dimension.
*
*
* @see `MultiGrid1D`
* @see `SoloGrid1D`
*/
class LIBKAMI_EXPORT Grid1D : public GridDomain {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid.
* @param[in] wrap_x should the grid wrap around on itself.
*/
Grid1D(unsigned int maximum_x, bool wrap_x = false);
class LIBKAMI_EXPORT Grid1D : public GridDomain {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid.
* @param[in] wrap_x should the grid wrap around on itself.
*/
explicit Grid1D(unsigned int maximum_x, bool wrap_x = false);
/**
* Deconstructor
*/
virtual ~Grid1D();
/**
* Deconstructor
*/
virtual ~Grid1D();
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true.
*/
virtual bool add_agent(AgentID agent_id, GridCoord1D coord) = 0;
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true.
*/
virtual bool add_agent(AgentID agent_id, GridCoord1D coord) = 0;
/**
* Remove agent from the grid.
*
* @param[in] agent_id the `AgentID` of the agent to remove.
*
* @returns false if the agent is not removed, otherwise, true.
*/
bool delete_agent(AgentID agent_id);
/**
* Remove agent from the grid.
*
* @param[in] agent_id the `AgentID` of the agent to remove.
*
* @returns false if the agent is not removed, otherwise, true.
*/
[[maybe_unused]] [[maybe_unused]] bool delete_agent(AgentID agent_id);
/**
* Remove agent from the grid at the specified location
*
* @param[in] agent_id the `AgentID` of the agent to remove.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not removed, otherwise, true.
*/
virtual bool delete_agent(AgentID agent_id, GridCoord1D coord);
/**
* Remove agent from the grid at the specified location
*
* @param[in] agent_id the `AgentID` of the agent to remove.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not removed, otherwise, true.
*/
bool delete_agent(AgentID agent_id, const GridCoord1D &coord);
/**
* Move an agent to the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to move.
* @param[in] coord the coordinates of the agent.
*/
bool move_agent(AgentID agent_id, GridCoord1D coord);
/**
* Move an agent to the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to move.
* @param[in] coord the coordinates of the agent.
*/
bool move_agent(AgentID agent_id, GridCoord1D coord);
/**
* Inquire if the specified location is empty.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location has no `Agent`s occupying it, false
* otherwise.
*/
bool is_location_empty(GridCoord1D coord) const;
/**
* Inquire if the specified location is empty.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location has no `Agent`s occupying it, false
* otherwise.
*/
[[nodiscard]] bool is_location_empty(const GridCoord1D& coord) const;
/**
* Inquire if the specified location is valid within the grid.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location specified is valid, false otherwise.
*/
bool is_location_valid(GridCoord1D coord) const;
/**
* Inquire if the specified location is valid within the grid.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location specified is valid, false otherwise.
*/
[[nodiscard]] bool is_location_valid(const GridCoord1D& coord) const;
/**
* Get the location of the specified agent.
*
* @param[in] agent_id the `AgentID` of the agent in question.
*
* @return the location of the specified `Agent`
*/
GridCoord1D get_location_by_agent(AgentID agent_id) const;
/**
* Get the location of the specified agent.
*
* @param[in] agent_id the `AgentID` of the agent in question.
*
* @return the location of the specified `Agent`
*/
[[nodiscard]] GridCoord1D get_location_by_agent(AgentID agent_id) const;
/**
* Get the contents of the specified location.
*
* @param[in] coord the coordinates of the query.
*
* @return a pointer to a `vector` of `AgentID`s. The pointer is to the
* internal copy of the agent list at the location, therefore, any changes
* to that object will update the state of the gird. Further, the pointer
* should not be deleted when no longer used.
*/
std::vector<AgentID> *get_location_contents(GridCoord1D coord) const;
/**
* Get the contents of the specified location.
*
* @param[in] coord the coordinates of the query.
*
* @return a pointer to a `vector` of `AgentID`s. The pointer is to the
* internal copy of the agent list at the location, therefore, any changes
* to that object will update the state of the gird. Further, the pointer
* should not be deleted when no longer used.
*/
[[nodiscard]] std::vector<AgentID> *get_location_contents(const GridCoord1D& coord) const;
/**
* Inquire to whether the grid wraps in the `x` dimension.
*
* @return true if the grid wraps, and false otherwise
*/
bool get_wrap_x(void) const;
/**
* Inquire to whether the grid wraps in the `x` dimension.
*
* @return true if the grid wraps, and false otherwise
*/
[[maybe_unused]] [[maybe_unused]] [[nodiscard]] bool get_wrap_x() const;
/**
* Return the neighborhood of the specified Agent
*
* @param[in] agent_id the `AgentID` of the agent in question
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*/
std::vector<GridCoord1D> get_neighborhood(AgentID agent_id,
bool include_center) const;
/**
* Return the neighborhood of the specified Agent
*
* @param[in] agent_id the `AgentID` of the agent in question
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*/
[[nodiscard]] std::vector<GridCoord1D> get_neighborhood(AgentID agent_id, bool include_center) const;
/**
* Return the neighborhood of the specified location
*
* @param[in] coord the coordinates of the specified location.
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*/
std::vector<GridCoord1D> get_neighborhood(GridCoord1D coord,
bool include_center) const;
/**
* Return the neighborhood of the specified location
*
* @param[in] coord the coordinates of the specified location.
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*/
[[nodiscard]] std::vector<GridCoord1D> get_neighborhood(const GridCoord1D& coord, bool include_center) const;
/**
* Get the size of the grid in the `x` dimension.
*
* @return the length of the grid in the `x` dimension
*/
unsigned int get_maximum_x(void) const;
/**
* Get the size of the grid in the `x` dimension.
*
* @return the length of the grid in the `x` dimension
*/
[[maybe_unused]] [[nodiscard]] unsigned int get_maximum_x() const;
protected:
/**
* A vector containing the `AgentID`s of all agents assgined to this
* grid.
*/
std::vector<AgentID> *_agent_grid;
protected:
/**
* A vector containing the `AgentID`s of all agents assigned to this
* grid.
*/
std::vector<AgentID> *_agent_grid;
/**
* A map containing the grid location of each agent.
*/
std::map<AgentID, GridCoord1D> *_agent_index;
/**
* A map containing the grid location of each agent.
*/
std::map<AgentID, GridCoord1D> *_agent_index;
/**
* Automatically adjust a coordinate location for wrapping.
*
* @param[in] coord the coordinates of the specified location.
*
* @return the adjusted coordinate wrapped if appropriate.
*/
GridCoord1D coord_wrap(GridCoord1D coord) const;
/**
* Automatically adjust a coordinate location for wrapping.
*
* @param[in] coord the coordinates of the specified location.
*
* @return the adjusted coordinate wrapped if appropriate.
*/
[[nodiscard]] GridCoord1D coord_wrap(const GridCoord1D& coord) const;
private:
unsigned int _maximum_x;
bool _wrap_x;
};
private:
unsigned int _maximum_x;
bool _wrap_x;
};
} // namespace kami

View File

@@ -27,62 +27,62 @@
#ifndef KAMI_GRID2D_H
#define KAMI_GRID2D_H
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/kami.h>
#include <iostream>
#include <map>
#include <vector>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/kami.h>
namespace kami {
/**
* Two-dimensional coordinates
*/
class LIBKAMI_EXPORT GridCoord2D : public GridCoord {
public:
/**
* Constructor for two-dimensional coordinates
*/
GridCoord2D(int x_coord, int y_coord)
: _x_coord(x_coord), _y_coord(y_coord){};
class LIBKAMI_EXPORT GridCoord2D : public GridCoord {
public:
/**
* Constructor for two-dimensional coordinates
*/
GridCoord2D(int x_coord, int y_coord)
: _x_coord(x_coord), _y_coord(y_coord){};
/**
* Get the coordinate in the first dimension or `x`.
*/
int get_x_location(void) const;
/**
* Get the coordinate in the first dimension or `x`.
*/
[[nodiscard]] int get_x_location() const;
/**
* Get the coordinate in the second dimension or `y`.
*/
int get_y_location(void) const;
/**
* Get the coordinate in the second dimension or `y`.
*/
[[nodiscard]] int get_y_location() const;
/**
* Convert the coordinate to a human-readable string.
*
* @return a human-readable form of the `Coord` as `std::string`.
*/
std::string to_string() const;
/**
* Convert the coordinate to a human-readable string.
*
* @return a human-readable form of the `Coord` as `std::string`.
*/
[[nodiscard]] std::string to_string() const override;
/**
* Test if two coordinates are equal
*/
friend bool operator==(const GridCoord2D &, const GridCoord2D &);
/**
* Test if two coordinates are equal
*/
friend bool operator==(const GridCoord2D &, const GridCoord2D &);
/**
* Test if two coordinates are not equal
*/
friend bool operator!=(const GridCoord2D &, const GridCoord2D &);
/**
* Test if two coordinates are not equal
*/
friend bool operator!=(const GridCoord2D &, const GridCoord2D &);
/**
* Output a given coordinate to the specified stream
*/
friend std::ostream &operator<<(std::ostream &, const GridCoord2D &);
/**
* Output a given coordinate to the specified stream
*/
friend std::ostream &operator<<(std::ostream &, const GridCoord2D &);
private:
int _x_coord, _y_coord;
};
private:
int _x_coord, _y_coord;
};
/**
* A two-dimensional grid where each cell may contain agents
@@ -92,191 +92,187 @@ class LIBKAMI_EXPORT GridCoord2D : public GridCoord {
* @see `MultiGrid2D`
* @see `SoloGrid2D`
*/
class LIBKAMI_EXPORT Grid2D : public GridDomain {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid in the first dimension
* @param[in] maximum_y the length of the grid in the second dimension
* @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
*/
Grid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x = false,
bool wrap_y = false);
class LIBKAMI_EXPORT Grid2D : public GridDomain {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid in the first dimension
* @param[in] maximum_y the length of the grid in the second dimension
* @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
*/
Grid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x = false,
bool wrap_y = false);
/**
* Deconstructor
*/
virtual ~Grid2D();
/**
* Deconstructor
*/
virtual ~Grid2D();
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true.
*/
virtual bool add_agent(AgentID agent_id, GridCoord2D coord) = 0;
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true.
*/
virtual bool add_agent(AgentID agent_id, GridCoord2D coord) = 0;
/**
* Remove agent from the grid.
*
* @param[in] agent_id the `AgentID` of the agent to remove.
*
* @returns false if the agent is not removed, otherwise, true.
*/
bool delete_agent(AgentID agent_id);
/**
* Remove agent from the grid.
*
* @param[in] agent_id the `AgentID` of the agent to remove.
*
* @returns false if the agent is not removed, otherwise, true.
*/
[[maybe_unused]] bool delete_agent(AgentID agent_id);
/**
* Remove agent from the grid at the specified location
*
* @param[in] agent_id the `AgentID` of the agent to remove.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not removed, otherwise, true.
*/
virtual bool delete_agent(AgentID agent_id, GridCoord2D coord);
/**
* Remove agent from the grid at the specified location
*
* @param[in] agent_id the `AgentID` of the agent to remove.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not removed, otherwise, true.
*/
bool delete_agent(AgentID agent_id, const GridCoord2D &coord);
/**
* Move an agent to the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to move.
* @param[in] coord the coordinates of the agent.
*/
bool move_agent(AgentID agent_id, GridCoord2D coord);
/**
* Move an agent to the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to move.
* @param[in] coord the coordinates of the agent.
*/
bool move_agent(AgentID agent_id, GridCoord2D coord);
/**
* Inquire if the specified location is empty.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location has no `Agent`s occupying it, false
* otherwise.
*/
bool is_location_empty(GridCoord2D coord) const;
/**
* Inquire if the specified location is empty.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location has no `Agent`s occupying it, false
* otherwise.
*/
[[nodiscard]] bool is_location_empty(const GridCoord2D& coord) const;
/**
* Inquire if the specified location is valid within the grid.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location specified is valid, false otherwise.
*/
bool is_location_valid(GridCoord2D coord) const;
/**
* Inquire if the specified location is valid within the grid.
*
* @param[in] coord the coordinates of the query.
*
* @return true if the location specified is valid, false otherwise.
*/
[[nodiscard]] bool is_location_valid(const GridCoord2D& coord) const;
/**
* Get the location of the specified agent.
*
* @param[in] agent_id the `AgentID` of the agent in question.
*
* @return the location of the specified `Agent`
*/
GridCoord2D get_location_by_agent(AgentID agent_id) const;
/**
* Get the location of the specified agent.
*
* @param[in] agent_id the `AgentID` of the agent in question.
*
* @return the location of the specified `Agent`
*/
[[nodiscard]] GridCoord2D get_location_by_agent(AgentID agent_id) const;
/**
* Get the contents of the specified location.
*
* @param[in] coord the coordinates of the query.
*
* @return a pointer to a `vector` of `AgentID`s. The pointer is to the
* internal copy of the agent list at the location, therefore, any changes
* to that object will update the state of the gird. Further, the pointer
* should not be deleted when no longer used.
*/
std::vector<AgentID> *get_location_contents(GridCoord2D coord) const;
/**
* Get the contents of the specified location.
*
* @param[in] coord the coordinates of the query.
*
* @return a pointer to a `vector` of `AgentID`s. The pointer is to the
* internal copy of the agent list at the location, therefore, any changes
* to that object will update the state of the gird. Further, the pointer
* should not be deleted when no longer used.
*/
[[nodiscard]] std::vector<AgentID> *get_location_contents(const GridCoord2D& coord) const;
/**
* Inquire to whether the grid wraps in the `x` dimension.
*
* @return true if the grid wraps, and false otherwise
*/
bool get_wrap_x(void) const;
/**
* Inquire to whether the grid wraps in the `x` dimension.
*
* @return true if the grid wraps, and false otherwise
*/
[[maybe_unused]] [[nodiscard]] bool get_wrap_x() const;
/**
* Inquire to whether the grid wraps in the `y` dimension.
*
* @return true if the grid wraps, and false otherwise
*/
bool get_wrap_y(void) const;
/**
* Inquire to whether the grid wraps in the `y` dimension.
*
* @return true if the grid wraps, and false otherwise
*/
[[maybe_unused]] [[nodiscard]] bool get_wrap_y() const;
/**
* Return the neighborhood of the specified Agent
*
* @param[in] agent_id the `AgentID` of the agent in question.
* @param[in] neighborhood_type the neighborhood type.
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*
* @see `NeighborhoodType`
*/
std::vector<GridCoord2D> get_neighborhood(
AgentID agent_id, GridNeighborhoodType neighborhood_type,
bool include_center) const;
/**
* Return the neighborhood of the specified Agent
*
* @param[in] agent_id the `AgentID` of the agent in question.
* @param[in] neighborhood_type the neighborhood type.
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*
* @see `NeighborhoodType`
*/
[[nodiscard]] std::vector<GridCoord2D> get_neighborhood(AgentID agent_id, GridNeighborhoodType neighborhood_type, bool include_center) const;
/**
* Return the neighborhood of the specified location
*
* @param[in] coord the coordinates of the specified location.
* @param[in] neighborhood_type the neighborhood type.
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*
* @see `NeighborhoodType`
*/
std::vector<GridCoord2D> get_neighborhood(
GridCoord2D coord, GridNeighborhoodType neighborhood_type,
bool include_center) const;
/**
* Return the neighborhood of the specified location
*
* @param[in] coord the coordinates of the specified location.
* @param[in] neighborhood_type the neighborhood type.
* @param[in] include_center should the center-point, occupied by the agent,
* be in the list.
*
* @return a vector of `GridCoord1D` that includes all of the coordinates
* for all adjacent points.
*
* @see `NeighborhoodType`
*/
[[nodiscard]] std::vector<GridCoord2D> get_neighborhood(const GridCoord2D& coord, GridNeighborhoodType neighborhood_type, bool include_center) const;
/**
* Get the size of the grid in the `x` dimension.
*
* @return the length of the grid in the `x` dimension
*/
unsigned int get_maximum_x(void) const;
/**
* Get the size of the grid in the `x` dimension.
*
* @return the length of the grid in the `x` dimension
*/
[[maybe_unused]] [[nodiscard]] unsigned int get_maximum_x() const;
/**
* Get the size of the grid in the `y` dimension.
*
* @return the length of the grid in the `xy dimension
*/
unsigned int get_maximum_y(void) const;
/**
* Get the size of the grid in the `y` dimension.
*
* @return the length of the grid in the `xy dimension
*/
[[maybe_unused]] [[nodiscard]] unsigned int get_maximum_y() const;
protected:
/**
* A vector containing the `AgentID`s of all agents assgined to this
* grid.
*/
std::vector<AgentID> **_agent_grid;
protected:
/**
* A vector containing the `AgentID`s of all agents assigned to this
* grid.
*/
std::vector<AgentID> **_agent_grid;
/**
* A map containing the grid location of each agent.
*/
std::map<AgentID, GridCoord2D> *_agent_index;
/**
* A map containing the grid location of each agent.
*/
std::map<AgentID, GridCoord2D> *_agent_index;
/**
* Automatically adjust a coordinate location for wrapping.
*
* @param[in] coord the coordinates of the specified location.
*
* @return the adjusted coordinate wrapped if appropriate.
*/
GridCoord2D coord_wrap(GridCoord2D coord) const;
/**
* Automatically adjust a coordinate location for wrapping.
*
* @param[in] coord the coordinates of the specified location.
*
* @return the adjusted coordinate wrapped if appropriate.
*/
[[nodiscard]] GridCoord2D coord_wrap(const GridCoord2D& coord) const;
private:
unsigned int _maximum_x, _maximum_y;
bool _wrap_x, _wrap_y;
};
private:
unsigned int _maximum_x, _maximum_y;
bool _wrap_x, _wrap_y;
};
} // namespace kami

View File

@@ -35,34 +35,34 @@ namespace kami {
/**
* An abstract for generic models
*/
class LIBKAMI_EXPORT Model {
public:
/**
* Get a reference to an `Agent` by `AgentID`
*
* @param[in] agent_id the `AgentID` to search for.
*
* @return a reference to the desired `Agent` or `nullptr` if not found.
*/
virtual Agent *get_agent_by_id(AgentID agent_id) const = 0;
class LIBKAMI_EXPORT Model {
public:
/**
* Get a reference to an `Agent` by `AgentID`
*
* @param[in] agent_id the `AgentID` to search for.
*
* @return a reference to the desired `Agent` or `nullptr` if not found.
*/
[[nodiscard]] virtual Agent *get_agent_by_id(AgentID agent_id) const = 0;
/**
* Execute a fixed number of time-steps for the model.
*
* This function should execute a fixed number of time-steps for the model.
*
* @param[in] n the number of time steps to execute.
*/
virtual void run(unsigned int n) = 0;
/**
* Execute a fixed number of time-steps for the model.
*
* This function should execute a fixed number of time-steps for the model.
*
* @param[in] n the number of time steps to execute.
*/
[[maybe_unused]] virtual void run(unsigned int n) = 0;
/**
* Execute a single time-step for the model.
*
* This function should step the model instance. Any activities that the
* model should perform as part of its time step should be in this function.
*/
virtual void step() = 0;
};
/**
* Execute a single time-step for the model.
*
* This function should step the model instance. Any activities that the
* model should perform as part of its time step should be in this function.
*/
virtual void step() = 0;
};
} // namespace kami

View File

@@ -40,28 +40,28 @@ namespace kami {
*
* @details The grid is linear and may wrap around in its only dimension.
*/
class LIBKAMI_EXPORT MultiGrid1D : public Grid1D {
public:
/**
* Constructor
*
* @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) {}
class LIBKAMI_EXPORT MultiGrid1D : public Grid1D {
public:
/**
* Constructor
*
* @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) {}
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord1D coord);
};
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord1D coord) override;
};
} // namespace kami

View File

@@ -43,32 +43,32 @@ namespace kami {
* @see `Grid2D`
* @see `SoloGrid2D`
*/
class LIBKAMI_EXPORT MultiGrid2D : public Grid2D {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid in the first dimension
* @param[in] maximum_y the length of the grid in the second dimension
* @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
*/
MultiGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x,
bool wrap_y);
class LIBKAMI_EXPORT MultiGrid2D : public Grid2D {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid in the first dimension
* @param[in] maximum_y the length of the grid in the second dimension
* @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
*/
MultiGrid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x, bool wrap_y)
: Grid2D(maximum_x, maximum_y, wrap_x, wrap_y) {};
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord2D coord);
};
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord2D coord) override;
};
} // namespace kami

View File

@@ -47,62 +47,50 @@ namespace kami {
*
* @note First create a Model for the scheduler to live in.
*/
class LIBKAMI_EXPORT RandomScheduler : public SequentialScheduler {
public:
/**
* @brief Constructor.
*
* @details The `model` parameter is used by the scheduler to get
* access to an `Agent`. The `Model` is presumed to maintain a master
* list of all `Agent`s in the `Model` and the `Model` can be queried for
* a reference to any particular `Agent` at `step()` time.
*
* @param model [in] A reference to the model the scheduler is timing.
*/
RandomScheduler(Model *model);
class LIBKAMI_EXPORT RandomScheduler : public SequentialScheduler {
public:
/**
* @brief Constructor.
*
* @details The `model` parameter is used by the scheduler to get
* access to an `Agent`. The `Model` is presumed to maintain a master
* list of all `Agent`s in the `Model` and the `Model` can be queried for
* a reference to any particular `Agent` at `step()` time.
*
* @param model [in] A reference to the model the scheduler is timing.
* @param rng [in] A uniform random number generator of type
* `std::mt19937`, used as the source of randomness.
*/
RandomScheduler(Model *model, std::shared_ptr<std::mt19937> rng);
/**
* @brief Constructor.
*
* @details The `model` parameter is used by the scheduler to get
* access to an `Agent`. The `Model` is presumed to maintain a master
* list of all `Agent`s in the `Model` and the `Model` can be queried for
* a reference to any particular `Agent` at `step()` time.
*
* @param model [in] A reference to the model the scheduler is timing.
* @param rng [in] A uniform random number generator of type
* `std::mt19937`, used as the source of randomness.
*/
RandomScheduler(Model *model, std::shared_ptr<std::mt19937> rng);
/**
* @brief Execute a single time step.
*
* @details This method will randomize the list of Agents in the scheduler's
* internal queue and then execute the `Agent::step()` method for every
* Agent assigned to this scheduler in the randomized order.
*/
void step() override;
/**
* @brief Execute a single time step.
*
* @details This method will randomize the list of Agents in the scheduler's
* internal queue and then execute the `Agent::step()` method for every
* Agent assigned to this scheduler in the randomized order.
*/
void step();
/**
* Set the random number generator used to randomize the order of agent
* stepping.
*
* @param rng [in] A uniform random number generator of type `std::mt19937`,
* used as the source of randomness.
*/
void set_rng(std::shared_ptr<std::mt19937> rng);
/**
* Set the random number generator used to randomize the order of agent
* stepping.
*
* @param rng [in] A uniform random number generator of type `std::mt19937`,
* used as the source of randomness.
*/
void set_rng(std::shared_ptr<std::mt19937> rng);
/**
* Get a reference to the random number generator used to randomize
* the order of agent stepping.
*/
[[maybe_unused]] std::shared_ptr<std::mt19937> get_rng();
/**
* Get a reference to the random number generator used to randomize
* the order of agent stepping.
*/
std::shared_ptr<std::mt19937> get_rng();
private:
std::shared_ptr<std::mt19937> _rng;
};
private:
std::shared_ptr<std::mt19937> _rng;
};
}; // namespace kami
} // namespace kami
#endif // KAMI_RANDOM_H

View File

@@ -39,29 +39,29 @@ namespace kami {
* scheduler will have a collection of agents assigned to it and will execute
* the step function for each agent based on the type of scheduling implemented.
*/
class LIBKAMI_EXPORT Scheduler {
public:
/**
* Add an Agent to the Scheduler.
*
* @param agent_id The AgentID of the agent to add.
*/
virtual void add_agent(AgentID agent_id) = 0;
class LIBKAMI_EXPORT Scheduler {
public:
/**
* Add an Agent to the Scheduler.
*
* @param agent_id The AgentID of the agent to add.
*/
virtual void add_agent(AgentID agent_id) = 0;
/**
* Remove an Agent from the Scheduler.
*
* @param agent_id The AgentID of the agent to remove.
*/
virtual void delete_agent(AgentID agent_id) = 0;
/**
* Remove an Agent from the Scheduler.
*
* @param agent_id The AgentID of the agent to remove.
*/
[[maybe_unused]] virtual void delete_agent(AgentID agent_id) = 0;
/**
* Step the Scheduler.
*
* A generic step function that executes a single time step.
*/
virtual void step() = 0;
};
/**
* Step the Scheduler.
*
* A generic step function that executes a single time step.
*/
virtual void step() = 0;
};
} // namespace kami

View File

@@ -27,14 +27,14 @@
#ifndef KAMI_SEQUENTIAL_H
#define KAMI_SEQUENTIAL_H
#include <algorithm>
#include <vector>
#include <kami/KAMI_EXPORT.h>
#include <kami/agent.h>
#include <kami/model.h>
#include <kami/scheduler.h>
#include <algorithm>
#include <vector>
namespace kami {
/**
@@ -47,62 +47,62 @@ namespace kami {
*
* \pre First create a Model for the scheduler to live in.
*/
class LIBKAMI_EXPORT SequentialScheduler : public Scheduler {
public:
/**
* @brief Constructor.
*
* @details The Model parameter is used by the scheduler to get
* access to an Agent. The Model is presumed to maintain a master
* list of all Agents in the Model and the Model can be queried for
* a reference to any particular Agent at `step()` time.
*/
SequentialScheduler(Model *model);
class LIBKAMI_EXPORT SequentialScheduler : public Scheduler {
public:
/**
* @brief Constructor.
*
* @details The Model parameter is used by the scheduler to get
* access to an Agent. The Model is presumed to maintain a master
* list of all Agents in the Model and the Model can be queried for
* a reference to any particular Agent at `step()` time.
*/
explicit SequentialScheduler(Model *model);
/**
* @brief Add an agent to the scheduler.
*
* @details The scheduler maintains a list of all AgentIDs currently
* assigned. This function adds a new Agent to the list.
*/
void add_agent(AgentID agent_id);
/**
* @brief Add an agent to the scheduler.
*
* @details The scheduler maintains a list of all AgentIDs currently
* assigned. This function adds a new Agent to the list.
*/
void add_agent(AgentID agent_id) override;
/**
* @brief Remove an agent from the scheduler.
*
* @details The scheduler maintains a list of all AgentIDs currently
* assigned. This function removes an Agent from the list.
*/
void delete_agent(AgentID agent_id);
/**
* @brief Remove an agent from the scheduler.
*
* @details The scheduler maintains a list of all AgentIDs currently
* assigned. This function removes an Agent from the list.
*/
void delete_agent(AgentID agent_id) override;
/**
* @brief Execute a single time step.
*
* @details This method will step through the list of Agents in the
* scheduler's internal queue and then execute the `Agent::step()`
* method for every Agent assigned to this scheduler in the order
* assigned.
*/
void step();
/**
* @brief Execute a single time step.
*
* @details This method will step through the list of Agents in the
* scheduler's internal queue and then execute the `Agent::step()`
* method for every Agent assigned to this scheduler in the order
* assigned.
*/
void step() override;
protected:
/**
* A vector containing the `AgentID`s of all agents assgined to this
* scheduler
*/
std::vector<AgentID> _agent_list;
protected:
/**
* A vector containing the `AgentID`s of all agents assigned to this
* scheduler
*/
std::vector<AgentID> _agent_list;
/**
* A pointer to the `Model` this scehduler belongs to
*/
Model *_model;
/**
* A pointer to the `Model` this scheduler belongs to
*/
Model *_model;
/**
* Counter to increment on each step
*/
int _step_counter;
};
/**
* Counter to increment on each step
*/
int _step_counter;
};
}; // namespace kami
} // namespace kami
#endif // KAMI_SEQUENTIAL_H

View File

@@ -29,8 +29,6 @@
#include <kami/KAMI_EXPORT.h>
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid1d.h>
#include <kami/kami.h>
@@ -41,28 +39,28 @@ namespace kami {
*
* @details The grid is linear and may wrap around in its only dimension.
*/
class LIBKAMI_EXPORT SoloGrid1D : public Grid1D {
public:
/**
* Constructor
*
* @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) {}
class LIBKAMI_EXPORT SoloGrid1D : public Grid1D {
public:
/**
* Constructor
*
* @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) {}
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord1D coord);
};
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord1D coord) override;
};
} // namespace kami

View File

@@ -27,14 +27,11 @@
#ifndef KAMI_SOLOGRID2D_H
#define KAMI_SOLOGRID2D_H
#include <kami/KAMI_EXPORT.h>
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid2d.h>
#include <kami/kami.h>
#include <vector>
namespace kami {
/**
@@ -45,30 +42,30 @@ namespace kami {
* @see `MultiGrid2D`
* @see `Grid2D`
*/
class LIBKAMI_EXPORT SoloGrid2D : public Grid2D {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid in the first dimension
* @param[in] maximum_y the length of the grid in the second dimension
* @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);
class LIBKAMI_EXPORT SoloGrid2D : public Grid2D {
public:
/**
* Constructor
*
* @param[in] maximum_x the length of the grid in the first dimension
* @param[in] maximum_y the length of the grid in the second dimension
* @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) {};
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord2D coord);
};
/**
* Place agent on the grid at the specified location.
*
* @param[in] agent_id the `AgentID` of the agent to add.
* @param[in] coord the coordinates of the agent.
*
* @returns false if the agent is not placed at the specified
* location, otherwise, true
*/
bool add_agent(AgentID agent_id, GridCoord2D coord) override;
};
} // namespace kami

View File

@@ -46,54 +46,54 @@ namespace kami {
*
* @note First create a Model for the scheduler to live in.
*/
class LIBKAMI_EXPORT StagedScheduler : public Scheduler {
public:
/**
* Constructor.
* The Model parameter is used by the scheduler to get access to an Agent.
* The Model is presumed to maintain a master list of all Agents in the
* Model and the Model can be queried for a reference to any particular
* Agent at `step()` time.
*/
StagedScheduler(Model *);
class LIBKAMI_EXPORT StagedScheduler : public Scheduler {
public:
/**
* Constructor.
* The Model parameter is used by the scheduler to get access to an Agent.
* The Model is presumed to maintain a master list of all Agents in the
* Model and the Model can be queried for a reference to any particular
* Agent at `step()` time.
*/
explicit StagedScheduler(Model *);
/**
* A deconstructor.
*/
virtual ~StagedScheduler();
/**
* A deconstructor.
*/
~StagedScheduler() = default;
/**
* Add an agent to the scheduler.
*
* The scheduler maintains a list of all AgentIDs currently assigned. This
* function adds a new Agent to the list.
*/
void add_agent(AgentID agent_id);
/**
* Add an agent to the scheduler.
*
* The scheduler maintains a list of all AgentIDs currently assigned. This
* function adds a new Agent to the list.
*/
void add_agent(AgentID agent_id) override;
/**
* Remove an agent from the scheduler.
*
* The scheduler maintains a list of all AgentIDs currently assigned. This
* function removes an Agent from the list.
*/
void delete_agent(AgentID agent_id);
/**
* Remove an agent from the scheduler.
*
* The scheduler maintains a list of all AgentIDs currently assigned. This
* function removes an Agent from the list.
*/
void delete_agent(AgentID agent_id) override;
/**
* Execute a single time step.
*
* 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.
*/
void step();
/**
* Execute a single time step.
*
* 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.
*/
void step() override;
private:
std::vector<AgentID> _agent_list;
Model *_model;
int _step_counter;
};
private:
std::vector<AgentID> _agent_list;
Model *_model;
int _step_counter;
};
}; // namespace kami
} // namespace kami
#endif // KAMI_STAGED_H

View File

@@ -30,28 +30,28 @@
namespace kami {
bool operator==(const AgentID &lhs, const AgentID &rhs) {
return lhs._id == rhs._id;
}
bool operator==(const AgentID &lhs, const AgentID &rhs) {
return lhs._id == rhs._id;
}
bool operator!=(const AgentID &lhs, const AgentID &rhs) {
return !(lhs == rhs);
}
bool operator!=(const AgentID &lhs, const AgentID &rhs) {
return !(lhs == rhs);
}
bool operator<(const AgentID &lhs, const AgentID &rhs) {
return lhs._id < rhs._id;
}
bool operator<(const AgentID &lhs, const AgentID &rhs) {
return lhs._id < rhs._id;
}
std::ostream &operator<<(std::ostream &lhs, const AgentID &rhs) {
return lhs << rhs.to_string();
}
std::ostream &operator<<(std::ostream &lhs, const AgentID &rhs) {
return lhs << rhs.to_string();
}
AgentID Agent::get_agent_id() const { return this->_agent_id; }
AgentID Agent::get_agent_id() const { return this->_agent_id; }
bool operator==(const Agent &lhs, const Agent &rhs) {
return lhs._agent_id == rhs._agent_id;
}
bool operator==(const Agent &lhs, const Agent &rhs) {
return lhs._agent_id == rhs._agent_id;
}
bool operator!=(const Agent &lhs, const Agent &rhs) { return !(lhs == rhs); }
bool operator!=(const Agent &lhs, const Agent &rhs) { return !(lhs == rhs); }
} // namespace kami

View File

@@ -30,8 +30,8 @@
namespace kami {
std::ostream &operator<<(std::ostream &lhs, const Coord &rhs) {
return lhs << rhs.to_string();
}
std::ostream &operator<<(std::ostream &lhs, const Coord &rhs) {
return lhs << rhs.to_string();
}
} // namespace kami

View File

@@ -25,135 +25,132 @@
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid1d.h>
#include <kami/kami.h>
#include <map>
#include <utility>
#include <vector>
namespace kami {
int GridCoord1D::get_x_location() const { return _x_coord; }
int GridCoord1D::get_x_location() const { return _x_coord; }
std::string GridCoord1D::to_string() const {
return std::string("(" + std::to_string(_x_coord) + ")");
}
std::string GridCoord1D::to_string() const {
return std::string("(" + std::to_string(_x_coord) + ")");
}
bool operator==(const GridCoord1D &lhs, const GridCoord1D &rhs) {
return (lhs._x_coord == rhs._x_coord);
}
bool operator==(const GridCoord1D &lhs, const GridCoord1D &rhs) {
return (lhs._x_coord == rhs._x_coord);
}
bool operator!=(const GridCoord1D &lhs, const GridCoord1D &rhs) {
return !(lhs == rhs);
}
bool operator!=(const GridCoord1D &lhs, const GridCoord1D &rhs) {
return !(lhs == rhs);
}
std::ostream &operator<<(std::ostream &lhs, const GridCoord1D &rhs) {
return lhs << rhs.to_string();
}
std::ostream &operator<<(std::ostream &lhs, const GridCoord1D &rhs) {
return lhs << rhs.to_string();
}
Grid1D::Grid1D(unsigned int maximum_x, bool wrap_x) {
_agent_grid = new std::vector<AgentID>[maximum_x];
_agent_index = new std::map<AgentID, GridCoord1D>;
_maximum_x = maximum_x;
_wrap_x = wrap_x;
}
Grid1D::Grid1D(unsigned int maximum_x, bool wrap_x) {
_agent_grid = new std::vector<AgentID>[maximum_x];
_agent_index = new std::map<AgentID, GridCoord1D>;
Grid1D::~Grid1D(void) {
delete _agent_index;
delete[] _agent_grid;
}
_maximum_x = maximum_x;
_wrap_x = wrap_x;
}
bool Grid1D::delete_agent(AgentID agent_id) {
GridCoord1D coord = get_location_by_agent(agent_id);
Grid1D::~Grid1D() {
delete _agent_index;
delete[] _agent_grid;
}
return delete_agent(agent_id, coord);
}
[[maybe_unused]] bool Grid1D::delete_agent(AgentID agent_id) {
GridCoord1D coord = get_location_by_agent(agent_id);
bool Grid1D::is_location_valid(GridCoord1D coord) const {
auto x = coord.get_x_location();
return (x >= 0 && x < static_cast<int>(_maximum_x));
}
return delete_agent(agent_id, coord);
}
bool Grid1D::is_location_empty(GridCoord1D coord) const {
auto x = coord.get_x_location();
bool Grid1D::is_location_valid(const GridCoord1D& coord) const {
auto x = coord.get_x_location();
return (x >= 0 && x < static_cast<int>(_maximum_x));
}
return _agent_grid[x].size() == 0;
}
bool Grid1D::is_location_empty(const GridCoord1D &coord) const {
auto x = coord.get_x_location();
bool Grid1D::delete_agent(AgentID agent_id, GridCoord1D coord) {
auto agent_list = _agent_grid[static_cast<int>(coord.get_x_location())];
return _agent_grid[x].empty();
}
for (auto test_agent_id = agent_list.begin();
test_agent_id < agent_list.end(); test_agent_id++) {
if (*test_agent_id == agent_id) {
agent_list.erase(test_agent_id);
_agent_index->erase(agent_id);
return true;
bool Grid1D::delete_agent(AgentID agent_id, const GridCoord1D &coord) {
auto agent_list = _agent_grid[static_cast<int>(coord.get_x_location())];
for (auto test_agent_id = agent_list.begin();
test_agent_id < agent_list.end(); test_agent_id++) {
if (*test_agent_id == agent_id) {
agent_list.erase(test_agent_id);
_agent_index->erase(agent_id);
return true;
}
}
return false;
}
return false;
}
bool Grid1D::move_agent(AgentID agent_id, GridCoord1D coord) {
GridCoord1D coord_current = get_location_by_agent(agent_id);
bool Grid1D::move_agent(AgentID agent_id, GridCoord1D coord) {
GridCoord1D coord_current = get_location_by_agent(agent_id);
if (delete_agent(agent_id, coord_current) == true)
return add_agent(agent_id, coord);
return false;
}
std::vector<GridCoord1D> Grid1D::get_neighborhood(AgentID agent_id,
bool include_center) const {
GridCoord1D coord = get_location_by_agent(agent_id);
return get_neighborhood(coord, include_center);
}
std::vector<GridCoord1D> Grid1D::get_neighborhood(GridCoord1D coord,
bool include_center) const {
std::vector<GridCoord1D> neighborhood;
auto x = coord.get_x_location();
// We assume our starting position is valid
if (include_center == true) neighborhood.push_back(coord);
// E, W
{
auto new_location = coord_wrap(GridCoord1D(x + 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord1D(x - 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
if (delete_agent(agent_id, coord_current))
return add_agent(agent_id, std::move(coord));
return false;
}
return neighborhood;
}
std::vector<GridCoord1D> Grid1D::get_neighborhood(AgentID agent_id, bool include_center) const {
GridCoord1D coord = get_location_by_agent(agent_id);
std::vector<AgentID> *Grid1D::get_location_contents(GridCoord1D coord) const {
if (is_location_valid(coord)) return &_agent_grid[coord.get_x_location()];
return nullptr;
}
return get_neighborhood(coord, include_center);
}
bool Grid1D::get_wrap_x(void) const { return _wrap_x; }
std::vector<GridCoord1D> Grid1D::get_neighborhood(const GridCoord1D& coord, bool include_center) const {
std::vector<GridCoord1D> neighborhood;
auto x = coord.get_x_location();
unsigned int Grid1D::get_maximum_x(void) const { return _maximum_x; }
// We assume our starting position is valid
if (include_center) neighborhood.push_back(coord);
GridCoord1D Grid1D::get_location_by_agent(AgentID agent_id) const {
return _agent_index->at(agent_id);
}
// E, W
{
auto new_location = coord_wrap(GridCoord1D(x + 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord1D(x - 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
GridCoord1D Grid1D::coord_wrap(GridCoord1D coord) const {
auto x = coord.get_x_location();
return neighborhood;
}
if (_wrap_x == true)
x = (x + static_cast<int>(_maximum_x)) % static_cast<int>(_maximum_x);
return GridCoord1D(x);
}
std::vector<AgentID> *Grid1D::get_location_contents(const GridCoord1D& coord) const {
if (is_location_valid(coord)) return &_agent_grid[coord.get_x_location()];
return nullptr;
}
[[maybe_unused]] bool Grid1D::get_wrap_x() const { return _wrap_x; }
[[maybe_unused]] unsigned int Grid1D::get_maximum_x() const { return _maximum_x; }
GridCoord1D Grid1D::get_location_by_agent(AgentID agent_id) const {
return _agent_index->at(agent_id);
}
GridCoord1D Grid1D::coord_wrap(const GridCoord1D& coord) const {
auto x = coord.get_x_location();
if(_wrap_x)
x = (x + static_cast<int>(_maximum_x)) % static_cast<int>(_maximum_x);
return GridCoord1D(x);
}
} // namespace kami

View File

@@ -23,202 +23,198 @@
* SOFTWARE.
*/
#include <map>
#include <utility>
#include <vector>
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid2d.h>
#include <kami/kami.h>
#include <map>
#include <vector>
namespace kami {
int GridCoord2D::get_x_location(void) const {
return _x_coord;
}
int GridCoord2D::get_x_location() const {
return _x_coord;
}
int GridCoord2D::get_y_location(void) const {
return _y_coord;
}
int GridCoord2D::get_y_location() const {
return _y_coord;
}
std::string GridCoord2D::to_string() const {
return std::string("(" + std::to_string(_x_coord) + ", " +
std::to_string(_y_coord) + ")");
}
std::string GridCoord2D::to_string() const {
return std::string("(" + std::to_string(_x_coord) + ", " +
std::to_string(_y_coord) + ")");
}
bool operator==(const GridCoord2D &lhs, const GridCoord2D &rhs) {
return (lhs._x_coord == rhs._x_coord && lhs._y_coord == rhs._y_coord);
}
bool operator==(const GridCoord2D &lhs, const GridCoord2D &rhs) {
return (lhs._x_coord == rhs._x_coord && lhs._y_coord == rhs._y_coord);
}
bool operator!=(const GridCoord2D &lhs, const GridCoord2D &rhs) {
return !(lhs == rhs);
}
bool operator!=(const GridCoord2D &lhs, const GridCoord2D &rhs) {
return !(lhs == rhs);
}
std::ostream &operator<<(std::ostream &lhs, const GridCoord2D &rhs) {
return lhs << rhs.to_string();
}
std::ostream &operator<<(std::ostream &lhs, const GridCoord2D &rhs) {
return lhs << rhs.to_string();
}
Grid2D::Grid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x,
bool wrap_y) {
_maximum_x = maximum_x;
_maximum_y = maximum_y;
_wrap_x = wrap_x;
_wrap_y = wrap_y;
Grid2D::Grid2D(unsigned int maximum_x, unsigned int maximum_y, bool wrap_x,
bool wrap_y) {
_maximum_x = maximum_x;
_maximum_y = maximum_y;
_wrap_x = wrap_x;
_wrap_y = wrap_y;
_agent_grid = new std::vector<AgentID> *[_maximum_x];
for (auto i = 0; i < _maximum_x; i++)
_agent_grid[i] = new std::vector<AgentID>[_maximum_y];
_agent_grid = new std::vector<AgentID> *[_maximum_x];
for (auto i = 0; i < _maximum_x; i++)
_agent_grid[i] = new std::vector<AgentID>[_maximum_y];
_agent_index = new std::map<AgentID, GridCoord2D>;
}
_agent_index = new std::map<AgentID, GridCoord2D>;
}
Grid2D::~Grid2D(void) {
delete _agent_index;
Grid2D::~Grid2D() {
delete _agent_index;
for (auto i = 0; i < _maximum_x; i++) delete[] _agent_grid[i];
delete[] _agent_grid;
}
for (auto i = 0; i < _maximum_x; i++) delete[] _agent_grid[i];
delete[] _agent_grid;
}
bool Grid2D::delete_agent(AgentID agent_id) {
auto location = get_location_by_agent(agent_id);
[[maybe_unused]] bool Grid2D::delete_agent(AgentID agent_id) {
auto coord = get_location_by_agent(agent_id);
return delete_agent(agent_id, location);
}
return delete_agent(agent_id, coord);
}
bool Grid2D::delete_agent(AgentID agent_id, GridCoord2D location) {
auto agent_list = _agent_grid[static_cast<int>(location.get_x_location())]
[static_cast<int>(location.get_y_location())];
for (auto test_agent_id = agent_list.begin();
test_agent_id < agent_list.end(); test_agent_id++) {
if (*test_agent_id == agent_id) {
agent_list.erase(test_agent_id);
_agent_index->erase(agent_id);
return true;
bool Grid2D::delete_agent(AgentID agent_id, const GridCoord2D &coord) {
auto agent_list = _agent_grid[static_cast<int>(coord.get_x_location())][static_cast<int>(coord.get_y_location())];
for (auto test_agent_id = agent_list.begin();
test_agent_id < agent_list.end(); test_agent_id++) {
if (*test_agent_id == agent_id) {
agent_list.erase(test_agent_id);
_agent_index->erase(agent_id);
return true;
}
}
return false;
}
return false;
}
bool Grid2D::is_location_valid(const GridCoord2D& coord) const {
auto x = coord.get_x_location();
auto y = coord.get_y_location();
bool Grid2D::is_location_valid(GridCoord2D location) const {
auto x = location.get_x_location();
auto y = location.get_y_location();
return (x >= 0 && x < static_cast<int>(_maximum_x) && y >= 0 &&
y < static_cast<int>(_maximum_y));
}
GridCoord2D Grid2D::get_location_by_agent(AgentID agent_id) const {
return _agent_index->at(agent_id);
}
bool Grid2D::move_agent(AgentID agent_id, GridCoord2D coord) {
GridCoord2D current_location = get_location_by_agent(agent_id);
if (delete_agent(agent_id, current_location) == true)
return add_agent(agent_id, coord);
return false;
}
bool Grid2D::get_wrap_x(void) const { return _wrap_x; }
bool Grid2D::get_wrap_y(void) const { return _wrap_y; }
std::vector<GridCoord2D> Grid2D::get_neighborhood(
AgentID agent_id, GridNeighborhoodType neighborhood_type,
bool includeCenter) const {
GridCoord2D location = get_location_by_agent(agent_id);
return get_neighborhood(location, neighborhood_type, includeCenter);
}
std::vector<GridCoord2D> Grid2D::get_neighborhood(
GridCoord2D location, GridNeighborhoodType neighborhood_type,
bool include_center) const {
std::vector<GridCoord2D> neighborhood;
auto x = location.get_x_location();
auto y = location.get_y_location();
// We assume our starting position is valid
if (include_center) neighborhood.push_back(location);
// N, E, S, W
{
auto new_location = coord_wrap(GridCoord2D(x, y - 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x, y + 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x + 1, y));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x - 1, y));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
return (x >= 0 && x < static_cast<int>(_maximum_x) && y >= 0 &&
y < static_cast<int>(_maximum_y));
}
if (neighborhood_type == GridNeighborhoodType::Moore) {
// NE, SE, SW, NW
GridCoord2D Grid2D::get_location_by_agent(AgentID agent_id) const {
return _agent_index->at(agent_id);
}
bool Grid2D::move_agent(AgentID agent_id, GridCoord2D coord) {
GridCoord2D current_location = get_location_by_agent(agent_id);
if (delete_agent(agent_id, current_location))
return add_agent(agent_id, std::move(coord));
return false;
}
[[maybe_unused]] bool Grid2D::get_wrap_x() const { return _wrap_x; }
[[maybe_unused]] bool Grid2D::get_wrap_y() const { return _wrap_y; }
std::vector<GridCoord2D> Grid2D::get_neighborhood(
AgentID agent_id, GridNeighborhoodType neighborhood_type,
bool includeCenter) const {
GridCoord2D location = get_location_by_agent(agent_id);
return get_neighborhood(location, neighborhood_type, includeCenter);
}
std::vector<GridCoord2D> Grid2D::get_neighborhood(const GridCoord2D& location, GridNeighborhoodType neighborhood_type, bool include_center) const {
std::vector<GridCoord2D> neighborhood;
auto x = location.get_x_location();
auto y = location.get_y_location();
// We assume our starting position is valid
if (include_center) neighborhood.push_back(location);
// N, E, S, W
{
auto new_location = coord_wrap(GridCoord2D(x + 1, y - 1));
auto new_location = coord_wrap(GridCoord2D(x, y - 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x + 1, y + 1));
auto new_location = coord_wrap(GridCoord2D(x, y + 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x - 1, y + 1));
auto new_location = coord_wrap(GridCoord2D(x + 1, y));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x - 1, y - 1));
auto new_location = coord_wrap(GridCoord2D(x - 1, y));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
if (neighborhood_type == GridNeighborhoodType::Moore) {
// NE, SE, SW, NW
{
auto new_location = coord_wrap(GridCoord2D(x + 1, y - 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x + 1, y + 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x - 1, y + 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
{
auto new_location = coord_wrap(GridCoord2D(x - 1, y - 1));
if (is_location_valid(new_location))
neighborhood.push_back(coord_wrap(new_location));
}
}
return neighborhood;
}
return neighborhood;
}
std::vector<AgentID> *Grid2D::get_location_contents(const GridCoord2D& coord) const {
if (is_location_valid(coord) && !is_location_empty(coord))
return &_agent_grid[coord.get_x_location()][coord.get_y_location()];
std::vector<AgentID> *Grid2D::get_location_contents(
GridCoord2D location) const {
if (is_location_valid(location) && !is_location_empty(location)) {
return &_agent_grid[location.get_x_location()]
[location.get_y_location()];
return nullptr;
}
return nullptr;
}
[[maybe_unused]] unsigned int Grid2D::get_maximum_x() const { return _maximum_x; }
[[maybe_unused]] unsigned int Grid2D::get_maximum_y() const { return _maximum_y; }
unsigned int Grid2D::get_maximum_x(void) const { return _maximum_x; }
unsigned int Grid2D::get_maximum_y(void) const { return _maximum_y; }
GridCoord2D Grid2D::coord_wrap(const GridCoord2D& coord) const {
auto x = coord.get_x_location();
auto y = coord.get_y_location();
GridCoord2D Grid2D::coord_wrap(GridCoord2D location) const {
auto x = location.get_x_location();
auto y = location.get_y_location();
if (_wrap_x)
x = (x + static_cast<int>(_maximum_x)) % static_cast<int>(_maximum_x);
if (_wrap_x)
y = (y + static_cast<int>(_maximum_y)) % static_cast<int>(_maximum_y);
return {x, y};
}
if (_wrap_x)
x = (x + static_cast<int>(_maximum_x)) % static_cast<int>(_maximum_x);
if (_wrap_x)
y = (y + static_cast<int>(_maximum_y)) % static_cast<int>(_maximum_y);
return GridCoord2D(x, y);
}
bool Grid2D::is_location_empty(const GridCoord2D& coord) const {
auto x = coord.get_x_location();
auto y = coord.get_y_location();
bool Grid2D::is_location_empty(GridCoord2D location) const {
auto x = location.get_x_location();
auto y = location.get_y_location();
return _agent_grid[x][y].size() == 0;
}
return _agent_grid[x][y].empty();
}
} // namespace kami

View File

@@ -25,21 +25,19 @@
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid1d.h>
#include <kami/kami.h>
#include <kami/multigrid1d.h>
namespace kami {
bool MultiGrid1D::add_agent(AgentID agent_id, GridCoord1D coord) {
if (is_location_valid(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord1D>(agent_id, coord));
_agent_grid[coord.get_x_location()].push_back(agent_id);
return (true);
bool MultiGrid1D::add_agent(AgentID agent_id, GridCoord1D coord) {
if (is_location_valid(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord1D>(agent_id, coord));
_agent_grid[coord.get_x_location()].push_back(agent_id);
return (true);
}
return (false);
}
return (false);
}
} // namespace kami

View File

@@ -25,26 +25,20 @@
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid2d.h>
#include <kami/kami.h>
#include <kami/multigrid2d.h>
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) {}
bool MultiGrid2D::add_agent(AgentID agent_id, GridCoord2D coord) {
if (is_location_valid(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord2D>(agent_id, coord));
_agent_grid[coord.get_x_location()][coord.get_y_location()].push_back(
agent_id);
return true;
}
bool MultiGrid2D::add_agent(AgentID agent_id, GridCoord2D coord) {
if (is_location_valid(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord2D>(agent_id, coord));
_agent_grid[coord.get_x_location()][coord.get_y_location()].push_back(
agent_id);
return true;
return false;
}
return false;
}
} // namespace kami

View File

@@ -23,35 +23,29 @@
* SOFTWARE.
*/
#include <kami/agent.h>
#include <kami/model.h>
#include <kami/random.h>
#include <kami/scheduler.h>
#include <chrono>
#include <iostream>
#include <random>
#include <string>
#include <utility>
#include <kami/model.h>
#include <kami/random.h>
namespace kami {
RandomScheduler::RandomScheduler(Model *model) : SequentialScheduler(model) {}
RandomScheduler::RandomScheduler(Model *model, std::shared_ptr<std::mt19937> rng)
: SequentialScheduler(model) {
this->set_rng(std::move(rng));
}
RandomScheduler::RandomScheduler(Model *model,
std::shared_ptr<std::mt19937> rng)
: SequentialScheduler(model) {
this->set_rng(rng);
}
void RandomScheduler::step() {
shuffle(_agent_list.begin(), _agent_list.end(), *_rng);
this->SequentialScheduler::step();
}
void RandomScheduler::step() {
shuffle(_agent_list.begin(), _agent_list.end(), *_rng);
this->SequentialScheduler::step();
}
void RandomScheduler::set_rng(std::shared_ptr<std::mt19937> rng) {
this->_rng = std::move(rng);
}
void RandomScheduler::set_rng(std::shared_ptr<std::mt19937> rng) {
this->_rng = rng;
}
std::shared_ptr<std::mt19937> RandomScheduler::get_rng() { return (_rng); }
[[maybe_unused]] std::shared_ptr<std::mt19937> RandomScheduler::get_rng() { return (_rng); }
} // namespace kami

View File

@@ -23,42 +23,37 @@
* SOFTWARE.
*/
#include <string>
#include <kami/agent.h>
#include <kami/model.h>
#include <kami/scheduler.h>
#include <kami/sequential.h>
#include <random>
#include <string>
namespace kami {
SequentialScheduler::SequentialScheduler(Model *model) {
_step_counter = 0;
_model = model;
}
void SequentialScheduler::add_agent(AgentID agent_id) {
_agent_list.push_back(agent_id);
}
void SequentialScheduler::delete_agent(AgentID agent_id) {
for (auto agent_list_iter = _agent_list.begin();
agent_list_iter < _agent_list.end(); agent_list_iter++)
if (*agent_list_iter == agent_id) _agent_list.erase(agent_list_iter);
return;
// ERROR HERE
}
void SequentialScheduler::step() {
_step_counter++;
for (auto agent_list_iter = _agent_list.begin();
agent_list_iter < _agent_list.end(); agent_list_iter++) {
Agent *agent = _model->get_agent_by_id(*agent_list_iter);
if (agent != nullptr) agent->step();
SequentialScheduler::SequentialScheduler(Model *model) {
_step_counter = 0;
_model = model;
}
void SequentialScheduler::add_agent(AgentID agent_id) {
_agent_list.push_back(agent_id);
}
void SequentialScheduler::delete_agent(AgentID agent_id) {
for (auto agent_list_iter = _agent_list.begin(); agent_list_iter < _agent_list.end(); agent_list_iter++)
if (*agent_list_iter == agent_id) _agent_list.erase(agent_list_iter);
// ERROR HERE
}
void SequentialScheduler::step() {
_step_counter++;
for (auto agent_list_iter = _agent_list.begin();
agent_list_iter < _agent_list.end(); agent_list_iter++) {
Agent *agent = _model->get_agent_by_id(*agent_list_iter);
if (agent != nullptr) agent->step();
}
}
}
} // namespace kami

View File

@@ -24,22 +24,18 @@
*/
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid1d.h>
#include <kami/kami.h>
#include <kami/sologrid1d.h>
namespace kami {
bool SoloGrid1D::add_agent(AgentID agent_id, GridCoord1D coord) {
if (is_location_valid(coord) & is_location_empty(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord1D>(agent_id, coord));
_agent_grid[coord.get_x_location()].push_back(agent_id);
return true;
bool SoloGrid1D::add_agent(AgentID agent_id, GridCoord1D coord) {
if (is_location_valid(coord) & is_location_empty(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord1D>(agent_id, coord));
_agent_grid[coord.get_x_location()].push_back(agent_id);
return true;
}
return false;
}
return false;
}
} // namespace kami

View File

@@ -24,29 +24,20 @@
*/
#include <kami/agent.h>
#include <kami/domain.h>
#include <kami/grid.h>
#include <kami/grid2d.h>
#include <kami/kami.h>
#include <kami/sologrid2d.h>
#include <vector>
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) {}
bool SoloGrid2D::add_agent(AgentID agent_id, GridCoord2D coord) {
if (is_location_valid(coord) & is_location_empty(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord2D>(agent_id, coord));
_agent_grid[coord.get_x_location()][coord.get_y_location()].push_back(agent_id);
return true;
}
bool SoloGrid2D::add_agent(AgentID agent_id, GridCoord2D coord) {
if (is_location_valid(coord) & is_location_empty(coord)) {
_agent_index->insert(std::pair<AgentID, GridCoord2D>(agent_id, coord));
_agent_grid[coord.get_x_location()][coord.get_y_location()].push_back(
agent_id);
return true;
return false;
}
return false;
}
} // namespace kami

View File

@@ -23,55 +23,40 @@
* SOFTWARE.
*/
#include <string>
#include <kami/agent.h>
#include <kami/model.h>
#include <kami/scheduler.h>
#include <kami/sequential.h>
#include <kami/staged.h>
#include <random>
#include <string>
namespace kami {
StagedScheduler::StagedScheduler(Model *model) {
_step_counter = 0;
_model = model;
}
StagedScheduler::~StagedScheduler() {}
void StagedScheduler::add_agent(AgentID agent_id) {
_agent_list.push_back(agent_id);
}
void StagedScheduler::delete_agent(AgentID agent_id) {
for (auto agent_list_iter = _agent_list.begin();
agent_list_iter < _agent_list.end(); agent_list_iter++)
if (*agent_list_iter == agent_id) _agent_list.erase(agent_list_iter);
return;
}
void StagedScheduler::step() {
_step_counter++;
for (auto agent_list_iter = _agent_list.begin();
agent_list_iter < _agent_list.end(); agent_list_iter++) {
StagedAgent *agent = dynamic_cast<StagedAgent *>(
_model->get_agent_by_id(*agent_list_iter));
if (agent != nullptr) agent->step();
// ERROR HERE
StagedScheduler::StagedScheduler(Model *model) {
_step_counter = 0;
_model = model;
}
for (auto agent_list_iter = _agent_list.begin();
agent_list_iter < _agent_list.end(); agent_list_iter++) {
StagedAgent *agent = dynamic_cast<StagedAgent *>(
_model->get_agent_by_id(*agent_list_iter));
if (agent != nullptr) agent->advance();
// ERROR HERE
void StagedScheduler::add_agent(AgentID agent_id) {
_agent_list.push_back(agent_id);
}
return;
}
void StagedScheduler::delete_agent(AgentID agent_id) {
for (auto agent_list_iter = _agent_list.begin(); agent_list_iter < _agent_list.end(); agent_list_iter++)
if (*agent_list_iter == agent_id) _agent_list.erase(agent_list_iter);
}
void StagedScheduler::step() {
_step_counter++;
for (auto agent_list_iter = _agent_list.begin(); agent_list_iter < _agent_list.end(); agent_list_iter++) {
auto *agent = dynamic_cast<StagedAgent *>(_model->get_agent_by_id(*agent_list_iter));
if (agent != nullptr) agent->step();
}
for (auto agent_list_iter = _agent_list.begin(); agent_list_iter < _agent_list.end(); agent_list_iter++) {
auto *agent = dynamic_cast<StagedAgent *>(_model->get_agent_by_id(*agent_list_iter));
if (agent != nullptr) agent->advance();
}
}
} // namespace kami

View File

@@ -23,21 +23,23 @@
* SOFTWARE.
*/
#include <string>
#include <kami/agent.h>
#include <kami/config.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <CLI/App.hpp>
#include <CLI/Config.hpp>
#include <CLI/Formatter.hpp>
#include <string>
using namespace kami;
using namespace std;
class TestAgent : public Agent {
void step(){};
void step() override {};
};
int main(int argc, char **argv) {
@@ -46,15 +48,12 @@ int main(int argc, char **argv) {
auto console = spdlog::stdout_color_st(ident);
string logLevelOption = "info";
app.add_option("-l", logLevelOption, "Set the logging level")
->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
app.add_option("-l", logLevelOption, "Set the logging level")->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
CLI11_PARSE(app, argc, argv);
console->set_level(spdlog::level::from_str(logLevelOption));
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING,
logLevelOption);
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING, logLevelOption);
TestAgent test_agent;
console->debug("Successfully created Agent with ID {}",
test_agent.get_agent_id().to_string());
console->debug("Successfully created Agent with ID {}", test_agent.get_agent_id().to_string());
}

View File

@@ -23,15 +23,17 @@
* SOFTWARE.
*/
#include <string>
#include <kami/agent.h>
#include <kami/config.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <CLI/App.hpp>
#include <CLI/Config.hpp>
#include <CLI/Formatter.hpp>
#include <string>
using namespace kami;
using namespace std;
@@ -42,15 +44,12 @@ int main(int argc, char **argv) {
auto console = spdlog::stdout_color_st(ident);
string logLevelOption = "info";
app.add_option("-l", logLevelOption, "Set the logging level")
->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
app.add_option("-l", logLevelOption, "Set the logging level")->check(CLI::IsMember(SPDLOG_LEVEL_NAMES));
CLI11_PARSE(app, argc, argv);
console->set_level(spdlog::level::from_str(logLevelOption));
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING,
logLevelOption);
console->info("Compiled with Kami/{}, log level {}", KAMI_VERSION_STRING, logLevelOption);
AgentID testAgentID;
console->debug("Successfully created AgentID with ID {}",
testAgentID.to_string());
console->debug("Successfully created AgentID with ID {}", testAgentID.to_string());
}