03_LR_FLP

Лабораторна робота №3
Списки
Цілі роботи:
ознайомлення з складними структурами даних у мові Prolog
одержання практичних навичок роботи зі списками та структурами при написанні правил на мові Prolog
Завдання:
Створити базу даних програми з фактів, які описують результати сесії студентів у вигляді:
student(Group, Fam, [D1/M1, D2/M2, D3/M3, D4/M4]).
де: D – назва дисципліни, M – відповідна оцінка, Group – навчальна група, Fam – прізвище студента. Отримати список об’єктів даних відповідно завдання (таблиця. 3.1) та вивести його у табличній формі.
Таблиця 3.1 – Варіанти завдань

№ варіанту
Зміст завдання


Студенти, що одержали тільки відмінні оцінки


Студенти, що одержали відмінну оцінку з вказаної дисципліні


Студенти, прізвище яких починається з зазначеної літери


Студенти, які отримують стипендію за результатами сесії (правила встановити самостійно)


Студенти, що отримали хоча б одну незадовільну оцінку


Студенти, що отримали більш двох незадовільних оцінок


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


Список студентів, упорядкований за середній бал


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


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


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


Список груп і кількості відмінних оцінок


Список груп і кількість студентів, що отримали позитивні оцінки


Список груп і кількість студентів, що мають середній бал вище вказаного


Список студентів і розмір стипендії за результатами сесії


Теоретичні відомості
Визначення списку у мові Prolog
Список – це послідовність з будь-якої кількості елементів. Кожний елемент може бути будь-яким термом, припустимим у Prolog, в т.ч. списком [1].
Список має структуру бінарного дерева. Для позначки списку використовується функтор «./2» (крапка) з двома аргументами:
.(Head, Tail),
Де:
Head – голова списку, у якості якого може бути будь-який терм;
Tail – хвіст списку, у якості якого може бути тільки список.
Таким чином, послідовність з чотирьох констант a, b, c, d, що складають список, можна представити у вигляді структури:
.(a, . (b, . (c, . (d, [])))),
де [] – пустий список.
Для більш зручної позначки списку застосовується інша форма запису – у квадратних дужках перелічуються елементи через кому:
[a, b, c, d]
Якщо потрібно виділити хвіст списку, використовується символ «|» (вертикальна риса), який розділяє один або декілька елементів списку від хвоста:
[a | T]
список містить голову і хвіст T з будь-якої кількості елементів

[a, b, c | T]
список містить три константи у початку і хвіст T з будь-якої кількості елементів

Обробка списків
Структура списків дає можливість застосування рекурсії для обробки списків, тому що дії, які виконуються стосовно голови можна повторити для хвоста списку. Одне з правил повинна бути термінальною, тобто виконується конкретизація зміни заздалегідь передбаченим значенням. Альтернативні правила повинні мати у складі умовної частини рекурсивну ціль. Розглянемо простий приклад – отримання останнього елементу списку.
Для рішення напишемо предикат, який має формат:
last_el(L, X).
де L – список,
X- результат (останній елемент, якщо він є).
Необхідно зазначити, що задача має два термінальних випадки:
якщо список пустий, результат може бути будь що, тобто зміна X залишається неконкретизованою:
last_el([], _).
Якщо список містить лише один елемент, він буде результатом:
last_el([X], X).
У інших випадках потрібно відкинути голову і знайти останній елемент тільки в хвості списку, тобто здійснювати рекурсивний виклик правила:
last_el([H|T], X) :- last_el(T, X).
У мові Prolog передбачено ряд предикатів для обробки списків, який представлений в таблиці 7.2.
Таблиця 7.2 – Вбудовані предикати для обробки списків

Предикат
Призначення

is_list()
Перевірка, чи є списком.

append(,,)
Обєднання списків і в результуючий список

member(, )
Перевірка входження терму в список

