Что такое оператор Пролога `^` (каретка)?

Что такое оператор Пролога ^?

Глядя на встроенную директиву Prolog op дает список встроенных операторов.

я понимаю

  • ** – это возведение в степень
  • /\ is or

но что такое ^?

Каждый из трех текущих ответов имеет ценность, и я кое-чему научился:

  • Рой за книгу
  • неверно для примеров
  • Я принял ответ CapelliC, потому что он ясно дал понять, что ^/2 имеет несколько значений
    в зависимости от контекста, что мгновенно прояснило мою путаницу.

person Guy Coder    schedule 12.11.2013    source источник
comment
Обратите внимание, что операторы, указанные вами в приведенной выше ссылке, отличаются как от стандартного, так и от SWI! Они устарели минимум на 10 лет. Например, это должно быть current_op(200,fy,-).   -  person false    schedule 12.11.2013
comment
На самом деле он называется Caret.   -  person David Tonhofer    schedule 15.04.2020


Ответы (4)


В Прологе большинство символов можно использовать «неинтерпретируемо» на синтаксическом уровне, в частности, после объявления op/3 любой атом может использоваться как оператор. Затем вы можете использовать, например, ^/2 в качестве конструктора функций для предметно-ориентированного языка (DSL) с семантикой, указанной в ваших правилах.

В SWI-Prolog (или, в более общем случае, в ISO Prolog), current_op/3 дает вам информацию об объявленных операторах:

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

Тем не менее, ожидается, что любой Пролог, реализующий setof/3, будет интерпретировать ^/2 как спецификатор квантификации, когда он помещается для украшения 2nd аргумента. Кроме того, ожидается, что любой Пролог, реализующий is/2, будет интерпретировать ^/2 как возведение в степень, когда оно встречается в правой части выражения is/2.

person CapelliC    schedule 12.11.2013
comment
Таким образом, семантическое значение ^/2 может меняться в одном и том же Прологе в зависимости от связанного контекста, например. либо есть/2, либо setof/3? - person Guy Coder; 12.11.2013

Оператор (^)/2 служит нескольким целям:

setof/3, bagof/3

Здесь он используется для обозначения экзистенциальных переменных (множества) термина. Как в setof(Ch, P^child_of(Ch,P), Chs), где P объявлено как экзистенциальная переменная.

В качестве нестандартного побочного эффекта многие системы определили его как предикат со следующим определением:

_^Goal :- Goal

Но тогда у других нет такого определения. В любом случае рекомендуется избегать определения предиката (^)/2.

(^)/2 - сила

Это вычисляемый функтор, доступный через (is)/2 и арифметическое сравнение, такое как (=:=)/2 и (>)/2. Также library(clpfd) использует его в этом значении. В отличие от (**)/2, которое всегда дает число с плавающей запятой, 2^2 является целым числом, что позволяет выполнять арифметические операции с большими целыми числами. Просто попробуйте ?- X is 7^7^7., чтобы узнать, поддерживает ли их ваша система.

Наконец, существуют пользовательские варианты использования (^)/2, которые не противоречат описанным выше видам использования, таким как лямбда-выражения через library(lambda) (источник).


Есть несколько общих замечаний по поводу его использования. (^)/2 ассоциируется справа, что означает, что: (7^7^7) = (7^(7^7)). У него очень низкий приоритет, что означает, что вы должны использовать скобки для аргументов со стандартными операторами.

person false    schedule 12.11.2013

В математических выражениях ^ — это возведение в степень, это просто другое обозначение для **.

В лямбда-выражениях это оператор передачи параметров.

Как в книге Перейры и Шибера:

Таким образом, лямбда-выражение λ x. x + 1 будет закодировано на Прологе как X^(X+1). Точно так же лямбда-выражение λ x. λ y.wrote(y, x) будет закодировано как терм Пролога X^Y^wrote(Y,X), предполагая правую ассоциативность "^"

