Разработка диалоговой системы, оформленной в виде пакета прикладных программ и реализующей идею искусственного интеллекта

1.Задание на лабораторную работу

Разработать диалоговую систему, оформленную в виде пакета прикладных программ и реализующую идею искусственного интеллекта. Для этого необходимо:

* Самостоятельно выбрать предметную область интеллектуального пакета

* Для выбранной предметной области описать семантическую сеть и правила вывода (базу знаний)

* Разработать блоки системной части пакета, реализующие:

* машину логического вывода

* процедуры работы с семантической сетью

* Подготовить отладочные варианты наборов данных

* Провести машинный эксперимент

* Описать полученные результаты

2.Руководство пользователя

2.1. Назначение программы

      В качестве предметной области была выбрана кулинария.

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

     Программа позволяет корректировать имеющуюся базу знаний и создавать новую. Корректировка заключается в добавлении и удалении знаний и фактов.  Но в целях соблюдения целостности базы знаний программа не позволит удалить некоторые знания и факты. Если факт  входит в состав знания, то его удаление повлечет нарушение целостности базы. Программа предложит сначала удалить знания, в которые входит этот факт, а потом уже сам факт.

2.2.Описание базы знаний

          

База знанийФакты (декларативные знания)Правила (процедурные знания)

Декларативные знания

Числовой кодЗначение12 яйца23 яйца34 яйца4100 грамм молока5200 грамм молока6400 грамм молока70,5 ложки соли81 ложка соли92 ложки соли101 стакан муки112 стакана муки124 стакана муки1310 ложек сахара1413 ложек сахара1515 ложек сахара16Изюм17Дорожжи18Творог19Омлет на 1-го человека20Омлет на 2-х человек21Опара22Тесто23Блины24Яичница на 1-го человека25Яичница на 2-х человек26Кулич27Ватрушка28Жарить29Печь

Процедурные знания

Код порождаемого фактаКоличество

свидетельствСвидетельства1941,4,7,282043,5,8,282145,9,11,1722521,3,4,12,1523222,282431,7,282533,8,2826322,16,2927322,18,29

2.3. Описание диалога

Данная программа построена по принципу диалога с пользователем, что обеспечивает удобство и психологический комфорт при работе с ней.

После запуска программы появляется стандартное windows-окно - в данном случае главное окно, приглашающее вас к работе. Данное окно содержит картинку, располагающую вас к приятной реализации программного продукта, и меню из трех пунктов: Главное меню, содержащее подпункты: Работа с системой и Выход, "Помощь" и  О программе.  Выбрав Работа с системой, вы не только узнаете о ее названии и версии, но и о создателях таковой. Выбор можно осуществлять кроме мыши с помощью сочетания клавиш (Alt + соответствующая буква). Нажав меню Работа с системой, вы окажитесь в окне CulinaryMiracles где вам будет представлены следующие возможности системы: Правка, Работа, Выход. Ознакомившись с пунктом Помощь, в котором содержится общая информация по данному программному продукту, вы смело можете приступать к реализации основных действий.

При выборе Работа с системой  появится рабочее окно, где вам будет предложены имеющиеся факты и цели исходной базы знаний. Теперь все в ваших руках. Данная программа предоставляет три варианта реализации ее возможностей. Во-первых, вы можете выбрать интересующие вас факты и спросить у системы, что можно из них приготовить, во-вторых, выбрать желаемые цели и запросить, какие факты необходимы для их реализации, и наконец в-третьих, выбрать и факты и цели, а затем система выдаст сообщение о том, что все в порядке либо подскажет вам какие из выбранных фактов оказались лишними, а каких не хватает. Выше перечисленные действия реализуются легко и просто с помощью кнопок: добавить факт/цель в список выбранных фактов/целей - "(", удалить факт/цель из списка выбранных фактов/целей - "(" и запуск на выполнение "OK". Для выполнения последующих запросов вам необходимо нажать кнопку "Сброс". 

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

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

 

2.4. Описание работа машинного логического вывода

2.4.1. Описание стратегии

     Стратегия реализации поставленной задачи  разбита на 3 возможных варианта желаний пользователя. Все зависит от того, что пользователь введет: только факты (компоненты), только знания (блюда), и факты и знания. Система сама распознает, какой вариант введен и пойдет по нужному  пути.

Случай 1. Введены только факты. В данном случае система задействует алгоритм планирования с прямым ходом.  Если хоть один целевой факт (т.е. съедобное блюдо) достижим, то программа покажет, что именно. Результатом может стать только одно блюдо. Т.е. на неимеющее смысла перечисление всех ингредиентов, программа скромно выдаст только одно блюдо.

Случай 2. Введены только знания. В этом случае программа задействует  алгоритм планирования с обратным ходом. Можно ввести как одно, так и несколько блюд, и программа выдаст все ингредиенты  для интересующих знаний.

Случай 3. Введены и факты и знания. В этом случае система анализирует, что необходимо для введеных знаний, потом какие необходимые факты ввел пользователь и в заключении сообщает какие факты лишние, а каких недостает.

2.4.2. Прямое планирование

 

Подготовка: обнуление различных ключей и счетчиков.

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

Цикл на просмотр всех правил до порождения целевого факта.

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

. Конец цикла.

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

Алгоритм прямого планирования реализован  в процедуре Direct.

2.4.3. Обратное планирование

   

Подготовка: обнуление различных ключей и счетчиков.

Цикл на просмотр всех введенных пользователем правил. Занесение этого значения в специальный массив.

