compiled-knowledge 4.0.0a5__cp313-cp313-macosx_10_13_universal2.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.

Files changed (167) hide show
  1. ck/__init__.py +0 -0
  2. ck/circuit/__init__.py +13 -0
  3. ck/circuit/circuit.c +38749 -0
  4. ck/circuit/circuit.cpython-313-darwin.so +0 -0
  5. ck/circuit/circuit_py.py +807 -0
  6. ck/circuit/tmp_const.py +74 -0
  7. ck/circuit_compiler/__init__.py +2 -0
  8. ck/circuit_compiler/circuit_compiler.py +26 -0
  9. ck/circuit_compiler/cython_vm_compiler/__init__.py +1 -0
  10. ck/circuit_compiler/cython_vm_compiler/_compiler.c +17373 -0
  11. ck/circuit_compiler/cython_vm_compiler/_compiler.cpython-313-darwin.so +0 -0
  12. ck/circuit_compiler/cython_vm_compiler/cython_vm_compiler.py +96 -0
  13. ck/circuit_compiler/interpret_compiler.py +223 -0
  14. ck/circuit_compiler/llvm_compiler.py +388 -0
  15. ck/circuit_compiler/llvm_vm_compiler.py +546 -0
  16. ck/circuit_compiler/named_circuit_compilers.py +57 -0
  17. ck/circuit_compiler/support/__init__.py +0 -0
  18. ck/circuit_compiler/support/circuit_analyser.py +81 -0
  19. ck/circuit_compiler/support/input_vars.py +148 -0
  20. ck/circuit_compiler/support/llvm_ir_function.py +234 -0
  21. ck/example/__init__.py +53 -0
  22. ck/example/alarm.py +366 -0
  23. ck/example/asia.py +28 -0
  24. ck/example/binary_clique.py +32 -0
  25. ck/example/bow_tie.py +33 -0
  26. ck/example/cancer.py +37 -0
  27. ck/example/chain.py +38 -0
  28. ck/example/child.py +199 -0
  29. ck/example/clique.py +33 -0
  30. ck/example/cnf_pgm.py +39 -0
  31. ck/example/diamond_square.py +68 -0
  32. ck/example/earthquake.py +36 -0
  33. ck/example/empty.py +10 -0
  34. ck/example/hailfinder.py +539 -0
  35. ck/example/hepar2.py +628 -0
  36. ck/example/insurance.py +504 -0
  37. ck/example/loop.py +40 -0
  38. ck/example/mildew.py +38161 -0
  39. ck/example/munin.py +22982 -0
  40. ck/example/pathfinder.py +53674 -0
  41. ck/example/rain.py +39 -0
  42. ck/example/rectangle.py +161 -0
  43. ck/example/run.py +30 -0
  44. ck/example/sachs.py +129 -0
  45. ck/example/sprinkler.py +30 -0
  46. ck/example/star.py +44 -0
  47. ck/example/stress.py +64 -0
  48. ck/example/student.py +43 -0
  49. ck/example/survey.py +46 -0
  50. ck/example/triangle_square.py +54 -0
  51. ck/example/truss.py +49 -0
  52. ck/in_out/__init__.py +3 -0
  53. ck/in_out/parse_ace_lmap.py +216 -0
  54. ck/in_out/parse_ace_nnf.py +288 -0
  55. ck/in_out/parse_net.py +480 -0
  56. ck/in_out/parser_utils.py +185 -0
  57. ck/in_out/pgm_pickle.py +42 -0
  58. ck/in_out/pgm_python.py +268 -0
  59. ck/in_out/render_bugs.py +111 -0
  60. ck/in_out/render_net.py +177 -0
  61. ck/in_out/render_pomegranate.py +184 -0
  62. ck/pgm.py +3494 -0
  63. ck/pgm_circuit/__init__.py +1 -0
  64. ck/pgm_circuit/marginals_program.py +352 -0
  65. ck/pgm_circuit/mpe_program.py +237 -0
  66. ck/pgm_circuit/pgm_circuit.py +75 -0
  67. ck/pgm_circuit/program_with_slotmap.py +234 -0
  68. ck/pgm_circuit/slot_map.py +35 -0
  69. ck/pgm_circuit/support/__init__.py +0 -0
  70. ck/pgm_circuit/support/compile_circuit.py +83 -0
  71. ck/pgm_circuit/target_marginals_program.py +103 -0
  72. ck/pgm_circuit/wmc_program.py +323 -0
  73. ck/pgm_compiler/__init__.py +2 -0
  74. ck/pgm_compiler/ace/__init__.py +1 -0
  75. ck/pgm_compiler/ace/ace.py +252 -0
  76. ck/pgm_compiler/factor_elimination.py +383 -0
  77. ck/pgm_compiler/named_pgm_compilers.py +63 -0
  78. ck/pgm_compiler/pgm_compiler.py +19 -0
  79. ck/pgm_compiler/recursive_conditioning.py +226 -0
  80. ck/pgm_compiler/support/__init__.py +0 -0
  81. ck/pgm_compiler/support/circuit_table/__init__.py +9 -0
  82. ck/pgm_compiler/support/circuit_table/circuit_table.c +16042 -0
  83. ck/pgm_compiler/support/circuit_table/circuit_table.cpython-313-darwin.so +0 -0
  84. ck/pgm_compiler/support/circuit_table/circuit_table_py.py +269 -0
  85. ck/pgm_compiler/support/clusters.py +556 -0
  86. ck/pgm_compiler/support/factor_tables.py +398 -0
  87. ck/pgm_compiler/support/join_tree.py +275 -0
  88. ck/pgm_compiler/support/named_compiler_maker.py +33 -0
  89. ck/pgm_compiler/variable_elimination.py +89 -0
  90. ck/probability/__init__.py +0 -0
  91. ck/probability/empirical_probability_space.py +47 -0
  92. ck/probability/probability_space.py +568 -0
  93. ck/program/__init__.py +3 -0
  94. ck/program/program.py +129 -0
  95. ck/program/program_buffer.py +180 -0
  96. ck/program/raw_program.py +61 -0
  97. ck/sampling/__init__.py +0 -0
  98. ck/sampling/forward_sampler.py +211 -0
  99. ck/sampling/marginals_direct_sampler.py +113 -0
  100. ck/sampling/sampler.py +62 -0
  101. ck/sampling/sampler_support.py +232 -0
  102. ck/sampling/uniform_sampler.py +66 -0
  103. ck/sampling/wmc_direct_sampler.py +169 -0
  104. ck/sampling/wmc_gibbs_sampler.py +147 -0
  105. ck/sampling/wmc_metropolis_sampler.py +159 -0
  106. ck/sampling/wmc_rejection_sampler.py +113 -0
  107. ck/utils/__init__.py +0 -0
  108. ck/utils/iter_extras.py +153 -0
  109. ck/utils/map_list.py +128 -0
  110. ck/utils/map_set.py +128 -0
  111. ck/utils/np_extras.py +51 -0
  112. ck/utils/random_extras.py +64 -0
  113. ck/utils/tmp_dir.py +94 -0
  114. ck_demos/__init__.py +0 -0
  115. ck_demos/ace/__init__.py +0 -0
  116. ck_demos/ace/copy_ace_to_ck.py +15 -0
  117. ck_demos/ace/demo_ace.py +44 -0
  118. ck_demos/all_demos.py +88 -0
  119. ck_demos/circuit/__init__.py +0 -0
  120. ck_demos/circuit/demo_circuit_dump.py +22 -0
  121. ck_demos/circuit/demo_derivatives.py +43 -0
  122. ck_demos/circuit_compiler/__init__.py +0 -0
  123. ck_demos/circuit_compiler/compare_circuit_compilers.py +32 -0
  124. ck_demos/circuit_compiler/show_llvm_program.py +26 -0
  125. ck_demos/pgm/__init__.py +0 -0
  126. ck_demos/pgm/demo_pgm_dump.py +18 -0
  127. ck_demos/pgm/demo_pgm_dump_stress.py +18 -0
  128. ck_demos/pgm/demo_pgm_string_rendering.py +15 -0
  129. ck_demos/pgm/show_examples.py +25 -0
  130. ck_demos/pgm_compiler/__init__.py +0 -0
  131. ck_demos/pgm_compiler/compare_pgm_compilers.py +50 -0
  132. ck_demos/pgm_compiler/demo_compiler_dump.py +50 -0
  133. ck_demos/pgm_compiler/demo_factor_elimination.py +47 -0
  134. ck_demos/pgm_compiler/demo_join_tree.py +25 -0
  135. ck_demos/pgm_compiler/demo_marginals_program.py +53 -0
  136. ck_demos/pgm_compiler/demo_mpe_program.py +55 -0
  137. ck_demos/pgm_compiler/demo_pgm_compiler.py +38 -0
  138. ck_demos/pgm_compiler/demo_recursive_conditioning.py +33 -0
  139. ck_demos/pgm_compiler/demo_variable_elimination.py +33 -0
  140. ck_demos/pgm_compiler/demo_wmc_program.py +29 -0
  141. ck_demos/pgm_inference/__init__.py +0 -0
  142. ck_demos/pgm_inference/demo_inferencing_basic.py +188 -0
  143. ck_demos/pgm_inference/demo_inferencing_mpe_cancer.py +45 -0
  144. ck_demos/pgm_inference/demo_inferencing_wmc_and_mpe_sprinkler.py +154 -0
  145. ck_demos/pgm_inference/demo_inferencing_wmc_student.py +110 -0
  146. ck_demos/programs/__init__.py +0 -0
  147. ck_demos/programs/demo_program_buffer.py +24 -0
  148. ck_demos/programs/demo_program_multi.py +24 -0
  149. ck_demos/programs/demo_program_none.py +19 -0
  150. ck_demos/programs/demo_program_single.py +23 -0
  151. ck_demos/programs/demo_raw_program_interpreted.py +21 -0
  152. ck_demos/programs/demo_raw_program_llvm.py +21 -0
  153. ck_demos/sampling/__init__.py +0 -0
  154. ck_demos/sampling/check_sampler.py +71 -0
  155. ck_demos/sampling/demo_marginal_direct_sampler.py +40 -0
  156. ck_demos/sampling/demo_uniform_sampler.py +38 -0
  157. ck_demos/sampling/demo_wmc_direct_sampler.py +40 -0
  158. ck_demos/utils/__init__.py +0 -0
  159. ck_demos/utils/compare.py +88 -0
  160. ck_demos/utils/convert_network.py +45 -0
  161. ck_demos/utils/sample_model.py +216 -0
  162. ck_demos/utils/stop_watch.py +384 -0
  163. compiled_knowledge-4.0.0a5.dist-info/METADATA +50 -0
  164. compiled_knowledge-4.0.0a5.dist-info/RECORD +167 -0
  165. compiled_knowledge-4.0.0a5.dist-info/WHEEL +5 -0
  166. compiled_knowledge-4.0.0a5.dist-info/licenses/LICENSE.txt +21 -0
  167. compiled_knowledge-4.0.0a5.dist-info/top_level.txt +2 -0
