2015-05-22 3 views
5

Любой программист с некоторым опытом работы в Prolog знает преимущества использования унарной нотации для чисел. К примеру, если мы представим ряд в виде списка 1" („4“ является список „[1,1,1,1]“ и так далее), мы можем определить:Пролог: отсутствует функция?

unary_succ(X,[1|X]). 

следующие запросы делает что ожидается:

?- X=[1,1],unary_succ(X,Y). 
X = [1, 1], 
Y = [1, 1, 1]. 

?- unary_succ(X,Y),X=[1,1]. 
X = [1, 1], 
Y = [1, 1, 1]. 

?- unary_succ(X,Y),Y=[1,1]. 
X = [1], 
Y = [1, 1]. 

Таким образом, оператор unary_succ (X, Y) «связывает» X и Y таким образом, что, если после того, как факт, говорится, одна из этих переменных связана со значением, другой -

Однако это поведение невозможно, если мы используем внутреннее числовое представление:

?- X=2,succ(X,Y). 
X = 2, 
Y = 3. 

?- succ(X,Y),X=2. 
ERROR: succ/2: Arguments are not sufficiently instantiated 

?- succ(X,Y),Y=2. 
ERROR: succ/2: Arguments are not sufficiently instantiated 

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

Мои вопросы:

а) некоторые простой способ сделать это в Прологе.

b) если это невозможно, любой другой язык программирования, который поддерживает эту функцию?

Любые комментарии могут быть отправлены.

Спасибо всем.

* Добавление I *

Другой пример:

user_id(john,1234). 
user_id(tom,5678). 

и запросы:

X=john,user_id(X,Y). 
user_id(X,Y),X=john 

, что в настоящее время решаемые возвратов.

+3

В SWI Prolog, я думаю, вы можете сделать это с помощью библиотеки clpfd. Возможно, вы захотите проверить его исходный код, чтобы узнать, как он реализован. – nhahtdh

+0

Привет. Спасибо за ваше сотрудничество. Добавленный к вопросу еще один пример, чтобы уточнить. –

+4

Второе предложение CLP (FD) от @nhahtdh: по крайней мере, для целых чисел, использование ограничений CLP (FD), безусловно, является реляционным решением, которое вы ищете, и оно обеспечивается всеми основными реализациями Prolog. Просто напишите 'X # = 2, Y # = X + 1' или эквивалентно' Y # = X + 1, X # = 2'. – mat

ответ

3

Этот вопрос известен как coroutining, и его необходимо решить довольно общим способом - afaik - требуется расширение базовой модели расчета Prolog. К счастью, большинство Prologs имеют такое расширение ... Итак, давайте попробуем in SWISH построить свой собственный «реактивный» расширение: не полностью

my_succ(X, Y) :- when((nonvar(X);nonvar(Y)), succ(X, Y)). 

редактировать на точку, но Jan размещен на список рассылки SWI-Prolog с помощью простого пример coroutining применения:

?- freeze(X, writeln(X)), findall(X, between(1,3,X), Xs). 
1 
2 
3 
Xs = [1, 2, 3], 
freeze(X, writeln(X)). 
+0

Большое спасибо, я не знал, что это утверждение существует. –

+2

'когда/2' существует в SICStus (origin), YAP и SWI. – false

+3

+1 для упоминания сопроцессора в целом. Тем не менее, этот конкретный пример не очень удачный, на мой взгляд, потому что 'Y # = X + 1' более удобно и гораздо более правильно разрешен с ограничениями CLP (FD). Я предлагаю вам дать дидактически более ценный пример для 'when/2' вместо текущего. – mat

4

проблемы вы описываете существует до тех пор, как ответы по системе Prolog ограничены (синтаксические) ответ заменам. В вашем примере цель succ(X, Y) потребует бесконечного количества ответов для описания всего набора решений. По этой причине вместо этого выдается номер instantiation_error.

Для решения этой проблемы нам необходимо расширить ответы. Таким образом, ответы не только включают ответы на замену, но и более сложный способ описания некоторых наборов.

library(clpfd) Предлагая ограничения на Z (и наиболее заметно конечные области).

?- use_module(library(clpfd)). 
?- Y #= X+1. 
X+1#=Y. 

Обратите внимание, что такие решатели не очень сильны в общем случае:

?- Y #= X+1, X #= Y+1. 
Y+1#=X, 
X+1#=Y. 

Вы можете ожидать, что система не в состоянии, однако она производит ответ, который по существу новой редакции запроса. По крайней мере, ответ неверен, потому что он просто утверждает: да, есть решение , предоставленное. Это отношение имеет место (чего нет, похоже на мелкий шрифт в договорах страхования или гарантийных сертификатах).

when/2 также известен как coroutining и во многих случаях слабее, чем то, что вы получаете с clpfd. Но в некоторых случаях он более эффективен для некоторых реализаций clpfd. Рассмотрим dif/2, который может быть выражен как when(?=(X,Y), X \== Y) и

| ?- dif(X, Y), X = Y. 
no 

... в то время как (в SICStus)

| ?- X #\= Y, X #= Y. 
Y #= X, 
Y #\= X, 
Y in inf..sup, 
X in inf..sup ? ; 
no 

library(clpq) предлагает решатель, который сильнее во многих ситуациях, но испытывает недостаток в число конкретных ограничений, как mod/2 , Во многих ситуациях это все еще интересно использовать, как здесь, в SICStus:

| ?- use_module(library(clpq)). 
yes 
| ?- {Y=X+1}. 
{X = -1+Y} ? 
yes 
| ?- {Y=X+1}, {X=Y+1}. 
no 
Смежные вопросы