Скачиваний:
30
Добавлен:
01.05.2014
Размер:
17 Кб
Скачать
unit logic;

interface
uses Attribute,Instances,RuleItem,Modul,Classes,DmmConstants,Forms;

      {Процедура обратного вывода}
       procedure Execute(rule1:TList;inst1:TDMInstances;OC:integer);
      {Процедура ответа на вопрос при первичном вводе значений атрибутов}
       procedure OtvetPoch_1v(i: integer);

      {Процедуры из обратного вывода}
       procedure in_steck(var steck : TList; atrindex : integer;atrval:double);  {закпись в стек}
       procedure out_steck(var steck : TList);  {выталкивание из стека}
       function  poisk_pravila(rule: TList; AtrInd:integer;var active_rule: array of boolean;var nom:integer):boolean; {поиск правила}
       function  znachen_pravila(rule:TList;nom:integer;inst_size:integer; steck:Tlist;var index:integer):integer; {значение правила}
       procedure rule_true(var steck_f,steck_c:TList;nom:integer;Rule:TList;var flag:boolean); {правило истинно}
       procedure zapomn_cel(var steck : TList;index:integer); {запомнить цель}
       procedure print_cel(steck_f:TList;inst:TDMInstances);   {печать значения цели}
       procedure Icannot;
       procedure TakeVal(index:integer;val:double{;var steck_f:TList}); {Взять значение}
       procedure Otv_Poch(nom:integer;rule:TList;inst:TDMInstances;sys:integer); {Ответить ПОЧЕМУ}
       procedure Otv_Kak(ind:integer;list_rules:TList;rule:TList;inst:TDMInstances);     {Ответить КАК}
       procedure initlogic(rule1:TList;inst1:TDMInstances;OC : integer);
       procedure Execute_all(rule1:TList;inst1:TDMInstances;OC : integer);
       procedure Free();
implementation

uses SysUtils,ItemSet;
       var  g_ind:integer;     {Значения запрошенного атрибута}
            g_value:double;
            active_rules: array of boolean;   {Массив активных правил}
            steck_f,steck_c,list_rules:TList;

{закпись в сtек}
       procedure in_steck(var steck : TList; atrindex : integer;atrval:double);
       var atr1:^TElemSteck;
           atr:TElemSteck;
       begin
       {тело процедуры}
           {Запись в стек на место следующее за последним элементом}
           new(atr1);
           atr:=TElemSteck.Create(atrindex,atrval);

           atr1^:=atr;

           steck.Insert(steck.Count,atr1);

       end;

{выталкивание из стека}
       procedure out_steck(var steck : TList);
       begin
       {тело процедуры}

       {удаляем из конца списка}
       steck.Delete(steck.Count-1);
       end;

{поиск правила}         {наличие соотв индекса в правилах и не закрытого}
       function poisk_pravila(rule: TList; AtrInd:integer;var active_rule: array of boolean;var nom:integer):boolean;
       var
            i:integer;
            rul:TDMRuleItem;     {!!!!!!!!!!!!!!}
       begin
       {тело процедуры}
            {Проверяем, содержит ли правая часть данный набор}
            {Поиск сводится к поиску индекса соотв атрибута среди ItemSetов}
            //new(rul);

            for i:=0 to rule.Count-1 do
            begin
              rul:=rule.Items[i];

              if  (rul.m_premise.m_condidtions[AtrInd]>IMIN_VALUE) then {active_rule[i]:=false}
              else
              if (rul.m_consequence.m_condidtions[AtrInd]>IMIN_VALUE) and (active_rule[i]=true) then
                  begin poisk_pravila:=true; nom:=i; exit; end;

             end;
             poisk_pravila:=false;
       end;
       
