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



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

         

Базовые процедуры поиска в и / или-графах



    Базовые процедуры поиска в И / ИЛИ-графах

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

        а :- b.                     % а  -  ИЛИ-вершина с двумя преемниками
        а :- с.                     % b  и  с
        b :- d, е.                 % b - И-вершина с двумя преемниками  d  и  е
        с :- h.
        с :- f, g.
        f :- h, i.
        d.  g.  h.                 % d,  g  и  h - целевые вершины

Для того, чтобы узнать, имеет ли эта задача решение, нужно просто спросить:

        ?-  а.

Получив этот вопрос, пролог-система произведет поиск в глубину в дереве рис. 13.4 и после того, как пройдет через все вершины подграфа, соответствующего решающему дереву рис. 13.4(b), ответит "да".



Преимущество такого метода программирования И / ИЛИ-поиска состоит в его простоте. Но есть и недостатки: Мы получаем ответ "да" или "нет", но не получаем решающее дерево. Можно было бы восстановить решающее дерево при помощи трассировки программы, но такой способ неудобен, да его и недостаточно, если мы хотим иметь возможность явно обратиться к решающему дереву как к объекту программы. В эту программу трудно вносить добавления, связанные с обработкой стоимостей. Если наш И / ИЛИ-граф - это граф общего вида, содержащий циклы, то пролог-система, следуя стратегии в глубину, может войти в бесконечный рекурсивный цикл.

Попробуем постепенно исправить эти недостатки. Сначала определим нашу собственную процедуру поиска в глубину для И / ИЛИ-графов.

Прежде всего мы должны изменить представление И / ИЛИ-графов. С этой целью введём бинарное отношение, изображаемое инфиксным оператором '--->'. Например, вершина  а  с двумя ИЛИ-преемниками будет представлена предложением

        а ---> или : [b, с].

Оба символа  '--->'  и  ':'  - инфиксные операторы, которые можно определить как

        :- ор( 600, xfx, --->).
        :- ор( 500, xfx, :).

Весь И / ИЛИ-граф рис. 13.4 теперь можно задать при помощи множества предложений

        а ---> или : [b, с].
        b ---> и : [d, e].
        с ---> и : [f, g].
        е ---> или : [h].
        f ---> или : [h, i].

        цель( d).     цель( g).    цель( h).

Процедуру поиска в глубину в И / ИЛИ-графах можно построить, базируясь на следующих принципах:

Для того, чтобы решить задачу вершины  В,   необходимо придерживаться приведенных ниже правил:

    (1)        Если  В   -  целевая вершина, то задача решается тривиальным образом.

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

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

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

Соответствующая программа выглядит так:

        решить( Верш) :-
                цель( Верш).

        решить( Верш) :-
                Верш ---> или : Вершины,                 % Верш - ИЛИ-вершина
                принадлежит( Верш1, Вершины),
                                    % Выбор преемника  Верш1  вершины  Верш
        решить( Bepш1).

        решить( Верш) :-
                Верш ---> и : Вершины,                     % Верш - И-вершина
                решитьвсе( Вершины).
                                    % Решить все задачи-преемники
        решитьвсе( [ ]).

        решитьвсе( [Верш | Вершины]) :-
                решить( Верш),
                решитьвсе( Вершины).

Здесь принадлежит - обычное отношение принадлежности к списку.

Эта программа все еще имеет недостатки: она не порождает решающее дерево, и она может зацикливаться, если И / ИЛИ-граф имеет соответствующую структуру (циклы).

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

        решить( Верш, РешДер).

Решающее дерево представим следующим образом. Мы имеем три случая:

    (1)        Если Верш - целевая вершина, то соответствующее решающее дерево и есть сама эта вершина.

    (2)        Если Верш - ИЛИ-вершина, то решающее дерево имеет вид

                        Верш ---> Поддерево

где Поддерево - это решающее дерево для одного из преемников вершины Верш.

    (3)        Если Верш - И-вершина, то решающее дерево имеет вид

                        Верш ---> и : Поддеревья

                где Поддеревья - список решающих деревьев для всех преемников вершины Верш.

line();

% Поиск в глубину для И / ИЛИ-графов
% Процедура решить( Верш, РешДер) находит решающее дерево для
% некоторой вершины в И / ИЛИ-графе

        решить( Верш, Верш) :-         % Решающее дерево для целевой
                цель( Верш).                    % вершины - это сама вершина

        решить( Верш, Верш ---> Дер) :-
                Верш ---> или : Вершины,        % Верш - ИЛИ-вершина
                принадлежит( Верш1, Вершины),
                                        % Выбор преемника  Верш1  вершины  Верш
                решить( Bepш1, Дер).

        решить( Верш, Верш ---> и : Деревья) :-
                Верш ---> и : Вершины,              % Верш - И-вершина
                решитьвсе( Вершины, Деревья).
                                         % Решить все задачи-преемники

        решитьвсе( [ ], [ ]).

        решитьвсе( [Верш | Вершины], [Дер | Деревья]) :-
                решить( Верш, Дер),
                решитьвсе( Вершины, Деревья).

        отобр( Дер) :-                                         % Отобразить решающее дерево
                отобр( Дер, 0),  !.                           % с отступом 0

        отобр( Верш ---> Дер, Н) :-
                                       % Отобразить решающее дерево с отступом Н
                write( Верш), write( '--->'),
                H1 is H + 7,
                отобр( Дер, H1),  !.

        отобр( и : [Д], Н) :-
                                       % Отобразить И-список решающих деревьев
        отобр( Д, Н).

        отобр( и : [Д | ДД], Н) :-
                                       % Отобразить И-список решающих деревьев
                отобр( Д, Н),
                tab( H),
                отобр( и : ДД, Н),  !.

        отобр( Верш, Н) :-
                write( Верш), nl.

line();



Формулировка игровой задачи для...



  Формулировка игровой задачи для игры двух лиц в
форме И / ИЛИ-дерева; участники игры: "игрок" и "противник".