Цикл на разложение каждого введенного пользователем правила на простые компоненты. Все компоненты (факты и знания)  заносятся в специальный массив, который  анализируется на наличие  в нем правил. Если правило найдено, то его разлагают на более простые составляющие, и так то тех пор, пока от введенного  правила останутся только простые факты.

Конец  цикла. Переход к следующему введенному правилу.

Конец алгоритма. Выдача результатов на экран.

Алгоритм прямого планирования реализован  в процедуре Inv.

2.5.Примеры реализации основных функций пользователя

     

Задание фактов и получение цели

Задание целей и получение фактов

Задание фактов и целей и получение информации о лишних и недостающих фактах

Задание фактов и целей и получение положительного сообщения системы

Добавление факта в базу

3.Описание программы

3.1. Общие свойства

Любая программа в интегрированной среде разработки приложений Delphi 4 состоит из файла проекта (файл с расширением dpr) и нескольких модулей (файлы с расширением pas), каждый из которых описывает программную единицу Object Pascal. Файл проект представляет собой программу, написанную на языке Object Pascal и предназначенную для обработки компилятором. Эта программа автоматически создается Delphi, содержит лишь несколько строк и не предназначена для редактирования.

Данная программа написана с помощью инструмента программирования  Delphi 4 и состоит из файла проекта CulinaryMiraclesи трех модулей: Culinary.pas, About.pas, Help.pas.

3.2. Логическая структура программы

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

3.3.Описание функций модулей

1procedure FormActivate Задание начальных параметров, загрузка базы знаний Base.dat2.

2procedure Timer1Timer Обеспечивает бегущие надписи при заставке3. 3procedure N6ClickОбработчик вызова меню О программе4.

4procedure N2ClickОбработчик вызова меню Работа с системой5.

5Procedure SpeedButton3ClickОбработчик нажатия кнопки Выход, выход из программы6.

6Procedure SpeedButton1ClickОбработчик нажатия кнопки Правка7.

7Procedure SpeedButton8ClickОбработчик нажатия кнопки Возврат, возврат в главное меню8.

Procedure SpeedButton2ClickОбработчик нажатия кнопки Работа, появления окна для выбора фактов и знаний9.

procedure N7ClickОбработчик вызова пункта Возврат в окне выбора фактов

procedure BitBtn1ClickЗанесение фактов в окошко "Выбранные факты"11.

Procedure BitBtn3ClickЗанесение фактов в окошко "Выбранные цели"12.

Procedure BitBtn5ClickОбработчик нажатия кнопки ОК, обработка введеных данных, выдача резльтатов13.

Procedure BitBtn6ClickОбработчик нажатия кнопки Сброс, обнуление счетчиков14. Procedure Timer2TimerОбеспечивает выплывание надписи ОК!15.

Procedure LoadBaseПроцедура открытия новой базы16.

procedure SaveBaseПроцедура сохранения текущей базы17.

Procedure SpeedButton6ClickОбработчик нажатия кнопки Открыть БЗ, выдача соответствующего диалогового окна18.

Procedure SpeedButton7ClickОбработчик нажатия кнопки Сохранить как, выдача соответствующего диалогового окна19.

procedure ListBox1ClickОтображение  фактов в окне "Имеющиеся факты"20.

Procedure SpeedButton4Click Обработчик нажатия кнопки Добавить, отображение окошка для добавления в БЗ фактов21.

Procedure SpeedButton10ClickОбработчик нажатия кнопки Отмена в окошке для добавления фактов, возврат в окно Правка22.

Procedure RadioGroup1ClickОбработчик выбора типа факта в окне добавления фактов23.

procedure AddSimpleFactПроцедура добавления простого факта24.

Procedure SpeedButton9ClickОбработчик нажатия кнопки ОК в окошке для добавления фактов, вызов процедуры AddSimpleFact25.

Procedure SpeedButton11ClickОбработчик нажатия кнопки Добавить при добавлении фактов в БЗ, эта кнопка добавляет факты в знание при его определении26. Procedure AddComplexFactПроцедура добавления правила27.

procedure DeleteFactПроцедура удаления факта28.

Procedure SpeedButton5ClickОбработчик нажатия кнопки Удалить29.

Procedure BitBtn2ClickУдаление фактов в окне "Выбранные факты"30.

procedure BitBtn4ClickУдаление фактов в окне "Выбранные цели"31.

procedure N5ClickВызов пункта меню Помощь, появление окна Помощь32.

procedure N4ClickВызов пункта меню Выход, выход из программы

4.Список литературы

1. В.А.Благодатских, С.Н.Семенов, А.М.Хамов. Лабораторный практикум по прикладному и системному программированию.- М.: Финансы и статистика, 1985.

2. Фаронов В.В. Delphi4,учебный курс. - М.: "Нолидж",1999.

3. В.А. Благодатских, М.А. Енгибарян, Е.В. Ковалевская. Экономика, разработка и использование программного обеспечения ЭВМ. - М.:Финансы и статистика, 1995.

4. Роб Баас, Майк Фервай. Delphi 4 Полное руководство - Киев, издательская группа BHV, 1999.

 

5.Приложения

5.1.Листинги программы

unit Culinary;

interface

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

  ExtCtrls, StdCtrls, jpeg, Menus, Buttons;

