lect 3 4 prolog

80
СКЛАДНІ ОБЄКТИ ДАНИХ Лекція 3-4

Upload: halyna-melnyk

Post on 09-Aug-2015

61 views

Category:

Education


3 download

TRANSCRIPT

СКЛАДНІ ОБ’ЄКТИ ДАНИХ

Лекція 3-4

Обумовлені складені терми

•Функтори

•Списки

•РядкиНеобумовлені

терми•Рядки

•Оператори•Змінні

•Композити

Атоми

Змінні

ПРОСТІ ОБ’ЄКТИ ДАНИХ

Змінна або константа.

Змінна може зв'язуватися з довільним допустимим аргументом Прологу або об'єктом даних. Змінні Прологу локальні, а не глобальні.

Константи містять символи, числа і атоми (не плутайте константи в даному контексті з символьними константами, константи в даному контексті з символьними константами, визначеними в розділі constants програми !).

Анонімна змінна (_) використовується у випадках, коли потрібно використовувати змінну, але не потрібно співставляти її з певним значенням.

goal [ _,X2, _,X4|_ ] = [mia, vincent, marsellus, jody, yolanda].X2 = vincentX4 = jodyYes

КОНСТАНТИ. СИМВОЛИ

Символи мають тип char.

Символ-константа записується

наступним чином:

Символьні константи, що представляють спеціальні функції:

КОНСТАНТИ. ЧИСЛА. АТОМИ

Числа можуть бути цілими (integer) або дійсними (real).

Атоми – тип symbol або string. Відмінність між ними - питання

машинного подання та реалізації.

Функтор

Функтор

1. СКЛАДЕНІ ОБ’ЄКТИ ДАНИХ ТА ФУНКТОРИ

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

1. СКЛАДЕНІ ОБ’ЄКТИ ДАНИХ ТА ФУНКТОРИ

Аргументи складеного об'єкту даних можуть самі бути складеними об'єктами.

У складеного об'єкту birthday в цьому прикладі є дві частини:

об'єкт person ("Leo", "Jensen")

об'єкт date ("Apr", 14, 1960).

Функтори для цих об'єктів будуть person і date.

1. СКЛАДЕНІ ОБ’ЄКТИ ДАНИХ. УНІФІКАЦІЯ

Складений об'єкт може бути уніфікований з простою змінною або із складеним об'єктом (таким, що містить змінні в якості частин у внутрішній структурі), який йому відповідає.

співставляється з Х і присвоює Х значення date ("April", 14, I960).

співставляється з

І присвоює змінним Mo = "April", Da = 14 і Yr = I960.

Уніфікація:

мета зіставляється із заголовком пропозицій:

через знак рівності (=), який є інфіксним предикатом (предикатом, який розташований між своїми аргументами, а не перед ними).

1. СКЛАДЕНІ ОБ’ЄКТИ ДАНИХ. УНІФІКАЦІЯ

1. СКЛАДЕНІ ОБ’ЄКТИ ДАНИХ. ВИКОРИСТАННЯ ДЕКІЛЬКОХ ЗНАЧЕНЬ ЯК ОДНОГО ЦІЛОГО

1. СКЛАДЕНІ ОБ’ЄКТИ ДАНИХ. ВИКОРИСТАННЯ ДЕКІЛЬКОХ ЗНАЧЕНЬ ЯК ОДНОГО ЦІЛОГО

1. ПРИКЛАД ВИКОРИСТАННЯ СКЛАДЕНИХ ОБ’ЄКТІВ

Приклад.Створити список людей, у кого день народження в поточному місяці.

ПРИКЛАД ВИКОРИСТАННЯ СКЛАДЕНИХ ОБ’ЄКТІВ

1. ОГОЛОШЕННЯ СКЛАДЕНИХ ДОМЕНІВ.

Приклад. Програма, яка показує, як складові об'єкти з домену articles можуть використовуватися у фактах, які визначають предикат owns.

ТИПИ ДАНИХ КОРИСТУВАЧА

Предикат особа першим аргументом має структуру студент/2, а другим -структуру дата/3.