та хода противника. Другими словами, игрок выигрывает в  Qi,  если он выигрывает во всех позициях  Ri1  и   Ri2  и  ... .  Таким образом, все позиции противника - это И-вершины. Целевые вершины - это позиции, выигранные согласно правилам игры, например позиции, в которых король противника получает мат. Позициям проигранным соответствуют задачи, не имеющие решения. Для того, чтобы решить игровую задачу, мы должны построить решающее дерево, гарантирующее победу игрока независимо от ответов противника. Такое дерево задает полную стратегию достижения выигрыша: для каждого возможного продолжения, выбранного противником, в дереве стратегии есть ответный ход, приводящий к победе.



Сведение задач к подзадачам.


Глава 13. СВЕДЕНИЕ ЗАДАЧ К ПОДЗАДАЧАМ.
И / ИЛИ-
ГРАФЫ

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

double_line();

И / или-представление задачи поиска маршрута рис. 13.1.



  И / ИЛИ-представление задачи поиска маршрута рис. 13.1.


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

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

        (1)         Для того, чтобы найти путь из  a  в  z  через
                     f,   необходимо:

                    1.1 найти путь из  а  и  f   и
                    1.2 найти путь из  f  в  z.

        (2)         Для того, чтобы найти путь из  a  в  z  через
                     g,   необходимо:

                     2.1 найти путь из  а  в  g   и
                     2.2 найти путь из  g  в  z.



Литература



Литература

И / ИЛИ-графы и связанные с ними алгоритмы поиска являются частью классических механизмов искусственного интеллекта для решения задач и реализации машинных игр. Ранним примером прикладной задачи, использующей эти методы, может служить программа символического интегрирования (Slagle 1963). И / ИЛИ-поиск используется в самой пролог-системе. Общее описание И / ИЛИ-графов и алгоритма можно найти в учебниках по искусственному интеллекту (Nilsson 1971; Nilsson 1980). Наша программа поиска с предпочтением - это один из вариантов алгоритма, известного под названием АО* . Формальные свойства АО* -алгоритма (включая его допустимость) изучались несколькими авторами. Подробный обзор полученных результатов можно найти в книге Pearl (1984).

Nilsson N.J. (1971). Problem-Solving Methods in Artificial Intelligence. McGraw-Hill.

Nilsson N.J. (1980). Principles of Artificial Intelligence. Tioga; also Springer-Verlag.

Pearl J. (1984). Heuristics: Intelligent Search Strategies for Computer Problem Solving. Addison-Wesley.

Slagle J.R. (1963). A heuristic program that solves symbolic integration problems in freshman calculus. In: Computers and Thought (E. Feigenbaum, J. Feldman, eds.). McGraw-Hill.



Поиск маршрута из а в z на карте дорог. Через реку



  Поиск маршрута из  а  в  z  на карте дорог. Через реку


можно переправиться в городах  f  и   g.  И / ИЛИ-представление этой
задачи показано на рис. 13.2.

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

На карте рис. 13.1 мы видим также реку. Допустим, что переправиться через нее можно только по двум мостам: один расположен в городе  f,   другой - в городе  g.  Очевидно, что искомый маршрут обязательно должен проходить через один из мостов, а значит, он должен пройти либо через  f,  либо через  g.   Таким образом, мы имеем две главных альтернативы:

        Для того, чтобы найти путь из  а  в  z,
        необходимо найти одно из двух:

        (1)         путь из  а  в  z,   проходящий через  f,  или
        (2)         путь из  а  в  z,   проходящий через  g.



Поиск с предпочтением в и / или-графах



    Поиск с предпочтением в И / ИЛИ-графах

    Эвристические оценки и алгоритм поиска
1.    Эвристические оценки и алгоритм поиска

Базовые процедуры поиска предыдущего раздела производят систематический и полный просмотр И / ИЛИ-дерева, не руководствуясь при этом какими-либо эвристиками. Для сложных задач подобные процедуры весьма не эффективны из-за большой комбинаторной сложности пространства поиска. В связи с этим возникает необходимость в эвристическом управлении поиском, направленном на уменьшение комбинаторной сложности за счет исключения бесполезных альтернатив. Управление эвристиками, излагаемое в настоящем разделе, будет основано на численных эвристических оценках "трудности" задач, входящих в состав И / ИЛИ-графа. Программу, которую мы составим, можно рассматривать как обобщение программы поиска с предпочтением в пространстве состояний гл. 12.

Начнем с того, что сформулируем критерий оптимальности, основанный на стоимостях дуг И / ИЛИ-графа. Во-первых, мы расширим наше представление И / ИЛИ-графов, дополнив его стоимостями дуг. Например, И / ИЛИ-граф рис. 13.4 можно представить следующими предложениями:

        а ---> или : [b/1, с/3].
        b ---> и : [d/1, е/1].
        с ---> и : [f/2, g/1].
        e ---> или : [h/6].
        f ---> или : [h/2, i/3].

        цель( d).  цель( g).   цель( h).

Стоимость решающего дерева мы определим как сумму стоимостей его дуг. Цель оптимизации - найти решающее дерево минимальной стоимости. Как и раньше, иллюстрацией служит рис. 13.4.

Будет полезным определить стоимость вершины И / ИЛИ-графа как стоимость оптимального решающего дерева для этой вершины. Стоимость вершины, определенная таким образом, соответствует "трудности" соответствующей задачи.

Мы будем предполагать, что стоимости вершин И / ИЛИ-графа можно оценить (не зная соответствующих решающих деревьев) при помощи эвристической функции  h.  Эти оценки будут использоваться для управления поиском. Наша программа поиска начнет свою работу со стартовой вершины и, распространяя поиск из уже просмотренных вершин на их преемников, будет постепенно наращивать дерево поиска. Этот процесс будет строить дерево даже в том случае, когда сам И / ИЛИ-граф не является деревом; при этом граф будет разворачиваться в дерево за счет дублирования своих отдельных частей.

Для продолжения поиска будет всегда выбираться "наиболее перспективное" решающее дерево-кандидат. Каким же образом используется функция   h   для оценки степени перспективности решающего дерева-кандидата или, точнее, вершины-кандидата - корня этого дерева?



