259 Commits
0.2.0 ... main

Author SHA1 Message Date
James P. Howard, II
568a5f6f5d Merge branch 'release/0.7.2' 2023-01-22 21:45:26 -05:00
James P. Howard, II
ffe25478c1 chore(version): Bump to version 0.7.2 2023-01-22 21:45:20 -05:00
James P. Howard, II
f10bc39cce docs(sphinx): Fix version numbers in Python requirements 2023-01-22 21:41:02 -05:00
James P. Howard, II
5a0f76f7fa docs(doxygen): Automate version numbering 2023-01-22 21:34:27 -05:00
James P. Howard, II
da5347b102 docs(doxygen): Cleanup doxygen config 2023-01-22 21:26:12 -05:00
James P. Howard, II
dcbfddad13 chore(docs): Update changelog for continuous domains 2023-01-22 21:17:36 -05:00
James P. Howard, II
7e3052bac0 chore(docs): Intro note in changelog 2023-01-22 21:14:54 -05:00
James P. Howard, II
14b244586c Merge branch 'release/0.7.1' into develop 2023-01-22 21:04:50 -05:00
James P. Howard, II
eacac535ab Merge branch 'release/0.7.1' 2023-01-22 21:04:42 -05:00
James P. Howard, II
cdce9feb51 chore(version): Bump to version 0.7.1 2023-01-22 21:04:37 -05:00
James P. Howard, II
4602d87024 docs(pdf): Remove latex build 2023-01-22 21:03:21 -05:00
James P. Howard, II
8f658dc5ca Merge branch 'release/0.7.0' into develop 2023-01-22 20:49:44 -05:00
James P. Howard, II
597bb298eb Merge branch 'release/0.7.0' 2023-01-22 20:49:34 -05:00
James P. Howard, II
60018c2bce chore(version): Bump to version 0.7.0 2023-01-22 20:49:28 -05:00
James P. Howard, II
74905d04a5 style(tests): automatic reformatting 2023-01-22 20:47:29 -05:00
James P. Howard, II
adec433bce style(source): automatic reformatting 2023-01-22 20:46:34 -05:00
James P. Howard, II
431a4ac8cf style(includes): automatic reformatting 2023-01-22 20:45:46 -05:00
James P. Howard, II
e56c257707 style(examples): automatic reformatting 2023-01-22 20:44:55 -05:00
James P. Howard, II
8cf2193f7c docs(changelog): Updates to changelog for tutorial 2023-01-22 20:42:44 -05:00
James P. Howard, II
dacb7d38de Merge branch 'feature/tutorial' into develop 2023-01-22 20:37:37 -05:00
James P. Howard, II
62e80ed547 docs(tutorial): Add the long-awaited tutorial 2023-01-22 20:33:54 -05:00
James P. Howard, II
e02b339055 docs(minimal): Create a minimal example
This is even more elementary than the starter model and is for use in the tutorial
2023-01-22 19:55:37 -05:00
James P. Howard, II
3af8d8b8e0 chore(docs): We use main, not master 2023-01-21 21:56:18 -05:00
James P. Howard, II
2e212ad5c6 chore(admin): Updated copyrights for 2023 2023-01-21 21:54:07 -05:00
James P. Howard, II
426f1b740d docs(examples): Additional updates for documentation 2023-01-21 21:52:54 -05:00
James P. Howard, II
0d75e3b691 docs(examples): Added documentation for each example 2023-01-21 21:50:01 -05:00
James P. Howard, II
9d27ec927d docs: About ABMs section
Created new about ABMs section using ChatGPT
2023-01-21 20:56:50 -05:00
James P. Howard, II
91fdb5fc68 docs(constants): Fix documentation for constants 2023-01-20 10:56:36 -05:00
James P. Howard, II
c08f9509e5 docs(gridx): Remove documentation for nonexistent option 2023-01-20 10:50:51 -05:00
James P. Howard, II
2ead0b30e0 docs(reporters): Add documentation for reporters
Add documentation for reporters, related classes ReporterModel and ReporterAgent, and the associated calls in the schedulers
2023-01-20 10:49:40 -05:00
James P. Howard, II
3e88c87644 docs(exceptions): Document exceptions 2023-01-20 10:48:42 -05:00
James P. Howard, II
003c3e1be0 chore(doxygen): Remove unused options to suppress warnings 2023-01-20 10:37:52 -05:00
James P. Howard, II
f333f96bca fix(hexgrid): Removing hexgrid
Hexgrids are not currently functional, so it is being removed
2023-01-19 08:46:44 -05:00
James P. Howard, II
5d58df48b2 build(cmake): automate selection of sources files
Use globbing to get the sources files for each example and the library
2023-01-18 23:35:21 -05:00
James P. Howard, II
022f9e31aa Added update to changelog 2022-09-21 11:46:19 -04:00
James P. Howard, II
ad9dbf3eb2 Updates to citations 2022-09-21 11:45:30 -04:00
James P. Howard, II
0f1f1ad41a Generalize coordinates to location 2022-09-16 16:51:41 -04:00
James P. Howard, II
f0295e9891 Rename exceptions to follow NounAdjective convention 2022-09-16 16:49:35 -04:00
James P. Howard, II
8f7b6b65c2 Unit test revisions for exception-handling 2022-09-16 16:47:17 -04:00
James P. Howard, II
80ac9571a7 Renamed kami::exception to kami::error to avoid conflicts with std::expection 2022-09-16 16:32:13 -04:00
James P. Howard, II
7a7db768ed Remove code redundancies 2022-09-10 23:07:38 -04:00
James P. Howard, II
9eb47c8656 Move to exception-based error handling 2022-09-09 22:12:42 -04:00
James P. Howard, II
2aeef72f19 Grid distance API changes 2022-09-07 21:46:41 -04:00
James P. Howard, II
552d8fc725 Updated Reporter documentation 2022-09-07 21:46:01 -04:00
James P. Howard, II
8050ce9b8f Remove unnecessary includes from examples 2022-09-03 22:05:33 -04:00
James P. Howard, II
317509ce0b Rename x/y accessors 2022-09-03 22:01:15 -04:00
James P. Howard, II
e1028a377d Grid and domain cleanup and documentation updates 2022-09-03 21:56:32 -04:00
James P. Howard, II
860e367785 Correction to Jenny's Constant 2022-09-03 21:54:31 -04:00
James P. Howard, II
445e10252e Separate all method declarations from definitions 2022-09-03 21:54:31 -04:00
James P. Howard, II
a08b316b96 New step documentation 2022-09-01 11:39:29 -04:00
James P. Howard, II
893c8da8e2 Refactor get_neighborhood 2022-09-01 11:38:51 -04:00
James P. Howard, II
10cb3cf3f3 Added env=Debug to CodeQL 2022-08-29 22:15:28 -04:00
James P. Howard, II
3ed40f4cdb Rework CodeQL build steps based on build-develop 2022-08-29 22:10:43 -04:00
James P. Howard, II
003e7a4d12 Add develop to CodeQL 2022-08-29 22:07:21 -04:00
James P. Howard, II
6751951e84 Add CodeQL analysis 2022-08-29 21:55:56 -04:00
James P. Howard, II
7def091083 Remove the hash method from the coordinate types from the documentation 2022-08-29 15:20:06 -04:00
James P. Howard, II
a872c89b78 Added CFF file 2022-08-29 11:41:40 -04:00
James P. Howard, II
b573a3f676 Add package DOI 2022-08-29 11:06:44 -04:00
James P. Howard, II
d2ccdbea73 Make CTidy happy 2022-08-28 20:14:34 -04:00
James P. Howard, II
b9b1cb12e6 Let's start a Position for generic coords 2022-08-28 18:07:29 -04:00
James P. Howard, II
948f744414 Starting hexgrids 2022-08-28 18:06:25 -04:00
James P. Howard, II
06355bdf67 Updates to the testing code 2022-08-28 17:43:36 -04:00
James P. Howard, II
a215ca7320 Reporter agent test code 2022-08-28 16:56:48 -04:00
James P. Howard, II
097024a6b8 Reworked the agent and staged agent tests 2022-08-28 16:41:47 -04:00
James P. Howard, II
a0c2a7869c Reporter testing 2022-08-28 15:41:22 -04:00
James P. Howard, II
a45b9bf22d This file is gone 2022-08-26 23:48:25 -04:00
James P. Howard, II
7849a49355 Documentation updates: changelog.rst and todo.rst 2022-08-26 23:42:04 -04:00
James P. Howard, II
f86dbd4c24 Implementation of the Bank Reserves Model, including some reworking of everything else necessary, also, a partial unit test 2022-08-26 23:32:23 -04:00
James P. Howard, II
cdc9c56765 Let's add a default step method to the Model class 2022-08-24 13:46:12 -04:00
James P. Howard, II
972e83aeeb Create distance measures for the orthogonal grids 2022-08-24 13:45:39 -04:00
James P. Howard, II
922572973d Add some useful constants 2022-08-24 13:44:53 -04:00
James P. Howard, II
8906825235 We're going back to mt19937 as ranlux24 is slow 2022-08-24 13:44:15 -04:00
James P. Howard, II
64dc35c9c4 First blush on the reporter interface. No tests and no working examples yet... 2022-08-21 19:09:15 -04:00
James P. Howard, II
6c34098b53 Add Chebyshev distance constant 2022-08-21 11:41:47 -04:00
James P. Howard, II
bc0740219f Make shared_ptrs that can be unique, unique 2022-08-20 11:45:42 -04:00
James P. Howard, II
11660de09c Merge branch 'feature/reporters' into develop 2022-08-19 21:51:08 -04:00
James P. Howard, II
3b3a7f0bca Merge branch 'release/0.6.0' into develop 2022-08-19 20:58:14 -04:00
James P. Howard, II
d4db95f925 Merge branch 'release/0.6.0' 2022-08-19 20:57:58 -04:00
James P. Howard, II
0727030bcb Bump the version to 0.6.0 2022-08-19 20:57:47 -04:00
James P. Howard, II
85aede0721 We can be a little less circumspect in the testing 2022-08-19 20:56:12 -04:00
James P. Howard, II
06e98b1f94 Add build=missing to the Github workflow for Conan 2022-08-19 20:44:42 -04:00
James P. Howard, II
8613bc29b3 Added a to do list of things that should be done 2022-08-19 20:41:11 -04:00
James P. Howard, II
67cdf9bc29 Whitespace 2022-08-19 20:28:07 -04:00
James P. Howard, II
e7a5f342bf Updates to the Starter example reflecting Model changes 2022-08-19 20:27:50 -04:00
James P. Howard, II
9333e1c2fa Schedulers tests 2022-08-19 20:27:04 -04:00
James P. Howard, II
f18e2c99da Simplify the interface to random. I really have no idea why I let you set the RNG later, anyway. 2022-08-19 20:26:29 -04:00
James P. Howard, II
d884e603cb You know, there is no reason Model has to define the step/run interface
The user can do that for themselves
2022-08-19 19:21:43 -04:00
James P. Howard, II
78aca204f4 add using namespace kami to unit tests 2022-08-19 15:45:27 -04:00
James P. Howard, II
50b147beca Draft Population unit tests 2022-08-18 22:00:37 -04:00
James P. Howard, II
3dff3afb6e Automatically use all .cc files as tests 2022-08-18 18:17:47 -04:00
James P. Howard, II
80f98bdde0 Correction to examples readme 2022-08-18 16:57:27 -04:00
James P. Howard, II
72f0074d81 Completed first generation of unit tests on the grids 2022-08-18 16:56:16 -04:00
James P. Howard, II
f6967d0ec3 Versions of all supporting packages made current 2022-08-16 20:49:54 -04:00
James P. Howard, II
318f6dfecf Move dependencies for the examples to the examples' cmakelists 2022-08-16 11:34:53 -04:00
James P. Howard, II
05995525f1 Simplify overview in documentation 2022-08-12 13:40:56 -04:00
James P. Howard, II
d1ba71b416 Merge branch 'release/0.5.1' into develop 2022-08-11 22:21:23 -04:00
James P. Howard, II
13185c1e0b Merge branch 'release/0.5.1' 2022-08-11 22:21:14 -04:00
James P. Howard, II
beb6a1d99b Bump version number and date 2022-08-11 22:20:38 -04:00
James P. Howard, II
a801720aa5 Agent reporter sketch 2022-08-11 22:17:01 -04:00
James P. Howard, II
8a1ac91fae Add start for multigrid unit tests 2022-08-11 22:15:11 -04:00
James P. Howard, II
7c6fdd0b11 Add information to the README 2022-08-11 22:11:00 -04:00
James P. Howard, II
82d96676d7 Some cleanups to cmake build process 2022-08-11 22:10:27 -04:00
James P. Howard, II
40cbaced51 Correction to documentation badge 2022-08-08 17:37:27 -04:00
James P. Howard, II
2351e6f23e Add Model to tests 2022-08-08 17:34:20 -04:00
James P. Howard, II
018379554d Fix labels in StagedAgent unit tests 2022-08-08 17:34:20 -04:00
James P. Howard, II
0f8ee56948 Merge branch 'release/0.5.0' 2022-08-08 16:18:44 -04:00
James P. Howard, II
237be8bbe8 Grid modernization 2022-08-08 09:18:56 -04:00
James P. Howard, II
e21da48f5a Change pointer cast to static 2022-08-07 14:59:06 -04:00
James P. Howard, II
e19dc7b449 Add unit testing for Model 2022-08-07 14:56:42 -04:00
James P. Howard, II
d52102615c Cleanup and align return values from Model 2022-08-05 21:43:16 -04:00
James P. Howard, II
d1b6c60ec6 Apparently under Linux, gtest needs pthreads 2022-08-04 22:31:16 -04:00
James P. Howard, II
0d00c3ec40 Fully qualify the spdlog linking in the examples 2022-08-04 22:23:22 -04:00
James P. Howard, II
25b14c8aff Add new unit tests for Agent and AgentID 2022-08-04 22:12:42 -04:00
James P. Howard, II
2d88d32bd6 Comment alignment fix 2022-08-04 22:09:39 -04:00
James P. Howard, II
0015cdbd5a Start building a unit test framework 2022-08-04 22:09:11 -04:00
James P. Howard, II
7a335feae2 Move the version information into an anonymous namespace
This effectively makes it a private member of the class.
2022-08-04 22:06:39 -04:00
James P. Howard, II
8742637ac8 Suppress documentation for include guards and additional
documentation fixes

