compiled-knowledge 4.0.0a20__cp313-cp313-macosx_10_13_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.

Files changed (178) hide show
  1. ck/__init__.py +0 -0
  2. ck/circuit/__init__.py +17 -0
  3. ck/circuit/_circuit_cy.c +37525 -0
  4. ck/circuit/_circuit_cy.cpython-313-darwin.so +0 -0
  5. ck/circuit/_circuit_cy.pxd +32 -0
  6. ck/circuit/_circuit_cy.pyx +768 -0
  7. ck/circuit/_circuit_py.py +836 -0
  8. ck/circuit/tmp_const.py +74 -0
  9. ck/circuit_compiler/__init__.py +2 -0
  10. ck/circuit_compiler/circuit_compiler.py +26 -0
  11. ck/circuit_compiler/cython_vm_compiler/__init__.py +1 -0
  12. ck/circuit_compiler/cython_vm_compiler/_compiler.c +19826 -0
  13. ck/circuit_compiler/cython_vm_compiler/_compiler.cpython-313-darwin.so +0 -0
  14. ck/circuit_compiler/cython_vm_compiler/_compiler.pyx +380 -0
  15. ck/circuit_compiler/cython_vm_compiler/cython_vm_compiler.py +121 -0
  16. ck/circuit_compiler/interpret_compiler.py +223 -0
  17. ck/circuit_compiler/llvm_compiler.py +388 -0
  18. ck/circuit_compiler/llvm_vm_compiler.py +546 -0
  19. ck/circuit_compiler/named_circuit_compilers.py +57 -0
  20. ck/circuit_compiler/support/__init__.py +0 -0
  21. ck/circuit_compiler/support/circuit_analyser/__init__.py +13 -0
  22. ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.c +10620 -0
  23. ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.cpython-313-darwin.so +0 -0
  24. ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.pyx +98 -0
  25. ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_py.py +93 -0
  26. ck/circuit_compiler/support/input_vars.py +148 -0
  27. ck/circuit_compiler/support/llvm_ir_function.py +234 -0
  28. ck/example/__init__.py +53 -0
  29. ck/example/alarm.py +366 -0
  30. ck/example/asia.py +28 -0
  31. ck/example/binary_clique.py +32 -0
  32. ck/example/bow_tie.py +33 -0
  33. ck/example/cancer.py +37 -0
  34. ck/example/chain.py +38 -0
  35. ck/example/child.py +199 -0
  36. ck/example/clique.py +33 -0
  37. ck/example/cnf_pgm.py +39 -0
  38. ck/example/diamond_square.py +68 -0
  39. ck/example/earthquake.py +36 -0
  40. ck/example/empty.py +10 -0
  41. ck/example/hailfinder.py +539 -0
  42. ck/example/hepar2.py +628 -0
  43. ck/example/insurance.py +504 -0
  44. ck/example/loop.py +40 -0
  45. ck/example/mildew.py +38161 -0
  46. ck/example/munin.py +22982 -0
  47. ck/example/pathfinder.py +53747 -0
  48. ck/example/rain.py +39 -0
  49. ck/example/rectangle.py +161 -0
  50. ck/example/run.py +30 -0
  51. ck/example/sachs.py +129 -0
  52. ck/example/sprinkler.py +30 -0
  53. ck/example/star.py +44 -0
  54. ck/example/stress.py +64 -0
  55. ck/example/student.py +43 -0
  56. ck/example/survey.py +46 -0
  57. ck/example/triangle_square.py +54 -0
  58. ck/example/truss.py +49 -0
  59. ck/in_out/__init__.py +3 -0
  60. ck/in_out/parse_ace_lmap.py +216 -0
  61. ck/in_out/parse_ace_nnf.py +322 -0
  62. ck/in_out/parse_net.py +480 -0
  63. ck/in_out/parser_utils.py +185 -0
  64. ck/in_out/pgm_pickle.py +42 -0
  65. ck/in_out/pgm_python.py +268 -0
  66. ck/in_out/render_bugs.py +111 -0
  67. ck/in_out/render_net.py +177 -0
  68. ck/in_out/render_pomegranate.py +184 -0
  69. ck/pgm.py +3475 -0
  70. ck/pgm_circuit/__init__.py +1 -0
  71. ck/pgm_circuit/marginals_program.py +352 -0
  72. ck/pgm_circuit/mpe_program.py +237 -0
  73. ck/pgm_circuit/pgm_circuit.py +79 -0
  74. ck/pgm_circuit/program_with_slotmap.py +236 -0
  75. ck/pgm_circuit/slot_map.py +35 -0
  76. ck/pgm_circuit/support/__init__.py +0 -0
  77. ck/pgm_circuit/support/compile_circuit.py +83 -0
  78. ck/pgm_circuit/target_marginals_program.py +103 -0
  79. ck/pgm_circuit/wmc_program.py +323 -0
  80. ck/pgm_compiler/__init__.py +2 -0
  81. ck/pgm_compiler/ace/__init__.py +1 -0
  82. ck/pgm_compiler/ace/ace.py +299 -0
  83. ck/pgm_compiler/factor_elimination.py +395 -0
  84. ck/pgm_compiler/named_pgm_compilers.py +63 -0
  85. ck/pgm_compiler/pgm_compiler.py +19 -0
  86. ck/pgm_compiler/recursive_conditioning.py +231 -0
  87. ck/pgm_compiler/support/__init__.py +0 -0
  88. ck/pgm_compiler/support/circuit_table/__init__.py +17 -0
  89. ck/pgm_compiler/support/circuit_table/_circuit_table_cy.c +16398 -0
  90. ck/pgm_compiler/support/circuit_table/_circuit_table_cy.cpython-313-darwin.so +0 -0
  91. ck/pgm_compiler/support/circuit_table/_circuit_table_cy.pyx +332 -0
  92. ck/pgm_compiler/support/circuit_table/_circuit_table_py.py +304 -0
  93. ck/pgm_compiler/support/clusters.py +568 -0
  94. ck/pgm_compiler/support/factor_tables.py +406 -0
  95. ck/pgm_compiler/support/join_tree.py +332 -0
  96. ck/pgm_compiler/support/named_compiler_maker.py +43 -0
  97. ck/pgm_compiler/variable_elimination.py +91 -0
  98. ck/probability/__init__.py +0 -0
  99. ck/probability/empirical_probability_space.py +50 -0
  100. ck/probability/pgm_probability_space.py +32 -0
  101. ck/probability/probability_space.py +622 -0
  102. ck/program/__init__.py +3 -0
  103. ck/program/program.py +137 -0
  104. ck/program/program_buffer.py +180 -0
  105. ck/program/raw_program.py +67 -0
  106. ck/sampling/__init__.py +0 -0
  107. ck/sampling/forward_sampler.py +211 -0
  108. ck/sampling/marginals_direct_sampler.py +113 -0
  109. ck/sampling/sampler.py +62 -0
  110. ck/sampling/sampler_support.py +232 -0
  111. ck/sampling/uniform_sampler.py +72 -0
  112. ck/sampling/wmc_direct_sampler.py +171 -0
  113. ck/sampling/wmc_gibbs_sampler.py +153 -0
  114. ck/sampling/wmc_metropolis_sampler.py +165 -0
  115. ck/sampling/wmc_rejection_sampler.py +115 -0
  116. ck/utils/__init__.py +0 -0
  117. ck/utils/iter_extras.py +163 -0
  118. ck/utils/local_config.py +270 -0
  119. ck/utils/map_list.py +128 -0
  120. ck/utils/map_set.py +128 -0
  121. ck/utils/np_extras.py +51 -0
  122. ck/utils/random_extras.py +64 -0
  123. ck/utils/tmp_dir.py +94 -0
  124. ck_demos/__init__.py +0 -0
  125. ck_demos/ace/__init__.py +0 -0
  126. ck_demos/ace/copy_ace_to_ck.py +15 -0
  127. ck_demos/ace/demo_ace.py +49 -0
  128. ck_demos/all_demos.py +88 -0
  129. ck_demos/circuit/__init__.py +0 -0
  130. ck_demos/circuit/demo_circuit_dump.py +22 -0
  131. ck_demos/circuit/demo_derivatives.py +43 -0
  132. ck_demos/circuit_compiler/__init__.py +0 -0
  133. ck_demos/circuit_compiler/compare_circuit_compilers.py +32 -0
  134. ck_demos/circuit_compiler/show_llvm_program.py +26 -0
  135. ck_demos/pgm/__init__.py +0 -0
  136. ck_demos/pgm/demo_pgm_dump.py +18 -0
  137. ck_demos/pgm/demo_pgm_dump_stress.py +18 -0
  138. ck_demos/pgm/demo_pgm_string_rendering.py +15 -0
  139. ck_demos/pgm/show_examples.py +25 -0
  140. ck_demos/pgm_compiler/__init__.py +0 -0
  141. ck_demos/pgm_compiler/compare_pgm_compilers.py +63 -0
  142. ck_demos/pgm_compiler/demo_compiler_dump.py +60 -0
  143. ck_demos/pgm_compiler/demo_factor_elimination.py +47 -0
  144. ck_demos/pgm_compiler/demo_join_tree.py +25 -0
  145. ck_demos/pgm_compiler/demo_marginals_program.py +53 -0
  146. ck_demos/pgm_compiler/demo_mpe_program.py +55 -0
  147. ck_demos/pgm_compiler/demo_pgm_compiler.py +38 -0
  148. ck_demos/pgm_compiler/demo_recursive_conditioning.py +33 -0
  149. ck_demos/pgm_compiler/demo_variable_elimination.py +33 -0
  150. ck_demos/pgm_compiler/demo_wmc_program.py +29 -0
  151. ck_demos/pgm_compiler/time_fe_compiler.py +93 -0
  152. ck_demos/pgm_inference/__init__.py +0 -0
  153. ck_demos/pgm_inference/demo_inferencing_basic.py +188 -0
  154. ck_demos/pgm_inference/demo_inferencing_mpe_cancer.py +45 -0
  155. ck_demos/pgm_inference/demo_inferencing_wmc_and_mpe_sprinkler.py +154 -0
  156. ck_demos/pgm_inference/demo_inferencing_wmc_student.py +110 -0
  157. ck_demos/programs/__init__.py +0 -0
  158. ck_demos/programs/demo_program_buffer.py +24 -0
  159. ck_demos/programs/demo_program_multi.py +24 -0
  160. ck_demos/programs/demo_program_none.py +19 -0
  161. ck_demos/programs/demo_program_single.py +23 -0
  162. ck_demos/programs/demo_raw_program_interpreted.py +21 -0
  163. ck_demos/programs/demo_raw_program_llvm.py +21 -0
  164. ck_demos/sampling/__init__.py +0 -0
  165. ck_demos/sampling/check_sampler.py +71 -0
  166. ck_demos/sampling/demo_marginal_direct_sampler.py +40 -0
  167. ck_demos/sampling/demo_uniform_sampler.py +38 -0
  168. ck_demos/sampling/demo_wmc_direct_sampler.py +40 -0
  169. ck_demos/utils/__init__.py +0 -0
  170. ck_demos/utils/compare.py +120 -0
  171. ck_demos/utils/convert_network.py +45 -0
  172. ck_demos/utils/sample_model.py +216 -0
  173. ck_demos/utils/stop_watch.py +384 -0
  174. compiled_knowledge-4.0.0a20.dist-info/METADATA +50 -0
  175. compiled_knowledge-4.0.0a20.dist-info/RECORD +178 -0
  176. compiled_knowledge-4.0.0a20.dist-info/WHEEL +6 -0
  177. compiled_knowledge-4.0.0a20.dist-info/licenses/LICENSE.txt +21 -0
  178. compiled_knowledge-4.0.0a20.dist-info/top_level.txt +2 -0