Поиск в глубину для и / или-графов...



  Поиск в глубину для И / ИЛИ-графов. Эта программа может
зацикливаться. Процедура решить находит решающее дерево, а
процедура отобр показывает его пользователю. В процедуре отобр
предполагается, что на вывод вершины тратится только один символ.

Например, при поиске в И / ИЛИ-графе рис. 13.4 первое найденное решение задачи, соответствующей самой верхней вершине  а,   будет иметь следующее представление:

        а ---> b ---> и : [d, c ---> h]

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

        а ---> b ---> d
                             е ---> h

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

        решить( Верш, РешДер, МаксГлуб)

Как и раньше, вершиной Верш представлена решаемая задача, а РешДер - это решение этой задачи, имеющее глубину, не превосходящую МаксГлуб. МаксГлуб -это допустимая глубина поиска в графе. Если МаксГлуб = 0, то двигаться дальше запрещено, если же МаксГлуб > 0, то поиск распространяется на преемников вершины Верш, причем для них устанавливается меньший предел по глубине, равный МаксГлуб -1. Это дополнение легко ввести в программу рис. 13.8. Например, второе предложение процедуры решить примет вид:

        решить( Верш, Верш ---> Дер, МаксГлуб) :-
                МаксГлуб > 0,
                Верш ---> или : Вершины,
                % Верш - ИЛИ-вершина
                принадлежит ( Верш1, Вершины),
                                                        % Выбор преемника  Верш1  вершины  Верш
                Глуб1 is МаксГлуб - 1,                      % Новый предел по глубине
                решить( Bepш1, Дер, Глуб1).
                                                        % Решить задачу-преемник с меньшим ограничением

Нашу процедуру поиска в глубину с ограничением можно также использовать для имитации поиска в ширину. Идея состоит в следующем: многократно повторять поиск в глубину каждый раз все с большим значением ограничения до тех пор, пока решение не будет найдено, То есть попробовать решить задачу с ограничением по глубине, равным 0, затем - с ограничением 1, затем - 2 и т.д. Получаем следующую программу:

        имитация_в_ширину( Верш, РешДер) :-
                проба_в_глубину( Верш, РешДер, 0).

% Проба поиска с возрастающим ограничением, начиная с 0

        проба_в_глубину( Верш, РешДер, Глуб) :-
                решить( Верш, РешДер, Глуб);
                Глуб1 is Глуб + 1,
                            % Новый предел по глубине
                проба_в_глубину( Верш, РешДер, Глуб1).
                                                        % Попытка с новым ограничением

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



Получение оценки н трудности задач и / или-графа.



  Получение оценки  Н  трудности задач  И / ИЛИ-графа.

Обозначим через Н( В) оценку трудности вершины  В.  Для самой верхней вершины текущего дерева поиска  H( В)  просто совпадает с  h( В).  С другой стороны, для оценки внутренней вершины дерева поиска нам не обязательно использовать непосредственно значение  h,  поскольку у нас есть некоторая дополнительная информация об этой вершине: мы знаем ее преемников. Следовательно, как показано на рис. 13.9, мы можем приближенно оценить трудность внутренней ИЛИ-вершины как

        H( B) = min ( c( B, Bi) + H( Bi) )
                                i

где  с( В, В)  -  стоимость дуги, ведущей из  В  в  Вi.   Взятие минимума в этой формуле оправдано тем обстоятельством, что для того, чтобы решить задачу  В,  нам нужно решить только одну из ее задач-преемников. Трудность И-вершины  В   можно приближенно оценить так:

       

Представление дерева поиска.



  Представление дерева поиска.

можностей имеется в виду. Это может быть одна из следующих комбинаций:

        лист     решлист    дер    решдер

Далее, в представление дерева входят все или некоторые из следующих объектов: корневая вершина дерева, F-оценка дерева, стоимость  С  дуги И / ИЛИ-графа, ведущей в корень дерева, список поддеревьев, отношение (И или ИЛИ) между поддеревьями.

Список поддеревьев всегда упорядочен по возрастанию  F-оценок. Поддеревья, являющиеся решающими деревьями, помещаются в конец списка.

Обратимся теперь к программе рис. 13.12. Отношение самого высокого уровня - это

        и_или( Верш, РешДер)

где Верш - стартовая вершина. Программа строит решающее дерево (если таковое существует), рассчитывая на то, что оно окажется оптимальным решением. Будет ли это решение в действительности самым дешевым, зависит от той функции  h,  которую использует алгоритм. Существует теорема, в которой говорится о том, как оптимальность решения зависит от  h.  Эта теорема аналогична теореме о допустимости алгоритма поиска с предпочтением в пространстве состояний (гл. 12). Обозначим через  С( В)  стоимость оптимального решающего дерева для вершины  В.   Если для каждой вершины  В  И / ИЛИ-графа эвристическая оценка  h( B) <= C( B),   то гарантируется, что процедура  и_или   найдет оптимальное решение. Если же  h   не удовлетворяет этому условию, то найденное решение может оказаться субоптимальным. Существует тривиальная эвристическая функция, удовлетворяющая условию оптимальности, а именно   h = 0  для всех вершин. Ее недостатком является отсутствие эвристической силы.

Основную роль в программе рис. 13.12 играет отношение

        расширить( Дер, Предел, Дер1, ЕстьРеш)

Дер и Предел - его "входные" аргументы, а Дер1 и ЕстьРеш - "выходные". Аргументы имеют следующий смысл:

Дер - дерево поиска, подлежащее расширению.

Предел - предельное значени  F-оценки, при котором еще разрешено наращивать дерево Дер.

ЕстьРеш - индикатор, значения которого указывают на то, какой из следующих трех случаев имеет место:

    (1)        ЕстьРеш = да: Дер можно "нарастить" (с учетом ограничения Предел) таким образом, чтобы образовалось решающее дерево Дер1.

    (2)        ЕстьРеш = нет: дерево Дер можно расширить до состояния Дер1, для которого F-оценка превосходит Предел, но прежде чем F-оценка превзошла Предел, решающее дерево не было обнаружено.

    (3)        ЕстьРеш = никогда: Дер не содержит решения.

