【问题标题】:Can you use clpfd to implement a coverage algorithm?您可以使用 clpfd 来实现覆盖算法吗?
【发布时间】:2016-07-03 17:58:34
【问题描述】:

假设我想以简单的匹配方式找到区分两个类的一组特征/属性,我可以在 prolog 中使用 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(真阴性)。我想最大化价值并找到相应的特征集。

我查询?-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.

【问题讨论】:

  • findall(*) 不会像你期望的那样......
  • 怎么样? Covers/3 按我的意图工作,星号只是为了计算功能与示例结合的次数..
  • 星号可以直接换成E,我觉得不会有影响吧?
  • 问题是 findall 中隐含的变量的复制,而不是星号

标签: prolog swi-prolog clpfd prolog-findall


【解决方案1】:

CLP(FD) 约束的具体化

要推断什么匹配什么不匹配,请使用约束reification:它允许您将约束的真值反映到表示布尔值的 CLP(FD) 变量中。 p>

您可以使用这些值进行算术运算以表示匹配示例的数量等。

例如,在你的情况下,你可以写:

:- 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], 值 = 2 ; Fs = [1, 0, 0, 1], 值 = 1; Fs = [0, 0, 0, 0], 值 = 0 ; 等等

还请注意,我已经删除了一些多余的约束,例如 Value in inf..sup,因为约束求解器可以自己解决它们。


CLP(B):布尔约束的声明性替代方案

对于这种布尔模式,还可以查看 CLP(B):Boolean 变量上的约束逻辑编程,例如在 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))).

【讨论】:

  • 谢谢,太好了。一件事,是否也可以返回诸如 Fs =[0,X,0,1], X in 0..1, Value =3 之类的结果。以便匹配有变量?
  • 我的意思是 Fs =[Y,X,0,1] 在这种情况下。
  • 您当然可以在查询中使用部分实例化的模式,例如:?- c_s_mining([0,X,0,1], V).。在这个具体的例子中,这会产生两个解决方案,其值取决于X 是否为 1。所以,一般来说,不可能为V 提供单一的解决方案,因为它取决于具体的功能。对于Fs = [X,X,0,1],CLP(B) 版本执行您想要的操作:?- c_s_mining([X,X,0,1], V). 产生:V = 0,并将 X 约束为布尔值而不实例化它。
  • 我希望 c_s_mining([X,X,0,1],V) 产生 V =3 而不是 V= 0,因为 [X,X,0,1] 与三个正数相结合例子,但没有负面的例子..
  • [X,X|_] 表示前2个元素相同的列表,无论正负都没有这样的例子。
猜你喜欢
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 2014-05-06
  • 2012-11-05
  • 2014-08-13
  • 2011-05-27
相关资源
最近更新 更多