Lect 2 prolog

Post on 09-Aug-2015

54 views 4 download

Transcript of Lect 2 prolog

Prolog

Logic Programming LanguageLogic Programming Language

Лекція 2

Управління обчисленнями

Alain Colmerauer

(1971 University of Aix-Marseille )

Robert KowalskiRobert Kowalski

(University of Edinburgh до 1975)

Декларативна мова заснована на логіці предикатів.

Предикати:

Предикати + квантори = речення

Ім’я предикату

Предикати + квантори = речення

Резолюція (“якщо маємо”):

Будуємо:

Змістові форми (твердження) Хорна

Твердження Хорна vs Правила

Prolog програма складається з фактів та правил.

Факти – властивість об’єкту чи зв’язок між об’єктами:

parent(jane,alan).

читається як “Jane is the parent of Alan.”

Правила - висновок про властивість чи зв ’ язок, що побудований на передумовах.

parent(X,Y) :- mother(X,Y).

= “Person X is the parent of person Y if X is Y’s mother.”

І факти і правила є предикатами

Визначення предикатів складають clauses (“змістова форма”).

= індивідуальне визначення (чи то факт, чи правило).

mother(jane, alan). = факт

parent(P1,P2):- mother(P1,P2). = правило

голова тіло

clause складається з голови

та інколи має тіло.

-- факти не мають тіло,

оскільки вони завжди мають значення “істина”.

Голова предикату складається з імені предикату та інколиаргументів.

mother(jane, alan).