type

  TForm1 = class(TForm)

    Image1: TImage;

    Label1: TLabel;

    Label2: TLabel;

    Label3: TLabel;

    Timer1: TTimer;

    MainMenu1: TMainMenu;

    N1: TMenuItem;

    N2: TMenuItem;

    N3: TMenuItem;

    N4: TMenuItem;

    N5: TMenuItem;

    N6: TMenuItem;

    SpeedButton1: TSpeedButton;

    SpeedButton2: TSpeedButton;

    SpeedButton3: TSpeedButton;

    ListBox1: TListBox;

    ListBox2: TListBox;

    Label4: TLabel;

    Label5: TLabel;

    Bevel1: TBevel;

    Bevel2: TBevel;

    SpeedButton4: TSpeedButton;

    SpeedButton5: TSpeedButton;

    SpeedButton6: TSpeedButton;

    SpeedButton7: TSpeedButton;

    SpeedButton8: TSpeedButton;

    Bevel3: TBevel;

    ListBox4: TListBox;

    ListBox5: TListBox;

    ListBox6: TListBox;

    BitBtn1: TBitBtn;

    BitBtn2: TBitBtn;

    BitBtn3: TBitBtn;

    BitBtn4: TBitBtn;

    Label7: TLabel;

    Label8: TLabel;

    Label9: TLabel;

    Label10: TLabel;

    Bevel4: TBevel;

    Bevel5: TBevel;

    N7: TMenuItem;

    BitBtn5: TBitBtn;

    ComboBox1: TComboBox;

    ComboBox2: TComboBox;

    Label11: TLabel;

    Label12: TLabel;

    BitBtn6: TBitBtn;

    Label13: TLabel;

    Timer2: TTimer;

    ListBox3: TListBox;

    OpenDialog1: TOpenDialog;

    SaveDialog1: TSaveDialog;

    Bevel6: TBevel;

    Bevel7: TBevel;

    Label6: TLabel;

    ComboBox3: TComboBox;

    Edit1: TEdit;

    RadioGroup1: TRadioGroup;

    Panel1: TPanel;

    SpeedButton9: TSpeedButton;

    SpeedButton10: TSpeedButton;

    Label14: TLabel;

    Label15: TLabel;

    SpeedButton11: TSpeedButton;

    procedure FormActivate(Sender: TObject);

    procedure Timer1Timer(Sender: TObject);

    procedure N6Click(Sender: TObject);

    procedure N2Click(Sender: TObject);

    procedure SpeedButton3Click(Sender: TObject);

    procedure SpeedButton1Click(Sender: TObject);

    procedure SpeedButton8Click(Sender: TObject);

    procedure SpeedButton2Click(Sender: TObject);

    procedure N7Click(Sender: TObject);

    procedure BitBtn1Click(Sender: TObject);

    procedure BitBtn3Click(Sender: TObject);

    procedure BitBtn5Click(Sender: TObject);

    procedure BitBtn6Click(Sender: TObject);

    procedure Timer2Timer(Sender: TObject);

    procedure LoadBase;

    procedure SaveBase;

    procedure SpeedButton6Click(Sender: TObject);

    procedure SpeedButton7Click(Sender: TObject);

    procedure ListBox1Click(Sender: TObject);

    procedure SpeedButton4Click(Sender: TObject);

    procedure SpeedButton10Click(Sender: TObject);

    procedure RadioGroup1Click(Sender: TObject);

    procedure AddSimpleFact;

    procedure SpeedButton9Click(Sender: TObject);

    procedure SpeedButton11Click(Sender: TObject);

    procedure AddComplexFact;

    procedure DeleteFact;

    procedure SpeedButton5Click(Sender: TObject);

    procedure BitBtn2Click(Sender: TObject);

    procedure BitBtn4Click(Sender: TObject);

    procedure N5Click(Sender: TObject);

    procedure N4Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

   TFactFile = record      {факт}

         Number:integer; {номер факта}

         Znach:string[40]; {значение факта}

         Q:integer;      {количество порождаемых фактов}

         FactIn:array[1..10] of integer; {массив порождаемых фактов}

         Zel:byte;{Целевой или нецелевой факт}

         end;

  TKnow = Record     {порождаемый факт}

         Number:integer;   {номер порождаемого факта}

         Q:integer; {количество порождаемых фактов}

         FactIn:array[1..10] of integer; {массив порождаемых фактов}

         Zel:byte;

         end;

  TFact= record      {факт}

         Number:integer; {номер факта}

         Znach:string[40]; {значение факта}

         end;

  TBase=Record

      Fact:array[1..40] of integer;

      Rule:array [1..40] of TKnow;

      end;

  TFF=file of TFactFile;

var

  Form1: TForm1;

  FF:TFF;

  TermFact:array[1..50] of integer; {массив c тем что хотим иметь на выходе}

  NE,NK,NF,NF1,NFF,NR,KEND,Rez,NST,Num:integer;

  Spis:array[1..30] of integer; {необходимые факты для цели}

  SpisF:array[1..30] of integer; {выбранные факты}

  BaseKnow:TBase;

  Knowledge:array[1..5] of integer; {массив с выбранными правилами}

  VectFact:array[1..50] of TFact; {база фактов}

implementation

uses About, Help;

{$R *.DFM}

procedure TForm1.FormActivate(Sender: TObject);

var

   Know:TKnow;

   Fact:TFact;  FactFile:TFactFile;

   i,j:integer;