БАГАТОРІВНЕВІ СКЛАДЕНІ ОБ'ЄКТИ

book ("The Ugly Duckling", "Andersen“)

book ("The Ugly Duckling", author ("Hans Christian", "Andersen"))

book (title, author)

author = symbolauthor = symbol

author = author (first_name, last_name)

1. ВИЗНАЧЕННЯ СКЛАДЕНИХ ЗМІШАНИХ ДОМЕНІВ

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

3. ВИЗНАЧЕННЯ СКЛАДЕНИХ ЗМІШАНИХ ДОМЕНІВ. СПИСКИ

Припустимо, потрібно заповнити розклад занять з різних предметів, які можуть проводити різні викладачі. Можна написати наступну програму:

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

Тут було б зручно створити аргумент для предиката, який містить одне або декілька значень.

1. ВИЗНАЧЕННЯ СКЛАДЕНИХ ЗМІШАНИХ ДОМЕНІВ. СПИСКИ

Інший приклад – оголошення списку цілих

2. СПИСКИ

2. СПИСОК ЯК ЧАСТКОВИЙ ВИД СТРУКТУРИ

Під списком розуміють впорядковану послідовність елементів, яка може мати довільну довжину.

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

Список - це або порожній список, який не містить жодного елемента, або структура, що має два жодного елемента, або структура, що має два компоненти: голову та хвіст.

Кінець списку представляється як хвіст, який є порожнім списком.

2. СПОСОБИ ПРЕДСТАВЛЕННЯ СПИСКІВ

При використанні функторної форми запису голова і хвіст є компонентами функтора, що позначається крапкою ".".

При використанні графічної форми запису список представляється як спеціального виду дерево, що "зростає" зліва направо, причому гілки спрямовані вниз ("виноградне гроно").

При використанні дужкової форми запису послідовність елементів списку, що розділені комами, заключається у квадратні дужки.

2. ОГОЛОШЕННЯ СПИСКІВ

domains

integerlist = integer *

Символ (*) означає "список чого-небудь»

Елементи списку можуть бути будь-якими, включаючи інші списки. Однак всі його елементи повинні належати одному домену. Декларація домену для елементів повинна бути наступного вигляду:

domains

elementlist = elements *elementlist = elements *

elements = ....

У Visual Prolog можна змішувати стандартні типи в списку.

elementlist = elements *

elements = integer; real; symbol / * Невірно * /

Але правильно:

elementlist = elements *

elements = i (integer); r (real); s (symbol) % функтори тут i, r і s

2. ВИЗНАЧЕННЯ СПИСКІВ

Робота зі списками заснована на розщепленні на голову і хвіст: [Head | Tail].

Голова є перший аргумент функтора " | ", хвіст -другий: (Head | [Tail]]).

Функтор «|» використовується для конструювання списку. списку.

Хвіст списку є списком, що складається з усіх елементів вихідного списку, за винятком першого.

Приклади:

[1,2,3]-Head: 1, Tail: [2,3]; [[1], [2]]-Head: [1], Tail: [[2]].

ПРИКЛАД 1

[mia, vincent, jules, yolanda]

Head: mia

Tail: [vincent, jules, yolanda]

ПРИКЛАД 2

[[ ], dead(z), [2, [b,c]], [ ], Z, [2, [b,c]]]

Head: [ ]

Tail: [dead(z), [2, [b,c]], [ ], Z, [2, [b,c]]]

ПРИКЛАД 3

[dead(z)]

Head: dead(z)

Tail: [ ]

3. РОБОТА ЗІ СПИСКАМИ

3. СТВОРЕННЯ СПИСКІВ

findall(X,predecessor(pam,X),Preds).

Вихідний списокЗмінна запиту

Программа використовує findall для друку середнього віку групи людей

3. СТВОРЕННЯ СПИСКІВ

Пошук особи за віком

3. СТВОРЕННЯ СПИСКІВ

3. СТВОРЕННЯ НОВОГО СПИСКУ НА ОСНОВІ ДАНОГО

Приклад програми, яка переглядає список із чисел і робить з нього копію, відкидаючи від’ємні числа.