В зависимости от случая Дер1 - это либо решающее дерево, либо Дер, расширенное до момента перехода через Предел; если ЕстьРеш = никогда, то переменная Дер1 неинициализирована.

Процедура

        расширспис( Деревья, Предел, Деревья1, ЕстьРеш)

аналогична процедуре расширить. Так же, как и в процедуре расширить, Предел задает ограничение на рост дерева, а ЕстьРеш - это индикатор, указывающий, каков результат расширения ("да", "нет" или "никогда"). Первый аргумент - это, на этот раз, список деревьев (И-список или ИЛИ-список):

        Деревья = или:[Д1, Д2, ...] или
        Деревья = и : [Д1, Д2, ...]

Процедура расширспис выбирает из списка Деревья наиболее перспективное дерево (исходя из F-оценок). Так как деревья в списке упорядочены, таким деревом является первый элемент списка. Наиболее перспективное дерево подвергается расширению с новым ограничением Предел1. Значение Предел1 зависит от Предел, а также от других деревьев списка. Если Деревья - это ИЛИ-список, то Предел1 устанавливается как наименьшая из двух величин: Предел и F-оценка следующего по "качеству" дерева из списка Деревья. Если Деревья - это И-дерево, то Предел1 устанавливается равным Предел минус сумма F-оценок всех остальных деревьев из списка. Значение переменной Деревья1 зависит от случая, задаваемого индикатором ЕстьРеш. Если ЕстьРеш = нет, то Деревья1 - это то же самое, что и список Деревья, причем наиболее перспективное дерево расширено с учетом ограничения Предел1. Если ЕстьРеш = да, то Деревья1 - это решение для всего списка Деревья (найденное без выхода за границы значения Предел). Если ЕстьРеш = никогда, то переменная Деревья1 неинициализирована.

Процедура продолжить, вызываемая после расширения списка деревьев, решает, что делать дальше, в зависимости от результата срабатывания процедуры расширить. Эта процедура либо строит решающее дерево, либо уточняет дерево поиска и продолжает процесс его наращивания, либо выдает сообщение "никогда" в случае, когда было обнаружено, что список деревьев не содержит решения.

line();

/* ПРОГРАММА И / ИЛИ-ПОИСКА С ПРЕДПОЧТЕНИЕМ

Эта программа порождает только одно решение. Гарантируется, что это решение самое дешевое при условии, что используемая эвристическая функция является нижней гранью реальной стоимости решающих деревьев.

Дерево поиска имеет одну из следующих форм:

дер( Верш, F, С, Поддеревья)                     дерево-кандидат
лист( Верш, F, C)                                           лист дерева поиска
решдер( Верш, F, Поддеревья)                  решающее дерево
решлист( Верш, F)                                        лист решающего дерева

С - стоимость дуги, ведущей в Верш
F = С + Н, где Н - эвристическая оценка оптимального решающего дерева с корнем Верш

Список Поддеревья упорядочен таким образом, что
(1)        решающие поддеревья находятся в конце списка;
(2)        остальные поддеревья расположены в порядке возрастания F-оценок

*/

        :- ор( 500, xfx, :).

        :- ор( 600, xfx, --->).

        и_или( Верш, РешДер) :-
                расширить( лист( Верш, 0, 0), 9999, РешДер, да).
                                        % Предполагается, что 9999  >  любой F-оценки

% Процедура расширить( Дер, Предел, НовДер, ЕстьРеш)
% расширяет Дер в пределах ограничения Предел
% и порождает НовДер с "решающим статусом" ЕстьРеш.

% Случай 1:  выход за ограничение

        расширить( Дер, Предел, Дер, нет) :-
                f( Дер, F),  F > Предел,  !.                         % Выход за ограничение

% В остальных случаях  F  <=  Предел
% Случай 2:  встретилась целевая вершина

        расширить( лист( Верш, F, С), _, решлист( Верш, F), да) : -
                цель( Верш),  !.

% Случай 3:  порождение преемников листа

        расширить( лист( Верш, F,C), Предел, НовДер, ЕстьРеш) :-
                расшлист( Верш, С, Дер1),  !,
                расширить( Дер1, Предел, НовДер, ЕстьРеш);
                ЕстьРеш = никогда,  !.                             % Нет преемников, тупик

% Случай 4:  расширить дерево

                расширить( дер( Верш, F, С, Поддеревья),
                                    Предел, НовДер, ЕстьРеш) :-
                    Предел1 is Предел - С,
                    расширспис( Поддеревья, Предел1, НовПоддер, ЕстьРеш1),
                    продолжить( ЕстьРеш1, Верш, С, НовПоддер, Предел,
                                                                                            НовДер, ЕстьРеш).

% расширспис( Деревья, Предел, Деревья1, ЕстьРеш)
% расширяет деревья из заданного списка с учетом
% ограничения Предел и выдает новый список Деревья1
% с "решающим статусом" ЕстьРеш.

        расширспис( Деревья, Предел, Деревья1, ЕстьРеш) :-
                выбор( Деревья, Дер, ОстДер, Предел, Предел1),
                расширить( Дер, Предел1, НовДер, ЕстьРеш1),
                собрать( ОстДер, НовДер, ЕстьРеш1, Деревья1, ЕстьРеш).

% "продолжить" решает, что делать после расширения
% списка деревьев

        продолжить( да, Верш, С, Поддеревья, _,
                                                решдер( Верш, F, Поддеревья), да): -
                оценка( Поддеревья, Н), F is С + H,  !.

        продолжить( никогда, _, _, _, _, _, никогда) :-  !.

        продолжить( нет, Верш, С, Поддеревья, Предел,
                                                                                НовДер, ЕстьРеш) :-
                оценка( Поддеревья, Н), F is С + Н,  !,
                расширить( дер( Верш, F, С, Поддеревья), Предел,
                                                                                    НовДер, ЕстьРеш).

