Разработка программного модуля для нахождения оптимальных предельно-допустимых выбросов в атмосферу от группы источников
Существующая система установления ПДВ для промышленных источников. Характеристика симплекс метода. Программная реализация, пример практического применения, вывод полученных результатов. Сравнение различных методов расчета ПДВ для реального предприятия.
Рубрика | Экология и охрана природы |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 26.10.2010 |
Размер файла | 2,2 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
При отыскании Fmin в индексной строке должны быть отрицательные и нулевые оценки.
При отыскании Fmax в индексной строке должны быть нулевые и положительные оценки.
Переход ко второй итерации:
Для этого отыскиваем ключевой (главный) столбец и ключевую (главную) строку.
Ключевым столбцом является тот в котором находится наибольший положительный элемент индексной строки при отыскании Fmin или наименьший отрицательный элемент при отыскании Fmax.
Ключевой строкой называется та, в которой содержится наименьшее положительное частное от деления элементов столбца H на соответствующие элементы ключевого столбца.
На пересечении строки и столбца находится разрешающий элемент.
На этом этапе осуществляется к переходу к последующим итерациям.
Переход к итерациям:
Выводится базис ключевой строки, уступая место переменной из ключевого столбца со своим коэффициентом.
Заполняется строка вновь введенного базиса путем деления соответствующих элементов выделенной строки предыдущей итерации на разрешающий элемент.
Если в главной строке содержится нулевой элемент, то столбец, в котором находиться этот элемент переноситься в последующую итерацию без изменения.
Если в главном столбце имеется нулевой элемент, то строка, в которой он находиться переноситься без изменения в последующую итерацию.
Остальные элементы переносятся по формуле:
3. Формализация поставленной задачи
Прежде всего, покажем, что характерные свойства МАД и известные сведения из теории линейных операторов позволяют экспертизу АОМ и установление ПДВ формализовать в виде двух зависимых математических задач.
Пусть суммарное загрязнение ВБ города отдельной примесью характеризуется функцией C(X,t) пространственных координат и времени. Загрязнение считается допустимым при C(X,t) < N(X) , где N - норматив. Если C(X,t) > N(X), то необходимы АО мероприятия по достижению норматива. При их планировании из суммарного загрязнения атмосферы требуется выделить вклады Cj(X,t), j=1,…,J от J заданных источников, под которыми могут подразумеваться как отдельные трубы, аэрационные фонари и т.д., так и их совокупности, объединенные по различным признакам (по принадлежности к одному цеху, предприятию, ведомству по высоте выброса и т.д.). Пусть выбросы источников есть Q = (Q 1,Q 2,…,QJ). Предположим, что остальные параметры (высота, координаты и т.д.) в результате АОМ не изменяются. Тогда возникающую при экспертизе планов АОМ города задачу - определить изменение dC характеристик загрязнения ВБ по сравнению с базовым (предплановым) периодом - можно записать в виде:
dC = C0 - CP = A(Q) - A(X) (3.21)
где А- оператор модельной зависимости C от Q; величины C с индексом '0' относятся к базовому периоду, а с индексом 'P' - к ожидаемому после реализации запланированных АОМ. Заметим, что не только ожидаемый CP, но и существующий уровень загрязнения C0, суммарное значение которого в некоторых точках промышленного города регулярно измеряется [78], требует в (1.21) модельного представления C0 = A(Q0), поскольку в общем случае методы контроля загрязнения не могут указать вклад конкретного источника в измеряемую величину. Соотношение (3.21) показывает, что формализация выделенной задачи сводится к построению и надлежащему применению оператора А, позволяющего переходить от выбросов к характеристикам загрязнения ВБ и различать заданный источник на фоне всех остальных.
Пользуясь линейностью модели ОНД-86 по выбросам источников можно представить загрязнение атмосферы в контрольных точках жилой зоны в виде линейной формы:
,
где - концентрация в i-ой точке, - выброс j-го источника, - вклад j-го источника в i-й точке, который в дальнейшем будем называть коэффициентом влияния. Отметим, что на практике (поскольку число источников и контрольных точек конечно) оператор А представляет собой матрицу, состоящую из коэффициентов влияния aij.
Санитарные требования приводят к системе линейных неравенств:
,
решение которой ищется на интервале
,
где - технологически обоснованный минимум выброса j-го источника.
На сегодняшний день в методической литературе описаны два метода нахождения решения поставленной задачи: МРН-87 [24] и метод равного квотирования [26]. Оба метода кратко рассмотрены в параграфе . Они дают частное решение поставленной системы неравенств из соображений удобства нахождения единственного решения. Однако любое предприятие заинтересовано в минимальных затратах, необходимых для установления нормативных выбросов . Для этой цели, к поставленной системе неравенств добавляем целевую функцию:
Где в общем случае - стоимость снижения на единицу выброса для j-го источника. В данном виде решение Xj дает минимум затрат на достижение нормативного загрязнения атмосферы.
В предположении
,
что эквивалентно .
Следовательно, задача сводится к поиску максимально допустимого по сумме сочетания выбросов Xj данного предприятия, позволяющего достичь нормативного загрязнения атмосферы. В связи с линейностью модели ОНД-86 по отношению к выбросам для поиска решения поставленной задачи может быть применён Симплекс-метод.
4. Программная реализация и пример практического применения
Для достижения поставленной задачи по разработке интегрированного в ПК ЭРА-ВОЗДУХ программного модуля расчета оптимальных ПДВ проведено изучение структуры файлов, в которых головной модуль передают данные расчетного блоку УПРЗА ЭРА. Разработаны соответствующие процедуры для автоматизированного чтения всех необходимых файлов.
4.1 Выбор загрязняющих веществ
После указания директории с данными для расчета, программа сканирует файлы в папке WORK по маске «htop*.ppp», таким образом выбирая загрязняющие вещества, для которых имеются начальные данные и возможно провести расчет.
Далее для каждого отмеченного вещества независимо от других будет производиться считывание значений и расчет ПДВ (Xj).
4.2 Обработка точек с повышенным загрязнением
procedure get_point (s:string;var countPoint:integer;var point_pdk:tExtArray);
Процедура извлекает значения Ni (ПДК), а так же количество точек I (i=1,..,I), в которых выбросы превышают Ni, из файла вида «htop*.ppp» в директории /WORK/.
Внутренняя структура htop*.ppp представляет собой текстовый файл, содержащий таблицу с данными о контрольных точках. Значение Ni содержатся в 8-ом столбце. Чаще всего Ni в точках равно 1 или 0.8 для особо охраняемых территорий (санатории, зоны отдыха).
4.3 Обработка источников
procedure get_funnel(s:string; var countFunnel : integer ; var funnel_name : tsArray; var funnel_m:tExtArray;var funnel_min:tExtArray);
Процедура извлекает данные из файла вида «ist_*.txt», которые находятся в директории /DAT/. «ist_*.txt» - это текстовый файл, в котором в табличном виде представлена информация об источниках выбросов, в том числе:
· количество источников J;
· уникальный код источника;
· существующий выброс источника Qj;
· минимально возможный выброс Qjmin (не всегда указывается).
4.4 Обработка таблиц влияния источников на точки
procedure get_pointfunnel ( s : string; countPoint : integer; countfunnel : integer; funnel_name : tsArray; funnel_m : tExtArray; var pointfunnelx2 : tExtArrayx2; var point_cf : tExtArray);
Процедура извлекает коэффициенты влияния aij из файлов вида «10pd*.ppp», где «10pd*.ppp» - текстовый файл, содержащий отчет о результатах работы программы.
4.5 Применении симплекс-метода
procedure get_simplexsolve ( countPoint : integer; countFunnel : integer ; point_pdk : tExtArray; point_cf : tExtArray; funnel_m : tExtArray; funnel_min : tExtArray; pointfunnelx2 : tExtArrayx2; var x : tExtArray; var s_temp : string);
Процедура, используя данные расчетов программы «ЭРА-воздух», при помощи симплекс-метода рассчитывает оптимальные выбросы Xj для источников при заданных условиях.
4.6 Вывод полученных результатов
Результаты полученных вычислений выводятся на форму программы, а так же в файлы вида: «h_pd*.gpv», где * - это код вещества, для которого производился расчет.
4.7 Сравнение различных методов расчета ПДВ для реального предприятия
В расчете загрязнения атмосферы диоксидом азота на расчетном прямоугольнике 9 на 9 км с шагом 500 метров проведен расчет максимальных разовых концентраций, создаваемых 70-ю источниками выброса различного типа и высоты. В итоге получено поле максимальных концентраций, в которых есть области превышения норматива N, который в данном случае равен ПДК.
Картина загрязнения представлена на рисунке 1:
Рис 1. Загрязнение атмосферы в окрестности исследуемого предприятия.
Программный комплекс Эра-Воздух производит автоматический выбор точек превышения норматива N и позволяет найти расчетные значения ПДВ на основе методов МРН-87 и Метода равного квотирования.
При выполнении работы в программный комплекс добавлен новый модуль, в соответствии с алгоритмом описанным в пункте 5. Этот модуль позволяет рассчитать оптимальное значение ПДВ с использованием симплексного метода. Результаты расчетов ПДВ различными методами представлено ниже в таблицах 4.1, 4.2 и 4.3.
Таблица 4.1. Результаты расчета ПДВ (методом равного квотирования)
ПРИМЕСЬ=0301 Азот(IV) оксид (Азота диоксид)
Город :001 Кемерово, Объект : 0025
-----------------------------------------------------------------------------
| Код |Высота |Существую-|Минимально| Коэфф. | Расчетное |Кратность|
N | источника |источн.|щий выброс|возможный | норми- | значение |снижения |
п/п| выброса | м | г/с | выброс |рования | П Д В |выброса |
---|-----------|-------|----------|---г/с----|--------|----г/с----|---------|
15 00250010354 40.0 8.2390 0.0 0.485 3.9961 2.062
53 00250010944 40.0 8.2370 0.0 0.461 3.7941 2.171
Остальные источники не подлежат нормированию.
-----------------------------------------------------------------------------
В сумме по 0301 51.8545 0.0 0.832 43.1687 1.201
-----------------------------------------------------------------------------
Таблица 4.2. Результаты расчета ПДВ (метод МРН-87)
ПРИМЕСЬ=0301 Азот(IV) оксид (Азота диоксид)
Город :001 Кемерово, Объект :0025
-----------------------------------------------------------------------------
| Код |Высота |Существую-|Минимально| Коэфф. | Расчетное |Кратность|
N | источника |источн.|щий выброс|возможный | норми- | значение |снижения |
п/п| выброса | м | г/с | выброс |рования | П Д В |выброса |
---|-----------|-------|----------|---г/с----|--------|----г/с----|---------|
14 00250010353 33.4 1.0750 0.0 0.739 0.7942 1.354
15 00250010354 40.0 8.2390 0.0 0.739 6.0867 1.354
16 00250010356 60.0 2.1500 0.0 0.739 1.5884 1.354
24 00250010656 45.0 1.5000 0.0 0.739 1.1082 1.354
41 00250010892 60.0 9.0430 0.0 0.739 6.6807 1.354
52 00250010943 33.4 0.5280 0.0 0.739 0.3901 1.354
53 00250010944 40.0 8.2370 0.0 0.739 6.0852 1.354
54 00250010946 45.0 2.1470 0.0 0.739 1.5861 1.354
63 00250011198 24.4 0.5110 0.0 0.739 0.3775 1.354
66 00250011225 24.4 0.5890 0.0 0.739 0.4351 1.354
Остальные источники не подлежат нормированию.
----------------------------------------------------------------------------
В сумме по 0301 51.8545 0.0 0.829 42.9676 1.207
----------------------------------------------------------------------------
Таблица 4.3. Результаты расчета ПДВ (симплекс метод)
ПРИМЕСЬ=0301 Азот(IV) оксид (Азота диоксид)
Город :001 Кемерово, Объект :0025
---------------------------------------------------------
| Код |Существую-|Минимально| Расчетное | коэфф. |
| источника |щий выброс|возможный | значение | норми- |
| выброса | г/с | выброс | П Д В | рования |
|-----------|----------|---г/с----|----г/с----|---------|
|00250010353| 1.075000 | 0.000000 | 0.0196222 | 0.01825 |
|00250010943| 0.528000 | 0.000000 | 0.0000000 | 0.00000 |
|00250011225| 0.589000 | 0.000000 | 0.0000000 | 0.00000 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| в сумме: 51.854470 49.682092 | 0.95811 |
---------------------------------------------------------
Решение задачи линейного программирования показывает, что максимально возможный выброс по заводу в целом можно обеспечить при достижении нормы загрязнения, если закрыть источники 1225 и 0943, а на источнике 0353 снизить выброс примерно в 50 раз. О реальности такого решения могут судить технологические службы предприятия.
Итоговая таблица сравнения трех методов:
Метод |
Существующий выброс |
Расчетное значение |
Процент снижения |
|
Равного квотирования |
51.8545 |
43.1687 |
16,75 |
|
МРН-87 |
51.8545 |
42.9676 |
17,14 |
|
Симплексный |
51.8545 |
49.6820 |
4,19 |
Заключение
· Таким образом, в процессе выполнения дипломной работы проведен обзор существующей системы установления ПДВ для источников загрязнения атмосферы промышленных предприятий. При этом рассмотрена система обеспечения нормативных задач управления выбросами в атмосферу исходными данными. Исследована структура исходных данных их качество. Рассмотрены нормативные требования к загрязнению атмосферы населенных мест, которые накладывают ограничения на выбросы промышленных предприятий в атмосферу. Показано, что эти требования и свойство линейности нормативной модели расчета загрязнения атмосферы ОНД-86 по отношению к выбросам ИЗА позволяют представить процедуру нахождения расчетных значений ПДВ в виде задачи линейного программирования.
· Рассмотрены существующие в методической литературе способы расчета ПДВ в виде методов равного квотирования и МРН-87. Данные методы не имеют целевой функции и дают некоторые частные решения поставленной задачи.
· Изучен программный комплекс ЭРА-Воздух и форматы хранения и передачи данных между его модулями.
· Разработана процедура автоматического считывания исходных данных и результатов из ПК ЭРА-Воздух для полного обеспечения задачи линейного программирования исходными данными.
· Разработана программа расчета ПДВ на основе симплекс метода.
· Решена практическая задача по расчету ПДВ для одного из крупных предприятий г. Кемерово как встроенными в ПК ЭРА-ВОЗДУХ методами (МРН-87, равное квотирование), так и с использованием симплекс метода.
· Показано, что использование оптимизационного метода расчета ПДВ позволяет обеспечить нормативное загрязнение атмосферы при больших суммарных выбросах. В случае технологической приемлемости такого решения предприятие может существенно снизить платежи за сверхнормативный выброс в атмосферу.
Список литературы
Методическое пособие по расчету, нормированию и контролю выбросов загрязняющих веществ в атмосферный воздух. - СПб.: НИИ Атмосфера МПР РФ, 2002.
ОНД-86. Методика расчета концентраций в атмосферном воздухе вредных веществ, содержащихся в выбросах предприятий. Л.: Гидрометеоиздат, 1987.
Постановление Правительства Российской Федерации N182 от 2 марта 2000 г. «О порядке установления и пересмотра экологических и гигиенических нормативов качества атмосферного воздуха, предельно допустимых уровней физических воздействий на атмосферный воздух и государственной регистрации вредных (загрязняющих) веществ и потенциально опасных веществ». М., 2000.
Постановление Правительства Российской Федерации от 2 марта 2000 г. N 183 «О нормативах выбросов вредных (загрязняющих) веществ в атмосферный воздух и вредных физических воздействий на него». М., 2000.
Федеральный Закон «Об охране окружающей среды». М., 2002.
Рязанов В.А. О критериях и методах обоснования максимально допустимых концентраций атмосферных загрязнений в СССР.- В кн.: Предельно допустимые концентрации атмосферных загрязнений. Вып.8. - М.: Медицина, 1964, с. 5-21.
Перечень и коды веществ, загрязняющих атмосферный воздух. СПб., 2000.
Беспамятнов Г.П., Кротов Ю.А. Предельно допустимые концентрации химических веществ в окружающей среде - Л.: «Химия», 1985.
Пинигин М.А. Значение вероятностного подхода при решении вопросов гигиенического регламентирования атмосферных загрязнений. В кн. ”Медицинские проблемы охраны окружающей среды”. М.: 1981, с.95-102.
Берлянд М.Е. Прогноз и регулирование загрязнения атмосферы. -Л.: Гидрометеоиздат, 1985, 272с.
Безуглая Э.Ю. Мониторинг состояния загрязнения атмосферы в городах. Л.: Гидрометеоиздат, 1986, 200с.
Безуглая Э.Ю., Ковалевский А.Г., Расторгуева Г.П. Особенности распределения промышленных примесей в атмосфере городов различных типов. Тр. ГГО, вып. 467, 1983, с.81-87.
Перечень методик выполнения измерений концентраций загрязняющих веществ в выбросах промышленных предприятий СПб., 2001.
Перечень документов по расчету выделений (выбросов) загрязняющих веществ в атмосферный воздух, действующих в 2001-2002 годах. СПб., 2001.
Инструкция по инвентаризации выбросов загрязняющих веществ в атмосферу. Л., 1990.
СанПиН 2.1.6.1032-01 «Гигиенические требования к обеспечению качества атмосферного воздуха населенных мест». М., 2001.
.Атмосферная турбулентность и моделирование распространения примесей /под.ред. Ньистадта Ф.Т.М., Ван-Допа Х.- Л.: Гидрометеоиздат, 1985,-350 c.
Пененко В.В., Алоян А.Е. Модели и методы для задач охраны окружающей среды. -Новосибирск.: Наука, 1985.-256с.
Постановление Совета Министров РСФСР. Об утверждении на 1991 год нормативов за выбросы загрязняющих веществ в природную среду и порядка их применения./9 января 1991г. N 13 /. Собрание постановлений правительства РСФСР. -М.: N9, 1991.
Hanna S.R. Review of Atmospheric Diffusion Models for Regulatory Application.- WMO Tecnical Notes, No.177, 1982-42p.
Методы анализа загрязнений воздуха./Дугов Ю.С., Беликов А.Б., Дьяков Г.А., Тульчинский В.М.-М.: Химия, 1984,-384 с.
Вольберг Н.Ш., Егорова Е.Д., Кузьмина Т.А. Метрологические характеристики фотометрических методов анализа загрязнения атмосферы. - Тр. ГГО, 1982, No 450.c.107-111.
Израэль Ю.А, Гасилина Н.К., Ровинский Ф.Я. Система наблюдений и контроля загрязнения природной среды в СССР.- Метеорология и гидрология, 1978, No 10, c.5-12.
Методика расчета нормативов допустимых выбросов загрязняющих веществ в атмосферу для групп источников. МРН-87. - М., Госкомгидромет, Институт прикладной геофизики. 1987. -30с.
Рекомендации по определению допустимых вкладов в загрязнение атмосферы выбросов загрязняющих веществ предприятиями с использованием сводных расчетов загрязнения воздушного бассейна города (региона) выбросами промышленности и автотранспорта. СПб., 1999.-97с.
Васильев Ф.П. Методы решения экстремальных задач. М: Наука, 1980.-518с.
Вспомогательные указатели
Перечень сокращений
ЗВ - загрязняющее (вредное) вещество
ИЗА - источник загрязнения атмосферы
ПДВ - предельно допустимый выброс (допустимый выброс)
СЗЗ - санитарно-защитная зона
ПДКр - максимальная разовая предельно допустимая концентрация загрязняющего вещества в атмосферном воздухе населенных мест
ПДКс - среднесуточная предельно допустимая концентрация загрязняющего вещества в атмосферном воздухе населенных мест
ОБУВ - ориентировочный безопасный уровень воздействия загрязняющих веществ в атмосферном воздухе населенных мест
ГВС - газовоздушная смесь
ГОУ - газоочистная установка
ОНД - общесоюзный нормативный документ
НМУ - неблагоприятные метеорологические условия
УПРЗА - унифицированная программа расчета загрязнения атмосферы
Приложения
Unit1.pas
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ShellAPI, ShlObj, StdCtrls, Buttons, CheckLst,Masks,inifiles,
ComCtrls,simplex, Menus;
const MyDecimalSeparator='.';
type
tsArray = array of string;
tExtArrayx2 = array of tExtArray;
TForm1 = class(TForm)
Edit1: TEdit;
GroupBox1: TGroupBox;
CheckListBox1: TCheckListBox;
Label1: TLabel;
BitBtn1: TBitBtn;
Button3: TButton;
Memo1: TMemo;
SpeedButton1: TSpeedButton;
CheckBox1: TCheckBox;
SpeedButton2: TSpeedButton;
SpeedButton3: TSpeedButton;
SpeedButton4: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure N2Click(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
procedure SpeedButton4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
dir_path:string;
IniFile: TIniFile;
implementation
{$R *.dfm}
//запись в ini файл
procedure SaveIni(s:string);
var
IniPath: string;
FileName: string;
begin
GetDir(0,IniPath);
FileName:=IniPath+'\sav.ini';
IniFile:=TIniFile.Create(FileName);
Inifile.WriteString('patch','dir',s);
IniFile.Free;
end;
//чтение ini файла
function ReadIni:string;
var
IniPath: string;
FileName: string;
s:string;
begin
GetDir(0,IniPath);
FileName:=IniPath+'\sav.ini';
IniFile:=TIniFile.Create(FileName);
ReadIni:=Inifile.ReadString('patch','dir',s);
IniFile.Free;
end;
//--------- Удаляет пробел или запятую с краёв строки --------------------------
Function DelSpaceAndCap(s:string):string;
begin
while pos(copy(s,1,1),' ')<>0 do delete(s,1,1);
while pos(copy(s,length(s),1),' ')<>0 do delete(s,length(s),1);
result:=s;
end;
//--------- вырезает из строки имя ---------------------------------------------
Function ReturnSubString(Var s:string):string;
var
position,i : integer;
begin
s:=DelSpaceAndCap(s);
position:=0;
for i:=1 to length(s)-1 do
if (pos(copy(s,i,1),' ')<>0) and (position=0) then
position:=i;
if position=0 then begin
result:=s;
s:='';
end else begin
result := DelSpaceAndCap(copy(s,1,position));
Delete(s,1,position);
s:=DelSpaceAndCap(s);
end;
end;
//вывод ограничений
//==============================================================================
procedure vv(a:real;mas:tExtArray; Sign: TOperation);
var
i:integer;
s,s2,s3:string;
begin
s:=floattostr(mas[0]);
for i:=1 to length(mas)-1 do
s:=s+'+'+floattostr(mas[i]);
if Sign=less then s2:=' < ';
if Sign=Greater then s2:=' > ';
if Sign=Equal then s2:=' = ';
form1.memo1.lines.Add(s+s2+floattostr(a));
end;
//==============================================================================
//==============================================================================
//замена в строке всех вхождений одной подстроки на другую
function StrReplace(Str, Str1, Str2 : string):string;
var
p, L : integer;
s:string;
begin
s:=str;
L:=length(str1);
repeat
p:=pos(str1, s);
if p>0 then begin
Delete(s,p,L);
insert(str2, s, P);
end;
until P = 0;
StrReplace:=s;
end;
//==============================================================================
//==============================================================================
//========================= считывание таблиц влияния таблиц источников на точки
procedure get_pointfunnel(s:string;countPoint:integer;countfunnel:integer;funnel_name:tsArray;funnel_m:tExtArray;
var pointfunnelx2:tExtArrayx2; var point_cf:tExtArray);
var
h:textfile;
k,m:integer;
s_temp,s_temp2,s_temp3:string;
flag:boolean;
begin
SetLength(PointFunnelx2,countPoint,countFunnel);
SetLength(point_cf,countPoint);
for k:=0 to countPoint-1 do begin
point_cf[k]:=0;
for m:=0 to countFunnel-1 do
PointFunnelx2[k,m]:=0;
end;
AssignFile(h,dir_path+'\RESULT\'+'10pd'+s+'.ppp');
reset(h);
for k:=1 to 22 do readln(h,s_temp);
s_temp:=StrReplace(s_temp,'|',' ');
s_temp2:=s_temp;
for m:= 0 to CountPoint-1 do begin //общий цикл
flag:=true;
while flag do begin
if ReturnSubString(s_temp2)='Фоновая' then begin
point_cf[m]:=strtofloat(copy(s_temp,pos('%',s_temp)-4,4));
end else begin
s_temp3:=ReturnSubString(s_temp);
s_temp3:=ReturnSubString(s_temp);
s_temp3:=ReturnSubString(s_temp);
for k:=1 to 6 do s_temp2:=ReturnSubString(s_temp);
//showmessage(s_temp2);
for k:=0 to countFunnel-1 do
if s_temp3=copy(funnel_name[k],8,4) then
PointFunnelx2[m,k]:=strtofloat(s_temp2);//*funnel_m[k];
end;
readln(h,s_temp);
s_temp:=StrReplace(s_temp,'|',' ');
s_temp2:=s_temp;
if ReturnSubString(s_temp2)='В' then flag:=false;
end;
for k:=1 to 16 do readln(h,s_temp);
s_temp:=StrReplace(s_temp,'|',' ');
s_temp2:=s_temp;
end;
closefile(h);
end;
//==============================================================================
//==============================================================================
//========================================================= получение источников
procedure get_funnel(s:string; var countFunnel:integer;var funnel_name:tsArray;
var funnel_m:tExtArray;var funnel_min:tExtArray);
var
h,h2 : textfile;
index_funnel : integer;
i,j : integer;
s_temp,s_temp2:string;
begin
AssignFile(h,dir_path+'\DAT\'+'ist_'+s+'.txt');
reset(h);
index_funnel:=-11;
while s_temp<>'endI' do begin //чтение файла (установка размера массива)
readln(h,s_temp);
inc(index_funnel);
end;
closefile(h);
CountFunnel:=index_funnel;
setLength(funnel_m,CountFunnel);
setLength(funnel_min,CountFunnel);
setLength(funnel_name,CountFunnel);
for i:=0 to countFunnel-1 do begin
funnel_m[i]:=0;
funnel_min[i]:=0;
funnel_name[i]:='';
end;
AssignFile(h2,dir_path+'\DAT\'+'ist_'+s+'.txt');
reset(h2);
for j:=1 to 9 do
readln(h2,s_temp);
for i:= 0 to CountFunnel-1 do begin
readln(h2,s_temp);
funnel_name[i]:=ReturnSubString(s_temp);
for j:=1 to 14 do
s_temp2:=ReturnSubString(s_temp);
funnel_m[i]:=strtofloat(ReturnSubString(s_temp));
if DelSpaceAndCap(s_temp)<>'' then
funnel_min[i]:=strtofloat(DelSpaceAndCap(s_temp))
else funnel_min[i]:=0;
end;
closefile(h2);
end;
//==============================================================================
//==============================================================================
//============================================================= получение точек
procedure get_point (s:string;var countPoint:integer;var point_pdk:tExtArray);
var
index_point : integer;
i,j : integer;
h,h2 : textfile;
s_temp : string;
begin
index_point:=-2; // переменная для подсчета кол-ва точек
AssignFile(h,dir_path+'\WORK\'+'htop'+s+'.ppp');
reset(h);
while s_temp<>'000' do begin//чтение файла (установка размера массива)
readln(h,s_temp);
inc(index_point);
end;
closefile(h);
CountPoint:=index_point;
setLength(point_pdk,countPoint);
for i:=0 to countPoint-1 do
point_pdk[i]:=0; //зануление
AssignFile(h2,dir_path+'\WORK\'+'htop'+s+'.ppp');
reset(h2);
readln(h2,s_temp);
for i:= 0 to countPoint-1 do begin
readln(h2,s_temp);
for j:=1 to 8 do
point_pdk[i]:=strtofloat(ReturnSubString(s_temp));
end;
closefile(h2);
end;
//==============================================================================
//==============================================================================
//=========================================== решение при помощи симплекс метода
procedure get_simplexsolve(countPoint:integer;countFunnel:integer;point_pdk:tExtArray;
point_cf:tExtArray;funnel_m:tExtArray;funnel_min:tExtArray;
pointfunnelx2:tExtArrayx2;var x:tExtArray;var s_temp:string);
var
mas_temp : tExtArrayx2;
i,j : integer;
sim : TSimplex;
L : tExtArray;
begin
setLength(mas_temp,countFunnel,countFunnel);
setLength(L,countFunnel);
setLength(x,countFunnel);
for i:=0 to countFunnel-1 do
for j:=0 to countFunnel-1 do begin
if i=j then mas_temp[i,j]:=1 else mas_temp[i,j]:=0;
L[j]:=1;
end;
Sim:=TSimplex.Create(L,true);
for i:=0 to countPoint-1 do begin
//showmessage(vv(point_pdk[i],pointfunnelx2[i]));
Sim.AddCons(point_pdk[i],pointfunnelx2[i],less);
if form1.CheckBox1.Checked then vv(point_pdk[i],pointfunnelx2[i],less);
end;
for i:=0 to countFunnel-1 do begin
Sim.AddCons(funnel_m[i],mas_temp[i],less);
if funnel_min[i]>0 then begin
Sim.AddCons(funnel_min[i],mas_temp[i],Greater);
if form1.CheckBox1.Checked then vv(funnel_min[i],mas_temp[i],Greater);
end;
end;
if (Sim.Solve=SIMPLEX_DONE) then begin
s_temp:='решение найдено';
x:=Sim.GetSolution;
end
else s_temp:='Решения не существует';
end;
//==============================================================================
//==============================================================================
//==================================================== общий модуль для подсчета
procedure TForm1.Button3Click(Sender: TObject);
var
s,s_temp,ss : string;
countPoint : integer;
countfunnel : integer;
point_pdk : tExtArray;
point_cf : tExtArray;
funnel_m : tExtArray;
funnel_min : tExtArray;
funnel_name : tsArray;
pointfunnelx2 : tExtArrayx2;
i,j : integer;
x : tExtArray;
empty : boolean;
h : textfile;
funnelSumM,sumX:real;
begin
funnelSumM:=0;
sumX:=0;
memo1.Clear;
for i:=0 to checkListBox1.Items.Count-1 do begin
if CheckListBox1.Checked[i] then begin
application.ProcessMessages;
s:=checklistbox1.Items.Strings[i];
s:=returnSubString(s);
application.ProcessMessages;
get_point (s,countPoint,point_pdk);
get_funnel(s,countFunnel,funnel_name,funnel_m,funnel_min);
get_pointfunnel(s,countPoint,countfunnel,funnel_name,funnel_m,pointfunnelx2,point_cf);
get_simplexsolve(countPoint,CountFunnel,point_pdk,point_cf,funnel_m,funnel_min,pointfunnelx2,x,s_temp);
AssignFile(h,dir_path+'\RESULT\'+'h_pd'+s+'.gpv');
rewrite(h);
if s_temp='решение найдено' then begin
memo1.lines.Add('');
memo1.lines.Add(' Результаты расчета ПДВ (симплекс метод):');
memo1.lines.Add(' ПРИМЕСЬ='+s);
memo1.lines.Add('');
memo1.lines.Add('---------------------------------------------------------');
memo1.lines.Add('| Код |Существую-|Минимально| Расчетное | коэфф. |');
memo1.lines.Add('| источника |щий выброс|возможный | значение | норми- |');
memo1.lines.Add('| выброса | г/с | выброс | П Д В | рования |');
memo1.lines.Add('|-----------|----------|---г/с----|----г/с----|---------|');
writeln(h,'');
writeln(h,' Результаты расчета ПДВ (симплекс метод):');
writeln(h,' ПРИМЕСЬ='+s);
writeln(h,'');
writeln(h,'---------------------------------------------------------');
writeln(h,'| Код |Существую-|Минимально| Расчетное | коэфф. |');
writeln(h,'| источника |щий выброс|возможный | значение | норми- |');
writeln(h,'| выброса | г/с | выброс | П Д В | рования |');
writeln(h,'|-----------|----------|---г/с----|----г/с----|---------|');
empty:=true;
for j:=0 to countFunnel-1 do begin
funnelSumM:=FunnelSumM+funnel_m[j];
sumX:=SumX+x[j];
if abs(x[j]-funnel_m[j])>0.0000001 then
begin
ss:='|'+funnel_name[j]+'| '+FloatToStrF(funnel_m[j],ffFixed,1000,6)+' | '+FloatToStrF(funnel_min[j],ffFixed,1000,6);
ss:=ss+' | '+FloatToStrF(x[j],ffFixed,1000,7)+' | '+FloatToStrF(x[j]/funnel_m[j],ffFixed,1000,5)+' |';
memo1.lines.Add(ss);
writeln(h,ss);
empty:=false;
end;
end;
ss:='| в сумме: '+FloatToStrF(funnelSumM,ffFixed,1000,6)+' ';
ss:=ss+FloatToStrF(sumX,ffFixed,1000,6)+' | '+ FloatToStrF(sumX/funnelSumM,ffFixed,1000,5)+' |';
if empty then begin
memo1.lines.Add('| Нет выбросов для снижения |');
writeln(h,'| Нет выбросов для снижения |');
end;
if not empty then begin
memo1.lines.Add('- - - - - - - - - - - - - - - - - - - - - - - - - - - - -');
memo1.lines.Add(ss);
writeln(h,'- - - - - - - - - - - - - - - - - - - - - - - - - - - - -');
writeln(h,ss);
end;
memo1.lines.Add('---------------------------------------------------------');
memo1.lines.Add('');
memo1.lines.Add('');
writeln(h,'---------------------------------------------------------');
writeln(h,'');
writeln(h,'');
end else begin
memo1.lines.Add('');
memo1.lines.Add(' Результаты расчета ПДВ (симплекс метод):');
memo1.lines.Add(' ПРИМЕСЬ='+s);
memo1.lines.Add('');
memo1.lines.Add('---------------------------------------------------------');
memo1.lines.Add('| Решение не найдено |');
memo1.lines.Add('---------------------------------------------------------');
writeln(h,'');
writeln(h,' Результаты расчета ПДВ (симплекс метод):');
writeln(h,' ПРИМЕСЬ='+s);
writeln(h,'');
writeln(h,'---------------------------------------------------------');
writeln(h,'| Решение не найдено |');
writeln(h,'---------------------------------------------------------');
end;
closefile(h);
end;
// closefile(h);
end;
end;
//==============================================================================
//поиск файла по маске
procedure FindFiles(StartFolder, Mask: string; List: TStrings;
ScanSubFolders: Boolean = True);
var
SearchRec: TSearchRec;
FindResult: Integer;
begin
List.BeginUpdate;
try
StartFolder := IncludeTrailingBackslash(StartFolder);
FindResult := FindFirst(StartFolder + '*.*', faAnyFile, SearchRec);
try
while FindResult = 0 do
with SearchRec do
begin
if (Attr and faDirectory) <> 0 then
begin
if ScanSubFolders and (Name <> '.') and (Name <> '..') then
FindFiles(StartFolder + Name, Mask, List, ScanSubFolders);
end
else
begin
if MatchesMask(Name, Mask) then begin
List.Add(copy(Name,5,4));
//showmessage(StartFolder + Name);
end;
end;
FindResult := FindNext(SearchRec);
end;
finally
FindClose(SearchRec);
end;
finally
List.EndUpdate;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
DecimalSeparator:=MyDecimalSeparator;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
dir_path:=ReadIni;
edit1.Text:=dir_path;
{--}
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
var
h,h2:textfile;
i,j,k,n:integer;
s_temp:string;
s: array of array of string;
begin
dir_path:=edit1.Text;
checklistbox1.Items.Clear;
i:=0;
AssignFile(h,dir_path+'\WORK\activ2.txt');
reset(h);
//readln(h,s_temp);
while not EOF(h) do begin//чтение файла (установка размера массива)
readln(h,s_temp);
inc(i);
end;
closefile(h);
setlength(s,i,2);
AssignFile(h2,dir_path+'\WORK\activ2.txt');
reset(h2);
for j:=0 to i-1 do begin
readln(h2,s_temp);
s[j,0]:=copy(s_temp,24,4);
s[j,1]:=copy(s_temp,30,55);
end;
closefile(h2);
FindFiles(dir_path, 'htop*.ppp', checklistbox1.items, true);
n:=checklistbox1.items.Count-1;
for j:=0 to n do begin
for k:=0 to i-1 do begin
//showmessage(s[k,0]+' -| ');
if checklistbox1.items[0]=s[k,0] then begin
//showmessage(s[j,0]+' | '+s[j,1]);
checklistbox1.items.Delete(0);
checklistbox1.items.Add(s[k,0]+' '+s[k,1]);
end;
end;
end;
end;
procedure TForm1.N2Click(Sender: TObject);
var
TitleName : string;
lpItemID : PItemIDList;
BrowseInfo : TBrowseInfo;
DisplayName : array[0..MAX_PATH] of char;
TempPath : array[0..MAX_PATH] of char;
begin
FillChar(BrowseInfo, siCeof(TBrowseInfo), #0);
BrowseInfo.hwndOwner := Form1.Handle;
BrowseInfo.psCDisplayName := @DisplayName;
TitleName := 'Please specify a directory';
BrowseInfo.lpsCTitle := PChar(TitleName);
BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;
lpItemID := SHBrowseForFolder(BrowseInfo);
if lpItemId <> nil then
begin
SHGetPathFromIDList(lpItemID, TempPath);
edit1.Text:=TempPath;
GlobalFreePtr(lpItemID);
end;
//showmessage(tempPath);
dir_path:=tempPath;
//FindFiles(tempPath, 'htop*.ppp', checkmemo1.lines, true); //старая версия
SaveIni(dir_path);
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
TitleName : string;
lpItemID : PItemIDList;
BrowseInfo : TBrowseInfo;
DisplayName : array[0..MAX_PATH] of char;
TempPath : array[0..MAX_PATH] of char;
begin
FillChar(BrowseInfo, siCeof(TBrowseInfo), #0);
BrowseInfo.hwndOwner := Form1.Handle;
BrowseInfo.psCDisplayName := @DisplayName;
TitleName := 'Please specify a directory';
BrowseInfo.lpsCTitle := PChar(TitleName);
BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;
lpItemID := SHBrowseForFolder(BrowseInfo);
if lpItemId <> nil then
begin
SHGetPathFromIDList(lpItemID, TempPath);
edit1.Text:=TempPath;
GlobalFreePtr(lpItemID);
end;
//showmessage(tempPath);
dir_path:=tempPath;
//FindFiles(tempPath, 'htop*.ppp', checkmemo1.lines, true); //старая версия
SaveIni(dir_path);
end;
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
i:integer;
begin
for i:=0 to checklistbox1.Items.Count-1 do
checklistbox1.Checked[i]:=true;
end;
procedure TForm1.SpeedButton3Click(Sender: TObject);
var
i:integer;
begin
for i:=0 to checklistbox1.Items.Count-1 do
checklistbox1.Checked[i]:=false;
end;
procedure TForm1.SpeedButton4Click(Sender: TObject);
var
i:integer;
begin
for i:=0 to checklistbox1.Items.Count-1 do
if checklistbox1.Checked[i] then checklistbox1.Checked[i]:=false
else checklistbox1.Checked[i]:=true;
end;
end.
Simplex.pas
unit simplex;
interface
const
SIMPLEX_DONE = 0; // оптимизация успешно завершена
SIMPLEX_NO_SOLUTION = 1; // задача не имеет решения (не удается найти базис)
SIMPLEX_NO_BOTTOM = 2; // решения нет, т.к. линейная форма не ограничена снизу
SIMPLEX_NEXT_STEP = 3; // для получения решения нужно сделать еще хотя бы один шаг
MAX_VAL = 0.1e-12; //точность (значение, удовлетворяющее -MAX_VAL < X < MAX_VAL считается нулем)
type
TOperation = (Equal,Less,Greater);
TExtArray = array of extended;
TConstrain = record
A : TExtArray;
B : extended;
Sign : TOperation;
isT : boolean;
end;
TSimplex = class
M,N : integer; { M - число строк, N - число столбцов}
RealN : integer; {реальное число переменных, изначально вошедших в задачу}
Cons : array of TConstrain;
C : TExtArray;
L : extended;
Basis : array of integer;
Max : boolean; { направление оптимизации: минимизация или максимизация }
Constructor Create(_C:TExtArray; MaximiCe:boolean=false);
Constructor CreateBasis(const Simplex:TSimplex);
Constructor Copy(const Simplex:TSimplex);
Procedure AddCons(_B:extended; _A:TExtArray; Sign:TOperation);
Procedure SetAllLengths(Len:integer);
Function SimplexStep:integer;
Function CheckBasis:boolean;
Function FoundInBasis(num:integer): integer;
Function DoPrec(num:extended): extended;
Procedure NormaliCe;
Procedure MulString(Number:integer; Value:extended);
Procedure AddString(Num1,Num2:integer; Value:extended); {суммирование строки 1 со строкой 2, домноженной на коэффициент Value }
Function Solve:integer;
Function GetMin:extended;
Function GetSolution:TExtArray;
Destructor Free;
end;
TIntSimplex = class(TSimplex)
// CurX : TExtArray;
//CurL : extended;
// CurFound : boolean;
Constructor Create(_C:TExtArray; MaximiCe:boolean=false);
// Procedure DelLastCons;
Function IntSolve:integer;
Function GetIntMin:extended;
Function IsInteger(value:extended):boolean;
Function GetIntSolution:TExtArray;
// Function SearchCons(_B:extended;_A:TExtArray):integer;
end;
implementation
uses Math;
{ TSimplex }
Function TSimplex.DoPrec(num:extended): extended;
begin
if ((num < MAX_VAL) and (num > -MAX_VAL)) then
num := 0;
Result := num;
end;
procedure TSimplex.AddCons(_B: extended; _A: TExtArray; Sign: TOperation);
var
j : integer;
begin
if (Length(_A)>N) then SetAllLengths(Length(_A));
inc(M);
SetLength(Cons,M);
//if ((_B=0) and (Sign=Less)) then Sign:=Equal; //???
Cons[M-1].B:=_B;
Cons[M-1].Sign:=Sign;
SetLength(Cons[M-1].A,N);
for j:=0 to Length(_A)-1 do Cons[M-1].A[j]:=_A[j];
if Length(_A)<N then for j:=Length(_A) to N-1 do Cons[M-1].A[j]:=0;
end;
{суммирование строки 1 со строкой 2, домноженной на коэффициент Value }
procedure TSimplex.AddString(Num1, Num2: integer; Value: extended);
var
j : integer;
begin
for j:=0 to N-1 do Cons[Num1].A[j]:=Cons[Num1].A[j]+Cons[Num2].A[j]*Value;
Cons[Num1].B:=Cons[Num1].B+Cons[Num2].B*Value;
end;
function TSimplex.CheckBasis: boolean;
var
i,j,k : integer;
f : boolean;
begin
SetLength(Basis,M);
for i:=0 to M-1 do Basis[i]:=-1;
for j:=0 to N-1 do begin
f:=true;
k:=-1;
i:=0;
while (f and (i<M)) do begin
if ((Cons[i].A[j]<>0) and (Cons[i].A[j]<>1)) then f:=false;
if (Cons[i].A[j]=1) then begin
if (k=-1) then k:=i
else f:=false;
end;
inc(i);
end;
if (f and (k<>-1)) then Basis[k]:=j;
end;
f:=true;
for i:=0 to M-1 do f:=f and (Basis[i]<>-1);
Result:=f;
end;
constructor TSimplex.Create(_C: TExtArray; MaximiCe:boolean);
var
j : integer;
begin
N:=Length(_C);
RealN := N;
M:=0;
SetLength(C,N);
Max:=MaximiCe;
if (not MaximiCe) then for j:=0 to N-1 do C[j]:=-_C[j]
else for j:=0 to N-1 do C[j]:=_C[j];
Max:=MaximiCe;
L := 0;
end;
constructor TSimplex.Copy(const Simplex: TSimplex);
var
i,j : integer;
begin
M:=Simplex.M;
N:=Simplex.N;
RealN := Simplex.RealN;
SetLength(Cons,M);
SetLength(Basis,M);
SetLength(C,N);
Max:=Simplex.Max;
for i:=0 to M-1 do begin
SetLength(Cons[i].A,N);
Basis[i]:=-1;
for j:=0 to N-1 do Cons[i].A[j]:=Simplex.Cons[i].A[j];
Cons[i].B:=Simplex.Cons[i].B;
Cons[i].Sign:=Simplex.Cons[i].Sign;
end;
for i:=0 to Simplex.N-1 do C[i]:=Simplex.C[i];
L := Simplex.L;
end;
constructor TSimplex.CreateBasis(const Simplex: TSimplex);
var
i,j : integer;
begin
M:=Simplex.M;
N:=Simplex.N;
RealN := Simplex.RealN;
L := 0;
SetLength(Cons,M);
SetLength(Basis,M);
SetLength(C,N);
for i:=0 to N-1 do C[i]:=0;
for i:=0 to M-1 do begin
SetLength(Cons[i].A,N);
for j:=0 to N-1 do Cons[i].A[j]:=Simplex.Cons[i].A[j];
Cons[i].B:=Simplex.Cons[i].B;
Cons[i].Sign:=equal;
Cons[i].isT := false;
end;
for i:=0 to M-1 do begin
if (Simplex.Basis[i]<>-1) then Basis[i]:=Simplex.Basis[i]
else begin
SetAllLengths(N+1);
for j:=0 to M-1 do Cons[j].A[N-1]:=0;
Cons[i].A[N-1]:=1;
Cons[i].isT := true;
C[N-1] := 0;
for j:=0 to Simplex.N-1 do C[j] := C[j] + Simplex.Cons[i].A[j];
L := L + Cons[i].B;
end;
end;
end;
destructor TSimplex.Free;
begin
SetLength(C,0);
SetLength(Basis,0);
SetLength(Cons,0);
M:=0;
N:=0;
RealN := 0;
end;
function TSimplex.GetMin: extended;
var
i : integer;
begin
if (Max) then
Result := -L
else
Result := L;
end;
function TSimplex.GetSolution: TExtArray;
var
Solution : TExtArray;
i,j : integer;
begin
SetLength(Solution,RealN);
for j:=0 to RealN-1 do begin
Solution[j]:=0;
i:=0;
while ((i<M) and (Basis[i]<>j)) do inc(i);
if ((Basis[i]=j) and (i<M)) then Solution[j]:=Cons[i].B;
end;
Result:=Solution;
end;
procedure TSimplex.MulString(Number: integer; Value: extended);
var
j : integer;
begin
for j:=0 to N-1 do Cons[Number].A[j]:=Cons[Number].A[j]*Value;
Cons[Number].B:=Cons[Number].B*Value;
end;
procedure TSimplex.NormaliCe;
var
i : integer;
begin
for i:=0 to M-1 do if (Cons[i].Sign<>Equal) then begin
SetAllLengths(N+1);
if (Cons[i].Sign=Greater) then Cons[i].A[N-1]:=-1
else Cons[i].A[N-1]:=1;
Cons[i].Sign := Equal;
end;
end;
procedure TSimplex.SetAllLengths(Len: integer);
var
i, j : integer;
OldN : integer;
begin
OldN:=N;
N:=Len;
SetLength(C,N);
for i:=0 to M-1 do SetLength(Cons[i].A,N);
if (OldN<N) then begin
for j:=OldN to N-1 do begin
C[j]:=0;
for i:=0 to M-1 do Cons[i].A[j]:=0;
end;
end;
end;
function TSimplex.FoundInBasis(num:integer): integer;
var
i:integer;
f:boolean;
begin
f := false;
i := 0 ;
while (not f and (i<M)) do
begin
f := (Basis[i] = num);
inc(i);
end;
if (f) then
Result := i-1
else
Result := -1;
end;
function TSimplex.SimplexStep: integer;
var
i,j : integer;
f,opt : boolean;
x,y : integer; //координаты опорного элемента
CurMax : extended;
temp : array of TConstrain;
tempC : TExtArray;
begin
opt := true;
CurMax := -1;
for i := 0 to N-1 do
begin
//проверка на разрешимость
if (C[i] > 0) then
begin
opt := false; //а это попутная проверка на оптимальность
if (C[i] > CurMax) then //а это поиск ведущего столбца (максимальный элемент в C[i])
begin
CurMax := C[i];
x := i;
end;
f := true;
for j := 0 to M-1 do
f := f and (Cons[j].A[i] < 0);
if (f) then
begin
Result := SIMPLEX_NO_BOTTOM;
exit;
end;
end;
end;
if (opt) then
Result := SIMPLEX_DONE
else
begin
//зная номер ведущего столбца, ищем номер ведущей строки
CurMax := MaxExtended; //на самом деле тут будем искать минимум, а не Max
for j := 0 to M-1 do
if (Cons[j].A[x] > 0) then //идем только по положительным элементам
if (Cons[j].B/Cons[j].A[x] < CurMax) then
begin
CurMax := Cons[j].B/Cons[j].A[x];
y := j;
end
else if (DoPrec(Cons[j].B/Cons[j].A[x] - CurMax) = 0) then
if (Cons[j].isT) then
y := j;
//сохраняем текущие значения
SetLength(temp, M);
for j := 0 to M-1 do
begin
SetLength(temp[j].A, N);
for i := 0 to N-1 do
temp[j].A[i] := Cons[j].A[i];
temp[j].B := Cons[j].B;
end;
SetLength(tempC, N);
for i := 0 to N-1 do
tempC[i] := C[i];
//делаем пересчет таблицы
//строка делиться на ведущий элемент
MulString(y, 1/Cons[y].A[x]);
//преобразование остальных элементов
for j := 0 to M-1 do
begin
if (j <> y) then
begin
for i := 0 to N-1 do
begin
Cons[j].A[i] := DoPrec(temp[j].A[i] - temp[j].A[x]*temp[y].A[i]/temp[y].A[x]);
end;
Cons[j].B := DoPrec(temp[j].B - temp[j].A[x]*temp[y].B/temp[y].A[x]);
end
else
begin
for i := 0 to N-1 do
Cons[j].A[i] := DoPrec(Cons[j].A[i]);
end;
end;
//и строка с коэффициентами функции
for i := 0 to N-1 do
begin
C[i] := DoPrec(tempC[i] - tempC[x]*temp[y].A[i]/temp[y].A[x]);
end;
Basis[y] := x;
//и сама функция:
L := DoPrec(L - tempC[x]*temp[y].B/temp[y].A[x]);
for i:= 0 to M-1 do
SetLength(temp[i].A, 0);
SetLength(temp, 0);
SetLength(tempC, 0);
Result := SIMPLEX_NEXT_STEP;
end;
end;
function TSimplex.Solve: integer;
var
i,j : integer;
Simplex : TSimplex;
f : boolean;
Step : integer;
cc : extended;
begin
//oldN := N;
NormaliCe;
f:=false;
if (not CheckBasis) then begin
Simplex:=TSimplex.CreateBasis(self);
Simplex.Solve;
f:=Simplex.GetMin<>0;
if (not f) then for i:=0 to M-1 do begin
for j:=0 to N-1 do Cons[i].A[j]:=Simplex.Cons[i].A[j];
Cons[i].B:=Simplex.Cons[i].B;
Cons[i].isT := false;
Basis[i]:=Simplex.Basis[i];
cc := C[Basis[i]];
for j:=0 to N-1 do
C[j] := DoPrec(C[j] - cc*Cons[i].A[j]);
L := DoPrec(L - cc*Cons[i].B);
end;
Simplex.Free;
end;
if (f) then Step:=SIMPLEX_NO_SOLUTION
else repeat
Step:=SimplexStep;
until (Step<>SIMPLEX_NEXT_STEP);
//SetAllLengths(OldN);
Result:=Step;
end;
{ TIntSimplex }
constructor TIntSimplex.Create(_C:TExtArray; MaximiCe:boolean=false);
begin
//CurFound:=false;
inherited;
end;
function TIntSimplex.GetIntMin: extended;
begin
Result:=GetMin;
end;
function TIntSimplex.GetIntSolution: TExtArray;
begin
Result:=GetSolution;
end;
function TIntSimplex.IsInteger(Value:extended):boolean;
begin
Result:=((Value=floor(Value)) or (Value=ceil(Value)));
end;
function TIntSimplex.IntSolve: integer;
var
i : integer;
OldN : integer;
FractCol : integer;
FractRow : integer;
TmpX : TExtArray;
TmpCons : TExtArray;
NewValue : extended;
begin
if (Solve=SIMPLEX_DONE) then begin
//if (not CurFound or ((Simplex.GetMin<CurL) and not Max) or ((Simplex.GetMin>CurL) and Max)) then begin
TmpX:=GetSolution;
i:=0;
while ((i<RealN) and IsInteger(TmpX[i])) do inc(i);
FractCol:=i;
if (FractCol<>RealN) then begin // если найдена хотя бы одна нецелая переменная
OldN:=N;
SetLength(TmpCons,N);
FractRow := FoundInBasis(FractCol);
for i := 0 to N-1 do
if (FoundInBasis(i) = -1) then
TmpCons[i] := Cons[FractRow].A[i] - Floor(Cons[FractRow].A[i])
else
TmpCons[i] := 0;
NewValue := Cons[FractRow].B - Floor(Cons[FractRow].B);
//if (Max) then
AddCons(NewValue, TmpCons, Greater);
//else
// AddCons(NewValue, TmpCons, Less);
Result := IntSolve;
SetAllLengths(OldN); // удаляем пустые столбцы в конце, если они есть
end
else begin // если полученное решение - целочисленное\
Result := SIMPLEX_DONE;
end;
//end;
end
else
Result:=SIMPLEX_NO_SOLUTION;
end;
end.
Подобные документы
Инвентаризация источников выбросов загрязняющих веществ в атмосферу. Разработка нормативов предельно допустимых выбросов для цехов предприятия "Чеширский КОТ". Анализ образования отходов, нормативы шумовых источников воздействия и санитарно-защитной зоны.
курсовая работа [2,1 M], добавлен 21.07.2014Инвентаризация источников выбросов загрязняющих веществ в атмосферу. Мероприятия по снижению негативного воздействия на окружающую среду. Разработка нормативов предельно допустимых выбросов для производственных помещений предприятия ОАО "Тулачермет".
курсовая работа [4,7 M], добавлен 13.03.2011Характеристика предприятия как источника загрязнения атмосферы. Проведение расчетов и определение нормативов предельно допустимых выбросов. Мероприятия по регулированию выбросов при неблагоприятных метеорологических условиях. Контроль за их соблюдением.
курсовая работа [99,5 K], добавлен 12.11.2010Характеристика основных источников загрязняющих веществ гостиничных комплексов. Фильтры гостиничных комплексов. Экологический контроль и мониторинг, их цели, задачи и методы. Этапы инвентаризации источников выбросов. Принцип действия газоанализатора.
дипломная работа [2,8 M], добавлен 06.11.2015Расчёт предельно допустимых выбросов в атмосферу от горячих источников. Определение платы за выброс. Расчёт приземных концентраций загрязняющих веществ при выбросе газовоздушной смеси от одиночного источника. Границы санитарно-защитной зоны предприятия.
курсовая работа [86,6 K], добавлен 12.01.2015Характеристика технологического оборудования котельной как источника загрязнения атмосферы. Расчет параметров выбросов загрязняющих веществ в атмосферу. Использование критериев качества атмосферного воздуха при нормировании выбросов вредных веществ.
курсовая работа [290,1 K], добавлен 18.02.2013- Разработка проекта предельно-допустимых выбросов в атмосферу для стационарного источника загрязнения
Расчет выбросов оксидов азота, оксидов серы, оксида углерода и твердых загрязняющих веществ. Организация санитарно-защитной зоны. Разработка мероприятий по снижению выбросов загрязняющих веществ в атмосферу. Определение графика контроля за выбросами.
курсовая работа [1,3 M], добавлен 02.05.2012 Воздействие на атмосферу загрязняющих веществ, возникающих при сжигании каменного угля. Методы очистки отходящих газов. Применение электрофильтров при очистке дымовых выбросов. Расчет предельно допустимых выбросов для предприятия теплоэнергетики.
курсовая работа [1,7 M], добавлен 13.01.2015Элементы котельной установки. Расчет и предельно допустимые концентрации количества дымовых газов, количеств загрязняющих веществ, загрязнения атмосферного воздуха. Мероприятия по сокращению выбросов загрязняющих веществ в атмосферу населенных пунктов.
курсовая работа [168,5 K], добавлен 07.11.2012Нормирование выбросов загрязняющих веществ в окружающую среду путем установления предельно допустимых выбросов этих веществ в атмосферу. Расчет концентрации двуокиси серы, окислов азота, золы. Мероприятия по уменьшению выбросов загрязняющих веществ.
контрольная работа [112,5 K], добавлен 19.03.2013