【问题标题】:using operator across modules in swi-prolog在 swi-prolog 中跨模块使用运算符
【发布时间】:2013-09-03 00:20:39
【问题描述】:

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

我有一个“主”文件 (ch20.pl),我通过键入以下内容从 swi-prolog 交互式加载:

[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...

请注意,我使用

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 文档,而且很难用 google 找到示例..

【问题讨论】:

  • 您可以(或者)将(&lt;-)/2 谓词声明为位于user 伪模块中的多文件谓词,并且您的其他模块为此多文件谓词提供子句。只需调整 Carlo 的答案以使用 :- multifile user:(&lt;-)/2.。但他的原始解决方案的一个(封装)优点是,(&lt;-)/2 谓词仅在您加载导出它的模块(到user)时才在不合格的user 中可见。
  • 尝试使用 www SymbolHound dot com 进行符号搜索。

标签: prolog swi-prolog


【解决方案1】:

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

恕我直言,您的问题源于对构造的过多期望,它做了一些简单的事情,但产生了复杂的后果,因为它改变了语言元素的一个基本属性:原子,当用作 谓词标识符 ,成为对 Module:Name,其中 Module 被称为 context(嗯,有点……我希望有人能通过更准确的措辞和参考资料来帮助理解这个重要的主题)。


为了简化您的问题,让我们将 (

:- 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)), !.
...

我们从 topline 得到预期的结果

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

注意 ch20_utils 中的声明(eval 首次出现的地方):

:- multifile eval/2.

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

注意,我将最后一个子句从 ch20_utils 移到了 ch20_Ires。这是必需的,因为该子句是“笼统”规则,因此禁止检查 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.

【讨论】:

  • 非常感谢...我觉得我必须一直写 'ch20_utils:' 有点烦人,但我可以忍受 :).. 你能解释一下什么是再导出做? (swi-prolog doc,无法让我再次理解它..)
  • 这是一种快捷方式,可以一次导入和导出所有导入的符号。由于 op/3 声明,在我们的例子中很方便,在任何地方复制都相当冗长......
猜你喜欢
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 2017-03-11
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
相关资源
最近更新 更多