flopscope 0.2.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.
- benchmarks/__init__.py +1 -0
- benchmarks/__main__.py +6 -0
- benchmarks/_baseline.py +171 -0
- benchmarks/_bitwise.py +231 -0
- benchmarks/_complex.py +176 -0
- benchmarks/_contractions.py +291 -0
- benchmarks/_fft.py +198 -0
- benchmarks/_impl_urls.py +139 -0
- benchmarks/_linalg.py +197 -0
- benchmarks/_linalg_delegates.py +407 -0
- benchmarks/_metadata.py +141 -0
- benchmarks/_misc.py +653 -0
- benchmarks/_perf.py +321 -0
- benchmarks/_perm_group_calibration.py +175 -0
- benchmarks/_pointwise.py +372 -0
- benchmarks/_polynomial.py +193 -0
- benchmarks/_random.py +209 -0
- benchmarks/_reductions.py +136 -0
- benchmarks/_sorting.py +289 -0
- benchmarks/_stats.py +137 -0
- benchmarks/_window.py +92 -0
- benchmarks/accumulation/__init__.py +0 -0
- benchmarks/accumulation/bench_cost_compute.py +138 -0
- benchmarks/dashboard.py +312 -0
- benchmarks/runner.py +636 -0
- flopscope/__init__.py +273 -0
- flopscope/_accumulation/__init__.py +13 -0
- flopscope/_accumulation/_bipartite.py +121 -0
- flopscope/_accumulation/_burnside.py +51 -0
- flopscope/_accumulation/_cache.py +146 -0
- flopscope/_accumulation/_components.py +153 -0
- flopscope/_accumulation/_cost.py +1414 -0
- flopscope/_accumulation/_cost_descriptions.py +63 -0
- flopscope/_accumulation/_detection.py +318 -0
- flopscope/_accumulation/_ladder.py +191 -0
- flopscope/_accumulation/_output_orbit.py +104 -0
- flopscope/_accumulation/_partition.py +290 -0
- flopscope/_accumulation/_path_info.py +211 -0
- flopscope/_accumulation/_public.py +169 -0
- flopscope/_accumulation/_reduction.py +310 -0
- flopscope/_accumulation/_regimes.py +303 -0
- flopscope/_accumulation/_shape.py +33 -0
- flopscope/_accumulation/_wreath.py +209 -0
- flopscope/_budget.py +1027 -0
- flopscope/_config.py +118 -0
- flopscope/_counting_ops.py +451 -0
- flopscope/_display.py +478 -0
- flopscope/_docstrings.py +59 -0
- flopscope/_dtypes.py +20 -0
- flopscope/_einsum.py +717 -0
- flopscope/_errstate.py +25 -0
- flopscope/_flops.py +282 -0
- flopscope/_free_ops.py +2654 -0
- flopscope/_ndarray.py +1126 -0
- flopscope/_opt_einsum/LICENSE +21 -0
- flopscope/_opt_einsum/NOTICE +59 -0
- flopscope/_opt_einsum/__init__.py +209 -0
- flopscope/_opt_einsum/_contract.py +1478 -0
- flopscope/_opt_einsum/_helpers.py +164 -0
- flopscope/_opt_einsum/_hsluv.py +273 -0
- flopscope/_opt_einsum/_path_random.py +462 -0
- flopscope/_opt_einsum/_paths.py +1653 -0
- flopscope/_opt_einsum/_subgraph_symmetry.py +544 -0
- flopscope/_opt_einsum/_symmetry.py +140 -0
- flopscope/_opt_einsum/_typing.py +37 -0
- flopscope/_perm_group.py +717 -0
- flopscope/_pointwise.py +2522 -0
- flopscope/_polynomial.py +278 -0
- flopscope/_registry.py +3216 -0
- flopscope/_sorting_ops.py +571 -0
- flopscope/_symmetric.py +812 -0
- flopscope/_symmetry_transport.py +510 -0
- flopscope/_symmetry_utils.py +669 -0
- flopscope/_type_info.py +12 -0
- flopscope/_unwrap.py +70 -0
- flopscope/_validation.py +83 -0
- flopscope/_version_check.py +46 -0
- flopscope/_weights.py +195 -0
- flopscope/_window.py +177 -0
- flopscope/accounting.py +565 -0
- flopscope/data/default_weights.json +462 -0
- flopscope/data/weights.csv +509 -0
- flopscope/errors.py +197 -0
- flopscope/numpy/__init__.py +878 -0
- flopscope/numpy/fft/__init__.py +55 -0
- flopscope/numpy/fft/_free.py +51 -0
- flopscope/numpy/fft/_transforms.py +695 -0
- flopscope/numpy/linalg/__init__.py +105 -0
- flopscope/numpy/linalg/_aliases.py +126 -0
- flopscope/numpy/linalg/_compound.py +161 -0
- flopscope/numpy/linalg/_decompositions.py +353 -0
- flopscope/numpy/linalg/_properties.py +533 -0
- flopscope/numpy/linalg/_solvers.py +444 -0
- flopscope/numpy/linalg/_svd.py +122 -0
- flopscope/numpy/random/__init__.py +684 -0
- flopscope/numpy/random/_cost_formulas.py +115 -0
- flopscope/numpy/random/_counted_classes.py +241 -0
- flopscope/numpy/testing/__init__.py +13 -0
- flopscope/numpy/typing/__init__.py +30 -0
- flopscope/py.typed +0 -0
- flopscope/stats/__init__.py +84 -0
- flopscope/stats/_base.py +77 -0
- flopscope/stats/_cauchy.py +146 -0
- flopscope/stats/_erf.py +190 -0
- flopscope/stats/_expon.py +146 -0
- flopscope/stats/_laplace.py +150 -0
- flopscope/stats/_logistic.py +148 -0
- flopscope/stats/_lognorm.py +160 -0
- flopscope/stats/_ndtri.py +133 -0
- flopscope/stats/_norm.py +149 -0
- flopscope/stats/_truncnorm.py +186 -0
- flopscope/stats/_uniform.py +141 -0
- flopscope-0.2.0.dist-info/METADATA +23 -0
- flopscope-0.2.0.dist-info/RECORD +115 -0
- flopscope-0.2.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Connected-component decomposition of G_pt's label-interaction graph.
|
|
2
|
+
|
|
3
|
+
Each component gets its own restricted group (generators + dimino closure), V/W split,
|
|
4
|
+
sizes, and visible_positions. The cost orchestrator invokes the regime ladder per component.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
from flopscope._perm_group import _dimino
|
|
13
|
+
from flopscope._perm_group import _Permutation as Permutation
|
|
14
|
+
|
|
15
|
+
from ._detection import DetectedGroup, _classify_group_name
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class Component:
|
|
20
|
+
"""One independent block of G_pt's action on labels."""
|
|
21
|
+
|
|
22
|
+
indices: tuple[int, ...] # positions in all_labels
|
|
23
|
+
labels: tuple[str, ...]
|
|
24
|
+
va: tuple[str, ...]
|
|
25
|
+
wa: tuple[str, ...]
|
|
26
|
+
sizes: tuple[int, ...]
|
|
27
|
+
visible_positions: tuple[int, ...]
|
|
28
|
+
generators: tuple[Permutation, ...]
|
|
29
|
+
elements: tuple[Permutation, ...]
|
|
30
|
+
order: int
|
|
31
|
+
group_name: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class _UnionFind:
|
|
35
|
+
def __init__(self, n: int) -> None:
|
|
36
|
+
self._parent = list(range(n))
|
|
37
|
+
self._rank = [0] * n
|
|
38
|
+
|
|
39
|
+
def find(self, x: int) -> int:
|
|
40
|
+
while self._parent[x] != x:
|
|
41
|
+
self._parent[x] = self._parent[self._parent[x]]
|
|
42
|
+
x = self._parent[x]
|
|
43
|
+
return x
|
|
44
|
+
|
|
45
|
+
def union(self, a: int, b: int) -> None:
|
|
46
|
+
ra, rb = self.find(a), self.find(b)
|
|
47
|
+
if ra == rb:
|
|
48
|
+
return
|
|
49
|
+
if self._rank[ra] < self._rank[rb]:
|
|
50
|
+
ra, rb = rb, ra
|
|
51
|
+
self._parent[rb] = ra
|
|
52
|
+
if self._rank[ra] == self._rank[rb]:
|
|
53
|
+
self._rank[ra] += 1
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _build_label_interaction_components(
|
|
57
|
+
all_labels: Sequence[str],
|
|
58
|
+
generators: Sequence[Permutation],
|
|
59
|
+
) -> list[list[int]]:
|
|
60
|
+
"""Connected components of the label-interaction graph: labels are connected
|
|
61
|
+
if any single generator moves them together."""
|
|
62
|
+
n = len(all_labels)
|
|
63
|
+
uf = _UnionFind(n)
|
|
64
|
+
for gen in generators:
|
|
65
|
+
moved = [i for i in range(n) if gen.array_form[i] != i]
|
|
66
|
+
for j in range(1, len(moved)):
|
|
67
|
+
uf.union(moved[0], moved[j])
|
|
68
|
+
for i in range(n):
|
|
69
|
+
target = gen.array_form[i]
|
|
70
|
+
if target != i:
|
|
71
|
+
uf.union(i, target)
|
|
72
|
+
|
|
73
|
+
component_map: dict[int, list[int]] = {}
|
|
74
|
+
for i in range(n):
|
|
75
|
+
root = uf.find(i)
|
|
76
|
+
component_map.setdefault(root, []).append(i)
|
|
77
|
+
return [sorted(indices) for indices in component_map.values()]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _restrict_permutation(
|
|
81
|
+
perm: Permutation, indices: Sequence[int]
|
|
82
|
+
) -> Permutation | None:
|
|
83
|
+
"""Restrict perm to the given global indices. Returns None if perm doesn't preserve
|
|
84
|
+
the index set."""
|
|
85
|
+
local_idx = {global_idx: local_pos for local_pos, global_idx in enumerate(indices)}
|
|
86
|
+
arr: list[int] = []
|
|
87
|
+
for global_idx in indices:
|
|
88
|
+
target = perm.array_form[global_idx]
|
|
89
|
+
if target not in local_idx:
|
|
90
|
+
return None
|
|
91
|
+
arr.append(local_idx[target])
|
|
92
|
+
return Permutation(arr)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def decompose_into_components(
|
|
96
|
+
*,
|
|
97
|
+
detected_group: DetectedGroup,
|
|
98
|
+
v_labels: frozenset[str],
|
|
99
|
+
w_labels: frozenset[str],
|
|
100
|
+
sizes: Sequence[int],
|
|
101
|
+
) -> tuple[Component, ...]:
|
|
102
|
+
"""Pure: G_pt + V/W → independent components. Used by einsum and (future) reduction code paths."""
|
|
103
|
+
all_labels = detected_group.all_labels
|
|
104
|
+
raw_components = _build_label_interaction_components(
|
|
105
|
+
all_labels, detected_group.generators
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
components: list[Component] = []
|
|
109
|
+
for indices in raw_components:
|
|
110
|
+
labels = tuple(all_labels[i] for i in indices)
|
|
111
|
+
va = tuple(lbl for lbl in labels if lbl in v_labels)
|
|
112
|
+
wa = tuple(lbl for lbl in labels if lbl in w_labels)
|
|
113
|
+
comp_sizes = tuple(sizes[i] for i in indices)
|
|
114
|
+
visible_positions = tuple(labels.index(lbl) for lbl in va)
|
|
115
|
+
|
|
116
|
+
restricted_gens: list[Permutation] = []
|
|
117
|
+
seen_keys: set[tuple[int, ...]] = set()
|
|
118
|
+
for gen in detected_group.generators:
|
|
119
|
+
r = _restrict_permutation(gen, indices)
|
|
120
|
+
if r is None:
|
|
121
|
+
continue
|
|
122
|
+
if r.is_identity:
|
|
123
|
+
continue
|
|
124
|
+
key = tuple(r.array_form)
|
|
125
|
+
if key in seen_keys:
|
|
126
|
+
continue
|
|
127
|
+
seen_keys.add(key)
|
|
128
|
+
restricted_gens.append(r)
|
|
129
|
+
|
|
130
|
+
if restricted_gens:
|
|
131
|
+
elements = _dimino(tuple(restricted_gens))
|
|
132
|
+
else:
|
|
133
|
+
elements = (Permutation.identity(len(indices)),)
|
|
134
|
+
|
|
135
|
+
order = len(elements)
|
|
136
|
+
group_name = _classify_group_name(labels, restricted_gens, elements)
|
|
137
|
+
|
|
138
|
+
components.append(
|
|
139
|
+
Component(
|
|
140
|
+
indices=tuple(indices),
|
|
141
|
+
labels=labels,
|
|
142
|
+
va=va,
|
|
143
|
+
wa=wa,
|
|
144
|
+
sizes=comp_sizes,
|
|
145
|
+
visible_positions=visible_positions,
|
|
146
|
+
generators=tuple(restricted_gens),
|
|
147
|
+
elements=tuple(elements),
|
|
148
|
+
order=order,
|
|
149
|
+
group_name=group_name,
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
return tuple(components)
|