你能用clpfd实现一个覆盖算法吗?
Can you use clpfd to implement a coverage algorithm?
假设我想找到以简单匹配方式区分两个类的features/attributes集合,我可以在序言中使用clpfd来做到这一点吗?
c_s_mining(Features,Value):-
Features = [F1,F2,F3,F4],
Features ins 0..1,
ExampleA = [A1,A2,A3,A4],
ExampleB =[B1,B2,B3,B4],
ExampleC =[C1,C2,C3,C4],
A1 #=0, A2#=1,A3#=0,A4#=1,
B1 #=0, B2#=1,B3#=0,B4#=1,
C1 #=1, C2#=0,C3#=0,C4#=1,
ExampleD =[D1,D2,D3,D4],
ExampleE =[E1,E2,E3,E4],
ExampleQ =[Q1,Q2,Q3,Q4],
D1#=1,D2#=0,D3#=1,D4#=0,
E1#=1,E2#=0,E3#=1,E4#=0,
Q1#=0,Q2#=1,Q3#=1,Q4#=0,
Positives =[ExampleA,ExampleB,ExampleC],
Negatives = [ExampleD,ExampleE,ExampleQ],
TP in 0..sup,
FP in 0..sup,
covers(Features,Positives,TP),
covers(Features,Negatives,FP),
Value in inf..sup,
Value #= TP-FP.
covers(Features,Examples,Number_covered):-
findall(*,(member(E,Examples),E=Features),Covers), length(Covers,Number_covered).
每个例子由四个二元特征描述,有三个正例(A,B,C)和三个负例(D,E,Q)。
如果匹配,则一个示例被一组选定的特征覆盖。
因此,例如,如果 Features
与 [0,1,0,1]
统一,那么这将匹配两个正数和 0 个负数。
我设置 Value
等于 TP
(真阳性)- TN
(真阴性)。我想最大化 Value 并找到相应的一组特征。
我查询?-c_s_mining(Features,Value),labelling([max(Value)],[Value]).
我期望的答案是:Features =[0,1,0,1], Value =2
但我得到 Features =[_G1,_G2,_G3,G4],Value =0, G1 in 0..1, G2 in 0..1, G3 in 0..1, G4 in 0..1.
CLP(FD) 约束的具体化
要推断什么匹配什么不匹配,请使用约束 具体化:它允许您将约束的真值反映到 CLP(FD) 变量中,表示布尔值。
您可以对这些值进行算术运算,以表示匹配示例的数量等。
例如,在你的情况下,你可以这样写:
:- use_module(library(clpfd)).
c_s_mining(Features, Value) :-
ExampleA = [0,1,0,1],
ExampleB = [0,1,0,1],
ExampleC = [1,0,0,1],
ExampleD = [1,0,1,0],
ExampleE = [1,0,1,0],
ExampleQ = [0,1,1,0],
same_length(Features, ExampleA),
Features ins 0..1,
Positives = [ExampleA,ExampleB,ExampleC],
Negatives = [ExampleD,ExampleE,ExampleQ],
covers_number(Features, Positives, TP),
covers_number(Features, Negatives, FP),
Value #= TP-FP.
covers_number(Features, Examples, Number):-
maplist(covers_(Features), Examples, Numbers),
sum(Numbers, #=, Number).
covers_([F1,F2,F3,F4], [E1,E2,E3,E4], Covered) :-
Covered #<==> (F1#=E1 #/\ F2#=E2 #/\ F3#=E3 #/\ F4#=E4).
然后使用labeling/2
的优化选项先取最大值:
?- c_s_mining(Fs, Value), labeling([max(Value)], Fs).
Fs = [0, 1, 0, 1],
Value = 2 ;
Fs = [1, 0, 0, 1],
Value = 1 ;
Fs = [0, 0, 0, 0],
Value = 0 ;
etc.
另请注意,我删除了一些多余的约束,例如 Value in inf..sup
,因为约束求解器可以自行计算出它们。
CLP(B):布尔约束的声明性替代方案
对于此类布尔模式的情况,另请查看 CLP(B): Constraint Logic Programming over Boolean variables,可用于SICStus Prolog 和 SWI 中的示例。使用 CLP(B) 需要您以稍微不同的方式制定搜索,因为它缺少 CLP(FD) 强大的标签选项。然而,与 CLP(FD) 相比,CLP(B) 是 完整的 ,并且可以更早地检测到不一致以及包含的约束。
在下面的代码中,我使用 CLP(FD) 来指导搜索最优值,然后使用 CLP(B) 来说明实际约束。 labeling/1
的最终调用(注意这是来自 library(clpb)
,不要与 CLP(FD) 的 labeling/2
混淆)用于确保所有 CLP(B) 的接地值变量。在它出现的时候,它在某种意义上只是一种形式:由于 CLP(B) 的完整性,我们已经知道此时有一个解决方案。
:- use_module(library(clpb)).
:- use_module(library(clpfd)).
c_s_mining(Features, Value):-
ExampleA = [0,1,0,1],
ExampleB = [0,1,0,1],
ExampleC = [1,0,0,1],
ExampleD = [1,0,1,0],
ExampleE = [1,0,1,0],
ExampleQ = [0,1,1,0],
same_length(Features, ExampleA),
Positives = [ExampleA,ExampleB,ExampleC],
Negatives = [ExampleD,ExampleE,ExampleQ],
[TP,FP] ins 0..3, % (in this case)
Value #= TP-FP,
labeling([max(Value)], [TP,FP]),
covers_number(Features, Positives, TP),
covers_number(Features, Negatives, FP),
labeling(Features).
covers_number(Features, Examples, Number):-
maplist(covers_(Features), Examples, Numbers),
sat(card([Number], Numbers)).
covers_([F1,F2,F3,F4], [E1,E2,E3,E4], Covered) :-
sat(Covered =:= ((F1=:=E1)*(F2=:=E2)*(F3=:=E3)*(F4=:=E4))).
假设我想找到以简单匹配方式区分两个类的features/attributes集合,我可以在序言中使用clpfd来做到这一点吗?
c_s_mining(Features,Value):-
Features = [F1,F2,F3,F4],
Features ins 0..1,
ExampleA = [A1,A2,A3,A4],
ExampleB =[B1,B2,B3,B4],
ExampleC =[C1,C2,C3,C4],
A1 #=0, A2#=1,A3#=0,A4#=1,
B1 #=0, B2#=1,B3#=0,B4#=1,
C1 #=1, C2#=0,C3#=0,C4#=1,
ExampleD =[D1,D2,D3,D4],
ExampleE =[E1,E2,E3,E4],
ExampleQ =[Q1,Q2,Q3,Q4],
D1#=1,D2#=0,D3#=1,D4#=0,
E1#=1,E2#=0,E3#=1,E4#=0,
Q1#=0,Q2#=1,Q3#=1,Q4#=0,
Positives =[ExampleA,ExampleB,ExampleC],
Negatives = [ExampleD,ExampleE,ExampleQ],
TP in 0..sup,
FP in 0..sup,
covers(Features,Positives,TP),
covers(Features,Negatives,FP),
Value in inf..sup,
Value #= TP-FP.
covers(Features,Examples,Number_covered):-
findall(*,(member(E,Examples),E=Features),Covers), length(Covers,Number_covered).
每个例子由四个二元特征描述,有三个正例(A,B,C)和三个负例(D,E,Q)。
如果匹配,则一个示例被一组选定的特征覆盖。
因此,例如,如果 Features
与 [0,1,0,1]
统一,那么这将匹配两个正数和 0 个负数。
我设置 Value
等于 TP
(真阳性)- TN
(真阴性)。我想最大化 Value 并找到相应的一组特征。
我查询?-c_s_mining(Features,Value),labelling([max(Value)],[Value]).
我期望的答案是:Features =[0,1,0,1], Value =2
但我得到 Features =[_G1,_G2,_G3,G4],Value =0, G1 in 0..1, G2 in 0..1, G3 in 0..1, G4 in 0..1.
CLP(FD) 约束的具体化
要推断什么匹配什么不匹配,请使用约束 具体化:它允许您将约束的真值反映到 CLP(FD) 变量中,表示布尔值。
您可以对这些值进行算术运算,以表示匹配示例的数量等。
例如,在你的情况下,你可以这样写:
:- use_module(library(clpfd)).
c_s_mining(Features, Value) :-
ExampleA = [0,1,0,1],
ExampleB = [0,1,0,1],
ExampleC = [1,0,0,1],
ExampleD = [1,0,1,0],
ExampleE = [1,0,1,0],
ExampleQ = [0,1,1,0],
same_length(Features, ExampleA),
Features ins 0..1,
Positives = [ExampleA,ExampleB,ExampleC],
Negatives = [ExampleD,ExampleE,ExampleQ],
covers_number(Features, Positives, TP),
covers_number(Features, Negatives, FP),
Value #= TP-FP.
covers_number(Features, Examples, Number):-
maplist(covers_(Features), Examples, Numbers),
sum(Numbers, #=, Number).
covers_([F1,F2,F3,F4], [E1,E2,E3,E4], Covered) :-
Covered #<==> (F1#=E1 #/\ F2#=E2 #/\ F3#=E3 #/\ F4#=E4).
然后使用labeling/2
的优化选项先取最大值:
?- c_s_mining(Fs, Value), labeling([max(Value)], Fs). Fs = [0, 1, 0, 1], Value = 2 ; Fs = [1, 0, 0, 1], Value = 1 ; Fs = [0, 0, 0, 0], Value = 0 ; etc.
另请注意,我删除了一些多余的约束,例如 Value in inf..sup
,因为约束求解器可以自行计算出它们。
CLP(B):布尔约束的声明性替代方案
对于此类布尔模式的情况,另请查看 CLP(B): Constraint Logic Programming over Boolean variables,可用于SICStus Prolog 和 SWI 中的示例。使用 CLP(B) 需要您以稍微不同的方式制定搜索,因为它缺少 CLP(FD) 强大的标签选项。然而,与 CLP(FD) 相比,CLP(B) 是 完整的 ,并且可以更早地检测到不一致以及包含的约束。
在下面的代码中,我使用 CLP(FD) 来指导搜索最优值,然后使用 CLP(B) 来说明实际约束。 labeling/1
的最终调用(注意这是来自 library(clpb)
,不要与 CLP(FD) 的 labeling/2
混淆)用于确保所有 CLP(B) 的接地值变量。在它出现的时候,它在某种意义上只是一种形式:由于 CLP(B) 的完整性,我们已经知道此时有一个解决方案。
:- use_module(library(clpb)).
:- use_module(library(clpfd)).
c_s_mining(Features, Value):-
ExampleA = [0,1,0,1],
ExampleB = [0,1,0,1],
ExampleC = [1,0,0,1],
ExampleD = [1,0,1,0],
ExampleE = [1,0,1,0],
ExampleQ = [0,1,1,0],
same_length(Features, ExampleA),
Positives = [ExampleA,ExampleB,ExampleC],
Negatives = [ExampleD,ExampleE,ExampleQ],
[TP,FP] ins 0..3, % (in this case)
Value #= TP-FP,
labeling([max(Value)], [TP,FP]),
covers_number(Features, Positives, TP),
covers_number(Features, Negatives, FP),
labeling(Features).
covers_number(Features, Examples, Number):-
maplist(covers_(Features), Examples, Numbers),
sat(card([Number], Numbers)).
covers_([F1,F2,F3,F4], [E1,E2,E3,E4], Covered) :-
sat(Covered =:= ((F1=:=E1)*(F2=:=E2)*(F3=:=E3)*(F4=:=E4))).