delete(, , )
Отримання списку ·st2> у результаті видалення терму зі списку (

reverce(,)
Інвертування списку в список

flatten(,)
Розташування всіх елементів багаторівневого списку в простий список

length(, )
Отримання кількості елементів списку

Методичні вказівки
Збереження рішень у списках
Prolog система забезпечує отримання результатів рішень за допомогою механізму повернення. Однак кожне рішення необхідно використати одразу після отримання, інакше воно пропаде. Вбудовані предикати bagof, setof, findall дозволяють накопити рішення у списку для подальшої їх обробки.
Всі предикати мають формат:
F(X, P, L).
де:
F – один з вищеназваних функторів;
X – одна або декілька змін, що уособлюють ті об’єкти, які потрібно знайти;
P – предикат, у залежності від якого виконується пошук;
L – список для накопичення результатів.
В таблиці 7.3 наведені приклади застосування предикатів для родинних відносин, зображених на рисунку 5.1 – необхідно отримати список всіх об’єктів
Таблиця 7.3 – Предикати отримання списків об’єктів бази даних


Застосування
Результат

1
bagof(X,parent(X,_),L)
L=[тетяна];
L=[ігор];
L=[ігор];
L=[сергій];
L=[сергій, марина];
L=[петро]

2
setof(X,parent(X,_),L)
L=[тетяна];
L=[ігор];
L=[ігор];
L=[сергій];
L=[марина, сергій];
L=[петро]

3
findall(X,parent(X,_),L)
L=[тетяна, ігор, ігор, сергій, сергій, марина, петро]

бази даних, які є батьками (parent). Видно, що результати, які отримані предикатами bagof і setof, залежать від значення другого аргументу предиката parent, а предикат findall формує повний список об’єктів. Предикат setof у відміну від bagof упорядковує список.
Створення і декомпозиція атомів
У мові Prolog існує предикат name, який встановлює взаємозв’язок між атомами та їх кодировкою в ASCII. Предикат має формат:
name(A, L),
де: A – атом, L – список кодів символів атому A.
name істинно, якщо символи атому відповідають кодам списку L. Наприклад:
? name(a123, L).
L = [97, 47, 48, 49] % зміна L конкретизується списком кодів
% атому a123
? name(A, [97, 47, 48, 49])
A = a123 % зміна А конкретизується константою a123.
Приклад виконання завдання.
Задача: Отримати список студентів, які здобули оцінку «добре» з дисципліни «математика» на основі фактів бази даних, що записані у вигляді:
student (4151, petrov, [physics/5, mathematics/4, c++/5, oop/3]).
student(4152, veselkov, [physics/4, mathematics/3, c++/4, oop/5]).
Рішення:
Для отримання списку напишемо правило з використанням вбудованого предикату setof, тому що одностайно список буде упорядкованим. Однак, у зв’язку з тим, що setof в процесі пошуку рішення враховує значення інших аргументів (див. табл. 7.2), потрібно скласти окремий предикат для отримання прізвища студента, що одержав оцінку «добре» з математики:
p_stud(X) :- student(_, X, [ _,mathematics/4 |_ ] ).
Правило містить у правої частині ціль для співставлення з фактами student/3. Зверніть увагу на те, що застосована анонімна зміна для тих аргументів, які у даному випадку не потрібні. Тоді правило для отримання списку запишемо у наступному вигляді:
good_math(L) :- setof (X, .p_stud(X), L).
Для виводу списку напишемо рекурсивне правило:
% термінальне правило, виведення загальної кількості студентів
print_list([],N):-write(Всього ),write(N),
write( студентів’), !.
% рекурсивне правило. Виведення голови списку
print_list([X|T], N):- write(N), write(.’), tab(2), write(X),nl,
% рекурсивний виклик для виведення хвосту з наступним номером рядка
K is N + 1, print_list[T, K).
Напишемо заключне правило (предикат):
p :- good_math(L),print_list(L,1).
Контрольні запитання:
Визначення списку, правила запису списку
Рекурсивна обробка списків.
Навести приклади процедур обробки списків
Обробка структур, способи вибору потрібних даних з структури.
Вбудовані предикати накопичення рішень у списках.















13 PAGE \* MERGEFORMAT 145715







15

Приложенные файлы

  • doc 18085000
    Размер файла: 79 kB Загрузок: 0

Добавить комментарий