scientific-computing-system 1.6.2__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 (97) hide show
  1. cds/__init__.py +102 -0
  2. cds/__main__.py +8 -0
  3. cds/_version.py +10 -0
  4. cds/cli/__init__.py +104 -0
  5. cds/cli/__main__.py +8 -0
  6. cds/cli/_handlers.py +405 -0
  7. cds/cli/_parser.py +156 -0
  8. cds/cli/_style.py +117 -0
  9. cds/core/__init__.py +5 -0
  10. cds/core/_numeric.py +92 -0
  11. cds/core/models.py +166 -0
  12. cds/data_analysis/__init__.py +30 -0
  13. cds/data_analysis/dataset.py +122 -0
  14. cds/data_analysis/loader.py +75 -0
  15. cds/data_analysis/pandas_io.py +108 -0
  16. cds/data_analysis/transform.py +36 -0
  17. cds/data_analysis/viz.py +88 -0
  18. cds/diffeq/__init__.py +29 -0
  19. cds/diffeq/_implicit.py +349 -0
  20. cds/diffeq/solvers.py +312 -0
  21. cds/graph/__init__.py +31 -0
  22. cds/graph/algorithms.py +399 -0
  23. cds/hypothesis/__init__.py +48 -0
  24. cds/hypothesis/evaluator.py +369 -0
  25. cds/hypothesis/generator.py +275 -0
  26. cds/knowledge/__init__.py +41 -0
  27. cds/knowledge/graph.py +489 -0
  28. cds/knowledge/notes.py +231 -0
  29. cds/knowledge/retrieval.py +167 -0
  30. cds/math_utils/__init__.py +41 -0
  31. cds/math_utils/calculus.py +40 -0
  32. cds/math_utils/linalg.py +461 -0
  33. cds/math_utils/special.py +167 -0
  34. cds/ml/__init__.py +25 -0
  35. cds/ml/clustering.py +190 -0
  36. cds/ml/decomposition.py +172 -0
  37. cds/ml/linear_models.py +225 -0
  38. cds/ml/neighbors.py +162 -0
  39. cds/ml/neural.py +204 -0
  40. cds/ml/preprocessing.py +131 -0
  41. cds/ml/tree.py +202 -0
  42. cds/modeling/__init__.py +40 -0
  43. cds/modeling/_base.py +210 -0
  44. cds/modeling/_nodes.py +526 -0
  45. cds/modeling/expression.py +81 -0
  46. cds/modeling/model.py +134 -0
  47. cds/modeling/solver.py +176 -0
  48. cds/montecarlo/__init__.py +21 -0
  49. cds/montecarlo/methods.py +272 -0
  50. cds/nlp/__init__.py +170 -0
  51. cds/nlp/attention.py +285 -0
  52. cds/nlp/autograd/__init__.py +70 -0
  53. cds/nlp/autograd/_grad.py +120 -0
  54. cds/nlp/autograd/ops.py +133 -0
  55. cds/nlp/autograd/tensor.py +298 -0
  56. cds/nlp/bpe.py +449 -0
  57. cds/nlp/data.py +70 -0
  58. cds/nlp/embed.py +190 -0
  59. cds/nlp/layers.py +259 -0
  60. cds/nlp/model.py +456 -0
  61. cds/nlp/optim.py +163 -0
  62. cds/nlp/training.py +167 -0
  63. cds/nlp/viz.py +254 -0
  64. cds/numerical_integration/__init__.py +31 -0
  65. cds/numerical_integration/quadrature.py +480 -0
  66. cds/optimization/__init__.py +18 -0
  67. cds/optimization/_metaheuristics.py +287 -0
  68. cds/optimization/minimize.py +425 -0
  69. cds/plot/__init__.py +49 -0
  70. cds/plot/_backend.py +32 -0
  71. cds/plot/charts.py +462 -0
  72. cds/probability/__init__.py +55 -0
  73. cds/probability/_advanced.py +283 -0
  74. cds/probability/distributions.py +236 -0
  75. cds/py.typed +0 -0
  76. cds/quantum/__init__.py +51 -0
  77. cds/quantum/circuit.py +92 -0
  78. cds/quantum/multi_qubit.py +255 -0
  79. cds/quantum/simulator.py +38 -0
  80. cds/scientific/__init__.py +34 -0
  81. cds/scientific/constants.py +35 -0
  82. cds/scientific/formulas.py +116 -0
  83. cds/signals/__init__.py +43 -0
  84. cds/signals/filters.py +421 -0
  85. cds/signals/processing.py +224 -0
  86. cds/stats/__init__.py +83 -0
  87. cds/stats/_distributions.py +102 -0
  88. cds/stats/descriptive.py +172 -0
  89. cds/stats/hypothesis_tests.py +403 -0
  90. cds/stats/nonparametric.py +131 -0
  91. cds/stats/regression.py +51 -0
  92. cds/stats/time_series.py +408 -0
  93. scientific_computing_system-1.6.2.dist-info/METADATA +741 -0
  94. scientific_computing_system-1.6.2.dist-info/RECORD +97 -0
  95. scientific_computing_system-1.6.2.dist-info/WHEEL +4 -0
  96. scientific_computing_system-1.6.2.dist-info/entry_points.txt +2 -0
  97. scientific_computing_system-1.6.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,399 @@