3. СТВОРЕННЯ НОВОГО СПИСКУ НА ОСНОВІ ДАНОГО

Приклад програми, яка копіює елементи списка, примушуючи кожний елемент повторюватися двічі

3. ВБУДОВАНИЙ ОПЕРАТОР |

goal [X|Y] = [mia, vincent, jules, yolanda].

X = miaY = [vincent,jules,yolanda]Yes

goal [X|Y] = [ ].

no

goal [X,Y|Tail] = [[ ], dead(z), [2, [b,c]], [], Z, [2, [b,c]]] .

X = [ ]Y = dead(z)Z = _4543 Tail = [[2, [b,c]], [ ], Z, [2, [b,c]]] Yes

3. ВИКОРИСТАННЯ АНОНІМНИХ ЗМІННИХ

goal [X1,X2,X3,X4|Tail] = [mia, vincent, marsellus, jody, yolanda].X1 = miaX2 = vincentX3 = marsellusX4 = jodyTail = [yolanda]Yes

goal [ _,X2, _,X4|_ ] = [mia, vincent, marsellus, jody, yolanda].X2 = vincentX4 = jodyyes

3. ПРОГРАМНА РОБОТА ЗІ СПИСКОМ

Опис списку

Введення списку

Виведення списку

3. ВИВЕДЕННЯ СПСИКУ

Виводити порожній список -значить нічого не робити.

Інакше, виводити список - означає друкувати його голову (яка є однимелементом), потім друкувати його хвіст (список).

3. ВИЗНАЧЕННЯ КІЛЬКОСТІ ЕЛЕМЕНТІВ СПИСКУ

Логічне визначення:Довжина [] - 0.Довжина будь-якого іншого списку - 1 плюс довжина його хвоста.

3. ВИЗНАЧЕННЯ КІЛЬКОСТІ ЕЛЕМЕНТІВ СПИСКУ

… або хвостова рекурсія.

3. ПЕРЕТВОРЕННЯ ЕЛЕМЕНТІВ СПИСКУ

Додасть 1 до кожного елементу числового списку.

Щоб додати 1 до всіх елементів порожнього списку, треба створити інший порожній список.

Щоб додати 1 до всіх елементів будь-якого непорожнього списку, треба додати 1 до голови і зробити отриманий елемент головою результуючого списку, потім додати 1 до кожного елементу хвоста списку і зробити це хвостом результату.

3. ПРИНАЛЕЖНІСТЬ ДО СПИСКУ

… виражається предикатомmember (name, namelist). % "Name" належить "namelist”

Name належить списку, якщо Name є перший елемент списку, абоName належить списку, якщо Nameналежить хвосту.

3. ПРОЦЕДУРА ПЕРЕВІРКИ НАЛЕЖНОСТІ СПИСКУ

"деякий елемент міститься у списку елементів, якщо він є або головою списку, або міститься у хвості списку".

Гранична умова (1): число належить списку число належить списку цілих чисел, якщо воноє головою списку.

Рекурсивне правило (2): число, яке не являється головою списку, належить йому, якщо воно належить хвосту списку.

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

L1H L2

[H|L1]

L3

L3H

L3

3. ОБ'ЄДНАННЯ

СПИСКІВ.

Рекурсивне визначення

Базове твердження: з’єднання порожнього списку з довільним списком дає той самий список

Рекурсивний крок стверджує, що з’єднання непорожнього списку [H|T] з списком L, дає список з головою H і результат з’єднання T і L

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

goal conc([a,b,c],[1,2,3], R).

conc([], L, L).conc([H|L1], L2, [H|L3]):- conc(L1, L2, L3).

conc([a,b,c],[1,2,3], R).

/ \

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)/ \

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)/ \

† L0=[b|L1]

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

† L0=[b|L1]conc([c],[1,2,3],L1)

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)/ \

† L0=[b|L1]

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

† L0=[b|L1]conc([c],[1,2,3],L1)

/ \

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)/ \

† L0=[b|L1]

conc([], L, L).conc([H|L1], L2, [H|L3]):-

