ndxl 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ndxl-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: ndxl
3
+ Version: 1.0.0
4
+ Summary: Network Dynamics eXperimentation Library
5
+ Author: Ethan Codron
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "numpy"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ndxl"
7
+ version = "1.0.0"
8
+ description = "Network Dynamics eXperimentation Library"
9
+ authors = [
10
+ {name = "Ethan Codron"}
11
+ ]
12
+ readme = "README.md"
13
+ requires-python = ">=3.9"
14
+
15
+ [tool.setuptools]
16
+ package-dir = {""="src"}
17
+
18
+ [tool.setuptools.packages.find]
19
+ where=["src"]
20
+
21
+ [tool.setuptools.package-data]
22
+ ndxl=["lib/*.dll","lib/*.so"]
ndxl-1.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,6 @@
1
+ from .core import *
2
+ from .edge import *
3
+ from .network import *
4
+ from .vertex import *
5
+
6
+ lib.ndxlInit()
@@ -0,0 +1,68 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Union
5
+
6
+ import copy
7
+ import ctypes
8
+ import inspect
9
+ import numpy as np
10
+ import platform
11
+
12
+ # Load library from relative path
13
+ _cwd = Path(__file__).resolve().parent
14
+ libname = "NDXL.dll" if platform.system() == "Windows" else "libNDXL.so"
15
+ lib = ctypes.CDLL(str(_cwd / "lib" / libname))
16
+
17
+
18
+ # Error definitions from library header
19
+ NDXL_OK = 0
20
+ NDXL_ERR = -1
21
+ NDXL_VALUE_ERR = 1
22
+ NDXL_TYPE_ERR = 2
23
+ NDXL_ARG_ERR = 3
24
+
25
+
26
+ # NDXL object definitions
27
+ class NDXLNetwork(ctypes.Structure): pass
28
+ NDXLNetwork_p = ctypes.POINTER(NDXLNetwork)
29
+
30
+ class NDXLVertex(ctypes.Structure): pass
31
+ NDXLVertex_p = ctypes.POINTER(NDXLVertex)
32
+
33
+ class NDXLEdge(ctypes.Structure): pass
34
+ NDXLEdge_p = ctypes.POINTER(NDXLEdge)
35
+
36
+
37
+ # NDXL core functions
38
+ lib.ndxlGetLastErrorCode.restype = ctypes.c_int
39
+ lib.ndxlGetLastErrorCode.argtypes = []
40
+
41
+ lib.ndxlGetLastErrorMsg.restype = ctypes.c_char_p
42
+ lib.ndxlGetLastErrorMsg.argtypes = []
43
+
44
+ lib.ndxlPrintError.restype = None
45
+ lib.ndxlPrintError.argtypes = []
46
+
47
+ lib.ndxlRaiseError.restype = None
48
+ lib.ndxlRaiseError.argtypes = [ctypes.c_int, ctypes.c_char_p]
49
+
50
+ lib.ndxlInit.restype = ctypes.c_int
51
+ lib.ndxlInit.argtypes = []
52
+
53
+
54
+ # Wrapper functions
55
+ def libinit():
56
+ return lib.ndxlInit()
57
+
58
+ def get_last_error_code():
59
+ return lib.ndxlGetLastErrorCode()
60
+
61
+ def get_last_error_msg():
62
+ return lib.ndxlGetLastErrorMsg().value.decode('utf-8')
63
+
64
+ def print_error():
65
+ lib.ndxlPrintError()
66
+
67
+ def raise_error(code, msg):
68
+ lib.ndxlRaiseError(code, ctypes.c_char_p(msg.encode('utf-8')))
@@ -0,0 +1,271 @@
1
+ from __future__ import annotations
2
+
3
+ from .core import *
4
+
5
+ # Callbacks vvvvv
6
+
7
+ NDXLEdgeFunction = ctypes.CFUNCTYPE(None, NDXLEdge_p, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_double, ctypes.c_void_p)
8
+ NDXLEdgeCallback = ctypes.CFUNCTYPE(None, NDXLEdge_p, ctypes.POINTER(ctypes.c_double), ctypes.c_double, ctypes.c_void_p)
9
+ NoneEFn = NDXLEdgeFunction(0)
10
+ NoneECb = NDXLEdgeCallback(0)
11
+
12
+ # ^^^^^ Callbacks | constructor and destructor vvvvv
13
+
14
+ lib.ndxlCreateEdge.restype = NDXLEdge_p
15
+ lib.ndxlCreateEdge.argtypes = [NDXLVertex_p, NDXLVertex_p, ctypes.POINTER(ctypes.c_double), ctypes.c_size_t, ctypes.c_double, ctypes.c_bool, NDXLEdgeFunction, NDXLEdgeFunction, NDXLEdgeCallback, ctypes.c_void_p]
16
+
17
+ lib.ndxlCopyEdge.restype = NDXLEdge_p
18
+ lib.ndxlCopyEdge.argtypes = [NDXLEdge_p, NDXLVertex_p, NDXLVertex_p, ctypes.c_bool, ctypes.c_bool, ctypes.c_void_p]
19
+
20
+ lib.ndxlDestroyEdge.restype = ctypes.c_int
21
+ lib.ndxlDestroyEdge.argtypes = [ctypes.POINTER(NDXLEdge_p)]
22
+
23
+ # ^^^^^ Constructor and destructor | getters vvvvv
24
+
25
+ lib.ndxlGetEdgeCallback.restype = NDXLEdgeCallback
26
+ lib.ndxlGetEdgeCallback.argtypes = [NDXLVertex_p]
27
+
28
+ lib.ndxlGetEdgeDelay.restype = ctypes.c_double
29
+ lib.ndxlGetEdgeDelay.argtypes = [NDXLEdge_p]
30
+
31
+ lib.ndxlGetEdgeFirstVertex.restype = NDXLVertex_p
32
+ lib.ndxlGetEdgeFirstVertex.argtypes = [NDXLEdge_p]
33
+
34
+ lib.ndxlGetEdgeFunction.restype = NDXLEdgeFunction
35
+ lib.ndxlGetEdgeFunction.argtypes = [NDXLVertex_p]
36
+
37
+ lib.ndxlGetEdgeInitialState.restype = ctypes.POINTER(ctypes.c_double)
38
+ lib.ndxlGetEdgeInitialState.argtypes = [NDXLEdge_p]
39
+
40
+ lib.ndxlGetEdgeNoise.restype = NDXLEdgeFunction
41
+ lib.ndxlGetEdgeNoise.argtypes = [NDXLVertex_p]
42
+
43
+ lib.ndxlGetEdgeOrder.restype = ctypes.c_size_t
44
+ lib.ndxlGetEdgeOrder.argtypes = [NDXLEdge_p]
45
+
46
+ lib.ndxlGetEdgeParams.restype = ctypes.c_void_p
47
+ lib.ndxlGetEdgeParams.argtypes = [NDXLEdge_p]
48
+
49
+ lib.ndxlGetEdgeParent.restype = NDXLNetwork_p
50
+ lib.ndxlGetEdgeParent.argtypes = [NDXLEdge_p]
51
+
52
+ lib.ndxlGetEdgeSecondVertex.restype = NDXLVertex_p
53
+ lib.ndxlGetEdgeSecondVertex.argtypes = [NDXLEdge_p]
54
+
55
+ lib.ndxlGetEdgeState.restype = ctypes.POINTER(ctypes.c_double)
56
+ lib.ndxlGetEdgeState.argtypes = [NDXLEdge_p]
57
+
58
+ lib.ndxlGetEdgeTime.restype = ctypes.c_double
59
+ lib.ndxlGetEdgeTime.argtypes = [NDXLEdge_p]
60
+
61
+ # ^^^^^ Getters | setters vvvvv
62
+
63
+ lib.ndxlSetEdgeCallback.restype = ctypes.c_int
64
+ lib.ndxlSetEdgeCallback.argtypes = [NDXLVertex_p, NDXLEdgeCallback]
65
+
66
+ lib.ndxlSetEdgeFunction.restype = ctypes.c_int
67
+ lib.ndxlSetEdgeFunction.argtypes = [NDXLVertex_p, NDXLEdgeFunction]
68
+
69
+ lib.ndxlSetEdgeNoise.restype = ctypes.c_int
70
+ lib.ndxlSetEdgeNoise.argtypes = [NDXLVertex_p, NDXLEdgeFunction]
71
+
72
+ lib.ndxlSetEdgeState.restype = ctypes.c_int
73
+ lib.ndxlSetEdgeState.argtypes = [NDXLEdge_p, ctypes.POINTER(ctypes.c_double)]
74
+
75
+ # ^^^^^ Setters | functions vvvvv
76
+
77
+ lib.ndxlEdgeContainsVertex.restype = ctypes.c_bool
78
+ lib.ndxlEdgeContainsVertex.argtypes = [NDXLEdge_p, NDXLVertex_p]
79
+
80
+ lib.ndxlEdgeReset.restype = ctypes.c_int
81
+ lib.ndxlEdgeReset.argtypes = [NDXLEdge_p]
82
+
83
+ # ^^^^^ Functions | Python wrappers vvvvv
84
+
85
+ class edge:
86
+ def __init__(self, ptr, args):
87
+ self._ptr = ptr
88
+ self._pptr = args
89
+ self._params = ctypes.cast(self._pptr, ctypes.POINTER(ctypes.py_object)).contents.value
90
+ self._cplx = self._params[-3]
91
+
92
+ def __del__(self):
93
+ self._ptr = None
94
+ self._pptr = None
95
+ self._params = None
96
+
97
+ def __bool__(self):
98
+ return self._ptr != 0
99
+
100
+ def __len__(self):
101
+ _ord = lib.ndxlGetEdgeOrder(self._ptr)
102
+ return (_ord // 2) if self._cplx else _ord
103
+
104
+ def __str__(self):
105
+ return "'<ndxl.edge object at " + f"{id(self._ptr):#0{int(platform.architecture()[0][:-3]) // 4 + 2}X}" + " {'parent': " + f"<ndxl.network object at {id(self.parent.c_ptr):#0{int(platform.architecture()[0][:-3]) // 4 + 2}X}>" + ", 'vertex 1': " + str(self.first_vertex) + ", 'vertex 2': " + str(self.second_vertex) + ", 'state': " + str(self.state) + ", 'initial-state': " + str(self.initial_state) + ", 'time': " + str(lib.ndxlGetEdgeTime(self._ptr)) + ", 'function': " + str(self._params[0]) + ", 'noise': " + str(self._params[1]) + ", 'callback': " + str(self._params[2]) + "}>'"
106
+
107
+ def __repr__(self):
108
+ return f"NDXL edge\n===========\n\nParent: <ndxl.network object at {id(self.parent.c_ptr):#0{int(platform.architecture()[0][:-3]) // 4 + 2}X}>\nVertex 1: {self.first_vertex}\nVertex 2: {self.second_vertex}\nState: {self.state}\nInitial state: {self.initial_state}\nFunction: {self._params[0]}\nNoise: {self._params[1]}\nCallback: {self._params[2]}\nTime: {lib.ndxlGetEdgeTime(self._ptr)}\n"
109
+
110
+ @property
111
+ def c_ptr(self):
112
+ return self._ptr
113
+
114
+ def destroy(self):
115
+ _res = lib.ndxlDestroyEdge(ctypes.pointer(self._ptr))
116
+ del self._pptr
117
+ del self._params
118
+ return _res
119
+
120
+ @property
121
+ def callback(self):
122
+ return lib.ndxlGetEdgeCallback(self._ptr)
123
+
124
+ @callback.setter
125
+ def callback(self, cb):
126
+ self._params[2] = cb
127
+ return lib.ndxlSetEdgeCallback(self._ptr, NoneECb if cb is None else _ecb_bridge)
128
+
129
+ @property
130
+ def cplx(self):
131
+ return self._cplx
132
+
133
+ @property
134
+ def delay(self):
135
+ return lib.ndxlGetEdgeDelay(self._ptr)
136
+
137
+ @property
138
+ def first_vertex(self):
139
+ from .vertex import vertex
140
+ _vert = lib.ndxlGetEdgeFirstVertex(self._ptr)
141
+ return vertex(_vert, lib.ndxlGetVertexParams(_vert))
142
+
143
+ @property
144
+ def func(self):
145
+ return lib.ndxlGetEdgeFunction(self._ptr)
146
+
147
+ @func.setter
148
+ def func(self, fn):
149
+ self._params[0] = fn
150
+ return lib.ndxlSetEdgeFunction(self._ptr, NoneEFn if fn is None else _efunc_bridge)
151
+
152
+ @property
153
+ def initial_state(self):
154
+ return lib.ndxlGetEdgeInitialState(self._ptr)[:lib.ndxlGetEdgeOrder(self._ptr)]
155
+
156
+ @property
157
+ def noise(self):
158
+ return lib.ndxlGetEdgeNoise(self._ptr)
159
+
160
+ @noise.setter
161
+ def noise(self, zeta):
162
+ self._params[1] = zeta
163
+ return lib.ndxlSetEdgeNoise(self._ptr, NoneEFn if zeta is None else _enoise_bridge)
164
+
165
+ @property
166
+ def order(self):
167
+ return lib.ndxlGetEdgeOrder(self._ptr)
168
+
169
+ @property
170
+ def parent(self):
171
+ from .network import network
172
+ _nwk = lib.ndxlGetEdgeParent(self._ptr)
173
+ return network(_nwk, lib.ndxlGetNetworkParams(_nwk))
174
+
175
+ @property
176
+ def second_vertex(self):
177
+ from .vertex import vertex
178
+ _vert = lib.ndxlGetEdgeSecondVertex(self._ptr)
179
+ return vertex(_vert, lib.ndxlGetVertexParams(_vert))
180
+
181
+ @property
182
+ def shape(self):
183
+ return self._params[-2]
184
+
185
+ @property
186
+ def state(self):
187
+ _ord = self.order
188
+ _state = np.ctypeslib.as_array(lib.ndxlGetEdgeState(self._ptr), shape=(_ord,))
189
+ if self._cplx:
190
+ return (_state[:_ord // 2] + 1j * _state[_ord // 2: _ord]).reshape(self._params[-2])
191
+ return _state.reshape(self._params[-2])
192
+
193
+ @state.setter
194
+ def state(self, st):
195
+ _state = None
196
+ _nstate = 0
197
+ if st is not None:
198
+ _arr = np.asarray(st)
199
+ if self._cplx:
200
+ _ord = lib.ndxlGetEdgeOrder(self._ptr) // 2
201
+ _st = np.asarray(_arr.flatten(), dtype=complex)
202
+ _nstate = len(_st)
203
+ if _nstate != _ord:
204
+ raise ValueError(f"Attempting to assign {_nstate}-element state vector to edge of order {_ord}.")
205
+ _state = np.ctypeslib.as_ctypes(np.append(_st.real, _st.imag))
206
+ else:
207
+ _ord = lib.ndxlGetEdgeOrder(self._ptr)
208
+ _st = np.asarray(_arr.flatten(), dtype=float)
209
+ _nstate = len(_st)
210
+ if _nstate != _ord:
211
+ raise ValueError(f"Attempting to assign {_nstate}-element state vector to edge of order {_ord}.")
212
+ _state = np.ctypeslib.as_ctypes(_st)
213
+ return lib.ndxlSetEdgeState(self._ptr, _state)
214
+
215
+ @property
216
+ def time(self):
217
+ return lib.ndxlGetEdgeTime(self._ptr)
218
+
219
+ @NDXLEdgeFunction
220
+ def _efunc_bridge(ed, dstate, state, time, args):
221
+ _meta = ctypes.cast(args, ctypes.POINTER(ctypes.py_object)).contents.value
222
+ _func = _meta[0]
223
+ if _func:
224
+ _userdata = _meta[-1]
225
+ _e = edge(ed, lib.ndxlGetEdgeParams(ed))
226
+ _ord = _e.order
227
+ _inview = np.ctypeslib.as_array(state, shape=(_ord,))
228
+ _outview = np.ctypeslib.as_array(dstate, shape=(_ord,))
229
+ if _e.cplx:
230
+ _len = len(_e)
231
+ _result = np.asarray(_func(_e, (_inview[:_len] + 1j * _inview[_len: _ord]).reshape(_e.shape), time, *_userdata)).flatten()
232
+ _outview[:] = np.append(_result.real, _result.imag)
233
+ else:
234
+ _outview[:] = np.asarray(_func(_e, _inview.reshape(_e.shape), time, *_userdata)).flatten()
235
+
236
+ @NDXLEdgeFunction
237
+ def _enoise_bridge(ed, dstate, state, time, args):
238
+ _meta = ctypes.cast(args, ctypes.POINTER(ctypes.py_object)).contents.value
239
+ _noise = _meta[1]
240
+ if _noise:
241
+ _userdata = _meta[-1]
242
+ _e = edge(ed, lib.ndxlGetEdgeParams(ed))
243
+ _ord = _e.order
244
+ _inview = np.ctypeslib.as_array(state, shape=(_ord,))
245
+ _outview = np.ctypeslib.as_array(dstate, shape=(_ord,))
246
+ if _e.cplx:
247
+ _len = len(_e)
248
+ _result = np.asarray(_noise(_e, (_inview[:_len] + 1j * _inview[_len: _ord]).reshape(_e.shape), time, *_userdata)).flatten()
249
+ _outview[:] = np.append(_result.real, _result.imag)
250
+ else:
251
+ _outview[:] = np.asarray(_noise(_e, _inview.reshape(_e.shape), time, *_userdata)).flatten()
252
+
253
+ @NDXLEdgeCallback
254
+ def _ecb_bridge(ed, state, time, args):
255
+ _meta = ctypes.cast(args, ctypes.POINTER(ctypes.py_object)).contents.value
256
+ _cb = _meta[2]
257
+ if _cb:
258
+ _userdata = _meta[-1]
259
+ _e = edge(ed, lib.ndxlGetEdgeParams(ed))
260
+ _ord = _e.order
261
+ _view = np.ctypeslib.as_array(state, shape=(_ord,))
262
+ if _e.cplx:
263
+ _len = len(_e)
264
+ _tview = (_view[:_len] + 1j * _view[_len: _ord]).reshape(_e.shape)
265
+ _cb(_e, _tview, time, *_userdata)
266
+ _tview = _tview.flatten()
267
+ _view[:] = np.append(_tview.real, _tview.imag)
268
+ else:
269
+ _cb(_e, _view.reshape(_v.shape), time, *_userdata)
270
+
271
+ # ^^^^^ Python wrappers
Binary file
Binary file
@@ -0,0 +1,209 @@
1
+ from __future__ import annotations
2
+
3
+ from .core import *
4
+
5
+ # Callbacks vvvvv
6
+
7
+ NDXLNetworkCallback = ctypes.CFUNCTYPE(None, NDXLNetwork_p, ctypes.c_double, ctypes.c_void_p)
8
+
9
+ # ^^^^^ Callbacks | constructor and destructor vvvvv
10
+
11
+ lib.ndxlCreateNetwork.restype = NDXLNetwork_p
12
+ lib.ndxlCreateNetwork.argtypes = [ctypes.c_void_p]
13
+
14
+ lib.ndxlDestroyNetwork.restype = ctypes.c_int
15
+ lib.ndxlDestroyNetwork.argtypes = [ctypes.POINTER(NDXLNetwork_p)]
16
+
17
+ # ^^^^^ Constructor and destructor | getters vvvvv
18
+
19
+ lib.ndxlGetNetworkEdges.restype = ctypes.c_int
20
+ lib.ndxlGetNetworkEdges.argtypes = [NDXLNetwork_p, ctypes.POINTER(NDXLEdge_p)]
21
+
22
+ lib.ndxlGetNetworkOrder.restype = ctypes.c_size_t
23
+ lib.ndxlGetNetworkOrder.argtypes = [NDXLNetwork_p]
24
+
25
+ lib.ndxlGetNetworkParams.restype = ctypes.c_void_p
26
+ lib.ndxlGetNetworkParams.argtypes = [NDXLNetwork_p]
27
+
28
+ lib.ndxlGetNetworkSize.restype = ctypes.c_size_t
29
+ lib.ndxlGetNetworkSize.argtypes = [NDXLNetwork_p]
30
+
31
+ lib.ndxlGetNetworkTime.restype = ctypes.c_double
32
+ lib.ndxlGetNetworkTime.argtypes = [NDXLNetwork_p]
33
+
34
+ lib.ndxlGetNetworkVertices.restype = ctypes.c_int
35
+ lib.ndxlGetNetworkVertices.argtypes = [NDXLNetwork_p, ctypes.POINTER(NDXLVertex_p)]
36
+
37
+ # ^^^^^ Getters | functions vvvvv
38
+
39
+ lib.ndxlNetworkReset.restype = ctypes.c_int
40
+ lib.ndxlNetworkReset.argtypes = [NDXLNetwork_p]
41
+
42
+ lib.ndxlNetworkSimulateRalston.restype = ctypes.c_int
43
+ lib.ndxlNetworkSimulateRalston.argtypes = [NDXLNetwork_p, ctypes.c_double, ctypes.c_double, NDXLNetworkCallback]
44
+
45
+ lib.ndxlNetworkSimulateNystrom.restype = ctypes.c_int
46
+ lib.ndxlNetworkSimulateNystrom.argtypes = [NDXLNetwork_p, ctypes.c_double, ctypes.c_double, NDXLNetworkCallback]
47
+
48
+ lib.ndxlNetworkSimulateDopri.restype = ctypes.c_int
49
+ lib.ndxlNetworkSimulateDopri.argtypes = [NDXLNetwork_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.c_size_t, NDXLNetworkCallback]
50
+
51
+ lib.ndxlNetworkSimulateRkck.restype = ctypes.c_int
52
+ lib.ndxlNetworkSimulateRkck.argtypes = [NDXLNetwork_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.c_size_t, NDXLNetworkCallback]
53
+
54
+ lib.ndxlNetworkSimulateNorsett.restype = ctypes.c_int
55
+ lib.ndxlNetworkSimulateNorsett.argtypes = [NDXLNetwork_p, ctypes.c_double, ctypes.c_double, NDXLNetworkCallback]
56
+
57
+ lib.ndxlNetworkSimulateRadau.restype = ctypes.c_int
58
+ lib.ndxlNetworkSimulateRadau.argtypes = [NDXLNetwork_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.c_size_t, NDXLNetworkCallback]
59
+
60
+ # ^^^^^ Functions | Python wrappers vvvvv
61
+
62
+ class network:
63
+ def __init__(self, ptr, args):
64
+ self._ptr = ptr
65
+ self._pptr = args
66
+ self._params = ctypes.cast(self._pptr, ctypes.POINTER(ctypes.py_object)).contents.value
67
+
68
+ def __del__(self):
69
+ self._ptr = None
70
+ self._pptr = None
71
+ self._params = None
72
+
73
+ def __bool__(self):
74
+ return self._ptr != 0
75
+
76
+ def __str__(self):
77
+ return "'<ndxl.network object at " + f"{id(self._ptr):#0{int(platform.architecture()[0][:-3]) // 4 + 2}X}" + " {'order': " + str(lib.ndxlGetNetworkOrder(self._ptr)) + ", 'size': " + str(lib.ndxlGetNetworkSize(self._ptr)) + ", 'time': " + str(lib.ndxlGetNetworkTime(self._ptr)) + "}>'"
78
+
79
+ def __repr__(self):
80
+ return f"NDXL network\n============\n\nVertices (order): {lib.ndxlGetNetworkOrder(self._ptr)}\nEdges (size): {lib.ndxlGetNetworkSize(self._ptr)}\nTime: {lib.ndxlGetNetworkTime(self._ptr)}\n"
81
+
82
+ @property
83
+ def c_ptr(self):
84
+ return self._ptr
85
+
86
+ def destroy(self):
87
+ _res = lib.ndxlDestroyNetwork(ctypes.pointer(self._ptr))
88
+ del self._pptr
89
+ del self._params
90
+ return _res
91
+
92
+ @property
93
+ def edges(self):
94
+ from .edge import edge
95
+ _ne = lib.ndxlGetNetworkSize(self._ptr)
96
+ _arr = (NDXLEdge_p * _ne)()
97
+ lib.ndxlGetNetworkEdges(self._ptr, _arr)
98
+ return [edge(_arr[i], lib.ndxlGetEdgeParams(_arr[i])) for i in range(_ne)]
99
+
100
+ @property
101
+ def order(self):
102
+ return lib.ndxlGetNetworkOrder(self._ptr)
103
+
104
+ @property
105
+ def size(self):
106
+ return lib.ndxlGetNetworkSize(self._ptr)
107
+
108
+ @property
109
+ def time(self):
110
+ return lib.ndxlGetNetworkTime(self._ptr)
111
+
112
+ @property
113
+ def vertices(self):
114
+ from .vertex import vertex
115
+ _nv = lib.ndxlGetNetworkOrder(self._ptr)
116
+ _arr = (NDXLVertex_p * _nv)()
117
+ lib.ndxlGetNetworkVertices(self._ptr, _arr)
118
+ return [vertex(_arr[i], lib.ndxlGetVertexParams(_arr[i])) for i in range(_nv)]
119
+
120
+ def reset(self):
121
+ return lib.ndxlNetworkReset(self._ptr)
122
+
123
+ def simulate_ralston(self, tspan, step=0.1, cb=None):
124
+ self._params[0] = cb
125
+ return lib.ndxlNetworkSimulateRalston(self._ptr, tspan, step, _network_bridge)
126
+
127
+ def simulate_nystrom(self, tspan, step=0.1, cb=None):
128
+ self._params[0] = cb
129
+ return lib.ndxlNetworkSimulateNystrom(self._ptr, tspan, step, _network_bridge)
130
+
131
+ def simulate_dopri(self, tspan, atol=1e-6, rtol=1e-3, tstops=None, cb=None):
132
+ self._params[0] = cb
133
+ _nstops = 0 if tstops is None else len(tstops)
134
+ _tstops = None if tstops is None else (ctypes.c_double * _nstops)(*tstops)
135
+ return lib.ndxlNetworkSimulateDopri(self._ptr, tspan, atol, rtol, _tstops, _nstops, _network_bridge)
136
+
137
+ def simulate_rkck(self, tspan, atol=1e-6, rtol=1e-3, tstops=None, cb=None):
138
+ self._params[0] = cb
139
+ _nstops = 0 if tstops is None else len(tstops)
140
+ _tstops = None if tstops is None else (ctypes.c_double * _nstops)(*tstops)
141
+ return lib.ndxlNetworkSimulateRkck(self._ptr, tspan, atol, rtol, _tstops, _nstops, _network_bridge)
142
+
143
+ def simulate_nystrom(self, tspan, step=0.1, cb=None):
144
+ raise NotImplementedError("This function is under construction and will be available soon!")
145
+ #self._params[0] = cb
146
+ #return lib.ndxlNetworkSimulateNorsett(self._ptr, tspan, step, _network_bridge)
147
+
148
+ def simulate_radau(self, tspan, atol=1e-10, rtol=1e-8, tstops=None, cb=None):
149
+ raise NotImplementedError("This function is under construction and will be available soon!")
150
+ #self._params[0] = cb
151
+ #_nstops = 0 if tstops is None else len(tstops)
152
+ #_tstops = None if tstops is None else (ctypes.c_double * _nstops)(*tstops)
153
+ #return lib.ndxlNetworkSimulateRadau(self._ptr, tspan, atol, rtol, _tstops, _nstops, _network_bridge)
154
+
155
+ def create_vertex(self, state=None, func=None, noise=None, cb=None, args=None, cplx=False):
156
+ from .vertex import vertex, _vfunc_bridge, _vnoise_bridge, _vcb_bridge, NoneVFn, NoneVCb
157
+ _state = None
158
+ _nstate = 0
159
+ _sstate = ()
160
+ _cplx = cplx
161
+ if state is not None:
162
+ _arr = np.asarray(state)
163
+ _sstate = _arr.shape
164
+ if _arr.dtype == complex:
165
+ _st = np.asarray(_arr.flatten(), dtype=complex)
166
+ _nstate = len(_st) * 2
167
+ _state = np.ctypeslib.as_ctypes(np.append(_st.real, _st.imag))
168
+ _cplx = True
169
+ else:
170
+ _st = np.asarray(_arr.flatten(), dtype=float)
171
+ _nstate = len(_st)
172
+ _state = np.ctypeslib.as_ctypes(_st)
173
+ _pptr = ctypes.cast(ctypes.pointer(ctypes.py_object([func, noise, cb, _cplx, _sstate, () if args is None else copy.deepcopy(args)])), ctypes.c_void_p)
174
+ return vertex(lib.ndxlCreateVertex(self._ptr, _state, _nstate, NoneVFn if func is None else _vfunc_bridge, NoneVFn if noise is None else _vnoise_bridge, NoneVCb if cb is None else _vcb_bridge, _pptr), _pptr)
175
+
176
+ def create_edge(self, v1, v2, state=None, delay=0., directed=False, func=None, noise=None, cb=None, args=None):
177
+ from .edge import edge, _efunc_bridge, _enoise_bridge, _ecb_bridge, NoneEFn, NoneECb
178
+ _state = None
179
+ _nstate = 0
180
+ _sstate = ()
181
+ _cplx = cplx
182
+ if state is not None:
183
+ _arr = np.asarray(state)
184
+ _sstate = _arr.shape
185
+ if _arr.dtype == complex:
186
+ _st = np.asarray(_arr.flatten(), dtype=complex)
187
+ _nstate = len(_st) * 2
188
+ _state = np.ctypeslib.as_ctypes(np.append(_st.real, _st.imag))
189
+ _cplx = True
190
+ else:
191
+ _st = np.asarray(_arr.flatten(), dtype=float)
192
+ _nstate = len(_st)
193
+ _state = np.ctypeslib.as_ctypes(_st)
194
+ _pptr = ctypes.cast(ctypes.pointer(ctypes.py_object([func, noise, cb, _cplx, _sstate, () if args is None else copy.deepcopy(args)])), ctypes.c_void_p)
195
+ return edge(lib.ndxlCreateEdge(v1 if isinstance(v1, NDXLVertex_p) else v1.c_ptr, v2 if isinstance(v2, NDXLVertex_p) else v2.c_ptr, _state, _nstate, delay, directed, NoneEFn if func is None else _efunc_bridge, NoneEFn if noise is None else _enoise_bridge, NoneECb if cb is None else _ecb_bridge, _pptr), _pptr)
196
+
197
+ def create_network(args=None):
198
+ _pptr = ctypes.cast(ctypes.pointer(ctypes.py_object([None, () if args is None else copy.deepcopy(args)])), ctypes.c_void_p)
199
+ return network(lib.ndxlCreateNetwork(_pptr), _pptr)
200
+
201
+ @NDXLNetworkCallback
202
+ def _network_bridge(nwk, time, args):
203
+ _meta = ctypes.cast(args, ctypes.POINTER(ctypes.py_object)).contents.value
204
+ _cb = _meta[0]
205
+ if _cb:
206
+ _userdata = _meta[1]
207
+ _cb(network(nwk, lib.ndxlGetNetworkParams(nwk)), time, *_userdata)
208
+
209
+ # ^^^^^ Python wrappers
@@ -0,0 +1,329 @@
1
+ from __future__ import annotations
2
+
3
+ from .core import *
4
+
5
+ # Callbacks vvvvv
6
+
7
+ NDXLVertexFunction = ctypes.CFUNCTYPE(None, NDXLVertex_p, ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_double, ctypes.c_void_p)
8
+ NDXLVertexCallback = ctypes.CFUNCTYPE(None, NDXLVertex_p, ctypes.POINTER(ctypes.c_double), ctypes.c_double, ctypes.c_void_p)
9
+ NoneVFn = NDXLVertexFunction(0)
10
+ NoneVCb = NDXLVertexCallback(0)
11
+
12
+ # ^^^^^ Callbacks | constructor and destructor vvvvv
13
+
14
+ lib.ndxlCreateVertex.restype = NDXLVertex_p
15
+ lib.ndxlCreateVertex.argtypes = [NDXLNetwork_p, ctypes.POINTER(ctypes.c_double), ctypes.c_size_t, NDXLVertexFunction, NDXLVertexFunction, NDXLVertexCallback, ctypes.c_void_p]
16
+
17
+ lib.ndxlCopyVertex.restype = NDXLVertex_p
18
+ lib.ndxlCopyVertex.argtypes = [NDXLVertex_p, NDXLNetwork_p, ctypes.c_bool, ctypes.c_void_p]
19
+
20
+ lib.ndxlDestroyVertex.restype = ctypes.c_int
21
+ lib.ndxlDestroyVertex.argtypes = [ctypes.POINTER(NDXLVertex_p)]
22
+
23
+ # ^^^^^ Constructor and destructor | getters vvvvv
24
+
25
+ lib.ndxlGetVertexCallback.restype = NDXLVertexCallback
26
+ lib.ndxlGetVertexCallback.argtypes = [NDXLVertex_p]
27
+
28
+ lib.ndxlGetVertexDegree.restype = ctypes.c_size_t
29
+ lib.ndxlGetVertexDegree.argtypes = [NDXLVertex_p]
30
+
31
+ lib.ndxlGetVertexDegreeIn.restype = ctypes.c_size_t
32
+ lib.ndxlGetVertexDegreeIn.argtypes = [NDXLVertex_p]
33
+
34
+ lib.ndxlGetVertexDegreeOut.restype = ctypes.c_size_t
35
+ lib.ndxlGetVertexDegreeOut.argtypes = [NDXLVertex_p]
36
+
37
+ lib.ndxlGetVertexEdges.restype = ctypes.c_int
38
+ lib.ndxlGetVertexEdges.argtypes = [NDXLVertex_p, ctypes.POINTER(NDXLEdge_p)]
39
+
40
+ lib.ndxlGetVertexFirstEdge.restype = NDXLEdge_p
41
+ lib.ndxlGetVertexFirstEdge.argtypes = [NDXLVertex_p]
42
+
43
+ lib.ndxlGetVertexFunction.restype = NDXLVertexFunction
44
+ lib.ndxlGetVertexFunction.argtypes = [NDXLVertex_p]
45
+
46
+ lib.ndxlGetVertexInitialState.restype = ctypes.POINTER(ctypes.c_double)
47
+ lib.ndxlGetVertexInitialState.argtypes = [NDXLVertex_p]
48
+
49
+ lib.ndxlGetVertexLastEdge.restype = NDXLEdge_p
50
+ lib.ndxlGetVertexLastEdge.argtypes = [NDXLVertex_p]
51
+
52
+ lib.ndxlGetVertexNeighbour.restype = NDXLVertex_p
53
+ lib.ndxlGetVertexNeighbour.argtypes = [NDXLVertex_p, NDXLEdge_p]
54
+
55
+ lib.ndxlGetVertexNeighbours.restype = ctypes.c_int
56
+ lib.ndxlGetVertexNeighbours.argtypes = [NDXLVertex_p, ctypes.POINTER(NDXLVertex_p)]
57
+
58
+ lib.ndxlGetVertexNeighbourState.restype = ctypes.POINTER(ctypes.c_double)
59
+ lib.ndxlGetVertexNeighbourState.argtypes = [NDXLVertex_p, NDXLEdge_p]
60
+
61
+ lib.ndxlGetVertexNextEdge.restype = NDXLEdge_p
62
+ lib.ndxlGetVertexNextEdge.argtypes = [NDXLVertex_p, NDXLEdge_p]
63
+
64
+ lib.ndxlGetVertexNoise.restype = NDXLVertexFunction
65
+ lib.ndxlGetVertexNoise.argtypes = [NDXLVertex_p]
66
+
67
+ lib.ndxlGetVertexOrder.restype = ctypes.c_size_t
68
+ lib.ndxlGetVertexOrder.argtypes = [NDXLVertex_p]
69
+
70
+ lib.ndxlGetVertexParams.restype = ctypes.c_void_p
71
+ lib.ndxlGetVertexParams.argtypes = [NDXLVertex_p]
72
+
73
+ lib.ndxlGetVertexParent.restype = NDXLNetwork_p
74
+ lib.ndxlGetVertexParent.argtypes = [NDXLVertex_p]
75
+
76
+ lib.ndxlGetVertexState.restype = ctypes.POINTER(ctypes.c_double)
77
+ lib.ndxlGetVertexState.argtypes = [NDXLVertex_p]
78
+
79
+ lib.ndxlGetVertexTime.restype = ctypes.c_double
80
+ lib.ndxlGetVertexTime.argtypes = [NDXLVertex_p]
81
+
82
+ # ^^^^^ Getters | setters vvvvv
83
+
84
+ lib.ndxlSetVertexCallback.restype = ctypes.c_int
85
+ lib.ndxlSetVertexCallback.argtypes = [NDXLVertex_p, NDXLVertexCallback]
86
+
87
+ lib.ndxlSetVertexFunction.restype = ctypes.c_int
88
+ lib.ndxlSetVertexFunction.argtypes = [NDXLVertex_p, NDXLVertexFunction]
89
+
90
+ lib.ndxlSetVertexNoise.restype = ctypes.c_int
91
+ lib.ndxlSetVertexNoise.argtypes = [NDXLVertex_p, NDXLVertexFunction]
92
+
93
+ lib.ndxlSetVertexState.restype = ctypes.c_int
94
+ lib.ndxlSetVertexState.argtypes = [NDXLVertex_p, ctypes.POINTER(ctypes.c_double)]
95
+
96
+ # ^^^^^ Setters | functions vvvvv
97
+
98
+ lib.ndxlVertexReset.restype = ctypes.c_int
99
+ lib.ndxlVertexReset.argtypes = [NDXLVertex_p]
100
+
101
+ # ^^^^^ Functions | Python wrappers vvvvv
102
+
103
+ class vertex:
104
+ def __init__(self, ptr, args):
105
+ self._ptr = ptr
106
+ self._pptr = args
107
+ self._params = ctypes.cast(self._pptr, ctypes.POINTER(ctypes.py_object)).contents.value
108
+ self._cplx = self._params[-3]
109
+
110
+ def __del__(self):
111
+ self._ptr = None
112
+ self._pptr = None
113
+ self._params = None
114
+
115
+ def __bool__(self):
116
+ return self._ptr != 0
117
+
118
+ def __len__(self):
119
+ _ord = lib.ndxlGetVertexOrder(self._ptr)
120
+ return (_ord // 2) if self._cplx else _ord
121
+
122
+ def __str__(self):
123
+ return f"'<ndxl.vertex object at " + f"{id(self._ptr):#0{int(platform.architecture()[0][:-3]) // 4 + 2}X}" + " {'parent': " + f"<ndxl.network object at {id(self.parent.c_ptr):#0{int(platform.architecture()[0][:-3]) // 4 + 2}X}>" + ", 'degree': " + str(lib.ndxlGetVertexDegree(self._ptr)) + ", 'in-degree': " + str(lib.ndxlGetVertexDegreeIn(self._ptr)) + ", 'out-degree': " + str(lib.ndxlGetVertexDegreeOut(self._ptr)) + ", 'state': " + str(self.state) + ", 'initial-state': " + str(self.initial_state) + ", 'time': " + str(lib.ndxlGetVertexTime(self._ptr)) + ", 'function': " + str(self._params[0]) + ", 'noise': " + str(self._params[1]) + ", 'callback': " + str(self._params[2]) + "}>'"
124
+
125
+ def __repr__(self):
126
+ return f"NDXL vertex\n===========\n\nParent: <ndxl.network object at {id(self.parent.c_ptr):#0{int(platform.architecture()[0][:-3]) // 4 + 2}X}>\nState: {self.state}\nInitial state: {self.initial_state}\nDegree: {lib.ndxlGetVertexDegree(self._ptr)}\nIn-degree: {lib.ndxlGetVertexDegreeIn(self._ptr)}\nOut-degree: {lib.ndxlGetVertexDegreeOut(self._ptr)}\nFunction: {self._params[0]}\nNoise: {self._params[1]}\nCallback: {self._params[2]}\nTime: {lib.ndxlGetVertexTime(self._ptr)}\n"
127
+
128
+ @property
129
+ def c_ptr(self):
130
+ return self._ptr
131
+
132
+ def destroy(self):
133
+ _res = lib.ndxlDestroyVertex(ctypes.pointer(self._ptr))
134
+ del self._pptr
135
+ del self._params
136
+ return _res
137
+
138
+ @property
139
+ def callback(self):
140
+ return lib.ndxlGetVertexCallback(self._ptr)
141
+
142
+ @callback.setter
143
+ def callback(self, cb):
144
+ self._params[2] = cb
145
+ return lib.ndxlSetVertexCallback(self._ptr, NoneVCb if cb is None else _vcb_bridge)
146
+
147
+ @property
148
+ def cplx(self):
149
+ return self._cplx
150
+
151
+ @property
152
+ def degree(self):
153
+ return lib.ndxlGetVertexDegree(self._ptr)
154
+
155
+ @property
156
+ def degree_in(self):
157
+ return lib.ndxlGetVertexDegreeIn(self._ptr)
158
+
159
+ @property
160
+ def degree_out(self):
161
+ return lib.ndxlGetVertexDegreeOut(self._ptr)
162
+
163
+ @property
164
+ def edges(self):
165
+ from .edge import edge
166
+ _edge = lib.ndxlGetVertexFirstEdge(self._ptr)
167
+ while _edge:
168
+ yield edge(_edge, lib.ndxlGetEdgeParams(_edge))
169
+ _edge = lib.ndxlGetVertexNextEdge(self._ptr, _edge)
170
+
171
+ @property
172
+ def func(self):
173
+ return lib.ndxlGetVertexFunction(self._ptr)
174
+
175
+ @func.setter
176
+ def func(self, fn):
177
+ self._params[0] = fn
178
+ return lib.ndxlSetVertexFunction(self._ptr, NoneVFn if fn is None else _vfunc_bridge)
179
+
180
+ @property
181
+ def initial_state(self):
182
+ return lib.ndxlGetVertexInitialState(self._ptr)[:lib.ndxlGetVertexOrder(self._ptr)]
183
+
184
+ def neighbour(self, ed):
185
+ _vert = lib.ndxlGetVertexNeighbour(self._ptr, ed.c_ptr)
186
+ return vertex(_vert, lib.ndxlGetVertexParams(_vert))
187
+
188
+ def neighbour_state(self, ed):
189
+ _order = self.neighbour(ed).order
190
+ return lib.ndxlGetVertexNeighbourState(self._ptr, ed.c_ptr)[:_order]
191
+
192
+ @property
193
+ def neighbours(self):
194
+ for _edge in self.edges:
195
+ yield self.neighbour(_edge)
196
+
197
+ @property
198
+ def noise(self):
199
+ return lib.ndxlGetVertexNoise(self._ptr)
200
+
201
+ @noise.setter
202
+ def noise(self, zeta):
203
+ self._params[1] = zeta
204
+ return lib.ndxlSetVertexNoise(self._ptr, NoneVFn if zeta is None else _vnoise_bridge)
205
+
206
+ @property
207
+ def order(self):
208
+ return lib.ndxlGetVertexOrder(self._ptr)
209
+
210
+ @property
211
+ def parent(self):
212
+ from .network import network
213
+ _nwk = lib.ndxlGetVertexParent(self._ptr)
214
+ return network(_nwk, lib.ndxlGetNetworkParams(_nwk))
215
+
216
+ @property
217
+ def shape(self):
218
+ return self._params[-2]
219
+
220
+ @property
221
+ def state(self):
222
+ _ord = self.order
223
+ _state = np.ctypeslib.as_array(lib.ndxlGetVertexState(self._ptr), shape=(_ord,))
224
+ if self._cplx:
225
+ return (_state[:_ord // 2] + 1j * _state[_ord // 2: _ord]).reshape(self._params[-2])
226
+ return _state.reshape(self._params[-2])
227
+
228
+ @state.setter
229
+ def state(self, st):
230
+ _state = None
231
+ _nstate = 0
232
+ if st is not None:
233
+ _arr = np.asarray(st)
234
+ if self._cplx:
235
+ _ord = lib.ndxlGetVertexOrder(self._ptr) // 2
236
+ _st = np.asarray(_arr.flatten(), dtype=complex)
237
+ _nstate = len(_st)
238
+ if _nstate != _ord:
239
+ raise ValueError(f"Attempting to assign {_nstate}-element state vector to vertex of order {_ord}.")
240
+ _state = np.ctypeslib.as_ctypes(np.append(_st.real, _st.imag))
241
+ else:
242
+ _ord = lib.ndxlGetVertexOrder(self._ptr)
243
+ _st = np.asarray(_arr.flatten(), dtype=float)
244
+ _nstate = len(_st)
245
+ if _nstate != _ord:
246
+ raise ValueError(f"Attempting to assign {_nstate}-element state vector to vertex of order {_ord}.")
247
+ _state = np.ctypeslib.as_ctypes(_st)
248
+ return lib.ndxlSetVertexState(self._ptr, _state)
249
+
250
+ @property
251
+ def time(self):
252
+ return lib.ndxlGetVertexTime(self._ptr)
253
+
254
+ def create_edge(self, vert, state=None, delay=0., directed=False, func=None, noise=None, cb=None, args=None, cplx=False):
255
+ from .edge import edge, _efunc_bridge, _enoise_bridge, _ecb_bridge, NoneEFn, NoneECb
256
+ _state = None
257
+ _nstate = 0
258
+ _sstate = ()
259
+ _cplx = cplx
260
+ if state is not None:
261
+ _arr = np.asarray(state)
262
+ _sstate = _arr.shape
263
+ if _arr.dtype == complex:
264
+ _st = np.asarray(_arr.flatten(), dtype=complex)
265
+ _nstate = len(_st) * 2
266
+ _state = np.ctypeslib.as_ctypes(np.append(_st.real, _st.imag))
267
+ _cplx = True
268
+ else:
269
+ _st = np.asarray(_arr.flatten(), dtype=float)
270
+ _nstate = len(_st)
271
+ _state = np.ctypeslib.as_ctypes(_st)
272
+ _pptr = ctypes.cast(ctypes.pointer(ctypes.py_object([func, noise, cb, _cplx, _sstate, () if args is None else copy.deepcopy(args)])), ctypes.c_void_p)
273
+ return edge(lib.ndxlCreateEdge(self._ptr, vert if isinstance(vert, NDXLVertex_p) else vert.c_ptr, _state, _nstate, delay, directed, NoneEFn if func is None else _efunc_bridge, NoneEFn if noise is None else _enoise_bridge, NoneECb if cb is None else _ecb_bridge, _pptr), _pptr)
274
+
275
+ @NDXLVertexFunction
276
+ def _vfunc_bridge(vert, dstate, state, time, args):
277
+ _meta = ctypes.cast(args, ctypes.POINTER(ctypes.py_object)).contents.value
278
+ _func = _meta[0]
279
+ if _func:
280
+ _userdata = _meta[-1]
281
+ _v = vertex(vert, lib.ndxlGetVertexParams(vert))
282
+ _ord = _v.order
283
+ _inview = np.ctypeslib.as_array(state, shape=(_ord,))
284
+ _outview = np.ctypeslib.as_array(dstate, shape=(_ord,))
285
+ if _v.cplx:
286
+ _len = len(_v)
287
+ _result = np.asarray(_func(_v, (_inview[:_len] + 1j * _inview[_len: _ord]).reshape(_v.shape), time, *_userdata)).flatten()
288
+ _outview[:] = np.append(_result.real, _result.imag)
289
+ else:
290
+ _outview[:] = np.asarray(_func(_v, _inview.reshape(_v.shape), time, *_userdata)).flatten()
291
+
292
+ @NDXLVertexFunction
293
+ def _vnoise_bridge(vert, dstate, state, time, args):
294
+ _meta = ctypes.cast(args, ctypes.POINTER(ctypes.py_object)).contents.value
295
+ _noise = _meta[1]
296
+ if _noise:
297
+ _userdata = _meta[-1]
298
+ _v = vertex(vert, lib.ndxlGetVertexParams(vert))
299
+ _ord = _v.order
300
+ _inview = np.ctypeslib.as_array(state, shape=(_ord,))
301
+ _outview = np.ctypeslib.as_array(dstate, shape=(_ord,))
302
+ if _v.cplx:
303
+ _len = len(_v)
304
+ _result = np.asarray(_noise(_v, (_inview[:_len] + 1j * _inview[_len: _ord]).reshape(_v.shape), time, *_userdata)).flatten()
305
+ _outview[:] = np.append(_result.real, _result.imag)
306
+ else:
307
+ _outview[:] = np.asarray(_noise(_v, _inview.reshape(_v.shape), time, *_userdata)).flatten()
308
+ else:
309
+ _outview = np.ctypeslib.as_array(dstate, shape=(_ord,))
310
+
311
+ @NDXLVertexCallback
312
+ def _vcb_bridge(vert, state, time, args):
313
+ _meta = ctypes.cast(args, ctypes.POINTER(ctypes.py_object)).contents.value
314
+ _cb = _meta[2]
315
+ if _cb:
316
+ _userdata = _meta[-1]
317
+ _v = vertex(vert, lib.ndxlGetVertexParams(vert))
318
+ _ord = _v.order
319
+ _view = np.ctypeslib.as_array(state, shape=(_ord,))
320
+ if _v.cplx:
321
+ _len = len(_v)
322
+ _tview = (_view[:_len] + 1j * _view[_len: _ord]).reshape(_v.shape)
323
+ _cb(_v, _tview, time, *_userdata)
324
+ _tview = _tview.flatten()
325
+ _view[:] = np.append(_tview.real, _tview.imag)
326
+ else:
327
+ _cb(_v, _view.reshape(_v.shape), time, *_userdata)
328
+
329
+ # ^^^^^ Python wrappers
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: ndxl
3
+ Version: 1.0.0
4
+ Summary: Network Dynamics eXperimentation Library
5
+ Author: Ethan Codron
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
@@ -0,0 +1,12 @@
1
+ pyproject.toml
2
+ src/ndxl/__init__.py
3
+ src/ndxl/core.py
4
+ src/ndxl/edge.py
5
+ src/ndxl/network.py
6
+ src/ndxl/vertex.py
7
+ src/ndxl.egg-info/PKG-INFO
8
+ src/ndxl.egg-info/SOURCES.txt
9
+ src/ndxl.egg-info/dependency_links.txt
10
+ src/ndxl.egg-info/top_level.txt
11
+ src/ndxl/lib/NDXL.dll
12
+ src/ndxl/lib/libNDXL.so
@@ -0,0 +1 @@
1
+ ndxl