begin

     NF:=0;NF1:=0;NK:=0;

     AssignFile(FF,'Base.dat'); {Файл с фактами}

     Reset(FF);

     NFF:=0;

     While Not eof(FF) do

     begin

          Read(FF,FactFile);

          NFF:=NFF+1;

          VectFact[NFF].Number:=FactFile.Number;

          VectFact[NFF].Znach:=FactFile.Znach;

          ListBox1.Items.Add(VectFact[NFF].Znach);

          ListBox3.Items.Add(VectFact[NFF].Znach);

          if FactFile.Q>1 then

          begin

              NR:=NR+1;

              BaseKnow.Rule[NR].Number:=FactFile.Number;

              BaseKnow.Rule[NR].Zel:=FactFile.Zel;

              ListBox5.Items.Add(FactFile.Znach);

              BaseKnow.Rule[NR].Q:=FactFile.Q;

              for i:=1 to BaseKnow.Rule[NR].Q do

               BaseKnow.Rule[NR].FactIn[i]:=FactFile.FactIn[i];

          end;

    end;

    closefile(FF);

   

end;

procedure TForm1.Timer1Timer(Sender: TObject);

begin

label1.top:=label1.top-2;

label2.left:=label2.left+4;

label3.top:=label3.top+2;

if label2.left=100 then

 timer1.Enabled:=false;

end;

procedure TForm1.N6Click(Sender: TObject);

begin

AboutBox.Show;

end;

procedure TForm1.N2Click(Sender: TObject);

begin

N1.Visible:=false;

N2.Visible:=false;

N3.Visible:=false;

N4.Visible:=false;

{N5.Visible:=false;

N6.Visible:=false;}

label1.Visible:=false;

label2.Visible:=false;

label3.Visible:=false;

form1.Height:=150;

form1.Width:=185;

form1.BorderStyle:=bsDialog;

form1.Position:=poScreenCenter;

speedbutton1.Visible:=true;

speedbutton2.Visible:=true;

speedbutton3.Visible:=true;

end;

procedure TForm1.SpeedButton3Click(Sender: TObject);

begin

close;

end;

procedure TForm1.SpeedButton1Click(Sender: TObject);

begin

form1.Height:=343;

form1.Width:=450;

form1.BorderStyle:=bsSingle;

form1.Position:=poScreenCenter;

speedbutton1.Visible:=false;

speedbutton2.Visible:=false;

speedbutton3.Visible:=false;

speedbutton4.Visible:=true;

speedbutton5.Visible:=true;

speedbutton6.Visible:=true;

speedbutton7.Visible:=true;

speedbutton8.Visible:=true;

listbox1.Visible:=true;

listbox2.Visible:=true;

bevel1.Visible:=true;

bevel2.Visible:=true;

bevel3.Visible:=true;

bevel3.Width:=430;

label4.Visible:=true;

label5.Visible:=true;

label6.Visible:=true;

end;

procedure TForm1.SpeedButton8Click(Sender: TObject);

begin

form1.Height:=150;

form1.Width:=185;

form1.BorderStyle:=bsDialog;

form1.Position:=poScreenCenter;

speedbutton1.Visible:=true;

speedbutton2.Visible:=true;

speedbutton3.Visible:=true;

speedbutton5.Visible:=false;

speedbutton6.Visible:=false;

speedbutton7.Visible:=false;

speedbutton8.Visible:=false;

listbox1.Visible:=false;

listbox2.Visible:=false;

bevel1.Visible:=false;

bevel2.Visible:=false;

bevel3.Visible:=false;

bevel3.Width:=481;

label4.Visible:=false;

label5.Visible:=false;

label6.Visible:=false;

panel1.Visible:=false;

edit1.Visible:=false;

combobox3.Visible:=false;

radiogroup1.Visible:=false;

speedbutton11.visible:=false;

end;

procedure TForm1.SpeedButton2Click(Sender: TObject);

begin

form1.Height:=343;

form1.Width:=503;

form1.BorderStyle:=bsSingle;

form1.Position:=poScreenCenter;

speedbutton1.Visible:=false;

speedbutton2.Visible:=false;

speedbutton3.Visible:=false;

BitBtn5.Visible:=true;

BitBtn6.Visible:=true;

bevel3.Visible:=true;

bevel4.Visible:=true;

bevel5.Visible:=true;

bevel6.Visible:=true;

bevel7.Visible:=true;

ListBox3.Visible:=true;

ListBox4.Visible:=true;

ListBox5.Visible:=true;

ListBox6.Visible:=true;

label7.Visible:=true;

label8.Visible:=true;

label9.Visible:=true;

label10.Visible:=true;

label11.Visible:=true;

label12.Visible:=true;

ComboBox1.Visible:=true;

ComboBox2.Visible:=true;

BitBtn1.Visible:=true;

BitBtn2.Visible:=true;

BitBtn3.Visible:=true;

BitBtn4.Visible:=true;

N7.Visible:=true;

end;

procedure TForm1.N7Click(Sender: TObject);

begin

form1.Height:=150;

form1.Width:=185;

form1.BorderStyle:=bsDialog;

form1.Position:=poScreenCenter;

speedbutton1.Visible:=true;

speedbutton2.Visible:=true;

speedbutton3.Visible:=true;

BitBtn5.Visible:=false;

BitBtn6.Visible:=false;

bevel3.Visible:=false;

bevel4.Visible:=false;

bevel5.Visible:=false;

bevel6.Visible:=false;

bevel7.Visible:=false;

ListBox3.Visible:=false;

ListBox4.Visible:=false;

ListBox5.Visible:=false;

ListBox6.Visible:=false;

label7.Visible:=false;

