2013-06-20 1 views
1

Я пытаюсь сделать небольшой проект в прологе, где пользователь может ввести список, а затем он вычисляет среднее, максимальное в списке и т.д. и т.п.Пролог проблема с максимальной функцией списка: nondeterm против процедуры

Так так хорошо, но я столкнулся с проблемой при написании функции max (находит максимальное число в списке). Код:

maxN([X],X):-!. 
maxN([X|L],X) :- maxN(L,M), X > M. 
maxN([X|L],M) :- maxN(L,M), M >= X. 

сама функция работает отдельно, но я получаю сообщение об ошибке:

предиката «прогнозного :: (я, о) maxN/2», который объявлен как «процедура », на самом деле 'nondeterm' forma.pro

Это мой предикат в * определение .cl:

maxN

: (целое число * Z, число U) процедура (я, о).

Я не могу объявить его незаменимым, поскольку он вызывает проблемы со всей моей формой. Можете ли вы мне помочь/дать подсказку, как сделать процедуру? Я думаю, что мне нужно сделать разрез где-то, но мои попытки потерпели неудачу.

P.S. Я использую Visual Prolog 7.4.

Редактировать: После того, как вы попробовали альтернативы, предлагаемые для того, чтобы сделать два правила в одном или с аккумулятором, теперь я получаю, что предикат является «детермином» вместо процедуры. Согласно моему руководству Prolog, это означает, что предикат теперь не имеет нескольких решений, но вместо этого имеет шанс выйти из строя. В основном все варианты кода, которые я сделал до сих пор, приводят меня к «детекту».

+0

Вы должны включить диалект в этом вопросе. –

+0

Спасибо за помощь, ребята, я исправил «детекцию», добавив: maxN ([], Max): - Max = 0,!. Теперь я знаю, что это технически не очень правильно делать, но поскольку моя программа проверяет пустой список (в основном, maxN ([], Max) никогда не будет вызвана и существует только для полноты правил, он работает для меня. Спасибо вам за советы, они поставили меня в правильном направлении! –

+0

Он все равно может потерпеть неудачу, если вы передадите что-то помимо списка в первом аргументе. Если вы все еще хотите «исправить» это (я бы не хотел, t) вы можете предоставить другое правило формы 'maxN (X, undefined): - \ + is_list (X) .' –

ответ

1

Проблема заключается в том, что Пролог видит точку выбора между вашим вторым и третьими правилами. Другими словами, вы, человек, знаете, что оба X > M и M >= X не могут быть истинными, но Prolog не может это сделать.

ИМО лучше всего сделать было бы перефразировать эти два правила с одним правилом:

maxN([X], X) :- !. 
maxN([X|L], Max) :- 
    maxN(L, M), 
    X > M -> Max = X 
      ; Max = M. 

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

После @ советов CapelliC, вы могли также переформулировать это с аккумулятором:

maxN([X|Xs], Max) :- maxN_loop(Xs, X, Max). 

maxN_loop([], Max, Max). 
maxN_loop([X|Xs], Y, Max) :- 
    X > Y -> maxN_loop(Xs, X, Max) 
      ; maxN_loop(Xs, Y, Max). 
+0

Спасибо за ваш вклад, Даниэль, и жаль, что не упомянул диалект! Как вы, наверное, видите, я немного новичок во всех вещах Prolog. –

+0

Все в порядке. Это отличное место для получения помощи, но я должен упомянуть, что здесь никто не имеет большого опыта работы с Visual Prolog. Вам будет намного легче получить помощь здесь, если вы переключитесь на SWI-Prolog или GNU Prolog. –

+0

Ах, спасибо! Кстати, я случайно нажал кнопку ввода, прежде чем вносить свой ответ. Я хотел сказать, что я сделал с вашими предложениями: Я действительно пробовал перефразировать правила с одним раньше, но вместо этого вместо «неопределенного» я ​​получил, что maxN был «детертом», который также дает ошибку. Что касается моего руководства Prolog говорит, что определение означает, что предикат не даст множественного решения, но есть вариант, который он потерпит неудачу. Я попробовал предложение Acc, которое вы и CapelliC дали, но это также привело меня к «детексу». Но в любом случае спасибо, вы указали меня в правильном направлении, и я продолжу распутывать тайны Пролога! –

1

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

maxN([X|L],X) :- maxN(L,M), X > M, !. 

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

maxN([],A,A). 
maxN([X|L],A,M) :- X > A, !, maxN(L,X,M). 
maxN([X|L],A,M) :- maxN(L,A,M). 

Конечно, вызов верхнего уровня должен стать

maxN([F|L],M) :- maxN(L,F,M). 
+0

Спасибо за предложения CapelliC! –