Зарегистрировано «___»_____20___г. ________ __________________________ Подпись (расшифровка подписи) ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ БЕЛГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ УНИВЕРСИТЕТ (НИУ «БелГУ») ФАКУЛЬТЕТ КОМПЬЮТЕРНЫХ НАУК И ТЕЛЕКОММУНИКАЦИЙ КАФЕДРА МАТЕМАТИЧЕСКОГО ОБЕСПЕЧЕНИЯ И АДМИНИСТРИРОВАНИЯ ВЫЧИСЛИТЕЛЬНЫХ СИСТЕМ РАЗРАБОТКА ЭКСПЕРТНОЙ СИСТЕМЫ ВЫБОРА ТУРИСТИЧЕСКОГО ТУРА Курсовая работа студентки дневного отделения 4 курса группы 140901 Батищева Дениса Сергеевича Научный руководитель: ассистент Сунцова А.И. БЕЛГОРОД 2013 Содержание Введение ....................................................................................................................... 3 1. Экспертные системы. Базы знаний. Prolog........................................................... 5 1.1 Назначение экспертных систем .................................................................... 5 1.2 Особенности экспертных систем .................................................................. 6 1.3. Язык логического программирования ............................................................ 9 2. Разработка экспертной системы выбора туристического тура ........................ 11 2.1 Разработка экспертной системы..................................................................... 11 2.2 Разработка интерфейса ЭС на языке Visual C# 2010. .................................. 15 3. Тестирование экспертной системы ..................................................................... 19 Заключение ................................................................................................................ 22 Библиографический список ..................................................................................... 23 Приложение 1 ............................................................................................................ 24 Приложение 2. ........................................................................................................... 28 Введение Целью данной курсовой работы является разработка экспертной системы «Выбор туристического тура». Тема практически актуальна, так как все больше ресурсов переносится в онлайн, все больши́е базы знаний составляются по разным предметам, и все больше тенденция к потребительству наблюдается у основной части населения планеты. Экспертная система не говорит что лучше, она предоставляет те варианты, критерии которых устраивают пользователя в большей мере. Главным достоинством экспертных систем является возможность накопления знаний и сохранение их длительное время. В отличие от человека к любой информации экспертные системы подходят объективно, что улучшает качество проводимой экспертизы. Экспертная система по выбору туристического тура, может выбрать оптимальный вариант, основываясь на выборе опций пользователем. Все это возможно только благодаря наличию базы знаний в экспертной системе. В первой главе данной курсовой работы рассматриваются экспертные системы, а именно: их назначение и общие принципы построения; механизмы действия и принципы функционирования; классификация экспертных систем. Во второй главе курсовой работы рассматриваются среды разработки, в которых создаются экспертные системы. В третьей главе ведется непосредственное описание процесса разработки экспертной системы, иллюстрированное комментариями и различных аспектов данной экспертной системы. скриншотам 4 Курсовая работа содержит 33 страницы, 6 рисунков, 2 приложения. 5 1. Экспертные системы. Базы знаний. Prolog. Экспертная система — компьютерная программа, способная частично заменить специалиста-эксперта в разрешении проблемной ситуации. Современные ЭС начали разрабатываться исследователями искусственного интеллекта в 1970-х годах, а в 1980-х получили коммерческое подкрепление. Предтечи экспертных систем были предложены в 1832 году С. Н. Корсаковым, создавшим механические устройства, так называемые «интеллектуальные машины», позволявшие находить решения по заданным условиям, например, определять наиболее подходящие лекарства по наблюдаемым у пациента симптомам заболевания[1]. Таким образом, экспертная система, это программа, которая «эмулирует» способности эксперта в принятии решений. В этом разделе будут рассмотрены принципы работы экспертных систем, их применение на практике, отличия от «обычных» программ. 1.1 Назначение экспертных систем В информатике экспертные системы рассматриваются совместно с базами знаний как модели поведения экспертов в определенной области знаний с использованием процедур логического вывода и принятия решений, а базы знаний — как совокупность фактов и правил логического вывода в выбранной предметной области деятельности. Похожие действия выполняет такой программный инструмент как Мастер. ПО данного типа применяется как в системных программах, так и в прикладных для упрощения интерактивного общения с пользователем. Главное 6 отличие мастеров от ЭС — отсутствие базы знаний — все действия жестко запрограммированы. Это просто набор форм для заполнения пользователем. Другие подобные программы — поисковые или справочные (энциклопедические) системы. По запросу пользователя они предоставляют наиболее подходящие (релевантные) разделы базы статей (представления об объектах областей знаний, их виртуальную модель). Программные средства, базирующиеся на технологии экспертных систем, или инженерии знании получили значительное распространение в мире. Важность экспертных систем состоит в следующем: технология экспертных систем существенно расширяет круг практически значимых задач, решаемых на компьютерах, решение которых приносит значительный экономический эффект; технология ЭС является важнейшим средством в решении глобальных проблем традиционного программирования: длительность и, следовательно, высокая стоимость разработки сложных приложений; высокая стоимость сопровождения сложных систем, которая часто в несколько раз превосходит стоимость их разработки; низкий уровень повторной используемости программ и т.п.; объединение технологии ЭС с технологией традиционного программирования добавляет новые качества к программным продуктам за счет: обеспечения динамичной модификации приложений пользователем, а не программистом; большей "прозрачности" приложения. 1.2 Особенности экспертных систем Особенности экспертных систем: 7 • компетентность – в конкретной предметной области экспертная система должна достигать того же уровня, что и специалисты-люди; при этом она должна пользоваться теми же эвристическими приемами, также глубоко и широко отражать предметную область; • символьные рассуждения – знания, на которых основана экспертная система, представляют в символьном виде понятия реального мира, рассуждения также происходят в виде преобразовании символьных наборов; • глубина – экспертиза должна решать серьезные, нетривиальные задачи, отличающиеся сложностью знаний, которые экспертная система использует, или обилием информации; это не позволяет использовать полный перебор вариантов как метод решения задачи и заставляет прибегать к эвристическим, творческим, неформальным методам; • самосознание – экспертная система должна включать в себя механизм объяснения того, каким образом она приходит к решению задачи. Экспертные системы создаются для решения разного рода проблем, но они имеют схожую структуру (рис. 1.1.) и основные типы их деятельности можно сгруппировать в категории. Рис. 1.2.1. Схема обобщенной экспертной системы Диагностические системы используются для установления связи между нарушениями деятельности организма и их возможными причинами. Прогнозирующие системы предсказывают возможные результаты или события на основе данных о текущем состоянии объекта. Хотя пока еще отсутствуют ЭС, которые способны за счет своей информации о конъюнктуре 8 рынка помочь вам увеличить капитал, прогнозирующие системы уже сегодня могут предсказывать погоду, урожайность и поток пассажиров. Даже на персональном компьютере, установив простую систему, основанную на знаниях, вы можете получить местный прогноз погоды. Планирующие системы предназначены для достижения конкретных целей при решении задач с большим числом переменных. Интерпретирующие системы обладают способностью получать определенные заключения на основе результатов наблюдения. Системы, основанные на знаниях, могут применяться в качестве интеллектуальных систем контроля и принимать решения, анализируя данные, поступающие от нескольких источников. Такие системы уже работают на атомных электростанциях, управляют воздушным движением и осуществляют медицинский контроль. Они могут быть также полезны при регулировании финансовой деятельности предприятия и оказывать помощь при выработке решений в критических ситуациях. В сфере диагностики неисправностей в механических и электрических устройств используются системы, основанные на знаниях, незаменимы как при ремонте механических и электрических машин (автомобилей, дизельных локомотивов и т.д.), так и при устранении неисправностей и ошибок в аппаратном и программном обеспечении компьютеров. Системы, основанные на знаниях, могут входить составной частью в компьютерные системы обучения. Система получает информацию о деятельности некоторого объекта (например, студента) и анализирует его поведение. База знаний изменяется в соответствии с поведением объекта. Примером этого обучения может служить компьютерная игра, сложность которой увеличивается по мере возрастания степени квалификации играющего Большинство ЭС включают знания, по содержанию которых их можно отнести одновременно к нескольким типам. 9 1.3. Язык логического программирования При использовании ЭВМ для решения задач можно выделить два взаимосвязанных способа представления знания: 1) процедурное представление, т.е. определение алгоритма обработки данных; 2) декларативное представление, т.е. определение отдельных понятий, их состояния в конкретные моменты времени и связей между ними. Традиционные алгоритмические языки (Паскаль, Си, Фортран) являются процедурными, поскольку их цель – описание алгоритма. Но они содежрат и декларативные компоненты (описание переменных). В языке Пролог, напротив, основной является декларативная компонента, так что он предназначен не столько для обработки данных, как для обработки фактов и декларативных правил. Факты представляют собой логические формулы. База знаний (БЗ) задаётся совокупностью таких формул. Логические методы обеспечивают получение новых фактов из фактов, представленных в БЗ. Пролог может использоваться при разработке экспертных систем, а также для следующих задач: - доказательства теорем и вывода решений в задачах; - создания пакетов символьной обработки при решении уравнений, дифференцировании, интегрировании и т.д.; - разработки упрощенных версий систем ИИ; - создания естественно-языковых интерфейсов для существующих программ; - перевода текстов с одного языка на другой, в том числе – с одного языка программирования на другой. 10 Задача пролог – программы заключается в том, чтобы доказать, является ли заданное целевое утверждение следствием из имеющихся фактов и правил. Программа на языке пролог включает следующие основные разделы: описание имён и структур объектов (domains); описание предикатов – названий отношений, существующих между объектами (predicates); раздел целевых утверждений (goal), который может отсутствовать; в этом случае программа будет запрашивать целевое утверждение при запуске; описание фактов и правил, описывающих отношения (clauses). Запрос – это последовательность из одного предиката или множества предикатов, разделяемых запятыми и завершающаяся точкой. С помощью запросов можно установить истинность соответствующего выражения. Предикат запроса называется целью. Простые запросы, не содержащие переменных, называют да-нет-вопросами. Они допускают лишь два возможных ответа: “Yes” достигнута[3]. или “No”. В случае первого ответа говорят, что цель 11 2. Разработка экспертной системы выбора туристического тура В данном разделе рассматривается процесс разработки экспертной системы на Prolog и Windows Forms приложения как оболочки. 2.1 Разработка экспертной системы. Основа экспертной системы – база знаний с фактами и предикаты для логического вывода решения на основе этих фактов. Общую структуру базы знания может охарактеризовать дерево знаний. Дерево состоит из n-листьев. Листья с метками q<n> - вопросы системы, с метками a<n> - ответы. 12 q00 q0 q2 q3 q7 q9 q14 q19 q20 q21 q22 q23 a1 Not(q0) Not(q1) q3 q5 Not(q2) q1 q3 q6 q5 q10 q7 q14 q9 q15 q12 q20 q16 q23 q19 a2 q20 Not(q3) q8 q9 q9 q11 q12 q16 q14 q20 q16 q22 a3 Not(q2) q21 a7 a8 Рис. 2.1.1. Дерево знаний. На рисунке выше представлен фрагмент дерево знаний. Как можно заметить описаны только 5 туров из 10. При большем количестве из-за масштабирования рисунка он станет нечитаемым, поэтому только фрагмент. Для реализация данной базы знания на прологе было введено два предиката: tour<n> и q<n>. Предикат tour<n> описывает логические связи между вопросами, тем самым формируя цепочку вывода. Инициализация экспертной системы выполняется в предикате startQuiz/0. В нем происходит очистка всех основных термов, а так же вызов первого вопроса. Более подробно, описанное выше представлено на листинге с кодом на Пролог: cleanAndClear :retractall( yes(_) ), 13 retractall( no(_) ), retractall( resultTour(_) ), retractall( currentQuestion(_) ), retractall( askedQuestions(_,_) ). startQuiz :cleanAndClear, tour( Tour ), assert( resultTour(Tour) ). Чтобы понять логику описания ответов, ниже приведен пример для одного тура: tour1 :q00, q0, q2, q3, q7, q9, q14, q19, q20, q21, q22, q23 . То есть, каждый тур описывается набором предикатов q/1, в которых описываются ответы. Таким образом, для ответа на вопрос Пролог помещает текст унификации предиката q/1 в терм CurrentQuestion, который потом читается на клиентской стороне. Далее вся логика ответа пользователя на вопросы экспертной системы основывается на встроенных в Пролог предикатах thread_send_message и thread_get_message. Смысл в том, что экспертная система загружает в предикат currentQuestion один из термов q, и далее с помощью thread_get_message ждет реакции пользователя. Пользователь же, в Windows приложении, отвечая «да» или «нет» неявно вызывает предикат thread_send_message, который передает в терм Response или «y», или «n». Далее на основе полученного значения вопрос записывается либо в положительные, либо отрицательные. Реализация описанного выше на языке Пролог: 14 ask(Question) :retractall(currentQuestion(_)), assert(currentQuestion(Question)), thread_get_message(Response), assert(askedQuestions(Question, Response)), ( Response == y -> assert(yes(Question)) ; assert(no(Question)), fail ). answer(S) :(yes(S) -> true ; (no(S) -> fail ; ask(S))). Как можно заметить, в предикате answer/1 добавлены условия для уже вопросов, на которые пользователь дал ответ. Это реализуется с помощью попытки унификации предиката yes/1 или no/1. Таким образом, если пользователь уже отвечал на вопросы, которые содержатся в следующем предикате q/1, ему не надо отвечать повторно, Пролог за счет унификации пометит эти вопросы решенными. В случае, когда ответа на вопрос нет, Пролог передает терм S в предикат ask/1, в котором уже данные терм помещается как аргумент предиката currentQuestion и вызывается предикат thread_get_message. В зависимости от полученного из данного предиката значения терма Response 15 терм текущего вопроса помечается или как положительно отвеченный, либо – отрицательно. 2.2 Разработка интерфейса ЭС на языке Visual C# 2010. Приложение разрабатывалось с использованием ЯП C#. В качестве Prolog-библиотеки выступал SWI-Prolog v 6.2.13. Основная форма приложения содержит главное меню с тремя кнопками, одну кнопку типа Button и компонент RichTextBox. Работу с базой знаний приложения начинает сразу после запуска основной формы. Для этого в обработчик события загрузки формы добавлен код открытия OpenFileDialog с помощью которого выбирается файл с базой знаний. Далее этот файл используется, как аргумент для запуска движка Пролог методом PlEngine.Initialize( string[] params ). String[ ] _params = new String[ ] { "-q", "-f", expertSystemDBFile }; if ( !PlEngine.IsInitialized ) PlEngine.Initialize( _params ); Так же на форме расположена одна кнопка, меню и компонент RichTextBox. Компонент RichTextBox содержит трассировку заданных вопросов и их ответов. С помощью этой трассировки пользователь может видеть историю заданных вопросов, которая является своего рода логической цепочкой вывода ответа. В меню с помощью обработчика события нажатия на кнопку “Load Quiz” происходит вызов предиката startQuiz/0, который инициализирует необходимые термы пролога и вызывает первый вопрос. 16 Ниже представлен участок кода – обработчика события открытия формы. this._LogsForm.AddLog( "\nLoading quiz..." ); this.askQuestionButton.Enabled = true; PlQuery.PlCall( "startQuiz", new PlTermV( 0 ) ); String tourName = String.Empty; PlQuery query = new PlQuery( "resultTour( TourName )" ); foreach ( PlQueryVariables answVar in query.SolutionVariables ) tourName = answVar["TourName"].ToString( ); MessageBox.Show( "Ваш выбор - " + tourName, "Result", MessageBoxButtons.OK ); this.askQuestionButton.Enabled = false; Как можно заметить, сначала происходит вызов предиката startQuiz, и, так как его арность 0, это надо явно указывать. Далее, в этом же обработчике идет вызов предиката, который возвращает терм в котором указано найденное решение. Можно подумать, что это не логично, но так работает библиотека SwiPlCs. Дело в том, что при вызове предиката startQuiz/0 происходит переход в предикат ask/1, thread_get_mesage/1 который ожидает с помощью реакции встроенного пользователя, но предиката так как thread_get_message не возвращает управление пользователю, это неявно делает SwiPlCs. Таким образом, становится реальным использование двух запросов в пределах одного обработчика события. То есть, после вызова startQuiz/1 происходит неявное возвращение управления пользователю и реализуется логика вопрос-ответ, далее, при нахождении решения, управление 17 возвращается в обработчик события открытия формы, и становится возможной выборка терма с найденным решением. Далее, щелкая по кнопке Question, происходит вызов предиката currentQuestion, который является текущим вопросом для пользователя. Значение данного терма используется, как сообщение для компонента MessageBox. MessageBox удобен модальностью, то есть однозначность выбора либо «Да», либо «Нет». В зависимости от ответа пользователя вызывается встроенный в пролог предикат thread_send_message/2, с помощью которого осуществляется определение ответа пользователя. Ниже представлен фрагмент кода на C# для определения пользовательского ответа. String question = String.Empty; PlQuery query = new PlQuery( "currentQuestion( Question )" ); foreach ( PlQueryVariables answVar in query.SolutionVariables ) question = answVar["Question"].ToString( ); DialogResult quesionDialogResult; quesionDialogResult = MessageBox.Show( ( question + "?" ), "???", MessageBoxButtons.YesNo ); if ( quesionDialogResult == DialogResult.Yes ) PlQuery.PlCall( "thread_send_message(1, y)" ); else PlQuery.PlCall( "thread_send_message(1, n)" ); При условии достижения любой из целей предиката tour<1> возвращается управление в метод обработчика события нажатия по кнопке “Start Quiz”. В данном обработчике прочитывается терм resultTour, в котором содержится или 18 достигнутое решение с названием тура, либо сообщение о недостижимости цели в случае неизвестной комбинации ответов. Для отображения трассировки заданных вопросов в цикле происходит вызов предиката askedQuestions, который возвращает 2 переменных: вопрос и ответ на него. Реализуется с помощью следующего кода: PlQuery query = new PlQuery( "askedQuestions( Question, Answer )" ); foreach ( PlQueryVariables answVar in query.SolutionVariables ) this.questionsTraceRichTextBox.Text ).AppendFormat( "Question: \"{0}\", += ( new answer: StringBuilder( \"{1}\"\n", answVar["Question"].ToString( ), answVar["Answer"].ToString( ) ).ToString( ) ); 19 3. Тестирование экспертной системы После запуска приложения, происходит автоматический вызов диалога открытия файла, в котором надо выбрать файл с базой знаний. Далее, этот файл загружается в движок пролог и появляется основная форма. Рис. 3.1. Вид основной формы приложения после запуска. Как можно заметить – кнопка для ответа на вопрос не активна, так как еще не инициализирован опрос и не загружен первый вопрос. После нажатия на кнопку “Load Quiz” происходят необходимые действия и кнопка “Question” становится активной. Стоит отметить, что после завершения опроса и нахождения решения, она опять переключается в неактивное состояния. Это 20 сделано для того, чтобы не генерировать необъяснимые ситуации. Активировать обратно кнопку можно инициализировав опрос заново. После активации кнопки “Question” можно вызвать сообщение с текущим вопросом и вариантами ответов для него. Рис 3.2. MessageBox с текущим вопросом и кнопками ответа на него После ответа на несколько вопросов становится возможным вывод результирующего ответа и отображение его в новом MessageBox. Рис. 3.3. MessageBox с возможным решением 21 Кроме того, в любой момент можно отобразить трассировку заданных вопрос с ответами на них. Реализация данного действия описана в главе о разработке приложения. Рис. 3.4. Пример трассировки заданных вопросов с найденным решением 22 Заключение При выполнении курсовой работы была достигнута поставленная цель: создана экспертная система «Выбор туристического тура». При этом мною были изучены теоретические сведения об экспертных системах и их применении, закреплены навыки программирования на языке С#, изучены основы работы с языком логического программирования Пролог. Известно, что огромное количество людей практически каждый год уезжают на отдых. Но многие из них еще до конца не определились. Поэтому, при условии качественного наполнения базы знаний фактами, отражающими реальность, можно с уверенностью говорить о том, что такие системы могут пользоваться определенным спросом в современное время. При выполнении курсовой были решены следующие задачи: Во-первых, разработана база знаний на языке логического программирования Пролог с набором необходимых термов и предикатов для вывода корректного решения; Во-вторых, разработана Windows оболочка для базы знаний, реализующая все поставленные задачи В совокупности – разработана экспертная система, которая на основе нескольких вопросов выбирает подходящий ответ. Система протестирована и удовлетворяет базовым критериям реагирования на действия пользователя. работоспособности и адекватности 23 Библиографический список Книги Книга одного автора М. В. Бураков – Язык логического программирования Пролог – СанктПетербург, 2003. – 37 с. Книга двух авторов Стерлинг Л., Шапиро Э. Искусство программирования на языке Пролог – Москва, 1990. – 325 с. 24 Приложение 1 База знаний. Экспертная система. :- dynamic resultTour/1 . :- dynamic currentQuestion/1 . :- dynamic askedQuestions/2 . :- dynamic yes/1 , no/1 . cleanAndClear :retractall( yes(_) ), retractall( no(_) ), retractall( resultTour(_) ), retractall( currentQuestion(_) ), retractall( askedQuestions(_,_) ). startQuiz :cleanAndClear, tour( Tour ), assert( resultTour(Tour) ). tour('Вам не нужна экспертная система') :- not(q00), ! . tour('Вы бы определились уже..!') :- notKnown, ! . tour('Болгария, курортный поселок Дюни, отель Марина Бийч') :- tour1, !. 25 tour('Болгария, Святой Влас, аппартаменты Дейзи') :- tour2, ! . tour('Египет, Хургада, отель El Tabia') :- tour3, ! . tour('Египет, Макади Бей, отель Royal Azur') :- tour4, ! . tour('Мальта, Буджиба, отель The Bugibba Hotel') :- tour5, ! . tour('Мальта, Сент-Джулианс, отель Hilton Malta') :- tour6, ! . tour('Россия, Анапа, лагерь Энергетик') :- tour7, ! . tour('Россия, Анапа, санаторий Россиянка') :- tour8, ! . tour('Абхазия, Гагра, гостиница Alex Beach Hotel') :- tour9, ! . tour('Абхазия, Золотой берег, Гудаутский район, пансионат Золотой Берег') :tour10, ! . tour( 'Не могу ничего посоветовать :(' ) :- ! . notKnown :- q00, not(q0), ( not(q1) , not(q2) ). tour1 :q00, q0, q2, q3, q7, q9, q14, q19, q20, q21, q22, q23 . tour2 :q00, q0, not(q1), q3, q5, q6, q10, q14, q15, q20, q23. tour3 :q00, q0, not(q2), q3, q5, q7, q9, q12, q16, q19, q20, q22. tour4 :q00, q0, (q1 ; q2), q3, q6, q7, q8, q9, q14, q15, q23 . tour5 :q00, q0, (q1 ; q2), q4, q5, q7, q8, q10, q13, q14, q16, q21 . tour6 :q00, q0, (not(q1) ; q2), q3, q7, q8, q9, q13, q15, q20, q22 . tour7 :q00, not(q0), (q1 ; not(q2)), not(q3), q8, q9, q12, q16, q20 . tour8 :q00, not(q0), (q1 ; not(q2)), not(q3), q9, q11, q12, q14, q16, q21 . 26 tour9 :q00, not(q0), not(q1), q4, q5, q6, q7, q10, q20 . tour10 :q00, not(q0), (not(q1) ; not(q2)), q4, q5, q8, q16, q18, q20, q21 . q00 :- answer('Выбираете тур?'). q0 :- answer('Направление: Европа?'). q1 :- answer('Тип: отдых с детьми'). q2 :- answer('Тип: пляжный отдых'). q3 :- answer('Расположения отеля: отель на пляже'). q4 :- answer('В номере: наличие санузела/душа в номере'). q5 :- answer('В номере: наличие телевизора'). q6 :- answer('В номере: минибар'). q7 :- answer('Тип питания: швецкий стол'). q8 :- answer('На территории: наличие бассейна'). q9 :- answer('Тип пляжа: песчаный'). q10 :- answer('Тип пляжа: галечный'). q11 :- answer('Для детей: детский стол'). q12 :- answer('Для детей: детская площадка'). q13 :- answer('Развлечения: пляжное парти'). q14 :- answer('Развлечения: дискотека'). q15 :- answer('Развлечения: мини-гольф'). q16 :- answer('Развлечения: анимационные программы'). q17 :- answer('Красота и здоровье: джакузи'). q18 :- answer('Красота и здоровье: сауна'). q19 :- answer('Красота и здоровье: фитнес'). q20 :- answer('Развлечения: экскурсии'). q21 :- answer('Красота и здоровье: массаж'). q22 :- answer('Развлечения: рядом aквапарк'). 27 q23 :- answer('Красота и здоровье: SPA-центр'). ask(Question) :retractall(currentQuestion(_)), assert(currentQuestion(Question)), thread_get_message(Response), assert(askedQuestions(Question, Response)), ( Response == y -> assert(yes(Question)) ; assert(no(Question)), fail ). answer(S) :(yes(S) -> true ; (no(S) -> fail ; ask(S))). 28 Приложение 2. Windows приложение using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using SbsSW.SwiPlCs; namespace ExpertSystem { public partial class MainForm : Form { private LogsForm _LogsForm; public MainForm( ) { InitializeComponent( ); } // load knowledge base private void MainForm_Load( object sender, EventArgs e ) { this._LogsForm = new LogsForm( this ); 29 OpenFileDialog openFileDialog = new OpenFileDialog( ); String expertSystemDBFile = ""; if ( openFileDialog.ShowDialog( ) == DialogResult.OK ) expertSystemDBFile = openFileDialog.FileName; String[ ] _params = new String[ ] { "-q", "-f", expertSystemDBFile }; if ( !PlEngine.IsInitialized ) { PlEngine.Initialize( _params ); this._LogsForm.AddLogsRange( new string[ ] { "PlEngine initialized", new StringBuilder( ).AppendFormat( "Loaded file: {0}", expertSystemDBFile ).ToString( ) } ); } this.askQuestionButton.Enabled = false; } // clean and stop prolog engine private void MainForm_FormClosing( object sender, FormClosingEventArgs e ) { PlEngine.PlCleanup( ); PlEngine.PlHalt( ); } // load quiz. Fill currentQuesting term. Some kind of Prolog magic :) private void loadQuizToolStripMenuItem_Click( EventArgs e ) { this._LogsForm.AddLog( "\nLoading quiz..." ); this.askQuestionButton.Enabled = true; object sender, 30 PlQuery.PlCall( "startQuiz", new PlTermV( 0 ) ); String tourName = String.Empty; PlQuery query = new PlQuery( "resultTour( TourName )" ); foreach ( PlQueryVariables answVar in query.SolutionVariables ) tourName = answVar["TourName"].ToString( ); MessageBox.Show( "Ваш выбор - " + tourName, "Result", MessageBoxButtons.OK ); this.askQuestionButton.Enabled = false; } private void showTraceToolStripMenuItem_Click( object sender, EventArgs e ) { this.questionsTraceRichTextBox.Text = ( "Asked questions backtrace...\n" ); PlQuery query = new PlQuery( "askedQuestions( Question, Answer )" ); foreach ( PlQueryVariables answVar in query.SolutionVariables ) this.questionsTraceRichTextBox.Text ).AppendFormat( "Question: += ( \"{0}\", new StringBuilder( answer: \"{1}\"\n", answVar["Question"].ToString( ), answVar["Answer"].ToString( ) ).ToString( ) ); query = new PlQuery( "resultTour( TourName )" ); foreach ( PlQueryVariables answVar in query.SolutionVariables ) this.questionsTraceRichTextBox.Text += ( new StringBuilder( ).AppendFormat( "\nSuggestion: \"{0}\", \n", answVar["TourName"].ToString( ) ).ToString( ) ); } 31 // raise and show logs form private void showLogsToolStripMenuItem_Click( object sender, EventArgs e ) { this._LogsForm.Show( ); this._LogsForm.Select( ); } private void askQuestionButton_Click( object sender, EventArgs e ) { String question = String.Empty; PlQuery query = new PlQuery( "currentQuestion( Question )" ); foreach ( PlQueryVariables answVar in query.SolutionVariables ) question = answVar["Question"].ToString( ); DialogResult quesionDialogResult; quesionDialogResult = MessageBox.Show( ( question + "?" ), "???", MessageBoxButtons.YesNo ); if ( quesionDialogResult == DialogResult.Yes ) PlQuery.PlCall( "thread_send_message(1, y)" ); else PlQuery.PlCall( "thread_send_message(1, n)" ); } private void tourGeneratorToolStripMenuItem_Click( object sender, EventArgs e ) { } } 32 } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ExpertSystem { public partial class LogsForm : Form { private MainForm _QwnerForm; public LogsForm( ) { InitializeComponent( ); } public LogsForm( MainForm owner ) { this._QwnerForm = owner; InitializeComponent( ); } private void LogsForm_Shown( object sender, EventArgs e ) { this.Location = new Point( ( this._QwnerForm.Location.X this._QwnerForm.Size.Width + 10 ), this._QwnerForm.Location.Y ); } + 33 private void LogsForm_FormClosing( FormClosingEventArgs e ) { this.Hide( ); e.Cancel = true; } public void AddLog( String newLog ) { String[ ] _currentContent = this.logsRichTextBox.Lines; List<String> _newContent = new List<String>( ); _newContent.AddRange( _currentContent ); _newContent.Add( newLog ); this.logsRichTextBox.Lines = _newContent.ToArray( ); } public void AddLogsRange( String[ ] newLogs ) { String[ ] _currentContent = this.logsRichTextBox.Lines; List<String> _newContent = new List<String>( ); _newContent.AddRange( _currentContent ); _newContent.AddRange( newLogs ); this.logsRichTextBox.Lines = _newContent.ToArray( ); } } } object sender,