label8.Visible:=false;

label9.Visible:=false;

label10.Visible:=false;

BitBtn1.Visible:=false;

BitBtn2.Visible:=false;

BitBtn3.Visible:=false;

BitBtn4.Visible:=false;

N7.Visible:=false;

label11.Visible:=false;

label12.Visible:=false;

ComboBox1.Visible:=false;

ComboBox2.Visible:=false;

BitBtn6Click(Sender);

end;

procedure TForm1.BitBtn1Click(Sender: TObject);

var

  rab:integer;

begin

  rab:=ListBox3.itemindex;

  listbox4.Items.Add(VectFact[rab+1].Znach);

  NF1:=NF1+1;

  SpisF[NF1]:=VectFact[rab+1].Number;

  BaseKnow.Fact[NF1]:=VectFact[rab+1].Number;

  NF:=NF1;

end;

procedure TForm1.BitBtn3Click(Sender: TObject);

var rab,i,j:integer;

begin

  rab:=ListBox5.itemindex;

  for i:=1 to NFF do

    if BaseKnow.Rule[rab+1].Number=VectFact[i].Number then

    begin

      listbox6.Items.Add(VectFact[i].Znach);

      NK:=NK+1;

      Knowledge[NK]:=VectFact[i].Number;

    end;

end;

Procedure Direct;

var

    KIZ,NS,KA,k,i,l,j:integer;

begin

    {Теперь алгоритм прямого хода}

    KEnd:=0;KIZ:=0;NS:=0;

     While ((KEnd=0) and (KIZ=0)) do

     begin

        {организация обработки БЗ до тех пор, пока не получим}

        {требуемое целевое значение или не станет ясна }

        {невозможность его получения}

         KIZ:=1;

         i:=1;

         While (i<=NR) and (Kend=0) do

         begin

             {Просмотр всех правил до порождения}

             {целевого факта}

             KA:=0; {Проверка: нужно ли порождать факт?}

             k:=1;

             While ((KA=0) and (K<=NF)) do

             begin

                 if BaseKnow.Rule[i].Number=BaseKnow.Fact[k] then

                   KA:=1; {Факт входит в множество имеющихся}

                 k:=k+1;

             end;

             {Проверка: можно ли породить факт?}

             j:=1;

             While ((j<=BaseKnow.Rule[i].Q) and (KA=0)) do

             begin

                  {Анализ порождающих фактов}

                  KA:=1; k:=1;

                  While (k<=NF) and (KA=1) do

                  begin

                       {Проверка наличия порождающего факта}

                       {есть ли факт в БЗ}

                       if BaseKnow.Rule[i].FactIn[j]=BaseKnow.Fact[k] then

                          KA:=0;

                       k:=k+1;

                  end;

                  {если при выходе КА=1, то нет факта,}

                  {необходимого для порождения}

                  j:=j+1;

             end;

             if KA=0 then

             begin

                  {Все факты, необходимые для порождения}

                  {нового факта, есть в наличие}

                  NF:=NF+1;

                  BaseKnow.Fact[NF]:=BaseKnow.Rule[i].Number;

                  KIZ:=0;

                       {Проверка: является ля порожденный факт}

                       {целевым}

                       if BaseKnow.Rule[i].Zel=1 then

                         begin

                             KEND:=1;

                             Rez:=BaseKnow.Rule[i].Number;

                         end;

             end;

             i:=i+1;

         end;

         {Конец очередного просмотра всех правил}

         {Конец обработки БЗ}

     end;

end;

Procedure Inv;

var

    KVPC,KVPF,AnFact,NS1,Rab,FindFactAn:integer;

    L,NS,i,j,k,KA:integer;

begin

       {Алгоритм обратного хода}

     KEnd:=0; L:=1;   NST:=0;

     While (L<=NK) do

     begin

          {Организация просмотра всех целевых}

          {фактов, пока не подтвердится возможность}

          {порождения каког-л. из них}

          KEND:=0;

          Nst:=Nst+1;

          Spis[Nst]:=Knowledge[l];

          While (Kend=0)do

          begin

               FindFactAn:=0;

               j:=0;

               While (FindFactAn=0)and( j<=NST) do  {выбор факта для анализа}

               begin

                 for  k:=1 to NR do

                    if BaseKnow.Rule[k].Number=Spis[j]

                      then

                       begin

                         FindFactAn:=1;         {Ищем, есть ли правило}

                         AnFact:=Spis[j];       {которое можно породить}

                         for i:=j to Nst-1 do

                           Spis[i]:=Spis[i+1];

                         Nst:=Nst-1;

                       end;

                 j:=j+1;

               end;

               if FindFactAn=0 then

                 KEnd:=1        {Факта для анализа нет, конец анализа}

               else

               begin

                  i:=1;

                  While (I<=NR) do

                  begin

                      {анализ возм-ти  порождения}

                      {выбранного факта}

                      if AnFact=BaseKnow.Rule[i].Number then

                      begin

                         {требуемый факт является порожденным}

                          for j:=1 to BaseKnow.Rule[i].Q do

                          begin

                              NST:=NST+1;

                              Spis[Nst]:=BaseKnow.Rule[i].FactIn[j];

                          end;

                      end;{конец анализа порождаемого факта}

                      i:=i+1;

                  end;{While }

               end;

          end;

         l:=l+1;

     end;{Окончание обработки всех целевых фактов}

     if NST=NK then KEND:=0 else KEND:=1;

     {Ни один из целевых фактов не может быть порожден}

