lab 8 task 4

main
Artem-Darius Weber 8 months ago
parent 95a8d1c01a
commit 5cefdb0e7e

@ -1,4 +1,4 @@
.PHONY: run build clean task1 build-task1 clean-task1 interactive-task1 test-task1 demo-task1 trace-task1 info-task1 task2 build-task2 clean-task2 interactive-task2 test-task2 demo-task2 trace-task2 info-task2 task3 build-task3 clean-task3 interactive-task3 test-task3 demo-task3 trace-task3 info-task3
.PHONY: run build clean task1 build-task1 clean-task1 interactive-task1 test-task1 demo-task1 trace-task1 info-task1 task2 build-task2 clean-task2 interactive-task2 test-task2 demo-task2 trace-task2 info-task2 task3 build-task3 clean-task3 interactive-task3 test-task3 demo-task3 trace-task3 info-task3 task4 build-task4 clean-task4 interactive-task4 test-task4 demo-task4 trace-task4 info-task4 task5 build-task5 clean-task5 interactive-task5 test-task5 demo-task5 trace-task5 info-task5 task6 build-task6 clean-task6 interactive-task6 test-task6 demo-task6 trace-task6 info-task6
# task1 (default)
run:
@ -87,6 +87,81 @@ trace-task3:
info-task3:
cd task3 && make info
# task4
task4:
cd task4 && make run
build-task4:
cd task4 && make build
clean-task4:
cd task4 && make clean
interactive-task4:
cd task4 && make interactive
test-task4:
cd task4 && make test
demo-task4:
cd task4 && make demo
trace-task4:
cd task4 && make trace
info-task4:
cd task4 && make info
# task5
task5:
cd task5 && make run
build-task5:
cd task5 && make build
clean-task5:
cd task5 && make clean
interactive-task5:
cd task5 && make interactive
test-task5:
cd task5 && make test
demo-task5:
cd task5 && make demo
trace-task5:
cd task5 && make trace
info-task5:
cd task5 && make info
# task6
task6:
cd task6 && make run
build-task6:
cd task6 && make build
clean-task6:
cd task6 && make clean
interactive-task6:
cd task6 && make interactive
test-task6:
cd task6 && make test
demo-task6:
cd task6 && make demo
trace-task6:
cd task6 && make trace
info-task6:
cd task6 && make info
# Help
help:
@echo "Available commands for lab8:"
@ -121,6 +196,36 @@ help:
@echo " make build-task3 - Build task3 Docker image"
@echo " make clean-task3 - Clean task3 Docker images"
@echo ""
@echo "Task 4 (Akinator modifications):"
@echo " make task4 - Run task4 (basic info)"
@echo " make info-task4 - Show detailed task4 info"
@echo " make demo-task4 - Run task4 demonstration"
@echo " make test-task4 - Run task4 tests"
@echo " make interactive-task4 - Start task4 interactive session"
@echo " make trace-task4 - Run task4 with tracing"
@echo " make build-task4 - Build task4 Docker image"
@echo " make clean-task4 - Clean task4 Docker images"
@echo ""
@echo "Task 5 (Domain design):"
@echo " make task5 - Run task5 (basic info)"
@echo " make info-task5 - Show detailed task5 info"
@echo " make demo-task5 - Run task5 demonstration"
@echo " make test-task5 - Run task5 tests"
@echo " make interactive-task5 - Start task5 interactive session"
@echo " make trace-task5 - Run task5 with tracing"
@echo " make build-task5 - Build task5 Docker image"
@echo " make clean-task5 - Clean task5 Docker images"
@echo ""
@echo "Task 6 (Full Akinator system):"
@echo " make task6 - Run task6 (basic info)"
@echo " make info-task6 - Show detailed task6 info"
@echo " make demo-task6 - Run task6 demonstration"
@echo " make test-task6 - Run task6 tests"
@echo " make interactive-task6 - Start task6 interactive session"
@echo " make trace-task6 - Run task6 with tracing"
@echo " make build-task6 - Build task6 Docker image"
@echo " make clean-task6 - Clean task6 Docker images"
@echo ""
@echo "Default commands (task1):"
@echo " make run - Run task1"
@echo " make build - Build task1"

@ -0,0 +1,7 @@
FROM swipl:stable
WORKDIR /app
COPY *.pl ./
CMD ["swipl", "-g", "consult('akinator.pl')", "-t", "halt"]

@ -0,0 +1,45 @@
.PHONY: build run interactive clean test trace demo
# Build Docker image
build:
docker build -t lab8-task4-prolog .
# Run Prolog with family database (show basic info and exit)
run: build
docker run --rm -v $(PWD):/app lab8-task4-prolog swipl -g "consult('akinator.pl'), write('=== AKINATOR TASK4 ==='), nl, show_objects, halt"
# Interactive Prolog session
interactive: build
docker run -it --rm -v $(PWD):/app lab8-task4-prolog swipl akinator.pl
# Run test queries
test: build
docker run --rm -v $(PWD):/app lab8-task4-prolog swipl -g "consult('akinator.pl'), consult('tests.pl'), run_tests, halt"
# Run with tracing enabled
trace: build
docker run --rm -v $(PWD):/app lab8-task4-prolog swipl -g "consult('akinator.pl'), trace, start_akinator, notrace, halt"
# Show basic info about task4
info: build
docker run --rm -v $(PWD):/app lab8-task4-prolog swipl -g "consult('akinator.pl'), write('=== TASK4 INFO ==='), nl, show_objects, show_questions, halt"
# Run demo
demo: build
docker run --rm -v $(PWD):/app lab8-task4-prolog swipl -g "consult('akinator.pl'), consult('demo.pl'), demo, halt"
# Clean Docker images
clean:
docker rmi lab8-task4-prolog || true
# Help
help:
@echo "Available commands for lab8 task4:"
@echo " make build - Build Docker image"
@echo " make run - Run and show basic family info"
@echo " make info - Show detailed task3 information"
@echo " make demo - Run demonstration queries"
@echo " make test - Run test queries"
@echo " make interactive - Start interactive Prolog session"
@echo " make trace - Run with tracing enabled"
@echo " make clean - Clean Docker images"

@ -0,0 +1,350 @@
% ===============================================
% АКИНАТОР - ЗАДАНИЕ 4
% Модификация акинатора с добавлением объектов
% ===============================================
% Объекты без дополнительных вопросов (определяются существующими)
object(собака).
object(кошка).
object(рыбка).
object(попугай).
% Новые объекты, требующие дополнительных вопросов
object(хомяк).
object(черепаха).
object(игуана).
object(канарейка).
% ===============================================
% БАЗОВЫЕ ВОПРОСЫ
% ===============================================
% Основные характеристики
question(has_fur, 'Есть ли у животного шерсть?').
question(can_fly, 'Умеет ли животное летать?').
question(lives_in_water, 'Живет ли животное в воде?').
question(makes_sound, 'Издает ли животное звуки?').
% Дополнительные вопросы для новых объектов
question(is_small, 'Это маленькое животное (помещается в ладонь)?').
question(has_shell, 'Есть ли у животного панцирь?').
question(is_reptile, 'Это рептилия?').
question(can_sing, 'Умеет ли животное петь?').
% ===============================================
% ПРАВИЛА ДЛЯ ОПРЕДЕЛЕНИЯ ОБЪЕКТОВ
% ===============================================
% Объекты без дополнительных вопросов
knows(собака) :-
answer(has_fur, yes),
answer(can_fly, no),
answer(lives_in_water, no),
answer(makes_sound, yes).
knows(кошка) :-
answer(has_fur, yes),
answer(can_fly, no),
answer(lives_in_water, no),
answer(makes_sound, yes),
\+ answer(is_small, yes). % Не маленькая
knows(рыбка) :-
answer(has_fur, no),
answer(can_fly, no),
answer(lives_in_water, yes).
knows(попугай) :-
answer(has_fur, no),
answer(can_fly, yes),
answer(makes_sound, yes),
\+ answer(can_sing, yes). % Не поет специально
% Новые объекты с дополнительными вопросами
knows(хомяк) :-
answer(has_fur, yes),
answer(can_fly, no),
answer(lives_in_water, no),
answer(is_small, yes),
answer(makes_sound, no).
knows(черепаха) :-
answer(has_fur, no),
answer(can_fly, no),
answer(has_shell, yes),
answer(is_reptile, yes).
knows(игуана) :-
answer(has_fur, no),
answer(can_fly, no),
answer(lives_in_water, no),
answer(is_reptile, yes),
answer(has_shell, no).
knows(канарейка) :-
answer(has_fur, no),
answer(can_fly, yes),
answer(makes_sound, yes),
answer(can_sing, yes),
answer(is_small, yes).
% ===============================================
% СИСТЕМА АКИНАТОРА
% ===============================================
% Запуск акинатора
start_akinator :-
write('=== АКИНАТОР ЗАДАНИЕ 4 ==='), nl,
write('Загадайте животное из списка:'), nl,
show_objects,
nl,
write('Отвечайте на вопросы yes/no'), nl,
write('Для выхода введите quit'), nl,
nl,
retractall(answer(_, _)),
ask_questions.
% Основной цикл вопросов
ask_questions :-
% Попробуем определить объект с текущими ответами
( find_object(Object) ->
write('Вы загадали: '), write(Object), write('!'), nl,
write('Правильно? (yes/no): '),
read(Response),
handle_guess_response(Response, Object)
; % Если не можем определить, задаем следующий вопрос
find_next_question(Question),
ask_question(Question),
ask_questions
).
% Найти объект, который соответствует текущим ответам
find_object(Object) :-
object(Object),
knows(Object),
!.
% Найти следующий вопрос для задавания
find_next_question(Question) :-
question(Question, _),
\+ answer(Question, _),
!.
% Задать вопрос пользователю
ask_question(Question) :-
question(Question, Text),
write(Text), write(' (yes/no/quit): '),
read(Response),
handle_response(Question, Response).
% Обработка ответа на вопрос
handle_response(_, quit) :-
write('До свидания!'), nl, !.
handle_response(Question, yes) :-
assert(answer(Question, yes)).
handle_response(Question, no) :-
assert(answer(Question, no)).
handle_response(Question, _) :-
write('Пожалуйста, ответьте yes, no или quit'), nl,
ask_question(Question).
% Обработка ответа на догадку
handle_guess_response(yes, Object) :-
write('Отлично! Я угадал '), write(Object), write('!'), nl,
write('Хотите играть еще? (yes/no): '),
read(Again),
( Again = yes ->
start_akinator
; write('Спасибо за игру!'), nl
).
handle_guess_response(no, Object) :-
write('Я ошибся с '), write(Object), write('.'), nl,
write('Какое животное вы загадали? '),
read(CorrectObject),
write('Спасибо! В следующий раз я буду умнее.'), nl,
learn_new_object(CorrectObject),
write('Хотите играть еще? (yes/no): '),
read(Again),
( Again = yes ->
start_akinator
; write('Спасибо за игру!'), nl
).
handle_guess_response(quit, _) :-
write('До свидания!'), nl.
handle_guess_response(_, Object) :-
write('Пожалуйста, ответьте yes, no или quit'), nl,
write('Я думаю это '), write(Object), write('. Правильно? '),
read(Response),
handle_guess_response(Response, Object).
% Обучение новому объекту (упрощенная версия)
learn_new_object(Object) :-
write('Добавляю '), write(Object), write(' в базу знаний...'), nl.
% ===============================================
% ДЕМОНСТРАЦИОННЫЕ ФУНКЦИИ
% ===============================================
% Показать все объекты
show_objects :-
write('Доступные объекты:'), nl,
forall(object(Obj), (write(' - '), write(Obj), nl)).
% Показать все вопросы
show_questions :-
write('Доступные вопросы:'), nl,
forall(question(Q, Text),
(write(' '), write(Q), write(': '), write(Text), nl)).
% Показать правила для объекта
show_rules(Object) :-
write('Правила для '), write(Object), write(':'), nl,
( knows(Object) ->
write(' Объект определяется существующими правилами'), nl
; write(' Правила не найдены'), nl
).
% Демонстрация объектов без дополнительных вопросов
demo_simple_objects :-
write('=== ОБЪЕКТЫ БЕЗ ДОПОЛНИТЕЛЬНЫХ ВОПРОСОВ ==='), nl,
SimpleObjects = [собака, кошка, рыбка, попугай],
forall(member(Obj, SimpleObjects),
(write('- '), write(Obj), nl)).
% Демонстрация объектов с дополнительными вопросами
demo_complex_objects :-
write('=== ОБЪЕКТЫ С ДОПОЛНИТЕЛЬНЫМИ ВОПРОСАМИ ==='), nl,
ComplexObjects = [хомяк, черепаха, игуана, канарейка],
forall(member(Obj, ComplexObjects),
(write('- '), write(Obj), write(' (требует: '),
show_additional_questions(Obj), write(')'), nl)).
% Показать дополнительные вопросы для объекта
show_additional_questions(хомяк) :- write('is_small').
show_additional_questions(черепаха) :- write('has_shell, is_reptile').
show_additional_questions(игуана) :- write('is_reptile').
show_additional_questions(канарейка) :- write('can_sing, is_small').
show_additional_questions(_) :- write('нет').
% Тестирование определения объектов
test_object_recognition :-
write('=== ТЕСТИРОВАНИЕ РАСПОЗНАВАНИЯ ОБЪЕКТОВ ==='), nl,
% Тест 1: Собака (без дополнительных вопросов)
write('Тест 1: Собака'), nl,
retractall(answer(_, _)),
assert(answer(has_fur, yes)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(makes_sound, yes)),
( knows(собака) ->
write(' ✓ Собака определена правильно'), nl
; write(' ✗ Ошибка определения собаки'), nl
),
% Тест 2: Хомяк (с дополнительными вопросами)
write('Тест 2: Хомяк'), nl,
retractall(answer(_, _)),
assert(answer(has_fur, yes)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(is_small, yes)),
assert(answer(makes_sound, no)),
( knows(хомяк) ->
write(' ✓ Хомяк определен правильно'), nl
; write(' ✗ Ошибка определения хомяка'), nl
),
% Тест 3: Черепаха (с дополнительными вопросами)
write('Тест 3: Черепаха'), nl,
retractall(answer(_, _)),
assert(answer(has_fur, no)),
assert(answer(can_fly, no)),
assert(answer(has_shell, yes)),
assert(answer(is_reptile, yes)),
( knows(черепаха) ->
write(' ✓ Черепаха определена правильно'), nl
; write(' ✗ Ошибка определения черепахи'), nl
),
retractall(answer(_, _)),
nl.
% Интерактивная демонстрация
demo :-
write('=== ДЕМОНСТРАЦИЯ АКИНАТОРА ЗАДАНИЕ 4 ==='), nl, nl,
write('1. ПОКАЗАТЬ ВСЕ ОБЪЕКТЫ'), nl,
write('========================'), nl,
show_objects,
nl,
write('2. ПОКАЗАТЬ ВСЕ ВОПРОСЫ'), nl,
write('========================'), nl,
show_questions,
nl,
write('3. ОБЪЕКТЫ БЕЗ ДОПОЛНИТЕЛЬНЫХ ВОПРОСОВ'), nl,
write('======================================'), nl,
demo_simple_objects,
nl,
write('4. ОБЪЕКТЫ С ДОПОЛНИТЕЛЬНЫМИ ВОПРОСАМИ'), nl,
write('====================================='), nl,
demo_complex_objects,
nl,
write('5. ТЕСТИРОВАНИЕ РАСПОЗНАВАНИЯ'), nl,
write('============================'), nl,
test_object_recognition,
write('6. ЗАПУСК ИНТЕРАКТИВНОГО АКИНАТОРА'), nl,
write('=================================='), nl,
write('Для запуска интерактивной игры используйте: ?- start_akinator.'), nl,
nl,
write('=== ДЕМОНСТРАЦИЯ ЗАВЕРШЕНА ==='), nl.
% ===============================================
% ВСПОМОГАТЕЛЬНЫЕ ПРЕДИКАТЫ
% ===============================================
% Подсчет количества объектов
count_objects(Count) :-
findall(Obj, object(Obj), Objects),
length(Objects, Count).
% Подсчет количества вопросов
count_questions(Count) :-
findall(Q, question(Q, _), Questions),
length(Questions, Count).
% Проверка, является ли объект простым (без дополнительных вопросов)
is_simple_object(Object) :-
member(Object, [собака, кошка, рыбка, попугай]).
% Проверка, является ли объект сложным (с дополнительными вопросами)
is_complex_object(Object) :-
member(Object, [хомяк, черепаха, игуана, канарейка]).
% Получить статистику
akinator_stats :-
count_objects(ObjCount),
count_questions(QCount),
findall(O, is_simple_object(O), Simple),
findall(C, is_complex_object(C), Complex),
length(Simple, SimpleCount),
length(Complex, ComplexCount),
write('=== СТАТИСТИКА АКИНАТОРА ==='), nl,
write('Всего объектов: '), write(ObjCount), nl,
write('Всего вопросов: '), write(QCount), nl,
write('Простых объектов: '), write(SimpleCount), nl,
write('Сложных объектов: '), write(ComplexCount), nl,
nl.

