Главная Учебники - Разные Лекции (разные) - часть 35
|
СОДЕРЖАНИЕ 1 ОБЩИЕ СВЕДЕНИЯ ОБ ИНТЕРВАЛЬНОЙ АРИФМЕТИКЕ. 4
1.1 Интервальная арифметика. Интервальные числа. 4
1.2 Стандартная интервальная арифметика. 5
1.3 Интервальная арифметика с нестандартными вычитанием и делением. 6
1.4 Теоретические аспекты методов распространения ограничений. 7
2 МЕТОДЫ РАСПРОСТРАНЕНИЯ ОГРАНИЧЕНИЙ.. 9
2.2 Реализация на ЭВМ алгоритма Indigo. 12
2.3 Алгоритм Incremental Hierarchical Constraint Solver (IHCS)14
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ.. 18
ПРОЛОЖЕНИЕА. Текст программы на Delphi19
Распространение ограничений (иногда также называемое удовлетворением ограничениям или программированием в ограничениях) является одной из наиболее интенсивно развивающихся областей искусственного интеллекта, связанной с решением разнообразных задач. Представление проблемы в виде задачи распространения ограничений позволяет применять для ее решения наряду со специальными методами прикладной области достаточно эффективные и универсальные методы решения задач распространения ограничений. В настоящее время техника распространения ограничений все чаще используется как основа для решения различных прикладных задач, таких как временные рассуждения, задачи ресурсного и календарного планирования, математическое и инженерное моделирование, задачи на графах и т.д. Поэтому естественным является большое внимание, уделяемое исследованию и методов решения задач удовлетворения ограничений. Как правило, эти задачи представляют собой совокупность уравнений и неравенств, связывающих некоторые непрерывные переменные, хотя иногда ограничения могут задаваться в виде таблиц, а также включать целочисленные переменные. Целью данной курсовой работы является рассмотрение применения методов распространения ограничений при поиске допустимых решений. состоит из двух частей. В первое части рассмотрены теоретические аспекты задачи распространения ограничений, а также общие сведения об интервальной арифметике. Во второй части рассмотрены два алгоритма распространения ограничений Indigoи IHCS(IncrementalHierarchicalConstraintSolver. 1 ОБЩИЕ СВЕДЕНИЯ ОБ ИНТЕРВАЛЬНОЙ АРИФМЕТИКЕ
1.1 Интервальная арифметика. Интервальные числа
Пусть Множество всех интервалов обозначим через Символы Отношение порядка
на множестве Пересечение
Симметричным
является интервал Шириной
Середина
Абсолютная величина
Наконец, Расстояние
Вырожденныйинтервал
, то есть интервал с совпадающими концами 1.2 Стандартная интервальная арифметика
Арифметические операции над интервальными числами определяются следующим образом. Пусть причем в случае деления Легко проверить, что определение (1.4) эквивалентно соотношениям Заметим, что операцию вычитания можно выразить через сложение и умножение, положив В зависимости от знака чисел 1. 2. 3. 4. 5. 6. 7. 8. 9. Отсюда видно, что только в одном (последнем) случае для нахождения произведения требуется четыре умножения, а в остальных достаточно двух умножений. Если Из определения (1.4) непосредственно видно, что интервальные сложение и умножение ассоциативны и коммутативны, иначе говоря, для
Роль нуля и единицы играют обычные 0 и 1, которые, как отмечалось, отождествляются с вырожденными интервалами Равенство (1.4) (как и (1.5) – (1.8)) показывает, что если один из операндов является невырожденным интервалом, то результат арифметической операции также невырожденный интервал. Исключение составляет умножение на 1.3 Интервальная арифметика с нестандартными вычитанием и делением
Нестандартные операции вычитания Обозначим 1. 2. 3. Из равенства 4. Для 5. Для 6. Уравнение 7. 8. 9. 10. Из равенства Определим для элементов 11. Уравнение 12. Уравнение 13. Уравнение 14. 1.4 Теоретические аспекты методов распространения ограничений
Областью определения
переменной Самым точным и надежным с вычислительной точки зрения является представление вещественного числа Пусть мы имеем ограничение Будем говорить, что отношение Численной задачей
удовлетворения ограничений
(ЧЗУО) называется тройка где Будем рассматривать Решением численной ЗУО
2 МЕТОДЫ РАСПРОСТРАНЕНИЯ ОГРАНИЧЕНИЙ
2.1 Алгоритм I
ndigo Входными данными для алгоритма Indigo является множество ограничений, включая равенства и неравенства, и набор переменных. Алгоритм определяет оптимальный интервал для всей системы. Выполнение алгоритма происходит от самого сильного ограничения к самому слабому, в ходе которого мы пытаемся удовлетворить каждое ограничение путем сжимания границ переменных, входящих в него. Сжимание границ одних переменных ограничения может стать причиной сжимания границ других переменных. Для реализации этого алгоритм содержит очередь ограничений, которые необходимо проверить. Изначально очередь содержит только исходные ограничения Псевдокод алгоритм выглядит следующим образом: all constraints := list of all constraints, strongest first; all variables := set of all variables; active_constraints := new set; for v in all variables do initialize v.bounds to unbounded; end for; for current constraint in all constraints do tight_variables := new set; queue := new queue; queue.add(current_constraint); while queue not empty do cn := queue.front; tighten_bounds(cn, queue, tight_variables, active_constraints); check_constraint(cn, active_constraints); queue.dequeue; end while; end for; Переменная active_constraints
содержит множество ограничений, которые уже были рассмотрены, но которые могут быть рассмотрены опять, если мы сожмем границы одной из переменной ограничений. Во время обработки каждого ограничения очередь (queue
) содержит множество ограничений, границы чьих переменных может потребоваться сжать, и tight_variables
– это множество переменных, чьи границы были сжаты во время обработки текущего ограничения. Во время обработки текущего ограничения мы никогда не сжимаем границы одной переменной дважды. Процедура tighten_bounds
сжимает границы переменных ограничения Procedure tighten_bounds(cn, queue, tight variables, active constraints) for v in cn.variables and v not in tight_variables do tighten_flag := cn.tighten_bounds_for(v); tight_variables.add(v); if tighten_flag then for c in v.constraints do if c in active_constraints and c not in queue then queue.add(c); end if; end for; end if; end for; endproceduretighten_bounds; В процедуре tighten
_
bounds
процедура tighten
_
bounds
_
for
сжимает границы переданной переменной, на сколько это возможно, и возвращает истину, если границы изменились. Procedure check_constraint(cn, active constraints) If cn is unary then If cn is required and cn is not satisfiable then exception(required_constraint_not_satisfied); end if; return; end if; if not all of c’s variables have unique values then active_constraints.add(cn); return; end if; if cn is satisfied then active_constraints.delete(cn); else if cn is required then exception(required_constraint_not_satisfied); else exception(constraints_too_difficult); end if; end procedure check_constraint; В процедуре check
_
constraint
мы в первую очередь смотрим, унарное ли ограничение Рассмотрим применение алгоритма Indigo на следующем примере. Пусть нам дана система уравнений В данной системе первых четыре уравнения являются самыми сильными, т.е. они будут удовлетворятся в первую очередь. Пятое уравнение – строгое, шестое – среднее, а последних четыре являются слабыми. Ограничения начинают обрабатываться от самого сильного к слабому. Так после обработки неравенства Теперь переходим к строгому ограничению Затем мы обрабатываем среднее ограничение Наконец мы обрабатываем самое слабое ограничение 2.2 Реализация на ЭВМ алгоритма
Indigo На основе материала данной курсовой работы была разработана программа «Метод Индиго» на языке программирования Delphi, реализующая применение алгоритма Indigo для решения системы ограничений (2.1). После запуска программы перед пользователем появляется диалоговое окно, наглядный вид которого представлен на рис.2.1.
Рисунок 2.1 – Диалоговое окно метода Indigo Основная часть данного окна разделена на две составляющие: – текстовое поле «Условие», предназначенное для ввода исходной системы ограничений; – текстовое поле «Шаги решения», отображающее этапы решения алгоритма. При вводе ограничений в текстовое поле «Условие» пользователю необходимо указать статус каждого уравнения: сильное – r, строгое – s, среднее – m или слабое – w (рис. 2.2)
Рисунок 2.2 – Исходные данные В нижней части диалогового окна расположена кнопка «Решить». При нажатии на данную кнопку в правой части диалогового окна появляются пошаговые изменения переменных системы (рис 2.3), благодаря этому можно проследить на каком этапе и границы какой переменной были сжаты, а также можно увидеть решение системы в диалоговом окне «Решение» (рис. 2.4).
Рисунок 2.3 – Этапы решения
Рисунок 2.4 – Результат реализации алгоритма Текс программной реализации алгоритма находится в приложении А. 2.3 Алгоритм
Incremental Hierarchical Constraint Solver (IHCS) Incremental Hierarchical Constraint Solver (IHCS) –алгоритмпошаговогоиерархическогорешениясистемыограничений. В алгоритме IHCS, как и в Indigo, система ограничений может содержать как равенства, так и неравенства. Алгоритм базируется на идее преобразования начальной конфигурации Псевдокод данного алгоритма выглядит следующим образом: procedure IHCS(H: constraint hierarchy) AS•RS•US <- 0•0•H; while US not empty do apply forward rule to AS•RS•US, i.e., move c from US to AS if conflict in AS then apply backward rule to AS•RS•US; endif endwhile endIHCS Алгоритм начинается с конфигурации Прямой алгоритм – это адаптация алгоритма совместимости по дугам (arc consistency), основанного на распространении ограничений, обобщенного на случай ограничений с произвольным числом переменных. ПрямойходреализуетсяспомощьюфункцииForward
. Function Forward() while US = cj
US’
do US ¬ US’
AS ¬ ASÈ{cj
} AO ¬ AO+1 AOcj
¬ AO Enqueue(cj
,Q) ‘Q initially epty while Dequeue(Q,ck
) do if not Revise(ck
,Tcj
,Q) then if not Backward(ck
) then return false returntrue Счетчик Функция Revise
осуществляет удаление несовместимых ограничений из области переменных Во время работы обратного алгоритма должны выполняться следующие условия: 1. Только ограничения, имеющие отношение к конфликту могут изменить статус (смягчены или деактивированы) для того, чтобы избежать бесполезного поиска. 2. Повторно должна быть достигнута потенциально лучшая конфигурация, чтобы добиться значимого результата. 3. Никакая перспективная конфигурация не должна использоваться повторно, чтобы избежать циклов. 4. Для полноты алгоритма никакая перспективная конфигурация не должна быть пропущена. 5. Должна быть достигнута глобальная совместимость нового хранилища активных ограничений, повторно выполняя при этом как можно меньше работы. Обратное правило является правилом, которое перемещает ограничения в хранилище неисследованных ограничений. Если текущий конфликт возник не первым, то во время решения предыдущего конфликта обратное правило генерирует перспективную конфигурацию с неисследованными ограничениями. Ограничения, смягченные в предыдущих конфликтах, следует пересмотреть на предмет реактивации, если некоторые ограничения, вовлеченные в те конфликты, сейчас смягчены. Это даст шанс, что новое смягчение также разрешит эти ранние конфликты, следовательно, позволяет ранее смягченным ограничениям стать активными. За осуществление обратного правила отвечает функция Backward
. И наконец, алгоритм IHCSостанавливается, как только конфигурация становится Рассмотрим следующий пример:
при этом начальные значения В данной системе ограничений первых два неравенства являются строгими, а вторые два – слабыми. На первом шаге первое сильное ограничение На втором шаге из Учитывая третье ограничение В данной курсовой работе были рассмотрены основные понятия интервальной арифметики и задачи распространения ограничений. Задачи распространения ограничений над непрерывными областями обычно называются численными задачами удовлетворения ограничений. Задачи этого класса могут быть использованы для представления большого количества описывающих физические или химические явления моделей, в частности моделей с неточными данными или частично определенными параметрами. Для решения задач распространения ограничений существует различное множество алгоритмов. В курсовой работе были рассмотрены два из них: алгоритм распространения ограничений Indigo и IHCS (IncrementalHierarchicalConstraintSolver). Алгоритм Indigo заключается в том, что при обработке ограничений от самого сильного к самому слабому мы пытаемся удовлетворить каждое ограничение путем сжимания границ переменных, входящих в него, при этом сжимание границ одних переменных ограничения может стать причиной сжимания границ других переменных. Для выполнения этих действий в алгоритме используется очередь ограничений, которые необходимо проверить. Изначально очередь содержит только исходные ограничения Алгоритм IHCSбазируется на идее преобразования начальной конфигурации Рассматривая эти два алгоритма можно сказать, что Indigo достаточно легок в понимании и прост в реализации, по сравнению с IHCS. В данной курсовой работе был реализован алгоритм Indigo на языке программирования Delphi (см. Приложение А). В дальнейшем планируется реализовать IHCS и сравнить результаты, получаемые с помощью двух алгоритмов. СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1. Семенов, А.Л. Методы распространения ограничений: основные концепции / А.Л. Семенов // Международное совещание по интервальной математике и методам распространения ограничений: труды совещания. – Новосибирск. – 2003. – С. 6–20. 2. Лоенко, М. Решение систем нелинейных уравнений методами интервального распространения ограничений / М. Лоенко // Новосибирский филиал Российского научно-исследовательского института искусственного интеллекта. – Россия. – Том 7. – №2. – 2002.– С.84–93. 3. Borning, A. The Indigo Algorithm / A. Borning, R. Anderson, B. Freeman-Benson // TR 96-05-01, Department of Computer Science and Engineering, University of Washington. – 1996. 4. Menezes, F. Incremental Hierarchical Constraint Solver (IHCS) / F. Menezes, P. Barahoma, P. Codognet // An Incremental Hierarchical Constraint Solver, in: Proceedings of PPCP93, – Newport, 1993. – pp. 190-199. 5. Barták, R. Constraint Guide – Constraint Hierarchy Solvers / R. Barták // Guide to Constraint Programming [Электронныйресурс]. – 1998. – Режимдоступа : http://kti.mff.cuni.cz/~bartak/constraints/ch_solvers.html. – Датадоступа : 25.04.2010.
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, UMathParser, MyFunctions; type TForm1 = class(TForm) Button1: TButton; GroupBox1: TGroupBox; ListBox1: TListBox; GroupBox3: TGroupBox; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; TConstraint = class constructor Create(Constraint : string); destructor Free; function TightenBoundsForEqual(V : string) : boolean; function TightenBoundsForNoEqual(V : string) : boolean; function TightenBoundsForWeakEqual(V : string) : boolean; function TightenBoundsFor(V : string) : boolean; function IsElemInVars(Elem : string) : boolean; public Prior : char; // приоритет ограничения CType : char; // тип ограничения <= = >= 'l' 'e' 'm' Variables : TSArray; // переменные VarCount : integer; // число переменных LPart, RPart : TMathParser; end; TVariable = class VarName : string; LBound, RBound : extended; // границы интервала constructor Create(pName: string; pLBound, pRBound: extended); destructor Free; procedure SetBounds(pLBound,pRBound : extended); end; TConstraintList = record Count : integer; List : array of TConstraint; end; TVariableList = record Count : integer; List : array of TVariable; end; const LInfinity = -1e50; // минус бесконечность RInfinity = 1e50; // плюс бесконечность var Form1: TForm1; implementation uses CQueue, CSet, Math, VSet, Unit2; {$R *.dfm} var ConstraintList : TConstraintList; // список ограничений VariableList : TVariableList; // список переменных constructor TConstraint.Create(Constraint : string); var SLPart, SRPart : string; SVar : string; begin GetLeftAndRightParts(Constraint,SLPart,SRPart,Prior,CType); GetVarList(Constraint,Variables,VarCount,SVar); LPart:=TMathParser.create; RPart:=TMathParser.create; LPart.Translate(SLPart,SVar); RPart.Translate(SRPart,SVar); end; destructor TConstraint.Free; begin VarCount:=0; Variables:=nil; LPart.Free; RPart.Free; end; // возвращает указатель на переменную с именем Name Function GetPVariable(Name : string) : TVariable; var i : integer; begin i:=0; while VariableList.List[i].VarName <> Name do inc(i); Result:=VariableList.List[i]; end; Function Svertka(var OldL, OldR: extended; NewL, NewR: extended): boolean; var tempL, tempR : extended; begin tempL:=OldL; tempR:=OldR; if NewL <= NewR then begin if NewR < OldL then OldR:=OldL else if OldR < NewL then OldL:=OldR // свертка else begin OldL:=max(OldL,NewL); OldR:=min(OldR,NewR); end; end; if (tempL <> OldL) or (tempR <> OldR) then Result:=true else Result:=false; end; // СЖАТИЕ ПЕРЕМЕННЫХ ДЛЯ РАВЕНСТВА Function TConstraint.TightenBoundsForEqual(V : string) : boolean; type ArrayOfE = array of extended; var Number : integer; // номер переменной v в списке переменных i : integer; NumberArray : ArrayOfE; IndexMassiv : ArrayOfE; Svob : extended; // свободный член PVar,tempP : TVariable; tempLBound, tempRBound, Coef : extended; Function FillArray(Place : integer; Chislo : integer) : ArrayOfE; var i : integer; begin for i:=0 to VarCount-1 do NumberArray[i]:=0; NumberArray[Place]:=Chislo; Result:=NumberArray; end; begin Number:=0; while Variables[Number] <> V do inc(Number); SetLength(NumberArray,VarCount); SetLength(IndexMassiv,VarCount); // получаем коэффициенты for i:=0 to VarCount-1 do IndexMassiv[i]:=LPart.Get(FillArray(i,1)) - LPart.Get(FillArray(i,0)) - Svob:=LPart.Get(FillArray(0,0)) - RPart.Get(FillArray(0,0)); if IndexMassiv[Number] < 0 then begin for i:=0 to VarCount-1 do IndexMassiv[i]:=-IndexMassiv[i]; Svob:=-Svob; end; Coef:=IndexMassiv[Number]; PVar:=GetPVariable(V); tempLBound:=-Svob/Coef; tempRBound:=-Svob/Coef; for i:=0 to VarCount-1 do if i <> Number then begin tempP:=GetPVariable(Variables[i]); if IndexMassiv[i] > 0 then begin tempLBound:=tempLBound - IndexMassiv[i]*tempP.RBound/coef; tempRBound:=tempRBound - IndexMassiv[i]*tempP.LBound/coef; end else begin tempLBound:=tempLBound - IndexMassiv[i]*tempP.LBound/coef; tempRBound:=tempRBound - IndexMassiv[i]*tempP.RBound/coef; end; end; Result:=Svertka(PVar.LBound,PVar.RBound,tempLBound,tempRBound); end; // СЖАТИЕ ПЕРЕМЕННЫХ ДЛЯ НЕРАВЕНСТВА Function TConstraint.TightenBoundsForNoEqual(V : string) : boolean; var PVar : TVariable; begin PVar:=GetPVariable(V); if CType = 'l' then PVar.RBound:=RPart.Get([1]) else PVar.LBound:=RPart.Get([1]); Result:=True; end; // СЖАТИЕ ПЕРЕМЕННЫХ ДЛЯ СЛАБЫХ РАВЕНСТВ Function TConstraint.TightenBoundsForWeakEqual(V : string) : boolean; var PVar : TVariable; begin PVar:=GetPVariable(V); Result:=Svertka(PVar.LBound,PVar.RBound,RPart.Get([1]), end; // СЖАТИЕ ПЕРЕМЕННЫХ Function TConstraint.TightenBoundsFor(V : string) : boolean; var t : TVariable; Procedure ShowSteps; var NewString : string; i : integer; IsNew : boolean; begin IsNew:=True; t:=GetPVariable(V); NewString:=t.VarName + ': [' + FloatToStr(t.LBound) + '; ' for i:=0 to Form1.ListBox1.Count-1 do if Form1.ListBox1.Items.Strings[i] = NewString then begin IsNew:=False; break; end; if IsNew then Form1.ListBox1.Items.Append(NewString); end; begin if (CType = 'l') or (CType = 'm') then Result:=TightenBoundsForNoEqual(V) else if Prior <> 'w' then Result:=TightenBoundsForEqual(V) else Result:=TightenBoundsForWeakEqual(V); ShowSteps; end; Function TConstraint.IsElemInVars(Elem : string) : boolean; var temp : boolean; i : integer; begin temp:=False; for i:=0 to VarCount-1 do if Variables[i] = Elem then begin temp:=true; break; end; Result:=temp; end; Procedure TVariable.SetBounds(pLBound, pRBound : extended); begin LBound:=pLBound; RBound:=pRBound; end; constructor TVariable.Create(pName : string; pLBound, pRBound : extended); begin VarName:=pName; LBound:=pLBound; RBound:=pRBound; end; destructor TVariable.Free; begin end; Procedure GetConstraintList(FileName : string; var List : TConstraintList); var i : integer; s : string; begin List.Count:=Form1.Memo1.Lines.Count; SetLength(List.List,List.Count); for i:=0 to List.Count-1 do begin s:=Form1.Memo1.Lines.Strings[i]; List.List[i]:=TConstraint.Create(s); end; end; Procedure GetVariablesList(CList : TConstraintList; var VarList : TVariableList); var i,j : integer; Function IsNewVar : boolean; var k : integer; temp : boolean; begin temp:=true; for k:=0 to VarList.Count-1 do if VarList.List[k].VarName = CList.List[i].Variables[j] then temp:=False; Result:=temp; end; begin VarList.Count:=CList.List[0].VarCount; SetLength(VarList.List,VarList.Count+1); for i:=0 to VarList.Count - 1 do VarList.List[i]:=TVariable.Create(CList.List[0].Variables[i], LInfinity,RInfinity); for i:=1 to CList.Count-1 do for j:=0 to CList.List[i].VarCount-1 do if IsNewVar then begin inc(VarList.Count); SetLength(VarList.List,VarList.Count); VarList.List[VarList.Count-1]:= end; end; Procedure TightenBounds(cn : TConstraint; var Queue : TQueueOfC; var TightVariables : TSetOfV; var ActiveConstraints : TSetOfC); var i,j : integer; TightenFlag : boolean; v : string; begin for i:=0 to cn.VarCount-1 do if not TightVariables.IsElemIn(cn.Variables[i]) then begin v:=cn.Variables[i]; TightenFlag:=cn.TightenBoundsFor(v); TightVariables.Add(GetPVariable(v)); if TightenFlag then for j:=0 to ConstraintList.Count-1 do begin if ConstraintList.List[j].IsElemInVars(v) then if (ActiveConstraints.IsElemIn(ConstraintList.List[j])) and (not Queue.IsElemIn(ConstraintList.List[j])) then Queue.Add(ConstraintList.List[j]); end; end; end; Procedure CheckConstraints(cn : TConstraint; var ActiveConstraints : TSetOfC); var i : integer; temp : boolean; v : TVariable; begin temp:=False; // не все переменные имеют уникальные значения for i:=0 to cn.VarCount-1 do begin v:=GetPVariable(cn.Variables[i]); if v.LBound <> v.RBound then temp:=True; end; if temp then ActiveConstraints.Add(cn) else ActiveConstraints.Delete(cn); if cn.VarCount = 1 then ActiveConstraints.Delete(cn); end; procedure TForm1.Button1Click(Sender: TObject); var Queue : TQueueOfC; // очередь ограничений ActiveConstraints : TSetOfC; // активное множество ограничений TightVariables : TSetOfV; // cn : TConstraint; i : integer; Procedure ShowDecision; var i : integer; begin for i:=0 to VariableList.Count-1 do Form2.ListBox2.Items.Append(VariableList.List[i].VarName + ' = ' end; begin ListBox1.Clear; Form2.Show; Form2.ListBox2.Clear; GetConstraintList('Data.txt',ConstraintList); GetVariablesList(ConstraintList,VariableList); ActiveConstraints:=TSetOfC.Create; for i:=0 to ConstraintList.Count-1 do begin TightVariables:=TSetOfV.Create; Queue:=TQueueOfC.Create; Queue.Add(ConstraintList.List[i]); while not Queue.IsEmpty do begin cn:=Queue.Front; TightenBounds(cn,Queue,TightVariables,ActiveConstraints); CheckConstraints(cn,ActiveConstraints); Queue.Dequeue; end; end; ShowDecision; end; end. {=============================================================================} unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm2 = class(TForm) GroupBox2: TGroupBox; ListBox2: TListBox; private { Private declarations } public { Public declarations } end; var Form2: TForm2; implementation {$R *.dfm} end. {=============================================================================} unit MyFunctions; interface type TSArray = array of string; Procedure GetLeftAndRightParts(var Constraint : string; var LPart, RPart: string; var Prior, CType: char); Procedure GetVarList(Constraint : string; var Variables : TSArray; var VarCount: integer; var SVar: string); implementation // ВЫРЕЗАЕМ ЛЕВУЮ И ПРАВУЮ ЧАСТЬ В ОГРАНИЧЕНИИ, ОПРЕДЕЛЯЕМ ПРИОРИТЕТ И ТИП Procedure GetLeftAndRightParts(var Constraint : string; var LPart, RPart: string; var Prior, CType: char); var i : integer; begin Prior:=Constraint[1]; // приоритет Delete(Constraint,1,2); i:=pos('<=',Constraint); if i>0 then begin CType:='l'; LPart:=Copy(Constraint,1,i-1); RPart:=Copy(Constraint,i+2,Length(Constraint)-i-1); end else begin i:=pos('>=',Constraint); if i>0 then begin CType:='m'; LPart:=Copy(Constraint,1,i-1); RPart:=Copy(Constraint,i+2,Length(Constraint)-i-1); end else begin i:=pos('=',Constraint); CType:='e'; LPart:=Copy(Constraint,1,i-1); RPart:=Copy(Constraint,i+1,Length(Constraint)-i); end; end; end; // ПОЛУЧАЕМ СПИСОК ПЕРЕМЕННЫХ Procedure GetVarList(Constraint : string; var Variables : TSArray; var VarCount: integer; var SVar: string); var NumbersSet : set of char; s : string; LengthS, i, j : integer; begin NumbersSet:=['0'..'9','<','=','>','-','+','*',' ']; VarCount:=0; s:=Constraint + '+'; lengthS:=length(s); i:=1; while i<lengthS do begin while (s[i] in NumbersSet) and (i<lengthS) do inc(i); j:=i; while (not(s[i] in NumbersSet)) and (i<lengthS) do inc(i); if i > j then begin inc(VarCount); SetLength(Variables,VarCount); Variables[VarCount-1]:=Copy(s,j,i-j); end; end; SVar:=''; for i:=0 to VarCount-1 do SVar:=SVar + ',' + Variables[i]; Delete(SVar,1,1); end; end. {=============================================================================} unit CSet; interface uses Unit1; type TSetOfC = class Count : integer; Constraints : array of TConstraint; constructor Create; destructor Free; procedure Add(Elem : TConstraint); function IsElemIn(Elem : TConstraint) : boolean; procedure Delete(cn : TConstraint); end; implementation Constructor TSetOfC.Create; begin Count:=0; end; Destructor TSetOfC.Free; begin Count:=0; Constraints:=nil; end; Procedure TSetOfC.Add(Elem : TConstraint); begin inc(Count); SetLength(Constraints,Count); Constraints[Count-1]:=Elem; end; Function TSetOfC.IsElemIn(Elem : TConstraint) : boolean; var i : integer; temp : boolean; begin temp:=False; for i:=0 to Count-1 do if Constraints[i] = Elem then begin temp:=True; break; end; Result:=temp; end; Procedure TSetOfC.Delete(cn : TConstraint); var i,j : integer; begin for i:=0 to Count-1 do if cn = Constraints[i] then begin for j:=i to Count-2 do Constraints[j]:=Constraints[j+1]; Dec(Count); SetLength(Constraints,Count); break; end; end; end. {=============================================================================} unit CQueue; interface uses Unit1; type TQueueOfC = class Count : integer; Constraints : array of TConstraint; constructor Create; destructor Free; procedure Add(Elem : TConstraint); procedure Dequeue; function IsEmpty : boolean; function Front : TConstraint; function IsElemIn(Elem : TConstraint) : boolean; end; implementation Constructor TQueueOfC.Create; begin Count:=0; end; Destructor TQueueOfC.Free; begin Count:=0; Constraints:=nil; end; Procedure TQueueOfC.Add(Elem : TConstraint); begin inc(Count); SetLength(Constraints,Count); Constraints[Count-1]:=Elem; end; Procedure TQueueOfC.Dequeue; var i : integer; begin for i:=0 to Count-2 do Constraints[i]:=Constraints[i+1]; dec(Count); SetLength(Constraints,Count); end; Function TQueueOfC.IsEmpty : boolean; begin if Count = 0 then Result:=True else Result:=False; end; Function TQueueOfC.Front : TConstraint; begin Result:=Constraints[0]; end; Function TQueueOfC.IsElemIn(Elem : TConstraint) : boolean; var i : integer; temp : boolean; begin temp:=False; for i:=0 to Count-1 do if Constraints[i] = Elem then begin temp:=True; break; end; Result:=temp; end; end. {=============================================================================} unit VSet; interface uses Unit1; type TSetOfV = class Count : integer; Variables : array of TVariable; constructor Create; destructor Free; procedure Add(Elem : TVariable); function IsElemIn(v : string) : boolean; end; implementation Constructor TSetOfV.Create; begin Count:=0; end; Destructor TSetOfV.Free; begin Count:=0; Variables:=nil; end; Procedure TSetOfV.Add(Elem : TVariable); begin inc(Count); SetLength(Variables,Count); Variables[Count-1]:=Elem; end; function TSetOfV.IsElemIn(v : string) : boolean; var i : integer; temp : boolean; begin temp:=False; for i:=0 to Count-1 do begin if Variables[i].VarName = v then temp:=True; break; end; Result:=temp; end;
| |||||