% "собрать" соединяет результат расширения дерева со списком деревьев

        собрать( или : _, Дер, да, Дер, да):-  !.           % Есть решение ИЛИ-списка

        собрать( или : ДД, Дер, нет, или : НовДД, нет) :-
                встав( Дер, ДД, НовДД),  !.                     % Нет решения ИЛИ-списка

        собрать( или : [ ], _, никогда, _, никогда) :-  !.
                                                                                     % Больше нет кандидатов

        собрать( или:ДД, _, никогда, или:ДД, нет) :-  !.
                                                                                     % Есть еще кандидаты

        собрать( и : ДД, Дер, да, и : [Дер Э ДД], да ) :-
                всереш( ДД),  !.                                          % Есть решение И-списка

        собрать( и : _, _, никогда, _, никогда) :-  !.
                                                                                     % Нет решения И-списка

        собрать( и : ДД, Дер, ДаНет, и : НовДД, нет) :-
                встав( Дер, ДД, НовДД),  !.                     % Пока нет решения И-списка

% "расшлист" формирует дерево из вершины и ее преемников

        расшлист( Верш, С, дер( Верш, F, С, Оп : Поддеревья)) :-
                Верш---> Оп : Преемники,
                оценить( Преемники, Поддеревья),
                оценка( Оп : Поддеревья, Н), F is С + Н.

        оценить( [ ], [ ]).

        оценить( [Верш/С | ВершиныСтоим], Деревья) :-
                h( Верш, Н), F is С + Н,
                оценить( ВершиныСтоим, Деревья1),
                встав( лист( Верш, F, С), Деревья1, Деревья).

% "всереш" проверяет, все ли деревья в списке "решены"

        всереш([ ]).

        всереш( [Дер | Деревья] ) :-
                реш( Дер),
                всереш( Деревья).

        реш( решдер( _, _, _ ) ).

        реш( решлист( _ , _) ).

        f( Дер, F) :-                                                              % Извлечь F-оценку дерева
                arg( 2, Дер, F),  !.                                            % F - это 2-й аргумент Дер

% встав( Дер, ДД, НовДД) вставляет Дер в список
% деревьев ДД; результат - НовДД

        встав( Д, [ ], [Д] ) :-   !.

        встав( Д, [Д1 | ДД], [Д, Д1 | ДД] ) :-
                реш( Д1),  !.

        встав( Д, [Д1 | ДД], [Д1 | ДД1] ) :-
                реш( Д),
                встав( Д, ДД, ДД1),  !.

        встав( Д, [Д1 | ДД], [Д, Д1 | ДД] ) :-
                f( Д, F), f( Д1, F1), F=< F1,  !.

        встав( Д, [Д1 | ДД], [ Д1 | ДД1] ) :-
                встав( Д, ДД, ДД1).

% "оценка" находит "возвращенную" F-оценку И / ИЛИ-списка деревьев

        оценка( или :[Дер | _ ], F) :-
                                        % Первое дерево ИЛИ-списка - наилучшее
                f( Дер, F),  !.

        оценка( и :[ ], 0) :-   !.

        оценка( и : [Дер1 | ДД], F) :-
                f( Дер1, F1),
                оценка( и : ДД, F2),
                F is F1 + F2,  !.

        оценка( Дер, F) :-
                f( Дер, F).

% Отношение выбор( Деревья, Лучшее, Остальные, Предел, Предел1):
% Остальные - И / ИЛИ-список Деревья без его "лучшего" дерева
% Лучшее; Предел - ограничение для Списка Деревья, Предел1 -
% ограничение для дерева Лучшее

        выбор( Оп : [Дер], Дер, Оп : [ ], Предел, Предел) :-  !.
                                                               % Только один кандидат

        выбор( Оп : [Дер | ДД], Дер, Оп : ДД, Предел, Предел1) :-
                оценка( Оп : ДД, F),
                ( Оп = или,  !,  мин( Предел, F, Предел1);
                Оп = и, Предел1 is Предел - F).

        мин( А, В, А) :- А < В,   !.

        мин( А, В, В).

line();



Представление задач в виде и / или-графов



    Представление задач в виде И / ИЛИ-графов

В главах 11 и 12, говоря о решении задач, мы сконцентрировали свое внимание на пространстве состояний как средстве представления этих задач. В соответствии с таким подходом решение задач сводилось к поиску пути в графе пространства состояний. Однако для некоторых категорий задач представление в форме И / ИЛИ-графа является более естественным. Такое представление основано на разбиении задач на подзадачи. Разбиение на подзадачи дает преимущества в том случае, когда подзадачи взаимно независимы, а, следовательно, и решать их можно независимо друг от друга.

Проиллюстрируем это на примере. Рассмотрим задачу отыскания на карте дорог маршрута между двумя заданными городами, как показано на рис. 13.1. Не будем пока учитывать длину путей. Разумеется, эту задачу можно сформулировать как поиск пути в про-



Пример и / или-графа: d, g и h...



  (а)  Пример И / ИЛИ-графа:  d,  g  и  h  -   целевые вершины;
a  -  исходная задача.  (b)   и   (с)  Два решающих дерева, стоимости
которых равны  9  и  8  соответственно. Здесь стоимость решающего
дерева определена как сумма стоимостей всех входящих в него дуг.

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

Однако мы не обязательно должны измерять степень оптимальности решения, базируясь на стоимостях дуг. Иногда более естественным окажется приписывать стоимость не дугам, а вершинам, или же и тем, и другим одновременно.

Подведем итоги: И / ИЛИ-представление основано на философии сведения задач к подзадачам. Вершины И / ИЛИ-графа соответствуют задачам; связи между вершинами - отношениям между задачами. Вершина, из которой выходят ИЛИ-связи, называется ИЛИ-вершиной. Для того, чтобы решить соответствующую задачу, нужно решить одну из ее задач-преемников. Вершина, из которой выходят И-связи, называ ется И-вершиной. Для того, чтобы решить соответствующую задачу, нужно решить все ее задачи-преемники. При заданном И / ИЛИ-графе конкретная задача специфицируется заданием
        стартовой вершины и
        целевого условия для распознавания
        целевых вершин.
