在swi-prolog中跨模块使用运算符

时间:2013-09-03 00:20:40

标签: prolog swi-prolog

我目前正试图弄清楚如何在swi-prolog中使用相同的运算符及其相关谓词。

我有一个'main'文件(ch20.pl),我通过键入以下内容从swi-prolog interactive中加载:

[ch20].

ch20.pl 目前包含:

:- use_module(ch20_examples).
:- use_module(ch20_Ires).

ch20_examples.pl:

:- module(ch20_examples, [example/2, attribute/2]).

attribute(size, [small, large]).
attribute(shape, [long, compact, other]).
attribute(holes, [none, 1, 2, 3, many]).

example(nut, [size=small, shape=compact, holes=1]).
example(screw, [size=small, shape=long, holes=none]).
example(key, [size=small, shape=long, holes=1]).
example(nut, [size=small, shape=compact, holes=1]).
example(key, [size=large, shape=long, holes=1]).
example(screw, [size=small, shape=compact, holes=none]).
example(nut, [size=small, shape=compact, holes=1]).
example(pen, [size=large, shape=long, holes=none]).
example(scissors, [size=large, shape=long, holes=2]).
example(pen, [size=large, shape=long, holes=none]).
example(scissors, [size=large, shape=other, holes=2]).
example(key, [size=small, shape=other, holes=2]).

ch20_Ires.pl:

:- module(ch20_Ires,
            [   op(900, xfy, <-),
                (<-)/2
            ]).
:- use_module(ch20_utils).

R <- residual_info(Attribute) :-
    findall(X, (example(_, Attributes), member(Attribute=X, Attributes)), Values),
    list_to_set(Values, Values_set),
    setof(Class, Class^Attr^example(Class,Attr), Classes_set),
    Values_prob_sum <- sum_list(Values_set, value_prob(Values, Classes_set, Attribute)),
    R <- -Values_prob_sum, !.

R <- value_prob(Values, Classes_set, Attr, Val) :-
    include(==(Val), Values, Value_count_list),
    Value_count_n <- len(Value_count_list),
    Values_n <- len(Values),
    Val_prob <- Value_count_n / Values_n, 
    R <- Val_prob * sum_list(Classes_set, cond_prob(Attr, Val)), !.

R <- cond_prob(Attr, Val, Class) :-
    findall(_, (example(Class, Class_FeatureList), member(Attr=Val, Class_FeatureList)) , Class_list),
    Class_n <- len(Class_list),
    findall(_, (example(_, FeatureList), member(Attr=Val, FeatureList)), Feature_count_list),
    Feature_count <- len(Feature_count_list),
    (Class_n > 0, Cond_prob <- Class_n / Feature_count, R <- Cond_prob * log2(Cond_prob)
    ;
    R <- 0), !.

ch20_utils.pl:

:- module(ch20_utils,
            [   op(900, xfy, <-),
                (<-)/2
            ]).

R <- log2(X) :- R <- log(X) / log(2), !.
R <- len(L) :- length(L, R), !.
Sum <- sum_list([], _) :- Sum <- 0.
Sum <- sum_list([H|T], Func) :- 
    New_sum <- sum_list(T, Func), 
    !, Func =..Func_list, 
    append(Func_list,[H],Apply_func_list),
    Apply_func =..Apply_func_list,
    Sum <- New_sum + Apply_func.

R <- X :- compound(X), X =..[OP,X2,X3], R2 <- X2, R3 <- X3, Expr =..[OP,R2,R3], R is Expr, !.
R <- X :- R is X, !.

我目前的目标是能够评估:

?- X <- residual_info(size).

但它只是通过上面的设置返回false ...

请注意,我正在使用&lt; - 运算符来尝试使代码更具可读性,并且能够评估以下化合物:

X <- 18*log2(19)-5.

但这也意味着我的代码非常依赖于该部分:

R <- X :- compound(X), X =..[OP,X2,X3], R2 <- X2, R3 <- X3, Expr =..[OP,R2,R3], R is Expr, !.
R <- X :- R is X, !.

我试过搞乱多文件谓词,但我不认为我理解如何使用它。

但是,如果ch20_Ires.pl文件更改为:

:- module(ch20_Ires,
            [   op(900, xfy, <-),
                (<-)/2
            ]).
 R <- log2(X) :- R <- log(X) / log(2), !.
 R <- len(L) :- length(L, R), !.
 Sum <- sum_list([], _) :- Sum <- 0.
 Sum <- sum_list([H|T], Func) :- 
     New_sum <- sum_list(T, Func), 
     !, Func =..Func_list, 
     append(Func_list,[H],Apply_func_list), 
     Apply_func =..Apply_func_list, 
     Sum <- New_sum + Apply_func.

R <- residual_info(Attribute) :-
    findall(X, (example(_, Attributes), member(Attribute=X, Attributes)), Values),
    list_to_set(Values, Values_set),
    setof(Class, Class^Attr^example(Class,Attr), Classes_set),
    Values_prob_sum <- sum_list(Values_set, value_prob(Values, Classes_set, Attribute)),
    R <- -Values_prob_sum, !.