append(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

† L0=[b|L1]conc([c],[1,2,3],L1)

/ \

† L1=[c|L2]conc([],[1,2,3],L2)

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)/ \

† L0=[b|L1]

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

† L0=[b|L1]conc([c],[1,2,3],L1)

/ \

† L1=[c|L2]conc([],[1,2,3],L2)

/ \

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)/ \

† L0=[b|L1]

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

† L0=[b|L1]conc([c],[1,2,3],L1)

/ \

† L1=[c|L2]conc([],[1,2,3],L2)

/ \

L2=[1,2,3]

conc([a,b,c],[1,2,3], R).

/ \

† R = [a|L0]conc([b,c],[1,2,3],L0)/ \

† L0=[b|L1]

conc([], L, L).conc([H|L1], L2, [H|L3]):-

conc(L1, L2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. ДЕРЕВО РІШЕНЬ

† L0=[b|L1]conc([c],[1,2,3],L1)

/ \

† L1=[c|L2]conc([],[1,2,3],L2)

/ \

L2=[1,2,3] †

L2=[1,2,3]L1=[c|L2]=[c,1,2,3]L0=[b|L1]=[b,c,1,2,3]R=[a|L0]=[a,b,c,1,2,3]

3. ОБ'ЄДНАННЯ СПИСКІВ. РЕКУРСІЯ З ПРОЦЕДУРНОЇ ТОЧКИ ЗОРУ

append (List1, List2, List3)

Якщо List1порожній, то результатом об'єднання List1 і List2 залишиться List2 : append ([], List2, List2).List2).

Якщо List1 не порожній, то можна об'єднати List1 і List2для формування List3, зробивши голову List1 головою List3 :append ([H | L1], List2, [H | L3]): -append (L1, List2, L3).

3. ОБ'ЄДНАННЯ СПИСКІВ. РЕКУРСІЯ З ПРОЦЕДУРНОЇ ТОЧКИ ЗОРУ

3. ОБ'ЄДНАННЯ СПИСКІВ. РЕКУРСІЯ З ДЕКЛАРАТИВНОЇ ТОЧКИ ЗОРУ

3. СКЛАДЕНИЙ СПИСОК

Приклад, який демонструє об’єднання списків та використання оголошення доменів в типовому випадку роботи зі списками.

3. ДОДАТИ ЕЛЕМЕНТ В СПИСОК

Код:

LX

[X|L]

LX

add(X,L,[X|L]).

Приклад:

add(a,[1,2,3],L).

L

[L]

3. ЗНИЩИТИ ЕЛЕМЕНТ ЗІ СПИСКУ

Вважаємо, що del(X,L,L1), знищує X з L і переміщує новий список в L1.

Код:

del(X,[X|Tail],Tail). % якщо X голова списку Ldel(X,[Y|Tail], [Y|Tail1]):- del(X,Tail,Tail1).del(X,[Y|Tail], [Y|Tail1]):- del(X,Tail,Tail1).

Приклад:

del(1,[1,2,3],L).

[Y|L1]

L1YLX

L

[Y|L ]

YX

3. ПІДСПИСОК

S є підсписком L якщо:

(1) L може бути розбитий на 2 списка L1, L2 і

(2) L2 може бути розбитий на 2 спика: S і деякий L3

L1 L2X member(X,L)

L

member(X,L)

L1 L3S

L2

L[X|L2]

sublist(S,L)

sublist(S,L):- conc(L1,L2,L),conc(S,L3,L2).

3. ВСТАВКА ЕЛЕМЕНТА

insert (X, List, BiggerList) :-

del (X, BiggerList, List).del (X, BiggerList, List).

3. ПЕРЕСТАНОВКА

Відношення перестановка з 2-ма аргументами в 2-х списках таким чином, щоб один з них був отриманий шляхом перестановки елементів іншого.

goal permutation( [a,b,c], P ).

P = [a,b,c];

P = [a,c,b];

P = [b,a,c];

X L

додати X отримуючи …

приклад:goal permutation( [red,blue,green], P ).P = [red, blue, green];P = [red, green, blue];P = [blue, red, green]; P = [blue, green, red];P = [green, red, blue];P = [green, blue, red];no

L1

перестановку [X | L]

L1 - перестановка L

1.Якщо список порожній, нова перестановка є порожньою перестановкою ([],[]).

2. Якщо список не порожній, він має вигляд [X|L].2. Якщо список не порожній, він має вигляд [X|L].

permutation([X|L],P):-permutation(L,L1),insert(X,L1,P).

66

3. СОРТУВАННЯ СПИСКУ МЕТОДОМ ВСТАВКИ.

Cпочатку впорядкуємо хвіст, а потім вставимо головув потрібне місце хвоста.

Порожній список – впорядкований.

sort ( [ ], [ ]).

sort ( [ H | T ], S) :- sort (T, S1), insert (H, S1, S).sort ( [ H | T ], S) :- sort (T, S1), insert (H, S1, S).

insert (H, [ ], [H]).

insert (H, [ Y | T ], [ H | S ]) :- H<Y, S=[Y | T].

insert (H, [ Y | T ], [ Y | S ]) :- H>=Y, insert (H, T, S).

3. СКЛАДЕНИЙ СПИСОК

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

Приклад оголошення доменів для списку, який може містити символи, цілі, рядки або списки:цілі, рядки або списки:

domains % функтори l, i, c та sllist = l(list); i(integer); c(char); s(string)list = llist *

список[2, 9, ["food", "goo"], "new"] % Некоректно в Visual Prolog

повинен бути представлений в Visual Prolog як:[ i(2), i(9), l([s(“food”), s(“goo")]), s(“new") ] % Коректно.

ГРАМАТИЧНИЙ РОЗБІР СПИСКІВ

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

ГРАМАТИЧНИЙ

РОЗБІР СПИСКІВ

ГРАМАТИЧНИЙ

РОЗБІР СПИСКІВ

ГРАМАТИЧНИЙ РОЗБІР СПИСКІВ

4. РЯДКИ

4. РЯДКИ

Предикат frontchar працює згідно рівності:

String1 = об’єднання Char і String2:

frontchar (Stringl, Char, String2) %(i, o, o) (i, i, o) (i, o, i) (i, i, i) (o,i, i)

4. РЯДКИ

fronttoken (Stringl,Token,Rest) %(i, o, o) (i, i, o) (i,o,i) (i, i,i) (o, i, i)

У випадку потоку (i, o, o) fronttoken знаходить першу лексему в string1, звязує її з Token, а залишок string1 звязує з Rest.

Варіанти потока (i, i,o), (i, o, i), а також (i, i, i) служать для перевірки: якщо звязані аргументи відповідаються частинам String1 (першій лексемі, всьому, що знаходиться після першої лексеми, або ж і тому і лексемі, всьому, що знаходиться після першої лексеми, або ж і тому і другому), то fronttoken завершується успішно, інакше — неуспішно.

У випадку потоку (o, i, i), предикат створює обєднання Token і Rest, звязуючи string1 з результатом.

Послідовність знаків є лексемою, якщо вона:

- імя згідно синтаксису Visual Prolog;

- число (знак є окремою лексемою);

- відмінний від «пробілу» знак.

4. РЯДКИ

4. РЯДКИ

Предикат frontstr розщеплює string1 на дві частини:

frontstr(NumberOfChars, String1, StartStr, EndStr)

% (i, i, o, o)

де startstr містить NumberOfChars перших символів з string1, a Endstr містить залишок.

При зверненні до frontstr перші два параметра повинні бути звязаними, а останні два — вільними.звязаними, а останні два — вільними.

Предикат concat встановлює, що рядок strings є результатом зчеплення String1 і String2:

concat(Stringl,String2,StringS) %(i, i, o),(i, o, i),(o, i, i),(i, i, i)

Предикат str_len визначає або перевіряє довжину рядка або повертає рядок «пробілів» заданої довжини:

str_len (StringArg, Length) % (i, o), (i, i), (o, i)

4. РЯДКИ

4. РЯДКИ

4. РЯДКИ