compiled-knowledge 4.0.0a20__cp313-cp313-musllinux_1_2_x86_64.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.
Potentially problematic release.
This version of compiled-knowledge might be problematic. Click here for more details.
- ck/__init__.py +0 -0
- ck/circuit/__init__.py +17 -0
- ck/circuit/_circuit_cy.c +37520 -0
- ck/circuit/_circuit_cy.cpython-313-x86_64-linux-musl.so +0 -0
- ck/circuit/_circuit_cy.pxd +32 -0
- ck/circuit/_circuit_cy.pyx +768 -0
- ck/circuit/_circuit_py.py +836 -0
- ck/circuit/tmp_const.py +74 -0
- ck/circuit_compiler/__init__.py +2 -0
- ck/circuit_compiler/circuit_compiler.py +26 -0
- ck/circuit_compiler/cython_vm_compiler/__init__.py +1 -0
- ck/circuit_compiler/cython_vm_compiler/_compiler.c +19821 -0
- ck/circuit_compiler/cython_vm_compiler/_compiler.cpython-313-x86_64-linux-musl.so +0 -0
- ck/circuit_compiler/cython_vm_compiler/_compiler.pyx +380 -0
- ck/circuit_compiler/cython_vm_compiler/cython_vm_compiler.py +121 -0
- ck/circuit_compiler/interpret_compiler.py +223 -0
- ck/circuit_compiler/llvm_compiler.py +388 -0
- ck/circuit_compiler/llvm_vm_compiler.py +546 -0
- ck/circuit_compiler/named_circuit_compilers.py +57 -0
- ck/circuit_compiler/support/__init__.py +0 -0
- ck/circuit_compiler/support/circuit_analyser/__init__.py +13 -0
- ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.c +10615 -0
- ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.cpython-313-x86_64-linux-musl.so +0 -0
- ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.pyx +98 -0
- ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_py.py +93 -0
- ck/circuit_compiler/support/input_vars.py +148 -0
- ck/circuit_compiler/support/llvm_ir_function.py +234 -0
- ck/example/__init__.py +53 -0
- ck/example/alarm.py +366 -0
- ck/example/asia.py +28 -0
- ck/example/binary_clique.py +32 -0
- ck/example/bow_tie.py +33 -0
- ck/example/cancer.py +37 -0
- ck/example/chain.py +38 -0
- ck/example/child.py +199 -0
- ck/example/clique.py +33 -0
- ck/example/cnf_pgm.py +39 -0
- ck/example/diamond_square.py +68 -0
- ck/example/earthquake.py +36 -0
- ck/example/empty.py +10 -0
- ck/example/hailfinder.py +539 -0
- ck/example/hepar2.py +628 -0
- ck/example/insurance.py +504 -0
- ck/example/loop.py +40 -0
- ck/example/mildew.py +38161 -0
- ck/example/munin.py +22982 -0
- ck/example/pathfinder.py +53747 -0
- ck/example/rain.py +39 -0
- ck/example/rectangle.py +161 -0
- ck/example/run.py +30 -0
- ck/example/sachs.py +129 -0
- ck/example/sprinkler.py +30 -0
- ck/example/star.py +44 -0
- ck/example/stress.py +64 -0
- ck/example/student.py +43 -0
- ck/example/survey.py +46 -0
- ck/example/triangle_square.py +54 -0
- ck/example/truss.py +49 -0
- ck/in_out/__init__.py +3 -0
- ck/in_out/parse_ace_lmap.py +216 -0
- ck/in_out/parse_ace_nnf.py +322 -0
- ck/in_out/parse_net.py +480 -0
- ck/in_out/parser_utils.py +185 -0
- ck/in_out/pgm_pickle.py +42 -0
- ck/in_out/pgm_python.py +268 -0
- ck/in_out/render_bugs.py +111 -0
- ck/in_out/render_net.py +177 -0
- ck/in_out/render_pomegranate.py +184 -0
- ck/pgm.py +3475 -0
- ck/pgm_circuit/__init__.py +1 -0
- ck/pgm_circuit/marginals_program.py +352 -0
- ck/pgm_circuit/mpe_program.py +237 -0
- ck/pgm_circuit/pgm_circuit.py +79 -0
- ck/pgm_circuit/program_with_slotmap.py +236 -0
- ck/pgm_circuit/slot_map.py +35 -0
- ck/pgm_circuit/support/__init__.py +0 -0
- ck/pgm_circuit/support/compile_circuit.py +83 -0
- ck/pgm_circuit/target_marginals_program.py +103 -0
- ck/pgm_circuit/wmc_program.py +323 -0
- ck/pgm_compiler/__init__.py +2 -0
- ck/pgm_compiler/ace/__init__.py +1 -0
- ck/pgm_compiler/ace/ace.py +299 -0
- ck/pgm_compiler/factor_elimination.py +395 -0
- ck/pgm_compiler/named_pgm_compilers.py +63 -0
- ck/pgm_compiler/pgm_compiler.py +19 -0
- ck/pgm_compiler/recursive_conditioning.py +231 -0
- ck/pgm_compiler/support/__init__.py +0 -0
- ck/pgm_compiler/support/circuit_table/__init__.py +17 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy.c +16393 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy.cpython-313-x86_64-linux-musl.so +0 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy.pyx +332 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_py.py +304 -0
- ck/pgm_compiler/support/clusters.py +568 -0
- ck/pgm_compiler/support/factor_tables.py +406 -0
- ck/pgm_compiler/support/join_tree.py +332 -0
- ck/pgm_compiler/support/named_compiler_maker.py +43 -0
- ck/pgm_compiler/variable_elimination.py +91 -0
- ck/probability/__init__.py +0 -0
- ck/probability/empirical_probability_space.py +50 -0
- ck/probability/pgm_probability_space.py +32 -0
- ck/probability/probability_space.py +622 -0
- ck/program/__init__.py +3 -0
- ck/program/program.py +137 -0
- ck/program/program_buffer.py +180 -0
- ck/program/raw_program.py +67 -0
- ck/sampling/__init__.py +0 -0
- ck/sampling/forward_sampler.py +211 -0
- ck/sampling/marginals_direct_sampler.py +113 -0
- ck/sampling/sampler.py +62 -0
- ck/sampling/sampler_support.py +232 -0
- ck/sampling/uniform_sampler.py +72 -0
- ck/sampling/wmc_direct_sampler.py +171 -0
- ck/sampling/wmc_gibbs_sampler.py +153 -0
- ck/sampling/wmc_metropolis_sampler.py +165 -0
- ck/sampling/wmc_rejection_sampler.py +115 -0
- ck/utils/__init__.py +0 -0
- ck/utils/iter_extras.py +163 -0
- ck/utils/local_config.py +270 -0
- ck/utils/map_list.py +128 -0
- ck/utils/map_set.py +128 -0
- ck/utils/np_extras.py +51 -0
- ck/utils/random_extras.py +64 -0
- ck/utils/tmp_dir.py +94 -0
- ck_demos/__init__.py +0 -0
- ck_demos/ace/__init__.py +0 -0
- ck_demos/ace/copy_ace_to_ck.py +15 -0
- ck_demos/ace/demo_ace.py +49 -0
- ck_demos/all_demos.py +88 -0
- ck_demos/circuit/__init__.py +0 -0
- ck_demos/circuit/demo_circuit_dump.py +22 -0
- ck_demos/circuit/demo_derivatives.py +43 -0
- ck_demos/circuit_compiler/__init__.py +0 -0
- ck_demos/circuit_compiler/compare_circuit_compilers.py +32 -0
- ck_demos/circuit_compiler/show_llvm_program.py +26 -0
- ck_demos/pgm/__init__.py +0 -0
- ck_demos/pgm/demo_pgm_dump.py +18 -0
- ck_demos/pgm/demo_pgm_dump_stress.py +18 -0
- ck_demos/pgm/demo_pgm_string_rendering.py +15 -0
- ck_demos/pgm/show_examples.py +25 -0
- ck_demos/pgm_compiler/__init__.py +0 -0
- ck_demos/pgm_compiler/compare_pgm_compilers.py +63 -0
- ck_demos/pgm_compiler/demo_compiler_dump.py +60 -0
- ck_demos/pgm_compiler/demo_factor_elimination.py +47 -0
- ck_demos/pgm_compiler/demo_join_tree.py +25 -0
- ck_demos/pgm_compiler/demo_marginals_program.py +53 -0
- ck_demos/pgm_compiler/demo_mpe_program.py +55 -0
- ck_demos/pgm_compiler/demo_pgm_compiler.py +38 -0
- ck_demos/pgm_compiler/demo_recursive_conditioning.py +33 -0
- ck_demos/pgm_compiler/demo_variable_elimination.py +33 -0
- ck_demos/pgm_compiler/demo_wmc_program.py +29 -0
- ck_demos/pgm_compiler/time_fe_compiler.py +93 -0
- ck_demos/pgm_inference/__init__.py +0 -0
- ck_demos/pgm_inference/demo_inferencing_basic.py +188 -0
- ck_demos/pgm_inference/demo_inferencing_mpe_cancer.py +45 -0
- ck_demos/pgm_inference/demo_inferencing_wmc_and_mpe_sprinkler.py +154 -0
- ck_demos/pgm_inference/demo_inferencing_wmc_student.py +110 -0
- ck_demos/programs/__init__.py +0 -0
- ck_demos/programs/demo_program_buffer.py +24 -0
- ck_demos/programs/demo_program_multi.py +24 -0
- ck_demos/programs/demo_program_none.py +19 -0
- ck_demos/programs/demo_program_single.py +23 -0
- ck_demos/programs/demo_raw_program_interpreted.py +21 -0
- ck_demos/programs/demo_raw_program_llvm.py +21 -0
- ck_demos/sampling/__init__.py +0 -0
- ck_demos/sampling/check_sampler.py +71 -0
- ck_demos/sampling/demo_marginal_direct_sampler.py +40 -0
- ck_demos/sampling/demo_uniform_sampler.py +38 -0
- ck_demos/sampling/demo_wmc_direct_sampler.py +40 -0
- ck_demos/utils/__init__.py +0 -0
- ck_demos/utils/compare.py +120 -0
- ck_demos/utils/convert_network.py +45 -0
- ck_demos/utils/sample_model.py +216 -0
- ck_demos/utils/stop_watch.py +384 -0
- compiled_knowledge-4.0.0a20.dist-info/METADATA +50 -0
- compiled_knowledge-4.0.0a20.dist-info/RECORD +178 -0
- compiled_knowledge-4.0.0a20.dist-info/WHEEL +5 -0
- compiled_knowledge-4.0.0a20.dist-info/licenses/LICENSE.txt +21 -0
- compiled_knowledge-4.0.0a20.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Iterable, Dict, Optional, List, Sequence, Tuple, Set
|
|
6
|
+
|
|
7
|
+
from ck.circuit import Circuit, CircuitNode
|
|
8
|
+
from ck.pgm import PGM
|
|
9
|
+
from ck.pgm_circuit import PGMCircuit
|
|
10
|
+
from ck.pgm_compiler.support import clusters
|
|
11
|
+
from ck.pgm_compiler.support.circuit_table import CircuitTable
|
|
12
|
+
from ck.pgm_compiler.support.clusters import ClusterAlgorithm
|
|
13
|
+
from ck.pgm_compiler.support.factor_tables import make_factor_tables, FactorTables
|
|
14
|
+
from ck.utils.iter_extras import combos
|
|
15
|
+
|
|
16
|
+
# Standard cluster algorithms.
|
|
17
|
+
MIN_DEGREE: ClusterAlgorithm = clusters.min_degree
|
|
18
|
+
MIN_FILL: ClusterAlgorithm = clusters.min_fill
|
|
19
|
+
MIN_DEGREE_THEN_FILL: ClusterAlgorithm = clusters.min_degree_then_fill
|
|
20
|
+
MIN_FILL_THEN_DEGREE: ClusterAlgorithm = clusters.min_fill_then_degree
|
|
21
|
+
MIN_WEIGHTED_DEGREE: ClusterAlgorithm = clusters.min_weighted_degree
|
|
22
|
+
MIN_WEIGHTED_FILL: ClusterAlgorithm = clusters.min_weighted_fill
|
|
23
|
+
MIN_TRADITIONAL_WEIGHTED_FILL: ClusterAlgorithm = clusters.min_traditional_weighted_fill
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def compile_pgm(
|
|
27
|
+
pgm: PGM,
|
|
28
|
+
const_parameters: bool = True,
|
|
29
|
+
*,
|
|
30
|
+
algorithm: ClusterAlgorithm = MIN_FILL_THEN_DEGREE,
|
|
31
|
+
pre_prune_factor_tables: bool = False,
|
|
32
|
+
) -> PGMCircuit:
|
|
33
|
+
"""
|
|
34
|
+
Compile the PGM to an arithmetic circuit, using recursive conditioning.
|
|
35
|
+
|
|
36
|
+
Conforms to the `PGMCompiler` protocol.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
pgm: The PGM to compile.
|
|
40
|
+
const_parameters: If true, the potential function parameters will be circuit
|
|
41
|
+
constants, otherwise they will be circuit variables.
|
|
42
|
+
algorithm: algorithm to get an elimination order.
|
|
43
|
+
pre_prune_factor_tables: if true, then heuristics will be used to remove any provably zero row.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
a PGMCircuit object.
|
|
47
|
+
"""
|
|
48
|
+
elimination_order: Sequence[int] = algorithm(pgm).eliminated
|
|
49
|
+
factor_tables: FactorTables = make_factor_tables(
|
|
50
|
+
pgm=pgm,
|
|
51
|
+
const_parameters=const_parameters,
|
|
52
|
+
multiply_indicators=True,
|
|
53
|
+
pre_prune_factor_tables=pre_prune_factor_tables,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if pgm.number_of_factors == 0:
|
|
57
|
+
# Deal with special case: no factors
|
|
58
|
+
top: CircuitNode = factor_tables.circuit.const(1)
|
|
59
|
+
else:
|
|
60
|
+
dtree: _DTree = _make_dtree(elimination_order, factor_tables)
|
|
61
|
+
states: List[Sequence[int]] = [tuple(range(len(rv))) for rv in pgm.rvs]
|
|
62
|
+
top: CircuitNode = dtree.make_circuit(states, factor_tables.circuit)
|
|
63
|
+
|
|
64
|
+
top.circuit.remove_unreachable_op_nodes(top)
|
|
65
|
+
|
|
66
|
+
return PGMCircuit(
|
|
67
|
+
rvs=tuple(pgm.rvs),
|
|
68
|
+
conditions=(),
|
|
69
|
+
circuit_top=top,
|
|
70
|
+
number_of_indicators=factor_tables.number_of_indicators,
|
|
71
|
+
number_of_parameters=factor_tables.number_of_parameters,
|
|
72
|
+
slot_map=factor_tables.slot_map,
|
|
73
|
+
parameter_values=factor_tables.parameter_values,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _make_dtree(elimination_order: Sequence[int], factor_tables: FactorTables) -> _DTree:
|
|
78
|
+
if len(factor_tables.tables) == 0:
|
|
79
|
+
return _DTreeLeaf(CircuitTable(factor_tables.circuit, (), ()))
|
|
80
|
+
|
|
81
|
+
# Populate `trees` with all the leaves
|
|
82
|
+
trees: List[_DTree] = [_DTreeLeaf(table) for table in factor_tables.tables]
|
|
83
|
+
|
|
84
|
+
# join trees by elimination random variable
|
|
85
|
+
for rv_index in elimination_order:
|
|
86
|
+
next_trees: List[_DTree] = []
|
|
87
|
+
to_join: List[_DTree] = []
|
|
88
|
+
for tree in trees:
|
|
89
|
+
if rv_index in tree.vars:
|
|
90
|
+
to_join.append(tree)
|
|
91
|
+
else:
|
|
92
|
+
next_trees.append(tree)
|
|
93
|
+
if len(to_join) >= 2:
|
|
94
|
+
while len(to_join) > 1:
|
|
95
|
+
# join the two shallowest trees
|
|
96
|
+
to_join.sort(key=lambda t: -t.depth())
|
|
97
|
+
x = to_join.pop()
|
|
98
|
+
y = to_join.pop()
|
|
99
|
+
to_join.append(_DTreeInterior(x, y))
|
|
100
|
+
next_trees.append(to_join[0])
|
|
101
|
+
trees = next_trees
|
|
102
|
+
|
|
103
|
+
# Make sure there is only one tree
|
|
104
|
+
while len(trees) > 1:
|
|
105
|
+
x = trees.pop(0)
|
|
106
|
+
y = trees.pop(0)
|
|
107
|
+
trees.append(_DTreeInterior(x, y))
|
|
108
|
+
|
|
109
|
+
root = trees[0]
|
|
110
|
+
root.update_cutset()
|
|
111
|
+
return root
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class _DTree(ABC):
|
|
115
|
+
"""
|
|
116
|
+
A node in a binary decomposition tree.
|
|
117
|
+
|
|
118
|
+
A node is either a _DTreeLeaf, holding a single CircuitTable,
|
|
119
|
+
or is a _DTreeInterior, which has exactly two children.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def __init__(self, vars_idxs: Set[int]):
|
|
123
|
+
self.vars: Set[int] = vars_idxs
|
|
124
|
+
self.cutset: Sequence[int] = ()
|
|
125
|
+
self.context: Sequence[int] = ()
|
|
126
|
+
|
|
127
|
+
@abstractmethod
|
|
128
|
+
def update_cutset(self, acutset: Iterable[int] = ()) -> None:
|
|
129
|
+
"""
|
|
130
|
+
After the d-tree is defined, call `update_cutset` on the root
|
|
131
|
+
to ensure all fields are properly set.
|
|
132
|
+
"""
|
|
133
|
+
...
|
|
134
|
+
|
|
135
|
+
@abstractmethod
|
|
136
|
+
def make_circuit(self, states: List[Sequence[int]], circuit: Circuit) -> CircuitNode:
|
|
137
|
+
"""
|
|
138
|
+
After the d-tree is defined and cutsets are updated,
|
|
139
|
+
construct a circuit using recursive conditioning.
|
|
140
|
+
"""
|
|
141
|
+
...
|
|
142
|
+
|
|
143
|
+
@abstractmethod
|
|
144
|
+
def depth(self) -> int:
|
|
145
|
+
"""
|
|
146
|
+
Tree depth.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclass
|
|
151
|
+
class _DTreeLeaf(_DTree):
|
|
152
|
+
|
|
153
|
+
def __init__(self, table: CircuitTable):
|
|
154
|
+
super().__init__(set(table.rv_idxs))
|
|
155
|
+
self.table: CircuitTable = table
|
|
156
|
+
|
|
157
|
+
def update_cutset(self, acutset: Iterable[int] = ()) -> None:
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
def make_circuit(self, states: List[Sequence[int]], circuit: Circuit) -> CircuitNode:
|
|
161
|
+
table = self.table
|
|
162
|
+
|
|
163
|
+
key_states: List[Sequence[int]] = [
|
|
164
|
+
states[rv_idx]
|
|
165
|
+
for rv_idx in table.rv_idxs
|
|
166
|
+
]
|
|
167
|
+
to_sum: List[CircuitNode] = list(
|
|
168
|
+
filter(
|
|
169
|
+
(lambda n: n is not None),
|
|
170
|
+
(table.get(key) for key in combos(key_states))
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
return circuit.optimised_add(to_sum)
|
|
174
|
+
|
|
175
|
+
def depth(self) -> int:
|
|
176
|
+
return 1
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@dataclass
|
|
180
|
+
class _DTreeInterior(_DTree):
|
|
181
|
+
|
|
182
|
+
def __init__(self, x: _DTree, y: _DTree):
|
|
183
|
+
super().__init__(x.vars.union(y.vars))
|
|
184
|
+
self.x: _DTree = x
|
|
185
|
+
self.y: _DTree = y
|
|
186
|
+
self.cache: Dict[Tuple[int, ...], CircuitNode] = {}
|
|
187
|
+
|
|
188
|
+
def update_cutset(self, acutset: Iterable[int] = ()) -> None:
|
|
189
|
+
cutset: Set[int] = self.x.vars.intersection(self.y.vars).difference(acutset)
|
|
190
|
+
self.cutset = tuple(cutset)
|
|
191
|
+
self.context = tuple(self.vars.intersection(acutset))
|
|
192
|
+
|
|
193
|
+
next_acutset = cutset.union(acutset)
|
|
194
|
+
self.x.update_cutset(next_acutset)
|
|
195
|
+
self.y.update_cutset(next_acutset)
|
|
196
|
+
|
|
197
|
+
def make_circuit(self, states: List[Sequence[int]], circuit: Circuit) -> CircuitNode:
|
|
198
|
+
|
|
199
|
+
assert all(len(states[rv_idx]) == 1 for rv_idx in self.context), 'consistency check'
|
|
200
|
+
context_key: Tuple[int, ...] = tuple(
|
|
201
|
+
states[rv_idx][0]
|
|
202
|
+
for rv_idx in self.context
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
cache: Optional[CircuitNode] = self.cache.get(context_key)
|
|
206
|
+
if cache is not None:
|
|
207
|
+
return cache
|
|
208
|
+
|
|
209
|
+
cutset = self.cutset
|
|
210
|
+
key_states: List[Sequence[int]] = [
|
|
211
|
+
states[rv_idx]
|
|
212
|
+
for rv_idx in cutset
|
|
213
|
+
]
|
|
214
|
+
to_sum: List[CircuitNode] = []
|
|
215
|
+
for key in combos(key_states):
|
|
216
|
+
# Update the evidence with the keys
|
|
217
|
+
next_states = states.copy()
|
|
218
|
+
for s, i in zip(key, cutset):
|
|
219
|
+
next_states[i] = (s,)
|
|
220
|
+
|
|
221
|
+
# Recursively call
|
|
222
|
+
x_node = self.x.make_circuit(next_states, circuit)
|
|
223
|
+
y_node = self.y.make_circuit(next_states, circuit)
|
|
224
|
+
to_sum.append(circuit.optimised_mul((x_node, y_node)))
|
|
225
|
+
|
|
226
|
+
result = circuit.optimised_add(to_sum)
|
|
227
|
+
self.cache[context_key] = result
|
|
228
|
+
return result
|
|
229
|
+
|
|
230
|
+
def depth(self) -> int:
|
|
231
|
+
return max(self.x.depth(), self.y.depth())
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# There are two implementations of the `circuit_table` module are provided
|
|
2
|
+
# for developer R&D purposes. One is pure Python and the other is Cython.
|
|
3
|
+
# Which implementation is used can be selected here.
|
|
4
|
+
#
|
|
5
|
+
# A similar selection can be made for the `circuit` module.
|
|
6
|
+
# Note that if the Cython implementation is chosen for `circuit_table` then
|
|
7
|
+
# the Cython implementation must be chosen for `circuit`.
|
|
8
|
+
|
|
9
|
+
# from ._circuit_table_py import (
|
|
10
|
+
from ._circuit_table_cy import (
|
|
11
|
+
CircuitTable,
|
|
12
|
+
TableInstance,
|
|
13
|
+
sum_out,
|
|
14
|
+
sum_out_all,
|
|
15
|
+
project,
|
|
16
|
+
product,
|
|
17
|
+
)
|