mirror of
https://github.com/JHUAPL/kami.git
synced 2026-01-09 19:47:58 -05:00
Compare commits
259 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
568a5f6f5d | ||
|
|
ffe25478c1 | ||
|
|
f10bc39cce | ||
|
|
5a0f76f7fa | ||
|
|
da5347b102 | ||
|
|
dcbfddad13 | ||
|
|
7e3052bac0 | ||
|
|
14b244586c | ||
|
|
eacac535ab | ||
|
|
cdce9feb51 | ||
|
|
4602d87024 | ||
|
|
8f658dc5ca | ||
|
|
597bb298eb | ||
|
|
60018c2bce | ||
|
|
74905d04a5 | ||
|
|
adec433bce | ||
|
|
431a4ac8cf | ||
|
|
e56c257707 | ||
|
|
8cf2193f7c | ||
|
|
dacb7d38de | ||
|
|
62e80ed547 | ||
|
|
e02b339055 | ||
|
|
3af8d8b8e0 | ||
|
|
2e212ad5c6 | ||
|
|
426f1b740d | ||
|
|
0d75e3b691 | ||
|
|
9d27ec927d | ||
|
|
91fdb5fc68 | ||
|
|
c08f9509e5 | ||
|
|
2ead0b30e0 | ||
|
|
3e88c87644 | ||
|
|
003c3e1be0 | ||
|
|
f333f96bca | ||
|
|
5d58df48b2 | ||
|
|
022f9e31aa | ||
|
|
ad9dbf3eb2 | ||
|
|
0f1f1ad41a | ||
|
|
f0295e9891 | ||
|
|
8f7b6b65c2 | ||
|
|
80ac9571a7 | ||
|
|
7a7db768ed | ||
|
|
9eb47c8656 | ||
|
|
2aeef72f19 | ||
|
|
552d8fc725 | ||
|
|
8050ce9b8f | ||
|
|
317509ce0b | ||
|
|
e1028a377d | ||
|
|
860e367785 | ||
|
|
445e10252e | ||
|
|
a08b316b96 | ||
|
|
893c8da8e2 | ||
|
|
10cb3cf3f3 | ||
|
|
3ed40f4cdb | ||
|
|
003e7a4d12 | ||
|
|
6751951e84 | ||
|
|
7def091083 | ||
|
|
a872c89b78 | ||
|
|
b573a3f676 | ||
|
|
d2ccdbea73 | ||
|
|
b9b1cb12e6 | ||
|
|
948f744414 | ||
|
|
06355bdf67 | ||
|
|
a215ca7320 | ||
|
|
097024a6b8 | ||
|
|
a0c2a7869c | ||
|
|
a45b9bf22d | ||
|
|
7849a49355 | ||
|
|
f86dbd4c24 | ||
|
|
cdc9c56765 | ||
|
|
972e83aeeb | ||
|
|
922572973d | ||
|
|
8906825235 | ||
|
|
64dc35c9c4 | ||
|
|
6c34098b53 | ||
|
|
bc0740219f | ||
|
|
11660de09c | ||
|
|
3b3a7f0bca | ||
|
|
d4db95f925 | ||
|
|
0727030bcb | ||
|
|
85aede0721 | ||
|
|
06e98b1f94 | ||
|
|
8613bc29b3 | ||
|
|
67cdf9bc29 | ||
|
|
e7a5f342bf | ||
|
|
9333e1c2fa | ||
|
|
f18e2c99da | ||
|
|
d884e603cb | ||
|
|
78aca204f4 | ||
|
|
50b147beca | ||
|
|
3dff3afb6e | ||
|
|
80f98bdde0 | ||
|
|
72f0074d81 | ||
|
|
f6967d0ec3 | ||
|
|
318f6dfecf | ||
|
|
05995525f1 | ||
|
|
d1ba71b416 | ||
|
|
13185c1e0b | ||
|
|
beb6a1d99b | ||
|
|
a801720aa5 | ||
|
|
8a1ac91fae | ||
|
|
7c6fdd0b11 | ||
|
|
82d96676d7 | ||
|
|
40cbaced51 | ||
|
|
2351e6f23e | ||
|
|
018379554d | ||
|
|
0f8ee56948 | ||
|
|
237be8bbe8 | ||
|
|
e21da48f5a | ||
|
|
e19dc7b449 | ||
|
|
d52102615c | ||
|
|
d1b6c60ec6 | ||
|
|
0d00c3ec40 | ||
|
|
25b14c8aff | ||
|
|
2d88d32bd6 | ||
|
|
0015cdbd5a | ||
|
|
7a335feae2 | ||
|
|
8742637ac8 | ||
|
|
2f6c26406a | ||
|
|
cab9c86819 | ||
|
|
743c388fb3 | ||
|
|
cc7cf670bb | ||
|
|
c91caf723e | ||
|
|
c25d73b56e | ||
|
|
f7bf234f6a | ||
|
|
55b819ac8c | ||
|
|
ec28727ed9 | ||
|
|
a8c4212b94 | ||
|
|
fa74943eb5 | ||
|
|
6320f2d6da | ||
|
|
f8e26344c1 | ||
|
|
95165f4d72 | ||
|
|
3faa5b4c50 | ||
|
|
cddf317ee6 | ||
|
|
f87f9850d9 | ||
|
|
e82b08e8f8 | ||
|
|
10c42ec2fe | ||
|
|
084eda63f3 | ||
|
|
1c60e90514 | ||
|
|
9791cd6d8b | ||
|
|
e1c83d9158 | ||
|
|
9bdde03463 | ||
|
|
f5ae008df5 | ||
|
|
cf0b75c5fb | ||
|
|
cf35c348ca | ||
|
|
b5abb50892 | ||
|
|
1d192c99f6 | ||
|
|
b9a41e08a3 | ||
|
|
52191803ef | ||
|
|
9859000182 | ||
|
|
cc189f80c5 | ||
|
|
ddf96401c5 | ||
|
|
a5d3f8b1ad | ||
|
|
7af8e59b96 | ||
|
|
8747b22310 | ||
|
|
8d9b217298 | ||
|
|
7567ee7f36 | ||
|
|
c7685f03b7 | ||
|
|
715d4e0f7b | ||
|
|
01d8154017 | ||
|
|
c145466758 | ||
|
|
7d53af7bdf | ||
|
|
d7cd7bcfc4 | ||
|
|
98959520ea | ||
|
|
42c87ccccd | ||
|
|
ba0ae24cfc | ||
|
|
e2c825e2e6 | ||
|
|
c7f4c706cd | ||
|
|
584c2b94d8 | ||
|
|
b02efaae07 | ||
|
|
087bdadc16 | ||
|
|
2027ff05eb | ||
|
|
15647b905f | ||
|
|
f0ce59c967 | ||
|
|
7af69815f3 | ||
|
|
25febcb094 | ||
|
|
52bb8bb900 | ||
|
|
f3f2b00740 | ||
|
|
1200fb4de0 | ||
|
|
fb5d222915 | ||
|
|
30fdd46d93 | ||
|
|
f474d6feff | ||
|
|
caf6d01b58 | ||
|
|
44c541a4f8 | ||
|
|
0edd940344 | ||
|
|
10f33b5f61 | ||
|
|
b6406b86d8 | ||
|
|
54f49a732c | ||
|
|
f2601ea85f | ||
|
|
b9c7f9b605 | ||
|
|
d13960da35 | ||
|
|
24daa26bc6 | ||
|
|
c0daf3d07e | ||
|
|
58b1e07744 | ||
|
|
2759864e5c | ||
|
|
62cabc52c9 | ||
|
|
8aed4266d1 | ||
|
|
0021466fac | ||
|
|
50bea16026 | ||
|
|
caad12fc79 | ||
|
|
ff0649f6f3 | ||
|
|
1155fdea36 | ||
|
|
272ec5a030 | ||
|
|
57f4cc4d1d | ||
|
|
1692b99ff5 | ||
|
|
716d515f3e | ||
|
|
c813193e9c | ||
|
|
ccbeedbf4b | ||
|
|
4df9030514 | ||
|
|
1cdf75276d | ||
|
|
c22ecb2777 | ||
|
|
17602e5130 | ||
|
|
5c85571b72 | ||
|
|
cdf50bbea7 | ||
|
|
8803a09cb4 | ||
|
|
8f98db2ff0 | ||
|
|
78131e9e7d | ||
|
|
a93d8e566f | ||
|
|
c4f369407b | ||
|
|
382e074b7e | ||
|
|
2735cef23e | ||
|
|
bf56389a73 | ||
|
|
5fd5661bad | ||
|
|
0789d88f82 | ||
|
|
390ce0cbd9 | ||
|
|
47c141710f | ||
|
|
ca5dcfea59 | ||
|
|
394891a325 | ||
|
|
70b90bec01 | ||
|
|
ce9829a086 | ||
|
|
04bfa96059 | ||
|
|
077e7df773 | ||
|
|
175c1edda8 | ||
|
|
fcc177db7c | ||
|
|
4a8947b62d | ||
|
|
ab0d0bdcc0 | ||
|
|
6b02d5ba1a | ||
|
|
573b75dc27 | ||
|
|
60ff21519c | ||
|
|
6e3f814ce2 | ||
|
|
213d60f4b3 | ||
|
|
611f4c8de9 | ||
|
|
dcd960d1ed | ||
|
|
e2338e1337 | ||
|
|
4469e4c36c | ||
|
|
571732f13c | ||
|
|
4702cfe8d3 | ||
|
|
5e9389e1b3 | ||
|
|
fc0f1a1e52 | ||
|
|
93f91836a4 | ||
|
|
7298fa7729 | ||
|
|
dfff3243bd | ||
|
|
f038242d9b | ||
|
|
0fbb972e9c | ||
|
|
3809a417c9 | ||
|
|
0d5fa3f39e | ||
|
|
ffb67e6da3 | ||
|
|
41a1e9edbe | ||
|
|
e9ca6477d4 | ||
|
|
f38a69af4b |
@@ -1,55 +0,0 @@
|
||||
linux: &linux
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: python
|
||||
python: "3.7"
|
||||
services:
|
||||
- docker
|
||||
osx: &osx
|
||||
os: osx
|
||||
language: generic
|
||||
matrix:
|
||||
include:
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=conanio/gcc49
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=5 CONAN_DOCKER_IMAGE=conanio/gcc5
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=6 CONAN_DOCKER_IMAGE=conanio/gcc6
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=conanio/gcc7
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=conanio/clang39
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=conanio/clang40
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=conanio/clang50
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=conanio/clang60
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=7.0 CONAN_DOCKER_IMAGE=conanio/clang7
|
||||
- <<: *osx
|
||||
osx_image: xcode7.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=7.3
|
||||
- <<: *osx
|
||||
osx_image: xcode8.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=8.1
|
||||
- <<: *osx
|
||||
osx_image: xcode9
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.0
|
||||
- <<: *osx
|
||||
osx_image: xcode9.4
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.1
|
||||
- <<: *osx
|
||||
osx_image: xcode10.1
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=10.0
|
||||
|
||||
install:
|
||||
- chmod +x .ci/install.sh
|
||||
- ./.ci/install.sh
|
||||
|
||||
script:
|
||||
- chmod +x .ci/run.sh
|
||||
- ./.ci/run.sh
|
||||
@@ -1,66 +0,0 @@
|
||||
[server]
|
||||
# WARNING! Change default variable of jwt_secret. You should change it periodically
|
||||
# It only affects to current authentication tokens, you can change safetely anytime
|
||||
# When it changes user are just forced to log in again
|
||||
jwt_secret: dSktZiPDNsiBpFQKWIpUgdHp
|
||||
jwt_expire_minutes: 120
|
||||
|
||||
ssl_enabled: False
|
||||
port: 9300
|
||||
# Public port where files will be served. If empty will be used "port"
|
||||
public_port:
|
||||
host_name: localhost
|
||||
|
||||
# Authorize timeout are seconds the client has to upload/download files until authorization expires
|
||||
authorize_timeout: 1800
|
||||
|
||||
# Just for disk storage adapter
|
||||
# updown_secret is the key used to generate the upload/download authorization token
|
||||
disk_storage_path: ~/.conan_server/data
|
||||
disk_authorize_timeout: 1800
|
||||
updown_secret: EHKKsMYJTeyLITZlwrRVJJIL
|
||||
|
||||
|
||||
# Check docs.conan.io to implement a different authenticator plugin for conan_server
|
||||
# if custom_authenticator is not specified, [users] section will be used to authenticate
|
||||
# the users.
|
||||
#
|
||||
# custom_authenticator: my_authenticator
|
||||
|
||||
# name/version@user/channel: user1, user2, user3
|
||||
#
|
||||
# The rules are applied in order.
|
||||
# If a rule matches your package, then the server wont look further.
|
||||
# Place your more restrictive rules first.
|
||||
#
|
||||
# Example: All versions of opencv package from lasote user in testing channel is only
|
||||
# writeable by default_user and default_user2. Rest of packages are not writtable by anything
|
||||
# except the author.
|
||||
#
|
||||
# opencv/2.3.4@lasote/testing: default_user, default_user2
|
||||
#
|
||||
[write_permissions]
|
||||
*/*@*/*: *
|
||||
|
||||
# name/version@user/channel: user1, user2, user3
|
||||
# The rules are applied in order. If a rule applies to a conan, system wont look further.
|
||||
#
|
||||
# Example:
|
||||
# All versions of opencv package from lasote user in testing channel are only
|
||||
# readable by default_user and default_user2.
|
||||
# All versions of internal package from any user/channel are only readable by
|
||||
# authenticated users.
|
||||
# Rest of packages are world readable.
|
||||
#
|
||||
# opencv/*@lasote/testing: default_user default_user2
|
||||
# internal/*@*/*: ?
|
||||
# */*@*/*: *
|
||||
#
|
||||
# By default all users can read all blocks
|
||||
#
|
||||
[read_permissions]
|
||||
*/*@*/*: *
|
||||
|
||||
[users]
|
||||
#default_user: defaultpass
|
||||
demo: demo
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [[ "$(uname -s)" == 'Darwin' ]]; then
|
||||
echo "Darwin!"
|
||||
brew install cmake || true
|
||||
brew upgrade cmake
|
||||
else
|
||||
|
||||
|
||||
VERSION=3.13.4
|
||||
|
||||
which cmake
|
||||
wget -q https://github.com/Kitware/CMake/releases/download/v${VERSION}/cmake-${VERSION}-Linux-x86_64.tar.gz -O cmake.tar.gz
|
||||
tar -xzf cmake.tar.gz
|
||||
|
||||
# Remove the original files and copy the new ones over.
|
||||
#sudo rm -rf /usr/local/cmake-3.12.4/*
|
||||
sudo cp -r cmake-${VERSION}*/* $(dirname $(dirname $(which cmake)))
|
||||
which cmake
|
||||
|
||||
|
||||
fi
|
||||
|
||||
cmake --version
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [[ "$(uname -s)" == 'Darwin' ]]; then
|
||||
brew update || brew update
|
||||
brew outdated pyenv || brew upgrade pyenv
|
||||
brew install pyenv-virtualenv
|
||||
brew install cmake || true
|
||||
|
||||
if which pyenv > /dev/null; then
|
||||
eval "$(pyenv init -)"
|
||||
fi
|
||||
|
||||
pyenv install 2.7.10
|
||||
pyenv virtualenv 2.7.10 conan
|
||||
pyenv rehash
|
||||
pyenv activate conan
|
||||
fi
|
||||
|
||||
pip install conan --upgrade
|
||||
pip install conan_package_tools bincrafters_package_tools
|
||||
conan user
|
||||
conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [[ "$(uname -s)" == 'Darwin' ]]; then
|
||||
if which pyenv > /dev/null; then
|
||||
eval "$(pyenv init -)"
|
||||
fi
|
||||
pyenv activate conan
|
||||
fi
|
||||
|
||||
conan create . local/testing
|
||||
#python build.py
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
mkdir -p $HOME/.conan_server
|
||||
cp .ci-files/conan_server/* $HOME/.conan_server
|
||||
conan_server &
|
||||
sleep 3
|
||||
51
.github/workflows/build-develop.yml
vendored
Normal file
51
.github/workflows/build-develop.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Build (develop)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Debug
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# The CMake configure and build commands are platform agnostic and should work equally
|
||||
# well on Windows or Mac. You can convert this to a matrix build if you need
|
||||
# cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Conan
|
||||
id: conan
|
||||
uses: turtlebrowser/get-conan@main
|
||||
|
||||
- name: Conan The Frogarian
|
||||
run: conan frogarian
|
||||
|
||||
- name: Conan Profile Setup
|
||||
run: |
|
||||
conan config init
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Conan Install Dependencies
|
||||
run: conan install -if build . --build=missing
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Test
|
||||
# Execute tests defined by the CMake configuration.
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: cmake --build build --target test --config ${{env.BUILD_TYPE}}
|
||||
51
.github/workflows/build-main.yml
vendored
Normal file
51
.github/workflows/build-main.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Build (main)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Debug
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# The CMake configure and build commands are platform agnostic and should work equally
|
||||
# well on Windows or Mac. You can convert this to a matrix build if you need
|
||||
# cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Conan
|
||||
id: conan
|
||||
uses: turtlebrowser/get-conan@main
|
||||
|
||||
- name: Conan The Frogarian
|
||||
run: conan frogarian
|
||||
|
||||
- name: Conan Profile Setup
|
||||
run: |
|
||||
conan config init
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Conan Install Dependencies
|
||||
run: conan install -if build . --build=missing
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Test
|
||||
# Execute tests defined by the CMake configuration.
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: cmake --build build --target test --config ${{env.BUILD_TYPE}}
|
||||
89
.github/workflows/codeql-analysis.yml
vendored
Normal file
89
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "develop" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "main", "develop" ]
|
||||
schedule:
|
||||
- cron: '38 4 * * 1'
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Debug
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
- name: Install Conan
|
||||
id: conan
|
||||
uses: turtlebrowser/get-conan@main
|
||||
|
||||
- name: Conan The Frogarian
|
||||
run: conan frogarian
|
||||
|
||||
- name: Conan Profile Setup
|
||||
run: |
|
||||
conan config init
|
||||
conan profile update settings.compiler.libcxx=libstdc++11 default
|
||||
|
||||
- name: Conan Install Dependencies
|
||||
run: conan install -if build . --build=missing
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Test
|
||||
# Execute tests defined by the CMake configuration.
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: cmake --build build --target test --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -38,3 +38,10 @@ build/*
|
||||
|
||||
# Qtcreator files
|
||||
*.user
|
||||
|
||||
# VSCode files
|
||||
.vscode
|
||||
|
||||
# IDEA files
|
||||
.idea
|
||||
cmake-build-*
|
||||
|
||||
159
.gitlab-ci.yml
159
.gitlab-ci.yml
@@ -1,159 +0,0 @@
|
||||
stages:
|
||||
- analysis
|
||||
- build
|
||||
- test
|
||||
|
||||
cppcheck:
|
||||
image: ubuntu:bionic
|
||||
stage: analysis
|
||||
before_script:
|
||||
- apt update
|
||||
- apt install -y --no-install-recommends cppcheck=1.82-1 python3-pygments python-pygments
|
||||
- cppcheck --version
|
||||
script:
|
||||
- mkdir cppcheck
|
||||
#- cppcheck . -I include/ --verbose --enable=all --inconclusive --language=c++ --error-exitcode=1
|
||||
- cppcheck . -I include/ --enable=all --inconclusive --xml-version=2 --force --library=windows,posix,gnu . 2> cppcheck/result.xml
|
||||
- cppcheck-htmlreport --source-encoding="iso8859-1" --title="my project name" --source-dir . --report-dir=cppcheck --file=cppcheck/result.xml
|
||||
artifacts:
|
||||
paths:
|
||||
- cppcheck/
|
||||
expire_in: 1 week
|
||||
|
||||
|
||||
.build_template: &job_definition
|
||||
image: conanio/gcc7
|
||||
stage: build
|
||||
before_script:
|
||||
- env
|
||||
- sudo apt update
|
||||
- sudo apt install -y python3-pip
|
||||
- sudo pip3 install gcovr
|
||||
- sudo chmod +x ./.ci-files/install_conan.sh
|
||||
- sudo chmod +x ./.ci-files/install_cmake.sh
|
||||
- sudo chmod +x ./.ci-files/run_conan_server.sh
|
||||
- ./.ci-files/install_conan.sh
|
||||
- ./.ci-files/install_cmake.sh
|
||||
#
|
||||
- ./.ci-files/run_conan_server.sh
|
||||
- conan remote add local http://localhost:9300
|
||||
- conan remote list
|
||||
|
||||
script:
|
||||
- echo $USER --- $HOME
|
||||
- echo Working directory $PWD
|
||||
### Test that we can build the library properly
|
||||
- mkdir -p build && cd build
|
||||
- cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/local
|
||||
- cmake --build .
|
||||
- ctest
|
||||
- mkdir -p artifacts/coverage
|
||||
- gcovr . -r .. --html-details --html -o artifacts/coverage/index.html -e ../test/third_party
|
||||
- sudo cmake --build . --target install
|
||||
## Test that we can build the test application
|
||||
## and the find_package method works correctly.
|
||||
- rm -rf *
|
||||
- cmake ../test_cmake_install/cmake -D CMAKE_PREFIX_PATH=$HOME/local
|
||||
- cmake --build .
|
||||
- ctest
|
||||
## Build the Conan package and upload it to the local repo.
|
||||
- cd ..
|
||||
- conan user -p demo demo -r=local
|
||||
- conan create . local/testing
|
||||
- conan upload foo* -r=local -c --all
|
||||
- conan search "*" -r=local
|
||||
artifacts:
|
||||
paths:
|
||||
- artifacts/*
|
||||
expire_in: 1 week
|
||||
|
||||
build-gcc5:
|
||||
<<: *job_definition # Merge the contents of the 'job_definition' alias
|
||||
image: conanio/gcc5
|
||||
|
||||
build-gcc6:
|
||||
<<: *job_definition # Merge the contents of the 'job_definition' alias
|
||||
image: conanio/gcc6
|
||||
|
||||
build-gcc7:
|
||||
<<: *job_definition # Merge the contents of the 'job_definition' alias
|
||||
image: conanio/gcc7
|
||||
|
||||
build-gcc8:
|
||||
<<: *job_definition # Merge the contents of the 'job_definition' alias
|
||||
image: conanio/gcc8
|
||||
|
||||
build-clang60:
|
||||
<<: *job_definition
|
||||
image: conanio/clang60
|
||||
|
||||
build-clang40:
|
||||
<<: *job_definition
|
||||
image: conanio/clang40
|
||||
|
||||
build-clang50:
|
||||
<<: *job_definition
|
||||
image: conanio/clang50
|
||||
|
||||
build-clang7:
|
||||
<<: *job_definition
|
||||
image: conanio/clang7
|
||||
|
||||
build-clang39:
|
||||
<<: *job_definition
|
||||
image: conanio/clang39
|
||||
|
||||
|
||||
###############################################################################
|
||||
# The test package stage tests whether the different Conan generators work
|
||||
# correctly with the
|
||||
###############################################################################
|
||||
.test_package: &test_package_definition
|
||||
image: conanio/gcc7
|
||||
stage: test
|
||||
dependencies:
|
||||
- build-gcc5
|
||||
- build-gcc6
|
||||
- build-gcc7
|
||||
- build-gcc8
|
||||
before_script:
|
||||
- env
|
||||
- sudo apt update
|
||||
- sudo chmod +x ./.ci-files/install_conan.sh
|
||||
- sudo chmod +x ./.ci-files/install_cmake.sh
|
||||
- sudo chmod +x ./.ci-files/run_conan_server.sh
|
||||
- ./.ci-files/install_conan.sh
|
||||
- ./.ci-files/install_cmake.sh
|
||||
#
|
||||
- ./.ci-files/run_conan_server.sh
|
||||
- conan remote add local http://localhost:9300
|
||||
- conan remote list
|
||||
script:
|
||||
# Create and uplaod the recipe to the repository
|
||||
- conan user -p demo demo -r=local
|
||||
- conan create . local/testing
|
||||
- conan upload foo* -r=local -c --all
|
||||
# Test the Conan cmake generator
|
||||
- mkdir build && cd build
|
||||
- conan install ../test_cmake_install/conan_cmake_generator --build missing
|
||||
- cmake ../test_cmake_install/conan_cmake_generator
|
||||
- cmake --build .
|
||||
- rm -rf *
|
||||
# Test the Conan cmake_paths generator
|
||||
- conan install ../test_cmake_install/conan_cmake_paths_generator --build missing
|
||||
- cmake ../test_cmake_install/conan_cmake_paths_generator
|
||||
- cmake --build .
|
||||
- rm -rf *
|
||||
# Test the Conan find_package generator
|
||||
- conan install ../test_cmake_install/conan_cmake_find_package_generator --build missing
|
||||
- cmake ../test_cmake_install/conan_cmake_find_package_generator
|
||||
- cmake --build .
|
||||
- rm -rf *
|
||||
|
||||
test-package-gcc8:
|
||||
<<: *test_package_definition # Merge the contents of the 'job_definition' alias
|
||||
image: conanio/gcc8
|
||||
|
||||
test-package-clang60:
|
||||
<<: *test_package_definition # Merge the contents of the 'job_definition' alias
|
||||
image: conanio/clang60
|
||||
20
.readthedocs.yaml
Normal file
20
.readthedocs.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: "3.7"
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
56
.travis.yml
56
.travis.yml
@@ -1,56 +0,0 @@
|
||||
linux: &linux
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: python
|
||||
python: "3.7"
|
||||
services:
|
||||
- docker
|
||||
osx: &osx
|
||||
os: osx
|
||||
language: generic
|
||||
matrix:
|
||||
include:
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=conanio/gcc49
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=5 CONAN_DOCKER_IMAGE=conanio/gcc5
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=6 CONAN_DOCKER_IMAGE=conanio/gcc6
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=conanio/gcc7
|
||||
- <<: *linux
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=conanio/clang39
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=conanio/clang40
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=conanio/clang50
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=conanio/clang60
|
||||
- <<: *linux
|
||||
env: CONAN_CLANG_VERSIONS=7.0 CONAN_DOCKER_IMAGE=conanio/clang7
|
||||
- <<: *osx
|
||||
osx_image: xcode7.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=7.3
|
||||
- <<: *osx
|
||||
osx_image: xcode8.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=8.1
|
||||
- <<: *osx
|
||||
osx_image: xcode9
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.0
|
||||
- <<: *osx
|
||||
osx_image: xcode9.4
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.1
|
||||
- <<: *osx
|
||||
osx_image: xcode10.1
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=10.0
|
||||
|
||||
install:
|
||||
- chmod +x .ci-files/install_conan.sh .ci-files/install_cmake.sh
|
||||
- ./.ci-files/install_conan.sh
|
||||
- ./.ci-files/install_cmake.sh
|
||||
|
||||
script:
|
||||
- chmod +x .ci-files/run.sh
|
||||
- ./.ci-files/run.sh
|
||||
25
CITATION.cff
Normal file
25
CITATION.cff
Normal file
@@ -0,0 +1,25 @@
|
||||
# This CITATION.cff file was generated with cffinit.
|
||||
# Visit https://bit.ly/cffinit to generate yours today!
|
||||
|
||||
cff-version: 1.2.0
|
||||
title: Kami is Agent-Based Modeling in Modern C++
|
||||
message: >-
|
||||
If you use this software, please cite it using the
|
||||
metadata from this file.
|
||||
type: software
|
||||
license: MIT
|
||||
repository-code: "https://github.com/JHUAPL/kami"
|
||||
authors:
|
||||
- given-names: James Patrick
|
||||
family-names: Howard
|
||||
name-suffix: II
|
||||
email: james.howard@jhu.edu
|
||||
affiliation: Johns Hopkins Applied Physics Laboratory
|
||||
orcid: 'https://orcid.org/0000-0003-4530-1547'
|
||||
keywords:
|
||||
- "agent-based modelling"
|
||||
- research
|
||||
identifiers:
|
||||
- description: "This is the collection of archived snapshots of all versions of Kami"
|
||||
type: doi
|
||||
value: 10.5281/zenodo.6975259
|
||||
103
CMakeLists.txt
103
CMakeLists.txt
@@ -1,61 +1,27 @@
|
||||
#
|
||||
# This is the Top level CMakelists file which creates the namespace and
|
||||
# organizes all sublibraries under it.
|
||||
#
|
||||
# The project name in this file is considered the "Namespace"
|
||||
# and any libraries under it will be given a target of
|
||||
#
|
||||
# Namespace::library_name
|
||||
#
|
||||
#
|
||||
# This Lists file was modified from https://github.com/forexample/package-example
|
||||
#
|
||||
# This file creates project 'Foo' with two library targets 'bar' and 'cat'.
|
||||
# Target 'cat' depends on 'bar'. After installation this project can be found
|
||||
# by 'find_package(... CONFIG)' command:
|
||||
#
|
||||
# find_package(foo CONFIG REQUIRED)
|
||||
# target_link_libraries(... foo::bar)
|
||||
#
|
||||
# Note that requirements propagated automatically, for example:
|
||||
# * Foo::baz linked automatically
|
||||
# * <prefix>/include added to header search path
|
||||
# * FOO_BAZ_DEBUG=1/FOO_BAR_DEBUG=1 added on Debug
|
||||
# * FOO_BAZ_DEBUG=0/FOO_BAR_DEBUG=0 added on other configurations
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
####
|
||||
# Set minimum version of CMake. We need 3.13 at least.
|
||||
cmake_minimum_required(VERSION 3.13) # GENERATOR_IS_MULTI_CONFIG
|
||||
set(PROJECT_NAME "kami")
|
||||
|
||||
set(KAMI_VERSION_MAJOR 0)
|
||||
set(KAMI_VERSION_MINOR 2)
|
||||
set(KAMI_VERSION_PATCH 0)
|
||||
set(KAMI_VERSION_STRING ${KAMI_VERSION_MAJOR}.${KAMI_VERSION_MINOR}.${KAMI_VERSION_PATCH})
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 7)
|
||||
set(VERSION_PATCH 2)
|
||||
set(VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
|
||||
|
||||
################################################################################
|
||||
# Set variables for the project. The:
|
||||
# * PROJECT_NAME
|
||||
# * PROJECT_VERSION
|
||||
# * PROJECT_NAMESPACE should be the same as the project.
|
||||
project(kami VERSION ${KAMI_VERSION_STRING}
|
||||
LANGUAGES CXX)
|
||||
project(${PROJECT_NAME}
|
||||
VERSION ${VERSION_STRING}
|
||||
LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_BINARY_DIR}" CACHE STRING "Modules for CMake" FORCE)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
set(PROJECT_NAMESPACE kami ) # The project namespace. Library targets
|
||||
# will be referred by
|
||||
# foo::bar. This value should usually be
|
||||
# the same as the project.
|
||||
################################################################################
|
||||
|
||||
|
||||
|
||||
|
||||
set(PROJECT_NAMESPACE ${PROJECT_NAME})
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE)
|
||||
@@ -75,7 +41,6 @@ endif()
|
||||
|
||||
include(cmake/functions.cmake)
|
||||
include(cmake/warnings.cmake)
|
||||
include(cmake/cppcheck.cmake)
|
||||
|
||||
################################################################################
|
||||
# Sub libraries.
|
||||
@@ -96,7 +61,7 @@ ENDFOREACH()
|
||||
################################################################################
|
||||
# Examples.
|
||||
#
|
||||
# Each example will be built as a static or shared library and a
|
||||
# Each example will be built as a static or shared binary and a
|
||||
# target will be created for it.
|
||||
################################################################################
|
||||
|
||||
@@ -126,7 +91,7 @@ include(GNUInstallDirs)
|
||||
# * <prefix>/include/
|
||||
set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
|
||||
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
|
||||
# Configuration
|
||||
set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
@@ -149,7 +114,7 @@ write_basic_package_version_file(
|
||||
# * TARGETS_EXPORT_NAME
|
||||
# * PROJECT_NAME
|
||||
configure_package_config_file(
|
||||
"cmake/Config.cmake.in"
|
||||
"cmake/config.cmake.in"
|
||||
"${project_config}"
|
||||
INSTALL_DESTINATION "${config_install_dir}"
|
||||
)
|
||||
@@ -159,38 +124,32 @@ configure_package_config_file(
|
||||
# * <prefix>/lib/libbaz.a
|
||||
# * header location after install: <prefix>/include/foo/Bar.hpp
|
||||
# * headers can be included by C++ code `#include <foo/Bar.hpp>`
|
||||
install(
|
||||
TARGETS
|
||||
${sub_modules} ${example_modules}
|
||||
${COVERAGE_INSTALL_TARGET}
|
||||
EXPORT
|
||||
"${TARGETS_EXPORT_NAME}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
install(
|
||||
TARGETS ${sub_modules} ${example_modules} ${COVERAGE_INSTALL_TARGET}
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
|
||||
# Config
|
||||
# * <prefix>/lib/cmake/Foo/FooConfig.cmake
|
||||
# * <prefix>/lib/cmake/Foo/FooConfigVersion.cmake
|
||||
install(
|
||||
FILES
|
||||
"${project_config}" "${version_config}"
|
||||
DESTINATION
|
||||
"${config_install_dir}"
|
||||
FILES "${project_config}" "${version_config}"
|
||||
DESTINATION "${config_install_dir}"
|
||||
)
|
||||
|
||||
# Config
|
||||
# * <prefix>/lib/cmake/Foo/FooTargets.cmake
|
||||
install(
|
||||
EXPORT
|
||||
"${TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE
|
||||
"${namespace}"
|
||||
DESTINATION
|
||||
"${config_install_dir}"
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE "${namespace}"
|
||||
DESTINATION "${config_install_dir}"
|
||||
)
|
||||
|
||||
add_subdirectory(docs)
|
||||
add_subdirectory(docs)
|
||||
|
||||
set(ignoreMe "${CMAKE_C_COMPILER}")
|
||||
|
||||
22
COPYRIGHT
Normal file
22
COPYRIGHT
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2020-2023 The Johns Hopkins University Applied Physics
|
||||
Laboratory LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
50
README.md
50
README.md
@@ -1,25 +1,44 @@
|
||||
[](https://github.com/JHUAPL/kami/actions/workflows/build-main.yml)
|
||||
[](https://github.com/JHUAPL/kami/actions/workflows/build-develop.yml)
|
||||
[](https://kami.readthedocs.io/en/main/)
|
||||
[](https://github.com/JHUAPL/kami/releases)
|
||||

|
||||
[](https://doi.org/10.5281/zenodo.6975259)
|
||||
|
||||
# Kami is Agent-Based Modeling in Modern C++
|
||||
|
||||
# Compiling
|
||||
Agent-based models (ABMs) are models for simulating the actions of
|
||||
individual actors within a provided environment to understand the
|
||||
behavior of the agents, most individually and collectively. ABMs
|
||||
are particularly suited for addressing problems governed by nonlinear
|
||||
processes or where there is a wide variety of potential responses
|
||||
an individual agent may provide depending on the environment and
|
||||
behavior of other agents. Because of this, ABMs have become powerful
|
||||
tools in both simulation and modeling, especially in public health
|
||||
and ecology, where they are also known as individual-based models.
|
||||
ABMs also provide support in economic, business, robotics, and many
|
||||
other fields.
|
||||
|
||||
## Compiling
|
||||
|
||||
```Bash
|
||||
|
||||
# Build, test and install the library
|
||||
git clone https://github.com/k3jph/kami.git
|
||||
cd kami
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=/tmp/kami -DBUILD_SHARED_LIBS:BOOL=TRUE
|
||||
cmake --build .
|
||||
ctest -C Debug
|
||||
cmake --build . --target install
|
||||
conan install -if build .
|
||||
cmake -B build -DBUILD_SHARED_LIBS:BOOL=FALSE
|
||||
cmake --build build
|
||||
cmake --build build --target test
|
||||
cmake --build build --target install
|
||||
```
|
||||
|
||||
# Conan Package Manager
|
||||
## Conan Package Manager
|
||||
|
||||
This library comes with a `conanfile.py` to build it into a Conan package so that
|
||||
it may be used by external applications/libraries.
|
||||
|
||||
## Create Conan Packages
|
||||
### Create Conan Packages
|
||||
|
||||
Creating a Conan package is relatively easy. Simple cd into the source directory
|
||||
and execute the conan create function.
|
||||
@@ -31,10 +50,21 @@ cd kami
|
||||
conan create . kami/develop
|
||||
```
|
||||
|
||||
## Direct Dependencies
|
||||
|
||||
* [CLI11](https://github.com/CLIUtils/CLI11)
|
||||
* [Google Test](https://github.com/google/googletest)
|
||||
* [neargye-semver](https://github.com/Neargye/semver)
|
||||
* [spdlog](https://github.com/gabime/spdlog)
|
||||
|
||||
CLI11 and spdlog are both used extensively in the examples.
|
||||
Neither is used directly by the Kami library.
|
||||
|
||||
## Contribution guidelines
|
||||
|
||||
* Use [GitFlow](http://nvie.com/posts/a-successful-git-branching-model/)
|
||||
|
||||
* Use [Google Test](https://github.com/google/googletest)
|
||||
|
||||
## For more information
|
||||
|
||||
* James P. Howard, II <<james.howard@jhu.edu>>
|
||||
* James P. Howard, II <<james.howard@jhu.edu>>
|
||||
|
||||
@@ -8,4 +8,4 @@ include(FindPackageHandleStandardArgs)
|
||||
#Handle standard arguments to find_package like REQUIRED and QUIET
|
||||
find_package_handle_standard_args(Sphinx
|
||||
"Failed to find sphinx-build executable"
|
||||
SPHINX_EXECUTABLE)
|
||||
SPHINX_EXECUTABLE)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
add_custom_target(cppcheck
|
||||
#COMMAND mkdir -p coverage
|
||||
#COMMAND ${CMAKE_MAKE_PROGRAM} test
|
||||
#WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_custom_command(TARGET cppcheck
|
||||
COMMAND echo "=================== CPPCHECK ===================="
|
||||
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/cppcheck
|
||||
COMMAND cppcheck . -I include/ --enable=all --inconclusive --xml-version=2 --force --library=windows,posix,gnu . --output-file=${CMAKE_BINARY_DIR}/cppcheck/result.xml
|
||||
COMMAND cppcheck-htmlreport --source-encoding="iso8859-1" --title="mmp2top" --source-dir . --report-dir=${CMAKE_BINARY_DIR}/cppcheck --file=${CMAKE_BINARY_DIR}/cppcheck/result.xml
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} # Need separate command for this line
|
||||
)
|
||||
34
conanfile.py
34
conanfile.py
@@ -3,39 +3,35 @@ from conans import ConanFile, CMake
|
||||
|
||||
class KamiConan(ConanFile):
|
||||
name = "kami"
|
||||
version = "0.2.0"
|
||||
version = "0.7.2"
|
||||
license = "MIT"
|
||||
author = "James P. Howard, II <james.howard@jhu.edu>"
|
||||
url = "http://github.com/GavinNL/cpp_library_template"
|
||||
url = "https://github.com/jhuapl/kami"
|
||||
description = "Agent-Based Modeling in Modern C++"
|
||||
topics = ("agent-based modeling", "simulation", "orms")
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "cmake"
|
||||
generators = "cmake", "cmake_find_package"
|
||||
exports_sources = "*"
|
||||
|
||||
options = {"shared": [True, False], "fPIC": [True, False]}
|
||||
default_options = {"shared": False, "fPIC": True}
|
||||
default_options = {"shared": False, "fPIC": False}
|
||||
|
||||
|
||||
def _configure_cmake(self):
|
||||
cmake = CMake(self)
|
||||
|
||||
cmake.definitions["BUILD_SHARED_LIBS"] = self.options.shared
|
||||
|
||||
cmake.configure()
|
||||
|
||||
return cmake
|
||||
|
||||
|
||||
def build(self):
|
||||
cmake = self._configure_cmake()
|
||||
cmake = CMake(self) # it will find the packages by using our auto-generated FindXXX.cmake files
|
||||
cmake.definitions["BUILD_SHARED_LIBS"] = self.options.shared
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
|
||||
def package(self):
|
||||
'''
|
||||
Create a package using "cmake --build . --target install"
|
||||
All installation files are defined in the CMakeLists.txt file rather
|
||||
than in the conan package.
|
||||
'''
|
||||
cmake = self._configure_cmake()
|
||||
cmake.install()
|
||||
|
||||
@@ -44,9 +40,13 @@ class KamiConan(ConanFile):
|
||||
# These libraries are required when using the
|
||||
# following generators:
|
||||
# cmake, cmake_paths, cmake_
|
||||
self.cpp_info.libs = ["dog", "cat", "bar", "kami", "kamidata"]
|
||||
self.cpp_info.libs = ["kami"]
|
||||
|
||||
|
||||
def requirements(self):
|
||||
# Or add a new requirement!
|
||||
self.requires("spdlog/1.7.0")
|
||||
self.requires("cli11/1.9.1")
|
||||
self.requires("fmt/9.0.0")
|
||||
self.requires("spdlog/1.10.0")
|
||||
self.requires("cli11/2.2.0")
|
||||
self.requires("neargye-semver/0.3.0")
|
||||
self.requires("gtest/cci.20210126")
|
||||
self.requires("nlohmann_json/3.11.1")
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
[requires]
|
||||
spdlog/1.7.0
|
||||
cli11/1.9.1
|
||||
|
||||
[generators]
|
||||
cmake
|
||||
@@ -1,58 +1,60 @@
|
||||
find_package(Doxygen REQUIRED)
|
||||
find_package(Sphinx REQUIRED)
|
||||
if(NOT ${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||
find_package(Doxygen REQUIRED)
|
||||
find_package(Sphinx REQUIRED)
|
||||
|
||||
# Find all the public headers
|
||||
get_target_property(KAMI_PUBLIC_HEADER_DIR kami INTERFACE_INCLUDE_DIRECTORIES)
|
||||
file(GLOB_RECURSE KAMI_PUBLIC_HEADERS ${KAMI_PUBLIC_HEADER_DIR}/kami/*.hpp)
|
||||
# Find all the public headers
|
||||
get_target_property(KAMI_PUBLIC_HEADER_DIR libkami INTERFACE_INCLUDE_DIRECTORIES)
|
||||
file(GLOB_RECURSE KAMI_PUBLIC_HEADERS ${KAMI_PUBLIC_HEADER_DIR}/kami/*.h)
|
||||
|
||||
set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}/include/kami)
|
||||
set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/xml/index.xml)
|
||||
set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
|
||||
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}/include/kami)
|
||||
set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/xml/index.xml)
|
||||
set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
|
||||
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
|
||||
# Replace variables inside @@ with the current values
|
||||
configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)
|
||||
# Replace variables inside @@ with the current values
|
||||
configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)
|
||||
|
||||
# Doxygen won't create this for us
|
||||
file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR})
|
||||
# Doxygen won't create this for us
|
||||
file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR})
|
||||
|
||||
# Only regenerate Doxygen when the Doxyfile or public headers change
|
||||
add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE}
|
||||
DEPENDS ${KAMI_PUBLIC_HEADERS}
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}
|
||||
MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN}
|
||||
COMMENT "Generating docs"
|
||||
VERBATIM)
|
||||
# Only regenerate Doxygen when the Doxyfile or public headers change
|
||||
add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE}
|
||||
DEPENDS ${KAMI_PUBLIC_HEADERS}
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}
|
||||
MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN}
|
||||
COMMENT "Generating docs"
|
||||
VERBATIM)
|
||||
|
||||
# Nice named target so we can run the job easily
|
||||
add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE})
|
||||
# Nice named target so we can run the job easily
|
||||
add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE})
|
||||
|
||||
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/sphinx)
|
||||
set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html)
|
||||
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/sphinx)
|
||||
set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html)
|
||||
|
||||
# Only regenerate Sphinx when:
|
||||
# - Doxygen has rerun
|
||||
# - Our doc files have been updated
|
||||
# - The Sphinx config has been updated
|
||||
add_custom_command(OUTPUT ${SPHINX_INDEX_FILE}
|
||||
COMMAND
|
||||
${SPHINX_EXECUTABLE} -b html
|
||||
# Tell Breathe where to find the Doxygen output
|
||||
-Dbreathe_projects.kami=${DOXYGEN_OUTPUT_DIR}/xml
|
||||
${SPHINX_SOURCE} ${SPHINX_BUILD}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS
|
||||
# Other docs files you want to track should go here (or in some variable)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/index.rst
|
||||
${DOXYGEN_INDEX_FILE}
|
||||
MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py
|
||||
COMMENT "Generating documentation with Sphinx")
|
||||
# Only regenerate Sphinx when:
|
||||
# - Doxygen has rerun
|
||||
# - Our doc files have been updated
|
||||
# - The Sphinx config has been updated
|
||||
add_custom_command(OUTPUT ${SPHINX_INDEX_FILE}
|
||||
COMMAND
|
||||
${SPHINX_EXECUTABLE} -b html
|
||||
# Tell Breathe where to find the Doxygen output
|
||||
-Dbreathe_projects.kami=${DOXYGEN_OUTPUT_DIR}/xml
|
||||
${SPHINX_SOURCE} ${SPHINX_BUILD}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS
|
||||
# Other docs files you want to track should go here (or in some variable)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/index.rst
|
||||
${DOXYGEN_INDEX_FILE}
|
||||
MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py
|
||||
COMMENT "Generating documentation with Sphinx")
|
||||
|
||||
# Nice named target so we can run the job easily
|
||||
add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE})
|
||||
# Nice named target so we can run the job easily
|
||||
add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE})
|
||||
|
||||
# Add an install target to install the docs
|
||||
include(GNUInstallDirs)
|
||||
install(DIRECTORY ${SPHINX_BUILD}/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/html)
|
||||
# Add an install target to install the docs
|
||||
include(GNUInstallDirs)
|
||||
install(DIRECTORY ${SPHINX_BUILD}/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/html)
|
||||
endif()
|
||||
|
||||
417
docs/Doxyfile.in
417
docs/Doxyfile.in
@@ -38,13 +38,13 @@ PROJECT_NAME = "Kami"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.1.0
|
||||
PROJECT_NUMBER = "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "Kami is Agent-Based Modeling in C++
|
||||
PROJECT_BRIEF = "Kami is Agent-Based Modeling in C++"
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||
# in the documentation. The maximum height of the logo should not exceed 55
|
||||
@@ -230,12 +230,6 @@ TAB_SIZE = 4
|
||||
|
||||
ALIASES =
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
# will allow you to use the command class in the itcl::class meaning.
|
||||
|
||||
TCL_SUBST =
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C. For
|
||||
# instance, some of the names that are used will be different. The list of all
|
||||
@@ -281,7 +275,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
|
||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||
# the files are not read by doxygen.
|
||||
|
||||
EXTENSION_MAPPING =
|
||||
EXTENSION_MAPPING = h=C++
|
||||
|
||||
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
|
||||
# according to the Markdown format, which allows for more readable
|
||||
@@ -795,9 +789,9 @@ INPUT_ENCODING = UTF-8
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cc, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.hh, *.h, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
|
||||
# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
|
||||
|
||||
@@ -843,7 +837,7 @@ EXCLUDE_PATTERNS =
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */test/*
|
||||
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXCLUDE_SYMBOLS = *_H
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
|
||||
# that contain example code fragments that are included (see the \include
|
||||
@@ -1025,13 +1019,6 @@ VERBATIM_HEADERS = YES
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
||||
# which the alphabetical index list will be split.
|
||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all classes will
|
||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||
@@ -1438,17 +1425,6 @@ EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
FORMULA_FONTSIZE = 10
|
||||
|
||||
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
|
||||
# generated for formulas are transparent PNGs. Transparent PNGs are not
|
||||
# supported properly for IE 6.0, but are supported on all modern browsers.
|
||||
#
|
||||
# Note that when changing this option you need to delete any form_*.png files in
|
||||
# the HTML output directory before the changes have effect.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||
# http://www.mathjax.org) which uses client side Javascript for the rendering
|
||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||
@@ -1591,167 +1567,7 @@ EXTRA_SEARCH_MAPPINGS =
|
||||
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_LATEX = YES
|
||||
|
||||
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
# it.
|
||||
# The default directory is: latex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_OUTPUT = latex
|
||||
|
||||
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
|
||||
# invoked.
|
||||
#
|
||||
# Note that when enabling USE_PDFLATEX this option is only used for generating
|
||||
# bitmaps for formulas in the HTML output, but not in the Makefile that is
|
||||
# written to the output directory.
|
||||
# The default file is: latex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_CMD_NAME = latex
|
||||
|
||||
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
|
||||
# index for LaTeX.
|
||||
# The default file is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
|
||||
# documents. This may be useful for small projects and may help to save some
|
||||
# trees in general.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
COMPACT_LATEX = NO
|
||||
|
||||
# The PAPER_TYPE tag can be used to set the paper type that is used by the
|
||||
# printer.
|
||||
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
|
||||
# 14 inches) and executive (7.25 x 10.5 inches).
|
||||
# The default value is: a4.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
PAPER_TYPE = letter
|
||||
|
||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
||||
# that should be included in the LaTeX output. The package can be specified just
|
||||
# by its name or with the correct syntax as to be used with the LaTeX
|
||||
# \usepackage command. To get the times font for instance you can specify :
|
||||
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
|
||||
# To use the option intlimits with the amsmath package you can specify:
|
||||
# EXTRA_PACKAGES=[intlimits]{amsmath}
|
||||
# If left blank no extra packages will be included.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
|
||||
# generated LaTeX document. The header should contain everything until the first
|
||||
# chapter. If it is left blank doxygen will generate a standard header. See
|
||||
# section "Doxygen usage" for information on how to let doxygen write the
|
||||
# default header to a separate file.
|
||||
#
|
||||
# Note: Only use a user-defined header if you know what you are doing! The
|
||||
# following commands have a special meaning inside the header: $title,
|
||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
|
||||
# string, for the replacement values of the other commands the user is referred
|
||||
# to HTML_HEADER.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_HEADER =
|
||||
|
||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
||||
# generated LaTeX document. The footer should contain everything after the last
|
||||
# chapter. If it is left blank doxygen will generate a standard footer. See
|
||||
# LATEX_HEADER for more information on how to generate a default footer and what
|
||||
# special commands can be used inside the footer.
|
||||
#
|
||||
# Note: Only use a user-defined footer if you know what you are doing!
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_FOOTER =
|
||||
|
||||
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||
# LaTeX style sheets that are included after the standard style sheets created
|
||||
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
|
||||
# will copy the style sheet files to the output directory.
|
||||
# Note: The order of the extra style sheet files is of importance (e.g. the last
|
||||
# style sheet in the list overrules the setting of the previous ones in the
|
||||
# list).
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
|
||||
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the LATEX_OUTPUT output
|
||||
# directory. Note that the files will be copied as-is; there are no commands or
|
||||
# markers available.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_EXTRA_FILES =
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
|
||||
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
|
||||
# contain links (just like the HTML output) instead of page references. This
|
||||
# makes the output suitable for online browsing using a PDF viewer.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
PDF_HYPERLINKS = YES
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
||||
# higher quality PDF documentation.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
USE_PDFLATEX = YES
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
||||
# if errors occur, instead of asking the user for help. This option is also used
|
||||
# when generating formulas in HTML.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_BATCHMODE = NO
|
||||
|
||||
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
|
||||
# index chapters (such as File Index, Compound Index, etc.) in the output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_HIDE_INDICES = NO
|
||||
|
||||
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
|
||||
# code with syntax highlighting in the LaTeX output.
|
||||
#
|
||||
# Note that which sources are shown also depends on other settings such as
|
||||
# SOURCE_BROWSER.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_SOURCE_CODE = NO
|
||||
|
||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||
# bibliography, e.g. plainnat, or ieeetr. See
|
||||
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
# The default value is: plain.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_BIB_STYLE = plain
|
||||
|
||||
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to NO can help when comparing the output of multiple runs.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_TIMESTAMP = NO
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
@@ -1764,61 +1580,6 @@ LATEX_TIMESTAMP = NO
|
||||
|
||||
GENERATE_RTF = NO
|
||||
|
||||
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
# it.
|
||||
# The default directory is: rtf.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_OUTPUT = rtf
|
||||
|
||||
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
|
||||
# documents. This may be useful for small projects and may help to save some
|
||||
# trees in general.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
COMPACT_RTF = NO
|
||||
|
||||
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
|
||||
# contain hyperlink fields. The RTF file will contain links (just like the HTML
|
||||
# output) instead of page references. This makes the output suitable for online
|
||||
# browsing using Word or some other Word compatible readers that support those
|
||||
# fields.
|
||||
#
|
||||
# Note: WordPad (write) and others do not support links.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_HYPERLINKS = NO
|
||||
|
||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
|
||||
# file, i.e. a series of assignments. You only have to provide replacements,
|
||||
# missing definitions are set to their default value.
|
||||
#
|
||||
# See also section "Doxygen usage" for information on how to generate the
|
||||
# default style sheet that doxygen normally uses.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_STYLESHEET_FILE =
|
||||
|
||||
# Set optional variables used in the generation of an RTF document. Syntax is
|
||||
# similar to doxygen's config file. A template extensions file can be generated
|
||||
# using doxygen -e rtf extensionFile.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
||||
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
|
||||
# with syntax highlighting in the RTF output.
|
||||
#
|
||||
# Note that which sources are shown also depends on other settings such as
|
||||
# SOURCE_BROWSER.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_SOURCE_CODE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -1829,40 +1590,6 @@ RTF_SOURCE_CODE = NO
|
||||
|
||||
GENERATE_MAN = NO
|
||||
|
||||
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
# it. A directory man3 will be created inside the directory specified by
|
||||
# MAN_OUTPUT.
|
||||
# The default directory is: man.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
|
||||
MAN_OUTPUT = man
|
||||
|
||||
# The MAN_EXTENSION tag determines the extension that is added to the generated
|
||||
# man pages. In case the manual section does not start with a number, the number
|
||||
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
|
||||
# optional.
|
||||
# The default value is: .3.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
|
||||
MAN_EXTENSION = .3
|
||||
|
||||
# The MAN_SUBDIR tag determines the name of the directory created within
|
||||
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
|
||||
# MAN_EXTENSION with the initial . removed.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
|
||||
MAN_SUBDIR =
|
||||
|
||||
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
||||
# will generate one additional man file for each entity documented in the real
|
||||
# man page(s). These additional files only source the real man page, but without
|
||||
# them the man command would be unable to find the correct page.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||
|
||||
MAN_LINKS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -1871,24 +1598,7 @@ MAN_LINKS = NO
|
||||
# captures the structure of the code including all documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_XML = YES
|
||||
|
||||
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
# it.
|
||||
# The default directory is: xml.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_OUTPUT = xml
|
||||
|
||||
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
|
||||
# listings (including syntax highlighting and cross-referencing information) to
|
||||
# the XML output. Note that enabling this will significantly increase the size
|
||||
# of the XML output.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_PROGRAMLISTING = YES
|
||||
GENERATE_XML = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
@@ -1900,23 +1610,6 @@ XML_PROGRAMLISTING = YES
|
||||
|
||||
GENERATE_DOCBOOK = NO
|
||||
|
||||
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
|
||||
# front of it.
|
||||
# The default directory is: docbook.
|
||||
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
||||
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
|
||||
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
|
||||
# program listings (including syntax highlighting and cross-referencing
|
||||
# information) to the DOCBOOK output. Note that enabling this will significantly
|
||||
# increase the size of the DOCBOOK output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
||||
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -1941,32 +1634,6 @@ GENERATE_AUTOGEN_DEF = NO
|
||||
|
||||
GENERATE_PERLMOD = NO
|
||||
|
||||
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
|
||||
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
|
||||
# output from the Perl module output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
|
||||
|
||||
PERLMOD_LATEX = NO
|
||||
|
||||
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
|
||||
# formatted so it can be parsed by a human reader. This is useful if you want to
|
||||
# understand what is going on. On the other hand, if this tag is set to NO, the
|
||||
# size of the Perl module output will be much smaller and Perl will parse it
|
||||
# just the same.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
|
||||
|
||||
PERLMOD_PRETTY = YES
|
||||
|
||||
# The names of the make variables in the generated doxyrules.make file are
|
||||
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
|
||||
# so different doxyrules.make files included by the same Makefile don't
|
||||
# overwrite each other's variables.
|
||||
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
|
||||
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -1984,7 +1651,7 @@ ENABLE_PREPROCESSING = YES
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
MACRO_EXPANSION = YES
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
|
||||
# the macro expansion is limited to the macros specified with the PREDEFINED and
|
||||
@@ -1992,7 +1659,7 @@ MACRO_EXPANSION = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
|
||||
# INCLUDE_PATH will be searched if a #include is found.
|
||||
@@ -2024,11 +1691,11 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = __declspec(x)=
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
# macro definition that is found in the sources will be used. Use the PREDEFINED
|
||||
# macro definition that is found in the sources will be used. Use the MACRO_EXPANSION
|
||||
# tag if you want to use a different macro definition that overrules the
|
||||
# definition found in the source code.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
@@ -2091,34 +1758,10 @@ EXTERNAL_GROUPS = YES
|
||||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
|
||||
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
|
||||
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
|
||||
# disabled, but it is recommended to install and use dot, since it yields more
|
||||
# powerful graphs.
|
||||
# The default value is: YES.
|
||||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see:
|
||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
@@ -2151,30 +1794,6 @@ HAVE_DOT = NO
|
||||
|
||||
DOT_NUM_THREADS = 0
|
||||
|
||||
# When you want a differently looking font in the dot files that doxygen
|
||||
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
||||
# sure dot is able to find the font, which can be done by putting it in a
|
||||
# standard location or by setting the DOTFONTPATH environment variable or by
|
||||
# setting DOT_FONTPATH to the directory containing the font.
|
||||
# The default value is: Helvetica.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_FONTNAME = Helvetica
|
||||
|
||||
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
|
||||
# dot graphs.
|
||||
# Minimum value: 4, maximum value: 24, default value: 10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_FONTSIZE = 10
|
||||
|
||||
# By default doxygen will tell dot to use the default font as specified with
|
||||
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
|
||||
# the path where dot can find it using this tag.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_FONTPATH =
|
||||
|
||||
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
|
||||
# each documented class showing the direct and indirect inheritance relations.
|
||||
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
|
||||
@@ -2375,18 +1994,6 @@ DOT_GRAPH_MAX_NODES = 50
|
||||
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
|
||||
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
|
||||
# background. This is disabled by default, because dot on Windows does not seem
|
||||
# to support this out of the box.
|
||||
#
|
||||
# Warning: Depending on the platform used, enabling this option may lead to
|
||||
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
|
||||
# read).
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_TRANSPARENT = NO
|
||||
|
||||
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
||||
# files in one run (i.e. multiple -o and -T options on the command line). This
|
||||
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
|
||||
|
||||
40
docs/abm.rst
Normal file
40
docs/abm.rst
Normal file
@@ -0,0 +1,40 @@
|
||||
About Agent-Based Models
|
||||
========================
|
||||
|
||||
Agent-based models (ABM) are a type of computational model used
|
||||
to simulate the behavior of autonomous agents within a system. These
|
||||
agents can be individuals, groups, organizations, or other entities
|
||||
that interact with one another and with their environment.
|
||||
|
||||
One of the key features of ABMs is that they focus on the micro-level
|
||||
interactions between individual agents, rather than aggregating
|
||||
data to study macro-level phenomena. This allows for the examination
|
||||
of complex behaviors that emerge from the interactions between
|
||||
agents, such as the spread of a disease or the formation of social
|
||||
networks.
|
||||
|
||||
ABMs are often used in fields such as economics, sociology, and
|
||||
biology to study the behavior of individuals and groups. They can
|
||||
also be used to simulate the effects of different policies or
|
||||
interventions on a system.
|
||||
|
||||
In order to create an ABM, the researcher must first define the
|
||||
agents and their characteristics, such as their behavior, beliefs,
|
||||
and goals. They must also define the rules of interaction between
|
||||
the agents and their environment. Once these parameters are set,
|
||||
the model can be run to simulate the behavior of the agents over
|
||||
time.
|
||||
|
||||
ABMs are a powerful tool for understanding complex systems, but
|
||||
they also have their limitations. Because they focus on micro-level
|
||||
interactions, they may not accurately capture macro-level phenomena.
|
||||
Additionally, they often require a significant amount of computational
|
||||
resources and can be difficult to validate.
|
||||
|
||||
Overall, agent-based models are a valuable tool for understanding
|
||||
the behavior of complex systems and the emergence of complex behaviors
|
||||
from the interactions between individuals. However, it is important
|
||||
to use them in conjunction with other methods to fully understand
|
||||
the system being studied.
|
||||
|
||||
.. toctree::
|
||||
64
docs/changelog.rst
Normal file
64
docs/changelog.rst
Normal file
@@ -0,0 +1,64 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Below is the consolidated changelog for Kami.
|
||||
|
||||
- :feature:`0` Added baseline for continuous domains
|
||||
|
||||
- :release:`0.7.2 <2023.01.22>`
|
||||
- :bug:`0` Streamlined documentation builds
|
||||
|
||||
- :release:`0.7.1 <2023.01.22>`
|
||||
- :bug:`0` Corrected bug in documentation build
|
||||
|
||||
- :release:`0.7.0 <2023.01.22>`
|
||||
- :support:`0` Added a minimal example and tutorial
|
||||
- :support:`0` Added documentation for each example
|
||||
- :feature:`0` Readded step() to the Model interface
|
||||
- :feature:`0` Moved to exception-based error handling
|
||||
- :feature:`0` Added Bank Reserves model to demonstrate reporting
|
||||
- :feature:`0` Added data collecting and reporting modules
|
||||
- :feature:`0` Added some useful constants, for use as random seeds
|
||||
- :feature:`0` Switched from ranlux24 to mt19937 due to speed
|
||||
- :feature:`0` Added distance measures to grid coordinate objects
|
||||
|
||||
- :release:`0.6.0 <2022.08.19>`
|
||||
- :feature:`0` Added a to do list to the documentation
|
||||
- :feature:`0` Completed basic unit tests
|
||||
- :feature:`0` Removed step()/run() from Model interface
|
||||
- :feature:`0` Revised interfaces to the grids
|
||||
- :feature:`0` Updated all support packages to most current versions
|
||||
|
||||
- :release:`0.5.1 <2022.08.11>`
|
||||
- :support:`0` Completed initial unit tests
|
||||
- :support:`0` Added background info to READ ME
|
||||
|
||||
- :release:`0.5.0 <2022.08.08>`
|
||||
- :feature:`0` Added a barebones "starter" model to build from
|
||||
- :support:`0` Numerous documentation cleanups
|
||||
- :bug:`0` Numerous code cleanups to remove void returns and eliminate stored Model references
|
||||
- :feature:`0` Restructured the entire interface
|
||||
- :bug:`0` Numerous build process cleanups
|
||||
- :feature:`0` Added support semver versioning via neargye-semver
|
||||
- :bug:`0` Make library static by default
|
||||
- :bug:`0` Corrected the badge link in the README file
|
||||
|
||||
- :release:`0.4.2 <2021.09.25>`
|
||||
- :bug:`0` Fixed Changelog to move docs to support
|
||||
- :bug:`0` Fixed Changelog with current releases added
|
||||
|
||||
- :release:`0.4.1 <2021.09.25>`
|
||||
- :bug:`0` Fixed README file links
|
||||
|
||||
- :release:`0.4.0 <2021.09.25>`
|
||||
- :bug:`0` Cleaned up numerous issues found by CLion's linter
|
||||
- :support:`0` Added a new overview to the documents
|
||||
- :support:`0` Added basic installation instructions
|
||||
- :bug:`0` Retagged previous versions using pure Semantic Versioning
|
||||
- :support:`0` Documentation for `kami::RandomScheduler`
|
||||
- :support:`0` Added a changelog!
|
||||
|
||||
- :release:`0.3.0 <2021.09.20>`
|
||||
- :feature:`0` Initial public release.
|
||||
|
||||
.. toctree::
|
||||
158
docs/conf.py
158
docs/conf.py
@@ -1,34 +1,34 @@
|
||||
import subprocess, os
|
||||
import sphinx_bootstrap_theme
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from documenteer.sphinxconfig.utils import form_ltd_edition_name
|
||||
|
||||
|
||||
def configureDoxyfile(input_dir, output_dir):
|
||||
with open('Doxyfile.in', 'r') as file:
|
||||
filedata = file.read()
|
||||
|
||||
with open('Doxyfile.in', 'r') as file :
|
||||
filedata = file.read()
|
||||
filedata = filedata.replace('@DOXYGEN_INPUT_DIR@', input_dir)
|
||||
filedata = filedata.replace('@DOXYGEN_OUTPUT_DIR@', output_dir)
|
||||
|
||||
filedata = filedata.replace('@DOXYGEN_INPUT_DIR@', input_dir)
|
||||
filedata = filedata.replace('@DOXYGEN_OUTPUT_DIR@', output_dir)
|
||||
|
||||
with open('Doxyfile', 'w') as file:
|
||||
file.write(filedata)
|
||||
with open('Doxyfile', 'w') as file:
|
||||
file.write(filedata)
|
||||
|
||||
# Check if we're running on Read the Docs' servers
|
||||
read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if read_the_docs_build:
|
||||
input_dir = '../include/kami'
|
||||
output_dir = 'build'
|
||||
configureDoxyfile(input_dir, output_dir)
|
||||
subprocess.call('doxygen', shell=True)
|
||||
breathe_projects['kami'] = output_dir + 'docs/xml'
|
||||
|
||||
input_dir = '../include/kami'
|
||||
output_dir = 'build'
|
||||
configureDoxyfile(input_dir, output_dir)
|
||||
subprocess.call('doxygen', shell=True)
|
||||
breathe_projects = { "kami": output_dir + 'docs/xml' }
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Kami'
|
||||
copyright = '2020'
|
||||
author = 'James P. Howard, II'
|
||||
|
||||
copyright = '2020-2023 The Johns Hopkins University Applied Physics Laboratory LLC'
|
||||
author = 'James P. Howard, II <james.howard@jhu.edu>'
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
@@ -42,8 +42,14 @@ author = 'James P. Howard, II'
|
||||
extensions = [
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.githubpages',
|
||||
'breathe'
|
||||
]
|
||||
'breathe',
|
||||
'exhale',
|
||||
'myst_parser',
|
||||
'releases']
|
||||
|
||||
# 'releases' (changelog) settings
|
||||
releases_github_path = "JHUAPL/kami"
|
||||
releases_unstable_prehistory = True
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -62,22 +68,52 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
# Setup the breathe extension
|
||||
breathe_default_project = "kami"
|
||||
|
||||
# Setup the exhale extension
|
||||
exhale_args = {
|
||||
# These arguments are required
|
||||
"containmentFolder": "./api",
|
||||
"rootFileName": "library_root.rst",
|
||||
"rootFileTitle": "Library API",
|
||||
"doxygenStripFromPath": "..",
|
||||
# Suggested optional arguments
|
||||
"createTreeView": True,
|
||||
"exhaleExecutesDoxygen": True,
|
||||
"exhaleDoxygenStdin": "INPUT = ../include"
|
||||
}
|
||||
|
||||
# Tell sphinx what the primary language being documented is.
|
||||
primary_domain = 'cpp'
|
||||
|
||||
# Tell sphinx what the pygments highlight language should be.
|
||||
highlight_language = 'cpp'
|
||||
|
||||
# The short X.Y version
|
||||
version = ''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '0.1.0'
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
github_ref = os.getenv("GITHUB_REF", "")
|
||||
if github_ref == "":
|
||||
git_ref = "main"
|
||||
else:
|
||||
match = re.match(r"refs/(heads|tags|pull)/(?P<ref>.+)", github_ref)
|
||||
if not match:
|
||||
git_ref = "main"
|
||||
else:
|
||||
git_ref = match.group("ref")
|
||||
|
||||
version = form_ltd_edition_name(git_ref)
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = version
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
source_suffix = ['.rst', '.md']
|
||||
source_suffix = {
|
||||
'.rst': 'restructuredtext',
|
||||
'.md': 'markdown',
|
||||
}
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
@@ -119,43 +155,11 @@ pygments_style = 'sphinx'
|
||||
#
|
||||
# html_sidebars = {}
|
||||
#---sphinx-themes-----
|
||||
html_theme = 'bootstrap'
|
||||
html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a
|
||||
# theme further.
|
||||
html_theme_options = {
|
||||
# Navigation bar title. (Default: ``project`` value)
|
||||
'navbar_title': "Kami",
|
||||
|
||||
# Tab name for entire site. (Default: "Site")
|
||||
'navbar_site_name': "Site",
|
||||
|
||||
# A list of tuples containing pages or urls to link to.
|
||||
# Valid tuples should be in the following forms:
|
||||
# (name, page) # a link to a page
|
||||
# (name, "/aa/bb", 1) # a link to an arbitrary relative url
|
||||
# (name, "http://example.com", True) # arbitrary absolute url
|
||||
# Note the "1" or "True" value above as the third argument to indicate
|
||||
# an arbitrary url.
|
||||
'navbar_links': [
|
||||
("Examples", "examples"),
|
||||
("Link", "http://example.com", True),
|
||||
],
|
||||
|
||||
# Render the next and previous page links in navbar. (Default: true)
|
||||
'navbar_sidebarrel': True,
|
||||
|
||||
# Render the current pages TOC in the navbar. (Default: true)
|
||||
'navbar_pagenav': True,
|
||||
|
||||
# Tab name for the current pages TOC. (Default: "Page")
|
||||
'navbar_pagenav_name': "Page",
|
||||
|
||||
# Global TOC depth for "site" navbar tab. (Default: 1)
|
||||
# Switching to -1 shows all levels.
|
||||
'globaltoc_depth': 2,
|
||||
|
||||
# Include hidden TOCs in Site navbar?
|
||||
#
|
||||
# Note: If this is "false", you cannot have mixed ``:hidden:`` and
|
||||
@@ -165,32 +169,18 @@ html_theme_options = {
|
||||
# Values: "true" (default) or "false"
|
||||
'globaltoc_includehidden': "true",
|
||||
|
||||
# HTML navbar class (Default: "navbar") to attach to <div> element.
|
||||
# For black navbar, do "navbar navbar-inverse"
|
||||
'navbar_class': "navbar navbar-inverse",
|
||||
'display_version': True,
|
||||
}
|
||||
|
||||
# Fix navigation bar to top of page?
|
||||
# Values: "true" (default) or "false"
|
||||
'navbar_fixed_top': "true",
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# Location of link to source.
|
||||
# Options are "nav" (default), "footer" or anything else to exclude.
|
||||
'source_link_position': "nav",
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'kami', u'Kami: Agent-Based Modeling in Modern C++',
|
||||
[author], '3kami')
|
||||
]
|
||||
|
||||
# Bootswatch (http://bootswatch.com/) theme.
|
||||
#
|
||||
# Options are nothing (default) or the name of a valid theme
|
||||
# such as "cosmo" or "sandstone".
|
||||
#
|
||||
# The set of valid themes depend on the version of Bootstrap
|
||||
# that's used (the next config option).
|
||||
#
|
||||
# Currently, the supported themes are:
|
||||
# - Bootstrap 2: https://bootswatch.com/2
|
||||
# - Bootstrap 3: https://bootswatch.com/3
|
||||
'bootswatch_theme': "paper",
|
||||
|
||||
# Choose Bootstrap version.
|
||||
# Values: "3" (default) or "2" (in quotes)
|
||||
'bootstrap_version': "3",
|
||||
}
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
html_show_sphinx = False
|
||||
56
docs/examples/bankreserves.rst
Normal file
56
docs/examples/bankreserves.rst
Normal file
@@ -0,0 +1,56 @@
|
||||
bankreserves
|
||||
============
|
||||
|
||||
This example provides a two-dimensional bank reserves model (BSM)
|
||||
as an example of a simple application of the reporter classes for
|
||||
monitoring the internal functioning of the model.
|
||||
|
||||
The BSM is a type of computational model that simulates the behavior
|
||||
of customers and their interactions with a bank. It is used to study
|
||||
the dynamics of the money supply and the management of reserves by
|
||||
the bank.
|
||||
|
||||
In a BSM, individuals are represented as autonomous agents that
|
||||
make decisions about saving, borrowing, and repaying loans based
|
||||
on their individual objectives and constraints. The bank is also
|
||||
represented as an agent that maintains accounts for each individual.
|
||||
The interactions between individuals and the bank are simulated
|
||||
over time, and the model can be used to study the effects of different
|
||||
reserve requirements policies on the creation of money, borrowing,
|
||||
lending, and savings.
|
||||
|
||||
One of the main advantages of a BSM is that it allows for the
|
||||
examination of the micro-level interactions between individuals and
|
||||
the bank, which can provide a more detailed understanding of the
|
||||
dynamics of the monetary system.
|
||||
|
||||
It is important to note that BSMs are a simplified representation
|
||||
of the real world and may not capture all the nuances of the monetary
|
||||
system being studied. It's also important to use this model in
|
||||
conjunction with other methods to fully understand the monetary
|
||||
system.
|
||||
|
||||
.. list-table::
|
||||
:widths: 30 70
|
||||
:header-rows: 1
|
||||
|
||||
* - Option
|
||||
- Description
|
||||
* - -c *agent_count*
|
||||
- Set the number of agents
|
||||
* - -f *output_file_name*
|
||||
- Set the JSON report file
|
||||
* - -l *log_level_option*
|
||||
- Set the logging level
|
||||
* - -n *max_steps*
|
||||
- Set the number of steps to run the model
|
||||
* - -s *initial_seed*
|
||||
- Set the initial seed
|
||||
* - -x *x_size*
|
||||
- Set the number of columns
|
||||
* - -y *y_size*
|
||||
- Set the number of rows
|
||||
* - -w *max_initial_wealth*
|
||||
- Set the maximum initial agent wealth
|
||||
|
||||
.. toctree::
|
||||
60
docs/examples/boltzmann1d.rst
Normal file
60
docs/examples/boltzmann1d.rst
Normal file
@@ -0,0 +1,60 @@
|
||||
boltzmann1d
|
||||
===========
|
||||
|
||||
This example provides a one-dimensional Boltzmann wealth model (BWM)
|
||||
as an example of a simple application of the one-dimensional gridded
|
||||
system.
|
||||
|
||||
The BWM is a type of agent-based model used to study the distribution
|
||||
of wealth among individuals or agents within a population. The model
|
||||
is named after the physicist Ludwig Boltzmann, who first proposed
|
||||
a similar model to study the distribution of energy among particles
|
||||
in a gas.
|
||||
|
||||
In a BWM, agents are assigned a certain amount of wealth, and the
|
||||
model simulates their interactions over time. These interactions
|
||||
can include buying and selling goods and services, lending and
|
||||
borrowing money, and inheriting wealth from other agents.
|
||||
|
||||
The key feature of the BWM is that it incorporates a "wealth-exchange
|
||||
mechanism" which determines the probability of agents making a
|
||||
wealth exchange with each other. This mechanism is often based on
|
||||
the difference in wealth between agents, with wealthier agents more
|
||||
likely to make exchanges with other wealthy agents.
|
||||
|
||||
The model can be run for a specified number of time steps, and the
|
||||
resulting wealth distribution can be analyzed to study the emergence
|
||||
of wealth inequality and the factors that contribute to it. The
|
||||
model can also be used to study the effects of different policies
|
||||
or interventions on the wealth distribution.
|
||||
|
||||
The BWM has been used to study a variety of different economic
|
||||
systems, including capitalist, socialist, and feudal systems.
|
||||
However, it is important to note that like other agent-based models,
|
||||
the BWM is a simplified representation of the real world and may
|
||||
not capture all the nuances of the economic system being studied.
|
||||
|
||||
Overall, the BWM is a useful tool for studying the distribution of
|
||||
wealth and the emergence of wealth inequality in a population. It
|
||||
can provide insight into the factors that contribute to wealth
|
||||
inequality and the effects of different policies on the distribution
|
||||
of wealth.
|
||||
|
||||
.. list-table::
|
||||
:widths: 30 70
|
||||
:header-rows: 1
|
||||
|
||||
* - Option
|
||||
- Description
|
||||
* - -c *agent_count*
|
||||
- Set the number of agents
|
||||
* - -l *log_level_option*
|
||||
- Set the logging level
|
||||
* - -n *max_steps*
|
||||
- Set the number of steps to run the model
|
||||
* - -s *initial_seed*
|
||||
- Set the initial seed
|
||||
* - -x *x_size*
|
||||
- Set the number of columns
|
||||
|
||||
.. toctree::
|
||||
43
docs/examples/boltzmann2d.rst
Normal file
43
docs/examples/boltzmann2d.rst
Normal file
@@ -0,0 +1,43 @@
|
||||
boltzmann2d
|
||||
===========
|
||||
|
||||
This example provides a two-dimensional Boltzmann wealth model (BWM)
|
||||
as an example of a simple application of the two-dimensional gridded
|
||||
system.
|
||||
|
||||
The BWM is a type of agent-based model used to study the distribution
|
||||
of wealth among individuals within a population. The model simulates
|
||||
agents' interactions over time, such as buying and selling goods,
|
||||
lending and borrowing money, and inheriting wealth. The model is
|
||||
based on a "wealth-exchange mechanism" which determines the probability
|
||||
of agents making a wealth exchange with each other, it is often
|
||||
based on the difference in wealth between agents. The model can be
|
||||
run for a specified number of time steps, and the resulting wealth
|
||||
distribution can be analyzed to study the emergence of wealth
|
||||
inequality and the factors that contribute to it.
|
||||
|
||||
For more information on BWMs, please see the boltzmann1d_
|
||||
example documentation.
|
||||
|
||||
.. list-table::
|
||||
:widths: 30 70
|
||||
:header-rows: 1
|
||||
|
||||
* - Option
|
||||
- Description
|
||||
* - -c *agent_count*
|
||||
- Set the number of agents
|
||||
* - -l *log_level_option*
|
||||
- Set the logging level
|
||||
* - -n *max_steps*
|
||||
- Set the number of steps to run the model
|
||||
* - -s *initial_seed*
|
||||
- Set the initial seed
|
||||
* - -x *x_size*
|
||||
- Set the number of columns
|
||||
* - -y *y_size*
|
||||
- Set the number of rows
|
||||
|
||||
.. _boltzmann1d: boltzmann1d.html
|
||||
|
||||
.. toctree::
|
||||
21
docs/examples/index.rst
Normal file
21
docs/examples/index.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
Examples
|
||||
========
|
||||
|
||||
* bankreserves_
|
||||
* boltzmann1d_
|
||||
* boltzmann2d_
|
||||
* starter_
|
||||
|
||||
.. _bankreserves: bankreserves.html
|
||||
.. _boltzmann1d: boltzmann1d.html
|
||||
.. _boltzmann2d: boltzmann2d.html
|
||||
.. _starter: starter.html
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:maxdepth: 1
|
||||
|
||||
bankreserves
|
||||
boltzmann1d
|
||||
boltzmann2d
|
||||
starter
|
||||
24
docs/examples/starter.rst
Normal file
24
docs/examples/starter.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
starter
|
||||
=======
|
||||
|
||||
This example provides a starter scaffold for beginning a new
|
||||
agent-based model (ABM). The agents and models perform no real
|
||||
functions in the starter and is likely to be the most minimum
|
||||
functioning model.
|
||||
|
||||
.. list-table::
|
||||
:widths: 30 70
|
||||
:header-rows: 1
|
||||
|
||||
* - Option
|
||||
- Description
|
||||
* - -c *agent_count*
|
||||
- Set the number of agents
|
||||
* - -l *log_level_option*
|
||||
- Set the logging level
|
||||
* - -n *max_steps*
|
||||
- Set the number of steps to run the model
|
||||
* - -s *initial_seed*
|
||||
- Set the initial seed
|
||||
|
||||
.. toctree::
|
||||
@@ -1,11 +1,71 @@
|
||||
Docs
|
||||
====
|
||||
Introduction
|
||||
============
|
||||
|
||||
.. doxygennamespace:: kami
|
||||
:members:
|
||||
.. image:: https://github.com/JHUAPL/kami/actions/workflows/build-main.yml/badge.svg?branch=main
|
||||
:target: https://github.com/JHUAPL/kami/actions/workflows/build-main.yml
|
||||
:alt: Build Status (main)
|
||||
.. image:: https://github.com/JHUAPL/kami/actions/workflows/build-develop.yml/badge.svg?branch=develop
|
||||
:target: https://github.com/JHUAPL/kami/actions/workflows/build-develop.yml
|
||||
:alt: Build Status (develop)
|
||||
.. image:: https://readthedocs.org/projects/kami/badge/?version=main
|
||||
:target: https://kami.readthedocs.io/en/main/
|
||||
:alt: Documentation Status
|
||||
.. image:: https://img.shields.io/github/release/JHUAPL/kami.svg
|
||||
:target: https://github.com/JHUAPL/kami/releases
|
||||
:alt: Release Status
|
||||
.. image:: https://img.shields.io/github/license/JHUAPL/kami
|
||||
:alt: License Information
|
||||
.. image:: https://img.shields.io/badge/DOI-10.5281%2Fzenodo.6975259-success.svg
|
||||
:target: https://doi.org/10.5281/zenodo.6975259
|
||||
:alt: Package DOI
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
Kami is Agent-Based Modeling in Modern C++.
|
||||
|
||||
about
|
||||
api/library_root
|
||||
Overview
|
||||
========
|
||||
|
||||
Agent-based models (ABMs) are models for simulating the actions of
|
||||
individual actors within a provided environment to understand the
|
||||
behavior of the agents, most individually and collectively. ABMs
|
||||
are particularly suited for addressing problems governed by nonlinear
|
||||
processes or where there is a wide variety of potential responses
|
||||
an individual agent may provide depending on the environment and
|
||||
behavior of other agents. Because of this, ABMs have become powerful
|
||||
tools in both simulation and modeling, especially in public health
|
||||
and ecology, where they are also known as individual-based models.
|
||||
ABMs also provide support in economic, business, robotics, and many
|
||||
other fields.
|
||||
|
||||
Design Objectives
|
||||
-----------------
|
||||
|
||||
Kami provides agent-based modeling modern C++. The objectives in
|
||||
writing Kami are that it be lightweight, memory-efficient, and fast.
|
||||
It should be possible to develop a simple working model in under
|
||||
one hour of C++ development time. Accordingly, the platform is
|
||||
modeled on the Mesa_ library in Python, which itself was inspired
|
||||
by the MASON_ library in Java.
|
||||
|
||||
Many ABM platforms are designed around interaction and real time
|
||||
observation of the agent dynamics. Kami does not provide a
|
||||
visualization interface. Instead, Kami is meant to be used for
|
||||
ABMs requiring many runs with different starting conditions.
|
||||
Accordingly, Kami is single-threaded and multiple cores should be
|
||||
taken advantage of through multiple parallel runs of the supervising
|
||||
model.
|
||||
|
||||
.. _MASON: https://cs.gmu.edu/~eclab/projects/mason/
|
||||
.. _Mesa: https://mesa.readthedocs.io
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:maxdepth: 2
|
||||
|
||||
installation
|
||||
abm
|
||||
tutorial
|
||||
api/library_root
|
||||
examples/index
|
||||
changelog
|
||||
todo
|
||||
license
|
||||
40
docs/installation.md
Normal file
40
docs/installation.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Installation
|
||||
|
||||
## Requirements
|
||||
|
||||
The core of Kami, `libkami`, has no requirements beyond a modern C++ compiler and `neargye-semver/0.3.0`. However, both the examples provided and
|
||||
the unit tests provided rely on three additional C++ packages. The full list is:
|
||||
|
||||
* cli11/1.9.1
|
||||
* gtest/cci.20210126
|
||||
* neargye-semver/0.3.0"
|
||||
* spdlog/1.8.5
|
||||
* fmt/7.1.3
|
||||
|
||||
[`Google Test`](https://github.com/google/googletest) provides a
|
||||
unit testing framework. [`CLI11`](https://cliutils.github.io/CLI11/)
|
||||
provides a command line interface for each of the utilities that
|
||||
makeup the examples. [`spdlog`](https://github.com/gabime/spdlog)
|
||||
provides a uniform output interface. Coupled with a command line
|
||||
option to set the output level, `spdlog` allows the unit tests and
|
||||
example programs to provide variable output levels depending on the
|
||||
users needs. Finally, [`fmt`](https://fmt.dev/) is required by
|
||||
`spdlog` for simple and easy string formatting.
|
||||
|
||||
## Compiling
|
||||
|
||||
To compile and test locally in kami/build:
|
||||
|
||||
git clone https://github.com/k3jph/kami.git
|
||||
cd kami
|
||||
conan install -if build .
|
||||
cmake -B build -DBUILD_SHARED_LIBS:BOOL=FALSE
|
||||
cmake --build build
|
||||
cmake --build build --target test
|
||||
|
||||
## Conan Installation (Local)
|
||||
|
||||
To install via [Conan](https://conan.io/):
|
||||
|
||||
conan create . kami/develop
|
||||
|
||||
27
docs/license.rst
Normal file
27
docs/license.rst
Normal file
@@ -0,0 +1,27 @@
|
||||
License
|
||||
=======
|
||||
|
||||
Copyright (c) 2020-2023 The Johns Hopkins University Applied Physics
|
||||
Laboratory LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
.. toctree::
|
||||
@@ -1 +1,8 @@
|
||||
breathe
|
||||
breathe==4.34.0
|
||||
Sphinx==4.5.0
|
||||
exhale==0.3.6
|
||||
documenteer==0.7.0
|
||||
myst-parser==0.18.1
|
||||
sphinx-bootstrap-theme==0.8.1
|
||||
sphinx-rtd-theme==1.1.1
|
||||
releases==1.6.3
|
||||
|
||||
23
docs/todo.rst
Normal file
23
docs/todo.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
To Do List
|
||||
==========
|
||||
|
||||
Must Dos
|
||||
--------
|
||||
The list below is a list of things considered necessary before
|
||||
a 1.0 release. This list is *not* static.
|
||||
|
||||
- Network domain
|
||||
- Hexgrid domain
|
||||
- Continuous grid domain
|
||||
|
||||
Wishlist
|
||||
--------
|
||||
The list below is a list of things considered nice to have at
|
||||
any point.
|
||||
|
||||
- Revise unit tests to take advantage of fixtures
|
||||
- Network Boltzmann model example
|
||||
- Additional examples as appropriate
|
||||
- Globe domain, on sphere, with latitude and longitude
|
||||
|
||||
.. toctree::
|
||||
108
docs/tutorial.rst
Normal file
108
docs/tutorial.rst
Normal file
@@ -0,0 +1,108 @@
|
||||
Tutorial
|
||||
========
|
||||
|
||||
Kami's interface is heavily influenced by Mesa_'s interface. However,
|
||||
by being written in C++, Kami runs substantially faster. This
|
||||
allows for faster runs and more runs within a fixed amount of time.
|
||||
The advantage here is that an agent-based model (ABM) built on the
|
||||
Kami platform is better suited for statistical and Monte Carlo
|
||||
approaches to modelling.
|
||||
|
||||
Model Form
|
||||
----------
|
||||
|
||||
Kami-based models have five key components:
|
||||
|
||||
1. Agents, which are objects representing the actors within the model
|
||||
2. Populations, which are collections of Agents
|
||||
3. Domains, which provide a representation of "physical" space the Agent inhabits
|
||||
4. Schedulers, which provide a representation of "time" within the model
|
||||
5. Model, which are objects connecting Populations, Domains, and Schedulers
|
||||
|
||||
In general, a model should have one scheduler, one domain, and some
|
||||
number of agents. However, it would not be impossible to have more
|
||||
than one scheduler or more than one domain. Because this is
|
||||
implemented in C++, your agents should subclass Agent and your model
|
||||
should subclass model. The schedulers and domains are sufficient
|
||||
as is for their purposes though custom schedulers and domains are
|
||||
not unreasonable.
|
||||
|
||||
A Minimal ABM
|
||||
-------------
|
||||
|
||||
The minimal ABM starts with the simplest possible agent. Here, we
|
||||
create a class called ``MinimalAgent``:
|
||||
|
||||
.. code-block:: c++
|
||||
:linenos:
|
||||
|
||||
class MinimalAgent : public kami::Agent {
|
||||
public:
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override {
|
||||
return this->get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
An ``Agent``, and its subclasses, will automatically inherit an ``AgentID``,
|
||||
which is the unique identifier for the session. The only explicit
|
||||
requirement on the ``Agent`` subclass is a `step()` method that accepts
|
||||
a ``shared_ptr`` to a ``Model`` and it must return the ``Agent``'s ``AgentID``.
|
||||
Obviously, an ``Agent`` should do something useful before returning.
|
||||
|
||||
The second component is ``MinimalModel:``
|
||||
|
||||
.. code-block:: c++
|
||||
:linenos:
|
||||
|
||||
class MinimalModel: public kami::Model {
|
||||
public:
|
||||
MinimalModel() {
|
||||
auto sched = std::make_shared<kami::SequentialScheduler>();
|
||||
set_scheduler(sched);
|
||||
|
||||
auto pop = std::make_shared<kami::Population>();
|
||||
set_population(pop);
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
auto new_agent = std::make_shared<MinimalAgent>();
|
||||
pop->add_agent(new_agent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
The ``MinimalModel`` performs some important tasks that important to do
|
||||
during the setup or soon thereafter. In the constructor, first, a
|
||||
scheduler is created. The ``SequentialScheduler`` is the simplest
|
||||
scheduler and has no configuration needed. Using `set_scheduler()`,
|
||||
part of the Model class, the scheduler is associated with this
|
||||
model. Second, a `Population` is created and associated with this
|
||||
model with the `set_population()` method.
|
||||
|
||||
After this, the constructor initializes 10 ``MinimalAgents`` and adds
|
||||
them to the population.
|
||||
|
||||
.. code-block:: c++
|
||||
:linenos:
|
||||
|
||||
int main() {
|
||||
auto model = std::make_shared<MinimalModel>();
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
model->step();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
The last part is our `main()` function. It creates the `MinimalModel`
|
||||
then executes its `step()` method 10 times. The `step()` method, by
|
||||
default, calls the `step()` method of the scheduler. In the case of
|
||||
the ``SequentialScheduler``, it loops over all the ``Agent`` instances in the
|
||||
``Population`` and executes the associated `step()` method of each ``Agent``.
|
||||
|
||||
That is it. It is the simplest minimal model that can be created
|
||||
using the Kami platform. However, for a basis, it is likely better
|
||||
to use the starter model, included in the examples directory.
|
||||
|
||||
.. _Mesa: https://mesa.readthedocs.io
|
||||
|
||||
.. toctree::
|
||||
@@ -3,5 +3,5 @@
|
||||
Each folder in here is automatically traversed by the root level cmake list file.
|
||||
|
||||
1. Copy one of the existing folders to a new name.
|
||||
2. The name of the folder will be the name of the library
|
||||
2. The name of the folder will be the name of the example
|
||||
3. Change the source file list.
|
||||
|
||||
22
examples/bankreserves/CMakeLists.txt
Normal file
22
examples/bankreserves/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
####
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "bankreserves")
|
||||
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
file(GLOB EXAMPLE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cc")
|
||||
|
||||
create_executable(
|
||||
NAME ${EXAMPLE_NAME}
|
||||
SOURCES ${EXAMPLE_SOURCES}
|
||||
PUBLIC_DEFINITIONS USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS ${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS fmt spdlog::spdlog kami::libkami
|
||||
)
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${VERSION_STRING})
|
||||
106
examples/bankreserves/bankreserves.cc
Normal file
106
examples/bankreserves/bankreserves.cc
Normal file
@@ -0,0 +1,106 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bankreserves.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/stopwatch.h>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/multigrid2d.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/model.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/random.h>
|
||||
#include <kami/reporter.h>
|
||||
|
||||
std::shared_ptr<spdlog::logger> console = nullptr;
|
||||
std::shared_ptr<std::mt19937> rng = nullptr;
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "EmptyDeclOrStmt"
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char** argv
|
||||
) {
|
||||
std::string ident = "bankreserves";
|
||||
std::string log_level_option = "info";
|
||||
std::string output_file_name = ident + ".json";
|
||||
CLI::App app{ident};
|
||||
unsigned int
|
||||
initial_seed = kami::Constants::JENNYS_NUMBER,
|
||||
max_steps = 100,
|
||||
x_size = 20,
|
||||
y_size = 20,
|
||||
agent_count = x_size * y_size,
|
||||
max_initial_wealth = 10;
|
||||
|
||||
// This exercise is really stupid.
|
||||
auto levels_list = std::make_unique<std::list<std::string>>();
|
||||
for (auto& level_name : SPDLOG_LEVEL_NAMES)
|
||||
levels_list->push_back(std::string(level_name.data(), level_name.size()));
|
||||
|
||||
app.add_option("-c", agent_count, "Set the number of agents")->check(CLI::PositiveNumber);
|
||||
app.add_option("-f", output_file_name, "Set the JSON report file")->check(CLI::ExistingPath);
|
||||
app.add_option("-l", log_level_option, "Set the logging level")->check(
|
||||
CLI::IsMember(levels_list.get(), CLI::ignore_case));
|
||||
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);
|
||||
app.add_option("-w", max_initial_wealth, "Set the maximum initial agent wealth")->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.to_string(), log_level_option);
|
||||
|
||||
console->info("Starting Bank Reserves Model with {} agents for {} steps", agent_count, max_steps);
|
||||
auto model = std::make_shared<BankReservesModel>(agent_count, x_size, y_size, initial_seed, max_initial_wealth);
|
||||
spdlog::stopwatch sw;
|
||||
for (int i = 0; i < max_steps; i++)
|
||||
model->step();
|
||||
console->info("Bank Reserves Model simulation complete, requiring {} seconds", sw);
|
||||
|
||||
auto rpt = model->report();
|
||||
std::ofstream output_file(output_file_name);
|
||||
output_file << *rpt;
|
||||
console->info("JSON data report written to {}", output_file_name);
|
||||
console->trace("Done.");
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
195
examples/bankreserves/bankreserves.h
Normal file
195
examples/bankreserves/bankreserves.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef BANKRESERVES_H
|
||||
//! @cond SuppressGuard
|
||||
#define BANKRESERVES_H
|
||||
//! @endcond
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/stopwatch.h>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/multigrid2d.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/random.h>
|
||||
#include <kami/reporter.h>
|
||||
|
||||
extern std::shared_ptr<spdlog::logger> console;
|
||||
extern std::shared_ptr<std::mt19937> rng;
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<kami::AgentID>
|
||||
: fmt::formatter<std::string> {
|
||||
static auto format(
|
||||
kami::AgentID agent_id,
|
||||
format_context& ctx
|
||||
) {
|
||||
return format_to(ctx.out(), "{}", agent_id.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<kami::GridCoord2D>
|
||||
: fmt::formatter<std::string> {
|
||||
static auto format(
|
||||
const kami::GridCoord2D& coord,
|
||||
format_context& ctx
|
||||
) {
|
||||
return format_to(ctx.out(), "{}", coord.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A starter agent for a starter model
|
||||
*/
|
||||
class BankAgent
|
||||
: public kami::ReporterAgent {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
explicit BankAgent(int reserve_percent)
|
||||
:_reserve_percent(reserve_percent) {
|
||||
};
|
||||
|
||||
inline std::unique_ptr<nlohmann::json> collect() override {
|
||||
auto ret = std::make_unique<nlohmann::json>();
|
||||
|
||||
(*ret)["reserves"] = _reserves;
|
||||
(*ret)["available"] = _available_to_loan;
|
||||
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
inline kami::AgentID step(std::shared_ptr<kami::ReporterModel> model) override {
|
||||
return get_agent_id();
|
||||
};
|
||||
|
||||
int bank_balance() {
|
||||
_reserves = (_reserve_percent / 100) * _deposits;
|
||||
return _available_to_loan = _deposits - (_reserves + _bank_loans);
|
||||
}
|
||||
|
||||
private:
|
||||
double _bank_loans = 0;
|
||||
double _reserve_percent = 0;
|
||||
double _deposits = 0;
|
||||
double _reserves = (_reserve_percent / 100) * _deposits;
|
||||
double _available_to_loan = 0;
|
||||
|
||||
friend class PersonAgent;
|
||||
};
|
||||
|
||||
class PersonAgent
|
||||
: public kami::ReporterAgent {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
explicit PersonAgent(
|
||||
int wallet,
|
||||
std::shared_ptr<BankAgent>& bank
|
||||
)
|
||||
:
|
||||
_wallet(wallet), _bank(bank) {
|
||||
};
|
||||
|
||||
inline std::unique_ptr<nlohmann::json> collect() override {
|
||||
auto ret = std::make_unique<nlohmann::json>();
|
||||
|
||||
(*ret)["savings"] = _savings;
|
||||
(*ret)["loans"] = _loans;
|
||||
(*ret)["wallet"] = _wallet;
|
||||
(*ret)["wealth"] = _wealth;
|
||||
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a single time-step for the agent
|
||||
*/
|
||||
kami::AgentID step(std::shared_ptr<kami::ReporterModel> model) override;
|
||||
|
||||
private:
|
||||
int _step_counter = 0;
|
||||
double _savings = 0;
|
||||
double _loans = 0;
|
||||
double _wallet = 0;
|
||||
double _wealth = 0;
|
||||
std::shared_ptr<BankAgent> _bank;
|
||||
|
||||
/**
|
||||
* Move the agent to a random location on the world
|
||||
*/
|
||||
std::optional<kami::GridCoord2D> move_agent(std::shared_ptr<kami::ReporterModel>& model);
|
||||
|
||||
std::optional<kami::AgentID> do_business(std::shared_ptr<kami::ReporterModel>& model);
|
||||
|
||||
std::optional<int> balance_books(std::shared_ptr<kami::ReporterModel>& model);
|
||||
|
||||
kami::AgentID deposit_to_savings(double amount);
|
||||
|
||||
kami::AgentID withdraw_from_savings(double amount);
|
||||
|
||||
kami::AgentID repay_a_loan(double amount);
|
||||
|
||||
kami::AgentID take_out_loan(double amount);
|
||||
};
|
||||
|
||||
/**
|
||||
* The one-dimensional Boltzmann wealth model
|
||||
*/
|
||||
class BankReservesModel
|
||||
: public kami::ReporterModel {
|
||||
public:
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
explicit BankReservesModel(
|
||||
unsigned int agent_count,
|
||||
unsigned int x_size,
|
||||
unsigned int y_size,
|
||||
unsigned int initial_seed,
|
||||
unsigned int max_initial_wealth
|
||||
);
|
||||
|
||||
inline std::unique_ptr<nlohmann::json> collect() override {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BANKRESERVES_H
|
||||
76
examples/bankreserves/brmodel.cc
Normal file
76
examples/bankreserves/brmodel.cc
Normal file
@@ -0,0 +1,76 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bankreserves.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/stopwatch.h>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/multigrid2d.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/random.h>
|
||||
#include <kami/reporter.h>
|
||||
|
||||
BankReservesModel::BankReservesModel(
|
||||
unsigned int agent_count,
|
||||
unsigned int x_size,
|
||||
unsigned int y_size,
|
||||
unsigned int initial_seed,
|
||||
unsigned int max_initial_wealth
|
||||
) {
|
||||
rng = std::make_shared<std::mt19937>();
|
||||
rng->seed(initial_seed);
|
||||
|
||||
auto domain = std::make_shared<kami::MultiGrid2D>(x_size, y_size, true, true);
|
||||
auto sched = std::make_shared<kami::RandomScheduler>(rng);
|
||||
auto pop = std::make_shared<kami::Population>();
|
||||
|
||||
std::static_pointer_cast<void>(set_scheduler(sched));
|
||||
std::static_pointer_cast<void>(set_domain(domain));
|
||||
std::static_pointer_cast<void>(set_population(pop));
|
||||
|
||||
console->debug("Scheduler initiated with seed {}", initial_seed);
|
||||
auto bank_agent = std::make_shared<BankAgent>(10);
|
||||
pop->add_agent(bank_agent);
|
||||
|
||||
_step_count = 0;
|
||||
|
||||
std::uniform_int_distribution<int> dist_x(0, (int) x_size - 1);
|
||||
std::uniform_int_distribution<int> dist_y(0, (int) y_size - 1);
|
||||
std::uniform_int_distribution<unsigned int> dist(1, max_initial_wealth);
|
||||
|
||||
for (auto i = 0; i < agent_count; i++) {
|
||||
auto wallet = dist(*rng);
|
||||
auto new_agent = std::make_shared<PersonAgent>(10, bank_agent);
|
||||
|
||||
pop->add_agent(new_agent);
|
||||
domain->add_agent(new_agent->get_agent_id(), kami::GridCoord2D(dist_x(*rng), dist_x(*rng)));
|
||||
console->trace("Initialized agent with AgentID {} with wallet {}", new_agent->get_agent_id(), wallet);
|
||||
}
|
||||
}
|
||||
183
examples/bankreserves/person.cc
Normal file
183
examples/bankreserves/person.cc
Normal file
@@ -0,0 +1,183 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bankreserves.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/stopwatch.h>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/multigrid2d.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/random.h>
|
||||
#include <kami/reporter.h>
|
||||
|
||||
kami::AgentID PersonAgent::step(std::shared_ptr<kami::ReporterModel> model) {
|
||||
console->trace("step() called for agent {}", get_agent_id());
|
||||
move_agent(model);
|
||||
do_business(model);
|
||||
balance_books(model);
|
||||
_bank->bank_balance();
|
||||
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
std::optional<kami::GridCoord2D> PersonAgent::move_agent(std::shared_ptr<kami::ReporterModel>& model) {
|
||||
console->trace("move_agent() called for agent {}", get_agent_id());
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
auto domain = model->get_domain();
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid2D>(domain);
|
||||
|
||||
auto move_list = world->get_neighborhood(agent_id, false, kami::GridNeighborhoodType::Moore);
|
||||
std::uniform_int_distribution<int> dist(0, (int) move_list->size() - 1);
|
||||
auto new_location = *std::next(move_list->begin(), dist(*rng));
|
||||
|
||||
console->trace("Moving Agent {} to location {}", agent_id, new_location);
|
||||
world->move_agent(agent_id, new_location);
|
||||
|
||||
return new_location;
|
||||
}
|
||||
|
||||
std::optional<kami::AgentID> PersonAgent::do_business(std::shared_ptr<kami::ReporterModel>& model) {
|
||||
console->trace("do_business() called for agent {}", get_agent_id());
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
if (!(_savings > 0 | _wallet > 0 | _bank->_available_to_loan > 0))
|
||||
return agent_id;
|
||||
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid2D>(model->get_domain());
|
||||
auto population = model->get_population();
|
||||
|
||||
auto location = world->get_location_by_agent(agent_id);
|
||||
auto cell_mates_opt = world->get_location_contents(location);
|
||||
|
||||
if (!cell_mates_opt)
|
||||
return std::nullopt;
|
||||
|
||||
// Note, here we reverse the logic from that used in the Mesa
|
||||
// implementation. We prefer the guard clause to the nested
|
||||
// if statements. See Fowler.
|
||||
auto cell_mates = cell_mates_opt;
|
||||
if (cell_mates->size() < 2)
|
||||
return std::nullopt;
|
||||
|
||||
auto customer_id = agent_id;
|
||||
std::uniform_int_distribution<int> dist(0, (int) cell_mates->size() - 1);
|
||||
do { // There aren't enough do loops, ya know?
|
||||
customer_id = *std::next(cell_mates->begin(), dist(*rng));
|
||||
} while (customer_id == agent_id);
|
||||
|
||||
std::bernoulli_distribution coin_flip(0.5);
|
||||
if (coin_flip(*rng))
|
||||
return std::nullopt;
|
||||
|
||||
// If true, trade_amount = 5, if false, trade_amount = 2
|
||||
// Dropping the conditional should make this faster, but
|
||||
// really, this is just more elegant.
|
||||
auto trade_amount = (int) std::round(coin_flip(*rng)) * 3 + 2;
|
||||
|
||||
auto customer = std::static_pointer_cast<PersonAgent>(population->get_agent_by_id(customer_id));
|
||||
console->debug("Agent {} trading amount {} with agent {}", agent_id, trade_amount, customer_id);
|
||||
customer->_wallet += trade_amount;
|
||||
_wallet -= trade_amount;
|
||||
|
||||
return customer_id;
|
||||
}
|
||||
|
||||
std::optional<int> PersonAgent::balance_books(std::shared_ptr<kami::ReporterModel>& model) {
|
||||
console->debug(
|
||||
"balance_books() called for agent {} with wallet {}, savings {}, loans {}", get_agent_id(), _wallet,
|
||||
_savings, _loans);
|
||||
|
||||
if (_wallet < 0) {
|
||||
if (_savings >= -_wallet) {
|
||||
withdraw_from_savings(-_wallet);
|
||||
} else {
|
||||
if (_savings > 0) {
|
||||
withdraw_from_savings(_savings);
|
||||
}
|
||||
auto temp_loan = _bank->_available_to_loan;
|
||||
if (temp_loan >= -_wallet) {
|
||||
take_out_loan(-_wallet);
|
||||
} else {
|
||||
take_out_loan(temp_loan);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deposit_to_savings(_wallet);
|
||||
}
|
||||
|
||||
if (_loans > 0 & _savings > 0) {
|
||||
if (_savings > _loans) {
|
||||
withdraw_from_savings(_loans);
|
||||
repay_a_loan(_loans);
|
||||
} else {
|
||||
withdraw_from_savings(_savings);
|
||||
repay_a_loan(_wallet);
|
||||
}
|
||||
}
|
||||
|
||||
_wealth = _savings - _loans;
|
||||
console->debug("balance_books() exiting for agent {}, and wealth {}", get_agent_id(), _wealth);
|
||||
return _wealth;
|
||||
}
|
||||
|
||||
kami::AgentID PersonAgent::deposit_to_savings(double amount) {
|
||||
console->debug("deposit_to_savings() called for agent {}, and amount {}", get_agent_id(), amount);
|
||||
_wallet -= amount;
|
||||
_savings += amount;
|
||||
_bank->_deposits += amount;
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
kami::AgentID PersonAgent::withdraw_from_savings(double amount) {
|
||||
console->debug("withdraw_from_savings() called for agent {}, and amount {}", get_agent_id(), amount);
|
||||
_wallet += amount;
|
||||
_savings -= amount;
|
||||
_bank->_deposits -= amount;
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
kami::AgentID PersonAgent::repay_a_loan(double amount) {
|
||||
console->debug("repay_a_loan() called for agent {}, and amount {}", get_agent_id(), amount);
|
||||
_loans -= amount;
|
||||
_wallet -= amount;
|
||||
_bank->_available_to_loan += amount;
|
||||
_bank->_bank_loans -= amount;
|
||||
return get_agent_id();
|
||||
}
|
||||
|
||||
kami::AgentID PersonAgent::take_out_loan(double amount) {
|
||||
console->debug("take_out_loan() called for agent {}, and amount {}", get_agent_id(), amount);
|
||||
_loans += amount;
|
||||
_wallet += amount;
|
||||
_bank->_available_to_loan -= amount;
|
||||
_bank->_bank_loans += amount;
|
||||
return get_agent_id();
|
||||
}
|
||||
@@ -2,23 +2,21 @@
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "boltzmann1d")
|
||||
|
||||
project(${EXAMPLE_NAME}
|
||||
LANGUAGES CXX)
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
create_executable( NAME ${EXAMPLE_NAME}
|
||||
SOURCES
|
||||
boltzmann1d.cpp
|
||||
PUBLIC_DEFINITIONS
|
||||
USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS
|
||||
DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS
|
||||
kami
|
||||
)
|
||||
file(GLOB EXAMPLE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cc")
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${KAMI_VERSION_STRING})
|
||||
create_executable(
|
||||
NAME ${EXAMPLE_NAME}
|
||||
SOURCES ${EXAMPLE_SOURCES}
|
||||
PUBLIC_DEFINITIONS USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS ${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS fmt spdlog::spdlog kami::libkami
|
||||
)
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${VERSION_STRING})
|
||||
|
||||
223
examples/boltzmann1d/boltzmann1d.cc
Normal file
223
examples/boltzmann1d/boltzmann1d.cc
Normal file
@@ -0,0 +1,223 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "boltzmann1d.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/stopwatch.h>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/multigrid1d.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/random.h>
|
||||
|
||||
std::shared_ptr<spdlog::logger> console = nullptr;
|
||||
std::shared_ptr<std::mt19937> rng = nullptr;
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<kami::AgentID>
|
||||
: fmt::formatter<std::string> {
|
||||
static auto format(
|
||||
kami::AgentID agent_id,
|
||||
format_context& ctx
|
||||
) {
|
||||
return format_to(ctx.out(), "{}", agent_id.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<kami::GridCoord1D>
|
||||
: fmt::formatter<std::string> {
|
||||
static auto format(
|
||||
const kami::GridCoord1D& coord,
|
||||
format_context& ctx
|
||||
) {
|
||||
return format_to(ctx.out(), "{}", coord.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
MoneyAgent1D::~MoneyAgent1D() {
|
||||
console->trace("Deconstructing Agent {} with final wealth {}", get_agent_id(), _agent_wealth);
|
||||
}
|
||||
|
||||
kami::AgentID MoneyAgent1D::step(std::shared_ptr<kami::Model> model) {
|
||||
this->_step_counter++;
|
||||
|
||||
console->trace("Agent {} is moving", this->get_agent_id());
|
||||
this->move_agent(model);
|
||||
if (_agent_wealth > 0)
|
||||
this->give_money(model);
|
||||
|
||||
return this->get_agent_id();
|
||||
}
|
||||
|
||||
std::optional<kami::GridCoord1D> MoneyAgent1D::move_agent(std::shared_ptr<kami::Model> model) {
|
||||
console->trace("Entering move_agent");
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
auto domain = model->get_domain();
|
||||
if (!domain)
|
||||
throw (std::domain_error("model is missing domain"));
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid1D>(domain);
|
||||
|
||||
auto move_list_opt = world->get_neighborhood(agent_id, false);
|
||||
if (!move_list_opt)
|
||||
return std::nullopt;
|
||||
auto move_list = move_list_opt;
|
||||
std::uniform_int_distribution<int> dist(0, (int) move_list->size() - 1);
|
||||
auto new_location = *std::next(move_list->begin(), dist(*rng));
|
||||
|
||||
console->trace("Moving Agent {} to location {}", agent_id, new_location);
|
||||
world->move_agent(agent_id, new_location);
|
||||
console->trace("Exiting move_agent");
|
||||
|
||||
return new_location;
|
||||
}
|
||||
|
||||
std::optional<kami::AgentID> MoneyAgent1D::give_money(std::shared_ptr<kami::Model> model) {
|
||||
console->trace("Entering give_money");
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
auto domain = model->get_domain();
|
||||
if (!domain)
|
||||
throw (std::domain_error("model is missing domain"));
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid1D>(domain);
|
||||
|
||||
auto agents = model->get_population();
|
||||
if (!agents)
|
||||
throw (std::domain_error("model is missing population"));
|
||||
auto population = std::static_pointer_cast<kami::Population>(agents);
|
||||
|
||||
auto location = world->get_location_by_agent(agent_id);
|
||||
auto cell_mates_opt = world->get_location_contents(location);
|
||||
|
||||
if (!cell_mates_opt)
|
||||
return std::nullopt;
|
||||
|
||||
auto cell_mates = cell_mates_opt;
|
||||
if (cell_mates->size() < 2)
|
||||
return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int) cell_mates->size() - 1);
|
||||
auto other_agent_id = *std::next(cell_mates->begin(), dist(*rng));
|
||||
auto other_agent = std::static_pointer_cast<MoneyAgent1D>(population->get_agent_by_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;
|
||||
|
||||
console->trace("Exiting move_agent");
|
||||
return other_agent_id;
|
||||
}
|
||||
|
||||
BoltzmannWealthModel1D::BoltzmannWealthModel1D(
|
||||
unsigned int number_agents,
|
||||
unsigned int length_x,
|
||||
unsigned int new_seed
|
||||
) {
|
||||
rng = std::make_shared<std::mt19937>();
|
||||
rng->seed(new_seed);
|
||||
|
||||
auto domain = std::make_shared<kami::MultiGrid1D>(length_x, true);
|
||||
auto scheduler = std::make_shared<kami::RandomScheduler>(rng);
|
||||
auto population = std::make_shared<kami::Population>();
|
||||
|
||||
this->set_domain(domain);
|
||||
this->set_scheduler(scheduler);
|
||||
this->set_population(population);
|
||||
|
||||
console->debug("Scheduler initiated with seed {}", new_seed);
|
||||
|
||||
_step_count = 0;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int) length_x - 1);
|
||||
|
||||
for (unsigned int i = 0; i < number_agents; i++) {
|
||||
auto new_agent = std::make_shared<MoneyAgent1D>();
|
||||
|
||||
console->trace("Initializing agent with AgentID {}", new_agent->get_agent_id());
|
||||
population->add_agent(new_agent);
|
||||
domain->add_agent(new_agent->get_agent_id(), kami::GridCoord1D(dist(*rng)));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> BoltzmannWealthModel1D::step() {
|
||||
console->trace("Executing model step {}", ++_step_count);
|
||||
_sched->step(shared_from_this());
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "EmptyDeclOrStmt"
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char** argv
|
||||
) {
|
||||
std::string ident = "boltzmann1d";
|
||||
std::string log_level_option = "info";
|
||||
CLI::App app{ident};
|
||||
unsigned int x_size = 16, agent_count = x_size, max_steps = 100, initial_seed = 42;
|
||||
|
||||
// This exercise is really stupid.
|
||||
auto levels_list = std::make_unique<std::list<std::string>>();
|
||||
for (auto& level_name : SPDLOG_LEVEL_NAMES)
|
||||
levels_list->push_back(std::string(level_name.data(), level_name.size()));
|
||||
|
||||
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(levels_list.get(), CLI::ignore_case));
|
||||
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.to_string(), log_level_option);
|
||||
console->info(
|
||||
"Starting Boltzmann Wealth Model with {} agents on a {}-unit grid for {} steps", agent_count, x_size,
|
||||
max_steps);
|
||||
|
||||
spdlog::stopwatch sw;
|
||||
|
||||
auto model = std::make_shared<BoltzmannWealthModel1D>(agent_count, x_size, initial_seed);
|
||||
for (int i = 0; i < max_steps; i++)
|
||||
model->step();
|
||||
|
||||
console->info("Boltzmann Wealth Model simulation complete, requiring {} seconds", sw);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
@@ -1,134 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#include "boltzmann1d.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/kami.hpp>
|
||||
#include <kami/multigrid1d.hpp>
|
||||
#include <map>
|
||||
|
||||
kami::MultiGrid1D *MoneyAgent::world = nullptr;
|
||||
BoltzmannWealthModel *MoneyAgent::model = nullptr;
|
||||
|
||||
MoneyAgent::MoneyAgent() {
|
||||
stepCounter = 0;
|
||||
agentWealth = 1;
|
||||
}
|
||||
|
||||
void MoneyAgent::step() {
|
||||
stepCounter++;
|
||||
|
||||
moveAgent();
|
||||
if (agentWealth > 0)
|
||||
giveMoney();
|
||||
}
|
||||
|
||||
void MoneyAgent::setWorld(kami::MultiGrid1D *w) {
|
||||
world = w;
|
||||
}
|
||||
|
||||
void MoneyAgent::setModel(class BoltzmannWealthModel *m) {
|
||||
model = m;
|
||||
}
|
||||
|
||||
void MoneyAgent::moveAgent() {
|
||||
auto agentID = this->getAgentID();
|
||||
auto moveList = world->getNeighborhood(agentID, false);
|
||||
auto newLocation = moveList[static_cast<unsigned int>(rand()) % moveList.size()];
|
||||
|
||||
world->moveAgent(agentID, newLocation);
|
||||
}
|
||||
|
||||
int MoneyAgent::getWealth() {
|
||||
return agentWealth;
|
||||
}
|
||||
|
||||
void MoneyAgent::setWealth(int newWealth) {
|
||||
agentWealth = newWealth;
|
||||
}
|
||||
|
||||
void MoneyAgent::giveMoney() {
|
||||
kami::AgentID agentID = getAgentID();
|
||||
kami::GridCoord1D location = world->getLocationByAgent(agentID);
|
||||
std::vector<kami::AgentID> *cellMates = world->getCellContents(location);
|
||||
|
||||
if (cellMates->size() > 1) {
|
||||
kami::AgentID otherAgentID = cellMates->at(static_cast<unsigned int>(rand()) % cellMates->size());
|
||||
auto otherAgent = model->getAgentByID(otherAgentID);
|
||||
|
||||
otherAgent->agentWealth += 1;
|
||||
agentWealth -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void MoneyAgent::prinfo(void) const {
|
||||
kami::AgentID agentID = getAgentID();
|
||||
kami::GridCoord1D location = world->getLocationByAgent(agentID);
|
||||
|
||||
std::cout << " agent: " << agentID << " step: " << stepCounter << " wealth: " << agentWealth << " location: " << location << std::endl;
|
||||
}
|
||||
|
||||
BoltzmannWealthModel::BoltzmannWealthModel(unsigned int numberAgents, unsigned int lengthX) {
|
||||
world = new kami::MultiGrid1D(lengthX, 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(),
|
||||
kami::GridCoord1D(rand() % static_cast<int>(lengthX)));
|
||||
}
|
||||
}
|
||||
|
||||
BoltzmannWealthModel::~BoltzmannWealthModel() {
|
||||
for (auto agentPair = agentList.begin(); agentPair != agentList.end(); agentPair++) {
|
||||
delete agentPair->second;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
BoltzmannWealthModel model(16, 16);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
model.step();
|
||||
}
|
||||
|
||||
model.prinfo();
|
||||
}
|
||||
113
examples/boltzmann1d/boltzmann1d.h
Normal file
113
examples/boltzmann1d/boltzmann1d.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef BOLTZMANN1D_H
|
||||
//! @cond SuppressGuard
|
||||
#define BOLTZMANN1D_H
|
||||
//! @endcond
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/multigrid1d.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/random.h>
|
||||
|
||||
|
||||
/**
|
||||
* A sample agent for a one-dimensional Boltzmann wealth model
|
||||
*/
|
||||
class MoneyAgent1D
|
||||
: public kami::Agent {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create the agent
|
||||
*/
|
||||
MoneyAgent1D()
|
||||
:_step_counter(0), _agent_wealth(1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deconstruct the agent
|
||||
*/
|
||||
~MoneyAgent1D();
|
||||
|
||||
/**
|
||||
* Execute a single time-step for the agent
|
||||
*/
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override;
|
||||
|
||||
/**
|
||||
* Move the agent to a random location on the world
|
||||
*/
|
||||
std::optional<kami::GridCoord1D> move_agent(std::shared_ptr<kami::Model> model);
|
||||
|
||||
/**
|
||||
* Give money to a random agent
|
||||
*/
|
||||
std::optional<kami::AgentID> give_money(std::shared_ptr<kami::Model> model);
|
||||
|
||||
private:
|
||||
int _step_counter;
|
||||
int _agent_wealth;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The one-dimensional Boltzmann wealth model
|
||||
*/
|
||||
class BoltzmannWealthModel1D
|
||||
: public kami::Model {
|
||||
|
||||
public:
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
explicit BoltzmannWealthModel1D(
|
||||
unsigned int number_agents = 10,
|
||||
unsigned int length_x = 10,
|
||||
unsigned int new_seed = 42
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute a single time-step for the model.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> step() final;
|
||||
|
||||
private:
|
||||
unsigned int _step_count;
|
||||
};
|
||||
|
||||
#endif // BOLTZMANN1D_H
|
||||
@@ -1,58 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef BOLTZMAN1D_HPP
|
||||
#define BOLTZMAN1D_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <kami/multigrid1d.hpp>
|
||||
#include <kami/random.hpp>
|
||||
#include <map>
|
||||
|
||||
class MoneyAgent : public kami::Agent {
|
||||
public:
|
||||
MoneyAgent();
|
||||
|
||||
void step();
|
||||
|
||||
static void setWorld(kami::MultiGrid1D *w);
|
||||
static void setModel(class BoltzmannWealthModel *m);
|
||||
|
||||
void moveAgent();
|
||||
|
||||
int getWealth();
|
||||
void setWealth(int newWealth);
|
||||
void giveMoney();
|
||||
|
||||
void prinfo(void) const;
|
||||
|
||||
private:
|
||||
static kami::MultiGrid1D *world;
|
||||
static BoltzmannWealthModel *model;
|
||||
int stepCounter;
|
||||
int agentWealth;
|
||||
};
|
||||
|
||||
class BoltzmannWealthModel : public kami::Model {
|
||||
public:
|
||||
BoltzmannWealthModel(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::MultiGrid1D *world;
|
||||
unsigned int stepCount;
|
||||
};
|
||||
|
||||
#endif // BOLTZMAN1D_HPP
|
||||
@@ -2,23 +2,21 @@
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "boltzmann2d")
|
||||
|
||||
project(${EXAMPLE_NAME}
|
||||
LANGUAGES CXX)
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
create_executable( NAME ${EXAMPLE_NAME}
|
||||
SOURCES
|
||||
boltzmann2d.cpp
|
||||
PUBLIC_DEFINITIONS
|
||||
USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS
|
||||
DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS
|
||||
kami
|
||||
)
|
||||
file(GLOB EXAMPLE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cc")
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${KAMI_VERSION_STRING})
|
||||
create_executable(
|
||||
NAME ${EXAMPLE_NAME}
|
||||
SOURCES ${EXAMPLE_SOURCES}
|
||||
PUBLIC_DEFINITIONS USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS ${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS fmt spdlog::spdlog kami::libkami
|
||||
)
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${VERSION_STRING})
|
||||
|
||||
226
examples/boltzmann2d/boltzmann2d.cc
Normal file
226
examples/boltzmann2d/boltzmann2d.cc
Normal file
@@ -0,0 +1,226 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "boltzmann2d.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/stopwatch.h>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/multigrid2d.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/random.h>
|
||||
|
||||
std::shared_ptr<spdlog::logger> console = nullptr;
|
||||
std::shared_ptr<std::mt19937> rng = nullptr;
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<kami::AgentID>
|
||||
: fmt::formatter<std::string> {
|
||||
static auto format(
|
||||
kami::AgentID agent_id,
|
||||
format_context& ctx
|
||||
) {
|
||||
return format_to(ctx.out(), "{}", agent_id.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<kami::GridCoord2D>
|
||||
: fmt::formatter<std::string> {
|
||||
static auto format(
|
||||
const kami::GridCoord2D& coord,
|
||||
format_context& ctx
|
||||
) {
|
||||
return format_to(ctx.out(), "{}", coord.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
MoneyAgent2D::~MoneyAgent2D() {
|
||||
console->trace("Deconstructing Agent {} with final wealth {}", get_agent_id(), _agent_wealth);
|
||||
}
|
||||
|
||||
kami::AgentID MoneyAgent2D::step(std::shared_ptr<kami::Model> model) {
|
||||
this->_step_counter++;
|
||||
|
||||
console->trace("Agent {} is moving", this->get_agent_id());
|
||||
this->move_agent(model);
|
||||
if (_agent_wealth > 0)
|
||||
this->give_money(model);
|
||||
|
||||
return this->get_agent_id();
|
||||
}
|
||||
|
||||
std::optional<kami::GridCoord2D> MoneyAgent2D::move_agent(const std::shared_ptr<kami::Model>& model) {
|
||||
console->trace("Entering move_agent");
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
auto domain = model->get_domain();
|
||||
if (!domain)
|
||||
throw (std::domain_error("model is missing domain"));
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid2D>(domain);
|
||||
|
||||
auto move_list_opt = world->get_neighborhood(agent_id, false, kami::GridNeighborhoodType::VonNeumann);
|
||||
if (!move_list_opt)
|
||||
return std::nullopt;
|
||||
auto move_list = move_list_opt;
|
||||
std::uniform_int_distribution<int> dist(0, (int) move_list->size() - 1);
|
||||
auto new_location = *std::next(move_list->begin(), dist(*rng));
|
||||
|
||||
console->trace("Moving Agent {} to location {}", agent_id, new_location);
|
||||
world->move_agent(agent_id, new_location);
|
||||
console->trace("Exiting move_agent");
|
||||
|
||||
return new_location;
|
||||
}
|
||||
|
||||
std::optional<kami::AgentID> MoneyAgent2D::give_money(const std::shared_ptr<kami::Model>& model) {
|
||||
console->trace("Entering give_money");
|
||||
auto agent_id = get_agent_id();
|
||||
|
||||
auto domain = model->get_domain();
|
||||
if (!domain)
|
||||
throw (std::domain_error("model is missing domain"));
|
||||
auto world = std::static_pointer_cast<kami::MultiGrid2D>(domain);
|
||||
|
||||
auto agents = model->get_population();
|
||||
if (!agents)
|
||||
throw (std::domain_error("model is missing population"));
|
||||
auto population = std::static_pointer_cast<kami::Population>(agents);
|
||||
|
||||
auto location = world->get_location_by_agent(agent_id);
|
||||
auto cell_mates_opt = world->get_location_contents(location);
|
||||
|
||||
if (!cell_mates_opt)
|
||||
return std::nullopt;
|
||||
|
||||
auto cell_mates = cell_mates_opt;
|
||||
if (cell_mates->size() < 2)
|
||||
return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int) cell_mates->size() - 1);
|
||||
auto other_agent_id = *std::next(cell_mates->begin(), dist(*rng));
|
||||
auto other_agent = std::static_pointer_cast<MoneyAgent2D>(population->get_agent_by_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;
|
||||
|
||||
console->trace("Exiting move_agent");
|
||||
return other_agent_id;
|
||||
}
|
||||
|
||||
BoltzmannWealthModel2D::BoltzmannWealthModel2D(
|
||||
unsigned int number_agents,
|
||||
unsigned int length_x,
|
||||
unsigned int length_y,
|
||||
unsigned int new_seed
|
||||
) {
|
||||
rng = std::make_shared<std::mt19937>();
|
||||
rng->seed(new_seed);
|
||||
|
||||
auto domain = std::make_shared<kami::MultiGrid2D>(length_x, length_y, true, true);
|
||||
auto scheduler = std::make_shared<kami::RandomScheduler>(rng);
|
||||
auto population = std::make_shared<kami::Population>();
|
||||
|
||||
this->set_domain(domain);
|
||||
this->set_scheduler(scheduler);
|
||||
this->set_population(population);
|
||||
|
||||
console->debug("Scheduler initiated with seed {}", new_seed);
|
||||
|
||||
_step_count = 0;
|
||||
|
||||
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++) {
|
||||
auto new_agent = std::make_shared<MoneyAgent2D>();
|
||||
|
||||
console->trace("Initializing agent with AgentID {}", new_agent->get_agent_id());
|
||||
population->add_agent(new_agent);
|
||||
domain->add_agent(new_agent->get_agent_id(), kami::GridCoord2D(dist_x(*rng), dist_x(*rng)));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> BoltzmannWealthModel2D::step() {
|
||||
console->trace("Executing model step {}", _step_count++);
|
||||
_sched->step(shared_from_this());
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "EmptyDeclOrStmt"
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char** argv
|
||||
) {
|
||||
std::string ident = "boltzmann2d";
|
||||
std::string log_level_option = "info";
|
||||
CLI::App app{ident};
|
||||
unsigned int x_size = 16, y_size = 16, agent_count = x_size * y_size, max_steps = 100, initial_seed = 42;
|
||||
|
||||
// This exercise is really stupid.
|
||||
auto levels_list = std::make_unique<std::list<std::string>>();
|
||||
for (auto& level_name : SPDLOG_LEVEL_NAMES)
|
||||
levels_list->push_back(std::string(level_name.data(), level_name.size()));
|
||||
|
||||
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(levels_list.get(), CLI::ignore_case));
|
||||
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.to_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);
|
||||
|
||||
spdlog::stopwatch sw;
|
||||
|
||||
auto model = std::make_shared<BoltzmannWealthModel2D>(agent_count, x_size, y_size, initial_seed);
|
||||
for (int i = 0; i < max_steps; i++)
|
||||
model->step();
|
||||
|
||||
console->info("Boltzmann Wealth Model simulation complete, requiring {} seconds", sw);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
@@ -1,137 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#include "boltzmann2d.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/config.hpp>
|
||||
#include <kami/grid2d.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <kami/multigrid2d.hpp>
|
||||
#include <map>
|
||||
|
||||
kami::MultiGrid2D *MoneyAgent::world = nullptr;
|
||||
BoltzmannWealthModel *MoneyAgent::model = nullptr;
|
||||
|
||||
MoneyAgent::MoneyAgent() {
|
||||
stepCounter = 0;
|
||||
agentWealth = 1;
|
||||
}
|
||||
|
||||
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::GridNeighborhoodType::Moore, false);
|
||||
auto newLocation = moveList[static_cast<unsigned int>(rand()) % moveList.size()];
|
||||
|
||||
world->moveAgent(agentID, newLocation);
|
||||
}
|
||||
|
||||
int MoneyAgent::getWealth() {
|
||||
return agentWealth;
|
||||
}
|
||||
|
||||
void MoneyAgent::setWealth(int newWealth) {
|
||||
agentWealth = newWealth;
|
||||
}
|
||||
|
||||
void MoneyAgent::giveMoney() {
|
||||
kami::AgentID agentID = getAgentID();
|
||||
kami::GridCoord2D location = world->getLocationByAgent(agentID);
|
||||
std::vector<kami::AgentID> *cellMates = world->getCellContents(location);
|
||||
|
||||
if (cellMates->size() > 1) {
|
||||
kami::AgentID otherAgentID = cellMates->at(static_cast<unsigned int>(rand()) % cellMates->size());
|
||||
auto otherAgent = model->getAgentByID(otherAgentID);
|
||||
|
||||
otherAgent->agentWealth += 1;
|
||||
agentWealth -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void MoneyAgent::prinfo(void) const {
|
||||
kami::AgentID agentID = getAgentID();
|
||||
kami::GridCoord2D location = world->getLocationByAgent(agentID);
|
||||
|
||||
std::cout << " agent: " << agentID << " step: " << stepCounter << " wealth: " << agentWealth << " location: " << location << std::endl;
|
||||
}
|
||||
|
||||
BoltzmannWealthModel::BoltzmannWealthModel(unsigned int numberAgents, unsigned int lengthX, unsigned int lengthY) {
|
||||
world = new kami::MultiGrid2D(lengthX, lengthY, 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(),
|
||||
kami::GridCoord2D(rand() % static_cast<int>(lengthX),
|
||||
rand() % static_cast<int>(lengthY)));
|
||||
}
|
||||
}
|
||||
|
||||
BoltzmannWealthModel::~BoltzmannWealthModel() {
|
||||
for (auto agentPair = agentList.begin(); agentPair != agentList.end(); agentPair++) {
|
||||
delete agentPair->second;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
BoltzmannWealthModel model(100, 10, 10);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
model.step();
|
||||
}
|
||||
|
||||
model.prinfo();
|
||||
}
|
||||
116
examples/boltzmann2d/boltzmann2d.h
Normal file
116
examples/boltzmann2d/boltzmann2d.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef BOLTZMANN2D_H
|
||||
//! @cond SuppressGuard
|
||||
#define BOLTZMANN2D_H
|
||||
//! @endcond
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/multigrid2d.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/random.h>
|
||||
|
||||
/**
|
||||
* A sample agent for a two-dimensional Boltzmann wealth model
|
||||
*/
|
||||
class MoneyAgent2D
|
||||
: public kami::Agent {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create the agent
|
||||
*/
|
||||
MoneyAgent2D()
|
||||
:_step_counter(0), _agent_wealth(1) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deconstruct the agent
|
||||
*/
|
||||
~MoneyAgent2D();
|
||||
|
||||
/**
|
||||
* Execute a single time-step for the agent
|
||||
*/
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override;
|
||||
|
||||
/**
|
||||
* Move the agent to a random location on the world
|
||||
*/
|
||||
std::optional<kami::GridCoord2D> move_agent(const std::shared_ptr<kami::Model>& model);
|
||||
|
||||
/**
|
||||
* Give money to a random agent
|
||||
*/
|
||||
std::optional<kami::AgentID> give_money(const std::shared_ptr<kami::Model>& model);
|
||||
|
||||
private:
|
||||
int _step_counter;
|
||||
int _agent_wealth;
|
||||
};
|
||||
|
||||
/**
|
||||
* The two-dimensional Boltzmann wealth model
|
||||
*/
|
||||
class BoltzmannWealthModel2D
|
||||
: public kami::Model {
|
||||
|
||||
public:
|
||||
/**
|
||||
* 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
|
||||
* occupy in the first dimension
|
||||
* @param[in] length_y the length of the two-dimensional world the agents
|
||||
* occupy in the second dimension
|
||||
* @param[in] new_seed the initial seed used for the random number
|
||||
* generator.
|
||||
*/
|
||||
explicit BoltzmannWealthModel2D(
|
||||
unsigned int number_agents = 10,
|
||||
unsigned int length_x = 10,
|
||||
unsigned int length_y = 10,
|
||||
unsigned int new_seed = 42
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute a single time-step for the model.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> step() final;
|
||||
|
||||
private:
|
||||
unsigned int _step_count;
|
||||
};
|
||||
|
||||
#endif // BOLTZMANN2D_H
|
||||
@@ -1,59 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef BOLTZMAN2D_HPP
|
||||
#define BOLTZMAN2D_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <kami/multigrid2d.hpp>
|
||||
#include <kami/random.hpp>
|
||||
#include <map>
|
||||
#include <random>
|
||||
|
||||
class MoneyAgent : public kami::Agent {
|
||||
public:
|
||||
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;
|
||||
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 // BOLTZMAN2D_HPP
|
||||
@@ -1,24 +0,0 @@
|
||||
####
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(EXAMPLE_NAME "boltzmann3d")
|
||||
|
||||
project(${EXAMPLE_NAME}
|
||||
LANGUAGES CXX)
|
||||
|
||||
create_executable( NAME ${EXAMPLE_NAME}
|
||||
SOURCES
|
||||
boltzmann3d.cpp
|
||||
PUBLIC_DEFINITIONS
|
||||
USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS
|
||||
DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS
|
||||
kami
|
||||
)
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${KAMI_VERSION_STRING})
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#include "boltzmann3d.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/kami.hpp>
|
||||
#include <kami/multigrid3d.hpp>
|
||||
#include <kami/random.hpp>
|
||||
#include <map>
|
||||
|
||||
kami::MultiGrid3D *MoneyAgent::world = nullptr;
|
||||
BoltzmannWealthModel *MoneyAgent::model = nullptr;
|
||||
|
||||
MoneyAgent::MoneyAgent() {
|
||||
stepCounter = 0;
|
||||
agentWealth = 1;
|
||||
}
|
||||
|
||||
void MoneyAgent::step() {
|
||||
stepCounter++;
|
||||
|
||||
moveAgent();
|
||||
if (agentWealth > 0)
|
||||
giveMoney();
|
||||
}
|
||||
|
||||
void MoneyAgent::setWorld(kami::MultiGrid3D *w) {
|
||||
world = w;
|
||||
}
|
||||
|
||||
void MoneyAgent::setModel(class BoltzmannWealthModel *m) {
|
||||
model = m;
|
||||
}
|
||||
|
||||
void MoneyAgent::moveAgent() {
|
||||
auto agentID = this->getAgentID();
|
||||
auto moveList = world->getNeighborhood(agentID, kami::GridNeighborhoodType::Moore, false);
|
||||
auto newLocation = moveList[static_cast<unsigned int>(rand()) % moveList.size()];
|
||||
|
||||
world->moveAgent(agentID, newLocation);
|
||||
}
|
||||
|
||||
int MoneyAgent::getWealth() {
|
||||
return agentWealth;
|
||||
}
|
||||
|
||||
void MoneyAgent::setWealth(int newWealth) {
|
||||
agentWealth = newWealth;
|
||||
}
|
||||
|
||||
void MoneyAgent::giveMoney() {
|
||||
kami::AgentID agentID = getAgentID();
|
||||
kami::GridCoord3D location = world->getLocationByAgent(agentID);
|
||||
std::vector<kami::AgentID> *cellMates = world->getCellContents(location);
|
||||
|
||||
if (cellMates->size() > 1) {
|
||||
kami::AgentID otherAgentID = cellMates->at(static_cast<unsigned int>(rand()) % cellMates->size());
|
||||
auto otherAgent = model->getAgentByID(otherAgentID);
|
||||
|
||||
otherAgent->agentWealth += 1;
|
||||
agentWealth -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void MoneyAgent::prinfo(void) const {
|
||||
kami::AgentID agentID = getAgentID();
|
||||
kami::GridCoord3D location = world->getLocationByAgent(agentID);
|
||||
|
||||
std::cout << " agent: " << agentID << " step: " << stepCounter << " wealth: " << agentWealth << " location: " << location << std::endl;
|
||||
}
|
||||
|
||||
BoltzmannWealthModel::BoltzmannWealthModel(unsigned int numberAgents, unsigned int lengthX, unsigned int lengthY, unsigned int lengthZ) {
|
||||
world = new kami::MultiGrid3D(lengthX, lengthY, lengthZ, true, 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(),
|
||||
kami::GridCoord3D(rand() % static_cast<int>(lengthX),
|
||||
rand() % static_cast<int>(lengthY),
|
||||
rand() % static_cast<int>(lengthZ)));
|
||||
}
|
||||
}
|
||||
|
||||
BoltzmannWealthModel::~BoltzmannWealthModel() {
|
||||
for (auto agentPair = agentList.begin(); agentPair != agentList.end(); agentPair++) {
|
||||
delete agentPair->second;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
BoltzmannWealthModel model(64, 4, 4, 4);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
model.step();
|
||||
}
|
||||
|
||||
model.prinfo();
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef BOLTZMAN3D_HPP
|
||||
#define BOLTZMAN3D_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <kami/multigrid3d.hpp>
|
||||
#include <kami/random.hpp>
|
||||
#include <map>
|
||||
#include <random>
|
||||
|
||||
class MoneyAgent : public kami::Agent {
|
||||
public:
|
||||
MoneyAgent();
|
||||
|
||||
void step();
|
||||
|
||||
static void setWorld(kami::MultiGrid3D *w);
|
||||
static void setModel(class BoltzmannWealthModel *m);
|
||||
|
||||
void moveAgent();
|
||||
|
||||
int getWealth();
|
||||
void setWealth(int newWealth);
|
||||
void giveMoney();
|
||||
|
||||
void prinfo(void) const;
|
||||
|
||||
private:
|
||||
static kami::MultiGrid3D *world;
|
||||
static BoltzmannWealthModel *model;
|
||||
int stepCounter;
|
||||
int agentWealth;
|
||||
};
|
||||
|
||||
class BoltzmannWealthModel : public kami::Model {
|
||||
public:
|
||||
BoltzmannWealthModel(unsigned int = 1000, unsigned int = 10, 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::MultiGrid3D *world;
|
||||
unsigned int stepCount;
|
||||
};
|
||||
|
||||
#endif // BOLTZMAN_HPP
|
||||
22
examples/minimal/CMakeLists.txt
Normal file
22
examples/minimal/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
####
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "minimal")
|
||||
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
file(GLOB EXAMPLE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cc")
|
||||
|
||||
create_executable(
|
||||
NAME ${EXAMPLE_NAME}
|
||||
SOURCES ${EXAMPLE_SOURCES}
|
||||
PUBLIC_DEFINITIONS USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS ${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS fmt spdlog::spdlog kami::libkami
|
||||
)
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${VERSION_STRING})
|
||||
68
examples/minimal/minimal.cc
Normal file
68
examples/minimal/minimal.cc
Normal file
@@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* Copyright (c) 2023 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/model.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/sequential.h>
|
||||
|
||||
class MinimalAgent
|
||||
: public kami::Agent {
|
||||
public:
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override {
|
||||
return this->get_agent_id();
|
||||
}
|
||||
};
|
||||
|
||||
class MinimalModel
|
||||
: public kami::Model {
|
||||
public:
|
||||
MinimalModel() {
|
||||
auto sched = std::make_shared<kami::SequentialScheduler>();
|
||||
set_scheduler(sched);
|
||||
|
||||
auto pop = std::make_shared<kami::Population>();
|
||||
set_population(pop);
|
||||
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
auto new_agent = std::make_shared<MinimalAgent>();
|
||||
pop->add_agent(new_agent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto model = std::make_shared<MinimalModel>();
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
model->step();
|
||||
|
||||
return 0;
|
||||
}
|
||||
22
examples/starter/CMakeLists.txt
Normal file
22
examples/starter/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
####
|
||||
# Set minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(spdlog)
|
||||
|
||||
set(EXAMPLE_NAME "starter")
|
||||
|
||||
project(${EXAMPLE_NAME} LANGUAGES CXX)
|
||||
|
||||
file(GLOB EXAMPLE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cc")
|
||||
|
||||
create_executable(
|
||||
NAME ${EXAMPLE_NAME}
|
||||
SOURCES ${EXAMPLE_SOURCES}
|
||||
PUBLIC_DEFINITIONS USE_DOUBLE_PRECISION=1
|
||||
PRIVATE_DEFINITIONS DEBUG_VERBOSE
|
||||
PRIVATE_INCLUDE_PATHS ${CMAKE_SOURCE_DIR}/include
|
||||
PUBLIC_LINKED_TARGETS fmt spdlog::spdlog kami::libkami
|
||||
)
|
||||
|
||||
set_target_properties(${EXAMPLE_NAME} PROPERTIES VERSION ${VERSION_STRING})
|
||||
136
examples/starter/starter.cc
Normal file
136
examples/starter/starter.cc
Normal file
@@ -0,0 +1,136 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "starter.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/stopwatch.h>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/model.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/random.h>
|
||||
|
||||
std::shared_ptr<spdlog::logger> console = nullptr;
|
||||
std::shared_ptr<std::mt19937> rng = nullptr;
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<kami::AgentID>
|
||||
: fmt::formatter<std::string> {
|
||||
static auto format(
|
||||
kami::AgentID agent_id,
|
||||
format_context& ctx
|
||||
) {
|
||||
return format_to(ctx.out(), "{}", agent_id.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
StarterAgent::StarterAgent() {
|
||||
console->debug("StarterAgent with ID {} constructed", this->get_agent_id());
|
||||
}
|
||||
|
||||
StarterAgent::~StarterAgent() {
|
||||
console->debug("StarterAgent with ID {} deconstructed", this->get_agent_id());
|
||||
}
|
||||
|
||||
kami::AgentID StarterAgent::step(std::shared_ptr<kami::Model> model) {
|
||||
this->_step_counter++;
|
||||
return this->get_agent_id();
|
||||
}
|
||||
|
||||
StarterModel::StarterModel(
|
||||
unsigned int number_agents,
|
||||
unsigned int new_seed
|
||||
) {
|
||||
rng = std::make_shared<std::mt19937>();
|
||||
rng->seed(new_seed);
|
||||
|
||||
auto sched = std::make_shared<kami::RandomScheduler>(rng);
|
||||
auto pop = std::make_shared<kami::Population>();
|
||||
|
||||
_sched = sched;
|
||||
_pop = pop;
|
||||
|
||||
console->debug("Scheduler initiated with seed {}", new_seed);
|
||||
|
||||
_step_count = 0;
|
||||
|
||||
for (auto i = 0; i < number_agents; i++) {
|
||||
auto new_agent = std::make_shared<StarterAgent>();
|
||||
|
||||
console->trace("Initializing agent with AgentID {}", new_agent->get_agent_id());
|
||||
_pop->add_agent(new_agent);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<kami::Model> StarterModel::step() {
|
||||
console->trace("Executing model step {}", ++_step_count);
|
||||
_sched->step(shared_from_this());
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char** argv
|
||||
) {
|
||||
std::string ident = "starter";
|
||||
std::string log_level_option = "info";
|
||||
CLI::App app{ident};
|
||||
unsigned int agent_count = 100, max_steps = 100, initial_seed = 8675309;
|
||||
|
||||
// This exercise is really stupid.
|
||||
auto levels_list = std::make_unique<std::list<std::string>>();
|
||||
for (auto& level_name : SPDLOG_LEVEL_NAMES)
|
||||
levels_list->push_back(std::string(level_name.data(), level_name.size()));
|
||||
|
||||
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(levels_list.get(), CLI::ignore_case));
|
||||
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);
|
||||
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.to_string(), log_level_option);
|
||||
console->info("Starting Starter Model with {} agents for {} steps", agent_count, max_steps);
|
||||
|
||||
auto model = std::make_shared<StarterModel>(agent_count, initial_seed);
|
||||
|
||||
spdlog::stopwatch sw;
|
||||
for (int i = 0; i < max_steps; i++)
|
||||
model->step();
|
||||
|
||||
console->info("Starter Model simulation complete, requiring {} seconds", sw);
|
||||
}
|
||||
93
examples/starter/starter.h
Normal file
93
examples/starter/starter.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef STARTER_H
|
||||
//! @cond SuppressGuard
|
||||
#define STARTER_H
|
||||
//! @endcond
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/random.h>
|
||||
|
||||
/**
|
||||
* A starter agent for a starter model
|
||||
*/
|
||||
class StarterAgent
|
||||
: public kami::Agent {
|
||||
private:
|
||||
int _step_counter = 0;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
StarterAgent();
|
||||
|
||||
/**
|
||||
* Deconstructor
|
||||
*/
|
||||
~StarterAgent();
|
||||
|
||||
/**
|
||||
* Execute a single time-step for the agent
|
||||
*/
|
||||
kami::AgentID step(std::shared_ptr<kami::Model> model) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The one-dimensional Boltzmann wealth model
|
||||
*/
|
||||
class StarterModel
|
||||
: public kami::Model {
|
||||
private:
|
||||
unsigned int _step_count;
|
||||
|
||||
public:
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
explicit StarterModel(
|
||||
unsigned int number_agents = 10,
|
||||
unsigned int new_seed = 42
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute a single time-step for the model.
|
||||
*/
|
||||
std::shared_ptr<kami::Model> step();
|
||||
};
|
||||
|
||||
#endif // STARTER_H
|
||||
235
include/kami/agent.h
Normal file
235
include/kami/agent.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_AGENT_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_AGENT_H
|
||||
//! @endcond
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <kami/model.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief A unique identifier for each `Agent`.
|
||||
*
|
||||
* @details The unique identifier permits ordering to allow `AgentID`s to be used as keys
|
||||
* for `std::map`. The unique identifier is unique for the session, however,
|
||||
* `AgentID`s are not guaranteed to be unique from session-to-session.
|
||||
*
|
||||
* @see Agent
|
||||
*/
|
||||
class LIBKAMI_EXPORT AgentID {
|
||||
private:
|
||||
inline static long long _id_next = 1;
|
||||
|
||||
/**
|
||||
* @brief The unique identifier is a `long long`.
|
||||
*
|
||||
* @details 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;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new unique identifier.
|
||||
*/
|
||||
AgentID();
|
||||
|
||||
/**
|
||||
* @brief Convert the identifier to a human-readable string.
|
||||
*
|
||||
* @return a human-readable form of the `AgentID` as `std::string`.
|
||||
*/
|
||||
[[nodiscard]] std::string to_string() const;
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Test if one AgentID is less than another.
|
||||
*
|
||||
* @details 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Output an AgentID to the specified output stream
|
||||
*
|
||||
* @details 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
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A superclass for all agents.
|
||||
*
|
||||
* @details All agents should subclass the `Agent` class. At a minimum, subclasses must
|
||||
* implement the `step()` function, to execute a single time step for each
|
||||
* agent.
|
||||
*
|
||||
* @see `ReporterAgent`, `StagedAgent`
|
||||
*/
|
||||
class LIBKAMI_EXPORT Agent {
|
||||
private:
|
||||
const AgentID _agent_id;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get the `Agent`'s `AgentID`.
|
||||
*
|
||||
* @return the `AgentID`
|
||||
*/
|
||||
[[nodiscard]] AgentID get_agent_id() const;
|
||||
|
||||
/**
|
||||
* @brief Execute a time-step for the agent
|
||||
*
|
||||
* @details 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.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
*
|
||||
* @returns a copy of the AgentID
|
||||
*/
|
||||
virtual AgentID step(std::shared_ptr<Model> model) = 0;
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A superclass for all staged agents.
|
||||
*
|
||||
* @details Staged agents use a two-phase step to allow agents to take actions without
|
||||
* updating the state of the model before all agents have been allowed to
|
||||
* update. All work necessary to advance the `StagedAgent` state should take
|
||||
* place in the `step()` function. However, the `StagedAgent` should not actually
|
||||
* update the state, and instead save the results for later use. Finally,
|
||||
* during the `advance()` stage, the StagedAgent state should update.
|
||||
*
|
||||
* `StagedAgents` must implement both the `step()` and `advance()` functions.
|
||||
*/
|
||||
class LIBKAMI_EXPORT StagedAgent
|
||||
: public Agent {
|
||||
public:
|
||||
/**
|
||||
* @brief Post-step advance the agent
|
||||
*
|
||||
* @details 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.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
*
|
||||
*/
|
||||
virtual AgentID advance(std::shared_ptr<Model> model) = 0;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_AGENT_H
|
||||
@@ -1,133 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_AGENT_HPP
|
||||
#define KAMI_AGENT_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief A unique identifier for each agent.
|
||||
/// \details A unqiue identifier is created for each Agent at
|
||||
/// runtime. The unique identifier is an unsigned integer that
|
||||
/// increments monotonically with each new Agent instantiated.
|
||||
/// AgentIDs are not guaranteed to be unique from session-to-session.
|
||||
class KAMI_EXPORT AgentID {
|
||||
public:
|
||||
/// \brief Constructs a new unique identifier.
|
||||
AgentID();
|
||||
|
||||
/// \brief Convert the identifier to a human readable string.
|
||||
std::string toString() const;
|
||||
|
||||
/// \brief Test if two AgentID instances are equal.
|
||||
friend bool operator==(const AgentID &, const AgentID &);
|
||||
|
||||
/// \brief Test if two AgentID instances are not equal.
|
||||
friend bool operator!=(const AgentID &, const AgentID &);
|
||||
|
||||
/// \brief Test if one AgentID is less than another.
|
||||
/// \details Due to the way AgentID instance are used internally,
|
||||
/// the AgentID must be ordered. The `<` operator provides
|
||||
/// basic order sufficient for `std::map`.
|
||||
friend bool operator<(const AgentID &, const AgentID &);
|
||||
|
||||
/// \brief Output an AgentID to the specified output stream.
|
||||
friend std::ostream &operator<<(std::ostream &, const AgentID &);
|
||||
|
||||
private:
|
||||
static uint64_t idGen;
|
||||
uint64_t id;
|
||||
};
|
||||
|
||||
/// \brief A superclass for Agents
|
||||
///
|
||||
/// \details All agents should subclass the Agent class.
|
||||
/// At a minimum, subclasses must implement the `step()`
|
||||
/// function, to execute a single time step for each agent.
|
||||
class KAMI_EXPORT Agent {
|
||||
public:
|
||||
/// \brief Deconstructor
|
||||
virtual ~Agent() = default;
|
||||
|
||||
/// \brief Get the agent's self identification number.
|
||||
AgentID getAgentID() const;
|
||||
|
||||
/// \brief Execute a time-step for the agent
|
||||
///
|
||||
/// \details 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();
|
||||
|
||||
friend bool operator==(const Agent &, const Agent &);
|
||||
friend bool operator!=(const Agent &, const Agent &);
|
||||
|
||||
private:
|
||||
AgentID agentID;
|
||||
};
|
||||
|
||||
/// \brief A class for agents with pre-`step()` and post-`step()` staging.
|
||||
///
|
||||
/// \details Staged agents use a two-phase or three-phase step to allow agents to take actions without
|
||||
/// updating the state of the model before all agents have been allowed to
|
||||
/// update.
|
||||
class KAMI_EXPORT StagedAgent : public Agent {
|
||||
public:
|
||||
///
|
||||
StagedAgent();
|
||||
virtual ~StagedAgent() = default;
|
||||
|
||||
/// \brief Initialize a staged time step for the agent
|
||||
///
|
||||
/// \details This method should initialize a time-step, but not actually execute
|
||||
/// any changes. It should be implemented if a model's schedule expectes
|
||||
/// a staged stepping function wherein all agents step using the same
|
||||
/// state.
|
||||
virtual void preStep() = 0;
|
||||
|
||||
/// \brief Post-step actions the agent
|
||||
///
|
||||
/// \details This method should be called after `step()`. Any updates or cleanups
|
||||
/// to the agent should occur here that must happen after the step is complete.
|
||||
virtual void postStep() = 0;
|
||||
};
|
||||
|
||||
/// \brief A class for agents with two actions per scheduler step
|
||||
///
|
||||
/// \details This class is meant to be used for models that require two steps per
|
||||
/// scheduler cycle. This is conceived as being a "day" and "night" action for
|
||||
/// each agent where the scheduler interprets a step as a day-long period. However,
|
||||
/// it may be appropriate for other model configurations, too.
|
||||
class KAMI_EXPORT TwoActionAgent : public Agent {
|
||||
public:
|
||||
///
|
||||
TwoActionAgent();
|
||||
virtual ~TwoActionAgent() = default;
|
||||
|
||||
/// \brief Execute a time-step for the agent.
|
||||
///
|
||||
/// \details This function should step the agent instance completely and executes
|
||||
/// both the `stepA()` and `stepB()` methods.
|
||||
virtual void step();
|
||||
|
||||
/// \brief Execute the first element of the time step.
|
||||
///
|
||||
/// \details This method should execute the first action in a given time step.
|
||||
/// The action is not expected to be state preserving for other agents.
|
||||
virtual void stepA() = 0;
|
||||
|
||||
/// \brief Execute the second element of the time step.
|
||||
///
|
||||
/// \details This method should execute the second action in a given time step.
|
||||
/// The action is not expected to be state preserving for other agents.
|
||||
virtual void stepB() = 0;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_AGENT_HPP
|
||||
68
include/kami/config.h.in
Normal file
68
include/kami/config.h.in
Normal file
@@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains definitions made in CMakeLists.txt
|
||||
* that we want available in the source code.
|
||||
* In the source code, include "exampleConfig.h" (no .in suffix).
|
||||
* This header file will be generated, and filled with the
|
||||
* right definition values. Change the namings as you wish,
|
||||
* but make sure they match up with what's in CMakeLists.txt.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_CONFIG_H
|
||||
#define KAMI_CONFIG_H
|
||||
|
||||
#include <semver.hpp>
|
||||
|
||||
/**
|
||||
* The major version of the Kami library.
|
||||
*/
|
||||
#define KAMI_VERSION_MAJOR @VERSION_MAJOR@
|
||||
|
||||
/**
|
||||
* The minor version of the Kami library.
|
||||
*/
|
||||
#define KAMI_VERSION_MINOR @VERSION_MINOR@
|
||||
|
||||
/**
|
||||
* The patch level of the Kami library.
|
||||
*/
|
||||
#define KAMI_VERSION_PATCH @VERSION_PATCH@
|
||||
|
||||
namespace kami {
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* @brief A reference copy of the current version of Kami
|
||||
*/
|
||||
constexpr auto version = semver::version{KAMI_VERSION_MAJOR, KAMI_VERSION_MINOR, KAMI_VERSION_PATCH};
|
||||
}
|
||||
|
||||
} // namespace kami
|
||||
|
||||
|
||||
#endif // KAMI_CONFIG_H
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* This file contains definitions made in CMakeLists.txt
|
||||
* that we want available in the source code.
|
||||
* In the source code, include "exampleConfig.h" (no .in suffix).
|
||||
* This header file will be generated, and filled with the
|
||||
* right definition values. Change the namings as you wish,
|
||||
* but make sure they match up with whats in CMakeLists.txt.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_KAMI_VERSION_HPP
|
||||
#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
|
||||
@@ -1,20 +0,0 @@
|
||||
#ifndef KAMI_DATA_BAZ_HPP
|
||||
#define KAMI_DATA_BAZ_HPP
|
||||
|
||||
#include <iostream> // std::cout
|
||||
|
||||
// this is a generated header. It is needed
|
||||
// to build dll libraries that work on windows.
|
||||
// add the BAR_EXPORT definition to each
|
||||
// function/class you want to export to the dll.
|
||||
#include <kami/data/KAMIDATA_EXPORT.hpp>
|
||||
|
||||
namespace foo {
|
||||
|
||||
|
||||
KAMIDATA_EXPORT void baz();
|
||||
|
||||
|
||||
} // namespace foo
|
||||
|
||||
#endif // KAMI_DATA_BAZ_HPP
|
||||
93
include/kami/domain.h
Normal file
93
include/kami/domain.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_DOMAIN_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_DOMAIN_H
|
||||
//! @endcond
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief Provides an environment for the agents to participate in.
|
||||
*
|
||||
* @details Implementations of virtual environments are expected to subclass `Domain`.
|
||||
*/
|
||||
class LIBKAMI_EXPORT Domain {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @details Making this constructor protected makes the class abstract without having
|
||||
* to create any virtual functions.
|
||||
*/
|
||||
Domain() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Provides a coordinate system for each `Domain`.
|
||||
*
|
||||
* @details The coordinate system must be able to produce a human-readable version of the
|
||||
* coordinates given. For instance, an integer grid in two dimensions would
|
||||
* provide standard Descartes coordinates like (0, 0) for the origin, or (2, 3)
|
||||
* for the position that is two units "up" and three units to the "right" of the
|
||||
* origin. Implementation of a coordinate system is left up to the user, though
|
||||
* there are several established systems provided.
|
||||
*
|
||||
* @see GridCoord
|
||||
*/
|
||||
class LIBKAMI_EXPORT Coord {
|
||||
public:
|
||||
/**
|
||||
* @brief 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;
|
||||
|
||||
/**
|
||||
* @brief Output a `Coord` to the specified output stream
|
||||
*
|
||||
* @details 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
|
||||
|
||||
#endif // KAMI_DOMAIN_H
|
||||
@@ -1,20 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_DOMAIN_HPP
|
||||
#define KAMI_DOMAIN_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Provides an environment for the agents to participate in
|
||||
class KAMI_EXPORT Domain {
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_DOMAIN_HPP
|
||||
136
include/kami/error.h
Normal file
136
include/kami/error.h
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// Created by James Howard on 9/9/22.
|
||||
//
|
||||
|
||||
#ifndef KAMI_ERROR_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_ERROR_H
|
||||
//! @endcond
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace kami::error {
|
||||
|
||||
/**
|
||||
* @brief Agent was not found
|
||||
*/
|
||||
class AgentNotFound
|
||||
: public std::logic_error {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit AgentNotFound(const char* s)
|
||||
:std::logic_error(s) {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit AgentNotFound(const std::string& s)
|
||||
:std::logic_error(s) {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Location specified is invalid
|
||||
*
|
||||
* @see `LocationUnavailable`
|
||||
*/
|
||||
class LocationInvalid
|
||||
: public std::domain_error {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit LocationInvalid(const char* s)
|
||||
:std::domain_error(s) {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit LocationInvalid(const std::string& s)
|
||||
:std::domain_error(s) {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Location specified is unavailable
|
||||
*
|
||||
* @see `LocationInvalid`
|
||||
*/
|
||||
class LocationUnavailable
|
||||
: public std::domain_error {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit LocationUnavailable(const char* s)
|
||||
:std::domain_error(s) {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit LocationUnavailable(const std::string& s)
|
||||
:std::domain_error(s) {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The option given is not valid at this time
|
||||
*/
|
||||
class OptionInvalid
|
||||
: public std::invalid_argument {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit OptionInvalid(const char* s)
|
||||
:std::invalid_argument(s) {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit OptionInvalid(const std::string& s)
|
||||
:std::invalid_argument(s) {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The resource specified is not available at this time
|
||||
*/
|
||||
class ResourceNotAvailable
|
||||
: public std::logic_error {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit ResourceNotAvailable(const char* s)
|
||||
:std::logic_error(s) {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param s text description of the exception
|
||||
*/
|
||||
explicit ResourceNotAvailable(const std::string& s)
|
||||
:std::logic_error(s) {
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //KAMI_ERROR_H
|
||||
141
include/kami/grid.h
Normal file
141
include/kami/grid.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_GRID_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_GRID_H
|
||||
//! @endcond
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <kami/domain.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief Neighborhood types for orthogonal grid domains of cells.
|
||||
*
|
||||
* @details Orthogonal grid domains are those that provide cells equidistant
|
||||
* along a standard Cartesian grid. `GridNeighborhoodType` allows for the
|
||||
* 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,
|
||||
|
||||
/**
|
||||
* @brief Von Neumann neighborhood
|
||||
*
|
||||
* @details Von Neumann neighborhood types do not include
|
||||
* diagonally-adjacent cells as neighbors.
|
||||
*/
|
||||
VonNeumann
|
||||
};
|
||||
|
||||
/**
|
||||
* @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,
|
||||
|
||||
/**
|
||||
* @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 Chebyshev distance.
|
||||
*
|
||||
* @details The Chebyshev distance, also called the "chessboard" distance
|
||||
* is the number of single point jumps necessary to move from one point to
|
||||
* the next. This can be likened to a king on a chessboard and the number
|
||||
* of moves necessary to move from a given point to any other given point.
|
||||
*/
|
||||
Chebyshev
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An abstract domain based on a gridded environment.
|
||||
*
|
||||
* @details All gridded domains are expected to consist of cells in a
|
||||
* rectilinear grid where the cells are equal size and laid out in an ordered
|
||||
* fashion.
|
||||
*/
|
||||
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 {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Find the distance between two points
|
||||
*
|
||||
* @details Find the distance between two points using the
|
||||
* specified metric.
|
||||
*
|
||||
* However, the coordinate class is not aware of the
|
||||
* properties of the `GridDomain` it is operating on. Accordingly,
|
||||
* if the direct path is measured, without accounting for
|
||||
* and toroidal wrapping of the underlying `GridDomain`.
|
||||
*
|
||||
* @param p the point to measure the distance to
|
||||
*
|
||||
* @returns the distance as a `double`
|
||||
*/
|
||||
virtual double distance(std::shared_ptr<Coord>& p) const = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_GRID_H
|
||||
@@ -1,43 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_GRID_HPP
|
||||
#define KAMI_GRID_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Neighborhood types for orthogonal grid domains
|
||||
enum KAMI_EXPORT GridNeighborhoodType {
|
||||
/// \brief Moore neighborhood.
|
||||
/// \details Moore neighborhood types include diagonally
|
||||
/// adjacent cells as neighbors.
|
||||
Moore,
|
||||
|
||||
/// \brief Von Neumann neighborhood.
|
||||
/// \details Von Neumann neighborhood types do not include
|
||||
/// diagonally adjacent cells as neighbors.
|
||||
VonNeumann
|
||||
};
|
||||
|
||||
/// \brief Distance types for orthogonal grid domains
|
||||
enum KAMI_EXPORT GridDistanceType { Linear,
|
||||
Taxicab };
|
||||
|
||||
/// \brief An abstract domain based on a grid with integer steps
|
||||
class KAMI_EXPORT GridDomain : public Domain {
|
||||
};
|
||||
|
||||
/// \brief An abstract for integer coordinates
|
||||
class KAMI_EXPORT GridCoord {
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_DOMAIN_HPP
|
||||
363
include/kami/grid1d.h
Normal file
363
include/kami/grid1d.h
Normal file
@@ -0,0 +1,363 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_GRID1D_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_GRID1D_H
|
||||
//! @endcond
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/domain.h>
|
||||
#include <kami/error.h>
|
||||
#include <kami/grid.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief One-dimensional coordinates
|
||||
*/
|
||||
class LIBKAMI_EXPORT GridCoord1D
|
||||
: public GridCoord {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for one-dimensional coordinates
|
||||
*/
|
||||
explicit GridCoord1D(int x_coord);
|
||||
|
||||
/**
|
||||
* @brief Return the `x` coordinate
|
||||
*/
|
||||
[[nodiscard]] int x() const;
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
|
||||
/**
|
||||
* @brief Find the distance between two points
|
||||
*
|
||||
* @details Find the distance between two points using the
|
||||
* specified metric. There are three options provided by
|
||||
* the `GridDistanceType` class. However, of the three
|
||||
* distance types provided, all provide the same result so
|
||||
* the value is ignored and the single result is returned.
|
||||
*
|
||||
* However, the coordinate class is not aware of the
|
||||
* properties of the `Grid1D` it is operating on. Accordingly,
|
||||
* if the direct path is measured, without accounting for
|
||||
* and toroidal wrapping of the underlying `Grid1D`.
|
||||
*
|
||||
* @param p the point to measure the distance to
|
||||
*
|
||||
* @returns the distance as a `double`
|
||||
*/
|
||||
double distance(std::shared_ptr<Coord>& p) const override;
|
||||
|
||||
/**
|
||||
* @brief Test if two coordinates are equal
|
||||
*/
|
||||
friend bool operator==(
|
||||
const GridCoord1D& lhs,
|
||||
const GridCoord1D& rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Test if two coordinates are not equal
|
||||
*/
|
||||
friend bool operator!=(
|
||||
const GridCoord1D& lhs,
|
||||
const GridCoord1D& rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Output a given coordinate to the specified stream
|
||||
*/
|
||||
friend std::ostream& operator<<(
|
||||
std::ostream& lhs,
|
||||
const GridCoord1D& rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Add two coordinates together
|
||||
*/
|
||||
inline friend GridCoord1D operator+(
|
||||
const GridCoord1D& lhs,
|
||||
const GridCoord1D& rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Subtract one coordinate from another
|
||||
*/
|
||||
inline friend GridCoord1D operator-(
|
||||
const GridCoord1D& lhs,
|
||||
const GridCoord1D& rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
*
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord1D operator*(
|
||||
const GridCoord1D& lhs,
|
||||
double rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
*
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord1D operator*(
|
||||
double lhs,
|
||||
const GridCoord1D& rhs
|
||||
);
|
||||
|
||||
private:
|
||||
int _x_coord;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A one-dimensional grid where each cell may contain agents
|
||||
*
|
||||
* @details The grid is linear and may wrap around in its only dimension.
|
||||
*
|
||||
* @see `MultiGrid1D`
|
||||
* @see `SoloGrid1D`
|
||||
*/
|
||||
class LIBKAMI_EXPORT Grid1D
|
||||
: public GridDomain {
|
||||
public:
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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 AgentID add_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord1D& coord
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* @brief Remove agent from the grid.
|
||||
*
|
||||
* @param[in] agent_id the `AgentID` of the agent to remove.
|
||||
*
|
||||
* @returns the `AgentID` of the `Agent` deleted
|
||||
*/
|
||||
AgentID delete_agent(AgentID agent_id);
|
||||
|
||||
/**
|
||||
* @brief 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 the `AgentID` of the `Agent` deleted
|
||||
*/
|
||||
AgentID delete_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord1D& coord
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*/
|
||||
AgentID move_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord1D& coord
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
|
||||
/**
|
||||
* @brief 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(const AgentID& agent_id) const;
|
||||
|
||||
/**
|
||||
* @brief Get the contents of the specified location.
|
||||
*
|
||||
* @param[in] coord the coordinates of the query.
|
||||
*
|
||||
* @return a pointer to a `set` 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::shared_ptr<std::set<AgentID>>
|
||||
get_location_contents(const GridCoord1D& coord) const;
|
||||
|
||||
/**
|
||||
* @brief Inquire to whether the grid wraps in the `x` dimension.
|
||||
*
|
||||
* @return true if the grid wraps, and false otherwise
|
||||
*/
|
||||
[[nodiscard]] bool get_wrap_x() const;
|
||||
|
||||
/**
|
||||
* @brief 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 an `unordered_set` of `GridCoord1D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*/
|
||||
[[nodiscard]] std::shared_ptr<std::unordered_set<GridCoord1D>>
|
||||
get_neighborhood(
|
||||
AgentID agent_id,
|
||||
bool include_center
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief 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 an `unordered_set` of `GridCoord1D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*/
|
||||
[[nodiscard]] std::shared_ptr<std::unordered_set<GridCoord1D>>
|
||||
get_neighborhood(
|
||||
const GridCoord1D& coord,
|
||||
bool include_center
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Get the size of the grid in the `x` dimension.
|
||||
*
|
||||
* @return the length of the grid in the `x` dimension
|
||||
*/
|
||||
[[nodiscard]] unsigned int get_maximum_x() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Direction coordinates
|
||||
*
|
||||
* @details This can be used for addition to coordinates. Direction
|
||||
* `0` is the first direction clockwise from "vertical." In this
|
||||
* case, it can be on a vertically-oriented column, upwards, or to
|
||||
* the right on a horizontally-oriented column. Then the additional
|
||||
* directions are enumerated clockwise.
|
||||
*/
|
||||
const std::vector<GridCoord1D> directions = {GridCoord1D(1), GridCoord1D(-1)};
|
||||
|
||||
/**
|
||||
* @brief An `unordered_set` containing the `AgentID`s of all agents assigned to this
|
||||
* grid.
|
||||
*/
|
||||
std::unique_ptr<std::unordered_multimap<GridCoord1D, AgentID>> _agent_grid;
|
||||
|
||||
/**
|
||||
* @brief A map containing the grid location of each agent.
|
||||
*/
|
||||
std::unique_ptr<std::map<AgentID, GridCoord1D>> _agent_index;
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
//! @cond SuppressHashMethod
|
||||
#define KAMI_GRID1D_H
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<kami::GridCoord1D> {
|
||||
size_t operator()(const kami::GridCoord1D& key) const {
|
||||
return (hash<int>()(key.x()));
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
//! @endcond
|
||||
|
||||
#endif // KAMI_GRID1D_H
|
||||
@@ -1,114 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_GRID1D_HPP
|
||||
#define KAMI_GRID1D_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Onem-dimensional coordinates.
|
||||
class KAMI_EXPORT GridCoord1D : public GridCoord {
|
||||
public:
|
||||
/// \brief Constructor for one-dimensional coordinates.
|
||||
GridCoord1D(int);
|
||||
|
||||
/// Get the `X` coordinate.
|
||||
int getX(void) const;
|
||||
|
||||
/// Test if two coordinates are equal.
|
||||
friend bool operator==(const GridCoord1D &, const GridCoord1D &);
|
||||
|
||||
/// Test if two coordinates are not equal.
|
||||
friend bool operator!=(const GridCoord1D &, const GridCoord1D &);
|
||||
|
||||
/// Output a given coordinate to the specified stream.
|
||||
friend std::ostream &operator<<(std::ostream &, const GridCoord1D &);
|
||||
|
||||
private:
|
||||
int x;
|
||||
};
|
||||
|
||||
/// \brief A one-dimensional grid where each cell may contain
|
||||
/// agents.
|
||||
///
|
||||
/// \details The grid is linear and may wrap around in either
|
||||
/// dimension.
|
||||
class KAMI_EXPORT Grid1D : public GridDomain {
|
||||
public:
|
||||
/// Constructor
|
||||
Grid1D(unsigned int, bool);
|
||||
|
||||
/// Deconstructor
|
||||
virtual ~Grid1D();
|
||||
|
||||
/// \brief Place agent on the grid at the specified location.
|
||||
bool addAgent(AgentID, int);
|
||||
|
||||
/// \brief Place agent on the grid at the specified location.
|
||||
virtual bool addAgent(AgentID, GridCoord1D) = 0;
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID);
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID, int);
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID, GridCoord1D);
|
||||
|
||||
/// Move an agent to the specified location.
|
||||
bool moveAgent(AgentID, GridCoord1D);
|
||||
|
||||
/// Inquire if the specified location is empty.
|
||||
bool isEmpty(GridCoord1D) const;
|
||||
|
||||
/// Inquire if the specified location is valid within the grid.
|
||||
bool isLocationValid(GridCoord1D) const;
|
||||
|
||||
/// Get the location of the specified agent.
|
||||
GridCoord1D getLocationByAgent(AgentID) const;
|
||||
|
||||
/// Get the contents of the specified location.
|
||||
std::vector<AgentID> *getCellContents(GridCoord1D) const;
|
||||
|
||||
/// Set the wrapping in the `X` dimension.
|
||||
void setWrapX(bool);
|
||||
|
||||
/// Inquire to whether the grid wraps in the `X` dimension.
|
||||
bool getWrapX(void) const;
|
||||
|
||||
/// Return the neighborhood of the specified Agent
|
||||
std::vector<GridCoord1D> getNeighborhood(AgentID, bool) const;
|
||||
|
||||
/// Return the neighborhood of the specified Agent
|
||||
std::vector<GridCoord1D> getNeighborhood(GridCoord1D, bool) const;
|
||||
|
||||
/// Get the length of the grid in the `X` dimension.
|
||||
unsigned int getMaxX(void) const;
|
||||
|
||||
protected:
|
||||
std::vector<AgentID> *agentGrid;
|
||||
std::map<AgentID, GridCoord1D> *agentIndex;
|
||||
unsigned int maxX;
|
||||
bool wrapX;
|
||||
|
||||
GridCoord1D locationWrap(int) const;
|
||||
GridCoord1D locationWrap(GridCoord1D) const;
|
||||
|
||||
private:
|
||||
void setMaxX(unsigned int);
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_GRID1D_HPP
|
||||
458
include/kami/grid2d.h
Normal file
458
include/kami/grid2d.h
Normal file
@@ -0,0 +1,458 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_GRID2D_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_GRID2D_H
|
||||
//! @endcond
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/domain.h>
|
||||
#include <kami/grid.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief Two-dimensional coordinates
|
||||
*/
|
||||
class LIBKAMI_EXPORT GridCoord2D
|
||||
: public GridCoord {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for two-dimensional coordinates
|
||||
*/
|
||||
GridCoord2D(
|
||||
int x_coord,
|
||||
int y_coord
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Get the coordinate in the first dimension or `x`.
|
||||
*/
|
||||
[[nodiscard]] int x() const;
|
||||
|
||||
/**
|
||||
* @brief Get the coordinate in the second dimension or `y`.
|
||||
*/
|
||||
[[nodiscard]] int y() const;
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
|
||||
/**
|
||||
* @brief Find the distance between two points
|
||||
*
|
||||
* @details Find the distance between two points using the
|
||||
* specified metric.
|
||||
*
|
||||
* However, the coordinate class is not aware of the
|
||||
* properties of the `Grid2D` it is operating on. Accordingly,
|
||||
* if the direct path is measured, without accounting for
|
||||
* and toroidal wrapping of the underlying `Grid2D`.
|
||||
*
|
||||
* @param p the point to measure the distance to
|
||||
*
|
||||
* @returns the distance as a `double`
|
||||
*/
|
||||
double distance(std::shared_ptr<Coord>& p) const override;
|
||||
|
||||
/**
|
||||
* @brief Find the distance between two points
|
||||
*
|
||||
* @details Find the distance between two points using the
|
||||
* specified metric. There are three options provided by
|
||||
* the `GridDistanceType` class.
|
||||
*
|
||||
* However, the coordinate class is not aware of the
|
||||
* properties of the `Grid2D` it is operating on. Accordingly,
|
||||
* if the direct path is measured, without accounting for
|
||||
* and toroidal wrapping of the underlying `Grid2D`.
|
||||
*
|
||||
* @param p the point to measure the distance to
|
||||
* @param distance_type specify the distance type
|
||||
*
|
||||
* @returns the distance as a `double`
|
||||
*/
|
||||
double
|
||||
distance(
|
||||
std::shared_ptr<GridCoord2D>& p,
|
||||
GridDistanceType distance_type = GridDistanceType::Euclidean
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Test if two coordinates are equal
|
||||
*/
|
||||
friend bool operator==(
|
||||
const GridCoord2D&,
|
||||
const GridCoord2D&
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Test if two coordinates are not equal
|
||||
*/
|
||||
friend bool operator!=(
|
||||
const GridCoord2D&,
|
||||
const GridCoord2D&
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Output a given coordinate to the specified stream
|
||||
*/
|
||||
friend std::ostream& operator<<(
|
||||
std::ostream&,
|
||||
const GridCoord2D&
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Add two coordinates together
|
||||
*/
|
||||
inline friend GridCoord2D operator+(
|
||||
const GridCoord2D& lhs,
|
||||
const GridCoord2D& rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Subtract one coordinate from another
|
||||
*/
|
||||
inline friend GridCoord2D operator-(
|
||||
const GridCoord2D& lhs,
|
||||
const GridCoord2D& rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
*
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord2D operator*(
|
||||
const GridCoord2D& lhs,
|
||||
const double rhs
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Multiply a coordinate by a scalar
|
||||
*
|
||||
* @details If any component of the resulting value is not a whole number, it is
|
||||
* truncated following the same rules as `int`.
|
||||
*/
|
||||
inline friend GridCoord2D operator*(
|
||||
const double lhs,
|
||||
const GridCoord2D& rhs
|
||||
);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Find the distance between two points using the Chebyshev metric
|
||||
*
|
||||
* @param p the point to measure the distance to
|
||||
*
|
||||
* @returns the distance as a `double`
|
||||
*/
|
||||
inline double distance_chebyshev(std::shared_ptr<GridCoord2D>& p) const;
|
||||
|
||||
/**
|
||||
* @brief Find the distance between two points using the Euclidean metric
|
||||
*
|
||||
* @param p the point to measure the distance to
|
||||
*
|
||||
* @returns the distance as a `double`
|
||||
*/
|
||||
inline double distance_euclidean(std::shared_ptr<GridCoord2D>& p) const;
|
||||
|
||||
/**
|
||||
* @brief Find the distance between two points using the Manhattan metric
|
||||
*
|
||||
* @param p the point to measure the distance to
|
||||
*
|
||||
* @returns the distance as a `double`
|
||||
*/
|
||||
inline double distance_manhattan(std::shared_ptr<GridCoord2D>& p) const;
|
||||
|
||||
private:
|
||||
int _x_coord, _y_coord;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A two-dimensional grid where each cell may contain agents
|
||||
*
|
||||
* @details The grid is linear and may wrap around in its only dimension.
|
||||
*
|
||||
* @see `MultiGrid2D`
|
||||
* @see `SoloGrid2D`
|
||||
*/
|
||||
class LIBKAMI_EXPORT Grid2D
|
||||
: public GridDomain {
|
||||
public:
|
||||
/**
|
||||
* @brief 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
|
||||
*/
|
||||
explicit Grid2D(
|
||||
unsigned int maximum_x,
|
||||
unsigned int maximum_y,
|
||||
bool wrap_x = false,
|
||||
bool wrap_y = false
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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 AgentID add_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord2D& coord
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*/
|
||||
AgentID delete_agent(AgentID agent_id);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*/
|
||||
AgentID delete_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord2D& coord
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*/
|
||||
AgentID move_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord2D& coord
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
|
||||
virtual /**
|
||||
* @brief 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(const AgentID& agent_id) const;
|
||||
|
||||
/**
|
||||
* @brief Get the contents of the specified location.
|
||||
*
|
||||
* @param[in] coord the coordinates of the query.
|
||||
*
|
||||
* @return a pointer to a `set` 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::shared_ptr<std::set<AgentID>>
|
||||
get_location_contents(const GridCoord2D& coord) const;
|
||||
|
||||
/**
|
||||
* @brief Inquire to whether the grid wraps in the `x` dimension.
|
||||
*
|
||||
* @return true if the grid wraps, and false otherwise
|
||||
*/
|
||||
[[nodiscard]] bool get_wrap_x() const;
|
||||
|
||||
/**
|
||||
* @brief Inquire to whether the grid wraps in the `y` dimension.
|
||||
*
|
||||
* @return true if the grid wraps, and false otherwise
|
||||
*/
|
||||
[[nodiscard]] bool get_wrap_y() const;
|
||||
|
||||
virtual /**
|
||||
* @brief 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 set of `GridCoord2D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*
|
||||
* @see `NeighborhoodType`
|
||||
*/
|
||||
std::shared_ptr<std::unordered_set<GridCoord2D>>
|
||||
get_neighborhood(
|
||||
AgentID agent_id,
|
||||
bool include_center,
|
||||
GridNeighborhoodType neighborhood_type
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief 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 set of `GridCoord2D` that includes all of the coordinates
|
||||
* for all adjacent points.
|
||||
*
|
||||
* @see `NeighborhoodType`
|
||||
*/
|
||||
[[nodiscard]] std::shared_ptr<std::unordered_set<GridCoord2D>>
|
||||
get_neighborhood(
|
||||
const GridCoord2D& coord,
|
||||
bool include_center,
|
||||
GridNeighborhoodType neighborhood_type
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Get the size of the grid in the `x` dimension.
|
||||
*
|
||||
* @return the length of the grid in the `x` dimension
|
||||
*/
|
||||
[[nodiscard]] unsigned int get_maximum_x() const;
|
||||
|
||||
/**
|
||||
* @brief Get the size of the grid in the `y` dimension.
|
||||
*
|
||||
* @return the length of the grid in the `xy dimension
|
||||
*/
|
||||
[[nodiscard]] unsigned int get_maximum_y() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief von Neumann neighborhood coordinates
|
||||
*
|
||||
* @details This can be used for addition to coordinates. Direction
|
||||
* `0` is the first direction clockwise from "vertical." Then the additional
|
||||
* directions are enumerated clockwise.
|
||||
*/
|
||||
const std::vector<GridCoord2D> directions_vonneumann = {GridCoord2D(0, 1), GridCoord2D(1, 0),
|
||||
GridCoord2D(0, -1), GridCoord2D(-1, 0)};
|
||||
|
||||
/**
|
||||
* @brief Moore neighborhood coordinates
|
||||
*
|
||||
* @details This can be used for addition to coordinates. Direction
|
||||
* `0` is the first direction clockwise from "vertical." Then the additional
|
||||
* directions are enumerated clockwise.
|
||||
*/
|
||||
const std::vector<GridCoord2D> directions_moore = {GridCoord2D(0, 1), GridCoord2D(1, 1),
|
||||
GridCoord2D(1, 0), GridCoord2D(1, -1),
|
||||
GridCoord2D(0, -1), GridCoord2D(-1, -1),
|
||||
GridCoord2D(-1, 0), GridCoord2D(-1, 1)};
|
||||
|
||||
/**
|
||||
* @brief A map containing the `AgentID`s of all agents assigned to this
|
||||
* grid.
|
||||
*/
|
||||
std::unique_ptr<std::unordered_multimap<GridCoord2D, AgentID>> _agent_grid;
|
||||
|
||||
/**
|
||||
* @brief A map containing the grid location of each agent.
|
||||
*/
|
||||
std::unique_ptr<std::map<AgentID, GridCoord2D>> _agent_index;
|
||||
|
||||
/**
|
||||
* @brief 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;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
//! @cond SuppressHashMethod
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<kami::GridCoord2D> {
|
||||
size_t operator()(const kami::GridCoord2D& key) const {
|
||||
return ((hash<int>()(key.x()) ^ (hash<int>()(key.y()) << 1)) >> 1);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
//! @endcond
|
||||
|
||||
#endif // KAMI_GRID2D_H
|
||||
@@ -1,127 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_GRID2D_HPP
|
||||
#define KAMI_GRID2D_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Two-dimensional coordinates.
|
||||
class KAMI_EXPORT GridCoord2D : public GridCoord {
|
||||
public:
|
||||
/// \brief Constructor for two-dimensional coordinates.
|
||||
GridCoord2D(int, int);
|
||||
|
||||
/// Get the `X` coordinate.
|
||||
int getX(void) const;
|
||||
|
||||
/// Get the `Y` coordinate.
|
||||
int getY(void) const;
|
||||
|
||||
/// 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 &);
|
||||
|
||||
/// Output a given coordinate to the specified stream.
|
||||
friend std::ostream &operator<<(std::ostream &, const GridCoord2D &);
|
||||
|
||||
private:
|
||||
int x, y;
|
||||
};
|
||||
|
||||
/// \brief A two-dimensional grid where each cell may contain
|
||||
/// agents.
|
||||
///
|
||||
/// \details The grid is rectangular and may wrap around in either
|
||||
/// dimension.
|
||||
class KAMI_EXPORT Grid2D : public GridDomain {
|
||||
public:
|
||||
/// Constructor
|
||||
Grid2D(unsigned int, unsigned int, bool, bool);
|
||||
|
||||
/// Deconstructor
|
||||
virtual ~Grid2D();
|
||||
|
||||
/// \brief Place agent on the grid at the specified location.
|
||||
bool addAgent(AgentID, int, int);
|
||||
|
||||
/// \brief Place agent on the grid at the specified location.
|
||||
virtual bool addAgent(AgentID, GridCoord2D) = 0;
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID);
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID, int, int);
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID, GridCoord2D);
|
||||
|
||||
/// Move an agent to the specified location.
|
||||
bool moveAgent(AgentID, GridCoord2D);
|
||||
|
||||
/// Inquire if the specified location is empty.
|
||||
bool isEmpty(GridCoord2D) const;
|
||||
|
||||
/// Inquire if the specified location is valid within the grid.
|
||||
bool isLocationValid(GridCoord2D) const;
|
||||
|
||||
/// Get the location of the specified agent.
|
||||
GridCoord2D getLocationByAgent(AgentID) const;
|
||||
|
||||
/// Get the contents of the specified location.
|
||||
std::vector<AgentID> *getCellContents(GridCoord2D) const;
|
||||
|
||||
/// Set the wrapping in the `X` dimension.
|
||||
void setWrapX(bool);
|
||||
|
||||
/// Set the wrapping in the `Y` dimension.
|
||||
void setWrapY(bool);
|
||||
|
||||
/// Inquire to whether the grid wraps in the `X` dimension.
|
||||
bool getWrapX(void) const;
|
||||
|
||||
/// Inquire to whether the grid wraps in the `Y` dimension.
|
||||
bool getWrapY(void) const;
|
||||
|
||||
/// Return the neighborhood of the specified Agent
|
||||
std::vector<GridCoord2D> getNeighborhood(AgentID, GridNeighborhoodType, bool) const;
|
||||
|
||||
/// Return the neighborhood of the specified cell
|
||||
std::vector<GridCoord2D> getNeighborhood(GridCoord2D, GridNeighborhoodType, bool) const;
|
||||
|
||||
/// Get the length of the grid in the `X` dimension.
|
||||
unsigned int getMaxX(void) const;
|
||||
|
||||
/// Get the length of the grid in the `Y` dimension.
|
||||
unsigned int getMaxY(void) const;
|
||||
|
||||
protected:
|
||||
std::vector<AgentID> **agentGrid;
|
||||
std::map<AgentID, GridCoord2D> *agentIndex;
|
||||
unsigned int maxX, maxY;
|
||||
bool wrapX, wrapY;
|
||||
|
||||
GridCoord2D locationWrap(int, int) const;
|
||||
GridCoord2D locationWrap(GridCoord2D) const;
|
||||
|
||||
private:
|
||||
void setMaxX(unsigned int);
|
||||
void setMaxY(unsigned int);
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_GRID2D_HPP
|
||||
@@ -1,138 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_GRID3D_HPP
|
||||
#define KAMI_GRID3D_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Three-dimensional coordinates.
|
||||
class KAMI_EXPORT GridCoord3D : public GridCoord {
|
||||
public:
|
||||
/// \brief Constructor for three-dimensional coordinates.
|
||||
GridCoord3D(int, int, int);
|
||||
|
||||
/// Get the `X` coordinate.
|
||||
int getX(void) const;
|
||||
|
||||
/// Get the `Y` coordinate.
|
||||
int getY(void) const;
|
||||
|
||||
/// Get the `Z` coordinate.
|
||||
int getZ(void) const;
|
||||
|
||||
/// Test if two coordinates are equal.
|
||||
friend bool operator==(const GridCoord3D &, const GridCoord3D &);
|
||||
|
||||
/// Test if two coordinates are not equal.
|
||||
friend bool operator!=(const GridCoord3D &, const GridCoord3D &);
|
||||
|
||||
/// Output a given coordinate to the specified stream.
|
||||
friend std::ostream &operator<<(std::ostream &, const GridCoord3D &);
|
||||
|
||||
private:
|
||||
int x, y, z;
|
||||
};
|
||||
|
||||
/// \brief A three-dimensional grid where each cell may contain
|
||||
/// agents.
|
||||
///
|
||||
/// \details The grid is rectangular and may wrap around in any
|
||||
/// dimension.
|
||||
class KAMI_EXPORT Grid3D : public GridDomain {
|
||||
public:
|
||||
/// Constructor
|
||||
Grid3D(unsigned int, unsigned int, unsigned int, bool, bool, bool);
|
||||
|
||||
/// Deconstructor
|
||||
virtual ~Grid3D();
|
||||
|
||||
/// \brief Place agent on the grid at the specified location.
|
||||
bool addAgent(AgentID, int, int, int);
|
||||
|
||||
/// \brief Place agent on the grid at the specified location.
|
||||
virtual bool addAgent(AgentID, GridCoord3D) = 0;
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID);
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID, int, int, int);
|
||||
|
||||
/// Remove agent from the grid
|
||||
bool deleteAgent(AgentID, GridCoord3D);
|
||||
|
||||
/// Move an agent to the specified location.
|
||||
bool moveAgent(AgentID, GridCoord3D);
|
||||
|
||||
/// Inquire if the specified location is empty.
|
||||
bool isEmpty(GridCoord3D) const;
|
||||
|
||||
/// Inquire if the specified location is valid within the grid.
|
||||
bool isLocationValid(GridCoord3D) const;
|
||||
|
||||
/// Get the location of the specified agent.
|
||||
GridCoord3D getLocationByAgent(AgentID) const;
|
||||
|
||||
/// Get the contents of the specified location.
|
||||
std::vector<AgentID> *getCellContents(GridCoord3D) const;
|
||||
|
||||
/// Set the wrapping in the `X` dimension.
|
||||
void setWrapX(bool);
|
||||
/// Set the wrapping in the `Y` dimension.
|
||||
void setWrapY(bool);
|
||||
/// Set the wrapping in the `Z` dimension.
|
||||
void setWrapZ(bool);
|
||||
|
||||
/// Inquire to whether the grid wraps in the `X` dimension.
|
||||
bool getWrapX(void) const;
|
||||
|
||||
/// Inquire to whether the grid wraps in the `Y` dimension.
|
||||
bool getWrapY(void) const;
|
||||
|
||||
/// Inquire to whether the grid wraps in the `Z` dimension.
|
||||
bool getWrapZ(void) const;
|
||||
|
||||
/// Return the neighborhood of the specified Agent
|
||||
std::vector<GridCoord3D> getNeighborhood(AgentID, GridNeighborhoodType, bool) const;
|
||||
|
||||
/// Return the neighborhood of the specified cell
|
||||
std::vector<GridCoord3D> getNeighborhood(GridCoord3D, GridNeighborhoodType, bool) const;
|
||||
|
||||
/// Get the length of the grid in the `X` dimension.
|
||||
unsigned int getMaxX(void) const;
|
||||
|
||||
/// Get the length of the grid in the `Y` dimension.
|
||||
unsigned int getMaxY(void) const;
|
||||
|
||||
/// Get the length of the grid in the `Z` dimension.
|
||||
unsigned int getMaxZ(void) const;
|
||||
|
||||
protected:
|
||||
std::vector<AgentID> ***agentGrid;
|
||||
std::map<AgentID, GridCoord3D> *agentIndex;
|
||||
unsigned int maxX, maxY, maxZ;
|
||||
bool wrapX, wrapY, wrapZ;
|
||||
|
||||
GridCoord3D locationWrap(int, int, int) const;
|
||||
GridCoord3D locationWrap(GridCoord3D) const;
|
||||
|
||||
private:
|
||||
void setMaxX(unsigned int);
|
||||
void setMaxY(unsigned int);
|
||||
void setMaxZ(unsigned int);
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_GRID3D_HPP
|
||||
89
include/kami/kami.h
Normal file
89
include/kami/kami.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_KAMI_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_KAMI_H
|
||||
//! @endcond
|
||||
|
||||
#include <semver.hpp>
|
||||
|
||||
#include <kami/KAMI_EXPORT.h>
|
||||
#include <kami/config.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
// Forward declarations to clean up a lot of include-file madness
|
||||
class Agent;
|
||||
|
||||
class AgentID;
|
||||
|
||||
class Domain;
|
||||
|
||||
class Model;
|
||||
|
||||
class Population;
|
||||
|
||||
class ReporterAgent;
|
||||
|
||||
class ReporterModel;
|
||||
|
||||
class Scheduler;
|
||||
|
||||
/**
|
||||
* @brief Get the current version of Kami
|
||||
*
|
||||
* @return a `semver::version` object containing version information
|
||||
*/
|
||||
inline semver::version get_version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A catalog of handy constants, mostly useful for seeding
|
||||
* a random number generator
|
||||
*/
|
||||
class Constants {
|
||||
public:
|
||||
/**
|
||||
* @brief Life, the Universe, and Everything!
|
||||
*/
|
||||
static constexpr auto ADAMS_CONSTANT = 42u;
|
||||
|
||||
/**
|
||||
* @brief Jenny, I've got your number
|
||||
*/
|
||||
static constexpr auto JENNYS_NUMBER = 8675309u;
|
||||
|
||||
/**
|
||||
* @brief $(7^(e - 1/e) - 9) * pi^2$
|
||||
*/
|
||||
static constexpr auto JENNYS_CONSTANT = 867.530901981;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_KAMI_H
|
||||
@@ -1,15 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_KAMI_HPP
|
||||
#define KAMI_KAMI_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/config.hpp>
|
||||
#include <kami/model.hpp>
|
||||
#include <kami/scheduler.hpp>
|
||||
|
||||
#endif // KAMI_KAMI_HPP
|
||||
131
include/kami/model.h
Normal file
131
include/kami/model.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_MODEL_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_MODEL_H
|
||||
//! @endcond
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <kami/domain.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/population.h>
|
||||
#include <kami/scheduler.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief An abstract for generic models
|
||||
*
|
||||
* @see `ReporterModel`
|
||||
*/
|
||||
class LIBKAMI_EXPORT Model
|
||||
: public std::enable_shared_from_this<Model> {
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get the `Domain` associated with this model
|
||||
*
|
||||
* @returns a shared pointer to the `Domain`
|
||||
*/
|
||||
std::shared_ptr<Domain> get_domain();
|
||||
|
||||
/**
|
||||
* @brief Add a `Domain` to this scheduler
|
||||
*
|
||||
* @details This method will associate a model with the
|
||||
* scheduler.
|
||||
*
|
||||
* @returns a shared pointer to the `Domain`
|
||||
*/
|
||||
std::shared_ptr<Domain> set_domain(std::shared_ptr<Domain> domain);
|
||||
|
||||
/**
|
||||
* @brief Get the `Population` associated with this model
|
||||
*
|
||||
* @returns a shared pointer to the `Population`
|
||||
*/
|
||||
std::shared_ptr<Population> get_population();
|
||||
|
||||
/**
|
||||
* @brief Add a `Model` to this scheduler
|
||||
*
|
||||
* @details This method will associate a model with the
|
||||
* scheduler.
|
||||
*
|
||||
* @returns a shared pointer to the `Population`
|
||||
*/
|
||||
std::shared_ptr<Population> set_population(std::shared_ptr<Population> population);
|
||||
|
||||
/**
|
||||
* @brief Get the `Scheduler` associated with this model
|
||||
*
|
||||
* @returns a shared pointer to the `Scheduler`
|
||||
*/
|
||||
std::shared_ptr<Scheduler> get_scheduler();
|
||||
|
||||
/**
|
||||
* @brief Add a `Model` to this scheduler
|
||||
*
|
||||
* @details This method will associate a model with the
|
||||
* scheduler.
|
||||
*
|
||||
* @returns a shared pointer to the `Scheduler`
|
||||
*/
|
||||
std::shared_ptr<Scheduler> set_scheduler(std::shared_ptr<Scheduler> scheduler);
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step of the model
|
||||
*
|
||||
* @details This method will collect all the `Agent`s in the `Population` associated
|
||||
* with model and pass them to the associated `Scheduler` for stepping.
|
||||
*
|
||||
* @returns a shared pointer to the model instance
|
||||
*/
|
||||
virtual std::shared_ptr<Model> step();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Reference copy of the `Domain`
|
||||
*/
|
||||
std::shared_ptr<Domain> _domain = nullptr;
|
||||
|
||||
/**
|
||||
* @brief Reference copy of the `Population`
|
||||
*/
|
||||
std::shared_ptr<Population> _pop = nullptr;
|
||||
|
||||
/**
|
||||
* @brief Reference copy of the `Scheduler`
|
||||
*/
|
||||
std::shared_ptr<Scheduler> _sched = nullptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_MODEL_H
|
||||
@@ -1,35 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_MODEL_HPP
|
||||
#define KAMI_MODEL_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// An abstract for generic models
|
||||
class KAMI_EXPORT Model {
|
||||
public:
|
||||
/// Destructor.
|
||||
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.
|
||||
virtual void run(unsigned int) = 0;
|
||||
|
||||
/// 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.
|
||||
virtual void step() = 0;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_MODEL_HPP
|
||||
79
include/kami/multigrid1d.h
Normal file
79
include/kami/multigrid1d.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_MULTIGRID1D_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_MULTIGRID1D_H
|
||||
//! @endcond
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/domain.h>
|
||||
#include <kami/grid.h>
|
||||
#include <kami/grid1d.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief A one-dimensional grid where each cell may contain multiple agents
|
||||
*
|
||||
* @details The grid is linear and may wrap around in its only dimension.
|
||||
*
|
||||
* @see `Grid1D`
|
||||
* @see `SoloGrid1D`
|
||||
*/
|
||||
class LIBKAMI_EXPORT MultiGrid1D
|
||||
: public Grid1D {
|
||||
public:
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
*/
|
||||
AgentID add_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord1D& coord
|
||||
) override;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_MULTIGRID1D_H
|
||||
@@ -1,27 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_MULTIGRID1D_HPP
|
||||
#define KAMI_MULTIGRID1D_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/grid1d.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
class KAMI_EXPORT MultiGrid1D : public Grid1D {
|
||||
public:
|
||||
MultiGrid1D(unsigned int, bool);
|
||||
|
||||
bool addAgent(AgentID, GridCoord1D);
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_MULTIGRID1D_HPP
|
||||
84
include/kami/multigrid2d.h
Normal file
84
include/kami/multigrid2d.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_MULTIGRID2D_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_MULTIGRID2D_H
|
||||
//! @endcond
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/domain.h>
|
||||
#include <kami/grid.h>
|
||||
#include <kami/grid2d.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief A two-dimensional grid where each cell may contain multiple agents
|
||||
*
|
||||
* @details The grid is linear and may wrap around in either dimension.
|
||||
*
|
||||
* @see `Grid2D`
|
||||
* @see `SoloGrid2D`
|
||||
*/
|
||||
class LIBKAMI_EXPORT MultiGrid2D
|
||||
: public Grid2D {
|
||||
public:
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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 the `AgentID` of the agent added
|
||||
*/
|
||||
AgentID add_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord2D& coord
|
||||
) override;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_MULTIGRID2D_H
|
||||
@@ -1,27 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_MULTIGRID2D_HPP
|
||||
#define KAMI_MULTIGRID2D_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/grid2d.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
class KAMI_EXPORT MultiGrid2D : public Grid2D {
|
||||
public:
|
||||
MultiGrid2D(unsigned int, unsigned int, bool, bool);
|
||||
|
||||
bool addAgent(AgentID, GridCoord2D);
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_MULTIGRID2D_HPP
|
||||
@@ -1,27 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_MULTIGRID3D_HPP
|
||||
#define KAMI_MULTIGRID3D_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/grid3d.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
class KAMI_EXPORT MultiGrid3D : public Grid3D {
|
||||
public:
|
||||
MultiGrid3D(unsigned int, unsigned int, unsigned int, bool, bool, bool);
|
||||
|
||||
bool addAgent(AgentID, GridCoord3D);
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_MULTIGRID3D_HPP
|
||||
92
include/kami/population.h
Normal file
92
include/kami/population.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_POPULATION_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_POPULATION_H
|
||||
//! @endcond
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief An abstract for generic models
|
||||
*/
|
||||
class LIBKAMI_EXPORT Population {
|
||||
public:
|
||||
/**
|
||||
* @brief 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 nothing is not found
|
||||
*/
|
||||
[[nodiscard]] std::shared_ptr<Agent> get_agent_by_id(AgentID agent_id) const;
|
||||
|
||||
/**
|
||||
* @brief Add an Agent to the Population.
|
||||
*
|
||||
* @param agent The Agent to add.
|
||||
*
|
||||
* @returns the ID of the agent added
|
||||
*/
|
||||
AgentID add_agent(const std::shared_ptr<Agent>& agent) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Remove an Agent from the Population.
|
||||
*
|
||||
* @param agent_id The AgentID of the agent to remove.
|
||||
*
|
||||
* @returns a shared pointer to the Agent deleted
|
||||
*/
|
||||
std::shared_ptr<Agent> delete_agent(AgentID agent_id);
|
||||
|
||||
/**
|
||||
* @brief Returns the agent list.
|
||||
*
|
||||
* @returns a `std::vector` of all the `AgentID`'s in the `Population`
|
||||
*/
|
||||
[[nodiscard]] std::unique_ptr<std::vector<AgentID>> get_agent_list() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief A mapping of `AgentID` to `Agent` pointers
|
||||
*
|
||||
* @details This is the mapping of all `AgentID`s to
|
||||
* pointers to the corresponding `Agent` in this population.
|
||||
* This is left exposed as protected should any subclass
|
||||
* wish to manipulate this mapping directly.
|
||||
*/
|
||||
std::map<kami::AgentID, std::shared_ptr<Agent>> _agent_map;
|
||||
};
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_POPULATION_H
|
||||
46
include/kami/position.h
Normal file
46
include/kami/position.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_POSITION_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_POSITION_H
|
||||
//! @endcond
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <kami/grid1d.h>
|
||||
#include <kami/grid2d.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
typedef std::variant<
|
||||
GridCoord1D,
|
||||
GridCoord2D
|
||||
> Position;
|
||||
|
||||
}
|
||||
|
||||
#endif //KAMI_POSITION_H
|
||||
128
include/kami/random.h
Normal file
128
include/kami/random.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_RANDOM_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_RANDOM_H
|
||||
//! @endcond
|
||||
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/kami.h>
|
||||
#include <kami/scheduler.h>
|
||||
#include <kami/sequential.h>
|
||||
|
||||
namespace kami {
|
||||
/**
|
||||
* @brief Will execute all agent steps in a random order.
|
||||
*
|
||||
* @details A random scheduler will iterate over the agents assigned
|
||||
* to the scheduler and call their `step()` function in a random order.
|
||||
* That order should be different for each subsequent call to `step()`,
|
||||
* but is not guaranteed not to repeat.
|
||||
*/
|
||||
class LIBKAMI_EXPORT RandomScheduler
|
||||
: public SequentialScheduler,
|
||||
std::enable_shared_from_this<RandomScheduler> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*/
|
||||
RandomScheduler() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param rng [in] A uniform random number generator of type
|
||||
* `std::mt19937`, used as the source of randomness.
|
||||
*/
|
||||
explicit RandomScheduler(std::shared_ptr<std::mt19937> rng);
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step.
|
||||
*
|
||||
* @details This method will randomize the list of Agents provided
|
||||
* then execute the `Agent::step()` method for every Agent listed.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::unique_ptr<std::vector<AgentID>>
|
||||
step(
|
||||
std::shared_ptr<Model> model,
|
||||
std::unique_ptr<std::vector<AgentID>> agent_list
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step for a `ReporterModel`
|
||||
*
|
||||
* @details This method will randomize the list of Agents provided
|
||||
* then execute the `Agent::step()` method for every Agent listed.
|
||||
*
|
||||
* @param model a reference copy of the `ReporterModel`
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::unique_ptr<std::vector<AgentID>>
|
||||
step(
|
||||
std::shared_ptr<ReporterModel> model,
|
||||
std::unique_ptr<std::vector<AgentID>> agent_list
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @brief Set the RNG
|
||||
*
|
||||
* @details 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.
|
||||
*
|
||||
* @returns a shared pointer to the random number generator
|
||||
*/
|
||||
std::shared_ptr<std::mt19937> set_rng(std::shared_ptr<std::mt19937> rng);
|
||||
|
||||
/**
|
||||
* @brief Get the RNG
|
||||
*
|
||||
* @details 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 = nullptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_RANDOM_H
|
||||
@@ -1,69 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef KAMI_RANDOM_HPP
|
||||
#define KAMI_RANDOM_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Will execute all agent steps in a random order.
|
||||
/// \details A random scheduler will iterate over the agents assigned
|
||||
/// to the scheduler and call their `step()` function in a random order.
|
||||
/// That order should be different for each subsequent call to `step()`,
|
||||
/// but is not gauranteed not to repeat.
|
||||
/// \pre First create a Model for the scheduler to live in.
|
||||
class KAMI_EXPORT RandomScheduler : 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.
|
||||
RandomScheduler(Model *);
|
||||
|
||||
/// A deconstructor.
|
||||
virtual ~RandomScheduler();
|
||||
|
||||
/// \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 addAgent(AgentID);
|
||||
|
||||
/// \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 deleteAgent(AgentID);
|
||||
|
||||
/// \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();
|
||||
|
||||
protected:
|
||||
std::vector<AgentID> agentList;
|
||||
std::random_device rd;
|
||||
std::mt19937 rng{rd()};
|
||||
Model *model;
|
||||
int stepCounter;
|
||||
};
|
||||
|
||||
class KAMI_EXPORT TwoActionRandomScheduler : public RandomScheduler {
|
||||
public:
|
||||
/// \brief Execute a single time step.
|
||||
/// \details This method will randomize the list of TwoActionAgents in the
|
||||
/// scheduler's internal queue and then execute the `TwoActionAgent::stepA()`
|
||||
/// method for every TwoActionAgent assigned to this scheduler in the
|
||||
/// randomized order, then execute the `TwoActionAgent::stepB()` method for every
|
||||
// TwoActionAgent assigned to this scheduler in the randomized order,
|
||||
void step();
|
||||
};
|
||||
|
||||
}; // namespace kami
|
||||
|
||||
#endif // KAMI_RANDOM_HPP
|
||||
259
include/kami/reporter.h
Normal file
259
include/kami/reporter.h
Normal file
@@ -0,0 +1,259 @@
|
||||
/*-
|
||||
* Copyright (c) 2022 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_REPORTER_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_REPORTER_H
|
||||
//! @endcond
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/model.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
class Reporter;
|
||||
|
||||
class ReporterAgent;
|
||||
|
||||
class ReporterModel;
|
||||
|
||||
/**
|
||||
* @brief A superclass for all reporting agents
|
||||
*
|
||||
* @details All reporting agents should subclass the `ReportingAgent` class. At a minimum,
|
||||
* subclasses must implement the `step()` function, to execute a single time step for each
|
||||
* agent.
|
||||
*
|
||||
* @see `Agent`, `StagedAgent`
|
||||
*/
|
||||
class LIBKAMI_EXPORT ReporterAgent
|
||||
: public Agent {
|
||||
public:
|
||||
/**
|
||||
* @brief Collect the current state of the agent
|
||||
*
|
||||
* @details This function should collect the agent's
|
||||
* current state. The agent, notably, does not need
|
||||
* to collect historical state, as the historical state
|
||||
* is retained by the `Reporter` instance until such
|
||||
* time as `Reporter::report()` is called. However,
|
||||
* the implementation of the collect() function is
|
||||
* up to the end user who can, ultimately, return whatever
|
||||
* they want.
|
||||
*
|
||||
* The only restriction on collect is that it must return
|
||||
* its data as a [nlohmann::json](https://json.nlohmann.me/)
|
||||
* JSON object. See `Reporter` for additional details.
|
||||
*/
|
||||
virtual std::unique_ptr<nlohmann::json> collect() = 0;
|
||||
|
||||
/**
|
||||
* @brief Execute a time-step for the agent
|
||||
*
|
||||
* @details 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.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
*
|
||||
* @returns a copy of the AgentID
|
||||
*/
|
||||
virtual AgentID step(std::shared_ptr<ReporterModel> model) = 0;
|
||||
|
||||
private:
|
||||
// This should be uncallable, but knocks out the inherited method.
|
||||
AgentID step(std::shared_ptr<Model> model) override;;
|
||||
|
||||
int _step_counter = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An abstract for generic models with a reporting capability
|
||||
*
|
||||
* @see `Model`
|
||||
*/
|
||||
class LIBKAMI_EXPORT ReporterModel
|
||||
: public Model {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
ReporterModel();
|
||||
|
||||
/**
|
||||
* @brief Collect the current state of the model
|
||||
*
|
||||
* @details This function should collect the model's
|
||||
* current state. The model, notably, does not need
|
||||
* to collect historical state, as the historical state
|
||||
* is retained by the `Reporter` instance until such
|
||||
* time as `Reporter::report()` is called. However,
|
||||
* the implementation of the collect() function is
|
||||
* up to the end user who can, ultimately, return whatever
|
||||
* they want.
|
||||
*
|
||||
* This is not expected to return agent data collection,
|
||||
* as the agents' information is collected separately.
|
||||
*/
|
||||
virtual std::unique_ptr<nlohmann::json> collect() = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the step id of the model
|
||||
*
|
||||
* @details The step_id should probably be a monotonically
|
||||
* incrementing integer.
|
||||
*/
|
||||
virtual unsigned int get_step_id();
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step of the model
|
||||
*
|
||||
* @details This method will collect all the `Agent`s in the `Population` associated
|
||||
* with the model and pass them to the associated `Scheduler` for stepping. After scheduling,
|
||||
* this method will run the collect() for the `Reporter` associated with this model.
|
||||
*
|
||||
* @returns a shared pointer to the model instance
|
||||
*/
|
||||
virtual std::shared_ptr<Model> step() override;
|
||||
|
||||
/**
|
||||
* @brief Get the current report
|
||||
*
|
||||
* @details This method will return an object containg the data collected to that
|
||||
* point in the simulation.
|
||||
*
|
||||
* @returns a unique pointer to a `nlohmann::json` object representing the current report
|
||||
*/
|
||||
std::unique_ptr<nlohmann::json> report();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief The current report
|
||||
*/
|
||||
std::shared_ptr<Reporter> _rpt;
|
||||
|
||||
/**
|
||||
* @brief The model's current step count
|
||||
*/
|
||||
unsigned int _step_count{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A `Reporter` is a module that works with `ReporterAgent` and `ReporterModel`
|
||||
* to collect information about the state of the model for later analysis
|
||||
*/
|
||||
class LIBKAMI_EXPORT Reporter
|
||||
: public std::enable_shared_from_this<Reporter> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Reporter();
|
||||
|
||||
/**
|
||||
* @brief Empty the report
|
||||
*
|
||||
* @details Clear all entries from the report; new collection
|
||||
* operations begin with a blank slate.
|
||||
*
|
||||
* @returns a reference copy of the `Reporter`
|
||||
*/
|
||||
std::shared_ptr<Reporter> clear();
|
||||
|
||||
/**
|
||||
* @brief Collect the current state of the model
|
||||
*
|
||||
* @details This will collect the current state of
|
||||
* each agent associated with the population returned
|
||||
* by the `Model`'s `get_population()`.
|
||||
*
|
||||
* @param model reference copy of the model
|
||||
*
|
||||
* @returns a copy of the current report
|
||||
*/
|
||||
std::unique_ptr<nlohmann::json> collect(const std::shared_ptr<ReporterModel>& model);
|
||||
|
||||
/**
|
||||
* @brief Collect the current state of the model
|
||||
*
|
||||
* @details This will collect the current state of
|
||||
* each agent associated with the `Population`.
|
||||
*
|
||||
* @param model reference copy of the model
|
||||
* @param pop Population to collect on
|
||||
*
|
||||
* @returns a copy of the current report
|
||||
*/
|
||||
std::unique_ptr<nlohmann::json>
|
||||
collect(
|
||||
const std::shared_ptr<ReporterModel>& model,
|
||||
const std::shared_ptr<Population>& pop
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Collect the current state of the model
|
||||
*
|
||||
* @details This will collect the current state of
|
||||
* each agent given
|
||||
*
|
||||
* @param model reference copy of the model
|
||||
* @param agent_list a vector agents to report on
|
||||
*
|
||||
* @returns a copy of the current report
|
||||
*/
|
||||
std::unique_ptr<nlohmann::json>
|
||||
collect(
|
||||
const std::shared_ptr<ReporterModel>& model,
|
||||
const std::unique_ptr<std::vector<AgentID>>& agent_list
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Collect the report
|
||||
*
|
||||
* @details This will return the aggregate report
|
||||
* of all the data collected by this `Reporter`.
|
||||
*
|
||||
* @param model reference copy of the model
|
||||
*
|
||||
* @returns a copy of the current report
|
||||
*/
|
||||
std::unique_ptr<nlohmann::json> report(const std::shared_ptr<ReporterModel>& model);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief A vector of the the report collected so far
|
||||
*/
|
||||
std::unique_ptr<std::vector<nlohmann::json>> _report_data = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //KAMI_REPORTER_H
|
||||
124
include/kami/scheduler.h
Normal file
124
include/kami/scheduler.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_SCHEDULER_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_SCHEDULER_H
|
||||
//! @endcond
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/model.h>
|
||||
|
||||
namespace kami {
|
||||
/**
|
||||
* Create a Kami scheduler.
|
||||
*
|
||||
* Schedulers are responsible for executing each time step in the model. A
|
||||
* 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:
|
||||
/**
|
||||
* @brief Execute a single time step.
|
||||
*
|
||||
* @details This method will step through the list of Agents in the
|
||||
* `Population` associated with `model` and then execute the `Agent::step()`
|
||||
* method for every Agent assigned to this scheduler in the order
|
||||
* assigned.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
virtual std::unique_ptr<std::vector<AgentID>> step(std::shared_ptr<Model> model) = 0;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step for a `ReporterModel`
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param model a reference copy of the `ReporterModel`
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
virtual std::unique_ptr<std::vector<AgentID>> step(std::shared_ptr<ReporterModel> model) = 0;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step.
|
||||
*
|
||||
* @details This method will step through the list of Agents
|
||||
* provided and then execute the `Agent::step()`
|
||||
* method for every Agent assigned to this scheduler in the order
|
||||
* assigned.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
virtual std::unique_ptr<std::vector<AgentID>>
|
||||
step(
|
||||
std::shared_ptr<Model> model,
|
||||
std::unique_ptr<std::vector<AgentID>> agent_list
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step for a `ReporterModel`
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param model a reference copy of the `ReporterModel`
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
virtual std::unique_ptr<std::vector<AgentID>>
|
||||
step(
|
||||
std::shared_ptr<ReporterModel> model,
|
||||
std::unique_ptr<std::vector<AgentID>> agent_list
|
||||
) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Counter to increment on each step
|
||||
*/
|
||||
int _step_counter = 0;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_SCHEDULER_H
|
||||
@@ -1,45 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_SCHEDULER_HPP
|
||||
#define KAMI_SCHEDULER_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Create a Kami scheduler.
|
||||
/// \details Schedulers are responsible for executing each time step
|
||||
/// in the model. A 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 KAMI_EXPORT Scheduler {
|
||||
public:
|
||||
/// \brief Return a new Kami scheduler
|
||||
///
|
||||
/// \details This function should return a new instance of a
|
||||
/// scheduler class that implements this trait.
|
||||
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
|
||||
122
include/kami/sequential.h
Normal file
122
include/kami/sequential.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_SEQUENTIAL_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_SEQUENTIAL_H
|
||||
//! @endcond
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <kami/agent.h>
|
||||
#include <kami/kami.h>
|
||||
#include <kami/model.h>
|
||||
#include <kami/scheduler.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief Will execute all agent steps in a sequential order.
|
||||
*
|
||||
* @details A sequential scheduler will iterate over the agents assigned
|
||||
* to the scheduler and call their `step()` function in a sequential order.
|
||||
* That order is preserved between calls to `step()` but may be modified by
|
||||
* `addAgent()` or `deleteAgent()`.
|
||||
*/
|
||||
class LIBKAMI_EXPORT SequentialScheduler
|
||||
: public Scheduler {
|
||||
public:
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::unique_ptr<std::vector<AgentID>> step(std::shared_ptr<Model> model) override;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step for a `ReporterModel`
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param model a reference copy of the `ReporterModel`
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::unique_ptr<std::vector<AgentID>> step(std::shared_ptr<ReporterModel> model) override;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step.
|
||||
*
|
||||
* @details This method will step through the list of Agents
|
||||
* provided and then execute the `Agent::step()`
|
||||
* method for every Agent assigned to this scheduler in the order
|
||||
* assigned.
|
||||
*
|
||||
* @param model a reference copy of the model
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::unique_ptr<std::vector<AgentID>>
|
||||
step(
|
||||
std::shared_ptr<Model> model,
|
||||
std::unique_ptr<std::vector<AgentID>> agent_list
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @brief Execute a single time step for a `ReporterModel`
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param model a reference copy of the `ReporterModel`
|
||||
* @param agent_list list of agents to execute the step
|
||||
*
|
||||
* @returns returns vector of agents successfully stepped
|
||||
*/
|
||||
std::unique_ptr<std::vector<AgentID>>
|
||||
step(
|
||||
std::shared_ptr<ReporterModel> model,
|
||||
std::unique_ptr<std::vector<AgentID>> agent_list
|
||||
) override;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_SEQUENTIAL_H
|
||||
@@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef KAMI_SEQUENTIAL_HPP
|
||||
#define KAMI_SEQUENTIAL_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/model.hpp>
|
||||
#include <kami/scheduler.hpp>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/// \brief Will execute all agent steps in a sequential order.
|
||||
/// \details A sequential scheduler will iterate over the agents assigned
|
||||
/// to the scheduler and call their `step()` function in a sequential order.
|
||||
/// That order is preserved between calls to `step()` but may be modified by
|
||||
/// `addAgent()` or `deleteAgent()`.
|
||||
/// \pre First create a Model for the scheduler to live in.
|
||||
class KAMI_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 *);
|
||||
|
||||
/// A deconstructor.
|
||||
virtual ~SequentialScheduler();
|
||||
|
||||
/// \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 addAgent(AgentID);
|
||||
|
||||
/// \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 deleteAgent(AgentID);
|
||||
|
||||
/// \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();
|
||||
|
||||
private:
|
||||
std::vector<AgentID> agentList;
|
||||
Model *model;
|
||||
int stepCounter;
|
||||
};
|
||||
|
||||
}; // namespace kami
|
||||
|
||||
#endif // KAMI_SEQUENTIAL_HPP
|
||||
78
include/kami/sologrid1d.h
Normal file
78
include/kami/sologrid1d.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_SOLOGRID1D_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_SOLOGRID1D_H
|
||||
//! @endcond
|
||||
|
||||
#include <kami/KAMI_EXPORT.h>
|
||||
#include <kami/agent.h>
|
||||
#include <kami/grid1d.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief A one-dimensional grid where each cell may contain one agents
|
||||
*
|
||||
* @details The grid is linear and may wrap around in its only dimension.
|
||||
*
|
||||
* @see `Grid1D`
|
||||
* @see `MultiGrid1D`
|
||||
*/
|
||||
class LIBKAMI_EXPORT SoloGrid1D
|
||||
: public Grid1D {
|
||||
public:
|
||||
/**
|
||||
* @brief 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
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
*/
|
||||
AgentID add_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord1D& coord
|
||||
) override;
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_SOLOGRID1D_H
|
||||
@@ -1,26 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_SOLOGRID1D_HPP
|
||||
#define KAMI_SOLOGRID1D_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/grid1d.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
|
||||
namespace kami {
|
||||
|
||||
class KAMI_EXPORT SoloGrid1D : public Grid1D {
|
||||
public:
|
||||
SoloGrid1D(unsigned int, bool);
|
||||
|
||||
bool addAgent(AgentID, GridCoord1D);
|
||||
};
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_SOLOGRID1D_HPP
|
||||
83
include/kami/sologrid2d.h
Normal file
83
include/kami/sologrid2d.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*-
|
||||
* Copyright (c) 2020 The Johns Hopkins University Applied Physics
|
||||
* Laboratory LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_SOLOGRID2D_H
|
||||
//! @cond SuppressGuard
|
||||
#define KAMI_SOLOGRID2D_H
|
||||
//! @endcond
|
||||
|
||||
#include <kami/KAMI_EXPORT.h>
|
||||
#include <kami/agent.h>
|
||||
#include <kami/grid2d.h>
|
||||
#include <kami/kami.h>
|
||||
|
||||
namespace kami {
|
||||
|
||||
/**
|
||||
* @brief A two-dimensional grid where each cell may contain multiple agents
|
||||
*
|
||||
* @details The grid is linear and may wrap around in either dimension.
|
||||
*
|
||||
* @see `Grid2D`
|
||||
* @see `MultiGrid2D`
|
||||
*/
|
||||
class LIBKAMI_EXPORT SoloGrid2D
|
||||
: public Grid2D {
|
||||
public:
|
||||
/**
|
||||
* @details 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
|
||||
);;
|
||||
|
||||
/**
|
||||
* @details 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
|
||||
*/
|
||||
AgentID add_agent(
|
||||
AgentID agent_id,
|
||||
const GridCoord2D& coord
|
||||
) override;
|
||||
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_SOLOGRID2D_H
|
||||
@@ -1,28 +0,0 @@
|
||||
/*-
|
||||
* TODO FILEHEADER
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef KAMI_SOLOGRID2D_HPP
|
||||
#define KAMI_SOLOGRID2D_HPP
|
||||
|
||||
#include <kami/KAMI_EXPORT.hpp>
|
||||
#include <kami/agent.hpp>
|
||||
#include <kami/domain.hpp>
|
||||
#include <kami/grid.hpp>
|
||||
#include <kami/grid2d.hpp>
|
||||
#include <kami/kami.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace kami {
|
||||
|
||||
class KAMI_EXPORT SoloGrid2D : public Grid2D {
|
||||
public:
|
||||
SoloGrid2D(unsigned int, unsigned int, bool, bool);
|
||||
|
||||
bool addAgent(AgentID, GridCoord2D);
|
||||
};
|
||||
|
||||
} // namespace kami
|
||||
|
||||
#endif // KAMI_SOLOGRID2D_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user