end;

procedure TForm1.BitBtn5Click(Sender: TObject);  {нажали кнопку ОК}

var

   i,j,k,KA,l:integer;

begin

    BitBtn5.enabled:=false;

    if (NF1<>0) and (NK=0) then    {факты введены, цель не введена}

      begin

         Direct;

         if Kend<>0 then

           begin

             for i:=1 to NFF do

               if VectFact[i].Number=Rez then

                 ListBox6.Items.Add(VectFact[i].Znach);

             Label10.Caption:='Вы приготовите:';

             Label10.Font.Color:=clnavy;

           end

           else

           Application.MessageBox('Из выбранных компонентов ничего нельзя приготовить!','Ошибка!',mb_iconwarning);

      end;

    if (NF1=0) and (NK<>0) then {факты не введены, цель введена}

    begin

        Inv;

        if KEnd<>0 then

          begin

            for i:=1 to NST do

              for j:=1 to NFF do

                if Spis[i]=VectFact[j].Number then

                   ListBox4.Items.Add(VectFact[j].Znach);

             Label8.Caption:='Вам необходимо:';

             Label8.Font.Color:=clnavy;

          end;

    end;

    if (NK<>0) and (NF1<>0) then {анализ на совпадение фактов с целью}

    begin

      k:=1;

        While (k<=NR) do

          begin             {Если есть порождаемые факты}

               i:=1;     {то раскладываем их на простые составляющие}

               KA:=0;

               While (i<=NF1)and (KA=0) do

               begin

                   if BaseKnow.Rule[k].Number=SpisF[i] then

                      begin

                          for j:=i to NF1-1 do

                            SpisF[j]:=SpisF[j+1];

                          NF1:=NF1-1;

                          KA:=1;

                      end;

                   i:=i+1;

               end;

               if KA=1 then

               begin

                   for i:=1 to BaseKnow.Rule[k].Q do

                    begin

                         NF1:=NF1+1;

                         SpisF[NF1]:=BaseKnow.Rule[k].FactIn[i];

                    end;

                    k:=0;

                end;

                k:=k+1;

          end;

          INV;

          i:=1;

          While i<=NF1 do   {Проверка, что лишнее}

          begin             {или чего не хватает}

               KA:=0;

               j:=1;

               While (j<=NST) and (KA=0) do

               begin

                    if SpisF[i]=Spis[j] then

                       Ka:=1;

                    j:=j+1;

               end;

               if KA=1 then

               begin

                    for k:=i to NF1-1 do

                      SpisF[k]:=SpisF[k+1];

                    i:=i-1;

                    NF1:=NF1-1;

                    for l:=j-1 to NST-1 do

                      Spis[l]:=Spis[l+1];

                    NST:=Nst-1;

               end;

               i:=i+1;

          end;

        if (Nst=0)and (NF1=0) then

           Timer2.Enabled:=true else

           begin

                KA:=0;

                for i:=1 to NST do

                  for j:=1 to NFF do

                  begin

                    if (Spis[i]=VectFact[j].Number) and (KA=0)  then

                      begin

                        combobox2.Text:=VectFact[j].Znach;

                        KA:=1;

                      end;

                    if (Spis[i]=VectFact[j].Number) and (KA=1)  then

                       combobox2.Items.Add(VectFact[j].Znach);

                  end;

                KA:=0;

                for i:=1 to NF1 do

                  for j:=1 to NFF do

                  begin

                    if (SpisF[i]=VectFact[j].Number) and (KA=0) then

                      begin

                         combobox1.Text:=VectFact[j].Znach;

                         KA:=1;

                      end;

                    if (SpisF[i]=VectFact[j].Number) and (KA=1) then

                      combobox1.Items.Add(VectFact[j].Znach);

                  end;

           end;

    end;

    if (Nk=0) and (NF1=0) then

     begin

       Application.MessageBox('Исходные данные не введены!','Ошибка',mb_iconwarning);

       BitBtn5.Enabled:=true;

     end;

end;

procedure TForm1.BitBtn6Click(Sender: TObject);

begin

  listbox4.Items.Clear;

  listbox6.Items.Clear;

  label10.Caption:='Выбранные цели';

  label8.Caption:='Выбранные факты';

  Label10.Font.Color:=cllime;

  Label8.Font.Color:=cllime;

  NK:=0;

  NF1:=0;

  label13.Visible:=false;

  label13.Top:=104;

  ComboBox1.Clear;

  ComboBox2.Clear;

  BitBtn5.enabled:=true;

end;

procedure TForm1.Timer2Timer(Sender: TObject);

begin

label13.Visible:=true;

label13.top:=label13.top+2;

if label13.top=150 then

 timer2.Enabled:=false;

end;

procedure TForm1.LoadBase;

var

  i:integer;

  FF: TFF;

  FactFile:TFactFile;

begin

i:=0;

OpenDialog1.Filter:='База знаний|*.dat';

if not OpenDialog1.Execute  then

  exit;

if FileExists(OpenDialog1.FileName)=false then

  begin

    Application.MessageBox('Файл с таким именем не найден!','Error',MB_iconwarning);

    exit;

  end