Тіло можу бути утворене з декількох підцілей (викликів

Ім’я предикату аргументи

Тіло можу бути утворене з декількох підцілей (викликів інших предикатів) і термів.

Аргументи також складаються з термів:

-- константи jane

-- змінні Person1

-- складених термів

Константи:

Число: цілі ( 1, 0, -1, etc) дійсні (3.0E7)

Символьні: Починаються з малої літери символа алфавіту і містять

літери, цифри, _ (але не “пробіл”, знаки пунктуації чи великі літери).

abc, big_long_constant, x4_3t. рядкові константи:

“дещо” в ‘Like this’.

• Змінні завжди починаються з великої літери або _X, ABC, _89two5, _very_long_variable

“Типи” для змінних (або констант) відсутні – змінна набуває довільного значення.Всі Prolog змінні мають “локальний” контекст:

--- вони зберігають своє значення в межах clause-у; --- та сама змінна поза clause не утримує це значення.

• Імена:Використовуйте явні імена предикатів чи змінних.

“John wants to help Somebody.”може: wants(john, to_help, Somebody).не може: x87g(j,_789).

Використовуйте Verb Subject Object структуру:wants (john, to_help).

Приклади фактів (facts): male(adam). female(anne). parent(adam,barney).

Приклади правил (rules): 1. son(X,Y) :- parent(Y,X) , читається:

→For all X and Y, X is the son of Y if there exists X &→For all X and Y, X is the son of Y if there exists X &Y (X,Y)

→such that Y is the parent of X and X is male.

2. male(X), daughter(X,Y) :- parent(Y,X) , female(X) Читається як:

→For all X and Y, X is the daughter of Y ifthere exists X & Y

→such that Y is the parent of X and X is female.

Базова структура

Факти

Правила

Запити

Коллекція фактів та правил називається “базою знань”(database)

Коллекція фактів та запитів описує деяку область відношень.

Prolog Program

Facts Rules(Relationships)

Questions(Goals)

Clauses

Структура Prolog програми:

• опис доменівdomains

• опис предикатів

• динамічної бази данихdatabase

• опис предикатівpredicatespredicates

• цільове твердженняgoal

• твердженняclauses

Hello:-

nl,

write('Hello world!' ).

Узгодження:

Успішне узгодження

Арифметичні операції:+, –, *, /, mod, div.

Операції порівняння(відношення): < , <=, >, >=, =, <> (><)

Операції перевірки типу.

Стандартні предикати:not (Атом)

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

free (Змінна)free (Змінна)- перевіряє, чи аргумент Змінна є неконкретизована змінна. Виконується успішно, якщо Змінна не зв'язана певним значенням. Прототип: (і).

bound(Змінна)– перевіряє, чи аргумент Змінна є конкретизована змінна. Вико-нується успішно, якщо Змінна зв‘язана. Прототип: (о).

(1) забезпечується знаходження середнього арифметичного двох даних чисел (R - змінна у запиті) та перевірка факту того, що у трійці аргументів запиту сеp_ар/3 останній аргумент є числом - середнім арифметичним перших двох чисел (R -константа у запиті).

(3) запит буде виконано успішно, якщо у запиті X - число, Y - змінна, R - число..

(2) знаходиться перше з трьох чисел, якщо дано друге число та значення середнього арифметичного двох чисел (X - змінна у запиті).

Стандартні предикати перетворення :

char_int (Символ, Число)-перетворює символ у ціле число - ASCII код символу або навпаки. Символ - тип char. Число - тип integer. Прототип: (і, о), (о, і), (і, і).

str_int (Рядок, Число) - перетворює рядок символів у ціле число або навпаки. Рядок символів не може містити інших символів, крім символів-цифр; символ "пробіл" може міститися тільки на початку або у кінці рядка. Рядок - тип string. Число - тип integer.integer.Прототип: (і, о), (о, і), (і, і).

str_char (Рядок, Символ)-перетворює рядок символів, що складається з єдиного символу, у символ або навпаки. Рядок - тип string. Символ - тип char. Прототип: (і, о), (o, і), (і, і).

str_real (Рядок, Число) - перетворює рядок символів у дійсне число або навпаки. Рядок символів не може містити інших символів, крім символів-цифр, символу "десяткова крапка" та символу E (символ, що вказує на порядок числа при його представленні у плаваючій формі); символ "пропуск" може міститися тільки на початку або в кінці рядка.Рядок - тип string. Число - тип real. Прототип: (і, о), (o, i), (i, і).

Обчислення значень числових функцій

readint(X)

readreal(X)

readchar(X)

readln(X) (<=147)

write(X)

nl

Предикати введення-виведення

Співставлення - процес порівняння термів на збіг

Уніфікація — збіг цілі з головою правила або фактом.

goal green(X),edible(X). Green(p) Green(b)

Root

green(poisonivy).green(broccoli).edible(icecream).edible(broccoli).

1 1 Call: green(poisoniyy) ?1 1 Exit: green(poisonivy) ?2 1 Call: edible(poisonivy) ?2 1 Fail: edible(poisonivy) ?1 1 Redo:green(poisonivy)1 1 1 Call: green(broccoli) ?1 1 Exit: green(broccoli) ?2 1 Call: edible(broccoli) ?2 1 Exit: edible(broccoli) ?

Edible(p) Edible(b)

Answer

Приклад 1

? перевірка! уніфікація

? перевірка! уніфікація

Приклад 2

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

? перевірка ! уніфікація

узгодження підцілі з правилом

співставлення “успіх”співставлення “неуспіх”

! уніфікація

1

2

3

4

5

Нехай студентові залежно від набраної в процесі навчання суми балів Z присвоюється кваліфікація відповідно до таблиці

При запиті виду grade(53,G) успіх принесе тільки третій рядок, причому перші перевірки в другому й третьому рядках свідомо зайві внаслідок негативного результату для попереднього рядка.

Однак при цьому на запит можуть бути послідовно отримані всі чотири можливих відповіді.

Тому кращим буде варіант повної програми, у якому задоволення умовам одного варіанта виключає всі наступні

властивості відсікання:

3. Відсікання не впливає на цілі, розташовані правіше.

властивості відсікання:1. Відсікання відкидає всі розташовані після нього речення.2. Кон'юнкція цілей, що стоять перед відсіканням, приводить не більш ніж

до одного рішення,3. Відсікання не впливає на цілі, розташовані правіше.

With Out Cut

grade(G,a) :- G > 90.grade(G,b) :- G > 80.

With Cut

grade2(G,a) :- G > 90, !.grade2(G,b) :- G > 80, !.grade(G,b) :- G > 80.

grade(G,c) :- G > 70.grade(G,d) :- G > 60.grade(_,f).

grade2(G,b) :- G > 80, !.grade2(G,c) :- G > 70, !.grade2(G,d) :- G > 60, !.grade2(_,f).

Forced Backtrack With Grade

?- grade(83,X)X = b;X = c;X = d;X = fyes

Forced Backtrack With Grade2

?- grade2(83,X)X = b;yes

Forced back tracking

Три способи реалізації правил, що виконують ті Три способи реалізації правил, що виконують ті самі операції багаторазово:

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

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

:-fib(3,F).

N=3, M=2, K=1,використовують самовиклики. Повтор користувача використовує штучне зациклення.

fib(0,1). fib(1,1).fib(N,F) :- N=M+1, M=K+1, fib(M,G),

fib(K,H), F=G+H, N>1.

N=3, M=2, K=1,

F = G + H

:-fib(2,F).

N=2, M=1, K=0,

F = G + H

:-fib(1,F).

F = 1

:-fib(1,1).

:-fib(0,F).

F = 1

:-fib(0,1).

:-fib(1,F).

F = 1

:-fib(1,1).

Вид правила, що виконує повторення відкату:

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

Змусити Пролог виконати відкат до найближчої альтернативи може будь-який предикат, що завершився невдало. Але тільки наявність fail або іншого тотожно хибного предиката забезпечить перебір всіх альтернатив.

Вид правила повтору, обумовленого користувачем,

Твердження repeat викликає повторне виконання всіх наступних за ним компонентів.

відкат до правила repeat

1) Використовуючи предикати male/1, female/1, іparent_of/2 to опишіть Вашу родину в Prolog knowledge base

