什么是Prolog运算符^?

时间:2013-11-12 14:26:59

标签: lambda prolog exponentiation iso-prolog prolog-setof

什么是Prolog运算符^?

查看The Prolog Built-in Directive op会给出一个内置运算符列表。

我看到了 取指数是指数 / \是或

但是^是什么?

目前三个答案中的每一个都是有价值的,我学到了一些东西:

  • 罗伊为这本书
  • false为示例
  • 我接受了CapelliC的回答,因为它明确表示^ / 2有多重含义 视情况而定,这可以立即消除我的困惑。

4 个答案:

答案 0 :(得分:7)

运营商(^)/2有多种用途:

setof/3bagof/3

这里它用于表示术语存在变量(集合)。像 setof(Ch, P^child_of(Ch,P), Chs)其中P被声明为存在变量。

作为对此的非标准副作用,许多系统已将其定义为具有以下定义的谓词:

_^Goal :- Goal

但是,其他人没有这样的定义。无论如何,避免定义谓词(^)/2是个好主意。

(^)/2 - 权力

这是一个可评估的仿函数,可通过(is)/2(=:=)/2(>)/2等算术比较访问。 library(clpfd)也使用了这个含义。与始终导致浮点数的(**)/2形成对比,2^2是一个整数 - 从而允许具有bigint的算术。只需尝试?- X is 7^7^7.,看看您的系统是否支持它们。

最后,(^)/2的用户定义用途不会与library(lambda)source)的lambda表达式等上述用途发生冲突。


关于其使用,有一些一般性的评论。 (^)/2与权利相关联,这意味着: (7^7^7) = (7^(7^7))。它具有非常低的优先级,这意味着您必须使用括号作为标准运算符的参数。

答案 1 :(得分:3)

在数学表达式中,^是取幂,它只是**的不同符号。

在lambda表达式中,它是一个参数传递运算符。

如Pereira和Shieber的书:

因此lambda表达式为λx。 x + 1将在Prolog中编码为X ^(X + 1)。类似地,λ表达式λx。 λy.wrote(y,x)将被编码为Prolog术语X ^ Y ^写(Y,X),假设“^”的正确关联

答案 2 :(得分:3)

在Prolog中,大多数符号可以在句法层面上使用“未解释”,特别是在op / 3声明之后,任何原子都可以用作运算符。然后,您可以使用^ / 2作为域特定语言(DSL)的函数构造函数,并使用从规则中指定的语义。

是SWI-Prolog(或更常见的是ISO Prolog),current_op / 3为您提供有关已声明运算符的信息:

?- current_op(X,Y,^).
X = 200,
Y = xfy. 

也就是说,任何实现setof / 3的Prolog,当用于装饰2°参数时,预计会将^ / 2解释为量化说明符。同样,任何Prolog实现是/ 2,预期将^ / 2解释为取幂,当发生时是is / 2表达式的右侧。

答案 3 :(得分:1)

这是我在^setof/3中使用bagof/3的补充。

前记

就我个人而言,我认为^的语义是失败的,因为它看起来 好像是“存在的量化”,有时甚至被描述为这样(例如: GNU PrologSWI-Prolog library(yall)),但实际上是避免此功能,请写一个单独的谓词,以setof/3bagof/3来代替。如果发生了ISO Prolog-2,应该对其进行清理。

我们从ASCII图像概述开始:

                                 Clause-wide variable
                                         |
                                         |
                +------------------------+------------------------+
                |                                                 |
                |          Clause-wide variables                  |
                |          that are collected via the             |
                |          template at arg-position 1 by          |
                |          setof/3 (NOT local to setof/3)         |
                |          thus can be constrained elsewhere      |
                |          in the clause (possibly accidentally)  |
                |                           |                     |
                |                           |                     |                
                |                +-+--------+----------+-+        |
                |                | |                   | |        |
                |                | |                   | |        |            
get_closed_set(Set,K) :- setof( [X,Y] , P^R^search(P,R,X,Y,K) , Set).
                   |                    | |        | |     |
                   |                    <-------------------> Goal expression 
                   |                    | |        | |     |
                   |                    | |        | |     |                   
                   +---------------------------------------+-----+                    
                                        | |        | |           |
                                        | |        | |           |
                                        +-+----+---+-+          Clause-wide variable.
                                               |                Backtracking over this
                                               |                is done by the caller
                                               |                of get_closed_set/2.
                                               |
                                       Variables marked as "free for
                                       backtracking if fresh".
                                       This is NEARLY the same as "being
                                       local to the goal expression" or
                                       "being existentially quantified."
                                       Backtracking over these is done by setof/3.
                                       If these appear elsewhere in the clause,
                                       they be constrained (possibly accidentally)!