@ -0,0 +1,349 @@
% ===============================================
% Демонстрационные запросы для lab8 task4
% Акинатор с модификациями
% ===============================================
% Запуск демонстрации
demo :-
write('=== ДЕМОНСТРАЦИЯ ЗАДАНИЯ 4: МОДИФИЦИРОВАННЫЙ АКИНАТОР ==='), nl, nl,
% 1. Основная информация
write('1. ОСНОВНАЯ ИНФОРМАЦИЯ'), nl,
write('======================'), nl,
demo_basic_info,
nl,
% 2. Демонстрация простых объектов
write('2. ОБЪЕКТЫ БЕЗ ДОПОЛНИТЕЛЬНЫХ ВОПРОСОВ'), nl,
write('======================================'), nl,
demo_simple_objects_detailed,
nl,
% 3. Демонстрация сложных объектов
write('3. ОБЪЕКТЫ С ДОПОЛНИТЕЛЬНЫМИ ВОПРОСАМИ'), nl,
write('====================================='), nl,
demo_complex_objects_detailed,
nl,
% 4. Тестирование распознавания
write('4. ТЕСТИРОВАНИЕ РАСПОЗНАВАНИЯ ОБЪЕКТОВ'), nl,
write('===================================='), nl,
demo_recognition_tests,
nl,
% 5. Сравнение типов объектов
write('5. СРАВНЕНИЕ ТИПОВ ОБЪЕКТОВ'), nl,
write('==========================='), nl,
demo_object_comparison,
nl,
% 6. Инструкции по использованию
write('6. ИНСТРУКЦИИ ПО ИСПОЛЬЗОВАНИЮ'), nl,
write('=============================='), nl,
demo_usage_instructions,
nl,
write('=== ДЕМОНСТРАЦИЯ ЗАДАНИЯ 4 ЗАВЕРШЕНА ==='), nl.
% -----------------------------------------------
% Основная информация
% -----------------------------------------------
demo_basic_info :-
write('Модифицированный акинатор включает:'), nl,
akinator_stats,
nl,
write('Типы объектов:'), nl,
write('- Простые: определяются базовыми вопросами'), nl,
write('- Сложные: требуют дополнительных вопросов'), nl.
% -----------------------------------------------
% Демонстрация простых объектов
% -----------------------------------------------
demo_simple_objects_detailed :-
write('Простые объекты определяются базовыми характеристиками:'), nl,
SimpleObjects = [собака, кошка, рыбка, попугай],
forall(member(Obj, SimpleObjects), demo_simple_object_rules(Obj)).
demo_simple_object_rules(собака) :-
write('СОБАКА:'), nl,
write(' - Есть шерсть: ДА'), nl,
write(' - Умеет летать: НЕТ'), nl,
write(' - Живет в воде: НЕТ'), nl,
write(' - Издает звуки: ДА'), nl,
test_object_recognition_simple(собака),
nl.
demo_simple_object_rules(кошка) :-
write('КОШКА:'), nl,
write(' - Есть шерсть: ДА'), nl,
write(' - Умеет летать: НЕТ'), nl,
write(' - Живет в воде: НЕТ'), nl,
write(' - Издает звуки: ДА'), nl,
write(' - НЕ маленькая'), nl,
test_object_recognition_simple(кошка),
nl.
demo_simple_object_rules(рыбка) :-
write('РЫБКА:'), nl,
write(' - Есть шерсть: НЕТ'), nl,
write(' - Умеет летать: НЕТ'), nl,
write(' - Живет в воде: ДА'), nl,
test_object_recognition_simple(рыбка),
nl.
demo_simple_object_rules(попугай) :-
write('ПОПУГАЙ:'), nl,
write(' - Есть шерсть: НЕТ'), nl,
write(' - Умеет летать: ДА'), nl,
write(' - Издает звуки: ДА'), nl,
write(' - НЕ поет специально'), nl,
test_object_recognition_simple(попугай),
nl.
% -----------------------------------------------
% Демонстрация сложных объектов
% -----------------------------------------------
demo_complex_objects_detailed :-
write('Сложные объекты требуют дополнительных вопросов:'), nl,
ComplexObjects = [хомяк, черепаха, игуана, канарейка],
forall(member(Obj, ComplexObjects), demo_complex_object_rules(Obj)).
demo_complex_object_rules(хомяк) :-
write('ХОМЯК (требует дополнительный вопрос "is_small"):'), nl,
write(' - Есть шерсть: ДА'), nl,
write(' - Умеет летать: НЕТ'), nl,
write(' - Живет в воде: НЕТ'), nl,
write(' - Маленький: ДА'), nl,
write(' - Издает звуки: НЕТ'), nl,
test_object_recognition_complex(хомяк),
nl.
demo_complex_object_rules(черепаха) :-
write('ЧЕРЕПАХА (требует дополнительные вопросы "has_shell", "is_reptile"):'), nl,
write(' - Есть шерсть: НЕТ'), nl,
write(' - Умеет летать: НЕТ'), nl,
write(' - Есть панцирь: ДА'), nl,
write(' - Рептилия: ДА'), nl,
test_object_recognition_complex(черепаха),
nl.
demo_complex_object_rules(игуана) :-
write('ИГУАНА (требует дополнительный вопрос "is_reptile"):'), nl,
write(' - Есть шерсть: НЕТ'), nl,
write(' - Умеет летать: НЕТ'), nl,
write(' - Живет в воде: НЕТ'), nl,
write(' - Рептилия: ДА'), nl,
write(' - Панцирь: НЕТ'), nl,
test_object_recognition_complex(игуана),
nl.
demo_complex_object_rules(канарейка) :-
write('КАНАРЕЙКА (требует дополнительные вопросы "can_sing", "is_small"):'), nl,
write(' - Есть шерсть: НЕТ'), nl,
write(' - Умеет летать: ДА'), nl,
write(' - Издает звуки: ДА'), nl,
write(' - Умеет петь: ДА'), nl,
write(' - Маленькая: ДА'), nl,
test_object_recognition_complex(канарейка),
nl.
% -----------------------------------------------
% Тестирование распознавания объектов
% -----------------------------------------------
demo_recognition_tests :-
write('Проверка правильности определения объектов:'), nl, nl,
% Тесты простых объектов
write('ПРОСТЫЕ ОБЪЕКТЫ:'), nl,
test_simple_objects,
nl,
% Тесты сложных объектов
write('СЛОЖНЫЕ ОБЪЕКТЫ:'), nl,
test_complex_objects,
nl.
test_simple_objects :-
SimpleObjects = [собака, кошка, рыбка, попугай],
forall(member(Obj, SimpleObjects), test_simple_object_full(Obj)).
test_complex_objects :-
ComplexObjects = [хомяк, черепаха, игуана, канарейка],
forall(member(Obj, ComplexObjects), test_complex_object_full(Obj)).
test_simple_object_full(Object) :-
setup_answers_for_object(Object),
( knows(Object) ->
write('✓ '), write(Object), write(' - определен правильно'), nl
; write('✗ '), write(Object), write(' - ошибка определения'), nl
),
retractall(answer(_, _)).
test_complex_object_full(Object) :-
setup_answers_for_object(Object),
( knows(Object) ->
write('✓ '), write(Object), write(' - определен правильно'), nl
; write('✗ '), write(Object), write(' - ошибка определения'), nl
),
retractall(answer(_, _)).
% Настройка ответов для каждого объекта
setup_answers_for_object(собака) :-
retractall(answer(_, _)),
assert(answer(has_fur, yes)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(makes_sound, yes)).
setup_answers_for_object(кошка) :-
retractall(answer(_, _)),
assert(answer(has_fur, yes)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(makes_sound, yes)),
assert(answer(is_small, no)).
setup_answers_for_object(рыбка) :-
retractall(answer(_, _)),
assert(answer(has_fur, no)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, yes)).
setup_answers_for_object(попугай) :-
retractall(answer(_, _)),
assert(answer(has_fur, no)),
assert(answer(can_fly, yes)),
assert(answer(makes_sound, yes)),
assert(answer(can_sing, no)).
setup_answers_for_object(хомяк) :-
retractall(answer(_, _)),
assert(answer(has_fur, yes)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(is_small, yes)),
assert(answer(makes_sound, no)).
setup_answers_for_object(черепаха) :-
retractall(answer(_, _)),
assert(answer(has_fur, no)),
assert(answer(can_fly, no)),
assert(answer(has_shell, yes)),
assert(answer(is_reptile, yes)).
setup_answers_for_object(игуана) :-
retractall(answer(_, _)),
assert(answer(has_fur, no)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(is_reptile, yes)),
assert(answer(has_shell, no)).
setup_answers_for_object(канарейка) :-
retractall(answer(_, _)),
assert(answer(has_fur, no)),
assert(answer(can_fly, yes)),
assert(answer(makes_sound, yes)),
assert(answer(can_sing, yes)),
assert(answer(is_small, yes)).
% -----------------------------------------------
% Сравнение типов объектов
% -----------------------------------------------
demo_object_comparison :-
write('Анализ различий между типами объектов:'), nl, nl,
write('БАЗОВЫЕ ВОПРОСЫ (для всех объектов):'), nl,
BaseQuestions = [has_fur, can_fly, lives_in_water, makes_sound],
forall(member(Q, BaseQuestions),
(question(Q, Text), write(' - '), write(Text), nl)),
nl,
write('ДОПОЛНИТЕЛЬНЫЕ ВОПРОСЫ (только для сложных объектов):'), nl,
AdditionalQuestions = [is_small, has_shell, is_reptile, can_sing],
forall(member(Q, AdditionalQuestions),
(question(Q, Text), write(' - '), write(Text), nl)),
nl,
write('ПРИМЕРЫ РАЗЛИЧЕНИЯ:'), nl,
write('- Кошка vs Хомяк: размер (is_small)'), nl,
write('- Попугай vs Канарейка: умение петь (can_sing)'), nl,
write('- Черепаха vs Игуана: наличие панциря (has_shell)'), nl,
nl.
% -----------------------------------------------
% Инструкции по использованию
% -----------------------------------------------
demo_usage_instructions :-
write('Как использовать акинатор:'), nl, nl,
write('1. ИНТЕРАКТИВНАЯ ИГРА:'), nl,
write(' ?- start_akinator.'), nl,
write(' Загадайте одно из животных и отвечайте на вопросы'), nl, nl,
write('2. ДЕМОНСТРАЦИОННЫЕ КОМАНДЫ:'), nl,
write(' ?- demo. % Полная демонстрация'), nl,
write(' ?- show_objects. % Показать все объекты'), nl,
write(' ?- show_questions. % Показать все вопросы'), nl,
write(' ?- akinator_stats. % Статистика системы'), nl,
write(' ?- test_object_recognition. % Тестирование'), nl, nl,
write('3. ПРОВЕРКА КОНКРЕТНЫХ ОБЪЕКТОВ:'), nl,
write(' Настройте ответы и проверьте распознавание:'), nl,
write(' ?- retractall(answer(_,_)), assert(answer(has_fur,yes)), knows(X).'), nl, nl,
write('4. MAKEFILE КОМАНДЫ:'), nl,
write(' make run % Запуск с основной информацией'), nl,
write(' make demo % Запуск демонстрации'), nl,
write(' make interactive % Интерактивная сессия'), nl,
write(' make test % Запуск тестов'), nl,
nl.
% -----------------------------------------------
% Вспомогательные тесты
% -----------------------------------------------
test_object_recognition_simple(Object) :-
setup_answers_for_object(Object),
( knows(Object) ->
write(' → Распознавание: УСПЕШНО')
; write(' → Распознавание: ОШИБКА')
),
retractall(answer(_, _)).
test_object_recognition_complex(Object) :-
setup_answers_for_object(Object),
( knows(Object) ->
write(' → Распознавание: УСПЕШНО')
; write(' → Распознавание: ОШИБКА')
),
retractall(answer(_, _)).
% -----------------------------------------------
% Интерактивные примеры
% -----------------------------------------------
example_queries_task4 :-
write('=== ПРИМЕРЫ ИНТЕРАКТИВНЫХ ЗАПРОСОВ ЗАДАНИЯ 4 ==='), nl,
write('Вы можете выполнить следующие запросы в интерактивной сессии:'), nl, nl,
write('1. Запуск акинатора:'), nl,
write(' ?- start_akinator. % Интерактивная игра'), nl, nl,
write('2. Проверка объектов:'), nl,
write(' ?- object(X). % Найти все объекты'), nl,
write(' ?- knows(собака). % Проверить правила для собаки'), nl,
write(' ?- knows(хомяк). % Проверить правила для хомяка'), nl, nl,
write('3. Работа с ответами:'), nl,
write(' ?- assert(answer(has_fur,yes)). % Установить ответ'), nl,
write(' ?- answer(has_fur, X). % Проверить ответ'), nl,
write(' ?- retractall(answer(_,_)). % Очистить все ответы'), nl, nl,
write('4. Тестирование:'), nl,
write(' ?- test_object_recognition. % Полное тестирование'), nl,
write(' ?- demo_recognition_tests. % Демо-тесты'), nl, nl,
write('5. Информационные запросы:'), nl,
write(' ?- show_objects. % Показать объекты'), nl,
write(' ?- show_questions. % Показать вопросы'), nl,
write(' ?- akinator_stats. % Статистика'), nl,
write(' ?- demo. % Полная демонстрация'), nl, nl.

@ -0,0 +1,7 @@
FROM swipl:stable
WORKDIR /app
COPY *.pl ./
CMD ["swipl", "-g", "consult('domain.pl')", "-t", "halt"]