2) Сформулюйте правила для наступних відносин:

father(Father,Child) father(Father,Child) mother(Mother,Child) grandparent(Grandparent,Child) sister(Sister,Person) grandchild(Grandchild,Child)

father_of(X, Y) :- male(X), parent(X, Y).

Ex:grandparent(X, Z) :- parent(X, Y), parent(Y, Z).

Знайдіть предків (ancestor)

ancestor( Old, Young ) :- parent( Old, Young ).ancestor( Old, Young ) :- parent( Old, Middle ), ancestor( Middle, Young ).

ancestor( Old, Young ) :- parent( Old, Young ).ancestor( Old, Young ) :- parent( Old, Middle ), ancestor( Middle, Young ).

Base case

Recursive-clause

Example run:

?- ancestor( paul, harry ).

Call: ancestor(paul, harry ).

Call: parent(paul, harry ).

Fail.

Retry: ancestor(paul, harry ).

Call: parent(paul, Middle ).

ancestor( Old, Young ):-parent( Old,Young ).ancestor( Old, Young ):-parent( Old,Middle ), ancestor( Middle, Young ).

Call: parent(paul, Middle ).

Unify: Middle = lili.

Succeed: parent(paul, lili ).

Call: ancestor( lili, harry ).

Call: parent( lili, harry).

Succeed: parent( lili, harry ).

Succeed: ancestor( lili, harry ).

Succeed: ancestor(paul, harry)

RECURSIVE

Інше (узагальнене) правило рекурсії:Інше (узагальнене) правило рекурсії:

Дане правило рекурсії має 5 компонентів:(1) - це група предикатів. Не один з них не повинен впливати на рекурсію

(тобто перевіряти умови тощо) Найбільш часті предикати цієї частини -виведення, введення, присвоювання.

(2) - предикат умови виходу. Успіх чи невдача цього предиката або дозволяє продовжити рекурсію, або викликає її зупинку.

(3) - список інших предикатів. Не один з них не повинен впливати на рекурсію.

(4) - саме рекурсивне правило. Успіх цього правила викликає рекурсію.(5) - список предикатів. Жоден з них не повинен впливати на рекурсію

У вихідній рекурсії будується така рекурсивна структура, за якою, щоб довести деякий факт, необхідно довести попередньо-рекурсивний факт …. і т.д., доки цей процес не дійде до перевірки граничної умови.