Целевые вершины (или "терминальные вершины") соответствуют тривиальным (или "примитивным") задачам. Решение представляется в виде решающего графа - подграфа всего И / ИЛИ-графа. Представление задач в форме пространства состояний можно рассматривать как специальный частный случай И / ИЛИ-представления, когда все вершины И / ИЛИ-графа являются ИЛИ-вершинами. И / ИЛИ-представление имеет преимущество в том случае, когда вершинами, находящимися в отношении И, представлены подзадачи, которые можно решать независимо друг от друга. Критерий независимости можно несколько ослабить, а именно потребовать, чтобы существовал такой порядок решения И-задач, при котором решение более "ранних" подзадач не разрушалось бы при решении более "поздних" под задач. Дугам или вершинам, или и тем, и другим можно приписать стоимости с целью получить возможность сформулировать критерий оптимальности решения.

Примеры и/или-представления задач



    Примеры И/ИЛИ-представления задач

    И / ИЛИ-представление задачи поиска маршрута
1.    И / ИЛИ-представление задачи поиска маршрута

Для задачи отыскания кратчайшего маршрута (рис. 13.1) И / ИЛИ-граф вместе с функцией стоимости можно определить следующим образом: ИЛИ-вершины представляются в форме X-Z, что означает: найти кратчайший путь из  X  в  Z. И-вершины имеют вид

        X-Z  через  Y

что означает: найти кратчайший путь из  X  в   Z,  проходящий через  Y.
Вершина X-Z является целевой вершиной (примитивной задачей), если на карте существует непосредственная связь между  X  и  Z. Стоимость каждой целевой вершины X-Z равна расстоянию, которое необходимо  преодолеть по дороге, соединяющей X с Z. Стоимость всех остальных (нетерминальных) вершин равна 0.

Стоимость решающего графа равна сумме стоимостей всех его вершин (в нашем случае это просто сумма стоимостей всех терминальных вершин). В задаче рис. 13.1 стартовая вершина - это   а-z.  На рис.



Программа поиска с предпочтением в и / или-графе.



  Программа поиска с предпочтением в И / ИЛИ-графе.

Еще одна процедура

        собрать( ОстДер, НовДер, ЕстьРеш1, НовДеревья, ЕстьРеш)

связывает между собой несколько объектов, с которыми работает расширспис. НовДер - это расширенное дерево, взятое из списка деревьев процедуры расширспис, ОстДер - остальные, не измененные деревья из этого списка, а ЕстьРеш1 указывает на "решающий статус" дерева НовДер. Процедура собрать имеет дело с несколькими случаями в зависимости от значения ЕстьРеш1, а также от того, является ли список деревьев И-списком или ИЛИ-списком. Например, предложение

        собрать( или : _, Дер, да, Дер, да).

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

Для отображения решающего дерева можно определить процедуру, аналогичную процедуре отобр (рис. 13.8). Оставляем это читателю в качестве упражнения.

    Пример отношений, определяющих конкретную задачу: поиск маршрута
3.    Пример отношений, определяющих конкретную задачу: поиск маршрута

Давайте теперь сформулируем задачу нахождения маршрута как задачу поиска в И / ИЛИ-графе, причем сделаем это таким образом, чтобы наша формулировка могла бы быть непосредственно использована процедурой и_или рис. 13.12. Мы условимся, что карта дорог будет представлена при помощи отношения

        связь( Гор1, Гор2, Р)

означающего, что между городами Гор1 и Гор2 существует непосредственная связь, а соответствующее расстояние равно Р.   Далее, мы допустим, что существует отношение

        клпункт( Гор1-Гор2, Гор3)

имеющее следующий смысл: для того, чтобы найти маршрут из Гор1 в Гор2, следует рассмотреть пути, проходящие через Гор3 ( Гор3 - это "ключевой пункт" между Гор1 и Гор2). Например, на карте рис. 13.1  f   и  g  - это ключевые пункты между  а   и  z:

        клпункт( a-z, f).                 клпункт( a-z, g).

Мы реализуем следующий принцип построения маршрута:

Для того, чтобы найти маршрут между городами   X  и  Z,  необходимо:

    (1)        если между   X  и  Z  имеются ключевые пункты  Y1,   Y2,  ...,  то найти один из путей: путь из  X  в  Z  через  Y1,  или путь из  X  в  Z  через  Y2,  или
...

    (2)        если между   X  и  Z  нет ключевых пунктов, то найти такой соседний с  X   город  Y,  что существует маршрут из  Y  в  Z.

Таким образом, мы имеем два вида задач, которые мы будем представлять как

    (1)        X-Z                             найти маршрут из  X  в  Z

    (2)        X-Z через Y               найти маршрут из  X  в  Z,  проходящий через   Y

Здесь 'через' - это инфиксный оператор более высокого приоритета, чем '-', и более низкого, чем '--->'. Теперь можно определить соответствующий И / ИЛИ-граф явным образом при помощи следующего фрагмента программы:

        :- ор( 560, xfx, через)

        % Правила задачи X-Z, когда между  X  и  Z
        % имеются ключевые пункты,
        % стоимости всех дуг равны 0

        X-Z ---> или : СписокЗадач

        :- bagof( ( X-Z через Y)/0, клпункт( X-Z, Y),
                        СписокЗадач),   !.

        % Правила для задачи X-Z без ключевых пунктов

        X-Z ---> или : СписокЗадач

        :- bagof( ( Y-Z)/P, связь( X, Y, Р), СписокЗадач).

        % Сведение задачи типа ''через" к подзадачам,
           % связанным отношением И

        X-Z через Y---> и : [( X-Y)/0, ( Y-Z)/0].

        цель( Х-Х)         % Тривиальная задача: попасть из X в X

Функцию  h  можно определить, например, как расстояние, которое нужно преодолеть при воздушном сообщении между городами.



Решающее дерево минимальной стоимости для задачи поиска маршрута рис. 13.1, сформулированной в терминах и / или- графа.



  Решающее дерево минимальной стоимости для задачи