@@ -0,0 +1,380 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Dict, Tuple
4
+
5
+ import numpy as np
6
+ import ctypes as ct
7
+
8
+ from ck import circuit
9
+ from ck.circuit import OpNode
10
+ from ck.circuit_compiler.support.circuit_analyser import CircuitAnalysis
11
+ from ck.program.raw_program import RawProgramFunction
12
+ from ck.utils.np_extras import NDArrayNumeric, DTypeNumeric
13
+
14
+ from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
15
+ from cython.operator cimport dereference as deref, preincrement as incr, postdecrement
16
+
17
+ cimport numpy as cnp
18
+
19
+ cnp.import_array()
20
+
21
+ DTYPE_FLOAT64 = np.float64
22
+ ctypedef cnp.float64_t DTYPE_FLOAT64_t
23
+
24
+
25
+ ctypedef fused cvm_type:
26
+ double
27
+ float
28
+ int
29
+ long
30
+ short
31
+
32
+ DTYPE_TO_CVM_TYPE: Dict[DTypeNumeric, str] = {
33
+ np.float64: 'double',
34
+ np.float32: 'float',
35
+ np.intc: 'int',
36
+ np.long: 'long',
37
+ np.short: 'short',
38
+ }
39
+
40
+
41
+ def make_function(analysis: CircuitAnalysis, dtype: DTypeNumeric) -> Tuple[RawProgramFunction, int]:
42
+ """
43
+ Make a RawProgram function that interprets the circuit.
44
+
45
+ Args:
46
+ analysis: A circuit analysis object defining the function.
47
+ dtype: a numpy data type that must be a key in the dictionary, DTYPE_TO_CVM_TYPE.
48
+
49
+ Returns:
50
+ (function, number_of_tmps)
51
+ """
52
+
53
+ cdef Instructions instructions
54
+ np_consts: NDArrayNumeric
55
+ instructions, np_consts = _make_instructions_from_analysis(analysis, dtype)
56
+
57
+ ptr_type = ct.POINTER(np.ctypeslib.as_ctypes_type(dtype))
58
+ c_np_consts = np_consts.ctypes.data_as(ptr_type)
59
+
60
+ cvm_type_name: str = DTYPE_TO_CVM_TYPE[dtype]
61
+
62
+ # RawProgramFunction = Callable[[ct.POINTER, ct.POINTER, ct.POINTER], None]
63
+ if cvm_type_name == 'double':
64
+ def function(vars_in: ct.POINTER, tmps: ct.POINTER, result: ct.POINTER) -> None:
65
+ cdef size_t vars_in_addr = ct.cast(vars_in, ct.c_void_p).value
66
+ cdef size_t tmps_addr = ct.cast(tmps, ct.c_void_p).value
67
+ cdef size_t consts_addr = ct.cast(c_np_consts, ct.c_void_p).value
68
+ cdef size_t result_addr = ct.cast(result, ct.c_void_p).value
69
+ cvm[double](
70
+ <double *> vars_in_addr,
71
+ <double *> tmps_addr,
72
+ <double *> consts_addr,
73
+ <double *> result_addr,
74
+ instructions,
75
+ )
76
+ elif cvm_type_name == 'float':
77
+ def function(vars_in: ct.POINTER, tmps: ct.POINTER, result: ct.POINTER) -> None:
78
+ cdef size_t vars_in_addr = ct.cast(vars_in, ct.c_void_p).value
79
+ cdef size_t tmps_addr = ct.cast(tmps, ct.c_void_p).value
80
+ cdef size_t consts_addr = ct.cast(c_np_consts, ct.c_void_p).value
81
+ cdef size_t result_addr = ct.cast(result, ct.c_void_p).value
82
+ cvm[float](
83
+ <float *> vars_in_addr,
84
+ <float *> tmps_addr,
85
+ <float *> consts_addr,
86
+ <float *> result_addr,
87
+ instructions,
88
+ )
89
+ elif cvm_type_name == 'int':
90
+ def function(vars_in: ct.POINTER, tmps: ct.POINTER, result: ct.POINTER) -> None:
91
+ cdef size_t vars_in_addr = ct.cast(vars_in, ct.c_void_p).value
92
+ cdef size_t tmps_addr = ct.cast(tmps, ct.c_void_p).value
93
+ cdef size_t consts_addr = ct.cast(c_np_consts, ct.c_void_p).value
94
+ cdef size_t result_addr = ct.cast(result, ct.c_void_p).value
95
+ cvm[int](
96
+ <int *> vars_in_addr,
97
+ <int *> tmps_addr,
98
+ <int *> consts_addr,
99
+ <int *> result_addr,
100
+ instructions,
101
+ )
102
+ elif cvm_type_name == 'long':
103
+ def function(vars_in: ct.POINTER, tmps: ct.POINTER, result: ct.POINTER) -> None:
104
+ cdef size_t vars_in_addr = ct.cast(vars_in, ct.c_void_p).value
105
+ cdef size_t tmps_addr = ct.cast(tmps, ct.c_void_p).value
106
+ cdef size_t consts_addr = ct.cast(c_np_consts, ct.c_void_p).value
107
+ cdef size_t result_addr = ct.cast(result, ct.c_void_p).value
108
+ cvm[long](
109
+ <long *> vars_in_addr,
110
+ <long *> tmps_addr,
111
+ <long *> consts_addr,
112
+ <long *> result_addr,
113
+ instructions,
114
+ )
115
+ elif cvm_type_name == 'short':
116
+ def function(vars_in: ct.POINTER, tmps: ct.POINTER, result: ct.POINTER) -> None:
117
+ cdef size_t vars_in_addr = ct.cast(vars_in, ct.c_void_p).value
118
+ cdef size_t tmps_addr = ct.cast(tmps, ct.c_void_p).value
119
+ cdef size_t consts_addr = ct.cast(c_np_consts, ct.c_void_p).value
120
+ cdef size_t result_addr = ct.cast(result, ct.c_void_p).value
121
+ cvm[short](
122
+ <short *> vars_in_addr,
123
+ <short *> tmps_addr,
124
+ <short *> consts_addr,
125
+ <short *> result_addr,
126
+ instructions,
127
+ )
128
+ else:
129
+ raise ValueError(f'cvm_type_name unexpected: {cvm_type_name!r}')
130
+
131
+ return function, len(analysis.op_to_tmp)
132
+
133
+ # VM instructions
134
+ cdef int ADD = circuit.ADD
135
+ cdef int MUL = circuit.MUL
136
+ cdef int COPY = max(ADD, MUL) + 1
137
+
138
+ # VM arrays
139
+ cdef int VARS = 0
140
+ cdef int TMPS = 1
141
+ cdef int CONSTS = 2
142
+ cdef int RESULT = 3
143
+
144
+ cdef tuple[Instructions, cnp.ndarray] _make_instructions_from_analysis(
145
+ object analysis: CircuitAnalysis,
146
+ object dtype: DTypeNumeric,
147
+ ):
148
+ # Store const values in a numpy array
149
+ node_to_const_idx: Dict[int, int] = {
150
+ id(node): i
151
+ for i, node in enumerate(analysis.const_nodes)
152
+ }
153
+ np_consts: NDArrayNumeric = np.zeros(len(node_to_const_idx), dtype=dtype)
154
+ for i, node in enumerate(analysis.const_nodes):
155
+ np_consts[i] = node.value
156
+
157
+ # Where to get input values for each possible node.
158
+ cdef dict[int, ElementID] node_to_element = {}
159
+ # const nodes
160
+ for node_id, const_idx in node_to_const_idx.items():
161
+ node_to_element[node_id] = ElementID(CONSTS, const_idx)
162
+ # var nodes
163
+ for i, var_node in enumerate(analysis.var_nodes):
164
+ if var_node.is_const():
165
+ node_to_element[id(var_node)] = node_to_element[id(var_node.const)]
166
+ else:
167
+ node_to_element[id(var_node)] = ElementID(VARS, i)
168
+ # op nodes
169
+ for node_id, tmp_idx in analysis.op_to_tmp.items():
170
+ node_to_element[node_id] = ElementID(TMPS, tmp_idx)
171
+ for node_id, result_idx in analysis.op_to_result.items():
172
+ node_to_element[node_id] = ElementID(RESULT, result_idx)
173
+
174
+ # Build instructions
175
+ instructions: Instructions = Instructions()
176
+
177
+ cdef object op_node
178
+ for op_node in analysis.op_nodes:
179
+ instructions.append_op(op_node.symbol, op_node, node_to_element)
180
+
181
+ # Add any copy operations, i.e., result nodes that are not op nodes
182
+ for i, node in enumerate(analysis.result_nodes):
183
+ if not isinstance(node, OpNode):
184
+ dest: ElementID = ElementID(RESULT, i)
185
+ src: ElementID = node_to_element[id(node)]
186
+ instructions.append_copy(src, dest)
187
+
188
+ return instructions, np_consts
189
+
190
+ cdef struct ElementID:
191
+ int array # VARS, TMPS, CONSTS, RESULT
192
+ int index # index into the array
193
+
194
+ cdef struct Instruction:
195
+ int symbol # ADD, MUL, COPY
196
+ Py_ssize_t num_args
197
+ ElementID* args
198
+ ElementID dest
199
+
200
+ cdef class Instructions:
201
+ cdef Instruction* instructions
202
+ cdef int allocated
203
+ cdef int num_instructions
204
+
205
+ def __init__(self) -> None:
206
+ self.num_instructions = 0
207
+ self.allocated = 64
208
+ self.instructions = <Instruction *> PyMem_Malloc(self.allocated * sizeof(Instruction))
209
+
210
+ cdef void append_copy(
211
+ self,
212
+ ElementID src,
213
+ ElementID dest,
214
+ ) except*:
215
+ c_args = <ElementID *> PyMem_Malloc(sizeof(ElementID))
216
+ if not c_args:
217
+ raise MemoryError()
218
+
219
+ c_args[0] = src
220
+ self._append(COPY, 1, c_args, dest)
221
+
222
+ cdef void append_op(self, int symbol, object op_node: OpNode, dict[int, ElementID] node_to_element) except*:
223
+ args = op_node.args
224
+ cdef Py_ssize_t num_args = len(args)
225
+
226
+ # Create the instruction arguments array
227
+ c_args = <ElementID *> PyMem_Malloc(num_args * sizeof(ElementID))
228
+ if not c_args:
229
+ raise MemoryError()
230
+
231
+ cdef Py_ssize_t i = num_args
232
+ while i > 0:
233
+ i -= 1
234
+ c_args[i] = node_to_element[id(args[i])]
235
+
236
+ dest: ElementID = node_to_element[id(op_node)]
237
+
238
+ self._append(symbol, num_args, c_args, dest)
239
+
240
+ cdef void _append(self, int symbol, Py_ssize_t num_args, ElementID * c_args, ElementID dest) except*:
241
+ cdef int i
242
+
243
+ cdef int num_instructions = self.num_instructions
244
+
245
+ # Ensure sufficient instruction memory
246
+ cdef int allocated = self.allocated
247
+ if num_instructions == allocated:
248
+ allocated *= 2
249
+ self.instructions = <Instruction *> PyMem_Realloc(
250
+ self.instructions,
251
+ allocated * sizeof(Instruction),
252
+ )
253
+ if not self.instructions:
254
+ raise MemoryError()
255
+ self.allocated = allocated
256
+
257
+ # Add the instruction
258
+ self.instructions[num_instructions] = Instruction(
259
+ symbol,
260
+ num_args,
261
+ c_args,
262
+ dest
263
+ )
264
+ self.num_instructions = num_instructions + 1
265
+
266
+ def __dealloc__(self) -> None:
267
+ cdef Instruction * instructions = self.instructions
268
+ if instructions:
269
+ for i in range(self.num_instructions):
270
+ PyMem_Free(instructions[i].args)
271
+ PyMem_Free(instructions)
272
+
273
+ cdef void cvm(
274
+ cvm_type * vars_in,
275
+ cvm_type * tmps,
276
+ cvm_type * consts,
277
+ cvm_type * result,
278
+ Instructions instructions,
279
+ ):
280
+ # Core virtual machine (for fused type 'cvm_type').
281
+
282
+ cdef int symbol
283
+ cdef cvm_type accumulator
284
+ cdef ElementID * args
285
+ cdef ElementID * args_end
286
+ cdef ElementID * dest
287
+
288
+ # Index the four arrays by constants VARS, TMPS, CONSTS, and RESULT
289
+ cdef (cvm_type *) arrays[4]
290
+ arrays[VARS] = vars_in
291
+ arrays[TMPS] = tmps
292
+ arrays[CONSTS] = consts
293
+ arrays[RESULT] = result
294
+
295
+ cdef Instruction * instruction_ptr = instructions.instructions
296
+ cdef Instruction * instruction_end = instruction_ptr + instructions.num_instructions
297
+
298
+ while instruction_ptr < instruction_end:
299
+
300
+ symbol = instruction_ptr.symbol
301
+ args = instruction_ptr.args
302
+
303
+ accumulator = arrays[args.array][args.index]
304
+
305
+ if symbol == ADD:
306
+ args_end = args + instruction_ptr.num_args
307
+ incr(args)
308
+ while args < args_end:
309
+ accumulator += arrays[args.array][args.index]
310
+ incr(args)
311
+ elif symbol == MUL:
312
+ args_end = args + instruction_ptr.num_args
313
+ incr(args)
314
+ while args < args_end:
315
+ accumulator *= arrays[args.array][args.index]
316
+ incr(args)
317
+ # else symbol == COPY, nothing to do
318
+
319
+ dest = &instruction_ptr.dest
320
+ arrays[dest.array][dest.index] = accumulator
321
+
322
+ # Advance the instruction pointer
323
+ incr(instruction_ptr)
324
+
325
+
326
+ # This is the older 4.0.0a17 version which seems to be 10% faster sometimes!
327
+ #
328
+ # cdef void cvm(
329
+ # cvm_type * vars_in,
330
+ # cvm_type * tmps,
331
+ # cvm_type * consts,
332
+ # cvm_type * result,
333
+ # Instructions instructions,
334
+ # ):
335
+ # # Core virtual machine (for fused type 'cvm_type').
336
+ #
337
+ # cdef int symbol
338
+ # cdef Py_ssize_t i
339
+ # cdef cvm_type accumulator
340
+ # cdef ElementID* args
341
+ # cdef ElementID elem
342
+ #
343
+ # # Index the four arrays by constants VARS, TMPS, CONSTS, and RESULT
344
+ # cdef (cvm_type*) arrays[4]
345
+ # arrays[VARS] = vars_in
346
+ # arrays[TMPS] = tmps
347
+ # arrays[CONSTS] = consts
348
+ # arrays[RESULT] = result
349
+ #
350
+ # cdef Instruction* instruction_ptr = instructions.instructions
351
+ # cdef Py_ssize_t num_instructions = instructions.num_instructions
352
+ #
353
+ # while num_instructions > 0:
354
+ # num_instructions -= 1
355
+ #
356
+ # symbol = instruction_ptr.symbol
357
+ # args = instruction_ptr.args
358
+ #
359
+ # elem = args[0]
360
+ # accumulator = arrays[elem.array][elem.index]
361
+ #
362
+ # if symbol == ADD:
363
+ # i = instruction_ptr.num_args
364
+ # while i > 1:
365
+ # i -= 1
366
+ # elem = args[i]
367
+ # accumulator += arrays[elem.array][elem.index]
368
+ # elif symbol == MUL:
369
+ # i = instruction_ptr.num_args
370
+ # while i > 1:
371
+ # i -= 1
372
+ # elem = args[i]
373
+ # accumulator *= arrays[elem.array][elem.index]
374
+ # # else symbol == COPY, nothing to do
375
+ #
376
+ # elem = instruction_ptr.dest
377
+ # arrays[elem.array][elem.index] = accumulator
378
+ #
379
+ # # Advance the instruction pointer
380
+ # instruction_ptr = &(instruction_ptr[1])
@@ -0,0 +1,121 @@
1
+ from typing import Optional, Sequence, Tuple
2
+
3
+ import numpy as np
4
+
5
+ from ck.circuit import CircuitNode, Circuit, VarNode
6
+ from ck.circuit_compiler.support.input_vars import InferVars, InputVars, infer_input_vars
7
+ from ck.program.raw_program import RawProgram, RawProgramFunction
8
+ from ck.utils.np_extras import DTypeNumeric
9
+ from . import _compiler
10
+ from ..support.circuit_analyser import CircuitAnalysis, analyze_circuit
11
+
12
+
13
+ def compile_circuit(
14
+ *result: CircuitNode,
15
+ input_vars: InputVars = InferVars.ALL,
16
+ circuit: Optional[Circuit] = None,
17
+ dtype: DTypeNumeric = np.double,
18
+ ) -> RawProgram:
19
+ """
20
+ Make a RawProgram that interprets the given circuit using a Cython virtual cpu.
21
+
22
+ Args:
23
+ *result: if it is a single node, then the resulting function returns a single value,
24
+ if it is a sequence of nodes, then the resulting function returns a numpy array of values.
25
+ input_vars: how to determine the input variables.
26
+ circuit: optionally explicitly specify the Circuit
27
+ dtype: the numpy DType to use for the raw program.
28
+
29
+ Returns:
30
+ a raw program.
31
+
32
+ Raises:
33
+ ValueError: if the circuit is unknown, but it is needed.
34
+ ValueError: if not all nodes are from the same circuit.
35
+ ValueError: if the given dtype is not supported.
36
+ """
37
+ if dtype not in _compiler.DTYPE_TO_CVM_TYPE.keys():
38
+ raise ValueError(f'dtype not supported: {dtype!r}')
39
+
40
+ in_vars: Sequence[VarNode] = infer_input_vars(circuit, result, input_vars)
41
+ return CythonRawProgram(in_vars, result, dtype)
42
+
43
+
44
+ class CythonRawProgram(RawProgram):
45
+ def __init__(
46
+ self,
47
+ in_vars: Sequence[VarNode],
48
+ result: Sequence[CircuitNode],
49
+ dtype: DTypeNumeric,
50
+ ):
51
+ self.in_vars = in_vars
52
+ self.result = result
53
+
54
+ function, number_of_tmps = _make_function(
55
+ var_nodes=in_vars,
56
+ result_nodes=result,
57
+ dtype=dtype,
58
+ )
59
+
60
+ super().__init__(
61
+ function=function,
62
+ dtype=dtype,
63
+ number_of_vars=len(in_vars),
64
+ number_of_tmps=number_of_tmps,
65
+ number_of_results=len(result),
66
+ var_indices=tuple(var.idx for var in in_vars),
67
+ )
68
+
69
+ def __getstate__(self):
70
+ """
71
+ Support for pickle.
72
+ """
73
+ return {
74
+ 'dtype': self.dtype,
75
+ 'number_of_vars': self.number_of_vars,
76
+ 'number_of_tmps': self.number_of_tmps,
77
+ 'number_of_results': self.number_of_results,
78
+ 'var_indices': self.var_indices,
79
+ #
80
+ 'in_vars': self.in_vars,
81
+ 'result': self.result,
82
+ }
83
+
84
+ def __setstate__(self, state):
85
+ """
86
+ Support for pickle.
87
+ """
88
+ self.dtype = state['dtype']
89
+ self.number_of_vars = state['number_of_vars']
90
+ self.number_of_tmps = state['number_of_tmps']
91
+ self.number_of_results = state['number_of_results']
92
+ self.var_indices = state['var_indices']
93
+ #
94
+ self.in_vars = state['in_vars']
95
+ self.result = state['result']
96
+
97
+ self.function, _ = _make_function(
98
+ var_nodes=self.in_vars,
99
+ result_nodes=self.result,
100
+ dtype=self.dtype,
101
+ )
102
+
103
+
104
+ def _make_function(
105
+ var_nodes: Sequence[VarNode],
106
+ result_nodes: Sequence[CircuitNode],
107
+ dtype: DTypeNumeric,
108
+ ) -> Tuple[RawProgramFunction, int]:
109
+ """
110
+ Make a RawProgram function that interprets the circuit.
111
+
112
+ Args:
113
+ var_nodes: The chosen input variable nodes of the circuit.
114
+ result_nodes: The chosen output result nodes of the circuit.
115
+ dtype: a numpy data type that must be a key in the dictionary, DTYPE_TO_CVM_TYPE.
116
+
117
+ Returns:
118
+ (function, number_of_tmps)
119
+ """
120
+ analysis: CircuitAnalysis = analyze_circuit(var_nodes, result_nodes)
121
+ return _compiler.make_function(analysis, dtype)