Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекція_4_17_графы_И_ИЛИ.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
413.7 Кб
Скачать

2.3. Формулювання ігрових задач у термінах і/Або-Графів.

Такі ігри, як шахи чи шашки, природно розглядати як задачі, подані І/Або-Графами. Їх називають іграми двох осіб з повною інформацією. Вважатимемо, що можливі лише два результати: виграш і програш. (Ігри з виграшем, програшем і нічиєю також можна вважати лише з двома результатами: виграшем і невиграшем). Тому що гравці ходять по черзі, маємо два види позицій залежно від того, чий хід. Назвемо гравців свій і чужий, тоді матимемо два види позицій: свого ходу і чужого ходу. Нехай початкова позиція Р - це позиція свого ходу, кожен варіант свого ходу в якій веде до деякої з позицій чужого ходу Q1, Q2, Q3, ... (див. малюнок). Далі кожен варіант чужого ходу в позиції Q1 приводить до одній з своїх позицій R11, R12, ... .

В І/Або-дереві на малюнку вузли відповідають позиціям, а дуги - можливим ходам. Рівні свого ходу чергуються в дереві з рівнями чужого ходу.

Щоб виграти в початковій позиції Р, потрібно знайти хід, що переводить Р у виграшну позицію Qi при деякому i. Тому, позиція Р є виграшною, якщо виграшною є позиція Q1, або Q2, або Q3, або ... . Отже, Р - це Або-вузол. Для всіх i позиція Qi - це позиція чужого ходу, тому, якщо вона має бути виграшною для свого гравця, то необхідно домогтись, щоб її можна було виграти після довільного чужого ходу. Тому позиція Qi є виграшною, якщо виграшними є всі з позицій Ri1, Ri2 і ... . Згідно цьому, усі позиції чужого ходу є І-вузлами. Цільові вузли - це позиції, що виграні згідно правил даної гри; наприклад, у шахах - це матові позиції. Позиціям, програним згідно правил гри, відповідають задачі, що не мають рішення.

Щоб розв'язати ігрову задачу, треба побудувати вирішуюче дерево, що гарантує свою перемогу незалежно від чужих відповідей. Таке дерево задає повну стратегію перемоги в грі: для кожного чужого ходу у дереві стратегії є відповідний свій хід, що веде до перемоги.

3. Базові процедури пошуку в і/Або-Графах

Найпростіший спосіб пошуку в І/Або-Графах засобами Прологу - це використати переборний механізм, закладений у самій Пролог-системі. Виявляється, що це дуже просто зробити, тому що процедурний смисл Прологу і є не що інше, як пошук в І/Або-Графі. Наприклад, І/Або-Граф рис. 2 ( без обліку вартостей дуг) можна описати наступними твердженнями:

а :- b. % а - Або-вузол із двома спадкоємцями b і с

а :- с.

b :- d, е. % b - І-вузол із двома спадкоємцями d і е

с :- h.

с :- f, g.

f :- h, i.

d. g. h. % d, g і h - цільові вершини

Щоб взнати, чи має ця задача розв'язок, потрібно просто запитати:

?- а.

Одержавши це питання, пролог-система зробить пошук у глибину в дереві рис. 2, і після того, як пройде через усі вершини підграфа, відповість "так".

Перевага такого методу програмування І/Або-пошуку полягає в його простоті. Але є й недоліки:

  • Ми одержуємо лише відповідь "так" або "ні", але не одержуємо вирішуюче дерево. Можна було б відновити вирішуюче дерево за допомогою трасування програми, але це незручно і недостатньо, якщо вирішуюче дерево необхідне як об'єкт програми.

  • У цю програму важко вносити доповнення для обробки вартостей.

  • Якщо І/Або-Граф - це граф загального виду, що містить цикли, то пролог-система згідно до стратегії вглиб, може ввійти в нескінченний рекурсивний цикл.

Поступово виправимо ці недоліки. Спочатку визначимо власну процедуру пошуку вглиб для І/Або-Графів.

Насамперед треба змінити подання І/Або-Графів. Для цього введем бінарне відношення, зображуване інфіксним оператором '--->'. Наприклад, вершина а із двома Або-Спадкоємцями буде представлена твердженням

а ---> або : [b, с].

Обоє символи '--->' та ':' - інфіксні оператори, які визначимо як

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

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

Увесь І/Або-Граф (рис. 2) тепер задається твердженнями

а ---> або : [b, с].

b ---> і : [d, e].

с ---> і : [f, g].

е ---> або : [h].

f ---> або : [h, i].

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

Процедуру пошуку вглиб в І/Або-Графах можна побудувати, базуючись на наступних принципах:

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

(1) Якщо В - цільовий вузол, то рішення є тривіальним.

