/* GoogleAds */

Главная

ПРОЕКТ "ЧЕЛОВЕК. ЗЕМЛЯ. ВСЕЛЕННАЯ"

Инструменты пользователя

Инструменты сайта


project:prolog:swi:third



SWI-Prolog. Ваша третья программа

В предыдущей статье вы научились:

  • выполнять простые и расширенные запросы к этой программе.

Сейчас мы разберём чуть более сложную программу. Опять же, если вы хорошо разобрались с предыдущей, то, думаю, особых сложностей у вас не возникнет. :)

Что должен знать современный человек?

Итак, вот текст программы. Допустим, он хранится в файле animal.pl:

% собаки
dog(sharik). % дословно означает, что Шарик - собака
dog(tuzik).
% кошки
cat(pushok).
cat(druzgok).
 
% хомячки
hamster(pit).
 
% мужчины
man(bill).
man(george).
man(barak).
man(platon).
man(sokrat).
 
% женщины
woman(ann).
woman(kate).
woman(pam).
 
% ныне покойные
dead(sharik).
dead(platon).
dead(sokrat).
 
% возраст
age(sharik, 18). % возраст Шарика - 18 лет
age(tuzik, 10).  
age(pushok, 5). 
age(druzhok, 2).
age(bill, 62). 
age(george, 62). 
age(barak, 47). 
age(sokrat, 70). 
age(platon, 80). 
age(ann, 20). 
age(kate, 25). 
age(pam, 30).
 
% животные
animal(X) :-
    dog(X); % это либо собака
    cat(X); % либо кошка
    hamster(X). % либо хомячок
 
% Читается как: X - животное, если X - собака, либо Х - кошка, либо Х - хомяк. 
 
% люди
human(X) :-
    man(X); % либо мужчина
    woman(X). % либо женщина
 
% живые (или жившие) существа
living(X) :-
    animal(X);
    human(X).
 
% живые (в данный момент) существа
alive(X) :-
    living(X),
    \+ dead(X).
 
% старый
old(X) :-
    (   animal(X)
    ->  age(X, Age),
        Age >= 10 % считаем, что животные старше 10 лет - старые
    ;   human(X),
        age(X, Age),
        Age >= 60 % считаем, что люди старше 60 лет - старые
    ), 
    \+ dead(X). % старые, но при этом - живые
 
% молодой - значит - живой и не старый
young(X) :- 
    alive(X), 
    \+ old(X).

Традиционно разберём, что есть что в этой программе. Внимательно наблюдайте, как формируются простые определения, а на их основе формируются более сложные определения.

Cначала дадим собакам, кошкам, хомячка, мужчинам и женщинам имена. Для простоты будем использовать имена, написанные латинскими буквами. Обратите внимание, что имена начинаются со строчных (маленьких букв).

% собаки
dog(sharik). % дословно означает, что Шарик - собака
dog(tuzik).
% кошки
cat(pushok).
cat(druzgok).
 
% хомячки
hamster(pit).
 
% мужчины
man(bill).
man(george).
man(barak).
man(platon).
man(sokrat).
 
% женщины
woman(ann).
woman(kate).
woman(pam).

Затем укажем имена тех, кто уже покинул этот мир (dead):

dead(sharik).
dead(platon).
dead(sokrat).

Далее укажем для всех их возраст:

age(sharik, 18). % возраст Шарика - 18 лет
age(tuzik, 10).  
age(pushok, 5). 
age(druzhok, 2).
age(bill, 62). 
age(george, 62). 
age(barak, 47). 
age(sokrat, 70). 
age(platon, 80). 
age(ann, 20). 
age(kate, 25). 
age(pam, 30).

Затем определим, кого считать животным. Это либо собака, либо кошка, либо хомячок. Как видите, здесь уже появилась первая переменная Х, которая пишется с прописной (заглавной) буквы. Переменная Х просто определяет какое-то имя животного. Это имя будет конкретизировано, то есть переменной X будет присвоено какое-то значение, когда начнётся выполнение запроса и будет выполнено заданное условие запроса. Оператор читается как: X - животное, если X - собака, либо Х - кошка, либо Х - хомяк.

animal(X) :-
    dog(X);
    cat(X); 
    hamster(X).

Теперь определим, кого считать людьми. Тут проще. Это могут быть или мужчины, или женщины.

human(X) :-
    man(X); % либо мужчина
    woman(X). % либо женщина

Теперь определим, кто является живым существом вообще (living). Очевидно, что это могут быть животные и люди. Кто не в курсе… Человек это тоже живое существо :)

living(X) :-
    animal(X);
    human(X).

Теперь определим, кто является живым в данный момент существом (alive). Очевидно, что это живое существо вообще (living), но не считающееся умершим (dead):

Помним, что запятая в операторе является логическим оператором И. То есть, чтобы всё определение было TRUE («правда»), необходимо, чтобы обе части оператора (до запятой и после запятой) были тоже TRUE. То есть кто-то, имеющий имя Х, будет считаться живым, только в том случае, если он является живым существом И он не умер.

alive(X) :-
    living(X),
    \+ dead(X).

А сейчас определим, кого считать пожилым живым существом (old). Тут немного посложнее. Будем считаем, что животные старше 10 лет или люди старше 60 лет - пожилые (old). И они еще не умерли (dead).

Помним, что точка с запятой в операторе является логическим оператором ИЛИ. То есть, чтобы всё определение было TRUE («правда»), необходимо, чтобы одна из двух частей оператора (до запятой и после точки с запятой) или сразу обе, были тоже TRUE. То есть кто-то, имеющий имя Х и возраст Age будет считаться пожилым (old), только в том случае, если он является животным (animal) И его возраст 10 и более ( >= ) лет. ИЛИ это человек (human) с именем X и возрастом Age 60 и более лет.

