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.
- ck/__init__.py +0 -0
- ck/circuit/__init__.py +13 -0
- ck/circuit/circuit.c +38749 -0
- ck/circuit/circuit.cpython-313-darwin.so +0 -0
- ck/circuit/circuit_py.py +807 -0
- ck/circuit/tmp_const.py +74 -0
- ck/circuit_compiler/__init__.py +2 -0
- ck/circuit_compiler/circuit_compiler.py +26 -0
- ck/circuit_compiler/cython_vm_compiler/__init__.py +1 -0
- ck/circuit_compiler/cython_vm_compiler/_compiler.c +17373 -0
- ck/circuit_compiler/cython_vm_compiler/_compiler.cpython-313-darwin.so +0 -0
- ck/circuit_compiler/cython_vm_compiler/cython_vm_compiler.py +96 -0
- ck/circuit_compiler/interpret_compiler.py +223 -0
- ck/circuit_compiler/llvm_compiler.py +388 -0
- ck/circuit_compiler/llvm_vm_compiler.py +546 -0
- ck/circuit_compiler/named_circuit_compilers.py +57 -0
- ck/circuit_compiler/support/__init__.py +0 -0
- ck/circuit_compiler/support/circuit_analyser.py +81 -0
- ck/circuit_compiler/support/input_vars.py +148 -0
- ck/circuit_compiler/support/llvm_ir_function.py +234 -0
- ck/example/__init__.py +53 -0
- ck/example/alarm.py +366 -0
- ck/example/asia.py +28 -0
- ck/example/binary_clique.py +32 -0
- ck/example/bow_tie.py +33 -0
- ck/example/cancer.py +37 -0
- ck/example/chain.py +38 -0
- ck/example/child.py +199 -0
- ck/example/clique.py +33 -0
- ck/example/cnf_pgm.py +39 -0
- ck/example/diamond_square.py +68 -0
- ck/example/earthquake.py +36 -0
- ck/example/empty.py +10 -0
- ck/example/hailfinder.py +539 -0
- ck/example/hepar2.py +628 -0
- ck/example/insurance.py +504 -0
- ck/example/loop.py +40 -0
- ck/example/mildew.py +38161 -0
- ck/example/munin.py +22982 -0
- ck/example/pathfinder.py +53674 -0
- ck/example/rain.py +39 -0
- ck/example/rectangle.py +161 -0
- ck/example/run.py +30 -0
- ck/example/sachs.py +129 -0
- ck/example/sprinkler.py +30 -0
- ck/example/star.py +44 -0
- ck/example/stress.py +64 -0
- ck/example/student.py +43 -0
- ck/example/survey.py +46 -0
- ck/example/triangle_square.py +54 -0
- ck/example/truss.py +49 -0
- ck/in_out/__init__.py +3 -0
- ck/in_out/parse_ace_lmap.py +216 -0
- ck/in_out/parse_ace_nnf.py +288 -0
- ck/in_out/parse_net.py +480 -0
- ck/in_out/parser_utils.py +185 -0
- ck/in_out/pgm_pickle.py +42 -0
- ck/in_out/pgm_python.py +268 -0
- ck/in_out/render_bugs.py +111 -0
- ck/in_out/render_net.py +177 -0
- ck/in_out/render_pomegranate.py +184 -0
- ck/pgm.py +3494 -0
- ck/pgm_circuit/__init__.py +1 -0
- ck/pgm_circuit/marginals_program.py +352 -0
- ck/pgm_circuit/mpe_program.py +237 -0
- ck/pgm_circuit/pgm_circuit.py +75 -0
- ck/pgm_circuit/program_with_slotmap.py +234 -0
- ck/pgm_circuit/slot_map.py +35 -0
- ck/pgm_circuit/support/__init__.py +0 -0
- ck/pgm_circuit/support/compile_circuit.py +83 -0
- ck/pgm_circuit/target_marginals_program.py +103 -0
- ck/pgm_circuit/wmc_program.py +323 -0
- ck/pgm_compiler/__init__.py +2 -0
- ck/pgm_compiler/ace/__init__.py +1 -0
- ck/pgm_compiler/ace/ace.py +252 -0
- ck/pgm_compiler/factor_elimination.py +383 -0
- ck/pgm_compiler/named_pgm_compilers.py +63 -0
- ck/pgm_compiler/pgm_compiler.py +19 -0
- ck/pgm_compiler/recursive_conditioning.py +226 -0
- ck/pgm_compiler/support/__init__.py +0 -0
- ck/pgm_compiler/support/circuit_table/__init__.py +9 -0
- ck/pgm_compiler/support/circuit_table/circuit_table.c +16042 -0
- ck/pgm_compiler/support/circuit_table/circuit_table.cpython-313-darwin.so +0 -0
- ck/pgm_compiler/support/circuit_table/circuit_table_py.py +269 -0
- ck/pgm_compiler/support/clusters.py +556 -0
- ck/pgm_compiler/support/factor_tables.py +398 -0
- ck/pgm_compiler/support/join_tree.py +275 -0
- ck/pgm_compiler/support/named_compiler_maker.py +33 -0
- ck/pgm_compiler/variable_elimination.py +89 -0
- ck/probability/__init__.py +0 -0
- ck/probability/empirical_probability_space.py +47 -0
- ck/probability/probability_space.py +568 -0
- ck/program/__init__.py +3 -0
- ck/program/program.py +129 -0
- ck/program/program_buffer.py +180 -0
- ck/program/raw_program.py +61 -0
- ck/sampling/__init__.py +0 -0
- ck/sampling/forward_sampler.py +211 -0
- ck/sampling/marginals_direct_sampler.py +113 -0
- ck/sampling/sampler.py +62 -0
- ck/sampling/sampler_support.py +232 -0
- ck/sampling/uniform_sampler.py +66 -0
- ck/sampling/wmc_direct_sampler.py +169 -0
- ck/sampling/wmc_gibbs_sampler.py +147 -0
- ck/sampling/wmc_metropolis_sampler.py +159 -0
- ck/sampling/wmc_rejection_sampler.py +113 -0
- ck/utils/__init__.py +0 -0
- ck/utils/iter_extras.py +153 -0
- ck/utils/map_list.py +128 -0
- ck/utils/map_set.py +128 -0
- ck/utils/np_extras.py +51 -0
- ck/utils/random_extras.py +64 -0
- ck/utils/tmp_dir.py +94 -0
- ck_demos/__init__.py +0 -0
- ck_demos/ace/__init__.py +0 -0
- ck_demos/ace/copy_ace_to_ck.py +15 -0
- ck_demos/ace/demo_ace.py +44 -0
- ck_demos/all_demos.py +88 -0
- ck_demos/circuit/__init__.py +0 -0
- ck_demos/circuit/demo_circuit_dump.py +22 -0
- ck_demos/circuit/demo_derivatives.py +43 -0
- ck_demos/circuit_compiler/__init__.py +0 -0
- ck_demos/circuit_compiler/compare_circuit_compilers.py +32 -0
- ck_demos/circuit_compiler/show_llvm_program.py +26 -0
- ck_demos/pgm/__init__.py +0 -0
- ck_demos/pgm/demo_pgm_dump.py +18 -0
- ck_demos/pgm/demo_pgm_dump_stress.py +18 -0
- ck_demos/pgm/demo_pgm_string_rendering.py +15 -0
- ck_demos/pgm/show_examples.py +25 -0
- ck_demos/pgm_compiler/__init__.py +0 -0
- ck_demos/pgm_compiler/compare_pgm_compilers.py +50 -0
- ck_demos/pgm_compiler/demo_compiler_dump.py +50 -0
- ck_demos/pgm_compiler/demo_factor_elimination.py +47 -0
- ck_demos/pgm_compiler/demo_join_tree.py +25 -0
- ck_demos/pgm_compiler/demo_marginals_program.py +53 -0
- ck_demos/pgm_compiler/demo_mpe_program.py +55 -0
- ck_demos/pgm_compiler/demo_pgm_compiler.py +38 -0
- ck_demos/pgm_compiler/demo_recursive_conditioning.py +33 -0
- ck_demos/pgm_compiler/demo_variable_elimination.py +33 -0
- ck_demos/pgm_compiler/demo_wmc_program.py +29 -0
- ck_demos/pgm_inference/__init__.py +0 -0
- ck_demos/pgm_inference/demo_inferencing_basic.py +188 -0
- ck_demos/pgm_inference/demo_inferencing_mpe_cancer.py +45 -0
- ck_demos/pgm_inference/demo_inferencing_wmc_and_mpe_sprinkler.py +154 -0
- ck_demos/pgm_inference/demo_inferencing_wmc_student.py +110 -0
- ck_demos/programs/__init__.py +0 -0
- ck_demos/programs/demo_program_buffer.py +24 -0
- ck_demos/programs/demo_program_multi.py +24 -0
- ck_demos/programs/demo_program_none.py +19 -0
- ck_demos/programs/demo_program_single.py +23 -0
- ck_demos/programs/demo_raw_program_interpreted.py +21 -0
- ck_demos/programs/demo_raw_program_llvm.py +21 -0
- ck_demos/sampling/__init__.py +0 -0
- ck_demos/sampling/check_sampler.py +71 -0
- ck_demos/sampling/demo_marginal_direct_sampler.py +40 -0
- ck_demos/sampling/demo_uniform_sampler.py +38 -0
- ck_demos/sampling/demo_wmc_direct_sampler.py +40 -0
- ck_demos/utils/__init__.py +0 -0
- ck_demos/utils/compare.py +88 -0
- ck_demos/utils/convert_network.py +45 -0
- ck_demos/utils/sample_model.py +216 -0
- ck_demos/utils/stop_watch.py +384 -0
- compiled_knowledge-4.0.0a5.dist-info/METADATA +50 -0
- compiled_knowledge-4.0.0a5.dist-info/RECORD +167 -0
- compiled_knowledge-4.0.0a5.dist-info/WHEEL +5 -0
- compiled_knowledge-4.0.0a5.dist-info/licenses/LICENSE.txt +21 -0
- compiled_knowledge-4.0.0a5.dist-info/top_level.txt +2 -0
ck/utils/np_extras.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Type used by numpy and ctypes for data type definition
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
# A numpy/ctypes data type.
|
|
6
|
+
DType = np.typing.DTypeLike
|
|
7
|
+
|
|
8
|
+
# A numpy data type for holding state indexes.
|
|
9
|
+
DTypeStates = np.dtypes.UInt8DType | np.dtypes.UInt16DType | np.dtypes.UInt32DType | np.dtypes.UInt64DType
|
|
10
|
+
|
|
11
|
+
DTypeNumeric = (
|
|
12
|
+
np.dtypes.Float64DType | np.dtypes.Float32DType
|
|
13
|
+
| np.dtypes.Int8DType | np.dtypes.Int16DType | np.dtypes.Int32DType | np.dtypes.Int64DType
|
|
14
|
+
| np.dtypes.UInt8DType | np.dtypes.UInt16DType | np.dtypes.UInt32DType | np.dtypes.UInt64DType
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# A numpy array data type.
|
|
18
|
+
NDArray = np.typing.NDArray
|
|
19
|
+
|
|
20
|
+
NDArrayUInt8 = NDArray[np.dtypes.UInt8DType]
|
|
21
|
+
NDArrayUInt16 = NDArray[np.dtypes.UInt16DType]
|
|
22
|
+
NDArrayUInt32 = NDArray[np.dtypes.UInt32DType]
|
|
23
|
+
NDArrayUInt64 = NDArray[np.dtypes.UInt64DType]
|
|
24
|
+
|
|
25
|
+
NDArrayFloat64 = NDArray[np.dtypes.Float64DType]
|
|
26
|
+
|
|
27
|
+
NDArrayStates = NDArray[DTypeStates]
|
|
28
|
+
NDArrayNumeric = NDArray[DTypeNumeric]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Constants for maximum number of states.
|
|
32
|
+
_MAX_STATES_8: int = 2 ** 8 - 1
|
|
33
|
+
_MAX_STATES_16: int = 2 ** 16 - 1
|
|
34
|
+
_MAX_STATES_32: int = 2 ** 32 - 1
|
|
35
|
+
_MAX_STATES_64: int = 2 ** 64 - 1
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def dtype_for_number_of_states(number_of_states: int) -> DTypeStates:
|
|
39
|
+
"""
|
|
40
|
+
Infer the numpy dtype required to store any state index of the given PGM.
|
|
41
|
+
"""
|
|
42
|
+
# Infer the needed size of
|
|
43
|
+
if number_of_states <= _MAX_STATES_8:
|
|
44
|
+
return np.uint8
|
|
45
|
+
if number_of_states <= _MAX_STATES_16:
|
|
46
|
+
return np.uint16
|
|
47
|
+
if number_of_states <= _MAX_STATES_32:
|
|
48
|
+
return np.uint32
|
|
49
|
+
if number_of_states <= _MAX_STATES_64:
|
|
50
|
+
return np.uint64
|
|
51
|
+
raise ValueError(f'cannot determine dtype for the given number of states: {number_of_states!r}')
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A module with extra randomisation functions.
|
|
3
|
+
"""
|
|
4
|
+
import random
|
|
5
|
+
from typing import Protocol, Sequence, Tuple, Any, List
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Random(Protocol):
|
|
9
|
+
"""
|
|
10
|
+
A minimum protocol for a random number generator as used by CK.
|
|
11
|
+
The usual `random` package implements this protocol.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def random(self) -> float:
|
|
15
|
+
"""
|
|
16
|
+
Returns a random float in the interval [0, 1), includes 0, excludes 1.
|
|
17
|
+
"""
|
|
18
|
+
...
|
|
19
|
+
|
|
20
|
+
def randrange(self, a: int, b: int) -> int:
|
|
21
|
+
"""
|
|
22
|
+
Returns a random integer in interval [a, b), includes `a`, excludes `b`.
|
|
23
|
+
"""
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def random_pair(size: int, rand: Random = random) -> Tuple[int, int]:
|
|
28
|
+
"""
|
|
29
|
+
Return a random pair (i, j) where:
|
|
30
|
+
0 <= i < size,
|
|
31
|
+
0 <= j < size,
|
|
32
|
+
i != j.
|
|
33
|
+
"""
|
|
34
|
+
i = rand.randrange(0, size)
|
|
35
|
+
j = (i + rand.randrange(1, size)) % size
|
|
36
|
+
return i, j
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def random_permute(items: List[Any], rand: Random = random) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Randomly permute the given items.
|
|
42
|
+
For a list of length `n`, this method calls rand.randrange(...) `n - 1` times.
|
|
43
|
+
|
|
44
|
+
There is a numpy method to do this, but it uses its own random number generator.
|
|
45
|
+
"""
|
|
46
|
+
for i in range(len(items) - 1, 0, -1): # i = n - 1 down to 1
|
|
47
|
+
j = rand.randrange(0, i + 1) # 0 <= j <= i
|
|
48
|
+
items[i], items[j] = items[j], items[i] # exchange
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def random_permutation(size: int, rand: Random = random) -> Sequence[int]:
|
|
52
|
+
"""
|
|
53
|
+
Return a random permutation of the given size.
|
|
54
|
+
|
|
55
|
+
The returned list contains each integer 0 to size - 1
|
|
56
|
+
in a random order.
|
|
57
|
+
|
|
58
|
+
This method calls rand.randrange(...) 'size' times.
|
|
59
|
+
|
|
60
|
+
There is a numpy method to do this, but it uses its own random number generator.
|
|
61
|
+
"""
|
|
62
|
+
result = list(range(size))
|
|
63
|
+
random_permute(result, rand)
|
|
64
|
+
return result
|
ck/utils/tmp_dir.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is a module for creating a temporary directory and making it the working directory.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
from tmp_dir import tmp_dir
|
|
6
|
+
|
|
7
|
+
with tmp_dir():
|
|
8
|
+
# do some stuff
|
|
9
|
+
"""
|
|
10
|
+
import os as _os
|
|
11
|
+
import shutil as _shutil
|
|
12
|
+
import tempfile as _tempfile
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Union
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class tmp_dir:
|
|
18
|
+
__slots__ = ('_new_dir', '_old_cwd', '_chdir', '_delete_when_done')
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
name: Union[Path, str, None] = None,
|
|
23
|
+
chdir: bool = True,
|
|
24
|
+
delete_when_done: bool = True
|
|
25
|
+
):
|
|
26
|
+
"""
|
|
27
|
+
Create a temporary directory, make it the working
|
|
28
|
+
directory (unless chdir is False), clean up when done
|
|
29
|
+
(unless delete_when_done is False).
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
name: the name of the temporary directory. If name
|
|
33
|
+
is None, then `tempfile.mkdtemp()` is used.
|
|
34
|
+
chdir: if True, then chdir to the temporary directory.
|
|
35
|
+
delete_when_done: if True, then the temporary directory is
|
|
36
|
+
deleted when done.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
if name is None:
|
|
40
|
+
self._new_dir = Path(_tempfile.mkdtemp())
|
|
41
|
+
else:
|
|
42
|
+
self._new_dir = Path(name).absolute()
|
|
43
|
+
self._new_dir.mkdir(exist_ok=True, parents=True)
|
|
44
|
+
|
|
45
|
+
self._old_cwd = Path.cwd()
|
|
46
|
+
self._chdir = chdir
|
|
47
|
+
if chdir:
|
|
48
|
+
_os.chdir(self._new_dir)
|
|
49
|
+
self._delete_when_done = delete_when_done
|
|
50
|
+
|
|
51
|
+
def __del__(self):
|
|
52
|
+
"""
|
|
53
|
+
Calls self.done().
|
|
54
|
+
"""
|
|
55
|
+
self.done()
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def path(self) -> Path:
|
|
59
|
+
"""
|
|
60
|
+
What is the path to the temporary directory.
|
|
61
|
+
"""
|
|
62
|
+
return self._new_dir
|
|
63
|
+
|
|
64
|
+
def __truediv__(self, arg) -> Path:
|
|
65
|
+
"""
|
|
66
|
+
Append a path element, just like a Path object.
|
|
67
|
+
"""
|
|
68
|
+
return self.path / arg
|
|
69
|
+
|
|
70
|
+
def done(self) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Change back to the old working directory and delete the temporary
|
|
73
|
+
directory, along with all its contents.
|
|
74
|
+
|
|
75
|
+
Subsequent calls to done() take no further action.
|
|
76
|
+
"""
|
|
77
|
+
if self._new_dir is not None:
|
|
78
|
+
if self._chdir:
|
|
79
|
+
_os.chdir(self._old_cwd)
|
|
80
|
+
if self._delete_when_done:
|
|
81
|
+
_shutil.rmtree(self._new_dir)
|
|
82
|
+
self._old_cwd = None
|
|
83
|
+
self._new_dir = None
|
|
84
|
+
|
|
85
|
+
def __enter__(self):
|
|
86
|
+
# nothing to do - already created at __init__
|
|
87
|
+
return self
|
|
88
|
+
|
|
89
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
90
|
+
self.done()
|
|
91
|
+
return exc_val is None
|
|
92
|
+
|
|
93
|
+
def __str__(self):
|
|
94
|
+
return str(self._new_dir)
|
ck_demos/__init__.py
ADDED
|
File without changes
|
ck_demos/ace/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is an example Python script for copying Ace to CK.
|
|
3
|
+
"""
|
|
4
|
+
from ck.pgm_compiler.ace import copy_ace_to_default_location
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
SOURCE_ACE: str = r'C:\Research\Ace\ace_v3.0_windows'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
copy_ace_to_default_location(SOURCE_ACE)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
main()
|
ck_demos/ace/demo_ace.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from ck import example
|
|
2
|
+
from ck.pgm import PGM
|
|
3
|
+
from ck.pgm_compiler import ace
|
|
4
|
+
from ck.pgm_circuit import PGMCircuit
|
|
5
|
+
from ck.pgm_circuit.wmc_program import WMCProgram
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main() -> None:
|
|
9
|
+
pgm: PGM = example.Rain()
|
|
10
|
+
|
|
11
|
+
# `ace.compile_pgm` will look for an Ace installation in
|
|
12
|
+
# a default location. If Ace is not installed in the default
|
|
13
|
+
# location, then either: (1) pass the location as an argument
|
|
14
|
+
# to `ace.compile_pgm`, or (2) copy the Ace files to
|
|
15
|
+
# the default location using `ace.copy_ace_to_default_location`.
|
|
16
|
+
#
|
|
17
|
+
# Here is an example showing how to copy Ace to the default
|
|
18
|
+
# location from a source directory.
|
|
19
|
+
#
|
|
20
|
+
# ace.copy_ace_to_default_location(r'E:\Dropbox\Research\Ace\all')
|
|
21
|
+
|
|
22
|
+
pgm_cct: PGMCircuit = ace.compile_pgm(pgm, print_output=True)
|
|
23
|
+
|
|
24
|
+
print(f'PGM: {pgm.name}')
|
|
25
|
+
print()
|
|
26
|
+
print(f'Circuit:')
|
|
27
|
+
pgm_cct.dump()
|
|
28
|
+
print()
|
|
29
|
+
|
|
30
|
+
wmc = WMCProgram(pgm_cct)
|
|
31
|
+
|
|
32
|
+
print('Showing Program results:')
|
|
33
|
+
for indicators in pgm.instances_as_indicators():
|
|
34
|
+
instance_as_str = pgm.indicator_str(*indicators)
|
|
35
|
+
wmc_value = wmc.wmc(*indicators)
|
|
36
|
+
pgm_value = pgm.value_product_indicators(*indicators)
|
|
37
|
+
print(f' {instance_as_str:80} {wmc_value:.6f} {pgm_value:.6f}')
|
|
38
|
+
|
|
39
|
+
print()
|
|
40
|
+
print('Done.')
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
if __name__ == '__main__':
|
|
44
|
+
main()
|
ck_demos/all_demos.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Run all the demo scripts (except nominated exclusions).
|
|
3
|
+
This may be used as a 'smoke test'.
|
|
4
|
+
"""
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from subprocess import call
|
|
8
|
+
|
|
9
|
+
from ck_demos.utils.stop_watch import StopWatch
|
|
10
|
+
|
|
11
|
+
DEMO_TOP_DIR = '.' # relative to the directory this script is in
|
|
12
|
+
|
|
13
|
+
# These are scripts and directories we explicitly will not include
|
|
14
|
+
EXCEPTIONS = [
|
|
15
|
+
'utils', # package of utilities
|
|
16
|
+
'ace', # 3rd party, optional dependency
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
# These are what are printed as a separator lines
|
|
20
|
+
LINE = '-' * 80
|
|
21
|
+
LINE_2 = '=' * 80
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def main() -> int:
|
|
25
|
+
python_exe = sys.executable
|
|
26
|
+
print('Python executable:', python_exe)
|
|
27
|
+
print()
|
|
28
|
+
|
|
29
|
+
errors = []
|
|
30
|
+
script_count = 0
|
|
31
|
+
python_env = None
|
|
32
|
+
total_time = StopWatch()
|
|
33
|
+
|
|
34
|
+
# Start search of demo directories in the script directory.
|
|
35
|
+
script_path = Path(__file__)
|
|
36
|
+
script_name = script_path.stem
|
|
37
|
+
demos_top_dir_path = (script_path.parent / DEMO_TOP_DIR)
|
|
38
|
+
dirs = find_demo_dirs(demos_top_dir_path)
|
|
39
|
+
|
|
40
|
+
# Always exclude self if we happen to find our own script.
|
|
41
|
+
exceptions = set(EXCEPTIONS + [Path(__file__).name])
|
|
42
|
+
|
|
43
|
+
for demo_dir in dirs:
|
|
44
|
+
for script in demo_dir.iterdir():
|
|
45
|
+
if (
|
|
46
|
+
script.is_file() and
|
|
47
|
+
script.name.endswith('.py') and
|
|
48
|
+
(not script.name.startswith('_')) and
|
|
49
|
+
script.name not in exceptions
|
|
50
|
+
):
|
|
51
|
+
print(LINE)
|
|
52
|
+
print(script.name)
|
|
53
|
+
print(LINE)
|
|
54
|
+
script_count += 1
|
|
55
|
+
|
|
56
|
+
time = StopWatch()
|
|
57
|
+
return_code = call([python_exe, script.as_posix()], env=python_env)
|
|
58
|
+
time.stop()
|
|
59
|
+
|
|
60
|
+
if return_code != 0:
|
|
61
|
+
errors.append(f'Error code {return_code}: {script.name}')
|
|
62
|
+
print(LINE)
|
|
63
|
+
print(f'exited with code {return_code}, time = {time}, file = {script.name}')
|
|
64
|
+
|
|
65
|
+
print(LINE_2)
|
|
66
|
+
print(f'Done running {script_name}, {script_count} scripts in {total_time}s')
|
|
67
|
+
print(f'Number of errors: {len(errors)}')
|
|
68
|
+
for error in errors:
|
|
69
|
+
print(error)
|
|
70
|
+
|
|
71
|
+
# Provide a useful exit code.
|
|
72
|
+
if len(errors) > 0:
|
|
73
|
+
return -1
|
|
74
|
+
else:
|
|
75
|
+
return 0
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def find_demo_dirs(demos_top_dir_path: Path):
|
|
79
|
+
return [demos_top_dir_path] + [
|
|
80
|
+
d
|
|
81
|
+
for d in demos_top_dir_path.iterdir()
|
|
82
|
+
if d.is_dir() and d.name not in EXCEPTIONS
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == '__main__':
|
|
87
|
+
ret_code = main()
|
|
88
|
+
exit(ret_code)
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This demo shows how to dump a Circuit.
|
|
3
|
+
"""
|
|
4
|
+
from ck.circuit import Circuit
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def main() -> None:
|
|
8
|
+
cct = Circuit()
|
|
9
|
+
x0 = cct.new_var() # this var will have index 0
|
|
10
|
+
x1 = cct.new_var() # this var will have index 1
|
|
11
|
+
c123 = cct.const(123)
|
|
12
|
+
m = cct.mul(x0, x1)
|
|
13
|
+
_ = cct.add(c123, m)
|
|
14
|
+
|
|
15
|
+
cct.dump()
|
|
16
|
+
|
|
17
|
+
# with open('demo_cct_dump.txt', 'w') as out:
|
|
18
|
+
# circuit.dump(out)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if __name__ == '__main__':
|
|
22
|
+
main()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is a script for exploring partial derivatives.
|
|
3
|
+
"""
|
|
4
|
+
from ck.circuit_compiler.llvm_compiler import compile_circuit
|
|
5
|
+
from ck.circuit import Circuit
|
|
6
|
+
from ck.program import Program
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main() -> None:
|
|
10
|
+
cct = Circuit()
|
|
11
|
+
x = cct.new_vars(2) # indicators x[0] and x[1]
|
|
12
|
+
y = cct.new_vars(2) # indicators y[0] and y[1]
|
|
13
|
+
f = cct.new_vars(2) # factor between x and y
|
|
14
|
+
q = cct.add(
|
|
15
|
+
cct.mul(x[0], y[0], f[0]),
|
|
16
|
+
cct.mul(x[0], y[1], f[1]),
|
|
17
|
+
cct.mul(x[1], y[0], f[1]),
|
|
18
|
+
cct.mul(x[1], y[1], f[0]),
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
derivatives = cct.partial_derivatives(q, f) # returns a list: [f0', f1']
|
|
22
|
+
|
|
23
|
+
# prog is a function from [x0, x1, y0, y1, f0, f1] to [f0', f1', q]
|
|
24
|
+
prog = Program(compile_circuit(*derivatives + [q]))
|
|
25
|
+
|
|
26
|
+
# Make a dataset.
|
|
27
|
+
dataset = [
|
|
28
|
+
# x y f
|
|
29
|
+
[1, 0, 1, 0, 0.4, 0.6],
|
|
30
|
+
[0, 1, 1, 0, 0.4, 0.6],
|
|
31
|
+
[1, 0, 0, 1, 0.4, 0.6],
|
|
32
|
+
[0, 1, 0, 1, 0.4, 0.6],
|
|
33
|
+
[1, 1, 1, 1, 0.4, 0.6],
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
for instance in dataset:
|
|
37
|
+
result = prog(*instance)
|
|
38
|
+
print(instance, result[:-1], result[-1])
|
|
39
|
+
print()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if __name__ == '__main__':
|
|
43
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from typing import Sequence
|
|
2
|
+
|
|
3
|
+
from ck import example
|
|
4
|
+
from ck.circuit_compiler import NamedCircuitCompiler
|
|
5
|
+
from ck.pgm import PGM
|
|
6
|
+
from ck.pgm_compiler.named_pgm_compilers import NamedPGMCompiler
|
|
7
|
+
from ck_demos.utils.compare import compare
|
|
8
|
+
|
|
9
|
+
PGMS: Sequence[PGM] = [
|
|
10
|
+
example.Rain(),
|
|
11
|
+
# example.Insurance(),
|
|
12
|
+
# example.Pathfinder(),
|
|
13
|
+
# example.Mildew(),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
PGM_COMPILERS: Sequence[NamedPGMCompiler] = [NamedPGMCompiler.FE_BEST_JOINTREE]
|
|
17
|
+
|
|
18
|
+
CCT_COMPILERS: Sequence[NamedCircuitCompiler] = list(NamedCircuitCompiler)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main() -> None:
|
|
22
|
+
compare(
|
|
23
|
+
pgms=PGMS,
|
|
24
|
+
pgm_compilers=PGM_COMPILERS,
|
|
25
|
+
cct_compilers=CCT_COMPILERS,
|
|
26
|
+
)
|
|
27
|
+
print()
|
|
28
|
+
print('Done.')
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == '__main__':
|
|
32
|
+
main()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from ck import example
|
|
2
|
+
from ck.circuit import CircuitNode
|
|
3
|
+
from ck.circuit_compiler import llvm_vm_compiler
|
|
4
|
+
from ck.circuit_compiler.support.llvm_ir_function import LLVMRawProgram
|
|
5
|
+
from ck.pgm import PGM
|
|
6
|
+
from ck.pgm_circuit import PGMCircuit
|
|
7
|
+
from ck.pgm_compiler import NamedPGMCompiler, PGMCompiler
|
|
8
|
+
|
|
9
|
+
EXAMPLE_PGM: PGM = example.Rain()
|
|
10
|
+
PGM_COMPILER: PGMCompiler = NamedPGMCompiler.FE_BEST_JOINTREE
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main() -> None:
|
|
14
|
+
pgm_cct: PGMCircuit = PGM_COMPILER(EXAMPLE_PGM)
|
|
15
|
+
top: CircuitNode = pgm_cct.circuit_top
|
|
16
|
+
|
|
17
|
+
program: LLVMRawProgram = llvm_vm_compiler.compile_circuit(top)
|
|
18
|
+
|
|
19
|
+
print(program.llvm_program)
|
|
20
|
+
|
|
21
|
+
print()
|
|
22
|
+
print('Done.')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == '__main__':
|
|
26
|
+
main()
|
ck_demos/pgm/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Demonstrate dumping a PGM - stressing the method
|
|
3
|
+
"""
|
|
4
|
+
from ck import example
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def main() -> None:
|
|
8
|
+
pgm = example.Stress()
|
|
9
|
+
|
|
10
|
+
print('Dumping PGM')
|
|
11
|
+
pgm.dump(show_function_values=True)
|
|
12
|
+
|
|
13
|
+
print()
|
|
14
|
+
print('Done.')
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if __name__ == '__main__':
|
|
18
|
+
main()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from ck.pgm import PGM
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def main() -> None:
|
|
5
|
+
pgm = PGM()
|
|
6
|
+
|
|
7
|
+
a = pgm.new_rv('A', ('x', 'y', 'z'))
|
|
8
|
+
b = pgm.new_rv('B', (3, 5))
|
|
9
|
+
|
|
10
|
+
print(pgm.indicator_str(a[0], b[1], a[2]))
|
|
11
|
+
print(pgm.condition_str(a[0], b[1], a[2]))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == '__main__':
|
|
15
|
+
main()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from ck import example
|
|
2
|
+
from ck.pgm import PGM
|
|
3
|
+
|
|
4
|
+
INDENT: str = ' '
|
|
5
|
+
PRECISION: int = 3
|
|
6
|
+
MAX_STATE_DIGITS = 21
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main() -> None:
|
|
10
|
+
"""
|
|
11
|
+
Show all standard PGM examples
|
|
12
|
+
"""
|
|
13
|
+
for example_name, pgm_class in example.ALL_EXAMPLES.items():
|
|
14
|
+
pgm: PGM = pgm_class()
|
|
15
|
+
|
|
16
|
+
print(example_name)
|
|
17
|
+
pgm.dump_synopsis(prefix=INDENT)
|
|
18
|
+
print()
|
|
19
|
+
|
|
20
|
+
print()
|
|
21
|
+
print('Done.')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == '__main__':
|
|
25
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from typing import Sequence
|
|
2
|
+
|
|
3
|
+
from ck import example
|
|
4
|
+
from ck.circuit_compiler import NamedCircuitCompiler
|
|
5
|
+
from ck.pgm import PGM
|
|
6
|
+
from ck.pgm_circuit.support.compile_circuit import DEFAULT_CIRCUIT_COMPILER
|
|
7
|
+
from ck.pgm_compiler.named_pgm_compilers import NamedPGMCompiler
|
|
8
|
+
from ck_demos.utils.compare import compare
|
|
9
|
+
|
|
10
|
+
# @formatter:off
|
|
11
|
+
|
|
12
|
+
PGMS: Sequence[PGM] = [
|
|
13
|
+
example.Rain(),
|
|
14
|
+
example.Cancer(),
|
|
15
|
+
example.Earthquake(),
|
|
16
|
+
example.Asia(),
|
|
17
|
+
example.Survey(),
|
|
18
|
+
example.Sachs(),
|
|
19
|
+
example.Child(),
|
|
20
|
+
example.Alarm(),
|
|
21
|
+
|
|
22
|
+
# example.Hailfinder(),
|
|
23
|
+
# example.Insurance(),
|
|
24
|
+
# example.Pathfinder(),
|
|
25
|
+
# example.Mildew(),
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
CCT_COMPILERS: Sequence[NamedCircuitCompiler] = [DEFAULT_CIRCUIT_COMPILER]
|
|
29
|
+
|
|
30
|
+
PGM_COMPILERS: Sequence[NamedPGMCompiler] = [
|
|
31
|
+
named_compiler
|
|
32
|
+
for named_compiler in NamedPGMCompiler
|
|
33
|
+
if named_compiler.name.startswith('FE_') and 'WEIGHTED' not in named_compiler.name
|
|
34
|
+
] + [NamedPGMCompiler.ACE]
|
|
35
|
+
|
|
36
|
+
# @formatter:on
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def main() -> None:
|
|
40
|
+
compare(
|
|
41
|
+
pgms=PGMS,
|
|
42
|
+
pgm_compilers=PGM_COMPILERS,
|
|
43
|
+
cct_compilers=CCT_COMPILERS,
|
|
44
|
+
)
|
|
45
|
+
print()
|
|
46
|
+
print('Done.')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == '__main__':
|
|
50
|
+
main()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from ck import example
|
|
2
|
+
from ck.circuit import Circuit
|
|
3
|
+
from ck.pgm import PGM
|
|
4
|
+
from ck.pgm_circuit import PGMCircuit
|
|
5
|
+
from ck.pgm_circuit.wmc_program import WMCProgram
|
|
6
|
+
from ck.pgm_compiler.factor_elimination import join_tree_to_circuit
|
|
7
|
+
from ck.pgm_compiler.support.clusters import min_degree, Clusters
|
|
8
|
+
from ck.pgm_compiler.support.join_tree import JoinTree, clusters_to_join_tree
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main() -> None:
|
|
12
|
+
pgm: PGM = example.Rain()
|
|
13
|
+
|
|
14
|
+
print(f'PGM {pgm.name!r}')
|
|
15
|
+
print()
|
|
16
|
+
|
|
17
|
+
clusters: Clusters = min_degree(pgm)
|
|
18
|
+
|
|
19
|
+
clusters.dump()
|
|
20
|
+
|
|
21
|
+
join_tree: JoinTree = clusters_to_join_tree(clusters)
|
|
22
|
+
|
|
23
|
+
print('Join Tree:')
|
|
24
|
+
join_tree.dump()
|
|
25
|
+
print()
|
|
26
|
+
|
|
27
|
+
pgm_circuit: PGMCircuit = join_tree_to_circuit(join_tree)
|
|
28
|
+
circuit: Circuit = pgm_circuit.circuit_top.circuit
|
|
29
|
+
|
|
30
|
+
print('Circuit:')
|
|
31
|
+
circuit.dump()
|
|
32
|
+
print()
|
|
33
|
+
|
|
34
|
+
wmc = WMCProgram(pgm_circuit)
|
|
35
|
+
|
|
36
|
+
print()
|
|
37
|
+
print('Showing Program Results:')
|
|
38
|
+
print(f' {"State":80} {"WMC":8} {"PGM":8}')
|
|
39
|
+
for indicators in pgm.instances_as_indicators():
|
|
40
|
+
instance_as_str = pgm.indicator_str(*indicators)
|
|
41
|
+
wmc_value = wmc.wmc(*indicators)
|
|
42
|
+
pgm_value = pgm.value_product_indicators(*indicators)
|
|
43
|
+
print(f' {instance_as_str:80} {wmc_value:8.6f} {pgm_value:8.6f}')
|
|
44
|
+
|
|
45
|
+
print()
|
|
46
|
+
print('Done.')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == '__main__':
|
|
50
|
+
main()
|