else

  begin

   AssignFile(FF,OpenDialog1.FileName);

   reset(FF);

   NR:=0;

   NFF:=0;

     While Not eof(FF) do

     begin

          Read(FF,FactFile);

          NFF:=NFF+1;

          VectFact[NFF].Number:=FactFile.Number;

          VectFact[NFF].Znach:=FactFile.Znach;

          ListBox3.Items.Add(VectFact[NFF].Znach);

          ListBox1.Items.Add(VectFact[NFF].Znach);

          if FactFile.Q>1 then

          begin

              NR:=NR+1;

              BaseKnow.Rule[NR].Number:=FactFile.Number;

              BaseKnow.Rule[NR].Zel:=FactFile.Zel;

              ListBox5.Items.Add(FactFile.Znach);

              BaseKnow.Rule[NR].Q:=FactFile.Q;

              for i:=1 to BaseKnow.Rule[NR].Q do

               BaseKnow.Rule[NR].FactIn[i]:=FactFile.FactIn[i];

          end;

    end;

end;

closefile(FF);

end;

procedure TForm1.SpeedButton6Click(Sender: TObject);

var

  inf:integer;

begin

  inf:=Application.Messagebox('Загрузить новую БЗ?','Question',MB_YESNO+MB_ICONQUESTION);

  if inf=idNO then

   exit;

  if inf=idYes then

   begin

     ListBox1.Clear;

     ListBox2.Clear;

     ListBox3.Clear;

     ListBox4.Clear;

     ListBox5.Clear;

     ListBox6.Clear;

     LoadBase;

   end;

end;

procedure TForm1.SaveBase;

var i,k,j:integer;

   FF: TFF;

   FactFile:TFactFile;

begin

      SaveDialog1.Filter:='База знаний|*.dat';

if SaveDialog1.Execute then

  begin

   assignfile(FF,SaveDialog1.filename);

   rewrite(FF);

   for i:=1 to NFF do

     Begin

       FactFile.Number:=VectFact[i].Number;

       FactFile.Znach:=VectFact[i].Znach;

       FactFile.Q:=0;

        FactFile.Zel:=0;

       for j:=1 to NR do

         if VectFact[i].Number=BaseKnow.Rule[j].Number then

           begin

                FactFile.Q:= BaseKnow.Rule[j].Q;

                FactFile.Zel:= BaseKnow.Rule[j].Zel;

                for k:=1 to  BaseKnow.Rule[j].Q do

                   FactFile.FactIn[k]:=BaseKnow.Rule[j].FactIn[k];

           end;

       write(ff,FactFile);

     end;

  end

else exit;

closefile(FF);

end;

procedure TForm1.SpeedButton7Click(Sender: TObject);

begin

SaveBase;

end;

procedure TForm1.ListBox1Click(Sender: TObject);

var

  i,j,rab,r,t:integer;

begin

label6.Visible:=true;

t:=0;

ListBox2.Clear;

rab:=ListBox1.Itemindex;

for i:=1 to NR do

  if VectFact[rab+1].Number=BaseKnow.Rule[i].Number then

    begin

      t:=1;

      for j:=1 to BaseKnow.Rule[i].Q do

        for r:=1 to NFF do

          if VectFact[r].Number=BaseKnow.Rule[i].FactIn[j]then

            ListBox2.Items.Add(VectFact[r].Znach);

    end;

if t=1 then

  label6.Caption:='Порождаемый факт';

if t=0 then

  label6.Caption:='Простой факт';

 {}

end;

procedure TForm1.SpeedButton4Click(Sender: TObject);

begin

speedbutton6.Enabled:=false;

speedbutton7.Enabled:=false;

speedbutton8.Enabled:=false;

panel1.Visible:=true;

edit1.Visible:=true;

combobox3.Visible:=true;

radiogroup1.Visible:=true;

radiogroup1.ItemIndex:=0;

Num:=0;

edit1.SetFocus;

edit1.Clear;

end;

procedure TForm1.SpeedButton10Click(Sender: TObject);

begin

panel1.Visible:=false;

edit1.Visible:=false;

combobox3.Visible:=false;

radiogroup1.Visible:=false;

speedbutton11.visible:=false;

speedbutton6.Enabled:=true;

speedbutton7.Enabled:=true;

speedbutton8.Enabled:=true;

end;

procedure TForm1.RadioGroup1Click(Sender: TObject);

begin

if radiogroup1.ItemIndex=0 then

 begin

  combobox3.Enabled:=false;

  label14.Enabled:=false;

  speedbutton11.visible:=false;

  edit1.SetFocus;

 end;

if radiogroup1.ItemIndex=1 then

 begin

  combobox3.Enabled:=true;

  label14.Enabled:=true;

  speedbutton11.visible:=true;

  edit1.SetFocus;

 end;

end;

procedure TForm1.AddSimpleFact;

var

  i,t:integer;

  r:string;

begin

r:=edit1.text;

for i:=1 to NFF do

  if r=VectFact[i].Znach then

    begin

      Application.MessageBox('Такой факт уже существует!','Ошибка',mb_iconwarning);

      exit;

    end;

t:=VectFact[NFF].Number;

NFF:=NFF+1;

VectFact[NFF].Number:=t+1;

VectFact[NFF].Znach:=r;

ListBox1.items.add(VectFact[NFF].Znach);

ListBox3.items.add(VectFact[NFF].Znach);

end;

procedure TForm1.AddComplexFact;

var

  i,t:integer;

  r:string;

begin

r:=edit1.text;

for i:=1 to NFF do

  if r=VectFact[i].Znach then

    begin

      Application.MessageBox('Такой факт уже существует!','Ошибка',mb_iconwarning);

      exit;

    end;

t:=VectFact[NFF].Number;

NFF:=NFF+1;

VectFact[NFF].Number:=t+1;