@ -0,0 +1,45 @@
.PHONY: build run interactive clean test trace demo
# Build Docker image
build:
docker build -t lab8-task5-prolog .
# Run Prolog with domain database (show basic info and exit)
run: build
docker run --rm -v $(PWD):/app lab8-task5-prolog swipl -g "consult('domain.pl'), write('=== DOMAIN DESIGN TASK5 ==='), nl, show_domain_stats, halt"
# Interactive Prolog session
interactive: build
docker run -it --rm -v $(PWD):/app lab8-task5-prolog swipl domain.pl
# Run test queries
test: build
docker run --rm -v $(PWD):/app lab8-task5-prolog swipl -g "consult('domain.pl'), consult('tests.pl'), run_tests, halt"
# Run with tracing enabled
trace: build
docker run --rm -v $(PWD):/app lab8-task5-prolog swipl -g "consult('domain.pl'), trace, analyze_domain, notrace, halt"
# Show basic info about task5
info: build
docker run --rm -v $(PWD):/app lab8-task5-prolog swipl -g "consult('domain.pl'), write('=== TASK5 INFO ==='), nl, show_domain_stats, show_questions_analysis, halt"
# Run demo
demo: build
docker run --rm -v $(PWD):/app lab8-task5-prolog swipl -g "consult('domain.pl'), consult('demo.pl'), demo, halt"
# Clean Docker images
clean:
docker rmi lab8-task5-prolog || true
# Help
help:
@echo "Available commands for lab8 task5:"
@echo " make build - Build Docker image"
@echo " make run - Run and show domain structure"
@echo " make info - Show detailed task5 information"
@echo " make demo - Run demonstration queries"
@echo " make test - Run test queries"
@echo " make interactive - Start interactive Prolog session"
@echo " make trace - Run with tracing enabled"
@echo " make clean - Clean Docker images"

@ -0,0 +1,374 @@
% ===============================================
% Демонстрационные запросы для lab8 task5
% Дизайн предметной области
% ===============================================
% Запуск демонстрации
demo :-
write('=== ДЕМОНСТРАЦИЯ ЗАДАНИЯ 5: ДИЗАЙН ПРЕДМЕТНОЙ ОБЛАСТИ ==='), nl, nl,
% 1. Основная информация о предметной области
write('1. ОСНОВНАЯ ИНФОРМАЦИЯ О ПРЕДМЕТНОЙ ОБЛАСТИ'), nl,
write('=========================================='), nl,
demo_basic_domain_info,
nl,
% 2. Анализ структуры вопросов
write('2. АНАЛИЗ СТРУКТУРЫ ВОПРОСОВ'), nl,
write('============================'), nl,
demo_questions_structure,
nl,
% 3. Демонстрация групп объектов
write('3. ГРУППИРОВКА ОБЪЕКТОВ'), nl,
write('======================='), nl,
demo_object_grouping,
nl,
% 4. Проверка различимости
write('4. ПРОВЕРКА РАЗЛИЧИМОСТИ ОБЪЕКТОВ'), nl,
write('================================='), nl,
demo_distinguishability,
nl,
% 5. Тестирование идентификации
write('5. ТЕСТИРОВАНИЕ ИДЕНТИФИКАЦИИ'), nl,
write('============================='), nl,
demo_identification_tests,
nl,
% 6. Статистический анализ
write('6. СТАТИСТИЧЕСКИЙ АНАЛИЗ'), nl,
write('========================'), nl,
demo_statistical_analysis,
nl,
% 7. Рекомендации по оптимизации
write('7. РЕКОМЕНДАЦИИ ПО ОПТИМИЗАЦИИ'), nl,
write('==============================='), nl,
demo_optimization_recommendations,
nl,
write('=== ДЕМОНСТРАЦИЯ ЗАДАНИЯ 5 ЗАВЕРШЕНА ==='), nl.
% -----------------------------------------------
% Основная информация о предметной области
% -----------------------------------------------
demo_basic_domain_info :-
show_domain_stats,
nl,
write('ОПИСАНИЕ ПРЕДМЕТНОЙ ОБЛАСТИ:'), nl,
write('Данная предметная область содержит различных животных,'), nl,
write('которые можно классифицировать по 5 основным характеристикам.'), nl,
write('Область охватывает домашних и диких животных различных типов.'), nl.
% -----------------------------------------------
% Анализ структуры вопросов
% -----------------------------------------------
demo_questions_structure :-
write('Анализ покрытия и эффективности вопросов:'), nl,
question_coverage_analysis,
nl,
write('ДЕТАЛЬНЫЙ АНАЛИЗ ВОПРОСОВ:'), nl,
analyze_question_effectiveness,
nl.
% Анализ эффективности вопросов
analyze_question_effectiveness :-
findall(Q, question(Q, _), Questions),
forall(member(Question, Questions), analyze_single_question(Question)).
analyze_single_question(Question) :-
question(Question, Text),
findall(Obj, characteristic(Obj, Question, yes), YesObjects),
findall(Obj, characteristic(Obj, Question, no), NoObjects),
length(YesObjects, YesCount),
length(NoObjects, NoCount),
Total is YesCount + NoCount,
( Total > 0 ->
YesPercent is (YesCount * 100) // Total,
NoPercent is (NoCount * 100) // Total,
write(' '), write(Question), write(' ('), write(Text), write(')'), nl,
write(' ДА: '), write(YesCount), write(' ('), write(YesPercent), write('%)'), nl,
write(' НЕТ: '), write(NoCount), write(' ('), write(NoPercent), write('%)'), nl
; write(' '), write(Question), write(': нет данных'), nl
).
% -----------------------------------------------
% Демонстрация групп объектов
% -----------------------------------------------
demo_object_grouping :-
write('Группировка по основным характеристикам:'), nl,
analyze_object_groups,
nl,
write('ПЕРЕСЕЧЕНИЯ ГРУПП:'), nl,
demo_group_intersections.
demo_group_intersections :-
write('Домашние хищники: '),
findall(Obj, (characteristic(Obj, is_domestic, yes),
characteristic(Obj, is_predator, yes)), DomPred),
print_list(DomPred), nl,
write('Крупные летающие: '),
findall(Obj, (characteristic(Obj, is_large, yes),
characteristic(Obj, can_fly, yes)), LargeFlying),
print_list(LargeFlying), nl,
write('Мелкие дикие хищники: '),
findall(Obj, (characteristic(Obj, is_large, no),
characteristic(Obj, is_domestic, no),
characteristic(Obj, is_predator, yes)), SmallWildPred),
print_list(SmallWildPred), nl,
write('Летающие без меха: '),
findall(Obj, (characteristic(Obj, can_fly, yes),
characteristic(Obj, has_fur, no)), FlyingNoFur),
print_list(FlyingNoFur), nl.
% -----------------------------------------------
% Проверка различимости
% -----------------------------------------------
demo_distinguishability :-
write('Проверка уникальности объектов:'), nl,
check_uniqueness_detailed,
nl,
write('Примеры различающих вопросов:'), nl,
demo_distinguishing_examples.
check_uniqueness_detailed :-
findall(Obj, object(Obj), Objects),
check_uniqueness_for_objects(Objects).
check_uniqueness_for_objects([]).
check_uniqueness_for_objects([Obj|Rest]) :-
find_identical_objects(Obj, Identical),
( Identical = [] ->
write('✓ '), write(Obj), write(' - уникален'), nl
; write('✗ '), write(Obj), write(' - неуникален, идентичен: '),
print_list(Identical), nl
),
check_uniqueness_for_objects(Rest).
demo_distinguishing_examples :-
write('Примеры различения похожих объектов:'), nl,
% Кошка vs хомяк (оба домашние с мехом)
write('Кошка vs Хомяк:'), nl,
find_distinguishing_questions(кошка, хомяк, Diff1),
write(' Различающие вопросы: '), print_list(Diff1), nl,
% Лев vs тигр (оба крупные дикие хищники с мехом)
write('Лев vs Тигр:'), nl,
find_distinguishing_questions(лев, тигр, Diff2),
( Diff2 = [] ->
write(' Неразличимы текущими вопросами!'), nl
; write(' Различающие вопросы: '), print_list(Diff2), nl
),
% Попугай vs канарейка (обе домашние летающие птицы)
write('Попугай vs Канарейка:'), nl,
find_distinguishing_questions(попугай, канарейка, Diff3),
( Diff3 = [] ->
write(' Неразличимы текущими вопросами!'), nl
; write(' Различающие вопросы: '), print_list(Diff3), nl
).
% -----------------------------------------------
% Тестирование идентификации
% -----------------------------------------------
demo_identification_tests :-
write('Тестирование поиска объектов по характеристикам:'), nl,
test_object_identification,
nl,
write('ДОПОЛНИТЕЛЬНЫЕ ТЕСТЫ:'), nl,
demo_additional_identification_tests.
demo_additional_identification_tests :-
% Тест: только домашние
write('Поиск только по признаку "домашнее":'), nl,
identify_object_by_characteristics([is_domestic-yes], Domestic),
write(' Найдено объектов: '), length(Domestic, DCount), write(DCount), nl,
write(' Объекты: '), print_list(Domestic), nl, nl,
% Тест: летающие нехищники
write('Поиск летающих нехищников:'), nl,
identify_object_by_characteristics([can_fly-yes, is_predator-no], FlyingNonPred),
write(' Найдено объектов: '), length(FlyingNonPred, FNPCount), write(FNPCount), nl,
write(' Объекты: '), print_list(FlyingNonPred), nl, nl,
% Тест: крупные без меха
write('Поиск крупных без меха:'), nl,
identify_object_by_characteristics([is_large-yes, has_fur-no], LargeNoFur),
write(' Найдено объектов: '), length(LargeNoFur, LNFCount), write(LNFCount), nl,
write(' Объекты: '), print_list(LargeNoFur), nl.
% -----------------------------------------------
% Статистический анализ
% -----------------------------------------------
demo_statistical_analysis :-
write('Подробная статистика по категориям:'), nl,
category_statistics,
nl,
write('АНАЛИЗ РАСПРЕДЕЛЕНИЯ:'), nl,
analyze_distribution_balance,
nl,
write('ЭФФЕКТИВНОСТЬ КЛАССИФИКАЦИИ:'), nl,
analyze_classification_efficiency.
analyze_distribution_balance :-
findall(Q, question(Q, _), Questions),
forall(member(Question, Questions), check_question_balance(Question)).
check_question_balance(Question) :-
findall(_, characteristic(_, Question, yes), YesAnswers),
findall(_, characteristic(_, Question, no), NoAnswers),
length(YesAnswers, YesCount),
length(NoAnswers, NoCount),
Total is YesCount + NoCount,
( Total > 0 ->
Diff is abs(YesCount - NoCount),
Percentage is (Diff * 100) // Total,
write(' '), write(Question), write(': '),
( Percentage < 20 ->
write('сбалансирован ('), write(Percentage), write('% разброс)')
; Percentage < 40 ->
write('умеренно сбалансирован ('), write(Percentage), write('% разброс)')
; write('несбалансирован ('), write(Percentage), write('% разброс)')
), nl
; write(' '), write(Question), write(': нет данных'), nl
).
analyze_classification_efficiency :-
findall(Obj, object(Obj), Objects),
length(Objects, Total),
findall(Obj, is_unique_object(Obj), UniqueObjects),
length(UniqueObjects, UniqueCount),
DuplicateCount is Total - UniqueCount,
write('Общее количество объектов: '), write(Total), nl,
write('Уникальных объектов: '), write(UniqueCount), nl,
write('Неуникальных объектов: '), write(DuplicateCount), nl,
( DuplicateCount = 0 ->
write('✓ Все объекты различимы текущими вопросами'), nl
; Efficiency is (UniqueCount * 100) // Total,
write('Эффективность различения: '), write(Efficiency), write('%'), nl,
( Efficiency >= 90 ->
write('✓ Отличная различимость'), nl
; Efficiency >= 70 ->
write('⚠ Хорошая различимость'), nl
; write('✗ Требуется улучшение'), nl
)
).
% -----------------------------------------------
% Рекомендации по оптимизации
% -----------------------------------------------
demo_optimization_recommendations :-
write('Анализ качества предметной области:'), nl,
% Проверка покрытия
findall(Q, question(Q, _), Questions),
findall(Obj, object(Obj), Objects),
length(Questions, QCount),
length(Objects, OCount),
MaxDistinguishable is 2^QCount,
write('Текущая ситуация:'), nl,
write(' Вопросов: '), write(QCount), nl,
write(' Объектов: '), write(OCount), nl,
write(' Максимум различимых: '), write(MaxDistinguishable), nl, nl,
( OCount =< MaxDistinguishable ->
write('✓ ХОРОШО: Количество вопросов достаточно'), nl
; write('✗ ПРОБЛЕМА: Недостаточно вопросов'), nl,
NeededQuestions is ceiling(log(OCount)/log(2)),
write(' Рекомендуется минимум '), write(NeededQuestions), write(' вопросов'), nl
), nl,
% Рекомендации по балансировке
write('РЕКОМЕНДАЦИИ ПО УЛУЧШЕНИЮ:'), nl,
provide_improvement_recommendations.
provide_improvement_recommendations :-
% Найти несбалансированные вопросы
findall(Q, unbalanced_question(Q), UnbalancedQuestions),
( UnbalancedQuestions = [] ->
write('✓ Все вопросы достаточно сбалансированы'), nl
; write('⚠ Несбалансированные вопросы: '),
print_list(UnbalancedQuestions), nl,
write(' Рекомендация: добавить объекты для балансировки'), nl
), nl,
% Найти неуникальные объекты
findall(Obj, \+ is_unique_object(Obj), NonUniqueObjects),
( NonUniqueObjects = [] ->
write('✓ Все объекты уникальны'), nl
; write('⚠ Неуникальные объекты найдены'), nl,
write(' Рекомендация: добавить дополнительные вопросы'), nl,
write(' или изменить характеристики объектов'), nl
), nl,
write('ПРЕДЛОЖЕНИЯ ПО ДОПОЛНИТЕЛЬНЫМ ВОПРОСАМ:'), nl,
suggest_additional_questions.
unbalanced_question(Question) :-
findall(_, characteristic(_, Question, yes), YesAnswers),
findall(_, characteristic(_, Question, no), NoAnswers),
length(YesAnswers, YesCount),
length(NoAnswers, NoCount),
Total is YesCount + NoCount,
Total > 0,
Diff is abs(YesCount - NoCount),
Percentage is (Diff * 100) // Total,
Percentage >= 60. % Считаем несбалансированным если разброс >= 60%
suggest_additional_questions :-
write('Потенциальные дополнительные вопросы:'), nl,
write(' - "Это млекопитающее?" (для различения птиц/рептилий/млекопитающих)'), nl,
write(' - "Живет в воде?" (для различения водных и наземных)'), nl,
write(' - "Имеет полосы?" (для различения зебры/тигра и других)'), nl,
write(' - "Ночное животное?" (для различения по активности)'), nl,
write(' - "Может быть домашним питомцем?" (дополнительное уточнение)'), nl.
% -----------------------------------------------
% Интерактивные примеры
% -----------------------------------------------
example_queries_task5 :-
write('=== ПРИМЕРЫ ИНТЕРАКТИВНЫХ ЗАПРОСОВ ЗАДАНИЯ 5 ==='), nl,
write('Вы можете выполнить следующие запросы в интерактивной сессии:'), nl, nl,
write('1. Основная информация:'), nl,
write(' ?- show_domain_stats. % Статистика предметной области'), nl,
write(' ?- analyze_domain. % Полный анализ'), nl,
write(' ?- category_statistics. % Статистика по категориям'), nl, nl,
write('2. Анализ объектов:'), nl,
write(' ?- object(X). % Найти все объекты'), nl,
write(' ?- characteristic(собака, X, Y). % Характеристики собаки'), nl,
write(' ?- object_characteristics(кошка, Chars). % Все характеристики кошки'), nl, nl,
write('3. Поиск и идентификация:'), nl,
write(' ?- identify_object_by_characteristics([is_domestic-yes], Objects).'), nl,
write(' ?- characteristic(X, is_predator, yes). % Найти всех хищников'), nl,
write(' ?- characteristic(X, can_fly, yes). % Найти всех летающих'), nl, nl,
write('4. Анализ различимости:'), nl,
write(' ?- objects_distinguishable(лев, тигр). % Различимы ли лев и тигр'), nl,
write(' ?- find_distinguishing_questions(кошка, собака, Questions).'), nl,
write(' ?- is_unique_object(попугай). % Уникален ли попугай'), nl, nl,
write('5. Групповой анализ:'), nl,
write(' ?- analyze_object_groups. % Анализ групп'), nl,
write(' ?- check_object_distinguishability. % Проверка различимости'), nl,
write(' ?- test_object_identification. % Тестирование идентификации'), nl, nl,
write('6. Экспорт данных:'), nl,
write(' ?- export_domain_structure(''domain_export.pl''). % Экспорт в файл'), nl, nl.

