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 +7 -0
- ndxl-1.0.0/pyproject.toml +22 -0
- ndxl-1.0.0/setup.cfg +4 -0
- ndxl-1.0.0/src/ndxl/__init__.py +6 -0
- ndxl-1.0.0/src/ndxl/core.py +68 -0
- ndxl-1.0.0/src/ndxl/edge.py +271 -0
- ndxl-1.0.0/src/ndxl/lib/NDXL.dll +0 -0
- ndxl-1.0.0/src/ndxl/lib/libNDXL.so +0 -0
- ndxl-1.0.0/src/ndxl/network.py +209 -0
- ndxl-1.0.0/src/ndxl/vertex.py +329 -0
- ndxl-1.0.0/src/ndxl.egg-info/PKG-INFO +7 -0
- ndxl-1.0.0/src/ndxl.egg-info/SOURCES.txt +12 -0
- ndxl-1.0.0/src/ndxl.egg-info/dependency_links.txt +1 -0
- ndxl-1.0.0/src/ndxl.egg-info/top_level.txt +1 -0
ndxl-1.0.0/PKG-INFO
ADDED
|
@@ -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,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,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
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ndxl
|