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

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

{Процедура логического вывода}
procedure Execute(rule1:TList;inst1:TDMInstances);
{Процедура ответа на вопрос при первичном вводе значений атрибутов}
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 nom:integer;active_rules:array of boolean):boolean; {поиск правила}
function znachen_pravila(rule:TList;nom:integer;inst_size:integer; steck:Tlist):integer; {значение правила}
procedure rule_true(rule:TList;var steck_f:TList;var steck_f_all:TList;var list_rez:TList;nom:integer;inst_size:integer;var active_rules:array of boolean);
procedure print_rez(rez_list:Tlist;inst:TDMInstances);
procedure Otv_Kak(ind:integer;list_true_rul:TList;list_rules:TList;inst:TDMInstances);
procedure Otv_Poch;
procedure del_elofsteck(var steck : TList;index1:integer);
implementation

uses SysUtils;

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

cnt:=0;
for i:=0 to steck.Count-1 do begin
atr2:=steck.Items[i];
if atr2.index=atrindex then cnt:=cnt+1;
end;

if cnt=0 then steck.Insert(steck.Count,atr1);

end;

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

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

{Удаление конкр записи}
procedure del_elofsteck(var steck : TList;index1:integer);
var i:integer;
atr:^TElemSteck;
begin
for i:=0 to steck.Count-1 do begin
atr:=steck.Items[i];
if atr.index=index1 then begin steck.Delete(i);exit end;
end;
end;

{поиск правила}
function poisk_pravila(rule: TList; AtrInd:integer;var nom:integer;active_rules:array of boolean):boolean; {поиск правила}
var rul:TDMRuleItem;
i:integer;
begin
//new(rul);

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

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

{значение правила}
function znachen_pravila(rule:TList;nom:integer;inst_size:integer; steck:Tlist):integer;
var rul:TDMRuleItem;
fakt:^TElemSteck;
i,j,cnt:integer;
res:integer;
begin
//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:=1;exit; end;
end;
result:=res;
end;

{правило истинно}
procedure rule_true(rule:TList;var steck_f:TList;var steck_f_all:TList;var list_rez:TList;nom:integer;inst_size:integer;var active_rules:array of boolean);
var rul:TDMRuleItem;
i:integer;
begin
//new(rul);
rul:=rule.Items[nom];
for i:=0 to inst_size-1 do
if rul.m_consequence.m_condidtions[i]>IMIN_VALUE then
begin
in_steck(steck_f,i,rul.m_consequence.m_items[i]);
in_steck(list_rez,i,rul.m_consequence.m_items[i]);
in_steck(steck_f_all,i,rul.m_consequence.m_items[i]);
active_rules[nom]:=false; //доказано
end;
end;

{Печать результата}
procedure print_rez(rez_list:Tlist;inst:TDMInstances);
var fakt:^TElemSteck;
i:integer;
s:string;
begin
new(fakt);
ExpertMod.Memo1.Clear;
if rez_list.Count=0 then begin
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.TakeSys(3);
for i:=0 to rez_list.Count-1 do
begin
fakt:=rez_list.Items[i];

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

end;

{Роцедура прямого вывода}
procedure Execute(rule1:TList;inst1:TDMInstances);
type active= array of boolean;
var
active_rules: active; {доказано ли правило}
steck_f,steck_f_all,rez_list,list_true_rul:TList;

flag: boolean; {Флаг готовности}
i,nom,index,nom_pred:integer;
fakt:^TElemSteck;
BEGIN
{Инициализация всех списков}
steck_f:=TList.Create;
steck_f.Clear;
rez_list:=TList.Create;
rez_list.Clear;
list_true_rul:=TList.Create;
list_true_rul.Clear;
steck_f_all:=TList.Create;
steck_f_all.Clear;

new(fakt);
{Помечаем все правила как недоказанные}
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));

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


flag:=true;
nom_pred:=0;
while flag do

if steck_f.Count>0 then begin
fakt:=steck_f.Items[steck_f.Count-1];

if poisk_pravila(rule1,fakt.index,nom,active_rules) then
if znachen_pravila(rule1,nom,inst1.numAttributes,steck_f_all)=0 then
begin
rule_true(rule1,steck_f,steck_f_all,rez_list,nom,inst1.numAttributes,active_rules);
in_steck(list_true_rul,nom,0);
nom_pred:=nom;
end;

del_elofsteck(steck_f,fakt.index); //Удаляем текущий элемент из стека фактов
if steck_f.Count=0 then flag:=false;
end
else
if steck_f.Count=0 then flag:=false;


ExpertMod.TakeVal(0,list_true_rul);
print_rez(rez_list,inst1);
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 Otv_Poch;
begin
ExpertMod.Memo1.Lines.Add('');
ExpertMod.Memo1.Lines.Add('*****************************************');
ExpertMod.Memo1.Lines.Add('В данном режиме ответ на этот вопрос не потдерживается');
ExpertMod.Memo1.Lines.Add('*****************************************');

end;


{Отвечает на вопрос "КАК" по результатам вывода}
procedure Otv_Kak(ind:integer;list_true_rul:TList;list_rules: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 list_true_rul.Count>0 then begin
if ind<list_true_rul.count then begin
if ind=0 then ExpertMod.Memo1.Lines.Add('В начале было доказано правило: ')
else ExpertMod.Memo1.Lines.Add('Затем было доказано: ');
ExpertMod.Memo1.Lines.Add('');
//ind - какой раз смотрим
elem:=list_true_rul.Items[ind];
rul:=list_rules.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(rul.m_consequence.m_items[i]);

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

end;
end;
end;
end
else {Если ist_true_rul.Count=0}
begin
ExpertMod.Memo1.Lines.Add('На основе введенных значений не удалось доказать ни');
ExpertMod.Memo1.Lines.Add('одного правила');
end;
end;

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