поиска маршрута рис. 13.1, сформулированной в терминах И / ИЛИ-
графа.

13.5 показан решающий граф, имеющий стоимость 9. Это дерево соответствует пути [a, b, d, f, i, z], который можно построить, если пройти по всем листьям решающего дерева слева направо.

    Задача о ханойской башне
2.    Задача о ханойской башне

Задача о ханойской башне (рис. 13.6) - это еще один классический пример эффективного применения метода разбиения задачи на подзадачи и построения И / ИЛИ-графа. Для простоты мы рассмотрим упрощенную версию этой задачи, когда в ней участвует только три диска:

Имеется три колышка  1,  2  и  3  и три диска  а,  b  и  с  (а   -  наименьший из них, а  с  -   наибольший). Первоначально все диски находятся на колышке 1. Задача состоит в том, чтобы переложить все диски на колышек 3. На каждом шагу можно перекладывать только один диск, причем никогда нельзя помещать больший диск на меньший.

Эту задачу можно рассматривать как задачу достижения следующих трех целей:

    (1)        Диск  а   -  на колышек 3.
    (2)        Диск  b   -  на колышек 3.
    (3)        Диск  с   -  на колышек 3.

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



Решить р - это значит решить р1 или р2 или ... (б) решить q - это значит решить все: q1 и q2 и ... .



  (а)  Решить   Р  -  это значит решить  Р1  или   Р2  или  ...
(б)  Решить  Q  -  это значит решить все:   Q1  и  Q2  и  ... .

Итак, мы имеем две главных альтернативы для решения исходной задачи:  (1)  путь через  f   или  (2)  путь через  g.  Далее, каждую из этих альтернатив можно разбить на подзадачи (1.1 и 1.2 или 2.1 и 2.2 соответственно). Здесь важно то обстоятельство, что каждую из подзадач в обоих альтернативах можно решать независимо от другой. Полученное разбиение исходной задачи можно изобразить в форме И / ИЛИ-графа (рис. 13.2). Обратите внимание на полукруглые дуги, которые указывают на отношение   И  между соответствующими подзадачами. Граф, показанный на рис. 13.2 - это всего лишь верхняя часть всего  И / ИЛИ-дерева.   Дальнейшее разбиение подзадач можно было бы строить на основе введения дополнительных промежуточных городов.

Какие вершины  И / ИЛИ-графа  являются целевыми? Целевые вершины - это тривиальные, или "примитивные" задачи. В нашем примере такой подзадачей можно было бы считать подзадачу "найти путь из  а  в  с",   поскольку между городами  а  и  с   на карте имеется непосредственная связь.

Рассматривая наш пример, мы ввели ряд важных понятий. И / ИЛИ-граф - это направленный граф, вершины которого соответствуют задачам, а дуги - отношениям между задачами. Между дугами также существуют свои отношения. Это отношения И и ИЛИ, в зависимости от того, должны ли мы решить только одну из задач-преемников или же несколко из них (см. рис. 13.3). В принципе из вершины могут выходить дуги, находящиеся в отношении И вместе с дугами, находящимися в отношении ИЛИ. Тем не менее, мы будем предполагать, что каждая вершина имеет либо только И-преемников, либо только ИЛИ-преемников; дело в том, что в такую форму можно преобразовать любой И / ИЛИ граф, вводя в него при необходимости вспомогательные ИЛИ-вершины. Вершину, из которой выходят только И-дуги, называют И-вершиной; вершину, из которой выходят только ИЛИ-дуги, - ИЛИ-вершиной.

Когда задача представлялась в форме пространства состояний, ее решением был путь в этом пространстве. Что является решением в случае И / ИЛИ-представления? Решение должно, конечно, включать в себя все подзадачи И-вершины. Следовательно, это уже не путь, а дерево. Такое решающее дерево Т определяется следующим образом: исходная задача Р - это корень дерева Т; если Р является ИЛИ-вершиной, то в Т содержится только один из ее преемников (из И / ИЛИ-графа) вместе со своим собственным решающим деревом; если Р - это И-вершина, то все ее преемники (из И / ИЛИ-графа) вместе со своими решающими деревьями содержатся в Т.



это формальный аппарат для представления



Резюме

И / ИЛИ-граф - это формальный аппарат для представления задач. Такое представление является наиболее естественным и удобным для задач, которые разбиваются на независимые подзадачи. Примером могут служить игры. Вершины И / ИЛИ-графа бывают двух типов: И- вершины и ИЛИ-вершины. Конкретная задача определяется стартовой вершиной и целевым условием. Решение задачи представляется решающим деревом. Для моделирования оптимизационных задач в И / ИЛИ-граф можно ввести стоимости дуг и вершин. Процесс решения задачи, представленной И / ИЛИ-графом, включает в себя поиск в графе. Стратегия поиска в глубину предусматривает систематический просмотр графа и легко программируется. Однако эта стратегия может привести к неэффективности из-за комбинаторного взрыва. Для оценки трудности задач можно применить эвристики, а для управления поиском - принцип эвристического поиска с предпочтением. Эта стратегия более трудна в реализации. В данной главе были разработаны прологовские программы для поиска в глубину и поиска с предпочтением в И / ИЛИ-графах. Были введены следующие понятия:

        И / ИЛИ-графы
        И-дуги, ИЛИ-дуги
        И-вершины, ИЛИ-вершины
        решающий путь, решающее дерево
        стоимость дуг и вершин
        эвристические оценки в И / ИЛИ-графах
        "возвращенные" оценки
        поиск в глубину в И / ИЛИ-графах
        поиск с предпочтением в И / ИЛИ-графах

Трассировка процесса поиска с предпочтением в и / или-графе ( h = 0) при решении задачи рис. 13.4.



  Трассировка процесса поиска с предпочтением в
И / ИЛИ-графе ( h = 0) при решении задачи рис. 13.4.

