对于 SWI-Prolog 的 CLP(B) 库,我想实现sat_count/2的加权版本
sat_count(Sat0, N) :-
catch((parse_sat(Sat0, Sat),
sat_bdd(Sat, BDD),
sat_roots(Sat, Roots),
roots_and(Roots, _-BDD, _-BDD1),
% we mark variables that occur in Sat0 as visited ...
term_variables(Sat0, Vs),
maplist(put_visited, Vs),
% ... so that they do not appear in Vs1 ...
bdd_variables(BDD1, Vs1),
partition(universal_var, Vs1, Univs, Exis),
% ... and then remove remaining variables:
foldl(universal, Univs, BDD1, BDD2),
foldl(existential, Exis, BDD2, BDD3),
variables_in_index_order(Vs, IVs),
foldl(renumber_variable, IVs, 1, VNum),
bdd_count(BDD3, VNum, Count0),
var_u(BDD3, VNum, P),
% Do not unify N directly, because we are not prepared
% for propagation here in case N is a CLP(B) variable.
N0 is 2^(P - 1)*Count0,
% reset all attributes and Aux variables
throw(count(N0))),
count(N0),
N = N0).
我没有找到用于修改代码的库的详细文档。如何实现 sat_count/2 的加权版本?
编辑 1(2017 年 1 月 11 日):
感谢@mat 的回复,我无法添加评论,因为我没有足够的声誉。
weighted_sat_count/3
应该采用一对权重列表,每个变量一个权重(True 的权重和 False 状态的权重),然后其他两个参数与sat_count/2
.
计数是每个可接受分配的权重之和。每个可接受分配的权重是每个变量权重的乘积。
计算结果的算法是:
bdd_weight(BDD_node)
if BDD_node is 1-terminal return 1
if BDD_node is 0-terminal return 0
t_child <- 1-child of BDD_node
f_child <- 0-child of BDD_node
return (weight[BDD_node, 1] * bdd_weight(t_child) + weight[BDD_node, 0] * bdd_weight(f_child))
使用与计算的权重相关联的访问节点的地图,该算法可以更有效。
weight[,]
是权重对的列表,1 表示 True,0 表示 False。
编辑 2(2017 年 3 月 11 日):
例如:
A+B+C,一个简单的SAT公式
权重对列表:[(0.7, 0.3), (0.9, 0.1), (0.5, 0.5)],每个变量一个
?- weighted_sat_count([(0.7, 0.3), (0.9, 0.1), (0.5, 0.5)], +([A, B, C]), Count).
Count =
0.7*0.9*0.5 +
0.3*0.9*0.5 +
0.7*0.1*0.5 +
...