pynumerics 2.3.0__py3-none-any.whl

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.
Files changed (46) hide show
  1. pynumerics/__init__.py +73 -0
  2. pynumerics/_bin/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  3. pynumerics/_bin/Microsoft.CodeAnalysis.LICENSE.txt +27 -0
  4. pynumerics/_bin/Microsoft.CodeAnalysis.dll +0 -0
  5. pynumerics/_bin/Numerics.dll +0 -0
  6. pynumerics/_bin/pynumerics.runtimeconfig.json +15 -0
  7. pynumerics/_coverage.py +3825 -0
  8. pynumerics/_util.py +237 -0
  9. pynumerics/_version.py +40 -0
  10. pynumerics/bootstrap.py +593 -0
  11. pynumerics/callbacks.py +791 -0
  12. pynumerics/copulas.py +910 -0
  13. pynumerics/data.py +2233 -0
  14. pynumerics/differentiation.py +348 -0
  15. pynumerics/distributions.py +4043 -0
  16. pynumerics/download.py +623 -0
  17. pynumerics/enums.py +119 -0
  18. pynumerics/errors.py +245 -0
  19. pynumerics/functions.py +1142 -0
  20. pynumerics/goodness_of_fit.py +699 -0
  21. pynumerics/graphs.py +556 -0
  22. pynumerics/hypothesis_tests.py +445 -0
  23. pynumerics/identity.py +144 -0
  24. pynumerics/integration.py +677 -0
  25. pynumerics/linalg.py +1408 -0
  26. pynumerics/machine_learning.py +1335 -0
  27. pynumerics/marshal.py +733 -0
  28. pynumerics/mathematics.py +1053 -0
  29. pynumerics/mcmc.py +1406 -0
  30. pynumerics/multivariate.py +1539 -0
  31. pynumerics/ode.py +156 -0
  32. pynumerics/optimization.py +1736 -0
  33. pynumerics/probability.py +966 -0
  34. pynumerics/py.typed +0 -0
  35. pynumerics/regional.py +522 -0
  36. pynumerics/roots.py +274 -0
  37. pynumerics/runtime.py +384 -0
  38. pynumerics/sampling.py +1758 -0
  39. pynumerics/special.py +1079 -0
  40. pynumerics/statistics.py +1958 -0
  41. pynumerics/timeseries.py +1326 -0
  42. pynumerics-2.3.0.dist-info/METADATA +142 -0
  43. pynumerics-2.3.0.dist-info/RECORD +46 -0
  44. pynumerics-2.3.0.dist-info/WHEEL +5 -0
  45. pynumerics-2.3.0.dist-info/licenses/LICENSE +10 -0
  46. pynumerics-2.3.0.dist-info/top_level.txt +1 -0