за правилом (1) А є предком В, якщо А -один з батьків В; за правилом (2) А є предком В, якщо А є предком одного з батьків В, тобто предком С.

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

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

Приклад:Приклад:dog (X) :- dog (Y), parent (Y, X).dog (reks).

При спробі узгодити цільове твердження dog (X)Пролог спочатку намагається використати правило і рекурсивно породжує підціль dog (Y).

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

Накопичувач L (початкове значення 1 ) є логічною змінною, а не коміркою пам'яті. У процесі рекурсії передається не адреса, а значення.

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

Ця операція називається оптимізацією хвостовій рекурсії (tail recursion optimization) або оптимізацією останнього дзвінка (last-call optimization). З технічних причин оптимізація останнього дзвінка незастосовна до рекурсивних функцій.

Фраза «одна процедура викликає іншу, виконуючи свої самий останній крок» мовою Пролог означає:(1) виклик є найостаннішою підціллю

пропозиції,(2) раніше в пропозиції не було точок

поверненняПриклад, що задовольняє обом умовам:

predicates count(ulong)clauses

count(N):-write('\r',N), NewN = N+l, count(NewN).

GOAL nl, count(0).

predicates

fact(integer,integer)

clauses

fact(X,Y):-X=0,Y=1.

Recursive

int factorial(int X)

{

if(X==0)fact(X,Y):-X=0,Y=1.

fact(X,Y):- Z=X-1,

fact(Z,NZ),Y=NZ*X.

if(X==0)

return 1;

else

return X*factorial(X-1);

}

predicates

fact(integer,integer)

clauses

fact(0,1).

Recursive

int factorial(int X)

{

if(X==0)

Stack overflowfact(0,1).

fact(X,Y):- Z=X-1,

fact(Z,NZ),Y=NZ*X.

if(X==0)

return 1;

else

return X*factorial(X-1);

}

predicates

fact(integer,integer)

clauses

fact(0,1):-!.

Recursive

int factorial(int X)

{

if(X==0)fact(0,1):-!.

fact(X,Y):- Z=X-1,

fact(Z,NZ),Y=NZ*X.

if(X==0)

return 1;

else

return X*factorial(X-1);

}

Tracing

fact(4,Y).

Match with the second rule:

fact (4, Y ):- Z=4-1=3, fact (3,NZ),Y=NZ*4.

Match with the second rule:

fact (3,Y):- Z=3-1=2, fact (2,NZ),Y=NZ*3.

Match with the second rule:

2 2

6 6

6

24

Y=24

0

Match with the second rule:

fact (2,Y):- Z=2-1=1, fact (1,NZ),Y=NZ*2.

Match with the second rule:

fact (1,Y):- Z=1-1=0, fact (0,NZ),Y=NZ*1.

Match with the first rule:

fact (0,1).Then Y=1

1 12

1 1 1

predicates

fact(integer,integer)

fact_aux(integer,integer,integer)

clausesclauses

fact(X,F):-fact_aux(X,F,1).

fact_aux(0,F,Acc):- F=Acc,!.

fact_aux(X,F,Acc):-

NAcc=Acc*X, NX=X-1,

fact_aux(NX,F,NAcc).

Acc=1;

for(int i=X;i>0;i--)

{

Acc=Acc*i;

}

predicates

fact(integer,integer)

fact_aux(integer,integer,integer)

clausesclauses

fact(X,F):-fact_aux(X,F,1).

fact_aux(0,F,F):-!.

fact_aux(X,F,Acc):-

NAcc=Acc*X, NX=X-1,

fact_aux(NX,F,NAcc).

2 ? 3

3 ? 1

X F Acc NAcc NX

3 2

6 1

*=

1 ? 6

0 ? 6

6 0

predicates

power(integer,integer,integer)

clauses

power(X,0,1):-!.power(X,0,1):-!.

power(X,N,P):-Z=N-1,power(X,Z,NP),P=NP*X.

goal

power(2,4,X).

Tracing

power(2,4,P).

Match with the second rule:

power(2,4, P ):-Z=4-1=3, power(2,3,NP),P=NP*2.

