
- •Логічне програмування
- •Логічне програмування
- •7.080403 - “Програмне забезпечення автоматизованих систем”
- •Лабораторна робота № 1. Пролог - мова логічного програмування.
- •1.1.Загальний огляд мови Пролог.
- •1.2.Переваги і недоліки мови Пролог.
- •1.3.Числення предикатів - математична основа мови.
- •1.4.Побудова теорії деякої області знань.
- •1.5.Від формальної логіки до логічного програмування.
- •1.6.Механізм логічного виведення і керування пошуком.
- •Лабораторна робота №2 основні концепції прологу
- •2.1.Факти та правила.
- •2.2.Як змінні отримують свої значення.
- •2.3.Анонімні змінні.
- •2.4.Складні цілі: кон`юнкція та диз`юнкція.
- •2.5.Способи Співставлення.
- •Лабораторна робота № 3 структура програми pdc прологу
- •3.1.Основні розділи програми.
- •3.2 Стандартні домени.
- •3.3.Синтаксис правила.
- •3.4.Директиви комп`ютеру.
- •3.5.Бектрекінг.
- •3.5.1.Бектрекінг з внутрішньою ціллю.
- •Лабораторна робота № 4 контроль пошуку рішень
- •4.1.Використання предикату fail.
- •4.2.Відміна бектрекінгу.
- •1.Коли ви знаєте попередньо, що певні варіанти ніколи не дадуть поштовху в знаходженні розв'язку, тоді використання cut(зелений cut) відкидає перегляд альтернативних шляхів.
- •2.Коли логіка програми потребує використання cut для відкидання перегляду альтернативних підцілей, тоді його називають червоним відтинанням.
- •4.3.Предикат not - заперечення як неуспіх.
- •4.4.Труднощі у використанні відтинання і заперечення.
- •4.5.Засоби керування.
- •4.6.Узагальнення.
- •Лабораторна робота №5. Прості та складні об'єкти.
- •5.1 Прості дані.
- •5.1.1. Константи як об'єкти даних.
- •5.2.Складні об'єкти даних і функтори.
- •5.2.1.Уніфікація складних об`єктів.
- •5.2.2.Приклад застосування функторів.
- •5.3.Приклад використання складних об'зктів.
- •5.4.Опис доменів складних об'єктів.
- •5.5.Багаторівневі складні об'єкти.
- •5.6.Приклад, який ілюструє задання структури речення англійської мови.
- •5.7.Опис змішаних складних об'єктів.
- •5.7.1.Аргументи, які можуть мати різний тип.
- •5.7.2 Cписковий тип.
- •5.8.Порівняння складних об`єктів.
- •5.9.Узагальнення.
- •Лабораторна робота №6. Ітерація і рекурсія.
- •6.1.Реалізація ітераційного процесу за допомогою бектрекінгу.
- •6.2.Дії типу до і після.
- •6.3.Застосування бектрекінгу для реалізації циклів.
- •6.4.Рекурсивні процедури.
- •6.5.Використання аргументів в якості параметрів циклу.
- •Лабораторна робота №7 рекурсивні структури даних
- •7.1.Структура даних типу дерева.
- •7.2.Обходи дерева.
- •7.3.Створення дерева.
- •7.4.Бінарний пошук на дереві.
- •7.5. Сортування по дереву.
- •7.5.1 Програмна реалізація лексикографічного впорядкування при символьному вхідному потоці.
- •Лабораторна робота № 8 робота з списками в пролозі
- •8.1.Рекурсивна сутність списку.
- •8.2.Обробка списків.
- •8.2.1.Друк списків.
- •8.2.2.Підрахунок кількості елементів.
- •8.2.3.Іще один варіант підрахунку довжини списку.
- •8.2.4.Модифікація списку.
- •8.2.5.Належність елемента списку.
- •8.3.Використання одного й того ж предикату для вирішення різних задач.
- •8.4. Знаходження зразу всіх розв`язків.
- •8.5.Складні списки.
- •8.6.Реалізація синтаксичного аналізу за допомогою списків.
- •Лабораторна робота №9 техніка програмування в пролозі
- •9.1.Принципи побудови експертної системи.
- •9.2. Макетування: задача маршрутизації.
- •9.3.Пригоди в дивних печерах.
- •9.4. Моделювання апаратних засобів.
- •9.5.Задача про ханойські башні.
- •9.6.Ділення слів на склади.
- •9.7. Задача про n королев.
- •Лабораторна робота №10 особливі технічні прийоми для професіоналів
- •10.1.Потоковий аналіз.
- •10.2.Керування потоковим аналізом.
- •10.3. Стиль програмування.
8.2.4.Модифікація списку.
Модифікація списку заключається в якійсь зміні уже існуючого списку. Традиційно, така зміна проводиться послідовною обробкою елементів списку. Прикладом модифікації списку може служити програма, яка додає до кожного елементу списку 1.
Обчислення, які повинна виконувати програма, можна описати наступним чином:
1.Зв'язати голову і хвіст початкового списку відповідно з Head і Tail.
2.Зв'язати голову і хвіст результату з Head1 і Tail1
(Head1 і Tail1 ще не мають значень).
3.Додаючи 1 до Head, отримаємо Head1.
4.Рекурсивно додайте 1 до всіх элементів Tail, отримаєте Tail1.
Наступна програма реалізує запропонований алгоритм.
domains
list = integer*
predicates
add1(list, list)
clauses
add1([], []).
add1([Head|Tail], [Head1|Tail1]) :-
Head1= Head+1,
add1(Tail,Tail1).
Розглянемо ще одну програму модифікації списку. Вона сканує вхідний список і переписує його без від'ємних чисел.
domains
list = integer*
predicates
discard_negatives(list, list)
clauses
discard_negatives([], []).
discard_negatives([H|T], ProcessedTail) :-
/* якщо Н є від`ємним, тоді пропустити його */
H < 0, !,
discard_negatives(T, ProcessedTail).
discard_negatives([H|T], [H|ProcessedTail]) :-
discard_negatives(T, ProcessedTail).
Наступний предикат копіює елементи списку, повторюючи їх два рази.
doubletail([],[]).
dou bletail([H|T],[H|H| doubletail ]) : -
doubletail(T, doubletail ).
8.2.5.Належність елемента списку.
Припустимо, ми маємо список імен. Нам потрібно написати предикат, який би встановлював належність якогось імені (перший аргумент) вибраному списку імен (другий аргумент ). Нехай цим предикатом буде предикат:
member(name, namelist)
В наступній програмі перша фраза досліджує голову списку. Якщо голова списку співпадає з іменем, яке ми шукаємо , тоді можна зробити заключення, що ім`я належить списку. Тому, що в даному випадку хвіст списку нас не цікавить, він характеризується анонімною змінною. Якщо ж імені немає в голові, тоді його потрібно рекурсивним чином шукати в хвості списку. За це і відповідає друга фраза програми.
domains
namelist = name*
name = symbol
predicates
is_a_member_of(name, namelist)
clauses
is_a_member_of(Name,[Name|_]).
is_a_member_of(Name,[_|Tail]):- is_a_member_of(Name,Tail).
8.3.Використання одного й того ж предикату для вирішення різних задач.
Особливість ПРОЛОГУ заключається в тому, що коли ви будуєте предикат для вирішення якоїсь конкретної задачі , то він може використовуватись і для вирішення зовсім інших задач. Продемонструємо це на наступному прикладі. Побудуємо предикат конкатенації двох списків з трьома аргументами:
append(List1,List2,List3)
де List3 є результуючим списком. Використаємо наступний рекурсивний алгоритм.
Якщо перший список пустий, тоді результуючий список буде рівний другому списку (append([],List2,List2)). Інакше, головою третього списку становиться голова першого списку, а хвостом - залишок першого списку і другий список.
Прийдемо до програми:
domains
integerlist = integer*
predicates
append(integerlist, integerlist, integerlist)
clauses
append([], List, List).
append([X|L1], List2, [X|L3]) :-
append(L1, List2, L3).
Якщо ми задамо ціль
goal: append([1,2],[3,4]), тоді отримаємо список [1,2,3,4].
З іншого боку, розглядаючи предикат append з декларативної точки зору, ми визначили відношення між трьома списками. Таке відношення буде вірним і у випадку, коли буде відомий тільки третій список. Наприклад,
goal: append(L1,L2,[1,2,4] дасть результат
L1 = [], L2 = [1,2,[1,2,4]
l1 = [1], l2 = [2,4]
. . .
Також ви можете використати предикат append, щоб визначити який із списків можна додати до списку [3,4], щоб отримати список [1,2,3,4]. Наприклад, задавши
goal: append[L1,[3,4],[1,2,3,4] матимемо L1 =[1,2]
Предикат append визначає відношення між множинами на вході і виході. Тому відношення може використовуватись різними способами. Задаючи таке відношення, ви можете запитати:
Який вихід відповідає даному входу? або ж
Який вхід відповідає даному виходу?
Статус аргументів даного предикату при виклику, базується на зразку потоку даних. Предикат append може обробляти любий зразок потоку даних.
Але не всі предикати Прологу можуть бути викликані різними зразками потоку даних. Якщо фраза Прологу може оброблятись різними зразками потоку даних, тоді її називають інвертованою фразою. Зазначимо, що використання інвертованих фраз додає потужності вашим предикатам.