(2) Якщо вузол В має Або-Спадкоємців, то знайти рішення за допомогою одного з них (пробуючи використати їх одного за другим, поки не буде знайдений той, що дасть розв'язок).

(3) Якщо вузол В має І-Спадкоємців, то потрібно розв'язати всі відповідні задачі (пробуючи вирішувати їх одну за одною, поки всі вони не будуть вирішені).

Якщо наведені правил не приводять до розв'язку, слід вважати, що задача не може бути вирішена.

Відповідна програма виглядає так:

розв'язати( Вузол) :- ціль( Вузол).

розв'язати( Вузол) :-

Вузол ---> або : Вузли, % Вузол - Або-Вузол

належить( Вузол1, Вузли),

% Вибір спадкоємця Вузол1 вузла Вузол

розв'язати( Bузол1).

розв'язати( Вузол) :-

Вузол ---> і : Вузли, % Вузол - І-Вузол

решитьвсе( Вузли).

% Розв'язати всі задачі-спадкоємці

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

решитьвсе( [Вузол | Вузли]) :-розв'язати( Вузол),

решитьвсе( Вузли).

Тут належить - звичайне відношення приналежності елемента до списку. Ця програма усе ще має недоліки:

  • вона не породжує вирішуюче дерево, і

  • вона може зациклюватись, якщо І/Або-Граф має циклічну структуру.

Щоб програма породжувала вирішуюче дерево, до відношення розв'язати додається ще один аргумент:

розв'язати(Вузол, Решдер).

Вирішуюче дерево згідно до трьох випадків представляють так:

  • Якщо Вузол - цільовий, то відповідне вирішуюче дерево і є саме цей вузол Вузол.

  • Якщо Вузол - Або-Вузол, то вирішуюче дерево має вигляд

Вузол ---> Піддерево

де Піддерево - це вирішуюче дерево для одного зі

спадкоємців вузла Вузол.

  • Якщо Вузол - І-Вузол, то вирішуюче дерево має вигляд

Вузол ---> і : Піддерева

де Піддерева - список вирішуючих дерев для всіх спадкоємців вузла Вузол.

% Пошук вглиб для І/Або-Графів

розв'язати(Вузол, Вузол):- % Вирішуюче дерево для

цільового вузла - це сам вузол

ціль(Вузол).

розв'язати(Вузол, Вузол ---> Дер) :-

Вузол ---> або : Вузли, % Вузол - Або-Вузол

належить(Вузол1, Вузли),

% Вибір спадкоємця Вузол1 вузла Вузол

розв'язати(Bузол1, Дер).

розв'язати(Вузол, Вузол ---> і : Дерева) :-

Вузол ---> і : Вузли, % Вузол - І-Вузол

решитьвсе(Вузли, Дерева).

% Розв'язати всі задачі-спадкоємці

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

решитьвсе([Вузол|Вузли], [Дер|Дерева]) :-

розв'язати(Вузол, Дер),

решитьвсе(Вузли, Дерева).

% Відобразити вирішуюче дерево з відступом 0

отобр(Дер) :- отобр( Дер, 0), !.

% Відобразити вирішуюче дерево з відступом Н

отобр( Вузол ---> Дер, Н) :- write(Вузол), write( '--->'),

H1 = H + 7, отобр( Дер, H1), !.

% Відобразити І-Список вирішуючих дерев

отобр( і : [Д], Н) :- отобр( Д, Н).

отобр( і : [Д | ДД], Н) :- отобр( Д, Н), tab( H),отобр( і : ДД, Н), !.

отобр( Вузол, Н) :- write( Вузол), nl.

Ця програма може зациклюватись. Процедура розв'язати(Вузол, РешДер) знаходить вирішуюче дерево для деякого вузла в І/Або-Графі, а процедура отобр показує його користувачу. (У процедурі отобр вважається, що на вивід вузла витрачається лише один символ.)

Наприклад дерево, що вирішує рис. 2, буде видрукувано процедурою отобр у наступному виді:

а ---> b ---> d

е ---> h

Наведена програма усе ще зберігає схильність до входження в нескінченні цикли. Один із простих способів уникнути нескінченних циклів - це стежити за поточною глибиною пошуку й не давати програмі заходити за межі деякого обмеження по глибині. Це можна зробити, увівши у відношення розв'язати ще один аргумент:

розв'язати( Вузол, Решдер, Максглуб)

Як і раніше, вузлом Вузол представлено розв'язувану задачу, а РешДер - це розв'язок цієї задачі, що має глибину, не більшу за МаксГлуб. МаксГлуб - це припустима глибина пошуку в графі. Якщо МаксГлуб = 0, то рухатись далі заборонено, якщо ж МаксГлуб > 0, то пошук поширюється на спадкоємців вузла Вузол, причому глибиною МаксГлуб - 1 на одиницю меншу попереднього обмеження. Це доповнення легко вводиться в останню програму. Наприклад, друге твердження процедури розв'язати прийме вид:

розв'язати(Вузол, Вузол ---> Дер, МаксГлуб) :-

МаксГлуб > 0,

Вузол ---> або : Вузли, % Вузол - Або-Вузол

належить ( Вузол1, Вузли),

% Вибір спадкоємця Вузол1 вузла Вузол

Глуб1 = МаксГлуб - 1, % Нова межа по глибині

розв'язати(Bузол1, Дер, Глуб1). % Розв'язати

задачу-падкоємець із меншим обмеженням

Оцю процедуру пошуку вглиб з обмеженням можна також використовувати для імітації пошуку вшир. Ідея полягає в наступному: багаторазово повторювати пошук вглиб щораз з більшим значенням обмеження доти, поки розв'язок не буде знайдений. Тобто пробувати розв'язати задачу з обмеженням по глибині, рівним 0, потім - з обмеженням 1, потім - 2 і т.д. Така програма має вигляд:

% Проба пошуку зі зростаючим обмеженням,

починаючи з 0

імітація_вшир(Вузол,РешДер):-

проба_вглиб(Вузол, РешДер, 0).

проба_вглиб(Вузол,РешДер,Глуб):-

розв'язати( Верш, РешДер, Глуб);

Глуб1 = Глуб + 1, % Нова межа по глибині

проба_вглиб (Верш, РешДер, Глуб1). % Спроба

з новим обмеженням

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]