R <- value_prob(Values, Classes_set, Attr, Val) :-
    include(==(Val), Values, Value_count_list),
    Value_count_n <- len(Value_count_list),
    Values_n <- len(Values),
    Val_prob <- Value_count_n / Values_n,
    R <- Val_prob * sum_list(Classes_set, cond_prob(Attr, Val)), !.

R <- cond_prob(Attr, Val, Class) :-
    findall(_, (example(Class, Class_FeatureList), member(Attr=Val, Class_FeatureList)) , Class_list),
    Class_n <- len(Class_list),
    findall(_, (example(_, FeatureList), member(Attr=Val, FeatureList)), Feature_count_list),
    Feature_count <- len(Feature_count_list),
    (Class_n > 0, Cond_prob <- Class_n / Feature_count, R <- Cond_prob * log2(Cond_prob)
    ;
    R <- 0), !.

R <- X :- compound(X), X =..[OP,X2,X3], R2 <- X2, R3 <- X3, Expr =..[OP,R2,R3], R is Expr, !.
R <- X :- R is X, !.

一切正常,我可以实现我的目标:

?- X <- residual_info(size).
X = 1.5421864522230475.

但我真的想将我的逻辑分成更多的模块,而不是将所有内容都放在一个文件中。我希望能够使用这个模块应该提供的公共/私有系统。

我可以在代码中重新排列,或者我可以用这个多文件谓词以某种方式解决我的问题吗?

在旁注中,是否存在任何教授诸如使用模块和其他高级prolog技术之类的书籍?因为我发现很难使用swi-prolog文档,很难找到谷歌的例子..

1 个答案:

答案 0 :(得分:3)

模块是Prolog标准化中最具争议的问题之一。 然后很难找到有关该主题和示例的连贯信息。

恕我直言你的问题源于对构造的过多期望,它做了一些简单的事情,但结果复杂,因为它改变了语言元素的一个基本属性:atoms,当用作谓词标识符成为对模块:名称,其中模块被称为上下文(好吧,有点......我希望有人能用更准确的措辞和参考文献来帮助理解这个重要的主题)。


为了简化您的问题,让我们将(&lt; - )/ 2重命名为eval / 2。然后

:- module(ch20_Ires, []).
:- reexport([ch20_utils, ch20_examples]).

ch20_utils:eval(R, residual_info(Attribute)) :-
    findall(X, (example(_, Attributes), member(Attribute=X, Attributes)), Values),
    list_to_set(Values, Values_set),
    setof(Class, Class^Attr^example(Class,Attr), Classes_set),
    eval(Values_prob_sum, sum_list(Values_set, value_prob(Values, Classes_set, Attribute))),
    eval(R, -Values_prob_sum), !.
...    
% note: moved here from ch20_utils
ch20_utils:eval(R, X) :- R is X, !.

:- module(ch20_utils, [ eval/2 ]).
:- multifile eval/2.

eval(R, log2(X)) :- eval(R, log(X) / log(2)), !.
...

我们从顶线获得预期结果

17 ?- eval(X, residual_info(size)).
X = 1.5421864522230475.

请注意ch20_utils中的声明(首先看到eval):

:- multifile eval/2.

允许继续某些其他模块中的定义需要使用ch20_utils标识符限定其他定义。然后递归调用将有机会找到这些定义。

注意我将最后一个子句从ch20_utils移到了ch20_Ires。这是必需的,因为该子句是一个'catchall'规则,因此禁止检查ch20_Ires子句:实际上,我得到了

12 ?- eval(X, residual_info(size)).
ERROR: is/2: Arithmetic: `size/0' is not a function

在移动条款之前......


现在,回到原来的问题,因为你知道运算符只是语法糖:

:- module(ch20_Ires, []).
:- reexport([ch20_utils, ch20_examples]).

ch20_utils:(R <- residual_info(Attribute)) :-
    findall(X, (example(_, Attributes), member(Attribute=X, Attributes)), Values),
    list_to_set(Values, Values_set),
    setof(Class, Class^Attr^example(Class,Attr), Classes_set),
    Values_prob_sum <- sum_list(Values_set, value_prob(Values, Classes_set, Attribute)),
    R <- -Values_prob_sum, !.

...

% note: moved here from ch20_utils
ch20_utils:(R <- X) :- R is X, !.

:- module(ch20_utils,
            [ op(900, xfy, <-),
                (<-)/2
        ]).

:- multifile (<-)/2.

R <- log2(X) :- R <- log(X) / log(2), !.
R <- len(L) :- length(L, R), !.
Sum <- sum_list([], _) :- Sum <- 0.
Sum <- sum_list([H|T], Func) :-
    New_sum <- sum_list(T, Func),
    !, Func =..Func_list,
    append(Func_list,[H],Apply_func_list),
    Apply_func =..Apply_func_list,
    Sum <- New_sum + Apply_func.

R <- X :- compound(X), X =..[OP,X2,X3], R2 <- X2, R3 <- X3, Expr =.. [OP,R2,R3], R is Expr, !.

% R <- X :- R is X, !.

似乎解决了语法问题:

20 ?- X <- residual_info(size).
X = 1.5421864522230475.