compiled-knowledge 4.0.0a24__cp312-cp312-win_amd64.whl → 4.1.0__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/_circuit_cy.c +1 -1
- ck/circuit/_circuit_cy.cp312-win_amd64.pyd +0 -0
- ck/circuit/tmp_const.py +5 -4
- ck/circuit_compiler/cython_vm_compiler/_compiler.c +152 -152
- ck/circuit_compiler/cython_vm_compiler/_compiler.cp312-win_amd64.pyd +0 -0
- ck/circuit_compiler/interpret_compiler.py +2 -2
- ck/circuit_compiler/llvm_compiler.py +4 -4
- ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.c +1 -1
- ck/circuit_compiler/support/circuit_analyser/_circuit_analyser_cy.cp312-win_amd64.pyd +0 -0
- ck/circuit_compiler/support/input_vars.py +4 -4
- ck/circuit_compiler/support/llvm_ir_function.py +4 -4
- ck/dataset/__init__.py +1 -0
- ck/dataset/cross_table.py +334 -0
- ck/dataset/dataset.py +682 -0
- ck/dataset/dataset_builder.py +519 -0
- ck/dataset/dataset_compute.py +140 -0
- ck/dataset/dataset_from_crosstable.py +64 -0
- ck/dataset/dataset_from_csv.py +151 -0
- ck/dataset/sampled_dataset.py +96 -0
- ck/example/diamond_square.py +3 -1
- ck/example/triangle_square.py +3 -1
- ck/example/truss.py +3 -1
- ck/in_out/parse_net.py +21 -19
- ck/in_out/parser_utils.py +7 -3
- ck/learning/__init__.py +0 -0
- ck/learning/coalesce_cross_tables.py +403 -0
- ck/learning/model_from_cross_tables.py +296 -0
- ck/learning/parameters.py +117 -0
- ck/learning/train_generative_bn.py +198 -0
- ck/pgm.py +105 -92
- ck/pgm_circuit/marginals_program.py +5 -0
- ck/pgm_circuit/mpe_program.py +3 -4
- ck/pgm_circuit/pgm_circuit.py +27 -18
- ck/pgm_circuit/program_with_slotmap.py +27 -46
- ck/pgm_circuit/support/compile_circuit.py +2 -4
- ck/pgm_circuit/wmc_program.py +5 -0
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy.c +1 -1
- ck/pgm_compiler/support/circuit_table/_circuit_table_cy.cp312-win_amd64.pyd +0 -0
- ck/probability/cross_table_probability_space.py +53 -0
- ck/probability/divergence.py +226 -0
- ck/probability/empirical_probability_space.py +1 -0
- ck/probability/probability_space.py +53 -30
- ck/program/raw_program.py +23 -16
- ck/sampling/sampler_support.py +5 -6
- ck/utils/iter_extras.py +3 -2
- ck/utils/local_config.py +16 -8
- ck_demos/dataset/__init__.py +0 -0
- ck_demos/dataset/demo_dataset_builder.py +37 -0
- ck_demos/dataset/demo_dataset_from_sampler.py +18 -0
- ck_demos/learning/__init__.py +0 -0
- ck_demos/learning/demo_bayesian_network_from_cross_tables.py +70 -0
- ck_demos/learning/demo_simple_learning.py +55 -0
- ck_demos/sampling/demo_wmc_direct_sampler.py +2 -2
- {compiled_knowledge-4.0.0a24.dist-info → compiled_knowledge-4.1.0.dist-info}/METADATA +2 -1
- {compiled_knowledge-4.0.0a24.dist-info → compiled_knowledge-4.1.0.dist-info}/RECORD +58 -37
- {compiled_knowledge-4.0.0a24.dist-info → compiled_knowledge-4.1.0.dist-info}/WHEEL +0 -0
- {compiled_knowledge-4.0.0a24.dist-info → compiled_knowledge-4.1.0.dist-info}/licenses/LICENSE.txt +0 -0
- {compiled_knowledge-4.0.0a24.dist-info → compiled_knowledge-4.1.0.dist-info}/top_level.txt +0 -0
ck/pgm.py
CHANGED
|
@@ -15,33 +15,34 @@ from ck.utils.iter_extras import (
|
|
|
15
15
|
from ck.utils.np_extras import NDArrayFloat64, NDArrayUInt8
|
|
16
16
|
|
|
17
17
|
State: TypeAlias = Union[int, str, bool, float, None]
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"""
|
|
18
|
+
"""
|
|
19
|
+
The type for a possible state of a random variable.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
Instance: TypeAlias = Tuple[int, ...]
|
|
23
|
+
"""
|
|
24
|
+
An instance (of a sequence of random variables) is a tuple of integers
|
|
25
|
+
that are state indexes, co-indexed with a known sequence of random variables.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
Key: TypeAlias = Union[Sequence[int], int]
|
|
29
|
+
"""
|
|
30
|
+
A key identifies an instance, either as a sequence of integers or a
|
|
31
|
+
single integer. The integers are state indexes, co-indexed with a known
|
|
32
|
+
sequence of random variables. A single integer represents an instance with
|
|
33
|
+
one dimension.
|
|
34
|
+
"""
|
|
36
35
|
|
|
37
36
|
Shape: TypeAlias = Sequence[int]
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"""
|
|
37
|
+
"""
|
|
38
|
+
The type for the "shape" of a sequence of random variables.
|
|
39
|
+
That is, the shape of (rv1, rv2, rv3) is (len(rv1), len(rv2), len(rv3)).
|
|
40
|
+
"""
|
|
43
41
|
|
|
44
|
-
DEFAULT_CPT_TOLERANCE: float = 0.000001
|
|
42
|
+
DEFAULT_CPT_TOLERANCE: float = 0.000001
|
|
43
|
+
"""
|
|
44
|
+
A tolerance when checking CPT distributions sum to one (or zero).
|
|
45
|
+
"""
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
class PGM:
|
|
@@ -214,14 +215,17 @@ class PGM:
|
|
|
214
215
|
The returned random variable will have an `idx` equal to the value of
|
|
215
216
|
`self.number_of_rvs` just prior to adding the new random variable.
|
|
216
217
|
|
|
218
|
+
The states of the random variable can be specified either as an integer
|
|
219
|
+
representing the number of states, or as a sequence of state values. If a
|
|
220
|
+
single integer, `n`, is provided then the states will be: 0, 1, ..., n-1.
|
|
221
|
+
If a sequence of states are provided then the states must be unique.
|
|
222
|
+
|
|
217
223
|
Assumes:
|
|
218
224
|
Provided states contain no duplicates.
|
|
219
225
|
|
|
220
226
|
Args:
|
|
221
227
|
name: a name for the random variable.
|
|
222
|
-
states: either
|
|
223
|
-
single integer, `n`, is provided then the states will be 0, 1, ..., n-1.
|
|
224
|
-
If a sequence of states are provided then the states must be unique.
|
|
228
|
+
states: either the number of states or a sequence of state values.
|
|
225
229
|
|
|
226
230
|
Returns:
|
|
227
231
|
a RandomVariable object belonging to this PGM.
|
|
@@ -241,10 +245,11 @@ class PGM:
|
|
|
241
245
|
|
|
242
246
|
Assumes:
|
|
243
247
|
The given random variables all belong to this PGM.
|
|
248
|
+
|
|
244
249
|
The random variables contain no duplicates.
|
|
245
250
|
|
|
246
251
|
Args:
|
|
247
|
-
|
|
252
|
+
rvs: the random variables.
|
|
248
253
|
|
|
249
254
|
Returns:
|
|
250
255
|
a Factor object belonging to this PGM.
|
|
@@ -336,17 +341,18 @@ class PGM:
|
|
|
336
341
|
*input_rvs: RandomVariable
|
|
337
342
|
) -> Factor:
|
|
338
343
|
"""
|
|
339
|
-
Add a sparse 0/1 factor to this PGM representing
|
|
340
|
-
|
|
341
|
-
|
|
344
|
+
Add a sparse 0/1 factor to this PGM representing `result_rv == function(*rvs)`.
|
|
345
|
+
That is::
|
|
346
|
+
|
|
342
347
|
factor[result_s, *input_s] = 1, if result_s == function(*input_s);
|
|
343
348
|
= 0, otherwise.
|
|
349
|
+
|
|
344
350
|
Args:
|
|
345
351
|
function: a function from state indexes of the input random variables to a state index
|
|
346
352
|
of the result random variable. The function should take the same number of arguments
|
|
347
353
|
as `input_rvs` and return a state index for `result_rv`.
|
|
348
354
|
result_rv: the random variable defining result values.
|
|
349
|
-
|
|
355
|
+
input_rvs: the random variables defining input values.
|
|
350
356
|
|
|
351
357
|
Returns:
|
|
352
358
|
a Factor object belonging to this PGM, with a configured sparse potential function.
|
|
@@ -378,16 +384,17 @@ class PGM:
|
|
|
378
384
|
"""
|
|
379
385
|
Render indicators as a string.
|
|
380
386
|
|
|
381
|
-
For example
|
|
387
|
+
For example::
|
|
382
388
|
pgm = PGM()
|
|
383
389
|
a = pgm.new_rv('A', ('x', 'y', 'z'))
|
|
384
390
|
b = pgm.new_rv('B', (3, 5))
|
|
385
391
|
print(pgm.indicator_str(a[0], b[1], a[2]))
|
|
386
|
-
|
|
392
|
+
|
|
393
|
+
will print::
|
|
387
394
|
A=x, B=5, A=z
|
|
388
395
|
|
|
389
396
|
Args:
|
|
390
|
-
|
|
397
|
+
indicators: the indicators to render.
|
|
391
398
|
sep: the separator to use between the random variable and its state.
|
|
392
399
|
delim: the delimiter to used when rendering multiple indicators.
|
|
393
400
|
|
|
@@ -406,16 +413,17 @@ class PGM:
|
|
|
406
413
|
"""
|
|
407
414
|
Render indicators as a string, grouping indicators by random variable.
|
|
408
415
|
|
|
409
|
-
For example
|
|
416
|
+
For example::
|
|
410
417
|
pgm = PGM()
|
|
411
418
|
a = pgm.new_rv('A', ('x', 'y', 'z'))
|
|
412
419
|
b = pgm.new_rv('B', (3, 5))
|
|
413
420
|
print(pgm.condition_str(a[0], b[1], a[2]))
|
|
414
|
-
|
|
421
|
+
|
|
422
|
+
will print::
|
|
415
423
|
A in {x, z}, B=5
|
|
416
424
|
|
|
417
425
|
Args:
|
|
418
|
-
|
|
426
|
+
indicators: the indicators to render.
|
|
419
427
|
Return:
|
|
420
428
|
a string representation of the given indicators, as a condition.
|
|
421
429
|
"""
|
|
@@ -588,9 +596,11 @@ class PGM:
|
|
|
588
596
|
|
|
589
597
|
# Factors form a DAG
|
|
590
598
|
states: NDArrayUInt8 = np.zeros(self.number_of_factors, dtype=np.uint8)
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
599
|
+
if any(
|
|
600
|
+
self._has_cycle(factor, child_to_factor, states)
|
|
601
|
+
for factor in self._factors
|
|
602
|
+
):
|
|
603
|
+
return False
|
|
594
604
|
|
|
595
605
|
# All tests passed
|
|
596
606
|
return True
|
|
@@ -770,7 +780,7 @@ class PGM:
|
|
|
770
780
|
next_prefix: str = prefix + indent
|
|
771
781
|
next_next_prefix: str = next_prefix + indent
|
|
772
782
|
|
|
773
|
-
print(f'{prefix}PGM id={id(self)}
|
|
783
|
+
print(f'{prefix}PGM id={id(self)}')
|
|
774
784
|
self.dump_synopsis(prefix=next_prefix, precision=precision, max_state_digits=max_state_digits)
|
|
775
785
|
|
|
776
786
|
print(f'{prefix}random variables ({self.number_of_rvs})')
|
|
@@ -784,16 +794,16 @@ class PGM:
|
|
|
784
794
|
|
|
785
795
|
print(f'{prefix}factors ({self.number_of_factors})')
|
|
786
796
|
for factor in self.factors:
|
|
787
|
-
|
|
797
|
+
factor_rvs = ', '.join(repr(rv.name) for rv in factor.rvs)
|
|
788
798
|
if factor.is_zero:
|
|
789
|
-
function_ref = '<
|
|
799
|
+
function_ref = '<ZeroPotentialFunction>'
|
|
790
800
|
else:
|
|
791
801
|
function = factor.function
|
|
792
802
|
function_ref = f'{id(function)}: {function.__class__.__name__}'
|
|
793
803
|
|
|
794
|
-
print(f'{next_prefix}{factor.idx:>3} rvs={
|
|
804
|
+
print(f'{next_prefix}{factor.idx:>3} rvs=({factor_rvs}) function={function_ref}')
|
|
795
805
|
|
|
796
|
-
print(f'{prefix}functions ({self.
|
|
806
|
+
print(f'{prefix}functions, excluding ZeroPotentialFunction ({sum(1 for _ in self.non_zero_functions)})')
|
|
797
807
|
for function in sorted(self.non_zero_functions, key=lambda f: id(f)):
|
|
798
808
|
print(f'{next_prefix}{id(function):>13}: {function.__class__.__name__}')
|
|
799
809
|
function.dump(prefix=next_next_prefix, show_function_values=show_function_values, show_id_class=False)
|
|
@@ -930,9 +940,9 @@ class RandomVariable(Sequence[Indicator]):
|
|
|
930
940
|
in the random variable's PGM list of random variables.
|
|
931
941
|
|
|
932
942
|
A random variable behaves like a sequence of Indicators, where each indicator represents a random
|
|
933
|
-
variable being in a particular state. Specifically for a random variable rv, len(rv) is the
|
|
943
|
+
variable being in a particular state. Specifically for a random variable rv, `len(rv)` is the
|
|
934
944
|
number of states of the random variable and rv[i] is the Indicators representing that
|
|
935
|
-
rv is in the ith state. When sliced, the result is a tuple, i.e. rv[1:3] = (rv[1], rv[2])
|
|
945
|
+
rv is in the ith state. When sliced, the result is a tuple, i.e. `rv[1:3] = (rv[1], rv[2])`.
|
|
936
946
|
|
|
937
947
|
A RandomVariable has a name. This is for human convenience and has no functional purpose
|
|
938
948
|
within a PGM.
|
|
@@ -942,15 +952,18 @@ class RandomVariable(Sequence[Indicator]):
|
|
|
942
952
|
"""
|
|
943
953
|
Create a new random variable, in the given PGM.
|
|
944
954
|
|
|
955
|
+
The states of the random variable can be specified either as an integer
|
|
956
|
+
representing the number of states, or as a sequence of state values. If a
|
|
957
|
+
single integer, `n`, is provided then the states will be: 0, 1, ..., n-1.
|
|
958
|
+
If a sequence of states are provided then the states must be unique.
|
|
959
|
+
|
|
945
960
|
Assumes:
|
|
946
961
|
Provided states contain no duplicates.
|
|
947
962
|
|
|
948
963
|
Args:
|
|
949
964
|
pgm: the PGM that the random variable will belong to.
|
|
950
965
|
name: a name for the random variable.
|
|
951
|
-
states: either
|
|
952
|
-
single integer, `n`, is provided then the states will be 0, 1, ..., n-1.
|
|
953
|
-
If a sequence of states are provided then the states must be unique.
|
|
966
|
+
states: either the number of states or a sequence of state values.
|
|
954
967
|
"""
|
|
955
968
|
self._pgm: PGM = pgm
|
|
956
969
|
self._name: str = name
|
|
@@ -1212,15 +1225,14 @@ class RVMap(Sequence[RandomVariable]):
|
|
|
1212
1225
|
In addition to accessing a random variable by its index, an RVMap enables
|
|
1213
1226
|
access to the PGM random variable via the name of each random variable.
|
|
1214
1227
|
|
|
1215
|
-
For example, if `pgm.rvs[1]` is a random variable named `xray`, then
|
|
1216
|
-
```
|
|
1217
|
-
rvs = RVMap(pgm)
|
|
1228
|
+
For example, if `pgm.rvs[1]` is a random variable named `xray`, then::
|
|
1218
1229
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1230
|
+
rvs = RVMap(pgm)
|
|
1231
|
+
|
|
1232
|
+
# These all retrieve the same random variable object.
|
|
1233
|
+
xray = rvs[1]
|
|
1234
|
+
xray = rvs('xray')
|
|
1235
|
+
xray = rvs.xray
|
|
1224
1236
|
|
|
1225
1237
|
To use an RVMap on a PGM, the random variable names must be unique across the PGM.
|
|
1226
1238
|
"""
|
|
@@ -1527,7 +1539,7 @@ class Factor:
|
|
|
1527
1539
|
Set to the potential function to a new `ClausePotentialFunction` object.
|
|
1528
1540
|
|
|
1529
1541
|
Args:
|
|
1530
|
-
|
|
1542
|
+
key: defines the random variable states of the clause. The key is a sequence of
|
|
1531
1543
|
random variable state indexes, co-indexed with `Factor.rvs`.
|
|
1532
1544
|
|
|
1533
1545
|
Returns:
|
|
@@ -1556,7 +1568,7 @@ class Factor:
|
|
|
1556
1568
|
return self._potential_function
|
|
1557
1569
|
|
|
1558
1570
|
|
|
1559
|
-
@dataclass(frozen=True, eq=True)
|
|
1571
|
+
@dataclass(frozen=True, eq=True, slots=True)
|
|
1560
1572
|
class ParamId:
|
|
1561
1573
|
"""
|
|
1562
1574
|
A ParamId identifies a parameter of a potential function.
|
|
@@ -1863,7 +1875,7 @@ class PotentialFunction(ABC):
|
|
|
1863
1875
|
a hypothetical parameter index assuming that every valid key has a unique parameter
|
|
1864
1876
|
as per DensePotentialFunction.
|
|
1865
1877
|
"""
|
|
1866
|
-
return
|
|
1878
|
+
return natural_key_idx(self._shape, key)
|
|
1867
1879
|
|
|
1868
1880
|
def param_id(self, param_idx: int) -> ParamId:
|
|
1869
1881
|
"""
|
|
@@ -2021,7 +2033,7 @@ class ZeroPotentialFunction(PotentialFunction):
|
|
|
2021
2033
|
return 0
|
|
2022
2034
|
|
|
2023
2035
|
def param_idx(self, key: Key) -> int:
|
|
2024
|
-
return
|
|
2036
|
+
return natural_key_idx(self._shape, key)
|
|
2025
2037
|
|
|
2026
2038
|
def is_cpt(self, tolerance=DEFAULT_CPT_TOLERANCE) -> bool:
|
|
2027
2039
|
return True
|
|
@@ -2164,7 +2176,7 @@ class DensePotentialFunction(PotentialFunction):
|
|
|
2164
2176
|
"""
|
|
2165
2177
|
Set the values of the potential function using the given iterator.
|
|
2166
2178
|
|
|
2167
|
-
Mapping instances to
|
|
2179
|
+
Mapping instances to values is as follows:
|
|
2168
2180
|
Given Factor(rv1, rv2) where rv1 has 2 states, and rv2 has 3 states:
|
|
2169
2181
|
values[0] represents instance (0,0)
|
|
2170
2182
|
values[1] represents instance (0,1)
|
|
@@ -2209,7 +2221,7 @@ class DensePotentialFunction(PotentialFunction):
|
|
|
2209
2221
|
The order of values is the same as set_iter.
|
|
2210
2222
|
|
|
2211
2223
|
Args:
|
|
2212
|
-
|
|
2224
|
+
value: the values to use.
|
|
2213
2225
|
|
|
2214
2226
|
Returns:
|
|
2215
2227
|
self
|
|
@@ -2414,7 +2426,7 @@ class SparsePotentialFunction(PotentialFunction):
|
|
|
2414
2426
|
"""
|
|
2415
2427
|
Set the values of the potential function using the given iterator.
|
|
2416
2428
|
|
|
2417
|
-
Mapping instances to
|
|
2429
|
+
Mapping instances to values is as follows:
|
|
2418
2430
|
Given Factor(rv1, rv2) where rv1 has 2 states, and rv2 has 3 states:
|
|
2419
2431
|
values[0] represents instance (0,0)
|
|
2420
2432
|
values[1] represents instance (0,1)
|
|
@@ -2636,7 +2648,7 @@ class CompactPotentialFunction(PotentialFunction):
|
|
|
2636
2648
|
"""
|
|
2637
2649
|
Set the values of the potential function using the given iterator.
|
|
2638
2650
|
|
|
2639
|
-
Mapping instances to
|
|
2651
|
+
Mapping instances to `values` is as follows:
|
|
2640
2652
|
Given Factor(rv1, rv2) where rv1 has 2 states, and rv2 has 3 states:
|
|
2641
2653
|
values[0] represents instance (0,0)
|
|
2642
2654
|
values[1] represents instance (0,1)
|
|
@@ -2679,7 +2691,7 @@ class CompactPotentialFunction(PotentialFunction):
|
|
|
2679
2691
|
The order of values is the same as set_iter.
|
|
2680
2692
|
|
|
2681
2693
|
Args:
|
|
2682
|
-
|
|
2694
|
+
value: the values to use.
|
|
2683
2695
|
|
|
2684
2696
|
Returns:
|
|
2685
2697
|
self
|
|
@@ -3071,7 +3083,8 @@ class CPTPotentialFunction(PotentialFunction):
|
|
|
3071
3083
|
Calls self.set_cpd(parent_states, cpd) for each row (parent_states, cpd)
|
|
3072
3084
|
in rows. Any unmentioned parent states will have zero probabilities.
|
|
3073
3085
|
|
|
3074
|
-
Example usage, assuming three Boolean random variables
|
|
3086
|
+
Example usage, assuming three Boolean random variables::
|
|
3087
|
+
|
|
3075
3088
|
pgm.Factor(x, y, z).set_cpt().set(
|
|
3076
3089
|
# y z x[0] x[1]
|
|
3077
3090
|
((0, 0), (0.1, 0.9)),
|
|
@@ -3079,9 +3092,9 @@ class CPTPotentialFunction(PotentialFunction):
|
|
|
3079
3092
|
((1, 0), (0.1, 0.9)),
|
|
3080
3093
|
((1, 1), (0.1, 0.9))
|
|
3081
3094
|
)
|
|
3082
|
-
|
|
3095
|
+
|
|
3083
3096
|
Args:
|
|
3084
|
-
|
|
3097
|
+
rows: are tuples (key, cpd) used to set the potential function values.
|
|
3085
3098
|
|
|
3086
3099
|
Raises:
|
|
3087
3100
|
ValueError: if a CPD is not valid.
|
|
@@ -3105,7 +3118,7 @@ class CPTPotentialFunction(PotentialFunction):
|
|
|
3105
3118
|
Any list entry may be None, indicating 'guaranteed zero' for the associated parent states.
|
|
3106
3119
|
|
|
3107
3120
|
Args:
|
|
3108
|
-
|
|
3121
|
+
cpds: are the CPDs used to set the potential function values.
|
|
3109
3122
|
|
|
3110
3123
|
Raises:
|
|
3111
3124
|
ValueError: if a CPD is not valid.
|
|
@@ -3355,26 +3368,7 @@ def rv_instances_as_indicators(*rvs: RandomVariable, flip: bool = False) -> Iter
|
|
|
3355
3368
|
return _combos(rvs, flip=not flip)
|
|
3356
3369
|
|
|
3357
3370
|
|
|
3358
|
-
def
|
|
3359
|
-
"""
|
|
3360
|
-
Convert a key to an instance.
|
|
3361
|
-
|
|
3362
|
-
Args:
|
|
3363
|
-
key: a key into a state space.
|
|
3364
|
-
|
|
3365
|
-
Returns:
|
|
3366
|
-
A instance from the state space, as a tuple of state indexes, co-indexed with the given shape.
|
|
3367
|
-
|
|
3368
|
-
Assumes:
|
|
3369
|
-
The key is valid for the implied state space.
|
|
3370
|
-
"""
|
|
3371
|
-
if isinstance(key, int):
|
|
3372
|
-
return (key,)
|
|
3373
|
-
else:
|
|
3374
|
-
return tuple(key)
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
def _natural_key_idx(shape: Shape, key: Key) -> int:
|
|
3371
|
+
def natural_key_idx(shape: Shape, key: Key) -> int:
|
|
3378
3372
|
"""
|
|
3379
3373
|
What is the natural index of the given key, assuming the given shape.
|
|
3380
3374
|
|
|
@@ -3400,6 +3394,25 @@ def _natural_key_idx(shape: Shape, key: Key) -> int:
|
|
|
3400
3394
|
return result
|
|
3401
3395
|
|
|
3402
3396
|
|
|
3397
|
+
def _key_to_instance(key: Key) -> Instance:
|
|
3398
|
+
"""
|
|
3399
|
+
Convert a key to an instance.
|
|
3400
|
+
|
|
3401
|
+
Args:
|
|
3402
|
+
key: a key into a state space.
|
|
3403
|
+
|
|
3404
|
+
Returns:
|
|
3405
|
+
A instance from the state space, as a tuple of state indexes, co-indexed with the given shape.
|
|
3406
|
+
|
|
3407
|
+
Assumes:
|
|
3408
|
+
The key is valid for the implied state space.
|
|
3409
|
+
"""
|
|
3410
|
+
if isinstance(key, int):
|
|
3411
|
+
return (key,)
|
|
3412
|
+
else:
|
|
3413
|
+
return tuple(key)
|
|
3414
|
+
|
|
3415
|
+
|
|
3403
3416
|
def _zero_space(shape: Shape) -> int:
|
|
3404
3417
|
"""
|
|
3405
3418
|
Return the size of the zero space of the given shape. This is the number
|
|
@@ -308,6 +308,11 @@ class MarginalsProgram(ProgramWithSlotmap, ProbabilitySpace):
|
|
|
308
308
|
The sampler will yield state lists, where the state
|
|
309
309
|
values are co-indexed with rvs, or self.rvs if rvs is None.
|
|
310
310
|
|
|
311
|
+
For more information about this sampler, see the publication:
|
|
312
|
+
Suresh, S., Drake, B. (2025). Sampling of Large Probabilistic Graphical Models
|
|
313
|
+
Using Arithmetic Circuits. AI 2024: Advances in Artificial Intelligence. AI 2024.
|
|
314
|
+
Lecture Notes in Computer Science, vol 15443. https://doi.org/10.1007/978-981-96-0351-0_13.
|
|
315
|
+
|
|
311
316
|
Args:
|
|
312
317
|
rvs: the list of random variables to sample; the
|
|
313
318
|
yielded state vectors are co-indexed with rvs; if None,
|
ck/pgm_circuit/mpe_program.py
CHANGED
|
@@ -228,10 +228,9 @@ class MPEProgram(ProgramWithSlotmap):
|
|
|
228
228
|
class MPEResult:
|
|
229
229
|
"""
|
|
230
230
|
An MPE result is the result of MPE inference.
|
|
231
|
-
|
|
232
|
-
Fields:
|
|
233
|
-
wmc: the weighted model count value of the MPE solution.
|
|
234
|
-
mpe: The MPE solution instance. If there are ties then this will just be once instance.
|
|
235
231
|
"""
|
|
236
232
|
wmc: float
|
|
233
|
+
"""the weighted model count value of the MPE solution."""
|
|
234
|
+
|
|
237
235
|
mpe: Instance
|
|
236
|
+
"""the MPE solution instance. If there are ties then this will just be once instance."""
|
ck/pgm_circuit/pgm_circuit.py
CHANGED
|
@@ -16,33 +16,42 @@ class PGMCircuit:
|
|
|
16
16
|
holds the values of the parameters. Specifically, given parameter id `param_id`, then
|
|
17
17
|
`parameter_values[slot_map[param_id] - number_of_indicators]` is the value of the
|
|
18
18
|
identified parameter as it was in the PGM.
|
|
19
|
-
|
|
20
|
-
Fields:
|
|
21
|
-
rvs: holds the random variables from the PGM as it was compiled, in order.
|
|
22
|
-
|
|
23
|
-
conditions: any conditions on `rvs` that were compiled into the circuit.
|
|
24
|
-
|
|
25
|
-
number_of_indicators: is the number of indicators in `rvs` which is
|
|
26
|
-
`sum(len(rv) for rv in rvs`. Specifically, `circuit.vars[i]` is the circuit variable
|
|
27
|
-
corresponding to the ith indicator, where `circuit` is `circuit_top.circuit` and
|
|
28
|
-
indicators are ordered as per `rvs`.
|
|
29
|
-
|
|
30
|
-
number_of_parameters: is the number of parameters from the PGM that are
|
|
31
|
-
represented as circuit variables. This may be zero if parameters from the PGM
|
|
32
|
-
were compiled as constants.
|
|
33
|
-
|
|
34
|
-
slot_map[x]: gives the index of the circuit variable corresponding to x,
|
|
35
|
-
where x is either a random variable indicator (Indicator) or a parameter id (ParamId).
|
|
36
|
-
|
|
37
19
|
"""
|
|
38
20
|
|
|
39
21
|
rvs: Sequence[RandomVariable]
|
|
22
|
+
"""holds the random variables from the PGM as it was compiled, in order."""
|
|
23
|
+
|
|
40
24
|
conditions: Sequence[Indicator]
|
|
25
|
+
"""any conditions on `rvs` that were compiled into the circuit."""
|
|
26
|
+
|
|
41
27
|
circuit_top: CircuitNode
|
|
28
|
+
"""the top circuit node defining the network function."""
|
|
29
|
+
|
|
42
30
|
number_of_indicators: int
|
|
31
|
+
"""
|
|
32
|
+
the number of indicators in `rvs` which is
|
|
33
|
+
`sum(len(rv) for rv in rvs`. Specifically, `circuit.vars[i]` is the circuit variable
|
|
34
|
+
corresponding to the ith indicator, where `circuit` is `circuit_top.circuit` and
|
|
35
|
+
indicators are ordered as per `rvs`.
|
|
36
|
+
"""
|
|
37
|
+
|
|
43
38
|
number_of_parameters: int
|
|
39
|
+
"""
|
|
40
|
+
the number of parameters from the PGM that are
|
|
41
|
+
represented as circuit variables. This may be zero if parameters from the PGM
|
|
42
|
+
were compiled as constants.
|
|
43
|
+
"""
|
|
44
|
+
|
|
44
45
|
slot_map: SlotMap
|
|
46
|
+
"""
|
|
47
|
+
gives the index of the circuit variable corresponding to x,
|
|
48
|
+
where x is either a random variable indicator (Indicator) or a parameter id (ParamId).
|
|
49
|
+
"""
|
|
50
|
+
|
|
45
51
|
parameter_values: NDArray
|
|
52
|
+
"""
|
|
53
|
+
parameter values, co-indexed with the circuit variables, counting beyond `number_of_indicators`.
|
|
54
|
+
"""
|
|
46
55
|
|
|
47
56
|
def dump(self, *, prefix: str = '', indent: str = ' ') -> None:
|
|
48
57
|
"""
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from typing import Tuple, Sequence, Dict
|
|
1
|
+
from typing import Tuple, Sequence, Dict
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from ck.pgm import RandomVariable, Indicator, ParamId
|
|
4
6
|
from ck.pgm_circuit.slot_map import SlotMap, SlotKey
|
|
5
7
|
from ck.probability.probability_space import Condition, check_condition
|
|
6
8
|
from ck.program.program_buffer import ProgramBuffer
|
|
@@ -69,40 +71,6 @@ class ProgramWithSlotmap:
|
|
|
69
71
|
def slot_map(self) -> SlotMap:
|
|
70
72
|
return self._slot_map
|
|
71
73
|
|
|
72
|
-
def instances(self, flip: bool = False) -> Iterable[Instance]:
|
|
73
|
-
"""
|
|
74
|
-
Enumerate instances of the random variables.
|
|
75
|
-
|
|
76
|
-
Each instance is a tuples of state indexes, co-indexed with the given random variables.
|
|
77
|
-
|
|
78
|
-
The order is the natural index order (i.e., last random variable changing most quickly).
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
flip: if true, then first random variable changes most quickly.
|
|
82
|
-
|
|
83
|
-
Returns:
|
|
84
|
-
an iteration over tuples, each tuple holds state indexes
|
|
85
|
-
co-indexed with the given random variables.
|
|
86
|
-
"""
|
|
87
|
-
return rv_instances(*self._rvs, flip=flip)
|
|
88
|
-
|
|
89
|
-
def instances_as_indicators(self, flip: bool = False) -> Iterable[Sequence[Indicator]]:
|
|
90
|
-
"""
|
|
91
|
-
Enumerate instances of the random variables.
|
|
92
|
-
|
|
93
|
-
Each instance is a tuples of indicators, co-indexed with the given random variables.
|
|
94
|
-
|
|
95
|
-
The order is the natural index order (i.e., last random variable changing most quickly).
|
|
96
|
-
|
|
97
|
-
Args:
|
|
98
|
-
flip: if true, then first random variable changes most quickly.
|
|
99
|
-
|
|
100
|
-
Returns:
|
|
101
|
-
an iteration over tuples, each tuples holds random variable indicators
|
|
102
|
-
co-indexed with the given random variables.
|
|
103
|
-
"""
|
|
104
|
-
return rv_instances_as_indicators(*self._rvs, flip=flip)
|
|
105
|
-
|
|
106
74
|
def compute(self) -> NDArrayNumeric:
|
|
107
75
|
"""
|
|
108
76
|
Execute the program to compute and return the result. As per `ProgramBuffer.compute`.
|
|
@@ -114,7 +82,10 @@ class ProgramWithSlotmap:
|
|
|
114
82
|
|
|
115
83
|
def compute_conditioned(self, *condition: Condition) -> NDArrayNumeric:
|
|
116
84
|
"""
|
|
117
|
-
|
|
85
|
+
Compute the program value, after setting the given condition.
|
|
86
|
+
|
|
87
|
+
Equivalent to::
|
|
88
|
+
|
|
118
89
|
self.set_condition(*condition)
|
|
119
90
|
return self.compute()
|
|
120
91
|
"""
|
|
@@ -143,29 +114,36 @@ class ProgramWithSlotmap:
|
|
|
143
114
|
"""
|
|
144
115
|
return self._program_buffer.vars
|
|
145
116
|
|
|
146
|
-
def __setitem__(self, item: int | slice | SlotKey |
|
|
117
|
+
def __setitem__(self, item: int | slice | SlotKey | RandomVariable, value: float) -> None:
|
|
147
118
|
"""
|
|
148
|
-
Set
|
|
119
|
+
Set input slot value/s.
|
|
149
120
|
"""
|
|
150
121
|
if isinstance(item, (int, slice)):
|
|
151
122
|
self._program_buffer[item] = value
|
|
152
123
|
elif isinstance(item, (Indicator, ParamId)):
|
|
153
124
|
self._program_buffer[self._slot_map[item]] = value
|
|
125
|
+
elif isinstance(item, RandomVariable):
|
|
126
|
+
for ind in item:
|
|
127
|
+
self._program_buffer[self._slot_map[ind]] = value
|
|
154
128
|
else:
|
|
155
|
-
|
|
156
|
-
for i in item:
|
|
157
|
-
self[i] = value
|
|
129
|
+
raise IndexError(f'unknown index type: {type(item)}')
|
|
158
130
|
|
|
159
|
-
def __getitem__(self, item: int | slice | SlotKey) -> NDArrayNumeric:
|
|
131
|
+
def __getitem__(self, item: int | slice | SlotKey | RandomVariable) -> NDArrayNumeric:
|
|
160
132
|
"""
|
|
161
|
-
Get
|
|
133
|
+
Get input slot value/s.
|
|
162
134
|
"""
|
|
163
135
|
if isinstance(item, (int, slice)):
|
|
164
136
|
return self._program_buffer[item]
|
|
165
137
|
elif isinstance(item, (Indicator, ParamId)):
|
|
166
138
|
return self._program_buffer[self._slot_map[item]]
|
|
139
|
+
elif isinstance(item, RandomVariable):
|
|
140
|
+
return np.fromiter(
|
|
141
|
+
(self._program_buffer[self._slot_map[ind]] for ind in item),
|
|
142
|
+
dtype=self._program_buffer.dtype,
|
|
143
|
+
count=len(item)
|
|
144
|
+
)
|
|
167
145
|
else:
|
|
168
|
-
raise IndexError('unknown index type')
|
|
146
|
+
raise IndexError(f'unknown index type: {type(item)}')
|
|
169
147
|
|
|
170
148
|
def set_condition(self, *condition: Condition) -> None:
|
|
171
149
|
"""
|
|
@@ -208,7 +186,10 @@ class ProgramWithSlotmap:
|
|
|
208
186
|
|
|
209
187
|
Args:
|
|
210
188
|
rv: a random variable whose indicators are in the slot map.
|
|
211
|
-
values: list of values
|
|
189
|
+
values: list of values
|
|
190
|
+
|
|
191
|
+
Assumes:
|
|
192
|
+
len(values) == len(rv).
|
|
212
193
|
"""
|
|
213
194
|
for i in range(len(rv)):
|
|
214
195
|
self[rv[i]] = values[i]
|
|
@@ -30,11 +30,9 @@ def compile_results(
|
|
|
30
30
|
a compiled RawProgram.
|
|
31
31
|
"""
|
|
32
32
|
circuit: Circuit = pgm_circuit.circuit_top.circuit
|
|
33
|
-
if const_parameters:
|
|
34
|
-
parameter_values = pgm_circuit.parameter_values
|
|
35
|
-
number_of_indicators = pgm_circuit.number_of_indicators
|
|
33
|
+
if const_parameters and len(pgm_circuit.parameter_values) > 0:
|
|
36
34
|
with TmpConst(circuit) as tmp:
|
|
37
|
-
for slot, value in enumerate(parameter_values, start=number_of_indicators):
|
|
35
|
+
for slot, value in enumerate(pgm_circuit.parameter_values, start=pgm_circuit.number_of_indicators):
|
|
38
36
|
tmp.set_const(slot, value)
|
|
39
37
|
raw_program: RawProgram = compiler(*results, circuit=circuit)
|
|
40
38
|
else:
|
ck/pgm_circuit/wmc_program.py
CHANGED
|
@@ -132,6 +132,11 @@ class WMCProgram(ProgramWithSlotmap, ProbabilitySpace):
|
|
|
132
132
|
* calls rand.random() once and rand.randrange(...) n times,
|
|
133
133
|
* calls self.program().compute_result() at least once and <= 1 + m.
|
|
134
134
|
|
|
135
|
+
For more information about this sampler, see the publication:
|
|
136
|
+
Suresh, S., Drake, B. (2025). Sampling of Large Probabilistic Graphical Models
|
|
137
|
+
Using Arithmetic Circuits. AI 2024: Advances in Artificial Intelligence. AI 2024.
|
|
138
|
+
Lecture Notes in Computer Science, vol 15443. https://doi.org/10.1007/978-981-96-0351-0_13.
|
|
139
|
+
|
|
135
140
|
Args:
|
|
136
141
|
rvs: the list of random variables to sample; the
|
|
137
142
|
yielded state vectors are co-indexed with rvs; if None,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"/O2"
|
|
14
14
|
],
|
|
15
15
|
"include_dirs": [
|
|
16
|
-
"C:\\Users\\runneradmin\\AppData\\Local\\Temp\\build-env-
|
|
16
|
+
"C:\\Users\\runneradmin\\AppData\\Local\\Temp\\build-env-gp1o6j1g\\Lib\\site-packages\\numpy\\_core\\include"
|
|
17
17
|
],
|
|
18
18
|
"name": "ck.pgm_compiler.support.circuit_table._circuit_table_cy",
|
|
19
19
|
"sources": [
|
|
Binary file
|