From 5cefdb0e7ed6ac4e5d855c0045f83dadbd627a26 Mon Sep 17 00:00:00 2001 From: Artem-Darius Weber Date: Sat, 19 Apr 2025 09:11:34 +0300 Subject: [PATCH] lab 8 task 4 --- lab8/Makefile | 107 ++++- lab8/task4/Dockerfile | 7 + lab8/task4/Makefile | 45 ++ lab8/task4/akinator.pl | 350 +++++++++++++++ lab8/task4/demo.pl | 349 +++++++++++++++ lab8/task5/Dockerfile | 7 + lab8/task5/Makefile | 45 ++ lab8/task5/demo.pl | 374 ++++++++++++++++ lab8/task5/domain.pl | 557 +++++++++++++++++++++++ lab8/task6/Dockerfile | 7 + lab8/task6/Makefile | 45 ++ lab8/task6/akinator.pl | 978 +++++++++++++++++++++++++++++++++++++++++ lab8/task6/demo.pl | 533 ++++++++++++++++++++++ 13 files changed, 3403 insertions(+), 1 deletion(-) create mode 100644 lab8/task4/Dockerfile create mode 100644 lab8/task4/Makefile create mode 100644 lab8/task4/akinator.pl create mode 100644 lab8/task4/demo.pl create mode 100644 lab8/task5/Dockerfile create mode 100644 lab8/task5/Makefile create mode 100644 lab8/task5/demo.pl create mode 100644 lab8/task5/domain.pl create mode 100644 lab8/task6/Dockerfile create mode 100644 lab8/task6/Makefile create mode 100644 lab8/task6/akinator.pl create mode 100644 lab8/task6/demo.pl diff --git a/lab8/Makefile b/lab8/Makefile index ef9fc58..057ab25 100644 --- a/lab8/Makefile +++ b/lab8/Makefile @@ -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" diff --git a/lab8/task4/Dockerfile b/lab8/task4/Dockerfile new file mode 100644 index 0000000..0e61d5b --- /dev/null +++ b/lab8/task4/Dockerfile @@ -0,0 +1,7 @@ +FROM swipl:stable + +WORKDIR /app + +COPY *.pl ./ + +CMD ["swipl", "-g", "consult('akinator.pl')", "-t", "halt"] \ No newline at end of file diff --git a/lab8/task4/Makefile b/lab8/task4/Makefile new file mode 100644 index 0000000..5641da6 --- /dev/null +++ b/lab8/task4/Makefile @@ -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" \ No newline at end of file diff --git a/lab8/task4/akinator.pl b/lab8/task4/akinator.pl new file mode 100644 index 0000000..f492bd3 --- /dev/null +++ b/lab8/task4/akinator.pl @@ -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. \ No newline at end of file diff --git a/lab8/task4/demo.pl b/lab8/task4/demo.pl new file mode 100644 index 0000000..24daa92 --- /dev/null +++ b/lab8/task4/demo.pl @@ -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. \ No newline at end of file diff --git a/lab8/task5/Dockerfile b/lab8/task5/Dockerfile new file mode 100644 index 0000000..3ef2cdc --- /dev/null +++ b/lab8/task5/Dockerfile @@ -0,0 +1,7 @@ +FROM swipl:stable + +WORKDIR /app + +COPY *.pl ./ + +CMD ["swipl", "-g", "consult('domain.pl')", "-t", "halt"] \ No newline at end of file diff --git a/lab8/task5/Makefile b/lab8/task5/Makefile new file mode 100644 index 0000000..cb06ba9 --- /dev/null +++ b/lab8/task5/Makefile @@ -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" \ No newline at end of file diff --git a/lab8/task5/demo.pl b/lab8/task5/demo.pl new file mode 100644 index 0000000..d7f512a --- /dev/null +++ b/lab8/task5/demo.pl @@ -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. \ No newline at end of file diff --git a/lab8/task5/domain.pl b/lab8/task5/domain.pl new file mode 100644 index 0000000..e432ac4 --- /dev/null +++ b/lab8/task5/domain.pl @@ -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. \ No newline at end of file diff --git a/lab8/task6/Dockerfile b/lab8/task6/Dockerfile new file mode 100644 index 0000000..0e61d5b --- /dev/null +++ b/lab8/task6/Dockerfile @@ -0,0 +1,7 @@ +FROM swipl:stable + +WORKDIR /app + +COPY *.pl ./ + +CMD ["swipl", "-g", "consult('akinator.pl')", "-t", "halt"] \ No newline at end of file diff --git a/lab8/task6/Makefile b/lab8/task6/Makefile new file mode 100644 index 0000000..dfb592d --- /dev/null +++ b/lab8/task6/Makefile @@ -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" \ No newline at end of file diff --git a/lab8/task6/akinator.pl b/lab8/task6/akinator.pl new file mode 100644 index 0000000..de7c97f --- /dev/null +++ b/lab8/task6/akinator.pl @@ -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. \ No newline at end of file diff --git a/lab8/task6/demo.pl b/lab8/task6/demo.pl new file mode 100644 index 0000000..4cff9dd --- /dev/null +++ b/lab8/task6/demo.pl @@ -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. \ No newline at end of file