Upload
halyna-melnyk
View
51
Download
4
Embed Size (px)
Citation preview
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 ~