cppyabm  1.0.17
An agent-based library to integrate C++ and Python
bind_tools.h
Go to the documentation of this file.
1 #pragma once
2 #include "bases.h"
3 #include <map>
4 #include <algorithm>
5 #include "pybind11/pybind11.h"
6 #include <pybind11/stl.h>
7 #include <pybind11/stl_bind.h>
8 namespace py=pybind11;
9 #define EXPOSE_AGENT_CONTAINER(...) \
10 namespace pybind11 { namespace detail { \
11  template<> class type_caster<vector<shared_ptr<__VA_ARGS__>>> : public type_caster_base<vector<shared_ptr<__VA_ARGS__>>> { }; \
12 }}
13 #define EXPOSE_PATCH_CONTAINER(...) \
14 namespace pybind11 { namespace detail { \
15  template<> class type_caster<map<unsigned,shared_ptr<__VA_ARGS__>>> : public type_caster_base<map<unsigned,shared_ptr<__VA_ARGS__>>> { }; \
16 }}
17 
18 
19 //!Tools for exposing C++ types and functions to Python
20 namespace bind_tools{
21  //! Template trampoline for Env-based classes
22  template<class ENV, class AGENT, class PATCH>
23  struct tramEnv : public ENV {
24  using ENV::ENV;
25  shared_ptr<PATCH> generate_patch(MESH_ITEM mesh_item) override {
27  shared_ptr<PATCH>,
28  ENV,
30  mesh_item
31  );
32  }
33  shared_ptr<AGENT> generate_agent(string agent_name) override {
35  shared_ptr<AGENT>,
36  ENV,
38  agent_name
39  );
40  }
41  void update_repo() override {
43  void,
44  ENV,
46 
47  );
48  }
49  void step() override {
51  void,
52  ENV,
53  step
54 
55  );
56  }
57 
58  };
59  //! Template trampoline for Agent-based classes
60  template<class ENV, class AGENT, class PATCH>
61  struct tramAgent : AGENT {
62  using AGENT::AGENT;
63  void step() override {
65  void,
66  AGENT,
67  step
68  );
69  }
70 
71  void inherit(shared_ptr<AGENT> father) override{
73  void,
74  AGENT,
75  inherit,
76  father
77  );
78  };
79  };
80  //! Template trampoline for Patch-based classes
81  template<class ENV, class AGENT, class PATCH>
82  struct tramPatch : PATCH {
83  using PATCH::PATCH;
84  void step() override {
86  void,
87  PATCH,
88  step
89  );
90  }
91 
92  };
93  //! Expose function for Env-based classes with trampoline.
94  template<class ENV,class AGENT,class PATCH,class tramclass>
95  py::class_<ENV, tramclass,std::shared_ptr<ENV>> expose_env(py::module m, string class_name_string){
96  auto class_binds_obj =
97  py::class_<ENV,tramclass,std::shared_ptr<ENV>> (m,class_name_string.c_str(),py::dynamic_attr())
98  .def(py::init<>())
99  .def("place_agent", py::overload_cast<shared_ptr<PATCH>,shared_ptr<AGENT>>(&ENV::place_agent), "Places the agent on the given patch")
100  .def("place_agent", py::overload_cast<unsigned,shared_ptr<AGENT>>(&ENV::place_agent), "Places the agent on the given patch index")
101  .def("place_agent_randomly",&ENV::place_agent_randomly)
102  .def("setup_domain",&ENV::setup_domain)
103  .def("step_agents",&ENV::step_agents)
104  .def("step_patches",&ENV::step_patches)
105  .def("update",&ENV::update)
106  .def("step",&ENV::step)
107  .def("setup_agents",&ENV::setup_agents)
108  .def("count_agents",&ENV::count_agents)
109  .def("memory_usage",&ENV::memory_usage)
110  .def_readwrite("patches",&ENV::patches)
111  .def_readwrite("agents",&ENV::agents);
112  return class_binds_obj;
113  }
114  //! Template trampoline for Env-based classes without trampoline
115  template<class ENV,class AGENT,class PATCH>
116  py::class_<ENV,std::shared_ptr<ENV>> expose_env(py::module m, string class_name_string){
117  auto class_binds_obj =
118  py::class_<ENV,std::shared_ptr<ENV>> (m,class_name_string.c_str(),py::dynamic_attr())
119  .def(py::init<>())
120  .def("memory_usage",&ENV::memory_usage)
121  .def("place_agent_randomly",&ENV::place_agent_randomly)
122  .def("setup_domain",&ENV::setup_domain)
123  .def("step_agents",&ENV::step_agents)
124  .def("step_patches",&ENV::step_patches)
125  .def("place_agent",&ENV::place_agent)
126  .def("update",&ENV::update)
127  .def("step",&ENV::step)
128  .def("setup_agents",&ENV::setup_agents)
129  .def("count_agents",&ENV::count_agents)
130  .def("connect_patch_agent", &ENV::connect_patch_agent)
131  .def_readwrite("patches",&ENV::patches)
132  .def_readwrite("agents",&ENV::agents);
133  return class_binds_obj;
134  }
135  //! Template trampoline for Agent-based classes with trampoline
136  template<class ENV,class AGENT,class PATCH,class tramclass>
137  py::class_<AGENT, tramclass,std::shared_ptr<AGENT>> expose_agent(py::module &m, string class_name_str){
138  auto class_binds_obj = py::class_<AGENT, tramclass,std::shared_ptr<AGENT>>(m,class_name_str.c_str(),py::dynamic_attr())
139  .def(py::init<shared_ptr<ENV>,string>(),"Initialize",py::arg("env"),py::arg("class_name"))
140  .def("move",&AGENT::move,"Move the agent to a new patch",py::arg("patch")=nullptr,py::arg("quiet")=false)
141  .def("order_hatch",&AGENT::order_hatch,"Hatch request",
142  py::arg("patch")=nullptr, py::arg("inherit")=false,
143  py::arg("quiet")=false, py::arg("reset")=false)
144  .def("order_move",&AGENT::order_move,"Move request",
145  py::arg("patch")=nullptr,
146  py::arg("quiet")=false, py::arg("reset")=false)
147  .def("order_switch",&AGENT::order_switch,"Switch request",
148  py::arg("to"))
149  .def_readwrite("disappear",&AGENT::disappear)
150  .def_readwrite("env",&AGENT::env)
151  .def_readwrite("patch",&AGENT::patch)
152  .def_readwrite("disappear",&AGENT::disappear)
153  .def_readwrite("class_name",&AGENT::class_name);
154  return class_binds_obj;
155  }
156  //! Template trampoline for Agent-based classes without trampoline
157  template<class ENV,class AGENT,class PATCH>
158  py::class_<AGENT,std::shared_ptr<AGENT>> expose_agent(py::module &m, string class_name_str){
159  auto class_binds_obj = py::class_<AGENT, std::shared_ptr<AGENT>>(m,class_name_str.c_str(),py::dynamic_attr())
160  .def(py::init<shared_ptr<ENV>,string>(),"Initialize",py::arg("env"),py::arg("class_name"))
161  .def("move",&AGENT::move,"Move the agent to a new patch",py::arg("patch")=nullptr,py::arg("quiet")=false)
162  .def("order_hatch",&AGENT::order_hatch,"Hatch request",
163  py::arg("patch")=nullptr, py::arg("inherit")=false,
164  py::arg("quiet")=false, py::arg("reset")=false)
165  .def("order_move",&AGENT::order_move,"Move request",
166  py::arg("patch")=nullptr,
167  py::arg("quiet")=false, py::arg("reset")=false)
168  .def("order_switch",&AGENT::order_switch,"Switch request",
169  py::arg("to"))
170  .def_readwrite("disappear",&AGENT::disappear)
171  .def_readwrite("env",&AGENT::env)
172  .def_readwrite("patch",&AGENT::patch)
173  .def_readwrite("disappear",&AGENT::disappear)
174  .def_readwrite("class_name",&AGENT::class_name);
175  return class_binds_obj;
176  }
177 
178  //! Template trampoline for Patch-based classes with trampoline
179  template<class ENV,class AGENT,class PATCH,class tramclass>
180  py::class_<PATCH,tramclass,std::shared_ptr<PATCH>> expose_patch(py::module &m, string class_name_ptr){
181  auto class_binds_obj = py::class_<PATCH,tramclass,std::shared_ptr<PATCH>>(m,class_name_ptr.c_str(),py::dynamic_attr())
182  .def(py::init<shared_ptr<ENV>,MESH_ITEM>())
183  .def("empty_neighbor", &PATCH::empty_neighbor,"Return an empty patch around the patch",
184  py::arg("quiet")=false)
185  .def("find_neighbor_agents",&PATCH::find_neighbor_agents,"Returns a vector of agents in one patch neighborhood",
186  py::arg("include_self")=true)
187  .def_readwrite("index",&PATCH::index)
188  .def_readwrite("coords",&PATCH::coords)
189  .def("get_agent",&PATCH::get_agent)
190  .def("empty",&PATCH::empty)
191  .def_readwrite("on_border",&PATCH::on_border)
192  .def_readwrite("neighbors",&PATCH::neighbors);
193  return class_binds_obj;
194 
195  }
196  //! Template trampoline for Patch-based classes without trampoline
197  template<class ENV,class AGENT,class PATCH>
198  py::class_<PATCH,std::shared_ptr<PATCH>> expose_patch(py::module &m, string class_name_ptr){
199  auto class_binds_obj = py::class_<PATCH,std::shared_ptr<PATCH>>(m,class_name_ptr.c_str(),py::dynamic_attr())
200  .def(py::init<shared_ptr<ENV>,MESH_ITEM>())
201  .def("empty_neighbor", &PATCH::empty_neighbor,"Return an empty patch around the patch",
202  py::arg("quiet")=false)
203  .def("find_neighbor_agents",&PATCH::find_neighbor_agents,"Returns a vector of agents in one patch neighborhood",
204  py::arg("include_self")=true)
205  .def_readwrite("coords",&PATCH::coords)
206  .def("get_agent",&PATCH::get_agent)
207  .def("empty",&PATCH::empty)
208  .def_readwrite("on_border",&PATCH::on_border)
209  .def_readwrite("neighbors",&PATCH::neighbors);
210  return class_binds_obj;
211 
212  }
213  //! function to expose exceptions
215  py::register_exception<patch_availibility>(m, "patch_availibility");
216  py::register_exception<undefined_member>(m, "undefined_member");
217 
218  }
219  //! function to expose mesh items
221  py::class_<MESH_ITEM>(m,"MESH_ITEM")
222  .def(py::init<>());
223  auto space_sub = m.def_submodule("space");
224  space_sub.def("grid2",&space::grid2,"Creates 3D grid mesh", py::arg("length"), py::arg("width"), py::arg("mesh_length"),py::arg("share") = false);
225  space_sub.def("grid3",&space::grid3,"Creates 3D grid mesh", py::arg("length"), py::arg("width"),py::arg("height"), py::arg("mesh_length"),py::arg("share") = false);
226 
227  }
228  //! funtion to expose agent and patch containers
229  template<class ENV,class AGENT,class PATCH>
231  using AgentsBank = vector<shared_ptr<AGENT>>;
232  using PatchesBank = map<unsigned,shared_ptr<PATCH>>;
233  py::bind_vector<AgentsBank>(m,"AgentsBank")
234  .def("append",[](AgentsBank& container,shared_ptr<AGENT> agent){
235  container.push_back(agent);
236  });
237  py::bind_map<PatchesBank>(m,"PatchesBank")
238  .def("clear",[](PatchesBank& container){
239  container.clear();
240  })
241  .def("keys",[](PatchesBank& container){
242  std::vector<unsigned> keys;
243  for (auto const& element : container) {
244  keys.push_back(element.first);
245  }
246  return keys;
247  })
248  .def("append",[](PatchesBank& container,shared_ptr<PATCH> patch){
249  container.insert(std::pair<unsigned,shared_ptr<PATCH>>(patch->index,patch));
250  });
251  }
252  //! Exposes default items
253  template<class ENV,class AGENT, class PATCH>
255  expose_containers<ENV,AGENT,PATCH>(m);
257  expose_mesh(m);
258  }
259  //!< the main class to create binding
260  template<class env,class agent,class patch,class tramenv,class tramagent,class trampatch>
261  struct Bind {
262  using py_env = py::class_<env,tramenv,std::shared_ptr<env>>;
263  using py_agent = py::class_<agent,tramagent,std::shared_ptr<agent>>;
264  using py_patch = py::class_<patch,trampatch,std::shared_ptr<patch>>;
265  Bind(py::module m,string env_name,string agent_name,string patch_name):
266  m_env(bind_tools::expose_env<env,agent,patch,tramenv>(m,env_name)),
267  m_agent(bind_tools::expose_agent<env,agent,patch,tramagent>(m,agent_name)),
268  m_patch(bind_tools::expose_patch<env,agent,patch,trampatch>(m,patch_name))
269  {
270  // expose defaults
271  bind_tools::expose_defaults<env,agent,patch>(m);
272  // m_env = ;
273  // // expose agent
274  // m_agent = ;
275  // // expose patch
276  // m_patch = ;
277  this->m = m;
278  }
280  return m_env;
281  }
283  return m_agent;
284  }
286  return m_patch;
287  }
292  };
293 }
294 
295 
bind_tools::tramEnv::generate_agent
shared_ptr< AGENT > generate_agent(string agent_name) override
Definition: bind_tools.h:33
bind_tools::Bind
Definition: bind_tools.h:261
bind_tools::Bind::get_agent
py_agent get_agent()
Definition: bind_tools.h:282
bases.h
stl.h
def
int def()
Definition: test_ABM.cpp:4
bind_tools::tramEnv::generate_patch
shared_ptr< PATCH > generate_patch(MESH_ITEM mesh_item) override
Definition: bind_tools.h:25
bind_tools::Bind::py_env
py::class_< env, tramenv, std::shared_ptr< env > > py_env
Definition: bind_tools.h:262
bind_tools::expose_defaults
void expose_defaults(py::module &m)
Exposes default items.
Definition: bind_tools.h:254
space::grid3
vector< MESH_ITEM > grid3(double length, double width, double height, double mesh_length, bool share)
A function to create 3D rectangular mesh.
Definition: mesh.h:96
bind_tools::expose_mesh
void expose_mesh(py::module &m)
function to expose mesh items
Definition: bind_tools.h:220
MESH_ITEM
A class for mesh items.
Definition: mesh.h:10
bind_tools::Bind::get_env
py_env get_env()
Definition: bind_tools.h:279
bind_tools::expose_exceptions
void expose_exceptions(py::module m)
function to expose exceptions
Definition: bind_tools.h:214
module
module_ module
Definition: pybind11.h:1067
bind_tools
Tools for exposing C++ types and functions to Python.
Definition: bind_tools.h:20
bind_tools::Bind::m_patch
py_patch m_patch
Definition: bind_tools.h:291
bind_tools::tramAgent
Template trampoline for Agent-based classes.
Definition: bind_tools.h:61
bind_tools::Bind::get_patch
py_patch get_patch()
Definition: bind_tools.h:285
bind_tools::tramPatch::step
void step() override
Definition: bind_tools.h:84
bind_tools::expose_patch
py::class_< PATCH, tramclass, std::shared_ptr< PATCH > > expose_patch(py::module &m, string class_name_ptr)
Template trampoline for Patch-based classes with trampoline.
Definition: bind_tools.h:180
PYBIND11_OVERLOAD
#define PYBIND11_OVERLOAD(ret_type, cname, fn,...)
Definition: pybind11.h:2443
init
detail::initimpl::constructor< Args... > init()
Binds an existing constructor taking arguments Args...
Definition: pybind11.h:1587
bind_tools::Bind::m_agent
py_agent m_agent
Definition: bind_tools.h:290
bind_tools::expose_containers
void expose_containers(py::module &m)
funtion to expose agent and patch containers
Definition: bind_tools.h:230
bind_tools::tramEnv::update_repo
void update_repo() override
Definition: bind_tools.h:41
pybind11.h
bind_tools::tramPatch
Template trampoline for Patch-based classes.
Definition: bind_tools.h:82
move
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
Definition: cast.h:1798
bind_tools::tramAgent::step
void step() override
Definition: bind_tools.h:63
bind_tools::tramEnv
Template trampoline for Env-based classes.
Definition: bind_tools.h:23
bind_tools::Bind::py_patch
py::class_< patch, trampatch, std::shared_ptr< patch > > py_patch
Definition: bind_tools.h:264
bind_tools::Bind::m_env
py_env m_env
Definition: bind_tools.h:289
bind_tools::tramAgent::inherit
void inherit(shared_ptr< AGENT > father) override
Definition: bind_tools.h:71
bind_tools::Bind::Bind
Bind(py::module m, string env_name, string agent_name, string patch_name)
Definition: bind_tools.h:265
bind_tools::Bind::m
py::module m
Definition: bind_tools.h:288
env
Definition: env.py:1
bind_tools::Bind::py_agent
py::class_< agent, tramagent, std::shared_ptr< agent > > py_agent
Definition: bind_tools.h:263
space::grid2
vector< MESH_ITEM > grid2(double length, double width, double mesh_length, bool share)
A function to create 2D rectangular mesh.
Definition: mesh.h:20
pybind11
Definition: __init__.py:1
bind_tools::tramEnv::step
void step() override
Definition: bind_tools.h:49
bind_tools::expose_env
py::class_< ENV, tramclass, std::shared_ptr< ENV > > expose_env(py::module m, string class_name_string)
Expose function for Env-based classes with trampoline.
Definition: bind_tools.h:95
test_async.m
m
Definition: test_async.py:5
bind_tools::expose_agent
py::class_< AGENT, tramclass, std::shared_ptr< AGENT > > expose_agent(py::module &m, string class_name_str)
Template trampoline for Agent-based classes with trampoline.
Definition: bind_tools.h:137
stl_bind.h