Did this the long way. The documentation for Doxygen says
I should be able to hide those defines with a single knob.
However, I cannot make it work.  So each one is now filtered
out individually.
2022-08-04 16:57:22 -04:00
James P. Howard, II
2f6c26406a Remove warning about CMAKE_C_COMPILER 2022-08-04 13:31:54 -04:00
James P. Howard, II
cab9c86819 Documentation revisions where appropriate 2022-08-04 12:38:29 -04:00
James P. Howard, II
743c388fb3 autofy version string creation 2022-08-04 11:35:26 -04:00
James P. Howard, II
cc7cf670bb Add dummy c'stor and d'stor to the starter example 2022-08-04 10:07:44 -04:00
James P. Howard, II
c91caf723e Added starter example 2022-08-03 09:28:03 -04:00
James P. Howard, II
c25d73b56e Documentation revisions 2022-08-02 21:01:48 -04:00
James P. Howard, II
f7bf234f6a Make these new style iterators 2022-08-02 20:57:04 -04:00
James P. Howard, II
55b819ac8c Clean up model returns 2022-08-02 20:50:05 -04:00
James P. Howard, II
ec28727ed9 Clean up population returns 2022-08-02 20:25:36 -04:00
James P. Howard, II
a8c4212b94 Remove void returns from scheduler-related classes 2022-08-02 20:07:46 -04:00
James P. Howard, II
fa74943eb5 Remove void returns from agent-related classes 2022-08-02 19:51:33 -04:00
James P. Howard, II
6320f2d6da Cleanups to the staged scheduler documentation 2022-08-02 19:38:19 -04:00
James P. Howard, II
f8e26344c1 Remove an errant internal model from Agent 2022-08-02 19:36:41 -04:00
James P. Howard, II
95165f4d72 Cleanups and updates to all of the documentation 2022-08-02 19:30:57 -04:00
James P. Howard, II
3faa5b4c50 Remove "maybe unused" as that is not helping 2022-08-02 19:09:05 -04:00
James P. Howard, II
cddf317ee6 Remove internal model references in schedulers 2022-08-02 15:29:22 -04:00
James P. Howard, II
f87f9850d9 Remove internal model references from populations 2022-08-02 14:29:20 -04:00
James P. Howard, II
e82b08e8f8 Remove unused stdio.h 2022-08-02 14:26:58 -04:00
James P. Howard, II
10c42ec2fe Remove model from agent, add it to step() and advance() methods 2022-08-02 14:26:10 -04:00
James P. Howard, II
084eda63f3 Updates to population definition 2022-08-02 14:20:57 -04:00
James P. Howard, II
1c60e90514 Reformatting grid.h 2022-08-02 10:33:05 -04:00
James P. Howard, II
9791cd6d8b Make RNG ranlux24 2022-08-02 10:29:40 -04:00
James P. Howard, II
e1c83d9158 Fix the virtualization of the Domain class 2022-07-16 18:38:44 -04:00
James P. Howard, II
9bdde03463 Started rebuilding the interface around Population requirements 2022-07-09 13:48:01 -04:00
James P. Howard, II
f5ae008df5 Rearrange header files and remove using namespaces to comply with Google recommendations 2022-07-01 17:50:48 -04:00
James P. Howard, II
cf0b75c5fb Additional support for semver to query the version 2022-07-01 17:18:10 -04:00
James P. Howard, II
cf35c348ca Updates to changelog 2022-06-18 12:35:56 -04:00
James P. Howard, II
b5abb50892 Remove Travis and Gitlab CIs 2022-06-17 21:25:58 -04:00
James P. Howard, II
1d192c99f6 Remove cppcheck 2022-06-17 21:25:24 -04:00
James P. Howard, II
b9a41e08a3 Revise package copyright years 2022-06-17 21:20:36 -04:00
James P. Howard, II
52191803ef Redo versioning with neargye-semver 2022-06-17 21:13:05 -04:00
James P. Howard, II
9859000182 Make library static by default 2022-06-17 21:12:01 -04:00
James P. Howard, II
cc189f80c5 Example and test building cleanups 2022-06-17 21:09:16 -04:00
James P. Howard, II
ddf96401c5 Correct the URL in conanfile.py 2022-06-16 21:13:53 -04:00
James P. Howard, II
a5d3f8b1ad Add IDEA files to gitconfig 2022-06-16 21:12:19 -04:00
James P. Howard, II
7af8e59b96 Corrected the badge link in the README file 2021-09-25 21:20:42 -04:00
James P. Howard, II
8747b22310 Merge branch 'hotfix/0.4.2' into develop 2021-09-25 21:14:01 -04:00
James P. Howard, II
8d9b217298 Merge branch 'hotfix/0.4.2' 2021-09-25 21:13:31 -04:00
James P. Howard, II
7567ee7f36 Bump version to 0.4.2 2021-09-25 21:13:01 -04:00
James P. Howard, II
c7685f03b7 Patches to changelog 2021-09-25 21:12:35 -04:00
James P. Howard, II
715d4e0f7b Merge branch 'hotfix/0.4.1' into develop 2021-09-25 20:53:04 -04:00
James P. Howard, II
01d8154017 Merge branch 'hotfix/0.4.1' 2021-09-25 20:52:45 -04:00
James P. Howard, II
c145466758 Added support for README links 2021-09-25 20:52:37 -04:00
James P. Howard, II
7d53af7bdf Merge branch 'release/0.4.0' into develop 2021-09-25 19:39:12 -04:00
James P. Howard, II
d7cd7bcfc4 Merge branch 'release/0.4.0' 2021-09-25 19:39:02 -04:00
James P. Howard, II
98959520ea Bump version to 0.4.0 2021-09-25 19:38:49 -04:00
James P. Howard, II
42c87ccccd Merge branch 'hotfix/0.3.1' into develop 2021-09-25 19:34:08 -04:00
James P. Howard, II
ba0ae24cfc Merge branch 'hotfix/0.3.1' 2021-09-25 19:33:57 -04:00
James P. Howard, II
e2c825e2e6 Version bump to 0.3.1 2021-09-25 19:33:51 -04:00
James P. Howard, II
c7f4c706cd Separate build workflows for CI 2021-09-25 19:28:46 -04:00
James P. Howard, II
584c2b94d8 The CLion linter is a beast 2021-09-25 12:35:45 -04:00
James P. Howard, II
b02efaae07 Added missing copyrights 2021-09-24 13:58:20 -04:00
James P. Howard, II
087bdadc16 Updated changelog 2021-09-23 22:09:41 -04:00
James P. Howard, II
2027ff05eb Reworked Overview and TOC 2021-09-23 15:38:00 -04:00
James P. Howard, II
15647b905f Added the index to the TOC 2021-09-23 13:48:23 -04:00
James P. Howard, II
f0ce59c967 Pull out the links into a more native RST format 2021-09-23 13:46:20 -04:00
James P. Howard, II
7af69815f3 Not Markdown 2021-09-23 13:42:40 -04:00
James P. Howard, II
25febcb094 Fleshed out introduction text 2021-09-23 13:40:26 -04:00
James P. Howard, II
52bb8bb900 Finished requirements section 2021-09-21 21:26:09 -04:00
James P. Howard, II
f3f2b00740 Move releases to released version 2021-09-21 21:16:21 -04:00
James P. Howard, II
1200fb4de0 Added blank like to support changelog processing on RTD 2021-09-21 21:13:00 -04:00
James P. Howard, II
fb5d222915 Rebuild the changelog management process 2021-09-21 20:59:48 -04:00
James P. Howard, II
30fdd46d93 Start installation instructions in Markdown 2021-09-21 20:58:47 -04:00
James P. Howard, II
f474d6feff Add documentation for kami::RandomScheduler 2021-09-21 20:10:40 -04:00
James P. Howard, II
caf6d01b58 Add a changelog link 2021-09-20 21:25:20 -04:00
James P. Howard, II
44c541a4f8 Add a changelog 2021-09-20 21:17:09 -04:00
James P. Howard, II
0edd940344 Removing conancenter badge until ready to go on conancenter 2021-09-20 11:33:45 -04:00
James P. Howard, II
10f33b5f61 Add license information badges 2021-09-20 11:17:45 -04:00
James P. Howard, II
b6406b86d8 There's still a broken reference to SPDLOG here 2021-09-20 11:07:31 -04:00
James P. Howard, II
54f49a732c Add installation directions 2021-09-20 11:03:41 -04:00
James P. Howard, II
f2601ea85f Anchors aweigh! I really need to learn restructured text. 2021-09-20 10:58:17 -04:00
James P. Howard, II
b9c7f9b605 Remove alt text and add test badge 2021-09-20 10:43:19 -04:00
James P. Howard, II
d13960da35 Corrections to index badges 2021-09-20 10:37:44 -04:00
James P. Howard, II
24daa26bc6 Merge branch 'release/v0.3.0' 2021-09-20 10:33:08 -04:00
James P. Howard, II
c0daf3d07e Removed markup trash 2021-09-20 10:30:23 -04:00
James P. Howard, II
58b1e07744 Update breath 2021-09-20 10:24:56 -04:00
James P. Howard, II
2759864e5c Added Sphinx Bootstrap 2021-09-20 10:21:12 -04:00
James P. Howard, II
62cabc52c9 Fix release shield...copied without correcting from spdlog 2021-09-20 09:43:39 -04:00
James P. Howard, II
8aed4266d1 Update badges 2021-09-20 08:59:48 -04:00
James P. Howard, II
0021466fac Fix version number 2021-09-16 22:01:49 -04:00
James P. Howard, II
50bea16026 Synchronize the examples build files 2021-09-16 21:21:19 -04:00
James Howard
caad12fc79 Add some badges 2021-09-17 01:05:33 +00:00
James Howard
ff0649f6f3 Do not specify the test directory and drop install 2021-09-17 00:55:34 +00:00
James Howard
1155fdea36 General cleanup for CI 2021-09-17 00:53:38 +00:00
James Howard
272ec5a030 Add documenteer 2021-09-17 00:37:22 +00:00
James Howard
57f4cc4d1d Specify breath version 2021-09-17 00:33:02 +00:00
James Howard
1692b99ff5 Rework conan init 2021-09-17 00:25:19 +00:00
James Howard
716d515f3e Add default arch 2021-09-17 00:08:08 +00:00
James Howard
c813193e9c Add default compiler 2021-09-17 00:03:16 +00:00
James Howard
ccbeedbf4b Add default compiler 2021-09-17 00:02:08 +00:00
James Howard
4df9030514 Remove Clang 2021-09-16 23:56:16 +00:00
James Howard
1cdf75276d Add Conan profile configuration 2021-09-16 23:54:41 +00:00
James Howard
c22ecb2777 Add Clang install to test build 2021-09-16 18:26:49 +00:00
James Howard
17602e5130 Update build.yml
Reconfigure the build environment
2021-09-16 10:14:19 -04:00
James P. Howard, II
5c85571b72 Add MyST-Parser 2021-09-16 08:58:48 -04:00
James P. Howard, II
cdf50bbea7 Fix RTD build requirement 2021-09-16 08:56:38 -04:00
James P. Howard, II
8803a09cb4 Added Documenteer 2021-09-16 08:44:01 -04:00
James P. Howard, II
8f98db2ff0 Update the license to the correct info! 2021-09-16 08:35:37 -04:00
James P. Howard, II
78131e9e7d Add readthedocs config file 2021-09-16 08:35:18 -04:00
James P. Howard, II
a93d8e566f Updates to the conanfile 2021-07-20 13:39:14 -04:00
James P. Howard, II
c4f369407b Updates to documentation 2021-07-20 12:16:06 -04:00
James P. Howard, II
382e074b7e New RNG 2021-07-20 12:15:33 -04:00
James P. Howard, II
2735cef23e Standardize the documentation format 2021-07-15 13:13:15 -04:00
James P. Howard, II
bf56389a73 Rebuilt random scheduler with shared RNG 2021-07-14 21:52:30 -04:00
James P. Howard, II
5fd5661bad Correct capitalization 2021-07-12 19:55:30 -04:00
James P. Howard, II
0789d88f82 Fixes on Sphinx build...look at that 2021-07-12 19:45:52 -04:00
James P. Howard, II
390ce0cbd9 Remove kamidata 2021-07-12 19:44:59 -04:00
James P. Howard, II
47c141710f Corrections to missing documentation 2021-07-12 17:40:43 -04:00
James P. Howard, II
ca5dcfea59 Major reorganization 2021-07-12 16:55:06 -04:00
James P. Howard, II
394891a325 Added GitHub action for build test 2021-07-12 15:50:00 -04:00
James P. Howard, II
70b90bec01 New documentation for Coord, Domain, and output function for Coord 2021-04-17 22:58:59 -04:00
James P. Howard, II
ce9829a086 Updated documentation for agent 2021-04-17 22:48:50 -04:00
James P. Howard, II
04bfa96059 Added vscode to gitignore 2021-03-26 20:48:35 -04:00
James P. Howard, II
077e7df773 Starting to flush out the grid and domain cores 2020-12-27 14:31:05 -05:00
James P. Howard, II
175c1edda8 Refactoring of the schedulers 2020-12-23 17:31:47 -05:00
James P. Howard, II
fcc177db7c Refactored agents 2020-12-23 17:00:09 -05:00
James P. Howard, II
4a8947b62d Refactored the random scheduler 2020-12-14 17:35:55 -05:00
James P. Howard, II
ab0d0bdcc0 Simplify two-stage agents and models 2020-12-14 15:42:28 -05:00
James P. Howard, II
6b02d5ba1a Remove excess spaces at end of files 2020-12-14 15:17:24 -05:00
James P. Howard, II
573b75dc27 Added license information 2020-12-14 15:13:16 -05:00
James P. Howard, II
60ff21519c Removed redundant deconstructor from Agent 2020-12-14 15:04:51 -05:00
James P. Howard, II
6e3f814ce2 Rename the distance measures...in case I ever decide to use them 2020-12-14 15:02:04 -05:00
James P. Howard, II
213d60f4b3 Removing redundant code in kami.cc 2020-12-13 20:30:47 -05:00
James P. Howard, II
611f4c8de9 Adding parameter names to class definition 2020-12-13 20:30:26 -05:00
James P. Howard, II
dcd960d1ed Renamed head guards for consistency 2020-12-13 20:23:59 -05:00
James P. Howard, II
e2338e1337 Reorganization of libkami 2020-11-19 21:48:27 -05:00
James P. Howard, II
4469e4c36c Make fmt dependency explicit 2020-11-19 20:45:14 -05:00
James P. Howard, II
571732f13c Add Coord for later use 2020-11-19 20:16:25 -05:00
James P. Howard, II
4702cfe8d3 Move from .cpp/.hpp to .cc/.h 2020-11-19 19:42:15 -05:00
James P. Howard, II
5e9389e1b3 Added seed selection to the RandomScheduler and support for using it to the 2D BWM 2020-10-13 10:58:48 -04:00
James P. Howard, II
fc0f1a1e52 Added a macro for KAMI_VERSION_STRING 2020-10-12 21:02:50 -04:00
James P. Howard, II
93f91836a4 Casual cleanups for the conan information 2020-10-12 21:01:54 -04:00
James P. Howard, II
7298fa7729 Add conan install to travis build process 2020-10-03 18:57:36 -04:00
James P. Howard, II
dfff3243bd Add conan install to build process 2020-10-03 18:41:59 -04:00
James P. Howard, II
f038242d9b Add latest cmake to download on Travis... 2020-10-03 18:36:24 -04:00
James P. Howard, II
0fbb972e9c Rewrite travis build process from scratch 2020-10-03 18:17:19 -04:00
James P. Howard, II
3809a417c9 Switch python Travis to python 3 2020-10-03 17:46:25 -04:00
James P. Howard, II
0d5fa3f39e Added sphinx to Travis build 2020-10-03 17:39:02 -04:00
James P. Howard, II
ffb67e6da3 Add standardized logging to the examples and test codes 2020-10-03 17:33:31 -04:00
James P. Howard, II
41a1e9edbe Add doxygen to Travis config 2020-09-30 22:03:00 -04:00
James P. Howard, II
e9ca6477d4 Fixed a header mistake 2020-09-30 22:02:36 -04:00
James P. Howard, II
f38a69af4b Merge branch 'release/v0.2.0' into develop 2020-09-29 21:16:56 -04:00
155 changed files with 11891 additions and 3967 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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
View 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
View 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
View File

