mirror of
https://github.com/JHUAPL/kami.git
synced 2026-01-09 14:58:02 -05:00
Initial import
This commit is contained in:
@@ -6,13 +6,18 @@
|
|||||||
# For many purposes, you may not need to change anything about this file.
|
# For many purposes, you may not need to change anything about this file.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.8.2)
|
cmake_minimum_required(VERSION 3.8.2)
|
||||||
|
project("KAMI" CXX)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/")
|
||||||
|
|
||||||
|
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||||
|
conan_basic_setup()
|
||||||
|
|
||||||
# Set project name, version and laguages here. (change as needed)
|
# Set project name, version and laguages here. (change as needed)
|
||||||
# Version numbers are available by including "exampleConfig.h" in
|
# Version numbers are available by including "exampleConfig.h" in
|
||||||
# the source. See exampleConfig.h.in for some more details.
|
# the source. See exampleConfig.h.in for some more details.
|
||||||
project(CPP_BOILERPLATE VERSION 1.2.3.4 LANGUAGES CXX)
|
project(CPP_BOILERPLATE VERSION 1.2.3.4 LANGUAGES CXX)
|
||||||
|
|
||||||
|
|
||||||
# Options: Things you can set via commandline options to cmake (e.g. -DENABLE_LTO=[ON|OFF])
|
# Options: Things you can set via commandline options to cmake (e.g. -DENABLE_LTO=[ON|OFF])
|
||||||
option(ENABLE_WARNINGS_SETTINGS "Allow target_set_warnings to add flags and defines.
|
option(ENABLE_WARNINGS_SETTINGS "Allow target_set_warnings to add flags and defines.
|
||||||
Set this to OFF if you want to provide your own warning parameters." ON)
|
Set this to OFF if you want to provide your own warning parameters." ON)
|
||||||
@@ -38,12 +43,15 @@ find_lto(CXX)
|
|||||||
# Locate files (change as needed).
|
# Locate files (change as needed).
|
||||||
# --------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------
|
||||||
set(SOURCES # All .cpp files in src/
|
set(SOURCES # All .cpp files in src/
|
||||||
src/example.cpp
|
src/agent.cpp
|
||||||
|
src/kami.cpp
|
||||||
|
src/multigrid2d.cpp
|
||||||
|
src/random.cpp
|
||||||
)
|
)
|
||||||
set(TESTFILES # All .cpp files in tests/
|
set(TESTFILES # All .cpp files in tests/
|
||||||
tests/main.cpp
|
tests/dummy.cpp
|
||||||
)
|
)
|
||||||
set(LIBRARY_NAME engine) # Default name for the library built from src/*.cpp (change if you wish)
|
set(LIBRARY_NAME kami) # Default name for the library built from src/*.cpp (change if you wish)
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------
|
||||||
# Build! (Change as needed)
|
# Build! (Change as needed)
|
||||||
@@ -55,7 +63,7 @@ add_library(${LIBRARY_NAME} OBJECT ${SOURCES})
|
|||||||
target_include_directories(${LIBRARY_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(${LIBRARY_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
# There's also (probably) doctests within the library, so we need to see this as well.
|
# There's also (probably) doctests within the library, so we need to see this as well.
|
||||||
target_link_libraries(${LIBRARY_NAME} PUBLIC doctest)
|
target_link_libraries(${LIBRARY_NAME} PUBLIC spdlog)
|
||||||
|
|
||||||
# Set the compile options you want (change as needed).
|
# Set the compile options you want (change as needed).
|
||||||
target_set_warnings(${LIBRARY_NAME} ENABLE ALL AS_ERROR ALL DISABLE Annoying)
|
target_set_warnings(${LIBRARY_NAME} ENABLE ALL AS_ERROR ALL DISABLE Annoying)
|
||||||
@@ -63,16 +71,16 @@ target_set_warnings(${LIBRARY_NAME} ENABLE ALL AS_ERROR ALL DISABLE Annoying)
|
|||||||
|
|
||||||
# Add an executable for the file app/main.cpp.
|
# Add an executable for the file app/main.cpp.
|
||||||
# If you add more executables, copy these lines accordingly.
|
# If you add more executables, copy these lines accordingly.
|
||||||
add_executable(main app/main.cpp) # Name of exec. and location of file.
|
add_executable(boltzmann examples/boltzmann.cpp) # Name of exec. and location of file.
|
||||||
target_link_libraries(main PRIVATE ${LIBRARY_NAME}) # Link the executable to library (if it uses it).
|
target_link_libraries(boltzmann PRIVATE ${LIBRARY_NAME}) # Link the executable to library (if it uses it).
|
||||||
target_set_warnings(main ENABLE ALL AS_ERROR ALL DISABLE Annoying) # Set warnings (if needed).
|
target_set_warnings(boltzmann ENABLE ALL AS_ERROR ALL DISABLE Annoying) # Set warnings (if needed).
|
||||||
target_enable_lto(main optimized) # enable link-time-optimization if available for non-debug configurations
|
target_enable_lto(boltzmann optimized) # enable link-time-optimization if available for non-debug configurations
|
||||||
|
|
||||||
# Set the properties you require, e.g. what C++ standard to use. Here applied to library and main (change as needed).
|
# Set the properties you require, e.g. what C++ standard to use. Here applied to library and main (change as needed).
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
${LIBRARY_NAME} main
|
${LIBRARY_NAME} boltzmann
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
CXX_STANDARD_REQUIRED YES
|
CXX_STANDARD_REQUIRED YES
|
||||||
CXX_EXTENSIONS NO
|
CXX_EXTENSIONS NO
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ Example:
|
|||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
> mkdir build && cd build
|
> mkdir build && cd build
|
||||||
|
> conan install ..
|
||||||
> cmake .. -DCMAKE_BUILD_TYPE=[Debug | Coverage | Release]
|
> cmake .. -DCMAKE_BUILD_TYPE=[Debug | Coverage | Release]
|
||||||
> make
|
> make
|
||||||
> ./main
|
> ./main
|
||||||
|
|||||||
35
app/main.cpp
35
app/main.cpp
@@ -1,35 +0,0 @@
|
|||||||
// Executables must have the following defined if the library contains
|
|
||||||
// doctest definitions. For builds with this disabled, e.g. code shipped to
|
|
||||||
// users, this can be left out.
|
|
||||||
#ifdef ENABLE_DOCTEST_IN_LIBRARY
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT
|
|
||||||
#include "doctest.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "exampleConfig.h"
|
|
||||||
#include "example.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Simple main program that demontrates how access
|
|
||||||
* CMake definitions (here the version number) from source code.
|
|
||||||
*/
|
|
||||||
int main() {
|
|
||||||
std::cout << "C++ Boiler Plate v"
|
|
||||||
<< PROJECT_VERSION_MAJOR
|
|
||||||
<< "."
|
|
||||||
<< PROJECT_VERSION_MINOR
|
|
||||||
<< "."
|
|
||||||
<< PROJECT_VERSION_PATCH
|
|
||||||
<< "."
|
|
||||||
<< PROJECT_VERSION_TWEAK
|
|
||||||
<< std::endl;
|
|
||||||
std::system("cat ../LICENSE");
|
|
||||||
|
|
||||||
// Bring in the dummy class from the example source,
|
|
||||||
// just to show that it is accessible from main.cpp.
|
|
||||||
Dummy d = Dummy();
|
|
||||||
return d.doSomething() ? 0 : -1;
|
|
||||||
}
|
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
# correct definitions. Here only used to make version number available to
|
# correct definitions. Here only used to make version number available to
|
||||||
# the source code. Include "exampleConfig.h" (no .in suffix) in the source.
|
# the source code. Include "exampleConfig.h" (no .in suffix) in the source.
|
||||||
configure_file (
|
configure_file (
|
||||||
"${PROJECT_SOURCE_DIR}/include/exampleConfig.h.in"
|
"${PROJECT_SOURCE_DIR}/include/kami/config.hpp.in"
|
||||||
"${PROJECT_BINARY_DIR}/exampleConfig.h"
|
"${PROJECT_BINARY_DIR}/include/kami/config.hpp"
|
||||||
)
|
)
|
||||||
# add the binary tree to the search path for include files
|
# add the binary tree to the search path for include files
|
||||||
# so that we will find exampleConfig.h
|
# so that we will find exampleConfig.h
|
||||||
|
|||||||
6
conanfile.txt
Normal file
6
conanfile.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[requires]
|
||||||
|
catch2/2.2.2@bincrafters/stable
|
||||||
|
spdlog/1.7.0
|
||||||
|
|
||||||
|
[generators]
|
||||||
|
cmake
|
||||||
151
examples/boltzmann.cpp
Normal file
151
examples/boltzmann.cpp
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "boltzmann.hpp"
|
||||||
|
|
||||||
|
// #include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <kami/agent.hpp>
|
||||||
|
#include <kami/kami.hpp>
|
||||||
|
#include <kami/multigrid2d.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
MoneyAgent::MoneyAgent() {
|
||||||
|
rd = new std::random_device();
|
||||||
|
rng = new std::mt19937{(*rd)()};
|
||||||
|
|
||||||
|
stepCounter = 0;
|
||||||
|
agentWealth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneyAgent::~MoneyAgent() {
|
||||||
|
delete rng;
|
||||||
|
delete rd;
|
||||||
|
};
|
||||||
|
|
||||||
|
void MoneyAgent::step() {
|
||||||
|
stepCounter++;
|
||||||
|
|
||||||
|
moveAgent();
|
||||||
|
if (agentWealth > 0)
|
||||||
|
giveMoney();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoneyAgent::setWorld(kami::MultiGrid2D *w) {
|
||||||
|
world = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoneyAgent::setModel(class BoltzmannWealthModel *m) {
|
||||||
|
model = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoneyAgent::moveAgent() {
|
||||||
|
auto agentID = this->getAgentID();
|
||||||
|
auto moveList = world->getNeighborhood(agentID, kami::NeighborhoodType::Moore, false);
|
||||||
|
|
||||||
|
std::uniform_int_distribution<unsigned long> dist(0, moveList.size() - 1);
|
||||||
|
auto newLocation = moveList[dist(*rng)];
|
||||||
|
|
||||||
|
world->moveAgent(agentID, newLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MoneyAgent::getWealth() {
|
||||||
|
return agentWealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoneyAgent::setWealth(int newWealth) {
|
||||||
|
agentWealth = newWealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoneyAgent::giveMoney() {
|
||||||
|
kami::AgentID agentID = getAgentID();
|
||||||
|
kami::MultiGrid2DCoord location = world->getLocationByAgent(agentID);
|
||||||
|
std::vector<kami::AgentID> *cellMates = world->getCellContents(location);
|
||||||
|
|
||||||
|
if (cellMates->size() > 1) {
|
||||||
|
std::uniform_int_distribution<unsigned long> dist(0, cellMates->size() - 1);
|
||||||
|
kami::AgentID otherAgentID = cellMates->at(dist(*rng));
|
||||||
|
auto otherAgent = model->getAgentByID(otherAgentID);
|
||||||
|
|
||||||
|
otherAgent->agentWealth += 1;
|
||||||
|
agentWealth -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoneyAgent::prinfo(void) const {
|
||||||
|
kami::AgentID agentID = getAgentID();
|
||||||
|
kami::MultiGrid2DCoord location = world->getLocationByAgent(agentID);
|
||||||
|
|
||||||
|
std::cout << " agent: " << agentID << " step: " << stepCounter << " wealth: " << agentWealth << " location: " << location << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoltzmannWealthModel::BoltzmannWealthModel(unsigned int numberAgents, unsigned int width, unsigned int height) {
|
||||||
|
auto seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||||
|
std::minstd_rand rng(static_cast<unsigned int>(seed));
|
||||||
|
std::uniform_int_distribution<unsigned long> distWidth(0, width - 1);
|
||||||
|
std::uniform_int_distribution<unsigned long> distHeight(0, height - 1);
|
||||||
|
world = new kami::MultiGrid2D(width, height, true, true);
|
||||||
|
sched = new kami::RandomScheduler(this);
|
||||||
|
|
||||||
|
stepCount = 0;
|
||||||
|
MoneyAgent::setWorld(world);
|
||||||
|
MoneyAgent::setModel(this);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < numberAgents; i++) {
|
||||||
|
MoneyAgent *newAgent = new MoneyAgent();
|
||||||
|
agentList.insert(std::pair<kami::AgentID, MoneyAgent *>(newAgent->getAgentID(), newAgent));
|
||||||
|
sched->addAgent(newAgent->getAgentID());
|
||||||
|
world->addAgent(newAgent->getAgentID(), static_cast<int>(distWidth(rng)), static_cast<int>(distHeight(rng)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BoltzmannWealthModel::~BoltzmannWealthModel() {
|
||||||
|
for (auto agent = agentList.begin(); agent != agentList.end(); ++agent) {
|
||||||
|
world->deleteAgent(agent->first);
|
||||||
|
sched->deleteAgent(agent->first);
|
||||||
|
agentList.erase(agent);
|
||||||
|
}
|
||||||
|
delete sched;
|
||||||
|
delete world;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoltzmannWealthModel::step() {
|
||||||
|
stepCount++;
|
||||||
|
sched->step();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoltzmannWealthModel::run(unsigned int n) {
|
||||||
|
for (unsigned int i = 0; i < n; i++)
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoltzmannWealthModel::prinfo(void) const {
|
||||||
|
std::cout << " step: " << stepCount << std::endl
|
||||||
|
<< " agentinfo: " << std::endl;
|
||||||
|
for (auto agent = agentList.begin(); agent != agentList.end(); ++agent) {
|
||||||
|
agent->second->prinfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneyAgent *BoltzmannWealthModel::getAgentByID(kami::AgentID agentID) const {
|
||||||
|
MoneyAgent *agentPair = agentList.at(agentID);
|
||||||
|
|
||||||
|
return agentPair;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::random_device *MoneyAgent::rd = nullptr;
|
||||||
|
std::mt19937 *MoneyAgent::rng = nullptr;
|
||||||
|
kami::MultiGrid2D *MoneyAgent::world = nullptr;
|
||||||
|
BoltzmannWealthModel *MoneyAgent::model = nullptr;
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
BoltzmannWealthModel model(100, 10, 10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
model.step();
|
||||||
|
}
|
||||||
|
|
||||||
|
model.prinfo();
|
||||||
|
}
|
||||||
60
examples/boltzmann.hpp
Normal file
60
examples/boltzmann.hpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef BOLTZMAN_HPP
|
||||||
|
#define BOLTZMAN_HPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <kami/agent.hpp>
|
||||||
|
#include <kami/kami.hpp>
|
||||||
|
#include <kami/multigrid2d.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
class MoneyAgent : public kami::Agent {
|
||||||
|
public:
|
||||||
|
MoneyAgent();
|
||||||
|
~MoneyAgent();
|
||||||
|
|
||||||
|
void step();
|
||||||
|
|
||||||
|
static void setWorld(kami::MultiGrid2D *w);
|
||||||
|
static void setModel(class BoltzmannWealthModel *m);
|
||||||
|
|
||||||
|
void moveAgent();
|
||||||
|
|
||||||
|
int getWealth();
|
||||||
|
void setWealth(int newWealth);
|
||||||
|
void giveMoney();
|
||||||
|
|
||||||
|
void prinfo(void) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static kami::MultiGrid2D *world;
|
||||||
|
static BoltzmannWealthModel *model;
|
||||||
|
static std::random_device *rd;
|
||||||
|
static std::mt19937 *rng;
|
||||||
|
int stepCounter;
|
||||||
|
int agentWealth;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BoltzmannWealthModel : public kami::Model {
|
||||||
|
public:
|
||||||
|
BoltzmannWealthModel(unsigned int = 100, unsigned int = 10, unsigned int = 10);
|
||||||
|
~BoltzmannWealthModel();
|
||||||
|
void step();
|
||||||
|
void run(unsigned int n);
|
||||||
|
void prinfo(void) const;
|
||||||
|
|
||||||
|
MoneyAgent *getAgentByID(kami::AgentID agentID) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<kami::AgentID, MoneyAgent *> agentList;
|
||||||
|
kami::RandomScheduler *sched;
|
||||||
|
kami::MultiGrid2D *world;
|
||||||
|
unsigned int stepCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BOLTZMAN_HPP
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a dummy class to demonstrate features of the boiler plate.
|
|
||||||
*/
|
|
||||||
class Dummy {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor for Dummy (does nothing).
|
|
||||||
*/
|
|
||||||
Dummy();
|
|
||||||
/**
|
|
||||||
* Returns a bool.
|
|
||||||
* @return Always True.
|
|
||||||
*/
|
|
||||||
bool doSomething();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_DOCTEST_IN_LIBRARY
|
|
||||||
#include "doctest.h"
|
|
||||||
TEST_CASE("we can have tests in headers if we want")
|
|
||||||
{
|
|
||||||
Dummy d;
|
|
||||||
CHECK(d.doSomething() == true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
59
include/kami/agent.hpp
Normal file
59
include/kami/agent.hpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef KAMI_AGENT_HPP
|
||||||
|
#define KAMI_AGENT_HPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
/// A unique identifier for each agent
|
||||||
|
class AgentID {
|
||||||
|
public:
|
||||||
|
/// Create a new unique identifier
|
||||||
|
AgentID();
|
||||||
|
|
||||||
|
std::string toString() const;
|
||||||
|
|
||||||
|
friend bool operator==(const AgentID &, const AgentID &);
|
||||||
|
friend bool operator!=(const AgentID &, const AgentID &);
|
||||||
|
friend bool operator<(const AgentID &, const AgentID &);
|
||||||
|
friend std::ostream &operator<<(std::ostream &, const AgentID &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static uint64_t idGen;
|
||||||
|
uint64_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Agent {
|
||||||
|
public:
|
||||||
|
virtual ~Agent() = default;
|
||||||
|
|
||||||
|
AgentID getAgentID() const;
|
||||||
|
virtual void step();
|
||||||
|
|
||||||
|
friend bool operator==(const Agent &, const Agent &);
|
||||||
|
friend bool operator!=(const Agent &, const Agent &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AgentID agentID;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A class for agents with pre-`step()` and post-`step()` staging.
|
||||||
|
class StagedAgent : public Agent {
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
StagedAgent();
|
||||||
|
virtual ~StagedAgent() = default;
|
||||||
|
|
||||||
|
virtual void preStep() = 0;
|
||||||
|
virtual void postStep() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
|
|
||||||
|
#endif // KAMI_AGENT_HPP
|
||||||
@@ -6,7 +6,13 @@
|
|||||||
* right definition values. Change the namings as you wish,
|
* right definition values. Change the namings as you wish,
|
||||||
* but make sure they match up with whats in CMakeLists.txt.
|
* but make sure they match up with whats in CMakeLists.txt.
|
||||||
*/
|
*/
|
||||||
#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
|
||||||
#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
#pragma once
|
||||||
#define PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
#ifndef KAMI_KAMI_VERSION_HPP
|
||||||
#define PROJECT_VERSION_TWEAK @PROJECT_VERSION_TWEAK@
|
#define KAMI_KAMI_VERSION_HPP
|
||||||
|
|
||||||
|
#define KAMI_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||||
|
#define KAMI_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||||
|
#define KAMI_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||||
|
|
||||||
|
#endif // KAMI_KAMI_VERSION_HPP
|
||||||
27
include/kami/domain.hpp
Normal file
27
include/kami/domain.hpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef KAMI_DOMAIN_HPP
|
||||||
|
#define KAMI_DOMAIN_HPP
|
||||||
|
|
||||||
|
#include <kami/kami.hpp>
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
/**
|
||||||
|
A domain provides an environment for the agents to participate in
|
||||||
|
*/
|
||||||
|
class Domain {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
A domain based on a grid with integer steps
|
||||||
|
*/
|
||||||
|
class GridDomain : public Domain {
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
|
|
||||||
|
#endif // KAMI_DOMAIN_HPP
|
||||||
13
include/kami/kami.hpp
Normal file
13
include/kami/kami.hpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef KAMI_KAMI_HPP
|
||||||
|
#define KAMI_KAMI_HPP
|
||||||
|
|
||||||
|
#include <kami/agent.hpp>
|
||||||
|
#include <kami/model.hpp>
|
||||||
|
#include <kami/random.hpp>
|
||||||
|
|
||||||
|
#endif // KAMI_KAMI_HPP
|
||||||
33
include/kami/model.hpp
Normal file
33
include/kami/model.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef KAMI_MODEL_HPP
|
||||||
|
#define KAMI_MODEL_HPP
|
||||||
|
|
||||||
|
#include <kami/agent.hpp>
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
/// An abstract for generic models
|
||||||
|
class Model {
|
||||||
|
public:
|
||||||
|
virtual ~Model();
|
||||||
|
|
||||||
|
/// Get a reference to an Agent by AgentID
|
||||||
|
virtual Agent *getAgentByID(AgentID) const = 0;
|
||||||
|
|
||||||
|
/// Run the model for a fixed number of steps.
|
||||||
|
void run(unsigned int) { return; }
|
||||||
|
|
||||||
|
/// Execute a 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.
|
||||||
|
void step() { return; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
|
|
||||||
|
#endif // KAMI_MODEL_HPP
|
||||||
88
include/kami/multigrid2d.hpp
Normal file
88
include/kami/multigrid2d.hpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef KAMI_MULTIGRID2D_HPP
|
||||||
|
#define KAMI_MULTIGRID2D_HPP
|
||||||
|
|
||||||
|
#include <kami/agent.hpp>
|
||||||
|
#include <kami/domain.hpp>
|
||||||
|
#include <kami/kami.hpp>
|
||||||
|
#include <kami/multigrid2d.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
typedef enum NeighborhoodType { Moore,
|
||||||
|
VonNeumann } NeighborhoodType;
|
||||||
|
|
||||||
|
class MultiGrid2DCoord {
|
||||||
|
public:
|
||||||
|
MultiGrid2DCoord(int, int);
|
||||||
|
|
||||||
|
void setCoord(int, int);
|
||||||
|
void setXCoord(int);
|
||||||
|
void setYCoord(int);
|
||||||
|
|
||||||
|
int getXCoord(void) const;
|
||||||
|
int getYCoord(void) const;
|
||||||
|
|
||||||
|
friend bool operator==(const MultiGrid2DCoord &, const MultiGrid2DCoord &);
|
||||||
|
friend bool operator!=(const MultiGrid2DCoord &, const MultiGrid2DCoord &);
|
||||||
|
friend std::ostream &operator<<(std::ostream &, const MultiGrid2DCoord &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int xCoord;
|
||||||
|
int yCoord;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MultiGrid2D : public GridDomain {
|
||||||
|
public:
|
||||||
|
MultiGrid2D(unsigned int, unsigned int, bool, bool);
|
||||||
|
~MultiGrid2D(void);
|
||||||
|
|
||||||
|
bool addAgent(AgentID, int, int);
|
||||||
|
bool addAgent(AgentID, MultiGrid2DCoord);
|
||||||
|
|
||||||
|
void deleteAgent(AgentID);
|
||||||
|
void deleteAgent(AgentID, int, int);
|
||||||
|
void deleteAgent(AgentID, MultiGrid2DCoord);
|
||||||
|
|
||||||
|
bool isLocationValid(MultiGrid2DCoord) const;
|
||||||
|
|
||||||
|
MultiGrid2DCoord getLocationByAgent(AgentID) const;
|
||||||
|
|
||||||
|
void moveAgent(AgentID, MultiGrid2DCoord);
|
||||||
|
|
||||||
|
void setColWrap(bool);
|
||||||
|
void setRowWrap(bool);
|
||||||
|
bool getColWrap(void) const;
|
||||||
|
bool getRowWrap(void) const;
|
||||||
|
|
||||||
|
std::vector<MultiGrid2DCoord> getNeighborhood(MultiGrid2DCoord, NeighborhoodType, bool) const;
|
||||||
|
std::vector<MultiGrid2DCoord> getNeighborhood(AgentID, NeighborhoodType, bool) const;
|
||||||
|
|
||||||
|
std::vector<AgentID> *getCellContents(MultiGrid2DCoord);
|
||||||
|
|
||||||
|
void setMaxRows(unsigned int);
|
||||||
|
void setMaxCols(unsigned int);
|
||||||
|
unsigned int getMaxRows(void) const;
|
||||||
|
unsigned int getMaxCols(void) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<AgentID> **agentGrid;
|
||||||
|
std::map<AgentID, MultiGrid2DCoord> *agentIndex;
|
||||||
|
static std::mutex lock;
|
||||||
|
unsigned int maxRows, maxCols;
|
||||||
|
bool colWrap, rowWrap;
|
||||||
|
|
||||||
|
MultiGrid2DCoord locationWrap(int, int) const;
|
||||||
|
MultiGrid2DCoord locationWrap(MultiGrid2DCoord) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
|
|
||||||
|
#endif // KAMI_MULTIGRID2D_HPP
|
||||||
33
include/kami/random.hpp
Normal file
33
include/kami/random.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef KAMI_RANDOM_HPP
|
||||||
|
#define KAMI_RANDOM_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <kami/agent.hpp>
|
||||||
|
#include <kami/model.hpp>
|
||||||
|
#include <kami/scheduler.hpp>
|
||||||
|
#include <random>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
class RandomScheduler : public Scheduler {
|
||||||
|
public:
|
||||||
|
RandomScheduler(Model *);
|
||||||
|
virtual ~RandomScheduler();
|
||||||
|
|
||||||
|
void addAgent(AgentID);
|
||||||
|
void deleteAgent(AgentID);
|
||||||
|
void step();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<AgentID> agentList;
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 rng{rd()};
|
||||||
|
Model *model;
|
||||||
|
int stepCounter;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace kami
|
||||||
|
|
||||||
|
#endif // KAMI_RANDOM_HPP
|
||||||
37
include/kami/scheduler.hpp
Normal file
37
include/kami/scheduler.hpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef KAMI_SCHEDULER_HPP
|
||||||
|
#define KAMI_SCHEDULER_HPP
|
||||||
|
|
||||||
|
#include <kami/agent.hpp>
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
/// An abstract class for a Scheduler
|
||||||
|
class Scheduler {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~Scheduler();
|
||||||
|
|
||||||
|
/// Add an Agent to the Scheduler.
|
||||||
|
///
|
||||||
|
/// @param agentID The AgentID of the agent to add.
|
||||||
|
virtual void addAgent(AgentID agentID) = 0;
|
||||||
|
|
||||||
|
/// Remove an Agent from the Scheduler.
|
||||||
|
///
|
||||||
|
/// @param agentID The AgentID of the agent to remove.
|
||||||
|
virtual void deleteAgent(AgentID agentID) = 0;
|
||||||
|
|
||||||
|
/// Step the Scheduler.
|
||||||
|
///
|
||||||
|
/// A generic step function that executes a single time step.
|
||||||
|
virtual void step() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
|
|
||||||
|
#endif // KAMI_SCHEDULER_HPP
|
||||||
22
setup.sh
22
setup.sh
@@ -1,22 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Revert to first commit, add and commit everything as single commit.
|
|
||||||
git reset $(git commit-tree HEAD^{tree} -m "Bolier plate for C++ project added")
|
|
||||||
|
|
||||||
name=$(git config user.name)
|
|
||||||
email=$(git config user.email)
|
|
||||||
|
|
||||||
# If this script is called with an argument, use that as the amended author
|
|
||||||
# EX: ./setup.sh "Author Name <author_email@email.com>"
|
|
||||||
if [[ "$1" ]]; then
|
|
||||||
git commit --amend --author="$1"
|
|
||||||
else
|
|
||||||
git commit --amend --author="$name <$email>"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Initialize submodules: This should already be done when cloning, but there are ways to muck it
|
|
||||||
# up if you do things in the wrong order. So just to be sure, we do it now.
|
|
||||||
git submodule update --init --recursive
|
|
||||||
|
|
||||||
# Remove the remote (you probably want your own instead).
|
|
||||||
git remote remove origin
|
|
||||||
52
src/agent.cpp
Normal file
52
src/agent.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kami/agent.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
uint64_t AgentID::idGen = 1;
|
||||||
|
|
||||||
|
AgentID::AgentID() {
|
||||||
|
id = idGen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AgentID::toString() const {
|
||||||
|
return std::to_string(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.id < rhs.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &lhs, const AgentID &rhs) {
|
||||||
|
return lhs << rhs.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentID Agent::getAgentID() const {
|
||||||
|
return agentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Agent::step() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Agent &lhs, const Agent &rhs) {
|
||||||
|
return lhs.agentID == rhs.agentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Agent &lhs, const Agent &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#include "example.h"
|
|
||||||
|
|
||||||
Dummy::Dummy() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dummy::doSomething() {
|
|
||||||
// Do silly things, using some C++17 features to enforce C++17 builds only.
|
|
||||||
constexpr int digits[2] = {0, 1};
|
|
||||||
auto [zero, one] = digits;
|
|
||||||
return zero + one;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_DOCTEST_IN_LIBRARY
|
|
||||||
#include "doctest.h"
|
|
||||||
TEST_CASE("we can have tests written here, to test impl. details")
|
|
||||||
{
|
|
||||||
CHECK(true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
10
src/kami.cpp
Normal file
10
src/kami.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "kami/model.hpp"
|
||||||
|
#include "kami/scheduler.hpp"
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
Model::~Model() {}
|
||||||
|
|
||||||
|
Scheduler::~Scheduler() {}
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
189
src/multigrid2d.cpp
Normal file
189
src/multigrid2d.cpp
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/*-
|
||||||
|
* TODO FILEHEADER
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kami/multigrid2d.hpp"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "kami/agent.hpp"
|
||||||
|
#include "kami/domain.hpp"
|
||||||
|
#include "kami/kami.hpp"
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
MultiGrid2DCoord::MultiGrid2DCoord(int newXCoord, int newYCoord) {
|
||||||
|
setXCoord(newXCoord);
|
||||||
|
setYCoord(newYCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2DCoord::setCoord(int newXCoord, int newYCoord) {
|
||||||
|
setXCoord(newXCoord);
|
||||||
|
setYCoord(newYCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2DCoord::setXCoord(int newXCoord) {
|
||||||
|
xCoord = newXCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2DCoord::setYCoord(int newYCoord) {
|
||||||
|
yCoord = newYCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MultiGrid2DCoord::getXCoord(void) const {
|
||||||
|
return xCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MultiGrid2DCoord::getYCoord(void) const {
|
||||||
|
return yCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const MultiGrid2DCoord &lhs, const MultiGrid2DCoord &rhs) {
|
||||||
|
return (lhs.xCoord == rhs.yCoord && lhs.yCoord == rhs.yCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const MultiGrid2DCoord &lhs, const MultiGrid2DCoord &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &lhs, const MultiGrid2DCoord &rhs) {
|
||||||
|
return lhs << "(" << rhs.xCoord << ", " << rhs.yCoord << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiGrid2D::MultiGrid2D(unsigned int newMaxCols, unsigned int newMaxRows, bool newColWrap = false, bool newRowWrap = false) {
|
||||||
|
setMaxCols(newMaxCols);
|
||||||
|
setMaxRows(newMaxRows);
|
||||||
|
|
||||||
|
setColWrap(newColWrap);
|
||||||
|
setRowWrap(newRowWrap);
|
||||||
|
|
||||||
|
agentGrid = new std::vector<AgentID> *[newMaxCols];
|
||||||
|
for (unsigned int i = 0; i < newMaxRows; i++)
|
||||||
|
agentGrid[i] = new std::vector<AgentID>[newMaxRows];
|
||||||
|
|
||||||
|
agentIndex = new std::map<AgentID, MultiGrid2DCoord>;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiGrid2D::~MultiGrid2D(void) {
|
||||||
|
delete agentIndex;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < maxRows; i++)
|
||||||
|
delete [] agentGrid[i];
|
||||||
|
delete [] agentGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MultiGrid2D::addAgent(AgentID agentID, int xCoord, int yCoord) {
|
||||||
|
return addAgent(agentID, MultiGrid2DCoord(xCoord, yCoord));
|
||||||
|
}
|
||||||
|
bool MultiGrid2D::addAgent(AgentID agentID, MultiGrid2DCoord location) {
|
||||||
|
if (isLocationValid(location)) {
|
||||||
|
agentIndex->insert(std::pair<AgentID, MultiGrid2DCoord>(agentID, location));
|
||||||
|
agentGrid[location.getXCoord()][location.getYCoord()].push_back(agentID);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2D::deleteAgent(AgentID agentID) {
|
||||||
|
MultiGrid2DCoord location = getLocationByAgent(agentID);
|
||||||
|
|
||||||
|
deleteAgent(agentID, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2D::deleteAgent(AgentID agentID, int xCoord, int yCoord) {
|
||||||
|
deleteAgent(agentID, MultiGrid2DCoord(xCoord, yCoord));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2D::deleteAgent(AgentID agentID, MultiGrid2DCoord location) {
|
||||||
|
auto agentList = agentGrid[static_cast<int>(location.getXCoord())][static_cast<int>(location.getYCoord())];
|
||||||
|
for (auto testAgentID = agentList.begin(); testAgentID < agentList.end(); testAgentID++) {
|
||||||
|
if (*testAgentID == agentID) {
|
||||||
|
agentList.erase(testAgentID);
|
||||||
|
agentIndex->erase(agentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MultiGrid2D::isLocationValid(MultiGrid2DCoord location) const {
|
||||||
|
auto xCoord = location.getXCoord();
|
||||||
|
auto yCoord = location.getYCoord();
|
||||||
|
|
||||||
|
return (xCoord >= 0 && xCoord < static_cast<int>(maxCols) && yCoord >= 0 && yCoord < static_cast<int>(maxRows));
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiGrid2DCoord MultiGrid2D::getLocationByAgent(AgentID agentID) const {
|
||||||
|
return agentIndex->at(agentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2D::moveAgent(AgentID agentID, MultiGrid2DCoord nextLocation) {
|
||||||
|
MultiGrid2DCoord currLocation = getLocationByAgent(agentID);
|
||||||
|
|
||||||
|
deleteAgent(agentID, currLocation);
|
||||||
|
addAgent(agentID, nextLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2D::setColWrap(bool newColWrap) { colWrap = newColWrap; }
|
||||||
|
void MultiGrid2D::setRowWrap(bool newRowWrap) { rowWrap = newRowWrap; }
|
||||||
|
bool MultiGrid2D::getColWrap(void) const { return colWrap; }
|
||||||
|
bool MultiGrid2D::getRowWrap(void) const { return rowWrap; }
|
||||||
|
|
||||||
|
std::vector<MultiGrid2DCoord> MultiGrid2D::getNeighborhood(AgentID agentID, NeighborhoodType nType, bool includeCenter) const {
|
||||||
|
MultiGrid2DCoord location = getLocationByAgent(agentID);
|
||||||
|
|
||||||
|
return getNeighborhood(location, nType, includeCenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<MultiGrid2DCoord> MultiGrid2D::getNeighborhood(MultiGrid2DCoord location, NeighborhoodType nType, bool includeCenter) const {
|
||||||
|
std::vector<MultiGrid2DCoord> neighborhood;
|
||||||
|
auto xCoord = location.getXCoord();
|
||||||
|
auto yCoord = location.getYCoord();
|
||||||
|
|
||||||
|
if (includeCenter == true)
|
||||||
|
neighborhood.push_back(location);
|
||||||
|
|
||||||
|
// N, E, S, W
|
||||||
|
neighborhood.push_back(locationWrap(xCoord, yCoord - 1));
|
||||||
|
neighborhood.push_back(locationWrap(xCoord + 1, yCoord));
|
||||||
|
neighborhood.push_back(locationWrap(xCoord, yCoord + 1));
|
||||||
|
neighborhood.push_back(locationWrap(xCoord - 1, yCoord));
|
||||||
|
|
||||||
|
if (nType == NeighborhoodType::Moore) {
|
||||||
|
// NE, SE, SW, NW
|
||||||
|
neighborhood.push_back(locationWrap(xCoord + 1, yCoord - 1));
|
||||||
|
neighborhood.push_back(locationWrap(xCoord + 1, yCoord + 1));
|
||||||
|
neighborhood.push_back(locationWrap(xCoord - 1, yCoord + 1));
|
||||||
|
neighborhood.push_back(locationWrap(xCoord - 1, yCoord - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return neighborhood;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AgentID> *MultiGrid2D::getCellContents(MultiGrid2DCoord location) {
|
||||||
|
if (isLocationValid(location)) {
|
||||||
|
return &agentGrid[location.getXCoord()][location.getYCoord()];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiGrid2D::setMaxCols(unsigned int newMaxCols) { maxCols = newMaxCols; }
|
||||||
|
void MultiGrid2D::setMaxRows(unsigned int newMaxRows) { maxRows = newMaxRows; }
|
||||||
|
unsigned int MultiGrid2D::getMaxCols(void) const { return maxCols; }
|
||||||
|
unsigned int MultiGrid2D::getMaxRows(void) const { return maxRows; }
|
||||||
|
|
||||||
|
MultiGrid2DCoord MultiGrid2D::locationWrap(MultiGrid2DCoord location) const {
|
||||||
|
return locationWrap(location.getXCoord(), location.getYCoord());
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiGrid2DCoord MultiGrid2D::locationWrap(int xCoord, int yCoord) const {
|
||||||
|
if (colWrap == true)
|
||||||
|
xCoord = (xCoord + static_cast<int>(maxCols)) % static_cast<int>(maxCols);
|
||||||
|
if (rowWrap == true)
|
||||||
|
yCoord = (yCoord + static_cast<int>(maxRows)) % static_cast<int>(maxRows);
|
||||||
|
return MultiGrid2DCoord(xCoord, yCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
49
src/random.cpp
Normal file
49
src/random.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kami/random.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
#include "kami/agent.hpp"
|
||||||
|
#include "kami/model.hpp"
|
||||||
|
#include "kami/scheduler.hpp"
|
||||||
|
|
||||||
|
namespace kami {
|
||||||
|
|
||||||
|
RandomScheduler::RandomScheduler(Model *newModel) {
|
||||||
|
stepCounter = 0;
|
||||||
|
model = newModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomScheduler::~RandomScheduler() {}
|
||||||
|
|
||||||
|
void RandomScheduler::addAgent(AgentID newAgentID) {
|
||||||
|
agentList.push_back(newAgentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomScheduler::deleteAgent(AgentID oldAgentID) {
|
||||||
|
for (auto agentID = agentList.begin(); agentID < agentList.end(); agentID++) {
|
||||||
|
if (*agentID == oldAgentID) {
|
||||||
|
agentList.erase(agentID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ERROR HERE
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomScheduler::step() {
|
||||||
|
stepCounter++;
|
||||||
|
|
||||||
|
shuffle(agentList.begin(), agentList.end(), rng);
|
||||||
|
for (auto agentID = agentList.begin(); agentID < agentList.end(); agentID++) {
|
||||||
|
Agent *agent = model->getAgentByID(*agentID);
|
||||||
|
if (agent != nullptr)
|
||||||
|
agent->step();
|
||||||
|
// ERROR HERE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace kami
|
||||||
@@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.8.2)
|
|||||||
|
|
||||||
# List all files containing tests. (Change as needed)
|
# List all files containing tests. (Change as needed)
|
||||||
set(TESTFILES # All .cpp files in tests/
|
set(TESTFILES # All .cpp files in tests/
|
||||||
main.cpp
|
|
||||||
dummy.cpp
|
dummy.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
#include "doctest.h"
|
#include <iostream>
|
||||||
#include "example.h"
|
|
||||||
|
|
||||||
// Tests that don't naturally fit in the headers/.cpp files directly
|
int main(void) {
|
||||||
// can be placed in a tests/*.cpp file. Integration tests are a good example.
|
std::cout << "foo";
|
||||||
|
|
||||||
TEST_CASE("complicated integration tests could be here")
|
|
||||||
{
|
|
||||||
Dummy d;
|
|
||||||
CHECK(d.doSomething() == true);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
|
|
||||||
// This is all that is needed to compile a test-runner executable.
|
|
||||||
// More tests can be added here, or in a new tests/*.cpp file.
|
|
||||||
Reference in New Issue
Block a user