{значение правила}
       function znachen_pravila(rule:TList;nom:integer;inst_size:integer; steck:Tlist;var index:integer):integer;
       var i,j,cnt:integer;
           res:integer;
          rul:TDMRuleItem;
          fakt:^TElemSteck;
          s:string;
       begin
       {тело процедуры}
       index:=-1;
       //new(rul);
       new(fakt);
       {Если все значения из правой части правила содержаться в стеке фактов,то
       правило истинно}
       rul:= rule.Items[nom];

       for i:=0 to inst_size-1 do
        if (rul.m_premise.m_condidtions[i]>IMIN_VALUE) then begin
           cnt:=0;
           for j:=0 to steck.Count-1 do begin
              fakt:= steck.Items[j];
              if (i=fakt.index) then
                begin
                cnt:=1;
                if ((rul.m_premise.m_items[i]=fakt.val)and(rul.m_premise.m_condidtions[i]=0))or
                   ((rul.m_premise.m_items[i]<=fakt.val)and(rul.m_premise.m_condidtions[i]=1))or
                   ((rul.m_premise.m_items[i]>=fakt.val)and(rul.m_premise.m_condidtions[i]=-1))
                    then res:=0
                    else begin result:=1; exit; end;
                end;

           end;
           if cnt=0 then begin result:=2;index:=i;exit; end;
       end;
       result:=res;
       end;

{правило истинно}
       procedure rule_true(var steck_f,steck_c:TList;nom:integer;Rule:TList;var flag:boolean);
       var fakt:^TElemSteck;
           rul:TDMRuleItem;
       begin
       new(fakt);
       //new(rul);
       {тело процедуры}
       rul:=Rule.Items[nom];

       fakt:= steck_c.Items[steck_c.Count-1];

       in_steck(steck_f,fakt.index,rul.m_consequence.m_items[fakt.index]); {запись в стек фактов}
       out_steck(steck_c);

       if steck_c.Count=0 then flag:=false else flag:=true;

       end;
       
{запомнить цель}
       procedure zapomn_cel(var steck : TList;index:integer);

       begin
       {тело процедуры}

       in_steck(steck, index,0)

       end;

{печать значения цели}
       procedure print_cel(steck_f:TList;inst:TDMInstances);
       var fakt:^TElemSteck;
           i:integer;
       begin
       {тело процедуры}
        new(fakt);
        ExpertMod.Memo1.Clear;
        ExpertMod.Memo1.Lines.Add('*****************************************');
        ExpertMod.Memo1.Lines.Add('Значение основной выведено успешно.');
        ExpertMod.Memo1.Lines.Add('*****************************************');
        ExpertMod.TakeSys(3);
        fakt:= steck_f.Items[steck_f.Count-1];
        ExpertMod.Memo1.Lines.Add(inst.attribute(fakt.index).name);

        if inst.attribute(fakt.index).attributeType=1 then  ExpertMod.Memo1.Lines.Add('равно '+FloatToStr(fakt.val));
        if inst.attribute(fakt.index).attributeType=2 then ExpertMod.Memo1.Lines.Add('равно '+inst.attribute(fakt.index).value(round(fakt.val)));
    end;

{Процедура начальной инициализации}
       procedure initlogic(rule1:TList;inst1:TDMInstances;OC : integer);
       var i:integer;
       begin
            {Инициализация всех списков}
             steck_f:=TList.Create;
             steck_f.Clear;
             steck_c:=TList.Create;
             steck_c.Clear;
             list_rules:=TList.Create;
             list_rules.Clear;

            {делаем все правила активными}
            SetLength(active_rules, rule1.Count);
            for i:=0 to rule1.Count-1 do
            active_rules[i]:=true;

            {Заполнение стека фактов данными из первичного ввода}

            for i:=0 to inst1.instance(i).numAttributes-1 do
            if inst1.instance(i).value(2)=1 then in_steck(steck_f,i,inst1.instance(i).value(1));

            {Занесение основной цели в стек целей}
            in_steck(steck_c,OC,0);
            
       end;

