
Лаб. 5 ФЛП
.docxЛабораторная работа 5
переменная
– это просто слово с маленькой буквы,
а в Prolog переменные должны начинаться с
заглавной буквы или с подчёркивания.
Это не терм.
'язык Пролог' – строка в одинарных кавычках. В Prolog строки в таких кавычках считаются атомами.
Пролог – начинается с заглавной буквы, а значит, это переменная.
Альберт(любит, мясо) – выглядит как сложный терм (функтор с аргументами), но Альберт с заглавной буквы интерпретируется как переменная. В таком виде это не терм.
любит(Альберт, мясо) – корректный сложный терм: функтор любит (с маленькой буквы, как и положено), два аргумента (Альберт – переменная, мясо – атом).
meal(food(Y), X) = meal(X, drink(Z))
Термы имеют одинаковый функтор meal/2, поэтому можно пытаться унифицировать их аргументы:
food(Y) = X
X = drink(Z)
Подставляя X = drink(Z) в первое уравнение: food(Y) = drink(Z)
food(Y) и drink(Z) не могут быть равны (разные функторы).
Сопоставление не удастся.
food(bread, X, beer) = food(Y, burger)
Термы food/3 и food/2 имеют разное количество аргументов, поэтому сопоставление не удастся.
likes(X, cola) = likes(Y, cola)
Функторы и вторая часть аргументов (cola) совпадают.
Остаётся X = Y, что возможно.
Успешное сопоставление: X = Y.
'bread' = bread
В Prolog 'bread' и bread – это одно и то же (одинаковые атомы).
Сопоставление удастся.
likes(X, food(Y)) = likes(Y, food(Z))
Функторы совпадают, разбираем аргументы:
X = Y
food(Y) = food(Z), что даёт Y = Z.
Успешное сопоставление: X = Y, Y = Z.
%3
отец(иван, настя). % Иван – отец Насти
отец(сергей, анна). % Сергей – отец Анны
%отец(X, настя)
%отец(иван, X)
%4
мать(елена, анна).
мать(ирина, сергей).
родитель(X, Y) :- отец(X, Y).
родитель(X, Y) :- мать(X, Y).
счастлив(X) :- родитель(X, _).
%счастлив(X)
%5
% Родственные отношения
отец(иван, анна).
отец(иван, сергей).
отец(пётр, мария).
отец(пётр, виктория).
отец(пётр, алексей).
мать(елена, анна).
мать(ирина, сергей).
мать(марина, мария).
мать(марина, виктория).
мать(марина, алексей).
мать(виктория, игорь).
мать(виктория, светлана).
мать(мария, павел).
% Общий предикат родитель/2
родитель(X, Y) :- отец(X, Y).
родитель(X, Y) :- мать(X, Y).
% Предикат "тётя"
тётя(X, Y) :-
сестра(X, Родитель), % X – сестра одного из родителей Y
родитель(Родитель, Y).
% Определение сестры
сестра(X, Y) :-
родитель(Родитель, X),
родитель(Родитель, Y),
X \= Y, % X и Y – разные люди
женский(X).
% Пол
женский(анна).
женский(мария).
женский(елена).
женский(ирина).
женский(марина).
женский(виктория).
женский(светлана).
%тётя(мария, игорь)
%тётя(мария, светлана)
%тётя(виктория, павел)
%тётя(марина, алексей)
%тётя(пётр,
светлана)
% Факты
автор("Война и мир", "Лев Толстой").
автор("Анна Каренина", "Лев Толстой").
автор("Преступление и наказание", "Фёдор Достоевский").
автор("Идиот", "Фёдор Достоевский").
автор("Мастер и Маргарита", "Михаил Булгаков").
жанр("Война и мир", "Роман").
жанр("Анна Каренина", "Роман").
жанр("Преступление и наказание", "Драма").
жанр("Идиот", "Драма").
жанр("Мастер и Маргарита", "Фантастика").
написал_в("Лев Толстой", 1869).
написал_в("Фёдор Достоевский", 1866).
написал_в("Фёдор Достоевский", 1869).
написал_в("Михаил Булгаков", 1940).
% Современники (разница в годах написания <= 50 лет)
современники(Автор1, Автор2) :-
написал_в(Автор1, Год1),
написал_в(Автор2, Год2),
Автор1 \= Автор2,
abs(Год1 - Год2) =< 50.
% Прямые связи между книгами (по автору или жанру)
прямая_связь(Книга1, Книга2) :-
автор(Книга1, Автор), автор(Книга2, Автор), Книга1 \= Книга2.
прямая_связь(Книга1, Книга2) :-
жанр(Книга1, Жанр), жанр(Книга2, Жанр), Книга1 \= Книга2.
% Рекурсивное правило: если Книга1 связана с КнигаПромежуточная, а та — с Книга2
связаны(Книга1, Книга2) :- связаны(Книга1, Книга2, []).
связаны(Книга1, Книга2, _) :-
прямая_связь(Книга1, Книга2).
связаны(Книга1, Книга2, Visited) :-
прямая_связь(Книга1, КнигаПромежуточная),
КнигаПромежуточная \= Книга1,
КнигаПромежуточная \= Книга2,
not(member(КнигаПромежуточная, Visited)), % Проверяем, не посещали ли уже
связаны(КнигаПромежуточная, Книга2, [КнигаПромежуточная | Visited]).
%современники("Лев Толстой", "Фёдор Достоевский")
%связаны("Война и мир", "Идиот")
%связаны("Мастер и Маргарита", "Анна Каренина")
%связаны("Война и мир", "Анна Каренина")
%связаны("Преступление и наказание", "Идиот")
% Факты о рейсах между городами
есть_рейс(мос, спб).
есть_рейс(мос, ект).
есть_рейс(мос, новосиб).
есть_рейс(спб, новосиб).
есть_рейс(спб, сочи).
есть_рейс(спб, минск).
есть_рейс(ект, сочи).
есть_рейс(сочи, киев).
есть_рейс(минск, новосиб).
есть_рейс(минск, киев).
есть_рейс(казань, омск).
% Двусторонние рейсы
рейс(X, Y) :- есть_рейс(X, Y).
рейс(Y, X) :- есть_рейс(X, Y).
% Связанность городов (учёт циклов)
связаны(X, Y) :- связаны(X, Y, []).
связаны(X, Y, _) :- рейс(X, Y). % Прямой рейс
связаны(X, Y, Посещённые) :-
рейс(X, Z),
Z \= Y,
\+ member(Z, Посещённые), % Не заходили в Z раньше (предотвращаем циклы)
связаны(Z, Y, [Z | Посещённые]). % Добавляем Z в список посещённых
%связаны(мос, киев)
%связаны(новосиб, киев)
%связаны(спб, мос)
%forall((есть_рейс(A, _); есть_рейс(_, A)), forall((есть_рейс(B, _); есть_рейс(_, B)), связаны(A, B)))