预期行为的测试用例

search(1,n,a,g).
search(2,m,a,g).

search(2,m,a,j).
search(1,m,a,j).
search(3,w,a,j).
search(3,v,a,j).

search(2,v,b,g).
search(3,m,b,g).
search(5,m,b,g).

search(2,w,b,h).


% ===
% HATTY EXPRESSIONS ("CLOSED EXPRESSIONS")
% ===

% If P and R do not appear anywhere else than in the goal expression.
% "P^R^" (not quite) closes off variables P,R: they are not (not quite) 
% invisible outside of the goal expression "P^R^search(P,R,X,Y)"

get_closed_set(Set) :- setof( [X,Y] , P^R^search(P,R,X,Y) , Set).
get_closed_bag(Bag) :- bagof( [X,Y] , P^R^search(P,R,X,Y) , Bag).

% The above is the same as this (which I recommend for clarity and
% to avoid annoying bug searches):

indirect_search(X,Y) :- search(_P,_R,X,Y).

get_closed_set_indirect(Set) :- setof( [X,Y] , indirect_search(X,Y) , Set).
get_closed_bag_indirect(Bag) :- bagof( [X,Y] , indirect_search(X,Y) , Bag).

% ===
% NONHATTY EXPRESSIONS ("OPEN EXPRESSIONS")
% ===

get_open_set(Set,P,R) :- setof( [X,Y] , search(P,R,X,Y) , Set).
get_open_bag(Bag,P,R) :- bagof( [X,Y] , search(P,R,X,Y) , Bag).

% ===
% TESTING
% ===

:- begin_tests(hat_operator).

test(clo_set)     :- get_closed_set(Set),
                     format("Closed Set:\n  ~q\n",[Set]),
                     Set = [[a,g],[a,j],[b,g],[b,h]].

test(clo_bag)     :- get_closed_bag(Bag),
                     format("Closed Bag:\n  ~q\n",[Bag]),
                     Bag = [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j],[b,g],[b,g],[b,g],[b,h]].

test(clo_set_ind) :- get_closed_set_indirect(Set),
                     format("Closed Set, indirect:\n  ~q\n",[Set]),
                     Set = [[a,g],[a,j],[b,g],[b,h]].

test(clo_bag_ind) :- get_closed_bag_indirect(Bag),
                     format("Closed Bag, indirect:\n  ~q\n",[Bag]),
                     Bag = [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j],[b,g],[b,g],[b,g],[b,h]].

test(opn_set)     :- bagof(solution(Set,P,R), get_open_set(Set,P,R), OuterBag),
                     format("Bag for get_open_set/3:\n  ~q\n",[OuterBag]).

test(opn_bag)     :- bagof(solution(Bag,P,R), get_open_bag(Bag,P,R), OuterBag),
                     format("Bag for get_open_bag/3:\n  ~q\n",[OuterBag]).

:- end_tests(hat_operator).

rt :- run_tests(hat_operator).

运行rt时,不会发生任何意外情况,就像具有存在量词的Fonzi:

Closed Set:            [[a,g],[a,j],[b,g],[b,h]]

Closed Bag:            [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j], 
                        [b,g],[b,g],[b,g],[b,h]]

Closed Set, indirect:  [[a,g],[a,j],[b,g],[b,h]]

Closed Bag, indirect:  [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j],
                        [b,g],[b,g],[b,g],[b,h]]

Bag for get_open_set/3:  [solution([[a,j]],1,m),solution([[a,g]],1,n),
                          solution([[a,g],[a,j]],2,m),solution([[b,g]],2,v),
                          solution([[b,h]],2,w),solution([[b,g]],3,m),
                          solution([[a,j]],3,v),solution([[a,j]],3,w),
                          solution([[b,g]],5,m)]

Bag for get_open_bag/3:  [solution([[a,j]],1,m),solution([[a,g]],1,n),
                          solution([[a,g],[a,j]],2,m),solution([[b,g]],2,v),
                          solution([[b,h]],2,w),solution([[b,g]],3,m),
                          solution([[a,j]],3,v),solution([[a,j]],3,w),
                          solution([[b,g]],5,m)]

尝试减少不太明显的表情的行为

您可能必须运行此命令才能查看更多列表输出(以SWI-Prolog为例):