{Процедура обратного вывода}
       procedure Execute(rule1:TList;inst1:TDMInstances;OC : integer);
       var
            flag,flag1: boolean;             {Флаг готовности}
            i,nom,index:integer;
            val:double;
            fakt:^TElemSteck;

       begin
             if (g_ind<>-1) and (g_value<>-1) then
                  begin in_steck(steck_f,g_ind,g_value);
                        g_ind:=-1;
                        g_value:=-1;
                        out_steck(steck_c);
                        end;

             new(fakt);
            {Готовность = false}
            flag:=true;

            {Пока не будет установлен флаг готовности}
            while flag do
            begin
               flag1:=true;
               fakt:= steck_c.Items[steck_c.Count-1];// as  TElemSteck;

               if  poisk_pravila(rule1,fakt.index, active_rules,nom) then
                begin
                  case znachen_pravila(rule1,nom,inst1.numAttributes,steck_f,index) of
                  0:{истина} begin rule_true(steck_f,steck_c,nom,rule1,flag1); flag:=flag1; in_steck(list_rules,nom,0); end;
                  1:{ложь} active_rules[nom]:=false;
                  2:{не определено} zapomn_cel(steck_c,index);
                  end;
                end
               else {нет правил}
               if fakt.index=OC then  {Была основная цель}
                  begin
                    Icannot;    {Не можем вывести}
                    flag:=false;
                  end
                  else
                    begin
                     ExpertMod.TakeVal(nom,list_rules);  {пересылка значений в modul}
                     ExpertMod.otvet(index);          {Запросит значение}
                     break;
                    end;

             end;
            ExpertMod.TakeVal(nom,list_rules);  {пересылка значений в modul}
            if steck_c.Count=0 then print_cel(steck_f,inst1);
       end;

        procedure Execute_all(rule1:TList;inst1:TDMInstances;OC : integer);
        begin
        TakeVal(-1,-1);
        logic.initlogic(rule1,inst1,OC);
        logic.Execute(rule1,inst1,OC);
        end;