@ -0,0 +1,557 @@
% ===============================================
% ДИЗАЙН ПРЕДМЕТНОЙ ОБЛАСТИ - ЗАДАНИЕ 5
% Структура для акинатора: 30 объектов, 5 вопросов
% ===============================================
% ===============================================
% ОПРЕДЕЛЕНИЕ ОБЪЕКТОВ (30 ОБЪЕКТОВ)
% ===============================================
% Домашние животные
object(собака).
object(кошка).
object(попугай).
object(хомяк).
object(рыбка).
object(черепаха).
object(канарейка).
object(кролик).
% Дикие животные
object(лев).
object(тигр).
object(слон).
object(жираф).
object(зебра).
object(волк).
object(медведь).
object(лиса).
object(олень).
object(заяц).
% Птицы
object(орел).
object(сова).
object(ворон).
object(голубь).
object(ласточка).
% Рептилии и земноводные
object(игуана).
object(змея).
object(лягушка).
object(крокодил).
% Насекомые
object(бабочка).
object(пчела).
object(муравей).
% ===============================================
% ВОПРОСЫ (5 ОСНОВНЫХ ВОПРОСОВ)
% ===============================================
question(is_domestic, 'Это домашнее животное?').
question(has_fur, 'Есть ли у животного шерсть или мех?').
question(can_fly, 'Умеет ли животное летать?').
question(is_large, 'Это крупное животное (больше кошки)?').
question(is_predator, 'Это хищник?').
% ===============================================
% ХАРАКТЕРИСТИКИ ОБЪЕКТОВ
% ===============================================
% Домашние животные
characteristic(собака, is_domestic, yes).
characteristic(собака, has_fur, yes).
characteristic(собака, can_fly, no).
characteristic(собака, is_large, yes).
characteristic(собака, is_predator, no).
characteristic(кошка, is_domestic, yes).
characteristic(кошка, has_fur, yes).
characteristic(кошка, can_fly, no).
characteristic(кошка, is_large, no).
characteristic(кошка, is_predator, yes).
characteristic(попугай, is_domestic, yes).
characteristic(попугай, has_fur, no).
characteristic(попугай, can_fly, yes).
characteristic(попугай, is_large, no).
characteristic(попугай, is_predator, no).
characteristic(хомяк, is_domestic, yes).
characteristic(хомяк, has_fur, yes).
characteristic(хомяк, can_fly, no).
characteristic(хомяк, is_large, no).
characteristic(хомяк, is_predator, no).
characteristic(рыбка, is_domestic, yes).
characteristic(рыбка, has_fur, no).
characteristic(рыбка, can_fly, no).
characteristic(рыбка, is_large, no).
characteristic(рыбка, is_predator, no).
characteristic(черепаха, is_domestic, yes).
characteristic(черепаха, has_fur, no).
characteristic(черепаха, can_fly, no).
characteristic(черепаха, is_large, no).
characteristic(черепаха, is_predator, no).
characteristic(канарейка, is_domestic, yes).
characteristic(канарейка, has_fur, no).
characteristic(канарейка, can_fly, yes).
characteristic(канарейка, is_large, no).
characteristic(канарейка, is_predator, no).
characteristic(кролик, is_domestic, yes).
characteristic(кролик, has_fur, yes).
characteristic(кролик, can_fly, no).
characteristic(кролик, is_large, no).
characteristic(кролик, is_predator, no).
% Дикие животные - крупные хищники
characteristic(лев, is_domestic, no).
characteristic(лев, has_fur, yes).
characteristic(лев, can_fly, no).
characteristic(лев, is_large, yes).
characteristic(лев, is_predator, yes).
characteristic(тигр, is_domestic, no).
characteristic(тигр, has_fur, yes).
characteristic(тигр, can_fly, no).
characteristic(тигр, is_large, yes).
characteristic(тигр, is_predator, yes).
characteristic(волк, is_domestic, no).
characteristic(волк, has_fur, yes).
characteristic(волк, can_fly, no).
characteristic(волк, is_large, yes).
characteristic(волк, is_predator, yes).
characteristic(медведь, is_domestic, no).
characteristic(медведь, has_fur, yes).
characteristic(медведь, can_fly, no).
characteristic(медведь, is_large, yes).
characteristic(медведь, is_predator, yes).
characteristic(лиса, is_domestic, no).
characteristic(лиса, has_fur, yes).
characteristic(лиса, can_fly, no).
characteristic(лиса, is_large, no).
characteristic(лиса, is_predator, yes).
% Дикие животные - крупные травоядные
characteristic(слон, is_domestic, no).
characteristic(слон, has_fur, no).
characteristic(слон, can_fly, no).
characteristic(слон, is_large, yes).
characteristic(слон, is_predator, no).
characteristic(жираф, is_domestic, no).
characteristic(жираф, has_fur, no).
characteristic(жираф, can_fly, no).
characteristic(жираф, is_large, yes).
characteristic(жираф, is_predator, no).
characteristic(зебра, is_domestic, no).
characteristic(зебра, has_fur, no).
characteristic(зебра, can_fly, no).
characteristic(зебра, is_large, yes).
characteristic(зебра, is_predator, no).
characteristic(олень, is_domestic, no).
characteristic(олень, has_fur, yes).
characteristic(олень, can_fly, no).
characteristic(олень, is_large, yes).
characteristic(олень, is_predator, no).
% Дикие животные - мелкие
characteristic(заяц, is_domestic, no).
characteristic(заяц, has_fur, yes).
characteristic(заяц, can_fly, no).
characteristic(заяц, is_large, no).
characteristic(заяц, is_predator, no).
% Птицы - хищные
characteristic(орел, is_domestic, no).
characteristic(орел, has_fur, no).
characteristic(орел, can_fly, yes).
characteristic(орел, is_large, yes).
characteristic(орел, is_predator, yes).
characteristic(сова, is_domestic, no).
characteristic(сова, has_fur, no).
characteristic(сова, can_fly, yes).
characteristic(сова, is_large, no).
characteristic(сова, is_predator, yes).
% Птицы - всеядные/зерноядные
characteristic(ворон, is_domestic, no).
characteristic(ворон, has_fur, no).
characteristic(ворон, can_fly, yes).
characteristic(ворон, is_large, no).
characteristic(ворон, is_predator, no).
characteristic(голубь, is_domestic, no).
characteristic(голубь, has_fur, no).
characteristic(голубь, can_fly, yes).
characteristic(голубь, is_large, no).
characteristic(голубь, is_predator, no).
characteristic(ласточка, is_domestic, no).
characteristic(ласточка, has_fur, no).
characteristic(ласточка, can_fly, yes).
characteristic(ласточка, is_large, no).
characteristic(ласточка, is_predator, no).
% Рептилии и земноводные
characteristic(игуана, is_domestic, no).
characteristic(игуана, has_fur, no).
characteristic(игуана, can_fly, no).
characteristic(игуана, is_large, no).
characteristic(игуана, is_predator, no).
characteristic(змея, is_domestic, no).
characteristic(змея, has_fur, no).
characteristic(змея, can_fly, no).
characteristic(змея, is_large, no).
characteristic(змея, is_predator, yes).
characteristic(лягушка, is_domestic, no).
characteristic(лягушка, has_fur, no).
characteristic(лягушка, can_fly, no).
characteristic(лягушка, is_large, no).
characteristic(лягушка, is_predator, no).
characteristic(крокодил, is_domestic, no).
characteristic(крокодил, has_fur, no).
characteristic(крокодил, can_fly, no).
characteristic(крокодил, is_large, yes).
characteristic(крокодил, is_predator, yes).
% Насекомые
characteristic(бабочка, is_domestic, no).
characteristic(бабочка, has_fur, no).
characteristic(бабочка, can_fly, yes).
characteristic(бабочка, is_large, no).
characteristic(бабочка, is_predator, no).
characteristic(пчела, is_domestic, no).
characteristic(пчела, has_fur, no).
characteristic(пчела, can_fly, yes).
characteristic(пчела, is_large, no).
characteristic(пчела, is_predator, no).
characteristic(муравей, is_domestic, no).
characteristic(муравей, has_fur, no).
characteristic(муравей, can_fly, no).
characteristic(муравей, is_large, no).
characteristic(муравей, is_predator, no).
% ===============================================
% АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ
% ===============================================
% Получить все характеристики объекта
object_characteristics(Object, Characteristics) :-
findall(Char-Value, characteristic(Object, Char, Value), Characteristics).
% Проверить уникальность объекта по характеристикам
is_unique_object(Object) :-
object_characteristics(Object, Chars1),
\+ (object(OtherObject),
OtherObject \= Object,
object_characteristics(OtherObject, Chars2),
Chars1 = Chars2).
% Найти объекты с одинаковыми характеристиками
find_identical_objects(Object, IdenticalObjects) :-
object_characteristics(Object, Chars),
findall(Other,
(object(Other),
Other \= Object,
object_characteristics(Other, Chars)),
IdenticalObjects).
% Анализ покрытия вопросами
question_coverage_analysis :-
findall(Q, question(Q, _), Questions),
length(Questions, QCount),
findall(Obj, object(Obj), Objects),
length(Objects, OCount),
write('Анализ покрытия:'), nl,
write('Количество вопросов: '), write(QCount), nl,
write('Количество объектов: '), write(OCount), nl,
MaxCombinations is 2^QCount,
write('Максимум комбинаций: '), write(MaxCombinations), nl,
( OCount =< MaxCombinations ->
write('✓ Вопросов достаточно для различения всех объектов'), nl
; write('✗ Недостаточно вопросов для различения всех объектов'), nl
).
% Проверить различимость всех объектов
check_object_distinguishability :-
write('Проверка различимости объектов:'), nl,
findall(Obj, object(Obj), Objects),
check_all_pairs_distinguishable(Objects).
check_all_pairs_distinguishable([]).
check_all_pairs_distinguishable([H|T]) :-
check_object_against_list(H, T),
check_all_pairs_distinguishable(T).
check_object_against_list(_, []).
check_object_against_list(Obj1, [Obj2|Rest]) :-
( objects_distinguishable(Obj1, Obj2) ->
write('✓ '), write(Obj1), write(' и '), write(Obj2), write(' различимы'), nl
; write('✗ '), write(Obj1), write(' и '), write(Obj2), write(' неразличимы'), nl
),
check_object_against_list(Obj1, Rest).
% Проверить, различимы ли два объекта
objects_distinguishable(Obj1, Obj2) :-
characteristic(Obj1, Question, Value1),
characteristic(Obj2, Question, Value2),
Value1 \= Value2, !.
% Найти минимальный набор вопросов для различения объектов
find_distinguishing_questions(Obj1, Obj2, Questions) :-
findall(Q,
(characteristic(Obj1, Q, V1),
characteristic(Obj2, Q, V2),
V1 \= V2),
Questions).
% Анализ групп объектов
analyze_object_groups :-
write('Анализ групп объектов:'), nl,
% Домашние vs дикие
findall(Obj, characteristic(Obj, is_domestic, yes), Domestic),
findall(Obj, characteristic(Obj, is_domestic, no), Wild),
length(Domestic, DomCount),
length(Wild, WildCount),
write('Домашние животные ('), write(DomCount), write('): '),
print_list(Domestic), nl,
write('Дикие животные ('), write(WildCount), write('): '),
print_list(Wild), nl, nl,
% С мехом vs без меха
findall(Obj, characteristic(Obj, has_fur, yes), Furry),
findall(Obj, characteristic(Obj, has_fur, no), NoFur),
length(Furry, FurCount),
length(NoFur, NoFurCount),
write('С мехом ('), write(FurCount), write('): '),
print_list(Furry), nl,
write('Без меха ('), write(NoFurCount), write('): '),
print_list(NoFur), nl, nl,
% Летающие vs нелетающие
findall(Obj, characteristic(Obj, can_fly, yes), Flying),
findall(Obj, characteristic(Obj, can_fly, no), NonFlying),
length(Flying, FlyCount),
length(NonFlying, NoFlyCount),
write('Летающие ('), write(FlyCount), write('): '),
print_list(Flying), nl,
write('Нелетающие ('), write(NoFlyCount), write('): '),
print_list(NonFlying), nl, nl,
% Крупные vs мелкие
findall(Obj, characteristic(Obj, is_large, yes), Large),
findall(Obj, characteristic(Obj, is_large, no), Small),
length(Large, LargeCount),
length(Small, SmallCount),
write('Крупные ('), write(LargeCount), write('): '),
print_list(Large), nl,
write('Мелкие ('), write(SmallCount), write('): '),
print_list(Small), nl, nl,
% Хищники vs нехищники
findall(Obj, characteristic(Obj, is_predator, yes), Predators),
findall(Obj, characteristic(Obj, is_predator, no), NonPredators),
length(Predators, PredCount),
length(NonPredators, NoPredCount),
write('Хищники ('), write(PredCount), write('): '),
print_list(Predators), nl,
write('Нехищники ('), write(NoPredCount), write('): '),
print_list(NonPredators), nl.
% Вывести список
print_list([]).
print_list([H]) :- write(H).
print_list([H|T]) :- write(H), write(', '), print_list(T).
% ===============================================
% ДЕМОНСТРАЦИОННЫЕ ФУНКЦИИ
% ===============================================
% Показать статистику предметной области
show_domain_stats :-
findall(Obj, object(Obj), Objects),
findall(Q, question(Q, _), Questions),
length(Objects, ObjCount),
length(Questions, QCount),
write('=== СТАТИСТИКА ПРЕДМЕТНОЙ ОБЛАСТИ ==='), nl,
write('Количество объектов: '), write(ObjCount), nl,
write('Количество вопросов: '), write(QCount), nl,
nl,
write('ОБЪЕКТЫ:'), nl,
forall(object(Obj), (write(' - '), write(Obj), nl)),
nl,
write('ВОПРОСЫ:'), nl,
forall(question(Q, Text),
(write(' '), write(Q), write(': '), write(Text), nl)).
% Показать анализ вопросов
show_questions_analysis :-
write('=== АНАЛИЗ ВОПРОСОВ ==='), nl,
question_coverage_analysis,
nl,
analyze_object_groups.
% Анализ предметной области
analyze_domain :-
write('=== ПОЛНЫЙ АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ ==='), nl, nl,
show_domain_stats,
nl,
show_questions_analysis,
nl,
write('=== ПРОВЕРКА РАЗЛИЧИМОСТИ ==='), nl,
check_object_distinguishability,
nl,
write('=== ПОИСК НЕУНИКАЛЬНЫХ ОБЪЕКТОВ ==='), nl,
find_non_unique_objects,
nl,
write('=== АНАЛИЗ ЗАВЕРШЕН ==='), nl.
% Найти неуникальные объекты
find_non_unique_objects :-
findall(Obj, object(Obj), Objects),
find_non_unique_in_list(Objects).
find_non_unique_in_list([]).
find_non_unique_in_list([H|T]) :-
find_identical_objects(H, Identical),
( Identical = [] ->
true
; write('Объект '), write(H), write(' имеет идентичные характеристики с: '),
print_list(Identical), nl
),
find_non_unique_in_list(T).
% Симуляция определения объекта по характеристикам
identify_object_by_characteristics(Characteristics, PossibleObjects) :-
findall(Obj,
(object(Obj),
forall(member(Char-Value, Characteristics),
characteristic(Obj, Char, Value))),
PossibleObjects).
% Тестирование различения объектов
test_object_identification :-
write('=== ТЕСТИРОВАНИЕ ОПРЕДЕЛЕНИЯ ОБЪЕКТОВ ==='), nl,
% Тест 1: Домашняя кошка
write('Тест 1: Поиск домашнего, мелкого, хищника с мехом'), nl,
TestChars1 = [is_domestic-yes, is_large-no, is_predator-yes, has_fur-yes],
identify_object_by_characteristics(TestChars1, Results1),
write('Найденные объекты: '), print_list(Results1), nl, nl,
% Тест 2: Крупный дикий хищник
write('Тест 2: Поиск дикого, крупного хищника'), nl,
TestChars2 = [is_domestic-no, is_large-yes, is_predator-yes],
identify_object_by_characteristics(TestChars2, Results2),
write('Найденные объекты: '), print_list(Results2), nl, nl,
% Тест 3: Летающие домашние
write('Тест 3: Поиск домашних летающих'), nl,
TestChars3 = [is_domestic-yes, can_fly-yes],
identify_object_by_characteristics(TestChars3, Results3),
write('Найденные объекты: '), print_list(Results3), nl, nl.
% ===============================================
% ЭКСПОРТ И ИМПОРТ ДАННЫХ
% ===============================================
% Экспорт структуры предметной области
export_domain_structure(Filename) :-
tell(Filename),
write('% Экспорт предметной области'), nl,
write('% Сгенерировано автоматически'), nl, nl,
% Экспорт объектов
write('% Объекты'), nl,
forall(object(Obj),
(write('object('), write(Obj), write(').'), nl)),
nl,
% Экспорт вопросов
write('% Вопросы'), nl,
forall(question(Q, Text),
(write('question('), write(Q), write(', '),
write(''''), write(Text), write(''''), write(').'), nl)),
nl,
% Экспорт характеристик
write('% Характеристики'), nl,
forall(characteristic(Obj, Char, Value),
(write('characteristic('), write(Obj), write(', '),
write(Char), write(', '), write(Value), write(').'), nl)),
told,
write('Предметная область экспортирована в файл: '), write(Filename), nl.
% Подсчет статистики по категориям
category_statistics :-
write('=== СТАТИСТИКА ПО КАТЕГОРИЯМ ==='), nl,
% Подсчет по типам животных
count_domestic_wild,
count_by_size,
count_by_mobility,
count_by_diet,
count_by_covering.
count_domestic_wild :-
findall(_, characteristic(_, is_domestic, yes), Domestic),
findall(_, characteristic(_, is_domestic, no), Wild),
length(Domestic, DomCount),
length(Wild, WildCount),
write('Домашние/дикие: '), write(DomCount), write('/'), write(WildCount), nl.
count_by_size :-
findall(_, characteristic(_, is_large, yes), Large),
findall(_, characteristic(_, is_large, no), Small),
length(Large, LargeCount),
length(Small, SmallCount),
write('Крупные/мелкие: '), write(LargeCount), write('/'), write(SmallCount), nl.
count_by_mobility :-
findall(_, characteristic(_, can_fly, yes), Flying),
findall(_, characteristic(_, can_fly, no), Ground),
length(Flying, FlyCount),
length(Ground, GroundCount),
write('Летающие/наземные: '), write(FlyCount), write('/'), write(GroundCount), nl.
count_by_diet :-
findall(_, characteristic(_, is_predator, yes), Predators),
findall(_, characteristic(_, is_predator, no), NonPredators),
length(Predators, PredCount),
length(NonPredators, NonPredCount),
write('Хищники/нехищники: '), write(PredCount), write('/'), write(NonPredCount), nl.
count_by_covering :-
findall(_, characteristic(_, has_fur, yes), Furry),
findall(_, characteristic(_, has_fur, no), NonFurry),
length(Furry, FurCount),
length(NonFurry, NonFurCount),
write('С мехом/без меха: '), write(FurCount), write('/'), write(NonFurCount), nl.

@ -0,0 +1,7 @@
FROM swipl:stable
WORKDIR /app
COPY *.pl ./
CMD ["swipl", "-g", "consult('akinator.pl')", "-t", "halt"]

@ -0,0 +1,45 @@
.PHONY: build run interactive clean test trace demo
# Build Docker image
build:
docker build -t lab8-task6-prolog .
# Run Prolog with akinator database (show basic info and exit)
run: build
docker run --rm -v $(PWD):/app lab8-task6-prolog swipl -g "consult('akinator.pl'), write('=== FULL AKINATOR TASK6 ==='), nl, akinator_info, halt"
# Interactive Prolog session
interactive: build
docker run -it --rm -v $(PWD):/app lab8-task6-prolog swipl akinator.pl
# Run test queries
test: build
docker run --rm -v $(PWD):/app lab8-task6-prolog swipl -g "consult('akinator.pl'), consult('tests.pl'), run_tests, halt"
# Run with tracing enabled
trace: build
docker run --rm -v $(PWD):/app lab8-task6-prolog swipl -g "consult('akinator.pl'), trace, start_akinator, notrace, halt"
# Show basic info about task6
info: build
docker run --rm -v $(PWD):/app lab8-task6-prolog swipl -g "consult('akinator.pl'), write('=== TASK6 INFO ==='), nl, akinator_info, akinator_statistics, halt"
# Run demo
demo: build
docker run --rm -v $(PWD):/app lab8-task6-prolog swipl -g "consult('akinator.pl'), consult('demo.pl'), demo, halt"
# Clean Docker images
clean:
docker rmi lab8-task6-prolog || true
# Help
help:
@echo "Available commands for lab8 task6:"
@echo " make build - Build Docker image"
@echo " make run - Run and show akinator info"
@echo " make info - Show detailed task6 information"
@echo " make demo - Run demonstration queries"
@echo " make test - Run test queries"
@echo " make interactive - Start interactive Prolog session"
@echo " make trace - Run with tracing enabled"
@echo " make clean - Clean Docker images"

@ -0,0 +1,978 @@
% ===============================================
% ПОЛНЫЙ АКИНАТОР - ЗАДАНИЕ 6
% Реализация полной системы акинатора
% ===============================================
% ===============================================
% БАЗА ЗНАНИЙ: ОБЪЕКТЫ И ХАРАКТЕРИСТИКИ
% ===============================================
% Животные (30 объектов)
object(собака).
object(кошка).
object(попугай).
object(хомяк).
object(рыбка).
object(черепаха).
object(канарейка).
object(кролик).
object(лев).
object(тигр).
object(слон).
object(жираф).
object(зебра).
object(волк).
object(медведь).
object(лиса).
object(олень).
object(заяц).
object(орел).
object(сова).
object(ворон).
object(голубь).
object(ласточка).
object(игуана).
object(змея).
object(лягушка).
object(крокодил).
object(бабочка).
object(пчела).
object(муравей).
% Вопросы для классификации
question(is_domestic, 'Это домашнее животное?').
question(has_fur, 'Есть ли у животного шерсть или мех?').
question(can_fly, 'Умеет ли животное летать?').
question(is_large, 'Это крупное животное (больше кошки)?').
question(is_predator, 'Это хищник?').
question(lives_in_water, 'Живет ли животное в воде?').
question(is_mammal, 'Это млекопитающее?').
question(has_stripes, 'Есть ли у животного полосы?').
question(is_nocturnal, 'Это ночное животное?').
question(can_swim, 'Умеет ли животное плавать?').
% Характеристики объектов (расширенная база знаний)
% Домашние животные
characteristic(собака, is_domestic, yes).
characteristic(собака, has_fur, yes).
characteristic(собака, can_fly, no).
characteristic(собака, is_large, yes).
characteristic(собака, is_predator, no).
characteristic(собака, lives_in_water, no).
characteristic(собака, is_mammal, yes).
characteristic(собака, has_stripes, no).
characteristic(собака, is_nocturnal, no).
characteristic(собака, can_swim, yes).
characteristic(кошка, is_domestic, yes).
characteristic(кошка, has_fur, yes).
characteristic(кошка, can_fly, no).
characteristic(кошка, is_large, no).
characteristic(кошка, is_predator, yes).
characteristic(кошка, lives_in_water, no).
characteristic(кошка, is_mammal, yes).
characteristic(кошка, has_stripes, no).
characteristic(кошка, is_nocturnal, yes).
characteristic(кошка, can_swim, no).
characteristic(попугай, is_domestic, yes).
characteristic(попугай, has_fur, no).
characteristic(попугай, can_fly, yes).
characteristic(попугай, is_large, no).
characteristic(попугай, is_predator, no).
characteristic(попугай, lives_in_water, no).
characteristic(попугай, is_mammal, no).
characteristic(попугай, has_stripes, no).
characteristic(попугай, is_nocturnal, no).
characteristic(попугай, can_swim, no).
characteristic(хомяк, is_domestic, yes).
characteristic(хомяк, has_fur, yes).
characteristic(хомяк, can_fly, no).
characteristic(хомяк, is_large, no).
characteristic(хомяк, is_predator, no).
characteristic(хомяк, lives_in_water, no).
characteristic(хомяк, is_mammal, yes).
characteristic(хомяк, has_stripes, no).
characteristic(хомяк, is_nocturnal, yes).
characteristic(хомяк, can_swim, no).
characteristic(рыбка, is_domestic, yes).
characteristic(рыбка, has_fur, no).
characteristic(рыбка, can_fly, no).
characteristic(рыбка, is_large, no).
characteristic(рыбка, is_predator, no).
characteristic(рыбка, lives_in_water, yes).
characteristic(рыбка, is_mammal, no).
characteristic(рыбка, has_stripes, no).
characteristic(рыбка, is_nocturnal, no).
characteristic(рыбка, can_swim, yes).
characteristic(черепаха, is_domestic, yes).
characteristic(черепаха, has_fur, no).
characteristic(черепаха, can_fly, no).
characteristic(черепаха, is_large, no).
characteristic(черепаха, is_predator, no).
characteristic(черепаха, lives_in_water, no).
characteristic(черепаха, is_mammal, no).
characteristic(черепаха, has_stripes, no).
characteristic(черепаха, is_nocturnal, no).
characteristic(черепаха, can_swim, yes).
characteristic(канарейка, is_domestic, yes).
characteristic(канарейка, has_fur, no).
characteristic(канарейка, can_fly, yes).
characteristic(канарейка, is_large, no).
characteristic(канарейка, is_predator, no).
characteristic(канарейка, lives_in_water, no).
characteristic(канарейка, is_mammal, no).
characteristic(канарейка, has_stripes, no).
characteristic(канарейка, is_nocturnal, no).
characteristic(канарейка, can_swim, no).
characteristic(кролик, is_domestic, yes).
characteristic(кролик, has_fur, yes).
characteristic(кролик, can_fly, no).
characteristic(кролик, is_large, no).
characteristic(кролик, is_predator, no).
characteristic(кролик, lives_in_water, no).
characteristic(кролик, is_mammal, yes).
characteristic(кролик, has_stripes, no).
characteristic(кролик, is_nocturnal, no).
characteristic(кролик, can_swim, no).
% Дикие хищники
characteristic(лев, is_domestic, no).
characteristic(лев, has_fur, yes).
characteristic(лев, can_fly, no).
characteristic(лев, is_large, yes).
characteristic(лев, is_predator, yes).
characteristic(лев, lives_in_water, no).
characteristic(лев, is_mammal, yes).
characteristic(лев, has_stripes, no).
characteristic(лев, is_nocturnal, yes).
characteristic(лев, can_swim, no).
characteristic(тигр, is_domestic, no).
characteristic(тигр, has_fur, yes).
characteristic(тигр, can_fly, no).
characteristic(тигр, is_large, yes).
characteristic(тигр, is_predator, yes).
characteristic(тигр, lives_in_water, no).
characteristic(тигр, is_mammal, yes).
characteristic(тигр, has_stripes, yes).
characteristic(тигр, is_nocturnal, yes).
characteristic(тигр, can_swim, yes).
characteristic(волк, is_domestic, no).
characteristic(волк, has_fur, yes).
characteristic(волк, can_fly, no).
characteristic(волк, is_large, yes).
characteristic(волк, is_predator, yes).
characteristic(волк, lives_in_water, no).
characteristic(волк, is_mammal, yes).
characteristic(волк, has_stripes, no).
characteristic(волк, is_nocturnal, yes).
characteristic(волк, can_swim, no).
characteristic(медведь, is_domestic, no).
characteristic(медведь, has_fur, yes).
characteristic(медведь, can_fly, no).
characteristic(медведь, is_large, yes).
characteristic(медведь, is_predator, yes).
characteristic(медведь, lives_in_water, no).
characteristic(медведь, is_mammal, yes).
characteristic(медведь, has_stripes, no).
characteristic(медведь, is_nocturnal, no).
characteristic(медведь, can_swim, yes).
characteristic(лиса, is_domestic, no).
characteristic(лиса, has_fur, yes).
characteristic(лиса, can_fly, no).
characteristic(лиса, is_large, no).
characteristic(лиса, is_predator, yes).
characteristic(лиса, lives_in_water, no).
characteristic(лиса, is_mammal, yes).
characteristic(лиса, has_stripes, no).
characteristic(лиса, is_nocturnal, yes).
characteristic(лиса, can_swim, no).
% Дикие травоядные
characteristic(слон, is_domestic, no).
characteristic(слон, has_fur, no).
characteristic(слон, can_fly, no).
characteristic(слон, is_large, yes).
characteristic(слон, is_predator, no).
characteristic(слон, lives_in_water, no).
characteristic(слон, is_mammal, yes).
characteristic(слон, has_stripes, no).
characteristic(слон, is_nocturnal, no).
characteristic(слон, can_swim, yes).
characteristic(жираф, is_domestic, no).
characteristic(жираф, has_fur, no).
characteristic(жираф, can_fly, no).
characteristic(жираф, is_large, yes).
characteristic(жираф, is_predator, no).
characteristic(жираф, lives_in_water, no).
characteristic(жираф, is_mammal, yes).
characteristic(жираф, has_stripes, no).
characteristic(жираф, is_nocturnal, no).
characteristic(жираф, can_swim, no).
characteristic(зебра, is_domestic, no).
characteristic(зебра, has_fur, no).
characteristic(зебра, can_fly, no).
characteristic(зебра, is_large, yes).
characteristic(зебра, is_predator, no).
characteristic(зебра, lives_in_water, no).
characteristic(зебра, is_mammal, yes).
characteristic(зебра, has_stripes, yes).
characteristic(зебра, is_nocturnal, no).
characteristic(зебра, can_swim, no).
characteristic(олень, is_domestic, no).
characteristic(олень, has_fur, yes).
characteristic(олень, can_fly, no).
characteristic(олень, is_large, yes).
characteristic(олень, is_predator, no).
characteristic(олень, lives_in_water, no).
characteristic(олень, is_mammal, yes).
characteristic(олень, has_stripes, no).
characteristic(олень, is_nocturnal, no).
characteristic(олень, can_swim, yes).
characteristic(заяц, is_domestic, no).
characteristic(заяц, has_fur, yes).
characteristic(заяц, can_fly, no).
characteristic(заяц, is_large, no).
characteristic(заяц, is_predator, no).
characteristic(заяц, lives_in_water, no).
characteristic(заяц, is_mammal, yes).
characteristic(заяц, has_stripes, no).
characteristic(заяц, is_nocturnal, no).
characteristic(заяц, can_swim, no).
% Птицы
characteristic(орел, is_domestic, no).
characteristic(орел, has_fur, no).
characteristic(орел, can_fly, yes).
characteristic(орел, is_large, yes).
characteristic(орел, is_predator, yes).
characteristic(орел, lives_in_water, no).
characteristic(орел, is_mammal, no).
characteristic(орел, has_stripes, no).
characteristic(орел, is_nocturnal, no).
characteristic(орел, can_swim, no).
characteristic(сова, is_domestic, no).
characteristic(сова, has_fur, no).
characteristic(сова, can_fly, yes).
characteristic(сова, is_large, no).
characteristic(сова, is_predator, yes).
characteristic(сова, lives_in_water, no).
characteristic(сова, is_mammal, no).
characteristic(сова, has_stripes, no).
characteristic(сова, is_nocturnal, yes).
characteristic(сова, can_swim, no).
characteristic(ворон, is_domestic, no).
characteristic(ворон, has_fur, no).
characteristic(ворон, can_fly, yes).
characteristic(ворон, is_large, no).
characteristic(ворон, is_predator, no).
characteristic(ворон, lives_in_water, no).
characteristic(ворон, is_mammal, no).
characteristic(ворон, has_stripes, no).
characteristic(ворон, is_nocturnal, no).
characteristic(ворон, can_swim, no).
characteristic(голубь, is_domestic, no).
characteristic(голубь, has_fur, no).
characteristic(голубь, can_fly, yes).
characteristic(голубь, is_large, no).
characteristic(голубь, is_predator, no).
characteristic(голубь, lives_in_water, no).
characteristic(голубь, is_mammal, no).
characteristic(голубь, has_stripes, no).
characteristic(голубь, is_nocturnal, no).
characteristic(голубь, can_swim, no).
characteristic(ласточка, is_domestic, no).
characteristic(ласточка, has_fur, no).
characteristic(ласточка, can_fly, yes).
characteristic(ласточка, is_large, no).
characteristic(ласточка, is_predator, no).
characteristic(ласточка, lives_in_water, no).
characteristic(ласточка, is_mammal, no).
characteristic(ласточка, has_stripes, no).
characteristic(ласточка, is_nocturnal, no).
characteristic(ласточка, can_swim, no).
% Рептилии и земноводные
characteristic(игуана, is_domestic, no).
characteristic(игуана, has_fur, no).
characteristic(игуана, can_fly, no).
characteristic(игуана, is_large, no).
characteristic(игуана, is_predator, no).
characteristic(игуана, lives_in_water, no).
characteristic(игуана, is_mammal, no).
characteristic(игуана, has_stripes, no).
characteristic(игуана, is_nocturnal, no).
characteristic(игуана, can_swim, yes).
characteristic(змея, is_domestic, no).
characteristic(змея, has_fur, no).
characteristic(змея, can_fly, no).
characteristic(змея, is_large, no).
characteristic(змея, is_predator, yes).
characteristic(змея, lives_in_water, no).
characteristic(змея, is_mammal, no).
characteristic(змея, has_stripes, no).
characteristic(змея, is_nocturnal, yes).
characteristic(змея, can_swim, yes).
characteristic(лягушка, is_domestic, no).
characteristic(лягушка, has_fur, no).
characteristic(лягушка, can_fly, no).
characteristic(лягушка, is_large, no).
characteristic(лягушка, is_predator, no).
characteristic(лягушка, lives_in_water, yes).
characteristic(лягушка, is_mammal, no).
characteristic(лягушка, has_stripes, no).
characteristic(лягушка, is_nocturnal, no).
characteristic(лягушка, can_swim, yes).
characteristic(крокодил, is_domestic, no).
characteristic(крокодил, has_fur, no).
characteristic(крокодил, can_fly, no).
characteristic(крокодил, is_large, yes).
characteristic(крокодил, is_predator, yes).
characteristic(крокодил, lives_in_water, yes).
characteristic(крокодил, is_mammal, no).
characteristic(крокодил, has_stripes, no).
characteristic(крокодил, is_nocturnal, no).
characteristic(крокодил, can_swim, yes).
% Насекомые
characteristic(бабочка, is_domestic, no).
characteristic(бабочка, has_fur, no).
characteristic(бабочка, can_fly, yes).
characteristic(бабочка, is_large, no).
characteristic(бабочка, is_predator, no).
characteristic(бабочка, lives_in_water, no).
characteristic(бабочка, is_mammal, no).
characteristic(бабочка, has_stripes, no).
characteristic(бабочка, is_nocturnal, no).
characteristic(бабочка, can_swim, no).
characteristic(пчела, is_domestic, no).
characteristic(пчела, has_fur, no).
characteristic(пчела, can_fly, yes).
characteristic(пчела, is_large, no).
characteristic(пчела, is_predator, no).
characteristic(пчела, lives_in_water, no).
characteristic(пчела, is_mammal, no).
characteristic(пчела, has_stripes, yes).
characteristic(пчела, is_nocturnal, no).
characteristic(пчела, can_swim, no).
characteristic(муравей, is_domestic, no).
characteristic(муравей, has_fur, no).
characteristic(муравей, can_fly, no).
characteristic(муравей, is_large, no).
characteristic(муравей, is_predator, no).
characteristic(муравей, lives_in_water, no).
characteristic(муравей, is_mammal, no).
characteristic(муравей, has_stripes, no).
characteristic(муравей, is_nocturnal, no).
characteristic(муравей, can_swim, no).
% ===============================================
% ОСНОВНАЯ ЛОГИКА АКИНАТОРА
% ===============================================
% Глобальные переменные для подсчета статистики
:- dynamic(questions_asked/1).
:- dynamic(session_stats/3). % session_stats(correct_guesses, wrong_guesses, total_questions)
% Инициализация статистики
init_stats :-
retractall(questions_asked(_)),
retractall(session_stats(_, _, _)),
assert(questions_asked(0)),
assert(session_stats(0, 0, 0)).
% Запуск акинатора
start_akinator :-
write('========================================'), nl,
write(' ДОБРО ПОЖАЛОВАТЬ В АКИНАТОР!'), nl,
write('========================================'), nl, nl,
write('Я попытаюсь угадать животное, которое вы загадали.'), nl,
write('Отвечайте на вопросы словами "yes", "no" или "quit".'), nl, nl,
show_available_animals,
nl,
init_stats,
main_game_loop.
% Показать доступных животных
show_available_animals :-
write('Доступные животные для загадывания:'), nl,
findall(Animal, object(Animal), Animals),
show_animals_list(Animals, 1).
show_animals_list([], _).
show_animals_list([Animal|Rest], N) :-
write(N), write('. '), write(Animal),
( (N mod 6 =:= 0) -> nl ; write(' ') ),
N1 is N + 1,
show_animals_list(Rest, N1).
% Основной игровой цикл
main_game_loop :-
write('Загадайте животное и нажмите Enter...'), nl,
read(_),
retractall(answer(_, _)),
start_questioning.
% Начало опроса
start_questioning :-
write('Начинаем игру! Отвечайте yes/no на вопросы:'), nl,
write('========================================='), nl,
ask_questions_intelligently.
% Интеллектуальный алгоритм задавания вопросов
ask_questions_intelligently :-
% Получить текущих кандидатов
get_current_candidates(Candidates),
length(Candidates, CandidateCount),
( CandidateCount =:= 0 ->
handle_no_candidates
; CandidateCount =:= 1 ->
handle_single_candidate(Candidates)
; CandidateCount =< 3 ->
handle_few_candidates(Candidates)
; % Много кандидатов - задать лучший вопрос
find_best_question(Candidates, BestQuestion),
ask_question(BestQuestion),
ask_questions_intelligently
).
% Получить текущих кандидатов на основе ответов
get_current_candidates(Candidates) :-
findall(Object,
(object(Object),
forall(answer(Question, Answer),
characteristic(Object, Question, Answer))),
Candidates).
% Найти лучший вопрос для разделения кандидатов
find_best_question(Candidates, BestQuestion) :-
findall(Question,
(question(Question, _),
\+ answer(Question, _)),
AvailableQuestions),
( AvailableQuestions = [] ->
BestQuestion = is_domestic % Запасной вариант
; find_most_balanced_question(AvailableQuestions, Candidates, BestQuestion)
).
% Найти наиболее сбалансированный вопрос
find_most_balanced_question([Question], _, Question) :- !.
find_most_balanced_question([Q1|RestQuestions], Candidates, BestQuestion) :-
calculate_question_balance(Q1, Candidates, Balance1),
find_most_balanced_question(RestQuestions, Candidates, Q2),
calculate_question_balance(Q2, Candidates, Balance2),
( Balance1 =< Balance2 ->
BestQuestion = Q1
; BestQuestion = Q2
).
% Вычислить сбалансированность вопроса (чем меньше, тем лучше)
calculate_question_balance(Question, Candidates, Balance) :-
findall(Obj,
(member(Obj, Candidates),
characteristic(Obj, Question, yes)),
YesCandidates),
findall(Obj,
(member(Obj, Candidates),
characteristic(Obj, Question, no)),
NoCandidates),
length(YesCandidates, YesCount),
length(NoCandidates, NoCount),
Balance is abs(YesCount - NoCount).
% Обработка случая, когда нет кандидатов
handle_no_candidates :-
write('Странно... Я не могу найти животное с такими характеристиками.'), nl,
write('Возможно, вы ошиблись в ответах или загадали животное, которого нет в моей базе.'), nl,
write('Какое животное вы загадали? '),
read(Mystery),
learn_from_failure(Mystery),
ask_play_again.
% Обработка случая с одним кандидатом
handle_single_candidate([Candidate]) :-
increment_questions_asked,
write('Я думаю, вы загадали: '), write(Candidate), write('!'), nl,
write('Правильно? (yes/no): '),
read(Response),
handle_guess_response(Response, Candidate).
% Обработка случая с несколькими кандидатами (2-3)
handle_few_candidates(Candidates) :-
write('У меня осталось несколько вариантов: '),
write_list(Candidates), nl,
% Попробуем угадать самый вероятный
select_most_likely(Candidates, MostLikely),
increment_questions_asked,
write('Я думаю, это: '), write(MostLikely), write('?'), nl,
write('Правильно? (yes/no): '),
read(Response),
( Response = yes ->
handle_correct_guess(MostLikely)
; Response = no ->
remove_candidate(MostLikely, Candidates, RemainingCandidates),
( RemainingCandidates = [] ->
handle_no_candidates
; RemainingCandidates = [LastCandidate] ->
handle_single_candidate([LastCandidate])
; handle_few_candidates(RemainingCandidates)
)
; write('Пожалуйста, ответьте yes или no.'), nl,
handle_few_candidates(Candidates)
).
% Выбрать наиболее вероятного кандидата
select_most_likely([First|_], First). % Простая стратегия - первый в списке
% Удалить кандидата из списка
remove_candidate(_, [], []).
remove_candidate(Candidate, [Candidate|Rest], Rest) :- !.
remove_candidate(Candidate, [Other|Rest], [Other|NewRest]) :-
remove_candidate(Candidate, Rest, NewRest).
% Задать вопрос пользователю
ask_question(Question) :-
increment_questions_asked,
question(Question, Text),
write('Вопрос: '), write(Text), write(' (yes/no/quit): '),
read(Response),
handle_response(Question, Response).
% Обработка ответа на вопрос
handle_response(_, quit) :-
write('Спасибо за игру! До свидания!'), nl,
show_session_stats, !.
handle_response(Question, yes) :-
assert(answer(Question, yes)).
handle_response(Question, no) :-
assert(answer(Question, no)).
handle_response(Question, _) :-
write('Пожалуйста, ответьте yes, no или quit.'), nl,
ask_question(Question).
% Обработка ответа на догадку
handle_guess_response(yes, Animal) :-
handle_correct_guess(Animal).
handle_guess_response(no, Animal) :-
handle_wrong_guess(Animal).
handle_guess_response(quit, _) :-
write('Спасибо за игру! До свидания!'), nl,
show_session_stats.
handle_guess_response(_, Animal) :-
write('Пожалуйста, ответьте yes, no или quit.'), nl,
write('Я думаю, это '), write(Animal), write('. Правильно? '),
read(Response),
handle_guess_response(Response, Animal).
% Обработка правильной догадки
handle_correct_guess(Animal) :-
write('Отлично! Я угадал '), write(Animal), write('!'), nl,
increment_correct_guesses,
questions_asked(QCount),
write('Мне потребовалось '), write(QCount), write(' вопросов.'), nl,
ask_play_again.
% Обработка неправильной догадки
handle_wrong_guess(Animal) :-
write('Я ошибся с '), write(Animal), write('.'), nl,
write('Какое животное вы загадали? '),
read(CorrectAnimal),
increment_wrong_guesses,
learn_from_mistake(CorrectAnimal, Animal),
ask_play_again.
% Обучение на ошибках
learn_from_mistake(CorrectAnimal, WrongGuess) :-
( object(CorrectAnimal) ->
write('Понятно, это был '), write(CorrectAnimal), write('.'), nl,
analyze_mistake(CorrectAnimal, WrongGuess)
; write('Спасибо! Я запомню животное '), write(CorrectAnimal), write('.'), nl,
write('К сожалению, его пока нет в моей базе данных.'), nl
).
% Анализ ошибки
analyze_mistake(Correct, Wrong) :-
write('Анализирую различия между '), write(Correct),
write(' и '), write(Wrong), write('...'), nl,
find_distinguishing_characteristics(Correct, Wrong),
write('Теперь я буду умнее!'), nl.
find_distinguishing_characteristics(Animal1, Animal2) :-
findall(Question-Value1-Value2,
(characteristic(Animal1, Question, Value1),
characteristic(Animal2, Question, Value2),
Value1 \= Value2),
Differences),
( Differences = [] ->
write('Эти животные имеют одинаковые характеристики в моей базе.'), nl
; write('Ключевые различия:'), nl,
show_differences(Differences)
).
show_differences([]).
show_differences([Question-Value1-Value2|Rest]) :-
question(Question, Text),
write(' '), write(Text), write(' -> '),
write(Value1), write(' vs '), write(Value2), nl,
show_differences(Rest).
% Обучение на неудачах
learn_from_failure(Mystery) :-
write('Буду помнить о '), write(Mystery), write('.'), nl,
write('Добавлю это животное в список для изучения.'), nl.
% Предложить сыграть еще раз
ask_play_again :-
nl,
write('Хотите сыграть еще раз? (yes/no): '),
read(Response),
( Response = yes ->
write('Отлично! Новая игра!'), nl, nl,
main_game_loop
; Response = no ->
write('Спасибо за игру! Было весело!'), nl,
show_session_stats
; write('Пожалуйста, ответьте yes или no.'), nl,
ask_play_again
).
% ===============================================
% СТАТИСТИКА И АНАЛИТИКА
% ===============================================
% Увеличить счетчик заданных вопросов
increment_questions_asked :-
retract(questions_asked(Count)),
NewCount is Count + 1,
assert(questions_asked(NewCount)).
% Увеличить счетчик правильных догадок
increment_correct_guesses :-
retract(session_stats(Correct, Wrong, Total)),
NewCorrect is Correct + 1,
NewTotal is Total + 1,
assert(session_stats(NewCorrect, Wrong, NewTotal)).
% Увеличить счетчик неправильных догадок
increment_wrong_guesses :-
retract(session_stats(Correct, Wrong, Total)),
NewWrong is Wrong + 1,
NewTotal is Total + 1,
assert(session_stats(Correct, NewWrong, NewTotal)).
% Показать статистику сессии
show_session_stats :-
session_stats(Correct, Wrong, Total),
write('========================================'), nl,
write(' СТАТИСТИКА СЕССИИ'), nl,
write('========================================'), nl,
write('Всего игр: '), write(Total), nl,
write('Правильных догадок: '), write(Correct), nl,
write('Неправильных догадок: '), write(Wrong), nl,
( Total > 0 ->
SuccessRate is (Correct * 100) // Total,
write('Процент успеха: '), write(SuccessRate), write('%'), nl
; write('Процент успеха: 0%'), nl
),
write('========================================'), nl.
% Информация об акинаторе
akinator_info :-
findall(Obj, object(Obj), Objects),
findall(Q, question(Q, _), Questions),
length(Objects, ObjCount),
length(Questions, QCount),
write('=== ИНФОРМАЦИЯ ОБ АКИНАТОРЕ ==='), nl,
write('Объектов в базе: '), write(ObjCount), nl,
write('Вопросов в базе: '), write(QCount), nl,
MaxDistinguishable is 2^QCount,
write('Максимум различимых объектов: '), write(MaxDistinguishable), nl,
( ObjCount =< MaxDistinguishable ->
write('✓ База данных сбалансирована'), nl
; write('⚠ Возможны проблемы с различением'), nl
),
nl,
write('КАТЕГОРИИ ЖИВОТНЫХ:'), nl,
show_animal_categories,
nl.
% Показать категории животных
show_animal_categories :-
count_by_category(is_domestic, 'Домашние/дикие'),
count_by_category(is_mammal, 'Млекопитающие/остальные'),
count_by_category(can_fly, 'Летающие/наземные'),
count_by_category(is_predator, 'Хищники/травоядные'),
count_by_category(is_large, 'Крупные/мелкие').
count_by_category(Category, Description) :-
findall(_, characteristic(_, Category, yes), YesList),
findall(_, characteristic(_, Category, no), NoList),
length(YesList, YesCount),
length(NoList, NoCount),
write(' '), write(Description), write(': '),
write(YesCount), write('/'), write(NoCount), nl.
% Статистика акинатора
akinator_statistics :-
write('=== РАСШИРЕННАЯ СТАТИСТИКА ==='), nl,
% Анализ уникальности
analyze_uniqueness,
nl,
% Анализ сложности вопросов
analyze_question_difficulty,
nl,
% Рекомендации
provide_recommendations.
% Анализ уникальности объектов
analyze_uniqueness :-
findall(Obj, object(Obj), Objects),
findall(Obj, is_unique_object(Obj), UniqueObjects),
length(Objects, Total),
length(UniqueObjects, Unique),
Duplicate is Total - Unique,
write('АНАЛИЗ УНИКАЛЬНОСТИ:'), nl,
write(' Всего объектов: '), write(Total), nl,
write(' Уникальных: '), write(Unique), nl,
write(' Дубликатов: '), write(Duplicate), nl,
( Duplicate = 0 ->
write(' ✓ Все объекты различимы'), nl
; Efficiency is (Unique * 100) // Total,
write(' Эффективность различения: '), write(Efficiency), write('%'), nl
).
% Проверка уникальности объекта
is_unique_object(Object) :-
\+ (object(OtherObject),
OtherObject \= Object,
same_characteristics(Object, OtherObject)).
% Проверка одинаковых характеристик
same_characteristics(Obj1, Obj2) :-
\+ (question(Question, _),
characteristic(Obj1, Question, Value1),
characteristic(Obj2, Question, Value2),
Value1 \= Value2).
% Анализ сложности вопросов
analyze_question_difficulty :-
write('АНАЛИЗ СЛОЖНОСТИ ВОПРОСОВ:'), nl,
findall(Q, question(Q, _), Questions),
forall(member(Question, Questions), analyze_single_question_difficulty(Question)).
analyze_single_question_difficulty(Question) :-
question(Question, Text),
findall(_, characteristic(_, Question, yes), YesList),
findall(_, characteristic(_, Question, no), NoList),
length(YesList, YesCount),
length(NoList, NoCount),
Total is YesCount + NoCount,
( Total > 0 ->
Balance is abs(YesCount - NoCount),
BalancePercent is (Balance * 100) // Total,
write(' '), write(Question), write(': '),
( BalancePercent < 20 ->
write('сбалансированный ('), write(BalancePercent), write('%)')
; BalancePercent < 40 ->
write('умеренный ('), write(BalancePercent), write('%)')
; write('несбалансированный ('), write(BalancePercent), write('%)')
), nl
; write(' '), write(Question), write(': нет данных'), nl
).
% Рекомендации по улучшению
provide_recommendations :-
write('РЕКОМЕНДАЦИИ:'), nl,
% Проверка дубликатов
findall(Obj, \+ is_unique_object(Obj), Duplicates),
( Duplicates = [] ->
write(' ✓ Дубликаты не найдены'), nl
; write(' ⚠ Найдены дубликаты, рекомендуется добавить вопросы'), nl
),
% Проверка покрытия
findall(Q, question(Q, _), Questions),
findall(Obj, object(Obj), Objects),
length(Questions, QCount),
length(Objects, ObjCount),
MaxCoverage is 2^QCount,
( ObjCount =< MaxCoverage ->
write(' ✓ Покрытие вопросов достаточное'), nl
; RecommendedQuestions is ceiling(log(ObjCount)/log(2)),
write(' ⚠ Рекомендуется минимум '), write(RecommendedQuestions),
write(' вопросов для '), write(ObjCount), write(' объектов'), nl
).
% ===============================================
% ДЕМОНСТРАЦИОННЫЕ ФУНКЦИИ
% ===============================================
% Демонстрация работы акинатора
demo_akinator :-
write('=== ДЕМОНСТРАЦИЯ АКИНАТОРА ==='), nl, nl,
write('1. ИНФОРМАЦИЯ О БАЗЕ ДАННЫХ'), nl,
write('============================'), nl,
akinator_info,
nl,
write('2. ТЕСТИРОВАНИЕ ЛОГИКИ'), nl,
write('======================'), nl,
test_akinator_logic,
nl,
write('3. АНАЛИЗ ЭФФЕКТИВНОСТИ'), nl,
write('========================'), nl,
akinator_statistics,
nl,
write('4. ИНСТРУКЦИИ ПО ИСПОЛЬЗОВАНИЮ'), nl,
write('==============================='), nl,
show_usage_instructions,
nl.
% Тестирование логики акинатора
test_akinator_logic :-
write('Тестирование поиска кандидатов:'), nl,
% Тест 1: домашний хищник
retractall(answer(_, _)),
assert(answer(is_domestic, yes)),
assert(answer(is_predator, yes)),
get_current_candidates(Candidates1),
write('Домашние хищники: '), write_list(Candidates1), nl,
% Тест 2: крупное летающее
retractall(answer(_, _)),
assert(answer(is_large, yes)),
assert(answer(can_fly, yes)),
get_current_candidates(Candidates2),
write('Крупные летающие: '), write_list(Candidates2), nl,
% Тест 3: полосатое животное
retractall(answer(_, _)),
assert(answer(has_stripes, yes)),
get_current_candidates(Candidates3),
write('Полосатые животные: '), write_list(Candidates3), nl,
retractall(answer(_, _)).
% Показать инструкции по использованию
show_usage_instructions :-
write('КАК ИСПОЛЬЗОВАТЬ АКИНАТОР:'), nl, nl,
write('1. ЗАПУСК ИГРЫ:'), nl,
write(' ?- start_akinator.'), nl,
write(' Следуйте инструкциям на экране'), nl, nl,
write('2. ОТВЕТЫ НА ВОПРОСЫ:'), nl,
write(' yes - да'), nl,
write(' no - нет'), nl,
write(' quit - выход из игры'), nl, nl,
write('3. ДЕМОНСТРАЦИОННЫЕ КОМАНДЫ:'), nl,
write(' ?- demo_akinator. % Полная демонстрация'), nl,
write(' ?- akinator_info. % Информация о базе'), nl,
write(' ?- akinator_statistics. % Статистика'), nl,
write(' ?- test_akinator_logic. % Тестирование логики'), nl, nl,
write('4. MAKEFILE КОМАНДЫ:'), nl,
write(' make run % Показать информацию об акинаторе'), nl,
write(' make interactive % Запустить интерактивную сессию'), nl,
write(' make demo % Запустить демонстрацию'), nl,
write(' make test % Запустить тесты'), nl, nl.
% Вспомогательная функция для вывода списка
write_list([]).
write_list([Item]) :- write(Item).
write_list([Item|Rest]) :-
write(Item), write(', '), write_list(Rest).
% ===============================================
% СЛУЖЕБНЫЕ ПРЕДИКАТЫ
% ===============================================
% Очистка состояния
reset_akinator :-
retractall(answer(_, _)),
retractall(questions_asked(_)),
retractall(session_stats(_, _, _)),
write('Состояние акинатора сброшено.'), nl.
% Экспорт статистики сессии
export_session_stats(Filename) :-
tell(Filename),
write('% Статистика сессии акинатора'), nl,
write('% Экспортировано: '), get_time(Time), write(Time), nl, nl,
session_stats(Correct, Wrong, Total),
write('session_correct_guesses('), write(Correct), write(').'), nl,
write('session_wrong_guesses('), write(Wrong), write(').'), nl,
write('session_total_games('), write(Total), write(').'), nl,
told,
write('Статистика экспортирована в '), write(Filename), nl.
% Получить случайное животное для тестирования
random_animal(Animal) :-
findall(Obj, object(Obj), Objects),
length(Objects, Len),
random(0, Len, Index),
nth0(Index, Objects, Animal).
% Симуляция игры для тестирования
simulate_game(Animal) :-
write('Симуляция игры для животного: '), write(Animal), nl,
retractall(answer(_, _)),
% Устанавливаем все характеристики животного
forall(characteristic(Animal, Question, Answer),
assert(answer(Question, Answer))),
% Проверяем, сможет ли акинатор угадать
get_current_candidates([Animal]),
write('✓ Акинатор успешно определил '), write(Animal), nl.
simulate_game(Animal) :-
write('✗ Акинатор не смог однозначно определить '), write(Animal), nl.

@ -0,0 +1,533 @@
% ===============================================
% Демонстрационные запросы для lab8 task6
% Полный акинатор
% ===============================================
% Запуск демонстрации
demo :-
write('=== ДЕМОНСТРАЦИЯ ЗАДАНИЯ 6: ПОЛНЫЙ АКИНАТОР ==='), nl, nl,
% 1. Информация о системе
write('1. ИНФОРМАЦИЯ О СИСТЕМЕ АКИНАТОРА'), nl,
write('=================================='), nl,
demo_system_info,
nl,
% 2. Демонстрация базы знаний
write('2. ДЕМОНСТРАЦИЯ БАЗЫ ЗНАНИЙ'), nl,
write('============================'), nl,
demo_knowledge_base,
nl,
% 3. Тестирование логики определения
write('3. ТЕСТИРОВАНИЕ ЛОГИКИ ОПРЕДЕЛЕНИЯ'), nl,
write('=================================='), nl,
demo_detection_logic,
nl,
% 4. Анализ эффективности
write('4. АНАЛИЗ ЭФФЕКТИВНОСТИ'), nl,
write('======================='), nl,
demo_efficiency_analysis,
nl,
% 5. Симуляция игровых сценариев
write('5. СИМУЛЯЦИЯ ИГРОВЫХ СЦЕНАРИЕВ'), nl,
write('=============================='), nl,
demo_game_scenarios,
nl,
% 6. Демонстрация обучения
write('6. ДЕМОНСТРАЦИЯ СИСТЕМЫ ОБУЧЕНИЯ'), nl,
write('================================='), nl,
demo_learning_system,
nl,
% 7. Инструкции по использованию
write('7. ИНСТРУКЦИИ ПО ИСПОЛЬЗОВАНИЮ'), nl,
write('==============================='), nl,
demo_usage_guide,
nl,
write('=== ДЕМОНСТРАЦИЯ ЗАДАНИЯ 6 ЗАВЕРШЕНА ==='), nl.
% -----------------------------------------------
% Информация о системе
% -----------------------------------------------
demo_system_info :-
akinator_info,
nl,
write('РАСШИРЕННЫЕ ВОЗМОЖНОСТИ:'), nl,
write('- Интеллектуальный алгоритм задавания вопросов'), nl,
write('- Система обучения на ошибках'), nl,
write('- Статистика игровых сессий'), nl,
write('- Анализ эффективности различения'), nl,
write('- Адаптивная стратегия угадывания'), nl.
% -----------------------------------------------
% Демонстрация базы знаний
% -----------------------------------------------
demo_knowledge_base :-
write('СТРУКТУРА БАЗЫ ЗНАНИЙ:'), nl,
% Показать количество объектов по категориям
demo_category_breakdown,
nl,
% Показать примеры характеристик
write('ПРИМЕРЫ ХАРАКТЕРИСТИК:'), nl,
demo_sample_characteristics,
nl,
% Анализ покрытия
write('АНАЛИЗ ПОКРЫТИЯ ВОПРОСОВ:'), nl,
demo_coverage_analysis.
demo_category_breakdown :-
Categories = [
(is_domestic, 'Домашние животные'),
(is_mammal, 'Млекопитающие'),
(can_fly, 'Летающие'),
(is_predator, 'Хищники'),
(is_large, 'Крупные животные'),
(has_stripes, 'Полосатые'),
(is_nocturnal, 'Ночные'),
(lives_in_water, 'Водные'),
(can_swim, 'Умеющие плавать')
],
forall(member((Category, Description), Categories),
demo_single_category(Category, Description)).
demo_single_category(Category, Description) :-
findall(Obj, characteristic(Obj, Category, yes), Objects),
length(Objects, Count),
write(' '), write(Description), write(': '), write(Count), write(' ('),
( Count =< 5 -> write_list(Objects); write('много объектов') ),
write(')'), nl.
demo_sample_characteristics :-
SampleAnimals = [собака, тигр, орел, лягушка, пчела],
forall(member(Animal, SampleAnimals), demo_animal_characteristics(Animal)).
demo_animal_characteristics(Animal) :-
write(' '), write(Animal), write(': '),
findall(Char-Value, characteristic(Animal, Char, Value), Characteristics),
demo_compact_characteristics(Characteristics),
nl.
demo_compact_characteristics([]).
demo_compact_characteristics([Char-yes|Rest]) :-
write(Char), write('+'),
( Rest \= [] -> write(', '); true ),
demo_compact_characteristics(Rest).
demo_compact_characteristics([_-no|Rest]) :-
demo_compact_characteristics(Rest).
demo_coverage_analysis :-
findall(Q, question(Q, _), Questions),
findall(Obj, object(Obj), Objects),
length(Questions, QCount),
length(Objects, OCount),
MaxCombinations is 2^QCount,
write(' Вопросов: '), write(QCount), nl,
write(' Объектов: '), write(OCount), nl,
write(' Максимум различимых: '), write(MaxCombinations), nl,
Coverage is (OCount * 100) // MaxCombinations,
write(' Использование пространства: '), write(Coverage), write('%'), nl,
( OCount =< MaxCombinations ->
write(' ✓ Покрытие достаточное'), nl
; write(' ⚠ Требуется больше вопросов'), nl
).
% -----------------------------------------------
% Тестирование логики определения
% -----------------------------------------------
demo_detection_logic :-
write('ТЕСТИРОВАНИЕ АЛГОРИТМА ОПРЕДЕЛЕНИЯ:'), nl,
% Тест поиска кандидатов
write('Тест 1: Поиск по одному критерию'), nl,
test_single_criterion_search,
nl,
% Тест поиска по нескольким критериям
write('Тест 2: Поиск по нескольким критериям'), nl,
test_multiple_criteria_search,
nl,
% Тест выбора лучшего вопроса
write('Тест 3: Выбор оптимального вопроса'), nl,
test_best_question_selection,
nl.
test_single_criterion_search :-
TestCriteria = [
(is_domestic-yes, 'домашние'),
(can_fly-yes, 'летающие'),
(is_predator-yes, 'хищники'),
(has_stripes-yes, 'полосатые')
],
forall(member((Criterion-Value, Description), TestCriteria),
test_single_search(Criterion, Value, Description)).
test_single_search(Criterion, Value, Description) :-
retractall(answer(_, _)),
assert(answer(Criterion, Value)),
get_current_candidates(Candidates),
length(Candidates, Count),
write(' '), write(Description), write(': '), write(Count), write(' кандидатов'),
( Count =< 5 -> (write(' ('), write_list(Candidates), write(')'))
; true
), nl.
test_multiple_criteria_search :-
TestCombinations = [
([is_domestic-yes, is_predator-yes], 'домашние хищники'),
([can_fly-yes, is_large-yes], 'крупные летающие'),
([is_mammal-yes, lives_in_water-yes], 'водные млекопитающие'),
([has_stripes-yes, is_large-yes], 'крупные полосатые')
],
forall(member((Criteria, Description), TestCombinations),
test_multiple_search(Criteria, Description)).
test_multiple_search(Criteria, Description) :-
retractall(answer(_, _)),
forall(member(Criterion-Value, Criteria), assert(answer(Criterion, Value))),
get_current_candidates(Candidates),
length(Candidates, Count),
write(' '), write(Description), write(': '), write(Count), write(' кандидатов'),
( Count =< 3 -> (write(' ('), write_list(Candidates), write(')'))
; true
), nl.
test_best_question_selection :-
% Тест на разных наборах кандидатов
TestScenarios = [
([собака, кошка, кролик, хомяк], 'домашние животные'),
([лев, тигр, волк, медведь], 'крупные хищники'),
([попугай, канарейка, орел, сова], 'птицы')
],
forall(member((Candidates, Description), TestScenarios),
test_question_selection(Candidates, Description)).
test_question_selection(Candidates, Description) :-
write(' '), write(Description), write(': '),
find_best_question(Candidates, BestQuestion),
question(BestQuestion, Text),
write('лучший вопрос - '), write(BestQuestion), write(' ('), write(Text), write(')'), nl.
% -----------------------------------------------
% Анализ эффективности
% -----------------------------------------------
demo_efficiency_analysis :-
write('АНАЛИЗ ЭФФЕКТИВНОСТИ СИСТЕМЫ:'), nl,
% Анализ уникальности
demo_uniqueness_analysis,
nl,
% Анализ сложности различения
demo_discrimination_complexity,
nl,
% Прогноз производительности
demo_performance_prediction.
demo_uniqueness_analysis :-
write('АНАЛИЗ УНИКАЛЬНОСТИ ОБЪЕКТОВ:'), nl,
findall(Obj, object(Obj), AllObjects),
findall(Obj, is_unique_object(Obj), UniqueObjects),
length(AllObjects, Total),
length(UniqueObjects, Unique),
Duplicates is Total - Unique,
write(' Всего объектов: '), write(Total), nl,
write(' Уникальных: '), write(Unique), nl,
write(' Дубликатов: '), write(Duplicates), nl,
( Duplicates > 0 ->
write(' Примеры дубликатов:'), nl,
demo_duplicate_examples
; write(' ✓ Все объекты уникальны'), nl
).
demo_duplicate_examples :-
findall(Obj, \+ is_unique_object(Obj), NonUniqueObjects),
FirstFew = [Obj1, Obj2, Obj3, Obj4, Obj5],
( append(FirstFew, _, NonUniqueObjects) -> Examples = FirstFew
; Examples = NonUniqueObjects
),
forall(member(Example, Examples), demo_single_duplicate(Example)).
demo_single_duplicate(Object) :-
findall(Other,
(object(Other), Other \= Object, same_characteristics(Object, Other)),
Duplicates),
( Duplicates \= [] ->
write(' '), write(Object), write(' = '), write_list(Duplicates), nl
; true
).
demo_discrimination_complexity :-
write('СЛОЖНОСТЬ РАЗЛИЧЕНИЯ:'), nl,
% Анализ минимального количества вопросов для различения пар
SamplePairs = [
(собака, кошка),
(лев, тигр),
(попугай, канарейка),
(слон, жираф)
],
forall(member((Obj1, Obj2), SamplePairs),
demo_pair_discrimination(Obj1, Obj2)).
demo_pair_discrimination(Obj1, Obj2) :-
findall(Question,
(characteristic(Obj1, Question, Val1),
characteristic(Obj2, Question, Val2),
Val1 \= Val2),
DiffQuestions),
length(DiffQuestions, DiffCount),
write(' '), write(Obj1), write(' vs '), write(Obj2), write(': '),
( DiffCount = 0 ->
write('неразличимы')
; DiffCount = 1 ->
write('1 вопрос ('), write_list(DiffQuestions), write(')')
; write(DiffCount), write(' вопросов')
), nl.
demo_performance_prediction :-
write('ПРОГНОЗ ПРОИЗВОДИТЕЛЬНОСТИ:'), nl,
% Оценка среднего количества вопросов
findall(Obj, object(Obj), Objects),
length(Objects, Total),
AverageQuestions is ceiling(log(Total)/log(2)),
write(' Теоретический минимум вопросов: '), write(AverageQuestions), nl,
% Анализ реального количества вопросов для различных животных
SampleAnimals = [собака, лев, попугай, рыбка, бабочка],
write(' Практические тесты:'), nl,
forall(member(Animal, SampleAnimals), demo_animal_questions(Animal)).
demo_animal_questions(Animal) :-
% Симуляция: сколько вопросов нужно для определения животного
retractall(answer(_, _)),
simulate_questions_for_animal(Animal, 0, QuestionCount),
write(' '), write(Animal), write(': ~'), write(QuestionCount), write(' вопросов'), nl.
simulate_questions_for_animal(Animal, Count, FinalCount) :-
get_current_candidates(Candidates),
length(Candidates, CandidateCount),
( CandidateCount =< 1 ->
FinalCount = Count
; % Найти лучший вопрос и ответить на него согласно характеристикам животного
find_best_question(Candidates, BestQuestion),
characteristic(Animal, BestQuestion, Answer),
assert(answer(BestQuestion, Answer)),
NewCount is Count + 1,
simulate_questions_for_animal(Animal, NewCount, FinalCount)
).
% -----------------------------------------------
% Симуляция игровых сценариев
% -----------------------------------------------
demo_game_scenarios :-
write('СИМУЛЯЦИЯ РАЗЛИЧНЫХ ИГРОВЫХ СЦЕНАРИЕВ:'), nl,
% Сценарий 1: Быстрое угадывание
write('Сценарий 1: Легкое животное (собака)'), nl,
demo_easy_scenario,
nl,
% Сценарий 2: Сложное угадывание
write('Сценарий 2: Сложное животное (тигр vs лев)'), nl,
demo_difficult_scenario,
nl,
% Сценарий 3: Редкое животное
write('Сценарий 3: Редкое животное (игуана)'), nl,
demo_rare_scenario,
nl.
demo_easy_scenario :-
Animal = собака,
write(' Загаданное животное: '), write(Animal), nl,
retractall(answer(_, _)),
% Симуляция последовательности вопросов
Questions = [is_domestic, is_large, has_fur, is_predator],
demo_question_sequence(Animal, Questions, 1).
demo_difficult_scenario :-
Animal = тигр,
write(' Загаданное животное: '), write(Animal), nl,
write(' Конкурент: лев (очень похожие характеристики)'), nl,
retractall(answer(_, _)),
% Найти различающий вопрос
findall(Q,
(characteristic(тигр, Q, V1),
characteristic(лев, Q, V2),
V1 \= V2),
DiffQuestions),
write(' Ключевые различающие вопросы: '), write_list(DiffQuestions), nl,
% Симуляция до точки различения
Questions = [is_domestic, is_mammal, is_large, is_predator, has_stripes],
demo_question_sequence(Animal, Questions, 1).
demo_rare_scenario :-
Animal = игуана,
write(' Загаданное животное: '), write(Animal), nl,
retractall(answer(_, _)),
% Показать, что делает это животное уникальным
write(' Уникальные характеристики: рептилия, не хищник, не живет в воде'), nl,
Questions = [is_mammal, is_predator, lives_in_water, can_fly],
demo_question_sequence(Animal, Questions, 1).
demo_question_sequence(_, [], _).
demo_question_sequence(Animal, [Question|RestQuestions], Num) :-
characteristic(Animal, Question, Answer),
assert(answer(Question, Answer)),
question(Question, Text),
write(' Вопрос '), write(Num), write(': '), write(Text), write(' -> '), write(Answer), nl,
get_current_candidates(Candidates),
length(Candidates, Count),
write(' Остается кандидатов: '), write(Count),
( Count =< 5 -> (write(' ('), write_list(Candidates), write(')'))
; true
), nl,
NextNum is Num + 1,
demo_question_sequence(Animal, RestQuestions, NextNum).
% -----------------------------------------------
% Демонстрация системы обучения
% -----------------------------------------------
demo_learning_system :-
write('ВОЗМОЖНОСТИ СИСТЕМЫ ОБУЧЕНИЯ:'), nl,
write('1. Анализ ошибок:'), nl,
write(' - Система запоминает неправильные догадки'), nl,
write(' - Анализирует различия между объектами'), nl,
write(' - Предлагает улучшения базы знаний'), nl, nl,
write('2. Адаптация стратегии:'), nl,
write(' - Выбор оптимальных вопросов'), nl,
write(' - Балансировка между скоростью и точностью'), nl,
write(' - Учет частоты загадывания объектов'), nl, nl,
write('3. Пример анализа ошибки:'), nl,
demo_error_analysis_example,
nl,
write('4. Статистика обучения:'), nl,
demo_learning_statistics.
demo_error_analysis_example :-
write(' Сценарий: Акинатор угадал "лев", а было "тигр"'), nl,
write(' Анализ различий:'), nl,
findall(Q-V1-V2,
(characteristic(лев, Q, V1),
characteristic(тигр, Q, V2),
V1 \= V2),
Differences),
forall(member(Question-LionVal-TigerVal, Differences),
(question(Question, Text),
write(' '), write(Text), write(': лев='), write(LionVal),
write(', тигр='), write(TigerVal), nl)).
demo_learning_statistics :-
write(' Метрики для отслеживания:'), nl,
write(' - Процент успешных угадываний'), nl,
write(' - Среднее количество вопросов'), nl,
write(' - Частота ошибок по категориям'), nl,
write(' - Эффективность различных стратегий'), nl.
% -----------------------------------------------
% Инструкции по использованию
% -----------------------------------------------
demo_usage_guide :-
write('ПОЛНОЕ РУКОВОДСТВО ПО ИСПОЛЬЗОВАНИЮ:'), nl, nl,
write('1. ЗАПУСК ИГРЫ:'), nl,
write(' ?- start_akinator.'), nl,
write(' Система проведет вас через весь процесс игры'), nl, nl,
write('2. ДЕМОНСТРАЦИОННЫЕ КОМАНДЫ:'), nl,
write(' ?- demo. % Полная демонстрация'), nl,
write(' ?- demo_akinator. % Демо акинатора'), nl,
write(' ?- akinator_info. % Информация о системе'), nl,
write(' ?- akinator_statistics. % Статистика эффективности'), nl, nl,
write('3. ТЕСТИРОВАНИЕ:'), nl,
write(' ?- test_akinator_logic. % Тест логики'), nl,
write(' ?- simulate_game(собака). % Симуляция для животного'), nl,
write(' ?- random_animal(X). % Случайное животное'), nl, nl,
write('4. АНАЛИЗ ДАННЫХ:'), nl,
write(' ?- get_current_candidates(X). % Текущие кандидаты'), nl,
write(' ?- find_best_question([собака,кошка], Q). % Лучший вопрос'), nl,
write(' ?- is_unique_object(тигр). % Проверка уникальности'), nl, nl,
write('5. УТИЛИТЫ:'), nl,
write(' ?- reset_akinator. % Сброс состояния'), nl,
write(' ?- show_session_stats. % Статистика сессии'), nl,
write(' ?- export_session_stats(''stats.pl''). % Экспорт статистики'), nl, nl,
write('6. MAKEFILE КОМАНДЫ:'), nl,
write(' make run % Информация об акинаторе'), nl,
write(' make interactive % Интерактивная игра'), nl,
write(' make demo % Демонстрация возможностей'), nl,
write(' make test % Запуск тестов'), nl,
write(' make trace % Трассировка выполнения'), nl, nl,
write('7. СОВЕТЫ ПО ИГРЕ:'), nl,
write(' - Отвечайте честно на все вопросы'), nl,
write(' - Если акинатор ошибся, сообщите правильный ответ'), nl,
write(' - Система учится на ваших ответах'), nl,
write(' - Попробуйте загадать разных животных'), nl, nl.
% -----------------------------------------------
% Интерактивные примеры
% -----------------------------------------------
example_queries_task6 :-
write('=== ПРИМЕРЫ ИНТЕРАКТИВНЫХ ЗАПРОСОВ ЗАДАНИЯ 6 ==='), nl,
write('Вы можете выполнить следующие запросы в интерактивной сессии:'), nl, nl,
write('1. Запуск акинатора:'), nl,
write(' ?- start_akinator. % Полная игра'), nl,
write(' ?- demo_akinator. % Демонстрация'), nl, nl,
write('2. Анализ и статистика:'), nl,
write(' ?- akinator_info. % Информация о системе'), nl,
write(' ?- akinator_statistics. % Подробная статистика'), nl,
write(' ?- show_session_stats. % Статистика сессии'), nl, nl,
write('3. Тестирование логики:'), nl,
write(' ?- test_akinator_logic. % Тест алгоритмов'), nl,
write(' ?- simulate_game(собака). % Симуляция игры'), nl,
write(' ?- get_current_candidates(Candidates). % Поиск кандидатов'), nl, nl,
write('4. Работа с вопросами:'), nl,
write(' ?- find_best_question([лев,тигр], Question). % Лучший вопрос'), nl,
write(' ?- question(X, Text). % Все вопросы'), nl,
write(' ?- characteristic(собака, X, Y). % Характеристики'), nl, nl,
write('5. Анализ уникальности:'), nl,
write(' ?- is_unique_object(тигр). % Проверка уникальности'), nl,
write(' ?- same_characteristics(лев, тигр). % Сравнение объектов'), nl,
write(' ?- find_distinguishing_characteristics(лев, тигр). % Различия'), nl, nl,
write('6. Утилиты:'), nl,
write(' ?- reset_akinator. % Сброс состояния'), nl,
write(' ?- random_animal(Animal). % Случайное животное'), nl,
write(' ?- export_session_stats(''file.pl''). % Экспорт данных'), nl, nl.
Loading…
Cancel
Save