@@ -38,3 +38,10 @@ build/*
# Qtcreator files
*.user
# VSCode files
.vscode
# IDEA files
.idea
cmake-build-*

View File

@@ -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
View 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

View File

@@ -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
View 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

View File

@@ -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
View 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.

View File

@@ -1,25 +1,44 @@
[![Build (main)](https://github.com/JHUAPL/kami/actions/workflows/build-main.yml/badge.svg)](https://github.com/JHUAPL/kami/actions/workflows/build-main.yml)
[![Build (develop)](https://github.com/JHUAPL/kami/actions/workflows/build-develop.yml/badge.svg)](https://github.com/JHUAPL/kami/actions/workflows/build-develop.yml)
[![Documentation status](https://readthedocs.org/projects/kami/badge/?version=main)](https://kami.readthedocs.io/en/main/)
[![Release status](https://img.shields.io/github/release/JHUAPL/kami.svg)](https://github.com/JHUAPL/kami/releases)
![License](https://img.shields.io/github/license/JHUAPL/kami)
[![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.6975259-success.svg)](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>>

View File

@@ -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)

View File

@@ -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
)

View File

@@ -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")

View File

@@ -1,6 +0,0 @@
[requires]
spdlog/1.7.0
cli11/1.9.1
[generators]
cmake

View File

@@ -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()

View File

@@ -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
View 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
View 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::

View File

@@ -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

View 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::

View 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::

View 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
View 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
View 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::

View File

@@ -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
View 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
View 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::

View File

@@ -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
View 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
View 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::

View File

@@ -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.

View 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})

View 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

View 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

View 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);
}
}

View 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();
}

View File

@@ -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})

View 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

View File

@@ -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();
}

View 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

View File

@@ -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

View File

@@ -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})

View 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

View File

@@ -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();
}

View 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

View File

@@ -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

View File

@@ -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})

View File

@@ -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();
}

View File

@@ -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

View 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})

View 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;
}

View 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
View 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);
}

View 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
View 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

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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
View 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
View 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

View File

@@ -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
View 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

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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
View 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

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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
View 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
View 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
View 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

View File

@@ -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
View 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
View 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

View File

@@ -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
View 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

View File

@@ -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
View 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

View File

@@ -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
View 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

View File

@@ -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