VectFact[NFF].Znach:=r;

ListBox1.items.add(VectFact[NFF].Znach);

ListBox3.items.add(VectFact[NFF].Znach);

ListBox5.items.add(VectFact[NFF].Znach);

NR:=NR+1;

BaseKnow.Rule[NR].Number:=VectFact[NFF].Number;

BaseKnow.Rule[NR].Q:=Num;

BaseKnow.Rule[NR].Zel:=1;

for i:=1 to Num do

  BaseKnow.Rule[NR].FactIn[i]:=SpisF[i];

end;

procedure TForm1.SpeedButton9Click(Sender: TObject);

begin

if radiogroup1.ItemIndex=0 then

  if edit1.Text='' then

    begin

      Application.MessageBox('Не введены данные!','Ошибка',mb_iconwarning);

      exit;

    end

  else

    AddSimpleFact;

if radiogroup1.ItemIndex=1 then

  if (edit1.Text='') or (ComboBox3.Text='')or (Num=0)then

    begin

      Application.MessageBox('Введены не все данные!','Ошибка',mb_iconwarning);

      exit;

    end

  else

   begin

    AddComplexFact;

    combobox3.Clear;

   end;

edit1.Clear;

Num:=0;

end;

procedure TForm1.SpeedButton11Click(Sender: TObject);

var rab:integer;

begin

  rab:=ListBox1.itemindex;

  ComboBox3.Items.Add(VectFact[rab+1].Znach);

  ComboBox3.ItemIndex:=0;

  Num:=Num+1;

  SpisF[Num]:=VectFact[rab+1].Number;

end;

procedure TForm1.DeleteFact;

var

  i,j,rab,t,k:integer;

begin

  rab:=ListBox1.ItemIndex+1;

  k:=VectFact[rab].Number;

  for i:=1 to NR do

    for j:=1 to BaseKnow.Rule[i].Q do

      if BaseKnow.Rule[i].FactIn[j]=k then

      begin

        Application.MessageBox('Для сохранения целостности базы удалите вначале факт, содержащий в себе данный!','Предупреждение',mb_iconwarning);

        exit;

      end;

  for i:=rab to NFF-1 do

    begin

      VectFact[i].Number:=VectFact[i+1].Number;

      VectFact[i].Znach:=VectFact[i+1].Znach;

    end;

  NFF:=NFF-1;

  for i:=1 to NR do

    if k=BaseKnow.Rule[i].Number then

      begin

        for t:=i to NR-1 do

          begin

             BaseKnow.Rule[t].Number:=BaseKnow.Rule[t+1].Number;

             BaseKnow.Rule[t].Q:=BaseKnow.Rule[t+1].Q;

             BaseKnow.Rule[t].Zel:=BaseKnow.Rule[t+1].Zel;

             for j:=1 to BaseKnow.Rule[t].Q do

               BaseKnow.Rule[t].FactIn[j]:=BaseKnow.Rule[t+1].FactIn[j];

          end;

      NR:=NR-1;

      end;

ListBox1.Clear;

ListBox2.Clear;

ListBox3.Clear;

ListBox5.Clear;

for i:=1 to NFF do

  begin

    ListBox1.Items.Add(VectFact[i].Znach);

    ListBox3.Items.Add(VectFact[i].Znach);

    for j:=1 to NR do

      if VectFact[i].Number=BaseKnow.Rule[j].Number then

        ListBox5.Items.Add(VectFact[i].Znach);

  end;

end;

procedure TForm1.SpeedButton5Click(Sender: TObject);

var

  inf:integer;

begin

  inf:=Application.Messagebox('Удалить факт?','Question',MB_YESNO+MB_ICONQUESTION);

  if inf=idNO then

   exit;

  if inf=idYes then

    DeleteFact;

end;

procedure TForm1.BitBtn2Click(Sender: TObject);

var

   rab,i,j:integer;

begin

  if NF1>0 then

  begin

    rab:=ListBox4.Itemindex;

    for i:=rab+1 to NF1-1 do

      begin

         SpisF[i]:=SpisF[i+1];

         BaseKnow.Fact[i]:=BaseKnow.Fact[i+1];

      end;

    NF1:=NF1-1; NF:=NF1;

    ListBox4.Clear;

    for i:=1 to NF1 do

      for j:=1 to NFF do

        if SpisF[i]=VectFact[j].Number then

          ListBox4.Items.Add(VectFact[j].Znach);

   end;

end;

procedure TForm1.BitBtn4Click(Sender: TObject);

var

   rab,i,j:integer;

begin

   if NK>0 then

   begin

        rab:=ListBox6.Itemindex;

        for i:=rab+1 to NK-1 do

          Knowledge[i]:=Knowledge[i+1];

        NK:=NK-1;

         ListBox6.Clear;

        for i:=1 to NK do

          for j:=1 to NFF do

            if Knowledge[i]=VectFact[j].Number then

                ListBox6.Items.Add(VectFact[j].Znach);

   end;

end;

procedure TForm1.N5Click(Sender: TObject);

begin

HelpBox.show;

end;

procedure TForm1.N4Click(Sender: TObject);

begin

close;

end;

end.

5.2.Распечатка экранных форм

       

Заставка



     Был выбран пункт меню Работа с системой



     

       Окно пункта меню Правка

  



     Пользователь пожелал добавить факт, отобразилось окошко



        В окне Правка можно просмотреть все факты, при этом узнать их статус и состав  

PAGE  13

PAGE  1