problog 2.2.5__py3-none-any.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.
- problog/__init__.py +114 -0
- problog/__main__.py +6 -0
- problog/__pycache__/__init__.cpython-312.pyc +0 -0
- problog/__pycache__/bdd_formula.cpython-312.pyc +0 -0
- problog/__pycache__/clausedb.cpython-312.pyc +0 -0
- problog/__pycache__/cnf_formula.cpython-312.pyc +0 -0
- problog/__pycache__/constraint.cpython-312.pyc +0 -0
- problog/__pycache__/core.cpython-312.pyc +0 -0
- problog/__pycache__/cycles.cpython-312.pyc +0 -0
- problog/__pycache__/dd_formula.cpython-312.pyc +0 -0
- problog/__pycache__/ddnnf_formula.cpython-312.pyc +0 -0
- problog/__pycache__/debug.cpython-312.pyc +0 -0
- problog/__pycache__/engine.cpython-312.pyc +0 -0
- problog/__pycache__/engine_builtin.cpython-312.pyc +0 -0
- problog/__pycache__/engine_stack.cpython-312.pyc +0 -0
- problog/__pycache__/engine_unify.cpython-312.pyc +0 -0
- problog/__pycache__/errors.cpython-312.pyc +0 -0
- problog/__pycache__/eval_nodes.cpython-312.pyc +0 -0
- problog/__pycache__/evaluator.cpython-312.pyc +0 -0
- problog/__pycache__/formula.cpython-312.pyc +0 -0
- problog/__pycache__/forward.cpython-312.pyc +0 -0
- problog/__pycache__/kbest.cpython-312.pyc +0 -0
- problog/__pycache__/logic.cpython-312.pyc +0 -0
- problog/__pycache__/maxsat.cpython-312.pyc +0 -0
- problog/__pycache__/parser.cpython-312.pyc +0 -0
- problog/__pycache__/program.cpython-312.pyc +0 -0
- problog/__pycache__/sdd_formula.cpython-312.pyc +0 -0
- problog/__pycache__/sdd_formula_explicit.cpython-312.pyc +0 -0
- problog/__pycache__/setup.cpython-312.pyc +0 -0
- problog/__pycache__/util.cpython-312.pyc +0 -0
- problog/__pycache__/version.cpython-312.pyc +0 -0
- problog/bdd_formula.py +176 -0
- problog/bdd_formula_alt.py +253 -0
- problog/bin/darwin/cnf2dDNNF_wine +12 -0
- problog/bin/darwin/dsharp +0 -0
- problog/bin/linux/dsharp +0 -0
- problog/bin/linux/maxsatz +0 -0
- problog/bin/source/maxsatz/maxsatz2009.c +3089 -0
- problog/bin/windows/dsharp.exe +0 -0
- problog/bin/windows/libgcc_s_dw2-1.dll +0 -0
- problog/bin/windows/libstdc++-6.dll +0 -0
- problog/bin/windows/maxsatz.exe +0 -0
- problog/clausedb.py +1065 -0
- problog/cnf_formula.py +391 -0
- problog/constraint.py +334 -0
- problog/core.py +226 -0
- problog/cycles.py +191 -0
- problog/dd_formula.py +650 -0
- problog/ddnnf_formula.py +413 -0
- problog/debug.py +273 -0
- problog/engine.py +641 -0
- problog/engine_builtin.py +2078 -0
- problog/engine_stack.py +1606 -0
- problog/engine_unify.py +446 -0
- problog/errors.py +123 -0
- problog/eval_nodes.py +874 -0
- problog/evaluator.py +700 -0
- problog/extern.py +343 -0
- problog/formula.py +1846 -0
- problog/forward.py +794 -0
- problog/ground_yap.py +214 -0
- problog/kbest.py +280 -0
- problog/learning/__init__.py +0 -0
- problog/learning/lfi.py +1607 -0
- problog/library/aggregate.pl +26 -0
- problog/library/apply.pl +147 -0
- problog/library/aproblog.py +68 -0
- problog/library/assert.py +34 -0
- problog/library/builtin.pl +3 -0
- problog/library/collect.pl +26 -0
- problog/library/control.pl +23 -0
- problog/library/cut.pl +42 -0
- problog/library/db.py +179 -0
- problog/library/lists.pl +316 -0
- problog/library/lists.py +27 -0
- problog/library/nlp4plp.d/constraints.pl +153 -0
- problog/library/nlp4plp.d/ge_solver_sparse.pl +246 -0
- problog/library/nlp4plp.d/histograms.pl +134 -0
- problog/library/nlp4plp.d/input_interface.pl +502 -0
- problog/library/nlp4plp.d/meta_prob.pl +136 -0
- problog/library/nlp4plp.d/multiset_constraints.pl +812 -0
- problog/library/nlp4plp.d/probabilistic_drawing.pl +319 -0
- problog/library/nlp4plp.d/property_based_merging.pl +98 -0
- problog/library/nlp4plp.d/run_solver.pl +17 -0
- problog/library/nlp4plp.d/setup_aux.pl +76 -0
- problog/library/nlp4plp.d/static_setup.pl +432 -0
- problog/library/nlp4plp.d/terms_to_predicates.pl +245 -0
- problog/library/nlp4plp.pl +1 -0
- problog/library/record.py +153 -0
- problog/library/scope.pl +14 -0
- problog/library/string.pl +15 -0
- problog/library/string.py +22 -0
- problog/logic.py +1335 -0
- problog/magic.py +209 -0
- problog/maxsat.py +113 -0
- problog/nnf_formula.py +5 -0
- problog/parser.py +1541 -0
- problog/pgm/__init__.py +0 -0
- problog/pgm/cpd.py +1060 -0
- problog/program.py +591 -0
- problog/pypl.py +93 -0
- problog/sdd_formula.py +968 -0
- problog/sdd_formula_explicit.py +516 -0
- problog/setup.py +193 -0
- problog/tasks/__init__.py +110 -0
- problog/tasks/__pycache__/__init__.cpython-312.pyc +0 -0
- problog/tasks/bayesnet.py +338 -0
- problog/tasks/constraint.py +392 -0
- problog/tasks/dtproblog.py +350 -0
- problog/tasks/explain.py +112 -0
- problog/tasks/ground.py +198 -0
- problog/tasks/map.py +105 -0
- problog/tasks/mpe.py +406 -0
- problog/tasks/probability.py +443 -0
- problog/tasks/sample.py +870 -0
- problog/tasks/shell.py +227 -0
- problog/tasks/time1.py +152 -0
- problog/test/__init__.py +0 -0
- problog/test/library/__init__.py +0 -0
- problog/test/library/test_string.py +83 -0
- problog/test/test_bn.py +105 -0
- problog/test/test_constraint.py +55 -0
- problog/test/test_ddnnf_formula.py +44 -0
- problog/test/test_dtproblog.py +150 -0
- problog/test/test_engine.py +267 -0
- problog/test/test_equality.py +13 -0
- problog/test/test_evaluator.py +121 -0
- problog/test/test_interface.py +62 -0
- problog/test/test_lfi.py +192 -0
- problog/test/test_lficont.py +69 -0
- problog/test/test_logic.py +151 -0
- problog/test/test_pypl.py +36 -0
- problog/test/test_sample.py +125 -0
- problog/test/test_subquery.py +125 -0
- problog/test/test_system.py +310 -0
- problog/test/test_tasks.py +334 -0
- problog/test/test_transformation.py +63 -0
- problog/test/test_try_call.py +125 -0
- problog/test/test_unify.py +68 -0
- problog/test/test_web.py +12 -0
- problog/util.py +688 -0
- problog/version.py +1 -0
- problog/web/__init__.py +0 -0
- problog/web/js/problog_editor.js +548 -0
- problog/web/run_learning.py +86 -0
- problog/web/run_problog.py +117 -0
- problog/web/server.py +613 -0
- problog/web/server_debug.py +299 -0
- problog-2.2.5.dist-info/METADATA +125 -0
- problog-2.2.5.dist-info/RECORD +153 -0
- problog-2.2.5.dist-info/WHEEL +5 -0
- problog-2.2.5.dist-info/entry_points.txt +2 -0
- problog-2.2.5.dist-info/top_level.txt +1 -0
problog/__init__.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Part of the ProbLog distribution.
|
|
3
|
+
|
|
4
|
+
Copyright 2015 KU Leuven, DTAI Research Group
|
|
5
|
+
|
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
you may not use this file except in compliance with the License.
|
|
8
|
+
You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
See the License for the specific language governing permissions and
|
|
16
|
+
limitations under the License.
|
|
17
|
+
"""
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
import typing
|
|
21
|
+
|
|
22
|
+
sys.setrecursionlimit(10000)
|
|
23
|
+
|
|
24
|
+
# Set the PATH and PYTHON_PATH variables
|
|
25
|
+
from .setup import set_environment, gather_info
|
|
26
|
+
|
|
27
|
+
set_environment()
|
|
28
|
+
|
|
29
|
+
system_info = gather_info()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def root_path(*args):
|
|
33
|
+
return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", *args))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
library_paths = [root_path("problog", "library")]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Load all submodules. This has two reasons:
|
|
40
|
+
# - initializes all transformations (@transform)
|
|
41
|
+
# - makes it possible to just import 'problog' and then use
|
|
42
|
+
# something like problog.program.PrologFile
|
|
43
|
+
from . import cnf_formula
|
|
44
|
+
from . import core
|
|
45
|
+
from . import engine
|
|
46
|
+
from . import evaluator
|
|
47
|
+
from . import formula
|
|
48
|
+
from . import logic
|
|
49
|
+
from . import ddnnf_formula
|
|
50
|
+
from . import parser
|
|
51
|
+
from . import program
|
|
52
|
+
from . import sdd_formula
|
|
53
|
+
from . import sdd_formula_explicit
|
|
54
|
+
from . import util
|
|
55
|
+
from . import bdd_formula
|
|
56
|
+
from . import forward
|
|
57
|
+
from . import cycles
|
|
58
|
+
from . import kbest
|
|
59
|
+
from . import tasks
|
|
60
|
+
from . import debug
|
|
61
|
+
|
|
62
|
+
_evaluatables: typing.Dict[str, typing.Type[evaluator.Evaluatable]] = {
|
|
63
|
+
"sdd": sdd_formula.SDD,
|
|
64
|
+
"sddx": sdd_formula_explicit.SDDExplicit,
|
|
65
|
+
"bdd": bdd_formula.BDD,
|
|
66
|
+
"nnf": ddnnf_formula.DDNNF,
|
|
67
|
+
"ddnnf": ddnnf_formula.DDNNF,
|
|
68
|
+
"kbest": kbest.KBestFormula,
|
|
69
|
+
"fsdd": forward.ForwardSDD,
|
|
70
|
+
"fbdd": forward.ForwardBDD,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
_semirings: typing.Dict[str, typing.Type[evaluator.Semiring]] = {
|
|
74
|
+
"prob": evaluator.SemiringProbability,
|
|
75
|
+
"logprob": evaluator.SemiringLogProbability,
|
|
76
|
+
"symbolic": evaluator.SemiringSymbolic,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_semirings() -> typing.Collection[str]:
|
|
81
|
+
"""Get the set of registered semirings."""
|
|
82
|
+
return _semirings.keys()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def register_semiring(name: str, cls: typing.Type[evaluator.Semiring]):
|
|
86
|
+
"""Register a semiring in the semiring registry."""
|
|
87
|
+
assert (
|
|
88
|
+
name not in _semirings
|
|
89
|
+
), "A semi-ring with the same name is already registered."
|
|
90
|
+
_semirings[name] = cls
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_semiring(name: typing.Optional[str] = None) -> typing.Type[evaluator.Semiring]:
|
|
94
|
+
"""Lookup a semiring."""
|
|
95
|
+
if name is None:
|
|
96
|
+
return _semirings["prob"]
|
|
97
|
+
return _semirings.get(name, None)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_evaluatables() -> typing.Collection[str]:
|
|
101
|
+
return _evaluatables.keys()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def get_evaluatable(
|
|
105
|
+
name: typing.Optional[str] = None,
|
|
106
|
+
semiring: typing.Optional[evaluator.Semiring] = None,
|
|
107
|
+
) -> typing.Type[evaluator.Evaluatable]:
|
|
108
|
+
if name is None:
|
|
109
|
+
if semiring is None or semiring.is_dsp():
|
|
110
|
+
return evaluator.EvaluatableDSP
|
|
111
|
+
else:
|
|
112
|
+
return formula.LogicNNF
|
|
113
|
+
else:
|
|
114
|
+
return _evaluatables[name]
|
problog/__main__.py
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
problog/bdd_formula.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""
|
|
2
|
+
problog.bdd_formula - Binary Decision Diagrams
|
|
3
|
+
----------------------------------------------
|
|
4
|
+
|
|
5
|
+
Provides access to Binary Decision Diagrams (BDDs).
|
|
6
|
+
|
|
7
|
+
..
|
|
8
|
+
Part of the ProbLog distribution.
|
|
9
|
+
|
|
10
|
+
Copyright 2015 KU Leuven, DTAI Research Group
|
|
11
|
+
|
|
12
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
+
you may not use this file except in compliance with the License.
|
|
14
|
+
You may obtain a copy of the License at
|
|
15
|
+
|
|
16
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
|
|
18
|
+
Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
See the License for the specific language governing permissions and
|
|
22
|
+
limitations under the License.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from .core import transform
|
|
26
|
+
from .dd_formula import DD, build_dd, DDManager
|
|
27
|
+
from .errors import InstallError
|
|
28
|
+
from .formula import LogicDAG
|
|
29
|
+
|
|
30
|
+
# noinspection PyBroadException
|
|
31
|
+
# noinspection PyUnresolvedReferences
|
|
32
|
+
try:
|
|
33
|
+
# noinspection PyPackageRequirements
|
|
34
|
+
import pyeda.boolalg.bdd as bdd
|
|
35
|
+
|
|
36
|
+
# noinspection PyPackageRequirements
|
|
37
|
+
import pyeda.boolalg.expr as bdd_expr
|
|
38
|
+
except Exception:
|
|
39
|
+
bdd = None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class BDD(DD):
|
|
43
|
+
"""A propositional logic formula consisting of and, or, not and atoms represented as an BDD."""
|
|
44
|
+
|
|
45
|
+
def __init__(self, **kwdargs):
|
|
46
|
+
if bdd is None:
|
|
47
|
+
raise InstallError("The BDD library is not available.")
|
|
48
|
+
|
|
49
|
+
DD.__init__(self, auto_compact=False, **kwdargs)
|
|
50
|
+
|
|
51
|
+
def _create_manager(self):
|
|
52
|
+
return BDDManager()
|
|
53
|
+
|
|
54
|
+
def get_atom_from_inode(self, node):
|
|
55
|
+
"""Get the original atom given an internal node.
|
|
56
|
+
|
|
57
|
+
:param node: internal node
|
|
58
|
+
:return: atom represented by the internal node
|
|
59
|
+
"""
|
|
60
|
+
return self.var2atom[self.get_manager().get_variable(node)]
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def is_available(cls):
|
|
64
|
+
"""Checks whether the BDD library is available."""
|
|
65
|
+
return bdd is not None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class BDDManager(DDManager):
|
|
69
|
+
"""
|
|
70
|
+
Manager for BDDs.
|
|
71
|
+
It wraps around the pyeda BDD module
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
# noinspection PyUnusedLocal
|
|
75
|
+
def __init__(self, varcount=0, auto_gc=True):
|
|
76
|
+
"""Create a new BDD manager.
|
|
77
|
+
|
|
78
|
+
:param varcount: number of initial variables
|
|
79
|
+
:type varcount: int
|
|
80
|
+
:param auto_gc: use automatic garbage collection and minimization
|
|
81
|
+
:type auto_gc: bool
|
|
82
|
+
"""
|
|
83
|
+
DDManager.__init__(self)
|
|
84
|
+
self.varcount = 1
|
|
85
|
+
self.ZERO = bdd.expr2bdd(bdd_expr.expr("0"))
|
|
86
|
+
self.ONE = bdd.expr2bdd(bdd_expr.expr("1"))
|
|
87
|
+
|
|
88
|
+
def add_variable(self, label=0):
|
|
89
|
+
if label == 0 or label > self.varcount:
|
|
90
|
+
self.varcount += 1
|
|
91
|
+
return self.varcount
|
|
92
|
+
else:
|
|
93
|
+
return label
|
|
94
|
+
|
|
95
|
+
def get_variable(self, node):
|
|
96
|
+
"""Get the variable represented by the given node.
|
|
97
|
+
|
|
98
|
+
:param node: internal node
|
|
99
|
+
:return: original node
|
|
100
|
+
"""
|
|
101
|
+
# noinspection PyProtectedMember
|
|
102
|
+
return int(bdd._VARS[node.root].name[1:])
|
|
103
|
+
|
|
104
|
+
def literal(self, label):
|
|
105
|
+
return bdd.bddvar("v" + str(self.add_variable(label)))
|
|
106
|
+
|
|
107
|
+
def is_true(self, node):
|
|
108
|
+
return node.is_one()
|
|
109
|
+
|
|
110
|
+
def true(self):
|
|
111
|
+
return self.ONE
|
|
112
|
+
|
|
113
|
+
def is_false(self, node):
|
|
114
|
+
return node.is_zero()
|
|
115
|
+
|
|
116
|
+
def false(self):
|
|
117
|
+
return self.ZERO
|
|
118
|
+
|
|
119
|
+
def conjoin2(self, r, s):
|
|
120
|
+
return r & s
|
|
121
|
+
|
|
122
|
+
def disjoin2(self, r, s):
|
|
123
|
+
return r | s
|
|
124
|
+
|
|
125
|
+
def negate(self, node):
|
|
126
|
+
return ~node
|
|
127
|
+
|
|
128
|
+
def same(self, node1, node2):
|
|
129
|
+
# Assumes BDD library always reuses equivalent nodes.
|
|
130
|
+
return node1 is node2
|
|
131
|
+
|
|
132
|
+
def ref(self, *nodes):
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
def deref(self, *nodes):
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
def write_to_dot(self, node, filename):
|
|
139
|
+
with open(filename, "w") as f:
|
|
140
|
+
print(node.to_dot(), file=f)
|
|
141
|
+
|
|
142
|
+
def wmc(self, node, weights, semiring):
|
|
143
|
+
pall = semiring.zero()
|
|
144
|
+
for path in node.satisfy_all():
|
|
145
|
+
pw = semiring.one()
|
|
146
|
+
for var, val in path.items():
|
|
147
|
+
var = int(var.name[1:])
|
|
148
|
+
pos, neg = weights[var]
|
|
149
|
+
if val:
|
|
150
|
+
p = pos
|
|
151
|
+
else:
|
|
152
|
+
p = neg
|
|
153
|
+
pw = semiring.times(p, pw)
|
|
154
|
+
pall = semiring.plus(pw, pall)
|
|
155
|
+
return pall
|
|
156
|
+
|
|
157
|
+
def wmc_literal(self, node, weights, semiring, literal):
|
|
158
|
+
raise NotImplementedError("not supported")
|
|
159
|
+
|
|
160
|
+
def wmc_true(self, weights, semiring):
|
|
161
|
+
return semiring.one()
|
|
162
|
+
|
|
163
|
+
def __del__(self):
|
|
164
|
+
pass
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@transform(LogicDAG, BDD)
|
|
168
|
+
def build_bdd(source, destination, **kwdargs):
|
|
169
|
+
"""Build an SDD from another formula.
|
|
170
|
+
|
|
171
|
+
:param source: source formula
|
|
172
|
+
:param destination: destination formula
|
|
173
|
+
:param kwdargs: extra arguments
|
|
174
|
+
:return: destination
|
|
175
|
+
"""
|
|
176
|
+
return build_dd(source, destination, **kwdargs)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""
|
|
2
|
+
problog.bdd_formula - Binary Decision Diagrams
|
|
3
|
+
----------------------------------------------
|
|
4
|
+
|
|
5
|
+
Provides access to Binary Decision Diagrams (BDDs).
|
|
6
|
+
|
|
7
|
+
..
|
|
8
|
+
Part of the ProbLog distribution.
|
|
9
|
+
|
|
10
|
+
Copyright 2015 KU Leuven, DTAI Research Group
|
|
11
|
+
|
|
12
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
+
you may not use this file except in compliance with the License.
|
|
14
|
+
You may obtain a copy of the License at
|
|
15
|
+
|
|
16
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
|
|
18
|
+
Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
See the License for the specific language governing permissions and
|
|
22
|
+
limitations under the License.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from .core import transform
|
|
26
|
+
from .dd_formula import DD, build_dd, DDManager
|
|
27
|
+
from .errors import InstallError
|
|
28
|
+
from .formula import LogicDAG
|
|
29
|
+
|
|
30
|
+
# noinspection PyBroadException
|
|
31
|
+
# noinspection PyUnresolvedReferences
|
|
32
|
+
try:
|
|
33
|
+
# noinspection PyPackageRequirements
|
|
34
|
+
pass
|
|
35
|
+
except Exception:
|
|
36
|
+
bdd = None
|
|
37
|
+
|
|
38
|
+
import dd.autoref as bdd
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class BDD(DD):
|
|
42
|
+
"""A propositional logic formula consisting of and, or, not and atoms represented as an BDD."""
|
|
43
|
+
|
|
44
|
+
def __init__(self, **kwdargs):
|
|
45
|
+
if bdd is None:
|
|
46
|
+
raise InstallError("The BDD library is not available.")
|
|
47
|
+
|
|
48
|
+
DD.__init__(self, auto_compact=False, **kwdargs)
|
|
49
|
+
|
|
50
|
+
def _create_manager(self):
|
|
51
|
+
return BDDManager()
|
|
52
|
+
|
|
53
|
+
def get_atom_from_inode(self, node):
|
|
54
|
+
"""Get the original atom given an internal node.
|
|
55
|
+
|
|
56
|
+
:param node: internal node
|
|
57
|
+
:return: atom represented by the internal node
|
|
58
|
+
"""
|
|
59
|
+
return self.var2atom[self.get_manager().get_variable(node)]
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def is_available(cls):
|
|
63
|
+
"""Checks whether the BDD library is available."""
|
|
64
|
+
return bdd is not None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class BDDManager(DDManager):
|
|
68
|
+
"""
|
|
69
|
+
Manager for BDDs.
|
|
70
|
+
It wraps around the pyeda BDD module
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
# noinspection PyUnusedLocal
|
|
74
|
+
def __init__(self, varcount=0, auto_gc=True):
|
|
75
|
+
"""Create a new BDD manager.
|
|
76
|
+
|
|
77
|
+
:param varcount: number of initial variables
|
|
78
|
+
:type varcount: int
|
|
79
|
+
:param auto_gc: use automatic garbage collection and minimization
|
|
80
|
+
:type auto_gc: bool
|
|
81
|
+
"""
|
|
82
|
+
DDManager.__init__(self)
|
|
83
|
+
self.varcount = 1
|
|
84
|
+
self.base = bdd.BDD()
|
|
85
|
+
self.ZERO = self.base.false
|
|
86
|
+
self.ONE = self.base.true
|
|
87
|
+
|
|
88
|
+
def add_variable(self, label=0):
|
|
89
|
+
if label == 0 or label > self.varcount:
|
|
90
|
+
self.varcount += 1
|
|
91
|
+
res = self.varcount
|
|
92
|
+
else:
|
|
93
|
+
res = label
|
|
94
|
+
self.base.declare("v" + str(res))
|
|
95
|
+
return res
|
|
96
|
+
|
|
97
|
+
def get_variable(self, node):
|
|
98
|
+
"""Get the variable represented by the given node.
|
|
99
|
+
|
|
100
|
+
:param node: internal node
|
|
101
|
+
:return: original node
|
|
102
|
+
"""
|
|
103
|
+
# noinspection PyProtectedMember
|
|
104
|
+
return self.base.var(node)
|
|
105
|
+
|
|
106
|
+
def literal(self, label):
|
|
107
|
+
return self.base.var("v" + str(self.add_variable(label)))
|
|
108
|
+
|
|
109
|
+
def is_true(self, node):
|
|
110
|
+
return node.is_one()
|
|
111
|
+
|
|
112
|
+
def true(self):
|
|
113
|
+
return self.ONE
|
|
114
|
+
|
|
115
|
+
def is_false(self, node):
|
|
116
|
+
return node.is_zero()
|
|
117
|
+
|
|
118
|
+
def false(self):
|
|
119
|
+
return self.ZERO
|
|
120
|
+
|
|
121
|
+
def conjoin2(self, r, s):
|
|
122
|
+
return r & s
|
|
123
|
+
|
|
124
|
+
def disjoin2(self, r, s):
|
|
125
|
+
return r | s
|
|
126
|
+
|
|
127
|
+
def negate(self, node):
|
|
128
|
+
return ~node
|
|
129
|
+
|
|
130
|
+
def same(self, node1, node2):
|
|
131
|
+
# Assumes BDD library always reuses equivalent nodes.
|
|
132
|
+
return node1 is node2
|
|
133
|
+
|
|
134
|
+
def ref(self, *nodes):
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
def deref(self, *nodes):
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
def write_to_dot(self, node, filename):
|
|
141
|
+
with open(filename, "w") as f:
|
|
142
|
+
print(node.to_dot(), file=f)
|
|
143
|
+
|
|
144
|
+
def _parse_expr(self, expr):
|
|
145
|
+
# EXPR := VAR | "TRUE" | "FALSE" | ITE
|
|
146
|
+
# ITE := "ite" "(" VAR "," EXPR "," EXPR ")"
|
|
147
|
+
# VAR := expression
|
|
148
|
+
lexpr = len(expr)
|
|
149
|
+
if expr.startswith("TRUE"):
|
|
150
|
+
res = "TRUE"
|
|
151
|
+
pos = 4
|
|
152
|
+
elif expr.startswith("FALSE"):
|
|
153
|
+
res = "FALSE"
|
|
154
|
+
pos = 5
|
|
155
|
+
elif expr.startswith("ite("):
|
|
156
|
+
pos = 4
|
|
157
|
+
var, rst = expr[pos:].split(", ", 1)
|
|
158
|
+
ift, pos1 = self._parse_expr(rst)
|
|
159
|
+
iff, pos2 = self._parse_expr(rst[pos1:])
|
|
160
|
+
res = (var, ift, iff)
|
|
161
|
+
pos += pos1 + pos2 + len(var)
|
|
162
|
+
elif expr.startswith("(~ "):
|
|
163
|
+
pos = 3
|
|
164
|
+
sub, pos1 = self._parse_expr(expr[pos:])
|
|
165
|
+
pos = pos + pos1 + 1
|
|
166
|
+
res = ("~", sub)
|
|
167
|
+
else:
|
|
168
|
+
pos = 0
|
|
169
|
+
while pos < lexpr and expr[pos] not in " ,)":
|
|
170
|
+
pos += 1
|
|
171
|
+
res = expr[:pos]
|
|
172
|
+
while pos < lexpr and expr[pos] in " ,)":
|
|
173
|
+
pos += 1
|
|
174
|
+
|
|
175
|
+
return res, pos
|
|
176
|
+
|
|
177
|
+
def _enum_paths(self, expr, weights, semiring, negated=False):
|
|
178
|
+
if expr == "TRUE":
|
|
179
|
+
if not negated:
|
|
180
|
+
yield semiring.one()
|
|
181
|
+
elif expr == "FALSE":
|
|
182
|
+
if negated:
|
|
183
|
+
yield semiring.one()
|
|
184
|
+
elif type(expr) == str:
|
|
185
|
+
v = int(expr[1:])
|
|
186
|
+
wp, wn = weights[abs(v)]
|
|
187
|
+
if v > 0:
|
|
188
|
+
pass
|
|
189
|
+
else:
|
|
190
|
+
wp, wn = wn, wp
|
|
191
|
+
if negated:
|
|
192
|
+
yield wn
|
|
193
|
+
else:
|
|
194
|
+
yield wp
|
|
195
|
+
elif len(expr) == 3:
|
|
196
|
+
v = int(expr[0][1:])
|
|
197
|
+
wp, wn = weights[abs(v)]
|
|
198
|
+
if v > 0:
|
|
199
|
+
pass
|
|
200
|
+
else:
|
|
201
|
+
wp, wn = wn, wp
|
|
202
|
+
|
|
203
|
+
for p in self._enum_paths(expr[1], weights, semiring, negated=negated):
|
|
204
|
+
if negated:
|
|
205
|
+
yield semiring.plus(wn, p)
|
|
206
|
+
else:
|
|
207
|
+
yield semiring.times(wp, p)
|
|
208
|
+
for p in self._enum_paths(expr[2], weights, semiring, negated=negated):
|
|
209
|
+
if negated:
|
|
210
|
+
yield semiring.plus(wp, p)
|
|
211
|
+
else:
|
|
212
|
+
yield semiring.times(wn, p)
|
|
213
|
+
else:
|
|
214
|
+
if negated:
|
|
215
|
+
pall = semiring.one()
|
|
216
|
+
else:
|
|
217
|
+
pall = semiring.zero()
|
|
218
|
+
for p in self._enum_paths(expr[1], weights, semiring, negated=not negated):
|
|
219
|
+
if negated:
|
|
220
|
+
pall = semiring.times(pall, p)
|
|
221
|
+
else:
|
|
222
|
+
pall = semiring.plus(pall, p)
|
|
223
|
+
yield pall
|
|
224
|
+
|
|
225
|
+
def wmc(self, node, weights, semiring):
|
|
226
|
+
pall = semiring.zero()
|
|
227
|
+
|
|
228
|
+
expr, _ = self._parse_expr(node.to_expr())
|
|
229
|
+
|
|
230
|
+
for prob in self._enum_paths(expr, weights, semiring):
|
|
231
|
+
pall = semiring.plus(prob, pall)
|
|
232
|
+
return pall
|
|
233
|
+
|
|
234
|
+
def wmc_literal(self, node, weights, semiring, literal):
|
|
235
|
+
raise NotImplementedError("not supported")
|
|
236
|
+
|
|
237
|
+
def wmc_true(self, weights, semiring):
|
|
238
|
+
return semiring.one()
|
|
239
|
+
|
|
240
|
+
def __del__(self):
|
|
241
|
+
pass
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
@transform(LogicDAG, BDD)
|
|
245
|
+
def build_bdd(source, destination, **kwdargs):
|
|
246
|
+
"""Build an SDD from another formula.
|
|
247
|
+
|
|
248
|
+
:param source: source formula
|
|
249
|
+
:param destination: destination formula
|
|
250
|
+
:param kwdargs: extra arguments
|
|
251
|
+
:return: destination
|
|
252
|
+
"""
|
|
253
|
+
return build_dd(source, destination, **kwdargs)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#! /bin/bash
|
|
2
|
+
|
|
3
|
+
# To start using:
|
|
4
|
+
# - Install wine
|
|
5
|
+
# For example using HomeBrew:
|
|
6
|
+
# brew install wine
|
|
7
|
+
# ProbLog expects `wine` to be available on the PATH.
|
|
8
|
+
# - Download c2d_windows.exe and rename it to cnf2dDNNF.exe
|
|
9
|
+
# see http://reasoning.cs.ucla.edu/c2d/
|
|
10
|
+
# - Rename this file to 'cnf2dDNNF' to activate
|
|
11
|
+
|
|
12
|
+
wine ${BASH_SOURCE[0]}.exe $*
|
|
Binary file
|
problog/bin/linux/dsharp
ADDED
|
Binary file
|
|
Binary file
|