Match with the second rule:

power(2,3,P):-Z=3-1=2, power(2,2,NP),P=NP*2.4 4

8 8

8

16

P=16

Match with the second rule:

power(2,2,P):- Z=2-1=1, power(2,1,NP),P=NP*2.

Match with the second rule:

power(2,1,P):- Z=1-1=0, power(2,0,NP),P=NP*2.

Match with the first rule:

power(2,0,1).Then P=1

2 24

4 48

1 12

predicates

power(integer,integer,integer)

power_aux(integer,integer,integer,integer)

clausesclauses

power(X,N,P):- power_aux(X,N,P,1).

power_aux(_,0,P,P):-!.

power_aux(X,N,P,Acc):-

Nacc=Acc*X, Z=N-1,power_aux(X,Z,P,Nacc).

Acc=1;

for(int i=N;i>0;i--)

{

Acc=Acc*X;

}

2 3 ? 2

2 4 ? 1

X N P Acc NAcc Z (new N)

2 3

4 2

*=

2 2 ? 4

2 0 ? 16

2 1 ? 8

8

16

1

0

fib(0)=1

fib(1)=1

fib(X)=fib(X-1)+fib(X-2)

Ex:

X 0 1 2 3 4 5

F(X) 1 1 2 3 5 8

F(X)=F(X1)+F(X2)

predicates

fib(integer,integer)

clauses

fib(1,1):-!.fib(1,1):-!.

fib(0,1):-!.

fib(X,Y):-

M=X-1,N=X-2,

fib(M,B),fib(N,A),Y=A+B.

predicates

fib(integer, integer)

fib_aux(integer, integer, integer, integer)

clauses

fib(X, Fib):-

fib_aux(X, Fib,1, 1).

int fib (int X)

{

int first = 1;

int second = 1;

for(int i = X; i>1; i--)fib_aux(X, Fib,1, 1).

fib_aux(1, Second,_, Second):-!.

fib_aux(X, Fib,First, Second):-

NewX = X - 1,

NewFirst = Second,

NewSecond = First + Second,

fib_aux(NewX, Fib, NewFirst, NewSecond).

for(int i = X; i>1; i--)

{

int temp=first;

first = second;

second = temp + second;

}

return second;

}

In this puzzle, we have three pegs and several disks, initially stacked from largest to smallest on the left peg

Our goal is to move the entire tower to the middle peg

We can only move one disk at a time

We can use right peg to temporally hold the disks

We can never place a larger disk on a We can never place a larger disk on a smaller disk in any peg

A B C

A B C

A B C

A B C

A B C

A B C

A B C

A B C

Recursive solution

- Move N - 1 discs from stack 1 to 3 with the help of stack 2.

- Move the Nth disc from 1 to 2- Move the N disc from 1 to 2

- Move N - 1 discs from stack 3 to 2 with the help of stack 1

Implementation in Prolog

hanoi(N) :- dohanoi(N, 1, 2, 3).

dohanoi(0, _ , _ , _ ) :- !.

dohanoi(N, A, B, C) :- N_1 is N-1,

dohanoi(N_1, A, C, B), moveit(A, B), moveit(A, B), dohanoi(N_1, C, B, A).

moveit(F, T) :- write([move, F, -->, T]), nl.

Output when n=3

?- hanoi(3).

[move,1,-->,2]

[move,1,-->,3]

[move,2,-->,3][move,2,-->,3]

[move,1,-->,2]

[move,3,-->,1]

[move,3,-->,2]

[move,1,-->,2]

yes

Output when n=4

?- hanoi(4).

[move,1,-->,3]

[move,1,-->,2]

[move,3,-->,2]

[move,1,-->,3]

[move,2,-->,1]

[move,2,-->,3]

[move,1,-->,3]

[move,1,-->,2][move,1,-->,2]

[move,3,-->,2]

[move,3,-->,1]

[move,2,-->,1]

[move,3,-->,2]

[move,1,-->,3]

[move,1,-->,2]

[move,3,-->,2]

yes

THANK YOU …

Bye Bye ~