1
+ """Graph algorithms — standard implementations from Cormen et al. (CLRS).
2
+
3
+ References:
4
+ - Cormen, Leiserson, Rivest, Stein. Introduction to Algorithms (4th ed.)
5
+ - Dijkstra, E.W. (1959). A note on two problems in connexion with graphs.
6
+ - Kruskal, J.B. (1956). On the shortest spanning subtree of a graph.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import heapq
12
+ import math
13
+ from collections import deque
14
+ from dataclasses import dataclass, field
15
+
16
+
17
+ @dataclass
18
+ class Edge:
19
+ """Weighted edge in a graph."""
20
+
21
+ src: int
22
+ dst: int
23
+ weight: float = 1.0
24
+
25
+
26
+ @dataclass
27
+ class Graph:
28
+ """Adjacency-list graph representation.
29
+
30
+ Supports both directed and undirected graphs with weighted edges.
31
+ """
32
+
33
+ n_vertices: int
34
+ directed: bool = False
35
+ adj: dict[int, list[tuple[int, float]]] = field(default_factory=dict)
36
+ edges: list[Edge] = field(default_factory=list)
37
+
38
+ def add_edge(self, u: int, v: int, weight: float = 1.0) -> None:
39
+ """Add an edge from u to v (and v to u if undirected)."""
40
+ self.adj.setdefault(u, []).append((v, weight))
41
+ if not self.directed:
42
+ self.adj.setdefault(v, []).append((u, weight))
43
+ self.edges.append(Edge(u, v, weight))
44
+
45
+
46
+ def bfs(graph: Graph, start: int) -> list[int]:
47
+ """Breadth-first search traversal.
48
+
49
+ Returns vertices in BFS order starting from `start`.
50
+ Time complexity: O(V + E) [CLRS §22.2]
51
+ """
52
+ visited: set[int] = set()
53
+ order: list[int] = []
54
+ queue: deque[int] = deque([start])
55
+ visited.add(start)
56
+
57
+ while queue:
58
+ node = queue.popleft()
59
+ order.append(node)
60
+ for neighbor, _ in graph.adj.get(node, []):
61
+ if neighbor not in visited:
62
+ visited.add(neighbor)
63
+ queue.append(neighbor)
64
+ return order
65
+
66
+
67
+ def dfs(graph: Graph, start: int) -> list[int]:
68
+ """Depth-first search traversal (iterative).
69
+
70
+ Returns vertices in DFS order starting from `start`.
71
+ Time complexity: O(V + E) [CLRS §22.3]
72
+ """
73
+ visited: set[int] = set()
74
+ order: list[int] = []
75
+ stack: list[int] = [start]
76
+
77
+ while stack:
78
+ node = stack.pop()
79
+ if node in visited:
80
+ continue
81
+ visited.add(node)
82
+ order.append(node)
83
+ for neighbor, _ in reversed(graph.adj.get(node, [])):
84
+ if neighbor not in visited:
85
+ stack.append(neighbor)
86
+ return order
87
+
88
+
89
+ def dijkstra(
90
+ graph: Graph,
91
+ start: int,
92
+ ) -> tuple[dict[int, float], dict[int, int | None]]:
93
+ """Dijkstra's shortest path algorithm.
94
+
95
+ Returns (distances, predecessors) from `start` to all reachable vertices.
96
+ Time complexity: O((V + E) log V) with binary heap [Dijkstra 1959]
97
+
98
+ Args:
99
+ graph: weighted graph (non-negative weights)
100
+ start: source vertex
101
+
102
+ Returns:
103
+ distances: dict mapping vertex -> shortest distance from start
104
+ predecessors: dict mapping vertex -> previous vertex on shortest path
105
+
106
+ Raises:
107
+ ValueError: if a negative weight is encountered
108
+ """
109
+ dist: dict[int, float] = {start: 0.0}
110
+ prev: dict[int, int | None] = {start: None}
111
+ heap: list[tuple[float, int]] = [(0.0, start)]
112
+ visited: set[int] = set()
113
+
114
+ while heap:
115
+ d, u = heapq.heappop(heap)
116
+ if u in visited:
117
+ continue
118
+ visited.add(u)
119
+
120
+ for v, w in graph.adj.get(u, []):
121
+ if w < 0:
122
+ raise ValueError("negative edge weights not supported")
123
+ new_dist = d + w
124
+ if v not in dist or new_dist < dist[v]:
125
+ dist[v] = new_dist
126
+ prev[v] = u
127
+ heapq.heappush(heap, (new_dist, v))
128
+
129
+ return dist, prev
130
+
131
+
132
+ def _find(parent: dict[int, int], x: int) -> int:
133
+ """Union-Find: find with path compression."""
134
+ while parent[x] != x:
135
+ parent[x] = parent[parent[x]]
136
+ x = parent[x]
137
+ return x
138
+
139
+
140
+ def _union(
141
+ parent: dict[int, int],
142
+ rank: dict[int, int],
143
+ a: int,
144
+ b: int,
145
+ ) -> bool:
146
+ """Union-Find: union by rank. Returns True if merged."""
147
+ ra, rb = _find(parent, a), _find(parent, b)
148
+ if ra == rb:
149
+ return False
150
+ if rank[ra] < rank[rb]:
151
+ ra, rb = rb, ra
152
+ parent[rb] = ra
153
+ if rank[ra] == rank[rb]:
154
+ rank[ra] += 1
155
+ return True
156
+
157
+
158
+ def kruskal_mst(graph: Graph) -> tuple[list[Edge], float]:
159
+ """Kruskal's minimum spanning tree algorithm.
160
+
161
+ Time complexity: O(E log E) [Kruskal 1956]
162
+
163
+ Args:
164
+ graph: undirected weighted graph
165
+
166
+ Returns:
167
+ mst_edges: list of edges in the MST
168
+ total_weight: sum of edge weights in the MST
169
+ """
170
+ sorted_edges = sorted(graph.edges, key=lambda e: e.weight)
171
+ parent = {i: i for i in range(graph.n_vertices)}
172
+ rank = {i: 0 for i in range(graph.n_vertices)}
173
+
174
+ mst: list[Edge] = []
175
+ total = 0.0
176
+
177
+ for edge in sorted_edges:
178
+ if _union(parent, rank, edge.src, edge.dst):
179
+ mst.append(edge)
180
+ total += edge.weight
181
+ if len(mst) == graph.n_vertices - 1:
182
+ break
183
+
184
+ return mst, total
185
+
186
+
187
+ def topological_sort(graph: Graph) -> list[int]:
188
+ """Kahn's algorithm for topological sort of a DAG.
189
+
190
+ Time complexity: O(V + E) [CLRS §22.4]
191
+
192
+ Args:
193
+ graph: directed acyclic graph
194
+
195
+ Returns:
196
+ list of vertices in topological order
197
+
198
+ Raises:
199
+ ValueError: if graph contains a cycle
200
+ """
201
+ in_degree: dict[int, int] = {i: 0 for i in range(graph.n_vertices)}
202
+ for u in graph.adj:
203
+ for v, _ in graph.adj[u]:
204
+ in_degree[v] = in_degree.get(v, 0) + 1
205
+
206
+ queue: deque[int] = deque(v for v in range(graph.n_vertices) if in_degree.get(v, 0) == 0)
207
+ order: list[int] = []
208
+
209
+ while queue:
210
+ u = queue.popleft()
211
+ order.append(u)
212
+ for v, _ in graph.adj.get(u, []):
213
+ in_degree[v] -= 1
214
+ if in_degree[v] == 0:
215
+ queue.append(v)
216
+
217
+ if len(order) != graph.n_vertices:
218
+ raise ValueError("graph contains a cycle")
219
+ return order
220
+
221
+
222
+ def has_cycle(graph: Graph) -> bool:
223
+ """Detect if a directed graph has a cycle using DFS coloring.
224
+
225
+ Time complexity: O(V + E)
226
+
227
+ WHITE=0 (unvisited), GRAY=1 (in current DFS path), BLACK=2 (finished).
228
+ """
229
+ WHITE, GRAY, BLACK = 0, 1, 2
230
+ color: dict[int, int] = {i: WHITE for i in range(graph.n_vertices)}
231
+
232
+ def _dfs(u: int) -> bool:
233
+ color[u] = GRAY
234
+ for v, _ in graph.adj.get(u, []):
235
+ if color[v] == GRAY:
236
+ return True
237
+ if color[v] == WHITE and _dfs(v):
238
+ return True
239
+ color[u] = BLACK
240
+ return False
241
+
242
+ return any(_dfs(v) for v in range(graph.n_vertices) if color[v] == WHITE)
243
+
244
+
245
+ def degree(graph: Graph, v: int) -> int:
246
+ """Degree of vertex ``v`` (out-degree if directed)."""
247
+ if v < 0 or v >= graph.n_vertices:
248
+ raise ValueError(f"vertex {v} out of range [0, {graph.n_vertices})")
249
+ return len(graph.adj.get(v, []))
250
+
251
+
252
+ def connected_components(graph: Graph) -> list[list[int]]:
253
+ """Connected components of an undirected graph (BFS forests).
254
+
255
+ For directed graphs, returns weakly connected components (ignores direction).
256
+ """
257
+ # Build undirected adjacency for weak connectivity.
258
+ undirected: dict[int, set[int]] = {i: set() for i in range(graph.n_vertices)}
259
+ for u, nbrs in graph.adj.items():
260
+ for v, _ in nbrs:
261
+ undirected[u].add(v)
262
+ undirected[v].add(u)
263
+
264
+ remaining = set(range(graph.n_vertices))
265
+ components: list[list[int]] = []
266
+ while remaining:
267
+ start = min(remaining)
268
+ visited: set[int] = set()
269
+ queue: deque[int] = deque([start])
270
+ visited.add(start)
271
+ order: list[int] = []
272
+ while queue:
273
+ u = queue.popleft()
274
+ order.append(u)
275
+ for v in undirected[u]:
276
+ if v not in visited:
277
+ visited.add(v)
278
+ queue.append(v)
279
+ components.append(sorted(order))
280
+ remaining -= visited
281
+ return components
282
+
283
+
284
+ def bellman_ford(
285
+ graph: Graph,
286
+ start: int,
287
+ ) -> tuple[dict[int, float], dict[int, int | None]]:
288
+ """Bellman–Ford single-source shortest paths (allows negative weights).
289
+
290
+ Returns ``(distances, predecessors)``. Unreachable vertices are omitted
291
+ from ``distances``. Raises ``ValueError`` if a negative cycle is reachable
292
+ from ``start``.
293
+ """
294
+ if start < 0 or start >= graph.n_vertices:
295
+ raise ValueError(f"start vertex {start} out of range")
296
+ dist: dict[int, float] = {start: 0.0}
297
+ prev: dict[int, int | None] = {start: None}
298
+
299
+ for _ in range(graph.n_vertices - 1):
300
+ updated = False
301
+ for e in graph.edges:
302
+ if e.src not in dist:
303
+ continue
304
+ nd = dist[e.src] + e.weight
305
+ if e.dst not in dist or nd < dist[e.dst]:
306
+ dist[e.dst] = nd
307
+ prev[e.dst] = e.src
308
+ updated = True
309
+ if not graph.directed and e.dst in dist:
310
+ # undirected: edges list stores one direction; relax reverse too
311
+ nd_r = dist[e.dst] + e.weight
312
+ if e.src not in dist or nd_r < dist[e.src]:
313
+ dist[e.src] = nd_r
314
+ prev[e.src] = e.dst
315
+ updated = True
316
+ if not updated:
317
+ break
318
+
319
+ # Negative cycle detection
320
+ for e in graph.edges:
321
+ if e.src in dist and (e.dst not in dist or dist[e.src] + e.weight < dist[e.dst]):
322
+ raise ValueError("negative cycle detected")
323
+ # Undirected reverse check (usually already caught by the forward test).
324
+ if (
325
+ not graph.directed
326
+ and e.dst in dist
327
+ and (e.src not in dist or dist[e.dst] + e.weight < dist[e.src])
328
+ ): # pragma: no cover
329
+ raise ValueError("negative cycle detected")
330
+ return dist, prev
331
+
332
+
333
+ def floyd_warshall(graph: Graph) -> list[list[float]]:
334
+ """All-pairs shortest paths (Floyd–Warshall).
335
+
336
+ Returns an ``n x n`` distance matrix. Unreachable pairs are ``math.inf``.
337
+ Raises ``ValueError`` if a negative cycle exists on the diagonal.
338
+ """
339
+ n = graph.n_vertices
340
+ dist: list[list[float]] = [[math.inf] * n for _ in range(n)]
341
+ for i in range(n):
342
+ dist[i][i] = 0.0
343
+ for e in graph.edges:
344
+ if e.weight < dist[e.src][e.dst]:
345
+ dist[e.src][e.dst] = e.weight
346
+ if not graph.directed and e.weight < dist[e.dst][e.src]:
347
+ dist[e.dst][e.src] = e.weight
348
+
349
+ for k in range(n):
350
+ for i in range(n):
351
+ dik = dist[i][k]
352
+ if dik == math.inf:
353
+ continue
354
+ for j in range(n):
355
+ cand = dik + dist[k][j]
356
+ if cand < dist[i][j]:
357
+ dist[i][j] = cand
358
+
359
+ for i in range(n):
360
+ if dist[i][i] < 0:
361
+ raise ValueError("negative cycle detected")
362
+ return dist
363
+
364
+
365
+ def prim_mst(graph: Graph, start: int = 0) -> tuple[list[Edge], float]:
366
+ """Prim's MST algorithm (binary heap), undirected graphs.
367
+
368
+ Returns ``(mst_edges, total_weight)``.
369
+ """
370
+ if graph.directed:
371
+ raise ValueError("prim_mst requires an undirected graph")
372
+ if graph.n_vertices == 0:
373
+ return [], 0.0
374
+ if start < 0 or start >= graph.n_vertices:
375
+ raise ValueError(f"start vertex {start} out of range")
376
+
377
+ in_mst = [False] * graph.n_vertices
378
+ # (weight, u, v) — edge u->v to add v
379
+ heap: list[tuple[float, int, int]] = [(0.0, start, start)]
380
+ mst: list[Edge] = []
381
+ total = 0.0
382
+ parent: dict[int, int | None] = {start: None}
383
+ best: dict[int, float] = {start: 0.0}
384
+
385
+ while heap and len(mst) < graph.n_vertices:
386
+ w, u, v = heapq.heappop(heap)
387
+ if in_mst[v]:
388
+ continue
389
+ in_mst[v] = True
390
+ if u != v:
391
+ mst.append(Edge(u, v, w))
392
+ total += w
393
+ for nbr, wt in graph.adj.get(v, []):
394
+ if not in_mst[nbr] and (nbr not in best or wt < best[nbr]):
395
+ best[nbr] = wt
396
+ parent[nbr] = v
397
+ heapq.heappush(heap, (wt, v, nbr))
398
+
399
+ return mst, total
@@ -0,0 +1,48 @@
1
+ """
2
+ Hypothesis generation and evaluation module for Cognitive Discovery.
3
+
4
+ Provides tools to generate structured scientific hypotheses from
5
+ research questions. Includes prompt templates and an offline
6
+ generator for immediate use, plus a clear Protocol for supplying
7
+ custom generator implementations for specialized research needs.
8
+
9
+ The focus is on making hypotheses falsifiable, with explicit
10
+ assumptions, predictions, and confidence estimates.
11
+
12
+ Example:
13
+ from cds.hypothesis import generate_hypotheses
14
+
15
+ hypos = generate_hypotheses(
16
+ "Why do we observe the Hubble tension?",
17
+ domain="cosmology",
18
+ n=3
19
+ )
20
+ """
21
+
22
+ from cds.core.models import Domain, Hypothesis, HypothesisStatus
23
+ from cds.hypothesis.evaluator import (
24
+ ChiSquareGofPayload,
25
+ EvaluationData,
26
+ EvaluationResult,
27
+ HypothesisEvaluator,
28
+ )
29
+ from cds.hypothesis.generator import (
30
+ HypothesisGenerator,
31
+ PromptTemplate,
32
+ SimpleOfflineGenerator,
33
+ generate_hypotheses,
34
+ )
35
+
36
+ __all__ = [
37
+ "Domain",
38
+ "Hypothesis",
39
+ "HypothesisStatus",
40
+ "HypothesisGenerator",
41
+ "PromptTemplate",
42
+ "SimpleOfflineGenerator",
43
+ "generate_hypotheses",
44
+ "HypothesisEvaluator",
45
+ "EvaluationData",
46
+ "ChiSquareGofPayload",
47
+ "EvaluationResult",
48
+ ]