{Выводит ответ на вопрос "Почему?" при первом вводе}
        procedure OtvetPoch_1v(i: integer);
        begin
        if i=2 then begin
        ExpertMod.Memo1.Lines.Add('*****************************************');
        ExpertMod.Memo1.Lines.Add('Данный атрибут запрашивается, чтобы узнать состояние исследуемой');
        ExpertMod.Memo1.Lines.Add('предметной области в данный момент времени.');
        ExpertMod.Memo1.Lines.Add('');
        ExpertMod.Memo1.Lines.Add('Введение всех атрибутов поможет системе быстрее получить результат.');
        ExpertMod.Memo1.Lines.Add('');
        ExpertMod.Memo1.Lines.Add('Вы можете не вводить это значение, тогда оно будет запрошено во время');
        ExpertMod.Memo1.Lines.Add('выполнения логического вывода, и у Вас будет возможность узнать более полную информацию об атрибуте.');
        ExpertMod.Memo1.Lines.Add('*****************************************');
        end
        else begin
        ExpertMod.Memo1.Lines.Add('*****************************************');
        ExpertMod.Memo1.Lines.Add('Значение атрибута вводится во второе поле,');
        ExpertMod.Memo1.Lines.Add('расположенное под полем названия атрибута.');
        ExpertMod.Memo1.Lines.Add('');
        ExpertMod.Memo1.Lines.Add('Если атрибут числовой, то значение должно быть вещественным числом.');
        ExpertMod.Memo1.Lines.Add('');
        ExpertMod.Memo1.Lines.Add('Если атрибут номинальный, достаточно ввести либо номер атрибута из приведенного списка,');
        ExpertMod.Memo1.Lines.Add('либо значение целым словом, либо первой буквой значения.');
        ExpertMod.Memo1.Lines.Add('*****************************************');
        end;
        end;

        {Сообщает, что основная цель недосижима}
        procedure Icannot;
        begin
        ExpertMod.Memo1.Clear;
        ExpertMod.Memo1.Lines.Add('*****************************************');
        ExpertMod.Memo1.Lines.Add('Значение заданной Вами основной цели не может быть ');
        ExpertMod.Memo1.Lines.Add('получено из-за недостаточности информации');
        ExpertMod.Memo1.Lines.Add('в распоряжении системы.');
        ExpertMod.Memo1.Lines.Add('*****************************************');
        end;

        {Вызывается из modul заносит полученные значения в стек фактов}
        procedure TakeVal(index:integer;val:double);
        begin
        g_ind:= index;
        g_value:=val;
        end;

        {отвечает на вопрос "Почему"}
        procedure Otv_Poch(nom:integer;rule:TList;inst:TDMInstances;sys:integer);
        var rul:TDMRuleItem;
            i:integer;
            s:String;
        begin
        //new(rul);
        ExpertMod.Memo1.Lines.Add('');
        if sys = 3 then  begin
        ExpertMod.Memo1.Lines.Add('*****************************************');
        ExpertMod.Memo1.Lines.Add('Чтобы проследить ход рассуждений системы');
        ExpertMod.Memo1.Lines.Add('введите вопрос "КАК?".');
        ExpertMod.Memo1.Lines.Add('Ответ на вопрос "Почему?" после получения результата');
        ExpertMod.Memo1.Lines.Add('система не потдерживает.');
        ExpertMod.Memo1.Lines.Add('*****************************************');
        end
        else begin
        ExpertMod.Memo1.Lines.Add('*****************************************');
        ExpertMod.Memo1.Lines.Add('Значение нужно, чтобы доказать правило: ');
        ExpertMod.Memo1.Lines.Add('');
        rul:=rule.Items[nom];

        ExpertMod.Memo1.Lines.Add('ЕСЛИ');

        for i:=0 to inst.numAttributes-1 do begin
          if (rul.m_premise.m_condidtions[i]>IMIN_VALUE) then
                begin

                if inst.attribute(i).attributeType=1 then s:=FloatToStr(rul.m_premise.m_items[i]);
                if inst.attribute(i).attributeType=2 then s:=inst.attribute(i).value(round(rul.m_premise.m_items[i]));

                if rul.m_premise.m_condidtions[i]=0 then ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' равно '+s);
                if rul.m_premise.m_condidtions[i]=1 then ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' больше '+s);
                if rul.m_premise.m_condidtions[i]=-1 then ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' меньше '+s);

                end;
             end;

        ExpertMod.Memo1.Lines.Add('ТО');
        for i:=0 to inst.numAttributes-1 do begin
          if (rul.m_consequence.m_items[i]>IMIN_VALUE) then
                begin

                if inst.attribute(i).attributeType=1 then s:=FloatToStr(rul.m_consequence.m_items[i]);
                if inst.attribute(i).attributeType=2 then s:=inst.attribute(i).value(round(rul.m_consequence.m_items[i]));

                ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' равно '+s);

                end;
             end;
          end;
        end;

        {Отвечает на вопрос "Как"}
        procedure Otv_Kak(ind:integer;list_rules:TList;rule:TList;inst:TDMInstances);
        var rul:TDMRuleItem;
            elem:^TElemSteck;
            i:integer;
            s:String;
        begin
        //new(rul);
        new(elem);
        ExpertMod.Memo1.Lines.Add('');
        ExpertMod.Memo1.Lines.Add('*****************************************');
        if ind = list_rules.Count then ExpertMod.Memo1.Lines.Add('На этом все. ')
        else begin
        ExpertMod.Memo1.Lines.Add('Последнее доказанное правило: ');
        ExpertMod.Memo1.Lines.Add('');
            //ind - какой раз смотрим
        elem:=list_rules.Items[list_rules.Count-ind-1];

        rul:=rule.Items[elem.index];

        ExpertMod.Memo1.Lines.Add('ЕСЛИ');
        for i:=0 to inst.numAttributes-1 do begin
          if (rul.m_premise.m_condidtions[i]>IMIN_VALUE) then
                begin

                if inst.attribute(i).attributeType=1 then s:=FloatToStr(rul.m_premise.m_items[i]);
                if inst.attribute(i).attributeType=2 then s:=inst.attribute(i).value(round(rul.m_premise.m_items[i]));

                if rul.m_premise.m_condidtions[i]=0 then ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' равно '+s);
                if rul.m_premise.m_condidtions[i]=-1 then ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' меньше '+s);
                if rul.m_premise.m_condidtions[i]=1 then ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' больше '+s);

                end;
             end;

        ExpertMod.Memo1.Lines.Add('ТО');
        for i:=0 to inst.numAttributes-1 do begin
          if (rul.m_consequence.m_condidtions[i]>IMIN_VALUE) then
                begin

                if inst.attribute(i).attributeType=1 then s:=FloatToStr(rul.m_consequence.m_items[i]);
                if inst.attribute(i).attributeType=2 then s:=inst.attribute(i).value(round(rul.m_consequence.m_items[i]));

                ExpertMod.Memo1.Lines.Add(inst.attribute(i).name+' равно '+s);

                end;
             end;
        end;
        end;

   procedure Free();
   begin
   g_ind:=-1;
   g_value:=-1;
   steck_f.Free;
   steck_c.Free;
   list_rules.Free;
   end;

end.
Соседние файлы в папке ExpertModule