@@ -0,0 +1,269 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Sequence, Tuple, Dict, Iterable, Set, Iterator
4
+
5
+ from ck.circuit import CircuitNode, Circuit
6
+ from ck.utils.map_list import MapList
7
+
8
+ TableInstance = Tuple[int, ...]
9
+
10
+
11
+ class CircuitTable:
12
+ """
13
+ A circuit table manages a set of CircuitNodes, where each node corresponds
14
+ to an instance for a set of (zero or more) random variables.
15
+
16
+ Operations on circuit tables typically add circuit nodes to the circuit. It will
17
+ heuristically avoid adding unnecessary nodes (e.g. addition of zero, multiplication
18
+ by zero or one.) However, it may be that interim circuit nodes are created that
19
+ end up not being used. Consider calling `Circuit.remove_unreachable_op_nodes` after
20
+ completing all circuit table operations.
21
+
22
+ It is generally expected that no CircuitTable row will be created with a constant
23
+ zero node. These are assumed to be optimised out already.
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ circuit: Circuit,
29
+ rv_idxs: Sequence[int],
30
+ rows: Iterable[Tuple[TableInstance, CircuitNode]] = (),
31
+ ):
32
+ """
33
+ Args:
34
+ circuit: the circuit whose nodes are being managed by this table.
35
+ rv_idxs: indexes of random variables.
36
+ rows: optional rows to add to the table.
37
+
38
+ Assumes:
39
+ * rv_idxs contains no duplicates.
40
+ * all row instances conform to the indexed random variables.
41
+ * all row circuit nodes belong to the given circuit.
42
+ """
43
+ self.circuit: Circuit = circuit
44
+ self.rv_idxs: Tuple[int, ...] = tuple(rv_idxs)
45
+ self.rows: Dict[TableInstance, CircuitNode] = dict(rows)
46
+
47
+ def __len__(self) -> int:
48
+ return len(self.rows)
49
+
50
+ def get(self, key, default=None):
51
+ return self.rows.get(key, default)
52
+
53
+ def __getitem__(self, key):
54
+ return self.rows[key]
55
+
56
+ def __setitem__(self, key, value):
57
+ self.rows[key] = value
58
+
59
+ def top(self) -> CircuitNode:
60
+ """
61
+ Get the circuit top value.
62
+
63
+ Raises:
64
+ RuntimeError if there is more than one row in the table.
65
+
66
+ Returns:
67
+ A single circuit node.
68
+ """
69
+ if len(self.rows) == 0:
70
+ return self.circuit.zero
71
+ elif len(self.rows) == 1:
72
+ return next(iter(self.rows.values()))
73
+ else:
74
+ raise RuntimeError('cannot get top node from a table with more that 1 row')
75
+
76
+
77
+ # ==================================================================================
78
+ # Circuit Table Operations
79
+ # ==================================================================================
80
+
81
+
82
+ def sum_out(table: CircuitTable, rv_idxs: Iterable[int]) -> CircuitTable:
83
+ """
84
+ Return a circuit table that results from summing out
85
+ the given random variables of this circuit table.
86
+
87
+ Normally this will return a new table. However, if rv_idxs is empty,
88
+ then the given table is returned unmodified.
89
+
90
+ Raises:
91
+ ValueError if rv_idxs is not a subset of table.rv_idxs.
92
+ ValueError if rv_idxs contains duplicates.
93
+ """
94
+ rv_idxs: Sequence[int] = tuple(rv_idxs)
95
+
96
+ if len(rv_idxs) == 0:
97
+ # nothing to do
98
+ return table
99
+
100
+ rv_idxs_set: Set[int] = set(rv_idxs)
101
+ if len(rv_idxs_set) != len(rv_idxs):
102
+ raise ValueError('rv_idxs contains duplicates')
103
+ if not rv_idxs_set.issubset(table.rv_idxs):
104
+ raise ValueError('rv_idxs is not a subset of table.rv_idxs')
105
+
106
+ remaining_rv_idxs = tuple(
107
+ rv_index
108
+ for rv_index in table.rv_idxs
109
+ if rv_index not in rv_idxs_set
110
+ )
111
+ num_remaining = len(remaining_rv_idxs)
112
+ if num_remaining == 0:
113
+ # Special case: summing out all random variables
114
+ return sum_out_all(table)
115
+
116
+ # index_map[i] is the location in table.rv_idxs for remaining_rv_idxs[i]
117
+ index_map = tuple(
118
+ table.rv_idxs.index(remaining_rv_index)
119
+ for remaining_rv_index in remaining_rv_idxs
120
+ )
121
+
122
+ groups: MapList[TableInstance, CircuitNode] = MapList()
123
+ for instance, node in table.rows.items():
124
+ group_instance = tuple(instance[i] for i in index_map)
125
+ groups.append(group_instance, node)
126
+
127
+ circuit: Circuit = table.circuit
128
+
129
+ def _result_rows() -> Iterator[Tuple[TableInstance, CircuitNode]]:
130
+ for group, to_add in groups.items():
131
+ _node: CircuitNode = circuit.optimised_add(to_add)
132
+ if not _node.is_zero():
133
+ yield group, _node
134
+
135
+ return CircuitTable(circuit, remaining_rv_idxs, _result_rows())
136
+
137
+
138
+ def sum_out_all(table: CircuitTable) -> CircuitTable:
139
+ """
140
+ Return a circuit table that results from summing out
141
+ all random variables of this circuit table.
142
+ """
143
+ circuit: Circuit = table.circuit
144
+ num_rows: int = len(table)
145
+ if num_rows == 0:
146
+ return CircuitTable(circuit, ())
147
+ elif num_rows == 1:
148
+ node = next(iter(table.rows.values()))
149
+ else:
150
+ node: CircuitNode = circuit.optimised_add(table.rows.values())
151
+ if node.is_zero():
152
+ return CircuitTable(circuit, ())
153
+
154
+ return CircuitTable(circuit, (), [((), node)])
155
+
156
+
157
+ def project(table: CircuitTable, rv_idxs: Iterable[int]) -> CircuitTable:
158
+ """
159
+ Call `sum_out(table, to_sum_out)`, where
160
+ `to_sum_out = table.rv_idxs - rv_idxs`.
161
+ """
162
+ to_sum_out: Set[int] = set(table.rv_idxs)
163
+ to_sum_out.difference_update(rv_idxs)
164
+ return sum_out(table, to_sum_out)
165
+
166
+
167
+ def product(x: CircuitTable, y: CircuitTable) -> CircuitTable:
168
+ """
169
+ Return a circuit table that results from the product of the two given tables.
170
+
171
+ If x or y equals `one_table`, then the other table is returned. Otherwise,
172
+ a new circuit table will be constructed and returned.
173
+ """
174
+ circuit: Circuit = x.circuit
175
+ if y.circuit is not circuit:
176
+ raise ValueError('circuit tables must refer to the same circuit')
177
+
178
+ # Make the smaller table 'y', and the other 'x'.
179
+ # This is to minimise the index size on 'y'.
180
+ if len(x) < len(y):
181
+ x, y = y, x
182
+
183
+ x_rv_idxs: Tuple[int, ...] = x.rv_idxs
184
+ y_rv_idxs: Tuple[int, ...] = y.rv_idxs
185
+
186
+ # Special case: y == 0 or 1, and has no random variables.
187
+ if y_rv_idxs == ():
188
+ if len(y) == 1 and y.top().is_one():
189
+ return x
190
+ elif len(y) == 0:
191
+ return CircuitTable(circuit, x_rv_idxs)
192
+
193
+ # Set operations on rv indexes. After these operations:
194
+ # * co_rv_idxs is the set of rv indexes common (co) to x and y,
195
+ # * yo_rv_idxs is the set of rv indexes in y only (yo), and not in x.
196
+ yo_rv_idxs: Set[int] = set(y_rv_idxs)
197
+ co_rv_idxs: Set[int] = set(x_rv_idxs)
198
+ co_rv_idxs.intersection_update(yo_rv_idxs)
199
+ yo_rv_idxs.difference_update(co_rv_idxs)
200
+
201
+ if len(co_rv_idxs) == 0:
202
+ # Special case: no common random variables.
203
+ return _product_no_common_rvs(x, y)
204
+
205
+ # Convert random variable index sets to sequences
206
+ yo_rv_idxs: Tuple[int, ...] = tuple(yo_rv_idxs) # y only random variables
207
+ co_rv_idxs: Tuple[int, ...] = tuple(co_rv_idxs) # common random variables
208
+
209
+ # Cache mappings from result Instance to index into source Instance (x or y).
210
+ # This will be used in indexing and product loops to pull our needed values
211
+ # from the source instances.
212
+ co_from_x_map = tuple(x.rv_idxs.index(rv_index) for rv_index in co_rv_idxs)
213
+ co_from_y_map = tuple(y.rv_idxs.index(rv_index) for rv_index in co_rv_idxs)
214
+ yo_from_y_map = tuple(y.rv_idxs.index(rv_index) for rv_index in yo_rv_idxs)
215
+
216
+ # Index the y rows by common-only key (y is the smaller of the two tables).
217
+ y_index: MapList[TableInstance, Tuple[TableInstance, CircuitNode]] = MapList()
218
+ for y_instance, y_node in y.rows.items():
219
+ co = tuple(y_instance[i] for i in co_from_y_map)
220
+ yo = tuple(y_instance[i] for i in yo_from_y_map)
221
+ y_index.append(co, (yo, y_node))
222
+
223
+ def _result_rows() -> Iterator[Tuple[TableInstance, CircuitNode]]:
224
+ # Iterate over x rows, yielding (instance, value).
225
+ # Rows with constant node values of one are optimised out.
226
+ for _x_instance, _x_node in x.rows.items():
227
+ _co = tuple(_x_instance[i] for i in co_from_x_map)
228
+ if _x_node.is_one():
229
+ # Multiplying by one.
230
+ # Iterate over matching y rows.
231
+ for _yo, _y_node in y_index.get(_co, ()):
232
+ yield _x_instance + _yo, _y_node
233
+ else:
234
+ # Iterate over matching y rows.
235
+ for _yo, _y_node in y_index.get(_co, ()):
236
+ yield _x_instance + _yo, circuit.optimised_mul((_x_node, _y_node))
237
+
238
+ return CircuitTable(circuit, x_rv_idxs + yo_rv_idxs, _result_rows())
239
+
240
+
241
+ def _product_no_common_rvs(x: CircuitTable, y: CircuitTable) -> CircuitTable:
242
+ """
243
+ Return the product of x and y, where x and y have no common random variables.
244
+
245
+ This is an optimisation of more general product algorithm as no index needs
246
+ to be construction based on the common random variables.
247
+
248
+ Rows with constant node values of one are optimised out.
249
+
250
+ Assumes:
251
+ * There are no common random variables between x and y.
252
+ * x and y are for the same circuit.
253
+ """
254
+ circuit: Circuit = x.circuit
255
+
256
+ result_rv_idxs: Tuple[int, ...] = x.rv_idxs + y.rv_idxs
257
+
258
+ def _result_rows() -> Iterator[Tuple[TableInstance, CircuitNode]]:
259
+ for x_instance, x_node in x.rows.items():
260
+ if x_node.is_one():
261
+ for y_instance, y_node in y.rows.items():
262
+ instance = x_instance + y_instance
263
+ yield instance, y_node
264
+ else:
265
+ for y_instance, y_node in y.rows.items():
266
+ instance = x_instance + y_instance
267
+ yield instance, circuit.optimised_mul((x_node, y_node))
268
+
269
+ return CircuitTable(circuit, result_rv_idxs, _result_rows())