Несколько экземпляров предложений Пролога с одинаковой наземной головой. Любое использование помимо этого, кроме (сомнительного) контроля вычислений? - PullRequest
2 голосов
/ 18 февраля 2020

В SWI Prolog:

Допускаются точные дубликаты пунктов:

a(1).
a(1).
?- a(X).
X = 1 ;
X = 1.

или даже:

c :- format("Hello from first c!").
c :- format("Hello from second c!").
Hello from first c!
true ;
Hello from second c!
true.

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

b(1) :- format("Hello from first b!").
b(1) :- format("Hello from second b!").
?- b(1).
Hello from first b!
true ;
Hello from second b!
true.

Предложения с одинаковыми не заземленными головками кажутся более разумными:

p(X) :- format("Yup, this is p(~w)",X).
p(X) :- format("Yup, this is also p(~w)",X).
p(X) :- format("You think you can get rid of good old p(~w) just like that?",X).
?- p('homer simpson').
Yup, this is p(homer simpson)
true ;
Yup, this is also p(homer simpson)
true ;
You think you can get rid of good old p(homer simpson) just like that?
true.
?- p(X).
Yup, this is p(_4782)
true ;
Yup, this is also p(_4782)
true ;
You think you can get rid of good old p(_4782) just like that?
true.

Это охватывает разумный случай пунктов с охраняемым телом:

p(X) :- X < 0,   format("It's less than 0: ~w", X).
p(X) :- X =:= 0, format("It's exactly 0: ~w", X).
p(X) :- X > 0,   format("It's larger than 0: ~w", X).

Если подумать ... мы уже сталкиваемся с окончательным случаем во встроенном repeat:

?- repeat.
true ;
true ;
true ;
true ; 
… 

Или можно легко создать промежуточный регистр:

h :- member(_,[1,2,3]).
?- h.
true ;
true ;
true.

Каким-то образом учебники затмевают тот факт, что предикаты имеют дополнительную семантику: они могут быть не только false или true для любых заданных аргументов основания, но на самом деле они могут быть true(n) - «истинно n раз, n ≥ 0» .

С теоретической точки зрения это сомнительно, по крайней мере для vanilla classic logi c.

С другой стороны, это полезно из вычислений общая точка зрения для:

  • Побочные эффекты (скорее для вывода, чем для ввода, и довольно незначительно).
  • Контроль вычислений (то есть repeat).

Существуют ли другие варианты использования?

Я действительно считаю, что компилятор должен отмечать регистры без переменных, такие как a/1, c/0, b/1 выше, как ошибки (легко обнаруживаемые), и даже repeat/0 должно иметь значение: repeat(Count). Все, что успешно вернет , НЕ ДОЛЖНО * повторить успешно в том же контексте на тех же основополагающих аргументах. У него такое же мягкое чувство неактуальности, как у a(X) :- b(Y). b(Z). Бррр!

Ответы [ 3 ]

3 голосов
/ 18 февраля 2020

Да, для диагностики c целей в чистых программах. Дублируя предложение, вы можете ответить на вопрос, как часто предложение вносит свой вклад в решение.

То есть вы подсчитываете ответы / решения, полученные в результате запроса, и сравниваете их с той же программой плюс дублированное предложение. Если число (избыточных) решений в настоящее время увеличивается, вы знаете, что это предложение вносит свой вклад. Коэффициент ld говорит вам, как часто.

Обратите внимание, что трассировщик не может сказать вам это так легко.

1 голос
/ 18 февраля 2020

@ ложно упоминает в своем ответе, используя дублированные предложения, чтобы «ответить на вопрос, как часто предложение способствует решению». Он также упоминает, что «трассировщик не может сказать вам об этом так легко».

Лучшее решение для этого варианта использования - использовать инструмент ports profiler , как, например, в ECLiPSe и Logtalk. Нет необходимости дублировать пункты для сбора этой информации.

В качестве примера рассмотрим следующую чистую программу, сохраненную в pure.pl файле:

a :- b, c.

b.
b :- d.

c.

d.

Давайте включим этот код в объект , Мы можем определить его в исходном файле:

:- object(pure).

    :- set_logtalk_flag(debug, on).

    :- public(a/0).
    :- include('pure.pl').

:- end_object.

В качестве альтернативы, мы можем создать pure как динамический c объект:

?- create_object(pure, [],  [set_logtalk_flag(debug,on), public(a/0), include('pure.pl')], []).
true.

В любом случае, после загрузки или создания объект pure и загружая инструмент ports_profiler, мы можем, например, запросить все решения для предиката a/0 и затем распечатать данные профилирования:

?- {ports_profiler(loader)}.
...
% (0 warnings)
true.

?- pure::a.
true ;
true.

?- ports_profiler::data.
-------------------------------------------------------------------
Entity  Predicate    Fact  Rule  Call  Exit *Exit  Fail  Redo Error
-------------------------------------------------------------------
pure    a/0             0     1     1     1     1     0     1     0
pure    b/0             1     1     1     1     1     0     1     0
pure    c/0             2     0     2     2     0     0     0     0
pure    d/0             1     0     1     1     0     0     0     0
-------------------------------------------------------------------
true.

В таблице показана информация о пересечении портов для всех предикатов используется в запросе к предикату a/0. Например, что предикат c/0 вызывается дважды (для двух решений a/0) и детерминированно завершается. С другой стороны, предикат b/0 был вызван один раз как преуспевший дважды (один из них недетерминирован) из-за обратного отслеживания.

Для получения подробной информации о переносном инструменте port_profiler и обсуждении, что он может предоставить, см .:

https://logtalk.org/manuals/devtools/ports_profiler.html

1 голос
/ 18 февраля 2020

Некоторые наблюдения в частном случае дублированных предложений .

Если повторяющиеся предложения для предиката a/1 находятся в объекте Logtalk или в модуле Prolog, который может быть скомпилирован как объект, линтер Logtalk может предупредить вас о дублированных предложениях. Например, для следующего модуля:

:- module(duplicates, []).

a(1).
a(1).

Получаем:

?- set_logtalk_flag(duplicated_clauses, warning).
true.

?- {duplicates}.
*     Duplicated clause: a(1)
*       first found at or above line 3
*       while compiling object duplicates
*       in file /Users/pmoura/duplicates.lgt at or above line 4
*     
% [ /Users/pmoura/duplicates.lgt loaded ]
% 1 compilation warning
true.

Это конкретное предупреждение о задержке обычно отключается по умолчанию из-за его вычислительных затрат. Если вы загрузите инструмент tutor до компиляции модуля, вы получите вместо этого:

?- {tutor(loader)}.
...
% (0 warnings)
true.

?- set_logtalk_flag(duplicated_clauses, warning).
true.

?- {duplicates}.
*     Duplicated clause: a(1)
*       first found at or above line 3
*       while compiling object duplicates
*       in file /Users/pmoura/Desktop/duplicates.lgt at or above line 4
*     Duplicated clauses are usually a source code editing error and can
*     result in spurious choice-points, degrading performance. Delete or
*     correct the duplicated clause to fix this warning.
*     
% [ /Users/pmoura/Desktop/duplicates.lgt loaded ]
% 1 compilation warning
true.

Предупреждение полезно и зарекомендовало себя в нетривиальных кодовых базах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...