2016-02-21 15 views
1

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

Я читал учебник (Prolog Programming for Artificial Intelligence), и Prolog, безусловно, трудно поднять. В то время как в книге рассматривается, как решить проблему, если есть одна коробка, в ней не упоминается, как начать решать эту проблему, если имеется более одного окна. Любые рекомендации/предложения будут высоко оценены.

move(state(middle, onbox, middle, hasnot), grasp, state(middle, onbox, middle, has)). 
move(state(Pos, onfloor, Pos, H), climb, state(Pos, onbox, Pos, H)). 
move(state(P1, onfloor, P1, H), push(P1, P2), state(P2, onfloor, P2, H)). 
move(state(P1, onfloor, P, H), walk(P1, P2), state(P2, onfloor, P, H)). 

canget(state(_ ,_ ,_ , has)). 
canget(state1) :- 
    move(State1, Move, State2), 
    canget(State2). 

Вопрос:

canget(state(atdoor, onfloor, atwindow, hasnot)). % (monkey's horizontal position, monkey's vertical position, position of the box, and whether or not the monkey has the banana). 

Единственное, что я могу думать о том, чтобы добавить еще одно поле для каждого пункта для позиции второго бокса, например, состояние (горизонтальная позиция, вертикальная позиция, позиция для box1, pos для box2 и статус банана).

+0

Я думаю, что я [видел эту проблему раньше] (http://stackoverflow.com/q/27674390/2936460) ... – SQB

ответ

2

Предлагаемое решение - один из способов решения этой проблемы: вы можете просто добавить еще один аргумент в термин, представляющий состояние.

Однако давайте стремимся к чему-то более общим: как бы вы это сделали, если есть не один или два, а n   коробки в комнате? Кроме того, предположим, что ящики имеют размеры S_1, ..., S_n (S_i не обязательно различаются), и их можно укладывать только тогда, когда ящик сверху меньше, чем тот, на котором он размещен.

Я предлагаю следующее представление для обозначения таких состояний:

Мы будем использовать пару Pos-Size, чтобы обозначить положение и размер каждого окна. Это просто инфикс обозначение термина -(Pos, Size), то есть функтор   - и Арность   2.

Мы будем использовать список таких пар, т.е. [Pos1-Size1, Pos2-Size2, ..., Pos_n-Size_n] представлять все ящики.

При укладке ящиков в одном и том же положении мы должны убедиться, что коробки, которые уже расположены в одном и том же положении, допускают такую ​​укладку. Я оставляю это упражнение для вас.

Кроме того, canget/1 на самом деле это не интересно, не так ли? Мы действительно заботимся о списке ходов, которые принимают нас к решению! Таким образом, мы расширим предикат с одним аргументом, который на самом деле позволяет нам видеть все хода на верхнем уровне, а также использовать более выразительное имя для обозначения того, что мы на самом деле с описанием:

moves(state(_ ,_ ,_ , has), []). 
moves(State0, [Move|Moves]) :- 
     move(State0, Move, State), 
     moves(State, Moves). 

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

?- length(Ms, _), moves(State0, Ms). 

, где State0 - начальное состояние головоломки.

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

moves(state(_ ,_ ,_ , has)) --> []. 
moves(State0) --> [Move], 
     { move(State0, Move, State) }, 
     moves(State). 

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

?- length(Ms, _), phrase(moves(State0), Ms). 

весело провести время, а также попробовать Искусство Пролога !

+0

Спасибо. Я все еще принимаю детские шаги, когда дело доходит до Пролога. Таким образом, я пошел дальше и добавил еще один аргумент для каждого состояния вместо того, чтобы реализовать более общее решение, которое вы предложили. Я проследил свою программу, и это похоже. Тем не менее, я просто хочу убедиться, что мне не нужно создавать какие-либо новые предложения, правильно или мне нужно создать новую, чтобы обезьяна могла самостоятельно перемещать либо маленькую коробку, либо большую коробку? – mylasthope

+0

Добавление нового предложения, описывающего связь между состояниями, в которых перемещается только новое поле, кажется хорошей идеей! Также представляется хорошей идеей отличать разные «push» действия, чтобы обозначить, какая коробка нажата. Например, прямо в функторе, это 'push_small (...)' и 'push_big (...)' или через новый аргумент, как в 'push (small, ...)' и 'push (большой, ...). Последний способ, конечно, легче обобщить на другие типы ящиков. – mat

+0

Я думаю, что я делаю это неправильно. Я отредактировал свою оригинальную программу для реализации различных «push» действий. Однако я столкнулся с ошибкой «Out of local stack». У меня есть следующее: 'move (state (P1, onfloor, P1, Psmall, H), push_big (P1, P2), состояние (P2, onfloor, P2, Psmall, H)).' И 'move (state (P1, onfloor, Pbig, P1, H), push_small (P1, P2), состояние (P2, onfloor, Pbig, P2, H)). Состояние следующее: (позиция обезьяны, включена ли обезьяна поле, положение большой коробки, положение маленькой коробки, и есть ли у нее банан). – mylasthope

Смежные вопросы