прекращается. В результате процесс поиска не успевает "осознать", что  h  -   это тоже целевая вершина и что порождено решающее дерево. Вместо этого происходит переключение активности на конкурирующую альтернативу  с.  Поскольку в этот момент F( b) = 9, устанавливается верхняя граница для  F( c),  равная 9. Дерево-кандидат с корнем  с   наращивается (с учетом установленного ограничения) до тех пор, пока не возникает ситуация, показанная на снимке  Е.  Теперь процесс поиска обнаруживает, что найдено решающее дерево (включающее в себя целевые вершины  h  и  g),  на чем поиск заканчивается. Заметьте, что в качестве результата процесс поиска выдает наиболее дешевое из двух возможных решающих деревьев, а именно решающее дерево рис. 13.4(с).

    Программа поиска
2.    Программа поиска

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

Существует несколько случаев, как показано на рис. 13.11. Различные формы представления поискового дерева возникают как комбинации следующих возможных вариантов, относящихся к размеру дерева и к его "решающему статусу". Размер:

(1)    дерево состоит из одной вершины (листа)
        или
(2)    оно имеет корень и (непустые) поддеревья.
Решающий статус:

(1)    обнаружено, что дерево соответствует
        решению задачи( т. е. является решающим
        деревом) или
(2)    оно все еще решающее дерево-кандидат.

Основной функтор, используемый для представления дерева, указывает, какая из комбинаций этих воз-

line();



для отображения решающего дерева, найденного



Упражнение

Напишите процедуру
        отобр2( РешДер)
для отображения решающего дерева, найденного программой и_или рис. 13.12. Формат отображения пусть будет аналогичен тому, что применялся в процедуре отобр (рис. 13.8), так что процедуру отобр2 можно получить, внеся в отобр изменения, связанные с другим представлением деревьев. Другая полезная модификация - заменить в отобр цель write( Верш) на процедуру, определяемую пользователем
        печверш( Верш, H)
которая выведет Верш в удобной для пользователя форме, а также конкретизирует  Н   в соответствии с количеством символов, необходимом для представления Верш в этой форме. В дальнейшем  Н  будет использоваться как величина отступа для поддеревьев.

к нему процедуры поиска настоящего



Упражнения

    Закончите составление программы поиска в глубину (с ограничением) для И / ИЛИ-графов, намеченную в настоящем разделе.
    Определите на Прологе И / ИЛИ-пространство для задачи "ханойская башня" и примените к нему процедуры поиска настоящего раздела.
    Рассмотрите какую-нибудь простую детерминированную игру двух лиц с полной информацией и дайте определение ее И / ИЛИ-представления. Используйте программу поиска в И / ИЛИ-графах для построения выигрывающих стратегий в форме И / ИЛИ-деревьев.


Задача о ханойской башне



  Задача о ханойской башне

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

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

        Первой достигнуть цель "диск  с  - на колышек 3",
        а затем - все остальные.

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

    (1)        Обеспечить возможность перемещения диска  с  с 1 на 3.
    (2)        Переложить   с  с 1 на 3.
    (3)        Достигнуть остальные цели  (а  на 3 и  b  на 3).

Переложить  c  с 1 на 3 возможно только в том случае, если диск  а  и  b   оба надеты на колышек 2. Таким образом наша исходная задача перемещения  а,  b   и  с  с 1 на 3 сводится к следующим трем подзадачам:

Для того, чтобы переложить  a,  b   и  с  с 1 на 3, необходимо

    (1)        переложить   а  и  b  с 1 на 2,  и
    (2)        переложить   с  с 1 на 3,  и
    (1)        переложить   а  и  b  с 2 на 3.

Задача 2 тривиальна (она решается за один шаг). Остальные две подзадачи можно решать независимо от задачи 2, так как диски  а  и  b   можно двигать, не обращая внимание на положение диска  с.  Для решения задач 1 и 3 можно применить тот же самый принцип разбиения (на этот раз диск  b  будет самым "трудным"). В соответствии с этим принципом задача 1 сводится к трем тривиальным подзадачам:

Для того, чтобы переложить  а  и  b   с 1 на 2, необходимо:

    (1)        переложить   а  с 1 на 3, и
    (2)        переложить   b  с 1 на 2, и
    (1)        переложить   а  с 3 на 2.

    Формулировка игровых задач в терминах И / ИЛИ-графов
3.    Формулировка игровых задач в терминах И / ИЛИ-графов

Такие игры, как шахматы или шашки, естественно рассматривать как задачи, представленные И / ИЛИ-графами. Игры такого рода называются играми двух лиц с полной информацией. Будем считать, что существует только два возможных исхода игры: ВЫИГРЫШ и ПРОИГРЫШ. (Об играх с тремя возможными исходами -ВЫИГРЫШ, ПРОИГРЫШ и НИЧЬЯ, можно также говорить, что они имеют только два исхода: ВЫИГРЫШ и НЕВЫИГРЫШ). Так как участники игры ходят по очереди, мы имеем два вида позиций, в зависимости от того, чей ход. Давайте условимся называть участников игры "игрок" и "противник", тогда мы будем иметь следующие два вида позиций: позиция с ходом игрока ("позиция игрока") и позиция с ходом противника ("позиция противника"). Допустим также, что начальная позиция  Р  -   это позиция игрока. Каждый вариант хода игрока в этой позиции приводит к одной из позиций противника  Q1,  Q2,  Q3,   ...  (см. рис. 13.7). Далее каждый вариант хода противника в позиции  Q1  приводит к одной из позиций игрока  R11,  R12,   ... .  В  И / ИЛИ-дереве, показанном на рис. 13.7, вершины соответствуют позициям, а дуги - возможным ходам. Уровни позиций игрока чередуются в дереве с уровнями позиций противника. Для того, чтобы выиграть в позиции   Р,  нужно найти ход, переводящий  Р   в выигранную позицию  Qi.  (при некотором  i).  Таким образом, игрок выигрывает в позиции  Р,  если он выигрывает в  Q1,  или  Q2,   или  Q3,  или ... . Следовательно,  Р  - это ИЛИ-вершина. Для любого  i  позиция  Qi  -   это позиция противника, поэтому если в этой позиции выигрывает игрок, то он выигрывает и после каждого вариан-