old(X) :-
    (   animal(X)
    ->  age(X, Age),
        Age >= 10 % считаем, что животные старше 10 лет - пожилые
    ;   human(X),
        age(X, Age),
        Age >= 60 % считаем, что люди старше 60 лет - пожилые
    ), 
    \+ dead(X). % старые, но при этом - живые

И, наконец, молодоё живое существо - это существо, которое живо и не является пожилым.

young(X) :- 
    alive(X), 
    \+ old(X).% молодой - значит - живой и не старый

Теперь можно ввести определённые запросы. Начнём с простого. Попытаемся определить, является ли Ann (в запросе - ann) человеком?

?- human(ann).
true.

Система ответила «true», то есть, да, ann - человек, так как у нас в программе есть оператор woman(ann) и выполняется одна из частей оператора human(X) :- man(X); woman(X). То есть, выполняя запрос система делает подстановку human(X) :- woman(X) и затем найдя оператор woman(ann), определяет имя Х как ann. В итоге система определяет итоговый оператор human(ann) :- woman(ann). как логичный и выводит на консоль true (правда).

Далее выясним, является ли tuzik человеком?

?- human(tuzik).
false.

Естественно, нет - false. В данном случае система выполняет похожие операции. Сначала выполняет оператор human(X) :- man(X); woman(X). Но tuzik в программе определён как животное dog(tuzik) и потому этот оператор выдаёт false, так как dog нет в правой части оператора. Там только man и woman.

Теперь определим, кто же вообще является человеком?

?- human(Who). Кто человек?
Who = bill ;

Нажимая на «пробел» получим остальные имена.

Сразу весь список людей можно получить таким способом:

?- bagof(H, human(H), Humans).
Humans = [bill, george, barak, platon, sokrat, ann, kate, pam].

Попробуем узнать, жив ли Сократ? Разберём этот момент подробнее. Некоторые технические моменты сознательно упростим для лучшего понимания. И если вы сможете разобраться в этих деталях, то вам лучше станет понятна логика Пролога.

Выполняя запрос alive(sokrat). (Жив ли Сократ?), система использует оператор alive(X) :- living(X), \+ dead(X). Здесь в правой части оператора стоит запятая, потому оба условия в правой части должны быть true, то есть выполняться, чтобы условие alive(X) - было тоже true. То есть система пытается подставить имя sokrat вместо переменной X в оба условия правой части.

Сначала система проверяет оператор living(sokrat). Для этого проверяется составной оператор: living(X) :- animal(X); human(X).

Опять вместо X подставляется sokrat: living(sokrat) :- animal(sokrat); human(sokrat).

Здесь стоит точка с запятой, потому может выполниться только одно из условий в правой части. В данном случае рассмотрим вариант с human, хотя система будет проверять аналогично и вариант с animal.

human(sokrat) - тоже составной оператор: human(X) :- man(X); woman(X). После подстановки X = sokrat он будет иметь вид human(sokrat) :- man(sokrat); woman(sokrat). Опять видим точку с запятой, то есть может выполниться только одно из условий в правой части.

Так как у нас в программе есть оператор man(sokrat), то в итоге оператор human(X) выдаст true, и соответственно оператор living(sokrat) :- animal(sokrat); human(sokrat). тоже выдаст true.

Вернёмся к оператору alive(X) :- living(X), \+ dead(X). Сейчас система определила, что первое условие в правой части living(X) - есть true, так как living(sokrat) - true.

Далее система проверит второе условие в правой части \+ dead(X). Это условие говорит о том, что человек будет считаться живым, если он НЕ умер. Но у нас есть в программе оператор dead(sokrat)., который объявляет, что sokrat - умер.

Если sokrat умер, то условие \+ dead(sokrat). ( НЕ умер (sokrat) ) - false (ложь).

В итоге мы получаем, что в операторе alive(X) :- living(X), \+ dead(X). в правой части условие living(sokrat) - true (правда), а условие \+ dead(sokrat). - false (ложь). Так как эти части разделены запятой, то для истинности всего оператора alive(sokrat) эти ОБЕ части должны быть true. В случае с sokrat это не так, потому весь оператор alive(X) :- living(X), \+ dead(X). в случае sokrat получает значение false, которое система выводит как ответ на запрос.

?- alive(sokrat)
false.

Аналогично можно узнать, жив ли pit. Так как pit нет в списке умерших, то система выводит true, то есть piy жив.

?- alive(pit).
true.

% перечислить молодых % ?- young(Y). % Y = pushok ;

% перечислить молодых мужчин % ?- young(H), man(H). % H = barak ; % false.

% показать все пары живых существ, где одно старше другого в 2 раза % ?- living(X), living(Y), age(X, AgeX), age(Y, AgeY), AgeX =:= 2 * AgeY. % X = tuzik, % Y = pushok, % AgeX = 10, % AgeY = 5 ; % X = ann, % Y = tuzik, % AgeX = 20, % AgeY = 10 ; % false.

Оглавление SWI-Prolog

Что должен знать современный человек?

!!Рекомендуем: Что должен знать современный человек?Семейная Энциклопедия ЗдоровьяСамоанализ. Работа над собойОглавление SWI-PrologГлавная сайта

project/prolog/swi/third.txt · Последние изменения: 2023/09/03 22:22 (внешнее изменение)

Вы можете оставить свои комментарии в разделе "Обсуждение".
Рекомендуем оформить подписку на новости данного раздела. Для этого нажмите на кнопку "Подписаться", расположенную справа снизу каждой страницы (знак конверта).




Индекс цитирования