compiled-knowledge 4.0.0a17__cp312-cp312-win_amd64.whl → 4.0.0a18__cp312-cp312-win_amd64.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/circuit/__init__.py +7 -0
- ck/circuit/_circuit_cy.cp312-win_amd64.pyd +0 -0
- ck/circuit/_circuit_cy.pxd +33 -0
- ck/circuit/_circuit_cy.pyx +84 -110
- ck/circuit/_circuit_py.py +2 -2
- ck/circuit_compiler/cython_vm_compiler/_compiler.cp312-win_amd64.pyd +0 -0
- ck/circuit_compiler/cython_vm_compiler/_compiler.pyx +6 -5
- ck/pgm_compiler/support/circuit_table/__init__.py +7 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy.cp312-win_amd64.pyd +0 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy.pyx +44 -37
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy_cpp_verion.pyx +601 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy_minimal_version.pyx +311 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy_v4.0.0a17.pyx +325 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_py.py +76 -41
- ck/pgm_compiler/support/named_compiler_maker.py +12 -2
- ck/utils/iter_extras.py +8 -1
- ck_demos/utils/compare.py +5 -1
- {compiled_knowledge-4.0.0a17.dist-info → compiled_knowledge-4.0.0a18.dist-info}/METADATA +1 -1
- {compiled_knowledge-4.0.0a17.dist-info → compiled_knowledge-4.0.0a18.dist-info}/RECORD +22 -19
- {compiled_knowledge-4.0.0a17.dist-info → compiled_knowledge-4.0.0a18.dist-info}/WHEEL +1 -1
- ck/circuit_compiler/cython_vm_compiler/_compiler.c +0 -16946
- {compiled_knowledge-4.0.0a17.dist-info → compiled_knowledge-4.0.0a18.dist-info}/licenses/LICENSE.txt +0 -0
- {compiled_knowledge-4.0.0a17.dist-info → compiled_knowledge-4.0.0a18.dist-info}/top_level.txt +0 -0
ck/circuit/__init__.py
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# There are two implementations of the `circuit` 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
|
+
# A similar selection can be made for the `circuit_table` module.
|
|
5
|
+
# Note that if the Cython implementation is chosen for `circuit_table` then
|
|
6
|
+
# the Cython implementation must be chosen for `circuit`.
|
|
7
|
+
|
|
1
8
|
# from ._circuit_py import (
|
|
2
9
|
from ._circuit_cy import (
|
|
3
10
|
Circuit,
|
|
Binary file
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
cdef class Circuit:
|
|
2
|
+
cdef public list[VarNode] vars
|
|
3
|
+
cdef public list[OpNode] ops
|
|
4
|
+
cdef public object zero
|
|
5
|
+
cdef public object one
|
|
6
|
+
cdef dict[object, ConstNode] _const_map
|
|
7
|
+
cdef object __derivatives
|
|
8
|
+
|
|
9
|
+
cdef OpNode op(self, int symbol, tuple[CircuitNode, ...] nodes)
|
|
10
|
+
cdef void _remove_unreachable_op_nodes(self, list[CircuitNode] nodes)
|
|
11
|
+
cdef list[OpNode] _reachable_op_nodes(self, list[CircuitNode] nodes)
|
|
12
|
+
cdef list[CircuitNode] _check_nodes(self, object nodes)
|
|
13
|
+
cdef void __check_nodes(self, object nodes, list[CircuitNode] result)
|
|
14
|
+
cdef object _derivatives(self, CircuitNode f)
|
|
15
|
+
cdef object _derivatives(self, CircuitNode f)
|
|
16
|
+
|
|
17
|
+
cdef class CircuitNode:
|
|
18
|
+
cdef public Circuit circuit
|
|
19
|
+
cdef public bint is_zero
|
|
20
|
+
cdef public bint is_one
|
|
21
|
+
|
|
22
|
+
cdef class ConstNode(CircuitNode):
|
|
23
|
+
cdef public object value
|
|
24
|
+
|
|
25
|
+
cdef class VarNode(CircuitNode):
|
|
26
|
+
cdef public int idx
|
|
27
|
+
cdef object _const
|
|
28
|
+
|
|
29
|
+
cpdef int is_const(self) except*
|
|
30
|
+
|
|
31
|
+
cdef class OpNode(CircuitNode):
|
|
32
|
+
cdef public tuple[object, ...] args
|
|
33
|
+
cdef public int symbol
|
ck/circuit/_circuit_cy.pyx
CHANGED
|
@@ -4,7 +4,7 @@ For more documentation on this module, refer to the Jupyter notebook docs/6_circ
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
from itertools import chain
|
|
7
|
-
from typing import Dict, Tuple, Optional, Iterable, Sequence, List, overload
|
|
7
|
+
from typing import Dict, Tuple, Optional, Iterable, Sequence, List, overload
|
|
8
8
|
|
|
9
9
|
# Type for values of ConstNode objects
|
|
10
10
|
ConstValue = float | int | bool
|
|
@@ -15,6 +15,8 @@ Args = CircuitNode | ConstValue | Iterable[CircuitNode | ConstValue]
|
|
|
15
15
|
ADD: int = 0
|
|
16
16
|
MUL: int = 1
|
|
17
17
|
|
|
18
|
+
cdef int c_ADD = ADD
|
|
19
|
+
cdef int c_MUL = MUL
|
|
18
20
|
|
|
19
21
|
cdef class Circuit:
|
|
20
22
|
"""
|
|
@@ -29,13 +31,6 @@ cdef class Circuit:
|
|
|
29
31
|
`VarNode` may be temporarily be set to a constant value.
|
|
30
32
|
"""
|
|
31
33
|
|
|
32
|
-
cdef public list[VarNode] vars
|
|
33
|
-
cdef public list[OpNode] ops
|
|
34
|
-
cdef public object zero
|
|
35
|
-
cdef public object one
|
|
36
|
-
cdef dict[Any, ConstNode] _const_map
|
|
37
|
-
cdef object __derivatives
|
|
38
|
-
|
|
39
34
|
def __init__(self, zero: ConstValue = 0, one: ConstValue = 1):
|
|
40
35
|
"""
|
|
41
36
|
Construct a new, empty circuit.
|
|
@@ -127,72 +122,57 @@ cdef class Circuit:
|
|
|
127
122
|
self._const_map[value] = node
|
|
128
123
|
return node
|
|
129
124
|
|
|
130
|
-
cdef OpNode _op(self, int symbol, tuple[CircuitNode, ...] nodes):
|
|
131
|
-
cdef OpNode node = OpNode(self, symbol, nodes)
|
|
132
|
-
self.ops.append(node)
|
|
133
|
-
return node
|
|
134
|
-
|
|
135
125
|
def add(self, *nodes: Args) -> OpNode:
|
|
136
126
|
"""
|
|
137
127
|
Create and return a new 'addition' node, applied to the given arguments.
|
|
138
128
|
"""
|
|
139
129
|
cdef list[CircuitNode] args = self._check_nodes(nodes)
|
|
140
|
-
return self.
|
|
130
|
+
return self.op(c_ADD, tuple(args))
|
|
141
131
|
|
|
142
132
|
def mul(self, *nodes: Args) -> OpNode:
|
|
143
133
|
"""
|
|
144
134
|
Create and return a new 'multiplication' node, applied to the given arguments.
|
|
145
135
|
"""
|
|
146
136
|
cdef list[CircuitNode] args = self._check_nodes(nodes)
|
|
147
|
-
return self.
|
|
137
|
+
return self.op(c_MUL, tuple(args))
|
|
148
138
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
cdef CircuitNode n
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
raise RuntimeError('node does not belong to this circuit')
|
|
162
|
-
if not n.is_zero:
|
|
163
|
-
to_add.append(n)
|
|
164
|
-
cdef int len_to_add = len(to_add)
|
|
165
|
-
if len_to_add == 0:
|
|
139
|
+
def optimised_add(self, *args: Args) -> CircuitNode:
|
|
140
|
+
"""
|
|
141
|
+
Optimised circuit node addition.
|
|
142
|
+
|
|
143
|
+
Performs the following optimisations:
|
|
144
|
+
* addition to zero is avoided: add(x, 0) = x,
|
|
145
|
+
* singleton addition is avoided: add(x) = x,
|
|
146
|
+
* empty addition is avoided: add() = 0,
|
|
147
|
+
"""
|
|
148
|
+
cdef tuple[CircuitNode] to_add = tuple(n for n in self._check_nodes(args) if not n.is_zero)
|
|
149
|
+
cdef size_t num_to_add = len(to_add)
|
|
150
|
+
if num_to_add == 0:
|
|
166
151
|
return self.zero
|
|
167
|
-
|
|
152
|
+
if num_to_add == 1:
|
|
168
153
|
return to_add[0]
|
|
169
|
-
|
|
170
|
-
return self._op(ADD, tuple(to_add))
|
|
154
|
+
return self.op(c_ADD, to_add)
|
|
171
155
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
for n in
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
to_mul.append(n)
|
|
189
|
-
cdef int len_to_mul = len(to_mul)
|
|
190
|
-
if len_to_mul == 0:
|
|
156
|
+
def optimised_mul(self, *args: Args) -> CircuitNode:
|
|
157
|
+
"""
|
|
158
|
+
Optimised circuit node multiplication.
|
|
159
|
+
|
|
160
|
+
Performs the following optimisations:
|
|
161
|
+
* multiplication by zero is avoided: mul(x, 0) = 0,
|
|
162
|
+
* multiplication by one is avoided: mul(x, 1) = x,
|
|
163
|
+
* singleton multiplication is avoided: mul(x) = x,
|
|
164
|
+
* empty multiplication is avoided: mul() = 1,
|
|
165
|
+
"""
|
|
166
|
+
cdef tuple[CircuitNode] to_mul = tuple(n for n in self._check_nodes(args) if not n.is_one)
|
|
167
|
+
if any(n.is_zero for n in to_mul):
|
|
168
|
+
return self.zero
|
|
169
|
+
cdef size_t num_to_mul = len(to_mul)
|
|
170
|
+
|
|
171
|
+
if num_to_mul == 0:
|
|
191
172
|
return self.one
|
|
192
|
-
|
|
173
|
+
if num_to_mul == 1:
|
|
193
174
|
return to_mul[0]
|
|
194
|
-
|
|
195
|
-
return self._op(MUL, tuple(to_mul))
|
|
175
|
+
return self.op(c_MUL, to_mul)
|
|
196
176
|
|
|
197
177
|
def cartesian_product(self, xs: Sequence[CircuitNode], ys: Sequence[CircuitNode]) -> List[CircuitNode]:
|
|
198
178
|
"""
|
|
@@ -209,7 +189,7 @@ cdef class Circuit:
|
|
|
209
189
|
xs: List[CircuitNode] = self._check_nodes(xs)
|
|
210
190
|
ys: List[CircuitNode] = self._check_nodes(ys)
|
|
211
191
|
return [
|
|
212
|
-
self.optimised_mul(
|
|
192
|
+
self.optimised_mul(x, y)
|
|
213
193
|
for x in xs
|
|
214
194
|
for y in ys
|
|
215
195
|
]
|
|
@@ -306,24 +286,6 @@ cdef class Circuit:
|
|
|
306
286
|
nodes = self._check_nodes(nodes)
|
|
307
287
|
self._remove_unreachable_op_nodes(nodes)
|
|
308
288
|
|
|
309
|
-
cdef void _remove_unreachable_op_nodes(self, list[CircuitNode] nodes):
|
|
310
|
-
# Set of object ids for all reachable op nodes
|
|
311
|
-
cdef set[int] seen = set()
|
|
312
|
-
|
|
313
|
-
cdef CircuitNode node
|
|
314
|
-
for node in nodes:
|
|
315
|
-
_reachable_op_nodes_seen_r(node, seen)
|
|
316
|
-
|
|
317
|
-
if len(seen) < len(self.ops):
|
|
318
|
-
# Invalidate unreadable op nodes
|
|
319
|
-
for op_node in self.ops:
|
|
320
|
-
if id(op_node) not in seen:
|
|
321
|
-
op_node.circuit = None
|
|
322
|
-
op_node.args = ()
|
|
323
|
-
|
|
324
|
-
# Keep only reachable op nodes, in the same order as `self.ops`.
|
|
325
|
-
self.ops = [op_node for op_node in self.ops if id(op_node) in seen]
|
|
326
|
-
|
|
327
289
|
def reachable_op_nodes(self, *nodes: Args) -> List[OpNode]:
|
|
328
290
|
"""
|
|
329
291
|
Iterate over all op nodes reachable from the given nodes, via op arguments.
|
|
@@ -341,17 +303,6 @@ cdef class Circuit:
|
|
|
341
303
|
nodes = self._check_nodes(nodes)
|
|
342
304
|
return self._reachable_op_nodes(nodes)
|
|
343
305
|
|
|
344
|
-
cdef list[OpNode] _reachable_op_nodes(self, list[CircuitNode] nodes):
|
|
345
|
-
# Set of object ids for all reachable op nodes
|
|
346
|
-
cdef set[int] seen = set()
|
|
347
|
-
|
|
348
|
-
cdef list[OpNode] result = []
|
|
349
|
-
|
|
350
|
-
cdef CircuitNode node
|
|
351
|
-
for node in nodes:
|
|
352
|
-
_reachable_op_nodes_r(node, seen, result)
|
|
353
|
-
return result
|
|
354
|
-
|
|
355
306
|
def dump(
|
|
356
307
|
self,
|
|
357
308
|
*,
|
|
@@ -415,6 +366,40 @@ cdef class Circuit:
|
|
|
415
366
|
args_str = ' '.join(node_name[id(arg)] for arg in op.args)
|
|
416
367
|
print(f'{next_prefix}{op_name}: {args_str}')
|
|
417
368
|
|
|
369
|
+
cdef OpNode op(self, int symbol, tuple[CircuitNode, ...] nodes):
|
|
370
|
+
cdef OpNode node = OpNode(self, symbol, nodes)
|
|
371
|
+
self.ops.append(node)
|
|
372
|
+
return node
|
|
373
|
+
|
|
374
|
+
cdef list[OpNode] _reachable_op_nodes(self, list[CircuitNode] nodes):
|
|
375
|
+
# Set of object ids for all reachable op nodes
|
|
376
|
+
cdef set[int] seen = set()
|
|
377
|
+
|
|
378
|
+
cdef list[OpNode] result = []
|
|
379
|
+
|
|
380
|
+
cdef CircuitNode node
|
|
381
|
+
for node in nodes:
|
|
382
|
+
_reachable_op_nodes_r(node, seen, result)
|
|
383
|
+
return result
|
|
384
|
+
|
|
385
|
+
cdef void _remove_unreachable_op_nodes(self, list[CircuitNode] nodes):
|
|
386
|
+
# Set of object ids for all reachable op nodes
|
|
387
|
+
cdef set[int] seen = set()
|
|
388
|
+
|
|
389
|
+
cdef CircuitNode node
|
|
390
|
+
for node in nodes:
|
|
391
|
+
_reachable_op_nodes_seen_r(node, seen)
|
|
392
|
+
|
|
393
|
+
if len(seen) < len(self.ops):
|
|
394
|
+
# Invalidate unreadable op nodes
|
|
395
|
+
for op_node in self.ops:
|
|
396
|
+
if id(op_node) not in seen:
|
|
397
|
+
op_node.circuit = None
|
|
398
|
+
op_node.args = ()
|
|
399
|
+
|
|
400
|
+
# Keep only reachable op nodes, in the same order as `self.ops`.
|
|
401
|
+
self.ops = [op_node for op_node in self.ops if id(op_node) in seen]
|
|
402
|
+
|
|
418
403
|
cdef list[CircuitNode] _check_nodes(self, object nodes: Iterable[Args]): # -> Sequence[CircuitNode]:
|
|
419
404
|
# Convert the given circuit nodes to a tuple, flattening nested iterables as needed.
|
|
420
405
|
#
|
|
@@ -427,7 +412,7 @@ cdef class Circuit:
|
|
|
427
412
|
self.__check_nodes(nodes, result)
|
|
428
413
|
return result
|
|
429
414
|
|
|
430
|
-
cdef void __check_nodes(self, nodes: Iterable[Args], list[CircuitNode] result):
|
|
415
|
+
cdef void __check_nodes(self, object nodes: Iterable[Args], list[CircuitNode] result):
|
|
431
416
|
# Convert the given circuit nodes to a tuple, flattening nested iterables as needed.
|
|
432
417
|
#
|
|
433
418
|
# Args:
|
|
@@ -455,7 +440,6 @@ cdef class Circuit:
|
|
|
455
440
|
self.__derivatives = derivatives
|
|
456
441
|
return derivatives
|
|
457
442
|
|
|
458
|
-
|
|
459
443
|
cdef class CircuitNode:
|
|
460
444
|
"""
|
|
461
445
|
A node in an arithmetic circuit.
|
|
@@ -470,9 +454,6 @@ cdef class CircuitNode:
|
|
|
470
454
|
A var node may be temporarily set to be a constant node, which may
|
|
471
455
|
be useful for optimising a compiled circuit.
|
|
472
456
|
"""
|
|
473
|
-
cdef public Circuit circuit
|
|
474
|
-
cdef public bint is_zero
|
|
475
|
-
cdef public bint is_one
|
|
476
457
|
|
|
477
458
|
def __init__(self, circuit: Circuit, is_zero: bool, is_one: bool):
|
|
478
459
|
self.circuit = circuit
|
|
@@ -485,11 +466,10 @@ cdef class CircuitNode:
|
|
|
485
466
|
def __mul__(self, other: CircuitNode | ConstValue):
|
|
486
467
|
return self.circuit.mul(self, other)
|
|
487
468
|
|
|
488
|
-
|
|
489
469
|
cdef class ConstNode(CircuitNode):
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
470
|
+
"""
|
|
471
|
+
A node in a circuit representing a constant value.
|
|
472
|
+
"""
|
|
493
473
|
|
|
494
474
|
def __init__(self, circuit, value: ConstValue, is_zero: bool = False, is_one: bool = False):
|
|
495
475
|
super().__init__(circuit, is_zero, is_one)
|
|
@@ -504,13 +484,10 @@ cdef class ConstNode(CircuitNode):
|
|
|
504
484
|
else:
|
|
505
485
|
return False
|
|
506
486
|
|
|
507
|
-
|
|
508
487
|
cdef class VarNode(CircuitNode):
|
|
509
488
|
"""
|
|
510
489
|
A node in a circuit representing an input variable.
|
|
511
490
|
"""
|
|
512
|
-
cdef public int idx
|
|
513
|
-
cdef object _const
|
|
514
491
|
|
|
515
492
|
def __init__(self, circuit, idx: int):
|
|
516
493
|
super().__init__(circuit, False, False)
|
|
@@ -552,13 +529,11 @@ cdef class OpNode(CircuitNode):
|
|
|
552
529
|
"""
|
|
553
530
|
A node in a circuit representing an arithmetic operation.
|
|
554
531
|
"""
|
|
555
|
-
cdef public tuple[object, ...] args
|
|
556
|
-
cdef public int symbol
|
|
557
532
|
|
|
558
533
|
def __init__(self, object circuit, symbol: int, tuple[object, ...] args: Tuple[CircuitNode]):
|
|
559
534
|
super().__init__(circuit, False, False)
|
|
560
535
|
self.args = tuple(args)
|
|
561
|
-
self.symbol = int
|
|
536
|
+
self.symbol = <int> symbol
|
|
562
537
|
|
|
563
538
|
def __str__(self) -> str:
|
|
564
539
|
return f'{self.op_str()}\\{len(self.args)}'
|
|
@@ -567,9 +542,9 @@ cdef class OpNode(CircuitNode):
|
|
|
567
542
|
"""
|
|
568
543
|
Returns the op node operation as a string.
|
|
569
544
|
"""
|
|
570
|
-
if self.symbol ==
|
|
545
|
+
if self.symbol == c_MUL:
|
|
571
546
|
return 'mul'
|
|
572
|
-
elif self.symbol ==
|
|
547
|
+
elif self.symbol == c_ADD:
|
|
573
548
|
return 'add'
|
|
574
549
|
else:
|
|
575
550
|
return '?' + str(self.symbol)
|
|
@@ -667,7 +642,7 @@ class _DerivativeHelper:
|
|
|
667
642
|
elif d is self.one:
|
|
668
643
|
d_node.derivative_self_mul = node
|
|
669
644
|
else:
|
|
670
|
-
d_node.derivative_self_mul = self.circuit.optimised_mul(
|
|
645
|
+
d_node.derivative_self_mul = self.circuit.optimised_mul(d, node)
|
|
671
646
|
|
|
672
647
|
return d_node.derivative_self_mul
|
|
673
648
|
|
|
@@ -685,7 +660,7 @@ class _DerivativeHelper:
|
|
|
685
660
|
d_node.sum_prod = None
|
|
686
661
|
|
|
687
662
|
# Construct the addition operation
|
|
688
|
-
d_node.derivative = self.circuit.optimised_add(to_add)
|
|
663
|
+
d_node.derivative = self.circuit.optimised_add(*to_add)
|
|
689
664
|
|
|
690
665
|
return d_node.derivative
|
|
691
666
|
|
|
@@ -706,7 +681,7 @@ class _DerivativeHelper:
|
|
|
706
681
|
to_mul.append(arg)
|
|
707
682
|
|
|
708
683
|
# Construct the multiplication operation
|
|
709
|
-
return self.circuit.optimised_mul(to_mul)
|
|
684
|
+
return self.circuit.optimised_mul(*to_mul)
|
|
710
685
|
|
|
711
686
|
def _mk_derivative_r(self, d_node: _DNode) -> None:
|
|
712
687
|
"""
|
|
@@ -718,11 +693,11 @@ class _DerivativeHelper:
|
|
|
718
693
|
node: CircuitNode = d_node.node
|
|
719
694
|
|
|
720
695
|
if isinstance(node, OpNode):
|
|
721
|
-
if node.symbol ==
|
|
696
|
+
if node.symbol == c_ADD:
|
|
722
697
|
for arg in node.args:
|
|
723
698
|
child_d_node = self._add(arg, d_node, [])
|
|
724
699
|
self._mk_derivative_r(child_d_node)
|
|
725
|
-
elif node.symbol ==
|
|
700
|
+
elif node.symbol == c_MUL:
|
|
726
701
|
for arg in node.args:
|
|
727
702
|
prod = [arg2 for arg2 in node.args if arg is not arg2]
|
|
728
703
|
child_d_node = self._add(arg, d_node, prod)
|
|
@@ -780,7 +755,6 @@ cdef void _reachable_op_nodes_r(CircuitNode node, set[int] seen, list[OpNode] re
|
|
|
780
755
|
_reachable_op_nodes_r(arg, seen, result)
|
|
781
756
|
result.append(node)
|
|
782
757
|
|
|
783
|
-
|
|
784
758
|
cdef void _reachable_op_nodes_seen_r(CircuitNode node, set[int] seen):
|
|
785
759
|
# Recursive helper for `remove_unreachable_op_nodes`. Performs a depth-first search.
|
|
786
760
|
#
|
ck/circuit/_circuit_py.py
CHANGED
|
@@ -721,7 +721,7 @@ class _DerivativeHelper:
|
|
|
721
721
|
d_node.sum_prod = None
|
|
722
722
|
|
|
723
723
|
# Construct the addition operation
|
|
724
|
-
d_node.derivative = self.circuit.optimised_add(to_add)
|
|
724
|
+
d_node.derivative = self.circuit.optimised_add(*to_add)
|
|
725
725
|
|
|
726
726
|
return d_node.derivative
|
|
727
727
|
|
|
@@ -742,7 +742,7 @@ class _DerivativeHelper:
|
|
|
742
742
|
to_mul.append(arg)
|
|
743
743
|
|
|
744
744
|
# Construct the multiplication operation
|
|
745
|
-
return self.circuit.optimised_mul(to_mul)
|
|
745
|
+
return self.circuit.optimised_mul(*to_mul)
|
|
746
746
|
|
|
747
747
|
def _mk_derivative_r(self, d_node: _DNode) -> None:
|
|
748
748
|
"""
|
|
Binary file
|
|
@@ -129,7 +129,7 @@ cdef struct ElementID:
|
|
|
129
129
|
|
|
130
130
|
cdef struct Instruction:
|
|
131
131
|
int symbol # ADD, MUL, COPY
|
|
132
|
-
|
|
132
|
+
Py_ssize_t num_args
|
|
133
133
|
ElementID* args
|
|
134
134
|
ElementID dest
|
|
135
135
|
|
|
@@ -158,14 +158,14 @@ cdef class Instructions:
|
|
|
158
158
|
|
|
159
159
|
cdef void append_op(self, int symbol, object op_node: OpNode, dict[int, ElementID] node_to_element) except*:
|
|
160
160
|
args = op_node.args
|
|
161
|
-
cdef
|
|
161
|
+
cdef Py_ssize_t num_args = len(args)
|
|
162
162
|
|
|
163
163
|
# Create the instruction arguments array
|
|
164
164
|
c_args = <ElementID*> PyMem_Malloc(num_args * sizeof(ElementID))
|
|
165
165
|
if not c_args:
|
|
166
166
|
raise MemoryError()
|
|
167
167
|
|
|
168
|
-
cdef
|
|
168
|
+
cdef Py_ssize_t i = num_args
|
|
169
169
|
while i > 0:
|
|
170
170
|
i -= 1
|
|
171
171
|
c_args[i] = node_to_element[id(args[i])]
|
|
@@ -175,7 +175,7 @@ cdef class Instructions:
|
|
|
175
175
|
self._append(symbol, num_args, c_args, dest)
|
|
176
176
|
|
|
177
177
|
|
|
178
|
-
cdef void _append(self, int symbol,
|
|
178
|
+
cdef void _append(self, int symbol, Py_ssize_t num_args, ElementID* c_args, ElementID dest) except *:
|
|
179
179
|
cdef int i
|
|
180
180
|
|
|
181
181
|
cdef int num_instructions = self.num_instructions
|
|
@@ -221,7 +221,8 @@ cdef void cvm_float64(
|
|
|
221
221
|
) except *:
|
|
222
222
|
# Core virtual machine (for dtype float64).
|
|
223
223
|
|
|
224
|
-
cdef int
|
|
224
|
+
cdef int symbol
|
|
225
|
+
cdef Py_ssize_t i
|
|
225
226
|
cdef double accumulator
|
|
226
227
|
cdef ElementID* args
|
|
227
228
|
cdef ElementID elem
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
# A similar selection can be made for the `circuit` module.
|
|
5
|
+
# Note that if the Cython implementation is chosen for `circuit_table` then
|
|
6
|
+
# the Cython implementation must be chosen for `circuit`.
|
|
7
|
+
|
|
1
8
|
# from ._circuit_table_py import (
|
|
2
9
|
from ._circuit_table_cy import (
|
|
3
10
|
CircuitTable,
|
|
Binary file
|