set_prolog_flag(answer_write_options,[max_depth(100)]).
set_prolog_flag(debugger_write_options,[max_depth(100)]).

目标表达中的字母

如果输入以下内容,则Prolog会正确警告“单个变量P,R”。好。

get_open_set(Set) :- setof([X,Y],search(P,R,X,Y),Set).

超出setof / 3或bagof / 3的范围

这是可以接受的,并且可以赋予其含义,但是Prolog将在调用时寻找过程^/2,并说“ ^ / 2只能作为setof / 3和bagof的第二个参数出现/ 3“ 。好吧。

get_outerly_closed_set(Set) :- P^R^setof([X,Y],search(P,R,X,Y),Set).

上面所说的可能是完全平凡的东西:

get_outerly_closed_set(Set) :- close_it_off(Set).
close_it_off(Set) :- setof([X,Y],search(_P,X,_R,Y),Set).

子句中其他地方使用的封闭变量:有问题!

现在,我们进入“语义失败”领域:Prolog并未将外部P视为与P中的P^不同的变量。这就是为什么P^不表示“∃P这样的”

get_closed_set_weird_1(Set,P) :- 
   setof( [X,Y] , P^R^search(P,R,X,Y) , Set),
   format("P=~q\n",[P]).
?- get_closed_set_weird_1(Set,P).
P=_14996
Set = [[a, g], [a, j], [b, g], [b, h]].

?- get_closed_set_weird_1(Set,1).
P=1
Set = [[a, g], [a, j]].

子句中其他位置使用的封闭变量的变化:有问题!

如果您写这样的东西,则不会出现警告:

get_closed_set_weird_2(Set) :-
   setof( [X,Y,P], P^R^search(P,R,X,Y), Set).
?- get_closed_set_weird_2(Set).
Set = [[a, g, 1], [a, g, 2], [a, j, 1], [a, j, 2], [a, j, 3], ...

实际上,P^最终被忽略了。上面的和:

get_closed_set_weird_2e(Set) :-
   setof( [X,Y,P], R^search(P,R,X,Y), Set).

在子句中其他位置使用的自由变量,范围超过问题!

这完全是预期的行为,但是对setof([X,Y], ...的随意阅读会导致人们认为[X,Y]setof/3范围内的自由变量。事实并非如此:[X,Y]只是一个模板,而XY实际上是整个子句范围的变量,可以在其他地方进行约束:

get_closed_set_weird_2(Set,X) :- 
   setof( [X,Y], P^R^search(P,R,X,Y) , Set),
   format("X=~q\n",[X]).
?- get_closed_set_weird_2(Set,X).
X=_20346
Set = [[a, g], [a, j], [b, g], [b, h]].

?- get_closed_set_weird_2(Set,b).
X=b
Set = [[b, g], [b, h]].

上面的内容会更清楚

get_closed_set_weird_2c(Set,V) :- 
   setof( [V,Y], close_it_off(V,Y), Set),
   format("V=~q\n",[V]).
close_it_off(X,Y) :- search(_P,_R,X,Y).
?- get_closed_set_weird_2c(Set,V).
V=_21682
Set = [[a, g], [a, j], [b, g], [b, h]].

但是请注意,这与我们在V之外的setof/3上回溯的绝对不同:

get_closed_set_weird_2x(Set,V) :- 
   setof( [X,Y], close_it_off(V,X,Y), Set),
   format("V=~q\n",[V]).
close_it_off(V,X,Y) :- V=X,search(_P,_R,X,Y).
?- get_closed_set_weird_2x(Set,V).
V=a
Set = [[a, g], [a, j]], V = a ;
V=b
Set = [[b, g], [b, h]], V = b.

应该有可接受的符号

一个人希望有一种干净的方法来指示目标表达式的哪些变量在目标表达式之外是可见的,哪些不是,以及哪些在范围内。

如何?

  • 如果目标表达式的开头有λX.,则X在目标表达式之外是可见的。子句中其他任何地方的X都是相同的X
  • 如果目标表达式的开头有∃X.,则X在目标表达式之外是不可见的。子句中其他地方的任何X都是不同的X(然后,编辑者会邀请您继续进行重命名)。
  • 出现在目标表达式中而没有前面的XλX.的任何∃X.都是编译器错误
  • 您可以将所需的任何内容(lambda或存在的或子句全局的)放入模板中。
  • 被调用的目标覆盖了它认为是新鲜的所有变量:显示为λX.的新鲜变量和显示为∃X.的任何变量

(不要抱怨上面的小写字母x;它看起来就是这样。λX. ∃X. Xx