pynumerics/graphs.py ADDED
@@ -0,0 +1,556 @@
1
+ """Shortest paths on directed networks from ``Numerics.Mathematics.Optimization``.
2
+
3
+ :class:`Edge` and :class:`Network` describe a directed network; the ``dijkstra_*`` functions and
4
+ :meth:`Network.solve` return a routing table with one row per node: column 0 is the next node
5
+ toward the destination, column 1 the index of the edge to take and column 2 the cumulative cost
6
+ (float32; the costs accumulate in float64 and are rounded once). The destination row is
7
+ ``(itself, -1, 0)`` and an unreachable node's row is ``(-1, -1, inf)``. :func:`shortest_distances` gives
8
+ float64 distances from several sources on a CSR graph, as ``scipy.sparse.csgraph.dijkstra`` does.
9
+
10
+ :class:`BinaryHeap` is the keyed min-heap the shortest-path solvers are built on. The knapsack
11
+ and dynamic programming solvers of the same namespace are in :mod:`pynumerics.optimization`.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from dataclasses import dataclass
17
+ from typing import Any
18
+
19
+ import numpy as np
20
+
21
+ from pynumerics._util import _opt
22
+ from pynumerics.errors import translate_public
23
+ from pynumerics.marshal import (
24
+ _net_rectangular,
25
+ _numpy_rectangular,
26
+ to_net_doubles,
27
+ to_net_ints,
28
+ to_net_singles,
29
+ to_numpy_doubles,
30
+ to_numpy_ints,
31
+ )
32
+
33
+
34
+ def _table_to_numpy(table: Any) -> np.ndarray:
35
+ """Copy a .NET ``float[,]`` routing table into a ``(nodes, 3)`` float32 array, bit for bit, in one copy."""
36
+ return _numpy_rectangular(table, np.float32)
37
+
38
+
39
+ def _table_to_net(table: Any) -> Any:
40
+ """Copy a ``(nodes, 3)`` array into a new .NET ``float[,]`` (rounded to float32) in one copy."""
41
+ array = np.asarray(table, dtype=np.float32)
42
+ if array.ndim != 2:
43
+ raise ValueError(f"Expected a 2-D routing table; got shape {array.shape}.")
44
+ return _net_rectangular(array)
45
+
46
+
47
+ def _singles(values: Any) -> Any:
48
+ """Copy edge weights into a ``System.Single[]`` (rounded to float32)."""
49
+ array = np.asarray(values, dtype=np.float32).reshape(1, 1, -1)
50
+ return to_net_singles(array)[0]
51
+
52
+
53
+ def _path(path: Any) -> np.ndarray | None:
54
+ """Copy a .NET ``List<int>`` of edge indices, or keep None."""
55
+ return None if path is None else to_numpy_ints(path.ToArray())
56
+
57
+
58
+ @dataclass(frozen=True, slots=True)
59
+ class Edge:
60
+ """A directed, weighted edge of a network (``Numerics.Mathematics.Optimization.Edge``).
61
+
62
+ Parameters
63
+ ----------
64
+ from_index : int
65
+ The start node.
66
+ to_index : int
67
+ The end node.
68
+ weight : float
69
+ The cost of the edge (stored as float32 by Numerics); infinity makes it impassable.
70
+ index : int
71
+ The edge index reported in paths and routing tables.
72
+ """
73
+
74
+ from_index: int
75
+ to_index: int
76
+ weight: float
77
+ index: int
78
+
79
+ @classmethod
80
+ def from_net(cls, net: Any) -> Edge:
81
+ """Copy a .NET ``Edge``.
82
+
83
+ Parameters
84
+ ----------
85
+ net : Numerics.Mathematics.Optimization.Edge
86
+ The .NET edge.
87
+
88
+ Returns
89
+ -------
90
+ Edge
91
+ The copy.
92
+ """
93
+ return cls(int(net.FromIndex), int(net.ToIndex), float(net.Weight), int(net.Index))
94
+
95
+ def to_net(self) -> Any:
96
+ """Return the .NET ``Edge``.
97
+
98
+ Returns
99
+ -------
100
+ Numerics.Mathematics.Optimization.Edge
101
+ A new .NET edge.
102
+ """
103
+ return _opt().Edge(int(self.from_index), int(self.to_index), float(self.weight), int(self.index))
104
+
105
+
106
+ def _edges(edges: Any) -> Any:
107
+ """Return the edges as a .NET ``Edge[]``.
108
+
109
+ Accepts :class:`Edge` values, ``(from, to, weight)`` or ``(from, to, weight, index)`` tuples (a
110
+ missing index is the position), or a .NET ``Edge[]`` passed through.
111
+ """
112
+ opt = _opt()
113
+ import System # noqa: PLC0415 - the runtime is running
114
+
115
+ if isinstance(edges, System.Array):
116
+ return edges
117
+ items = []
118
+ for position, edge in enumerate(edges):
119
+ if isinstance(edge, Edge):
120
+ items.append(edge.to_net())
121
+ continue
122
+ fields = tuple(edge)
123
+ index = int(fields[3]) if len(fields) > 3 else position
124
+ items.append(opt.Edge(int(fields[0]), int(fields[1]), float(fields[2]), index))
125
+ return System.Array[opt.Edge](items)
126
+
127
+
128
+ def _destinations(destinations: Any) -> Any:
129
+ """Return one destination as an int or several as a ``System.Int32[]``."""
130
+ if np.ndim(destinations) == 0:
131
+ return int(destinations)
132
+ return to_net_ints(destinations)
133
+
134
+
135
+ def dijkstra_solve(edges: Any, destinations: Any, node_count: int = -1) -> np.ndarray:
136
+ """Return the shortest-path routing table toward one or more destinations (``Dijkstra.Solve``).
137
+
138
+ Parameters
139
+ ----------
140
+ edges : sequence
141
+ :class:`Edge` values or ``(from, to, weight[, index])`` tuples.
142
+ destinations : int or array_like of int
143
+ One destination node, or several; each node routes to its cheapest one, earlier destinations
144
+ winning exact ties.
145
+ node_count : int, optional
146
+ Number of nodes; -1, the default, derives it from the edges.
147
+
148
+ Returns
149
+ -------
150
+ numpy.ndarray
151
+ The ``(nodes, 3)`` float32 routing table.
152
+ """
153
+ return _table_to_numpy(_opt().Dijkstra.Solve(_edges(edges), _destinations(destinations), int(node_count)))
154
+
155
+
156
+ def dijkstra_solve_nearest(edges: Any, destinations: Any, node_count: int = -1) -> np.ndarray:
157
+ """Return the routing table to the nearest destination in one multi-source pass (``Dijkstra.SolveNearest``).
158
+
159
+ Costs equal those of :func:`dijkstra_solve`; exact ties may route differently.
160
+
161
+ Parameters
162
+ ----------
163
+ edges : sequence
164
+ :class:`Edge` values or ``(from, to, weight[, index])`` tuples.
165
+ destinations : array_like of int
166
+ The destination nodes, at least one.
167
+ node_count : int, optional
168
+ Number of nodes; -1, the default, derives it from the edges.
169
+
170
+ Returns
171
+ -------
172
+ numpy.ndarray
173
+ The ``(nodes, 3)`` float32 routing table.
174
+ """
175
+ return _table_to_numpy(_opt().Dijkstra.SolveNearest(_edges(edges), to_net_ints(np.atleast_1d(destinations)),
176
+ int(node_count)))
177
+
178
+
179
+ def dijkstra_path_exists(table: Any, node: int) -> bool:
180
+ """Return whether a node reaches the destination in a routing table (``Dijkstra.PathExists``).
181
+
182
+ Parameters
183
+ ----------
184
+ table : array_like
185
+ A ``(nodes, 3)`` routing table.
186
+ node : int
187
+ The node.
188
+
189
+ Returns
190
+ -------
191
+ bool
192
+ True when the node's cost is finite.
193
+ """
194
+ return bool(_opt().Dijkstra.PathExists(_table_to_net(table), int(node)))
195
+
196
+
197
+ def dijkstra_get_path(table: Any, start: int) -> np.ndarray | None:
198
+ """Return the edge indices from a node to the destination (``Dijkstra.GetPath``).
199
+
200
+ Parameters
201
+ ----------
202
+ table : array_like
203
+ A ``(nodes, 3)`` routing table.
204
+ start : int
205
+ The start node.
206
+
207
+ Returns
208
+ -------
209
+ numpy.ndarray or None
210
+ The ordered int32 edge indices (empty at the destination), or None when unreachable.
211
+ """
212
+ return _path(_opt().Dijkstra.GetPath(_table_to_net(table), int(start)))
213
+
214
+
215
+ def dijkstra_try_get_path(table: Any, start: int) -> tuple[bool, np.ndarray, float]:
216
+ """Walk a routing table from a node, returning the path and its cost (``Dijkstra.TryGetPath``).
217
+
218
+ Parameters
219
+ ----------
220
+ table : array_like
221
+ A ``(nodes, 3)`` routing table.
222
+ start : int
223
+ The start node.
224
+
225
+ Returns
226
+ -------
227
+ tuple
228
+ ``(found, edge_indices, total_cost)``; an unreachable node gives ``(False, [], inf)``.
229
+ """
230
+ found, path, cost = _opt().Dijkstra.TryGetPath(_table_to_net(table), int(start), None, 0.0)
231
+ return bool(found), to_numpy_ints(path.ToArray()), float(cost)
232
+
233
+
234
+ def shortest_distances(graph: Any, sources: Any, limit: float = np.inf, *, return_predecessors: bool = False,
235
+ return_nearest_source: bool = False) -> Any:
236
+ """Return the double-precision distance of every node from its nearest source (``Dijkstra.ShortestDistances``).
237
+
238
+ The graph is directed, in compressed sparse row form: row ``n`` holds the edges leaving node ``n``. The
239
+ result matches ``scipy.sparse.csgraph.dijkstra(graph, indices=sources, min_only=True, limit=limit)``;
240
+ where SciPy reports -9999 for a missing predecessor or source, this function reports -1.
241
+
242
+ Parameters
243
+ ----------
244
+ graph : sparse matrix or tuple
245
+ A square SciPy sparse matrix or array (converted with ``tocsr()``; any other object with ``shape``,
246
+ ``indptr``, ``indices`` and ``data`` is read as CSR), or a ``(row_start, to_node, weight)`` tuple of
247
+ the CSR arrays. Weights must be non-negative; infinity makes
248
+ an edge impassable.
249
+ sources : int or array_like of int
250
+ The source nodes, each at distance zero. Integral floats are accepted; other floats raise ValueError.
251
+ limit : float, optional
252
+ The largest distance computed; farther nodes are reported unreachable. Default infinity.
253
+ return_predecessors : bool, optional
254
+ Also return the predecessor of each node on its shortest path (-1 for a source or an unreachable node).
255
+ return_nearest_source : bool, optional
256
+ Also return the source each shortest path starts from (-1 for an unreachable node).
257
+
258
+ Returns
259
+ -------
260
+ numpy.ndarray or tuple
261
+ The float64 distances, infinity where unreachable; with either flag, a tuple ``(distances, ...)``
262
+ holding the requested int32 arrays in the order predecessors, nearest source.
263
+
264
+ Raises
265
+ ------
266
+ ValueError
267
+ If the matrix is not square, a source is not integral, or the CSR arrays are inconsistent (raised by
268
+ Numerics).
269
+ TypeError
270
+ If the sources are not numbers.
271
+ """
272
+ dijkstra = _opt().Dijkstra
273
+ import System # noqa: PLC0415 - the namespace import above starts the runtime
274
+
275
+ if isinstance(graph, tuple):
276
+ row_start, to_node, weight = graph
277
+ node_count = len(row_start) - 1
278
+ else:
279
+ rows, cols = graph.shape
280
+ if rows != cols:
281
+ raise ValueError(f"The graph matrix must be square; got shape {graph.shape}.")
282
+ if hasattr(graph, "tocsr"):
283
+ # A CSC (or other) sparse matrix also has indptr/indices/data, which would read as the transpose.
284
+ graph = graph.tocsr()
285
+ row_start, to_node, weight, node_count = graph.indptr, graph.indices, graph.data, rows
286
+ source_array = np.atleast_1d(np.asarray(sources))
287
+ if source_array.dtype.kind == "f":
288
+ if not np.all(np.isfinite(source_array) & (source_array == np.floor(source_array))):
289
+ raise ValueError("The sources must be integral node indices.")
290
+ elif source_array.dtype.kind not in "iu":
291
+ raise TypeError(f"The sources must be integer node indices; got dtype {source_array.dtype}.")
292
+ # The typed array constructor binds once; Array.CreateInstance resolves its overloads on every call.
293
+ ints = System.Array[System.Int32]
294
+ predecessors = ints(node_count) if return_predecessors else None
295
+ nearest = ints(node_count) if return_nearest_source else None
296
+ distances = to_numpy_doubles(dijkstra.ShortestDistances(
297
+ int(node_count), to_net_ints(row_start), to_net_ints(to_node), to_net_doubles(weight),
298
+ to_net_ints(source_array), float(limit), predecessors, nearest))
299
+ if not (return_predecessors or return_nearest_source):
300
+ return distances
301
+ result = [distances]
302
+ if return_predecessors:
303
+ result.append(to_numpy_ints(predecessors))
304
+ if return_nearest_source:
305
+ result.append(to_numpy_ints(nearest))
306
+ return tuple(result)
307
+
308
+
309
+ class Network:
310
+ """A compiled directed network with fixed destinations (``Numerics.Mathematics.Optimization.Network``).
311
+
312
+ Parameters
313
+ ----------
314
+ edges : sequence
315
+ :class:`Edge` values or ``(from, to, weight[, index])`` tuples.
316
+ destination_indices : array_like of int
317
+ The destination nodes.
318
+
319
+ Attributes
320
+ ----------
321
+ net : Numerics.Mathematics.Optimization.Network
322
+ The wrapped .NET network.
323
+ """
324
+
325
+ def __init__(self, edges: Any, destination_indices: Any) -> None:
326
+ self.net = _opt().Network(_edges(edges), to_net_ints(np.atleast_1d(destination_indices)))
327
+ self._table: Any = None
328
+
329
+ @property
330
+ def destination_indices(self) -> np.ndarray:
331
+ """The destination nodes (``DestinationIndices``)."""
332
+ return to_numpy_ints(self.net.DestinationIndices)
333
+
334
+ @property
335
+ def incoming_edges(self) -> list[list[Edge]]:
336
+ """The incoming edges of each node, in edge order (``IncomingEdges``)."""
337
+ return [[Edge.from_net(e) for e in node] for node in self.net.IncomingEdges]
338
+
339
+ @property
340
+ def outgoing_edges(self) -> list[list[Edge]]:
341
+ """The outgoing edges of each node, in edge order (``OutgoingEdges``)."""
342
+ return [[Edge.from_net(e) for e in node] for node in self.net.OutgoingEdges]
343
+
344
+ @property
345
+ def node_count(self) -> int:
346
+ """The number of nodes (``NodeCount``)."""
347
+ return int(self.net.NodeCount)
348
+
349
+ def _reused_table(self) -> Any:
350
+ """Return the .NET table the reuse overloads fill, allocated once per network."""
351
+ if self._table is None:
352
+ import System # noqa: PLC0415 - the runtime is running
353
+
354
+ self._table = System.Array.CreateInstance(System.Single, self.node_count, 3)
355
+ return self._table
356
+
357
+ def solve(self, destinations: Any = None, *, edge_weights: Any = None, reuse: bool = False) -> np.ndarray:
358
+ """Return the routing table toward the destinations (``Network.Solve``).
359
+
360
+ Parameters
361
+ ----------
362
+ destinations : int or array_like of int, optional
363
+ Destinations to solve for; None uses the network's. Not allowed with ``edge_weights``.
364
+ edge_weights : array_like, optional
365
+ Custom weights, one per edge in constructor order, toward the network's destinations.
366
+ reuse : bool, optional
367
+ With ``edge_weights``, fill one .NET table kept by the network (the allocation-free
368
+ ``Solve(float[], float[,])`` overload) instead of a new one; default False.
369
+
370
+ Returns
371
+ -------
372
+ numpy.ndarray
373
+ The ``(nodes, 3)`` float32 routing table.
374
+
375
+ Raises
376
+ ------
377
+ ValueError
378
+ If both ``destinations`` and ``edge_weights`` are given.
379
+ """
380
+ if edge_weights is not None:
381
+ if destinations is not None:
382
+ raise ValueError("Custom edge weights solve toward the network's destinations; omit destinations.")
383
+ if reuse:
384
+ table = self._reused_table()
385
+ self.net.Solve(_singles(edge_weights), table)
386
+ return _table_to_numpy(table)
387
+ return _table_to_numpy(self.net.Solve(_singles(edge_weights)))
388
+ if destinations is None:
389
+ destinations = self.net.DestinationIndices
390
+ return _table_to_numpy(self.net.Solve(destinations))
391
+ return _table_to_numpy(self.net.Solve(_destinations(destinations)))
392
+
393
+ def solve_nearest(self, *, edge_weights: Any = None, reuse: bool = False) -> np.ndarray:
394
+ """Return the routing table to the nearest destination in one pass (``Network.SolveNearest``).
395
+
396
+ Parameters
397
+ ----------
398
+ edge_weights : array_like, optional
399
+ Custom weights, one per edge; None uses the constructor's.
400
+ reuse : bool, optional
401
+ With ``edge_weights``, fill one .NET table kept by the network; default False.
402
+
403
+ Returns
404
+ -------
405
+ numpy.ndarray
406
+ The ``(nodes, 3)`` float32 routing table.
407
+ """
408
+ if edge_weights is None:
409
+ return _table_to_numpy(self.net.SolveNearest())
410
+ table = self._reused_table() if reuse else _table_to_net(np.zeros((self.node_count, 3)))
411
+ self.net.SolveNearest(_singles(edge_weights), table)
412
+ return _table_to_numpy(table)
413
+
414
+ def get_path(self, edges_to_remove: Any, start: int, table: Any = None,
415
+ edge_weights: Any = None) -> np.ndarray | None:
416
+ """Return the shortest path from a node avoiding some edges (``Network.GetPath``).
417
+
418
+ Parameters
419
+ ----------
420
+ edges_to_remove : array_like of int
421
+ Edge indices to exclude.
422
+ start : int
423
+ The start node.
424
+ table : array_like, optional
425
+ A routing table solved on this network without exclusions; its route is reused when it
426
+ avoids every excluded edge.
427
+ edge_weights : array_like, optional
428
+ The custom weights ``table`` was solved with.
429
+
430
+ Returns
431
+ -------
432
+ numpy.ndarray or None
433
+ The ordered int32 edge indices. Without ``table`` an unreachable start gives None; with a
434
+ table it gives an empty array, as Numerics does.
435
+ """
436
+ removed = to_net_ints(np.asarray(edges_to_remove, dtype=np.int64).ravel())
437
+ if table is None:
438
+ return _path(self.net.GetPath(removed, int(start)))
439
+ if edge_weights is None:
440
+ return _path(self.net.GetPath(removed, int(start), _table_to_net(table)))
441
+ return _path(self.net.GetPath(removed, int(start), _table_to_net(table), _singles(edge_weights)))
442
+
443
+
444
+ @dataclass(frozen=True, slots=True)
445
+ class HeapNode:
446
+ """A node of a :class:`BinaryHeap` (``BinaryHeap<T>.Node``).
447
+
448
+ Parameters
449
+ ----------
450
+ weight : float
451
+ The priority (stored as float32 by Numerics).
452
+ index : int
453
+ The key the keyed operations address, in [0, heap size).
454
+ value : object, optional
455
+ Any value carried with the node.
456
+ """
457
+
458
+ weight: float
459
+ index: int
460
+ value: Any = None
461
+
462
+
463
+ class BinaryHeap:
464
+ """A fixed-capacity keyed binary min-heap (``Numerics.Mathematics.Optimization.BinaryHeap<object>``).
465
+
466
+ Parameters
467
+ ----------
468
+ heap_size : int
469
+ The capacity; node indices lie in [0, heap_size).
470
+
471
+ Attributes
472
+ ----------
473
+ net : Numerics.Mathematics.Optimization.BinaryHeap
474
+ The wrapped .NET heap of ``object`` values.
475
+ """
476
+
477
+ def __init__(self, heap_size: int) -> None:
478
+ import clr # noqa: PLC0415 - the namespace import starts the runtime
479
+ import System # noqa: PLC0415
480
+
481
+ heap_type = _opt().BinaryHeap[System.Object]
482
+ self.net = heap_type(int(heap_size))
483
+ node = clr.GetClrType(heap_type).GetNestedType("Node")
484
+ self._node_type = node.MakeGenericType(System.Array[System.Type]([clr.GetClrType(System.Object)]))
485
+
486
+ def _node(self, node: HeapNode) -> Any:
487
+ """Build the .NET node."""
488
+ import System # noqa: PLC0415 - the runtime is running
489
+
490
+ arguments = System.Array[System.Object]([System.Single(float(node.weight)), System.Int32(int(node.index)),
491
+ node.value])
492
+ return System.Activator.CreateInstance(self._node_type, arguments)
493
+
494
+ @property
495
+ def count(self) -> int:
496
+ """The number of nodes in the heap (``Count``)."""
497
+ return int(self.net.Count)
498
+
499
+ def __len__(self) -> int:
500
+ """Return the number of nodes in the heap.
501
+
502
+ Returns
503
+ -------
504
+ int
505
+ The count.
506
+ """
507
+ return self.count
508
+
509
+ def add(self, node: HeapNode) -> None:
510
+ """Add a node (``Add``).
511
+
512
+ Parameters
513
+ ----------
514
+ node : HeapNode
515
+ The node.
516
+ """
517
+ self.net.Add(self._node(node))
518
+
519
+ def remove_min(self) -> HeapNode:
520
+ """Remove and return the lightest node (``RemoveMin``).
521
+
522
+ Returns
523
+ -------
524
+ HeapNode
525
+ The node with the smallest weight.
526
+ """
527
+ node = self.net.RemoveMin()
528
+ return HeapNode(float(node.Weight), int(node.Index), node.Value)
529
+
530
+ def decrease_key(self, node: HeapNode) -> None:
531
+ """Lower the weight of the node with the same index, or add it when absent (``DecreaseKey``).
532
+
533
+ Parameters
534
+ ----------
535
+ node : HeapNode
536
+ The index to address and the candidate weight; a larger weight is ignored.
537
+ """
538
+ self.net.DecreaseKey(self._node(node))
539
+
540
+ def replace(self, node: HeapNode) -> None:
541
+ """Replace the weight and value of the node with the same index (``Replace``).
542
+
543
+ Parameters
544
+ ----------
545
+ node : HeapNode
546
+ The index to address and the replacement weight and value; an absent index does nothing.
547
+ """
548
+ self.net.Replace(self._node(node))
549
+
550
+
551
+ __all__ = [
552
+ "BinaryHeap", "Edge", "HeapNode", "Network", "dijkstra_get_path", "dijkstra_path_exists", "dijkstra_solve",
553
+ "dijkstra_solve_nearest", "dijkstra_try_get_path", "shortest_distances",
554
+ ]
555
+
556
+ translate_public(globals())