person Roy Dictus    schedule 12.11.2013
comment
mtome.com/Publications/PNLA/prolog-digital.pdf‎ (цифровое издание) и eecs.harvard.edu/shieber/Biblio (см. запись 1987 года). - person Roy Dictus; 12.11.2013
comment
это моя предпочтительная книга по Прологу! - person CapelliC; 12.11.2013
comment
Таким образом, лямбда-выражение λ x. x + 1 будет закодировано на Прологе как X^(X+1). Я этого не понимаю. Это полностью наоборот. X^foo(X,Y) на самом деле означает, что НЕ выставляйте X в foo в качестве параметра снаружи. Пролог по умолчанию уже предоставляет X и Y в foo(X,Y) и не как лямбда-параметры, а как глобальные переменные предложения. - person David Tonhofer; 14.04.2020
comment
@DavidTonhofer Насколько я понимаю вышеупомянутую книгу, авторы используют ^ в качестве конструктора терминов. Термины, которые они создают, отражают лямбда-выражения, чтобы иметь возможность составлять логические предложения первого порядка из более мелких частей (как FOL DSL или кодирование, если хотите). Они интерпретируют X^foo(X,Y) как означающее λx.foo(x,y). Таким образом, в этой интерпретации X является формальным параметром лямбда-выражения, а foo(X,Y) — его телом. Для Пролога это просто термы с логическими переменными. Семантика — это то, что вы определяете с помощью предикатов, обрабатывающих такие термины. - person ThomasH; 19.08.2020

Вот мое дополнение к использованию ^ в setof/3 и bagof/3.

Предварительное примечание:

Лично я считаю семантику ^ неудачной, потому что она выглядит так, как если бы это была «экзистенциальная квантификация» и даже иногда описывается как таковая (например: Пролог GNU, библиотека SWI-Prolog(yall)), но на самом деле это НЕ. Избегайте этой ошибки, вместо этого напишите отдельный предикат, который будет вызываться setof/3 и bagof/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, ничего неожиданного не происходит, мы как Фонзи с кванторами существования:

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

Головные уборы вне комплекта/3 или мешка/3

Это принято, и ему можно было бы придать значение, но Пролог будет искать процедуру ^/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).

Закрытая переменная, используемая в другом месте пункта: Проблемно!

Теперь мы попадаем на территорию «неудачи семантики»: Пролог не рассматривает внешнее 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] — это просто шаблон, а X и Y на самом деле являются переменными всего предложения, которые могут быть ограничены в другом месте:

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., является ошибкой компилятора.
  • Вы можете поместить все, что хотите, в шаблон, лямбда-ред, экзистенциализированный или глобальный.
  • Вызванная цель охватывает любые переменные, которые она считает свежими: либо свежие, отображаемые как λX., и любые переменные, отображаемые как ∃X..

(Не жалуйтесь на строчную букву x выше, она просто так выглядит. λX. ∃X. Xx)

person David Tonhofer    schedule 14.04.2020
comment
Хотя это хороший и подробный ответ, кажется, что вы пытаетесь ответить на этот вопрос, Prolog понимает setof/3 с маркировкой ^< /а>. Я не знаю, почему он был закрыт, это не то же самое, что Prolog: что делает ^ в setof?. Поскольку это не отвечает на основной вопрос, который я задал, мне жаль, что я не могу проголосовать за него. Возможно, вы можете использовать его в качестве ответа на другой вопрос. - person Guy Coder; 14.04.2020
comment
@GuyCoder Вы, конечно, правы, но, по крайней мере, я знаю, где его найти, если снова запутаюсь. Не беспокойтесь о голосовании, я хотел преследовать тех, кого собирал в домене JavaScript. - person David Tonhofer; 14.04.2020
comment
Я тоже использую StackOverflow как своего рода записную книжку, потому что, если вы размещаете материал в блоге, вряд ли кто-то его прочитает, но если вы размещаете его здесь, он привлекает больше внимания и иногда получает хорошие отзывы. :) Теперь, когда у SWI-Prolog есть форум с правильным HTML и форматированием, я больше использую его для публикации таких вещей. Поэтому для таких ответов я бы разместил их на форуме SWI-Prolog, а затем дал ссылку отсюда туда. - person Guy Coder; 14.04.2020