Как вернуть как переменный результат, так и истину/ложь в Прологе?

Звучит глупо, но предположим, что мой предикат "самый большой/2" возвращает самый большой элемент в списке... вывод должен выглядеть так:

?- largest([1,2,3,4,5], X).
X = 5.
false.

Я реализовал самый большой, и он работает так же, как и выше, за исключением того, что он не выводит «false». Как мне сделать так, чтобы он также выводил это «ложь». стоимость? Это за надоедливое задание, которое я должен закончить. :(


person Eteocles    schedule 24.11.2010    source источник


Ответы (4)


Эти дополнительные false. или No просто означают, что человек, запускающий программу, попросил получить все возможные решения для X, а не только первое возможное решение.

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

person aschepler    schedule 24.11.2010

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

 ?- A=5.
A = 5.

 ?- A=5,false.
false.

Однако

 ?- A=5;false.
A = 5 ;
false.

Чтобы добиться этого, вы должны сделать свой предикат "самый большой" недетерминированным. Но мне это кажется довольно глупым.

person Volodymyr Gubarkov    schedule 24.11.2010
comment
s(X): если я доведу вопрос до буквы T, этот несколько странный ответ будет он. И у этого есть отличное время, также! - person repeat; 25.03.2016

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

Предположим, у вас есть предикат foo/1 следующим образом:

foo(1).

foo(Bar) :-
   foo(Baz),
   Bar is Baz + 1.

Если вы спросите foo(Bar), переводчик ответит Bar = 1. После многократного нажатия ; интерпретатор вернется с Bar = 2, Bar = 3 и так далее.

В вашем примере поиск самого большого из списка должен быть детерминированным. Возврат не должен давать другой ответ.

Вам решать, интерпретировать ли задание как означающее, что вы должны разрешить откат, но он потерпит неудачу, или что было бы нормально даже не откатить его вообще.

person SQB    schedule 25.03.2016
comment
s(X): Забавно, как даже короткие спецификации приводят к принципиально противоположным выводам. - person repeat; 26.03.2016

В предыдущих ответах есть что-то от @aschepler, @Xonix и @SQB.

В этом ответе мы используем clpfd для выражения декларативного целого числа арифметика.

:- use_module(library(clpfd)).

Мы определяем largest/2 с помощью встроенного предиката member/2. , библиотека meta-predicate maplist/2 и ограничение конечного домена (#>=)/2:

largest(Zs, X) :-
   member(X, Zs),            % X is a member of the list Zs
   maplist(#>=(X), Zs).      % all Z in Zs fulfill X #>= Z

Примеры запросов:

?- largest([1,2,3,4,5], X).
X = 5.

?- largest([1,2,3,4,5,4], X).
X = 5 ;
false.

?- largest([1,2,3,4,5,5], X).
X = 5 ;
X = 5.

?- largest([1,2,3,4,5,5,4], X).
X = 5 ;
X = 5 ;
false.

?- largest([A,B,C,D], X).
A = X, X#>=D, X#>=C, X#>=B ;
B = X, X#>=A, X#>=D, X#>=C ;
C = X, X#>=A, X#>=D, X#>=B ;
D = X, X#>=A, X#>=C, X#>=B.
person repeat    schedule 25.03.2016