Графическое решение задач линейного программирования
Требования к функциям, выполняемым системой, программно-аппаратному и техническому обеспечению, к эргономике и технической эстетике, надежности и хранению информации. Схема взаимодействия модулей. Структурная схема программы. Наиболее вероятные ошибки.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 19.05.2014 |
Размер файла | 541,3 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Содержание
Введение
1. Постановка задачи
1.1 Требования к функциям, выполняемым системой
1.2 Требования к программно-аппаратному обеспечению
1.3 Требования к техническому обеспечению
1.4 Требования к эргономике и технической эстетике
1.5 Требования к надежности и хранению информации
2. Основная часть
2.1 Математическая модель
2.2 Метод решения задачи
2.3 Структурная схема программы
2.4 Схема взаимодействия модулей
3. Руководство программисту
4. Руководство пользователю
4.1 Общие сведения
4.2 Работа с помощью
4.3 Наиболее вероятные ошибки
Заключение
Список использованных источников
Приложение А - Текст программы
Приложение Б - Формы программы
Аннотация
Курсовой проект на тему «Графическое решение задач линейного программирования» содержит введение, четыре главы, заключение и приложения, которые состоят из текста, формы программы и диска с программой.
Программный продукт разработан в среде программирования Borland Delphi 7. Данная программа предназначена для получения практических навыков в разработке программных средств с использованием современных алгоритмических языков программирования и информационных технологий, стандартизации основных этапов жизненного цикла программных средств, стандартизации документирования программных средств, обеспечении надежности и качества функционирования программных средств, использовании методов тестирования программного обеспечения.
Имеется удобный и понятный интерфейс для работы с программой.
Введение
Линейное программирование - это раздел математики ориентируемый на нахождении экстремума в задачах, которые описываются линейными уравнениями.
Графический способ решения задач линейного программирования целесообразно использовать для решения задач с двумя переменными, когда ограничения выражены неравенствами.
Задачи курсового проекта:
- изучить теоретический материал по теме работы;
- описать создание программного продукта по теме работы.
1. Постановка задачи
Составить математическую модель графического решения задач линейного программирования. Описать предъявляемые требования к эргономике и технической эстетики для разработанного интерфейса программы. Разработать программный продукт для графического решения задач линейного программирования.
К основным параметрам функциональных задач в постановке задачи относятся:
1)цель и назначение данной задачи состоит в том, чтобы разработать программный продукт для графического решения задач линейного программирования;
2)условия решения задачи с использованием средств вычислительной техники:
- процессор: Pentium/Celeron/AMD K5- 2400 MHz;
- монитор SVGA, поддерживающий графический режим 1024*768;
- размер ОЗУ 1024Мб;
- свободное пространство на жестком диске не менее 20 Мб;
- видео карта 512 Мб;
- клавиатура;
- мышь;
3)содержание функций обработки входной информации при решения задачи: по введенным данным будет производиться расчет задачи;
4)требование к периодичности решения задачи: данный программный продукт будет использоваться по требованию оператора;
5)ограничение по срокам и точностям выходной информации: информация предоставляется сразу после завершения процесса обработки входной информации;
6)состав и форма представления выходной информации: выходные данные выводятся на экран;
7)источники входной информации для решения задачи: данные о технических характеристиках компьютеров;
8)пользователи задачи: программный продукт рассчитан на конечного пользователя.
1.1 Требования к функциям, выполняемым системой
Разработанный программный продукт «Графическое решение задач линейного программирования» должен удовлетворять эргономическим требованиям, требованиям к программно-аппаратному окружению, а также требованиям к надежности и хранению информации.
Обладать автоматизированным сбором информации, представлять информацию в более удобном виде.
В программном продукте реализованы следующие функции:
- решение задачи;
- справка.
1.2 Требования к программно-аппаратному обеспечению
Программное обеспечение должно удовлетворять следующим требованиям:
- возможность экономично и целесообразно использовать предоставляемую память;
- включать в себя проверку целостности данных;
- при возникновении ошибок выдавать сообщения, отражающие суть ошибок, облегчающее их исправление.
Для корректной работы с программным продуктом необходимо наличие следующих минимальных конфигураций аппаратного окружения :
- операционная система Windows XP, Windows 7 Ultimate;
- Delphi 7;
- Microsoft Office 2003, 2007.
1.3 Требования к техническому обеспечению
Для работы с программным продуктом необходимо наличие следующих минимальных конфигураций аппаратного окружения:
- процессор Intel Atom N570 CPU 3.2 GHz;
- RAM - 1Gb;
- HDD - 120Gb;
- клавиатура;
- мышь;
- монитор LG G2225HQ.
1.4 Требования к эргономике и технической эстетике
Эргономика представляет собой научную дисциплину, комплексно изучающую человека в конкретных условиях его деятельности. Возникшая на стыке общественных, технических и естественных наук, она является одновременно и проектной, и научной дисциплиной.
Взаимодействие пользователей с прикладным программным обеспечением, входящим в состав системы должно осуществляться посредством визуального графического интерфейса. Интерфейс системы должен быть понятным и удобным, не должен быть перегружен графическими элементами и должен обеспечивать быстрое отображение экранных форм. Навигационные элементы должны быть выполнены в удобной для пользователя форме. Средства редактирования информации должны удовлетворять принятым соглашениям в части использования функциональных клавиш, режимов работы, поиска, использования оконной_ системы. Ввод-вывод данных системы, прием управляющих команд и отображение результатов их исполнения должны выполняться в интерактивном режиме. Интерфейс должен соответствовать современным. эргономическим требованиям и обеспечивать удобный доступ к основным функциям и операциям системы.
Интерфейс должен быть рассчитан на преимущественное использование манипулятора типа «мышь», то есть управление системой должно осуществляться с помощью набора экранных меню, кнопок, значков и т. п. элементов. Клавиатурный режим ввода должен используется главным образом при заполнении и/или редактировании текстовых и числовых полей экранных форм. Все надписи экранных форм, а также сообщения, выдаваемые пользователю (кроме системных сообщений) должны быть на русском языке.
Система должна обеспечивать корректную обработку аварийных ситуаций, вызванных неверными действиями пользователей, неверным форматом или недопустимыми значениями входных данных. В указанных
случаях система должна выдавать пользователю соответствующие сообщения, после чего возвращаться в рабочее состояние, предшествовавшее неверной (недопустимой) команде или некорректному вводу данных.
Экранные формы должны проектироваться с учетом требований унификации:
- все экранные формы пользовательского интерфейса должны быть выполнены в едином графическом дизайне, с одинаковым расположением основных элементов управления и навигации;
- для обозначения сходных операций должны использоваться сходные графические значки, кнопки и другие управляющие (навигационные) элементы. Термины, используемые для обозначения типовых операций (добавление информационной сущности, редактирование поля данных), а также последовательности действий пользователя при их выполнении, должны быть унифицированы;
- внешнее поведение сходных элементов интерфейса (реакция на наведение указателя «мыши», переключение фокуса, нажатие кнопки) должны реализовываться одинаково для однотипных элементов.
1.5 Требования к надежности и хранению информации
Надежность - это одно из важнейших свойств программного продукта, обеспечение которого даёт возможность предусмотреть различные ситуации, когда операционная система или пользователь не могут корректно работать с программой. Например, неправильный ввод (текст вместо цифр), не поддерживаемая операционная система и т.д.
Вся система должна обладать надёжностью, необходимо предусмотреть, самые неожиданные действия пользователя и если они неправильны, программа должна объяснить, как сделать то, чего хочет программа от пользователя.
Данный программный продукт характеризуется высокой степенью_ надежности хранения информации. При некорректных действиях
пользователя программа не должна производить аварийное завершение_ работы, потому что это повлечет за собой потерю данных, а_ соответствующим образом обрабатывать эти действия, не прерывая нормальный ход программы.
Помимо этого в программе предусмотрено жесткий контроль вводимой информации, для сокращения случайных ошибок пользователя.
Хранение программного продукта может осуществляться на любом магнитном или оптическом носителе информации. В нашем случае применены компакт диски CD-R/DWD-R и Flash - носители.
Следует признать, что абсолютно надежных программ не существует, так как абсолютная степень надежности не может быть теоретически доказана и, следовательно, недостижима. Описанные модели представляют теоретический подход и, как правило, имеют ограниченное применение.
Типовая структура характеристик и атрибутов качества для оценивания исполняемого программного обеспечения, применяемые метрики, соответствующие виды, испытаний и методы измерений в методике представляются в таблицах.
Регистрация означает протоколирование выявляемых в процессе оценивания событий или проявлений ошибок (недостатков, нарушений требований).
Программная документация, в общем виде, должна удовлетворять следующим требованиям:
- соответствие требованиям стандартов единой системы программной документации;
- понятность документации;
- полнота документации;
- возможность освоения программного обеспечения по документации;
- возможность освоения программного обеспечения на контрольном примере;
- легкость установки и запуска программного обеспечения;
- понятность входных и выходных данных;
- наличие описания структуры функций программного обеспечения;
- соответствие функций программного обеспечения требованиям
техническому заданию;
- наличие описания функций программного обеспечения;
- отсутствие противоречий в реализации интерфейса с пользователем;
- отсутствие противоречий в диагностике системы;
- обеспечение помощи пользователю при затруднениях средствами
функции подсказки;
- достаточность документации для ввода программного обеспечения в
эксплуатации;
- правильность документации;
- приемлемость уровня технического исполнения документации;
- наличие краткой аннотации программного обеспечения;
- наличие описания решаемых задач;
- наличие описания ограничении по применению;
- наличие описания алгоритмов.
2. Основная часть
2.1 Математическая модель
Математическая модель - это математическое представление реальности.
Математическое моделирование - это процесс построения и изучения математических моделей.
Все естественные и общественные науки, использующие математический аппарат, по сути, занимаются математическим моделированием: заменяют реальный объект его математической моделью и затем изучают последнюю.
Графический способ решения ЗЛП целесообразно использовать для решения задач с двумя переменными, когда ограничения выражены системой неравенств 1:
(1)
x1 ? 0, x2 ? 0
2.2 Метод решения задачи
Алгоритм графического способа решения задач линейного программирования заключается:
1) Построить прямые уравнения, которые получаются в результате замены в ограничения знаков неравенств на знаки равенств;
2) Найти полуплоскости, определяемые каждым из ограничений задачи;
3) Определить многоугольник решений;
4) Построить вектор = (c1;c2) - вектор градиент;
5) Построить прямую F = c1x1 + c2x2 = 0, проходящую через начало координат и перпендикулярную вектору ;
6) Передвигать прямую F в направлении вектора , в результате чего либо находят точку, в которой целевая функция принимает экстремум (максимум или минимум), либо устанавливают неограниченность функции на множестве планов;
7) Определить координаты точки экстремума функции и вычислить значение целевой функции в этой точки.
Пример. Предприятие изготавливает два вида продукции - П1 и П2, которая поступает в оптовую продажу. Для производства продукции используются два вида сырья - А и В. Максимально возможные запасы сырья в сутки составляют 9 и 13 единиц соответственно. Расход сырья на единицу продукции вида П1 и вида П2 дан в таблице 1.
Таблица 1 - Расход сырья продукции
Сырье |
Расход сырья на 1 ед. продукции |
Запас сырья, ед. |
||
П1 |
П2 |
|||
А В |
2 3 |
3 2 |
9 13 |
Опыт работы показал, что суточный спрос на продукцию П1 никогда не превышает спроса на продукцию П2 более чем на 1 ед. кроме того, известно, что спрос на продукцию П2 никогда не превышает 2 ед. в сутки.
Оптовые цены единицы продукции равны: 3д.е. - для П1 4 д.е. для П2.
Какое количество продукции каждого вида должно производить предприятие, чтобы доход от реализации продукции был максимальным?
Решение: Для построения математической модели остается только идентифицировать переменные и представить цель и ограничения в виде математических функций этих переменных.
Предположим, что предприятие изготовит х1 единиц продукции П1 и х2 единиц продукции П2. поскольку производство продукции П1 и П2 ограничено имеющимися в распоряжении в распоряжении предприятия сырьем каждого вида и спросом на данную продукцию, а также учитывая, что количество изготавливаемых изделий не может быть отрицательным, должна выполняться система неравенств 2:
2х1 + 3х2 9;
3х1 + 2х2 13;
х1 - х2 1; (2)
х2 2;
х1 0; х2 0.
Доход от реализации х1 единиц продукции П1 и х2 продукции П2 составит F = 3x1 + 4x2.
Таким образом, мы приходим к следующей математической задаче: среди всех неотрицательных решений данной системы линейных неравенств требуется найти такое, при котором функция F принимает максимальное значение Fmax .
Найдем решение данной задачи графическим способом.
Построим многоугольник решений. Для этого в системе координат Х10Х2 на плоскости изобразим граничные прямые L1, L2, L3, L4:
2х1 + 3х2 = 9 (L1);
3х1 + 2х2 = 13 (L2);
х1 - х2 = 1 (L3);
х2 = 2 (L4).
Для построения прямой Z = 3х1 + 4х2 = 0 строим вектор-градиент С = (3;4) и через точку 0 проводим прямую, перпендикулярную ему. Построенную прямую Z = 0 перемещаем параллельно самой себе в направление вектора С. Из рисунка 9 следует, что по отношению к многоугольнику решений опорной эта прямая становится в точке С, где функция принимает максимальное значение. Точка С лежит на пересечении прямых L1 и L3. для определения ее координат решим систему уравнений 1:
2х1 + 3х2 = 9;
х1 - х2 = 1. (1)
Оптимальный план задачи х1 = 2,4; х2 = 1,4. подставляя значения х1 и х2 в линейную функцию, получим равенство 1:
Zmax = 3 * 2,4 + 4 * 1,4 = 12,8. (1)
Полученное решение означает, что объем производства продукции П1 должен быть равен 2,4 ед., а продукции П2 - 1,4 ед. доход, получаемый в этом случае, составит: Z = 12,8 д.е. Ответ показан на рисунке 1:
Размещено на http://www.allbest.ru/
Рисунок 1 - Геометрическая интерпретация решения задач линейного программирования
2.3 Структурная схема программы
Программный продукт имеет конструкцию построения - состав и взаимосвязь программный модулей. Пример структурной схемы программы представлен на рисунке 2.
Рисунок 2 - Структурная схема программы
2.4 Схема взаимодействия модулей
Программа содержит 4 модуля. Схема взаимодействия модулей программы изображена на рисунке 3.
Рисунок 3 - Схема взаимодействия модулей
3. Руководство программисту
Данный программный продукт написан в среде визуального программирования Borland Delphi 7 и был основан на модульном программировании. В программе используются стандартные компоненты Delphi, с помощью которых осуществляется её реализация. Программа включает в себя следующие файлы:
- graph_simplex.dpr - содержит общее описание проекта;
- graph_simplex.cfg - содержит параметры и настройки компилятора;
- graph_simplex.dof - содержит параметры и настройки проекта;
- graph_simplex.res - файл ресурсов;
- graph_simplex.exe - исполнимый файл;
- файлы с расширением *.pas - файлы модулей которые содержат код программы;
- файлы с расширением *.dfm - файлы в которых находится описание окон;
- файлы с расширением *.dcu - результат преобразования текста модулей в машинные инструкции.
Все вышеперечисленные файлы необходимы для правильной организации программы. Переименование или удаление любого из файлов приведет к сбою в работе программы.
Программы включает в себя 4 модуля каждый из которых выполняют определенные функции:
MainForm - рабочая среда программы;
NewTaskForm - новая задача ;
TaskSizeForm - новая симплекс - таблица ;
AboutForm - вызов справки
Для начала работы с программой нужно запустить файл graph_simplex.exe.
Текст программы представлен в приложении А.
4. Руководство пользователю
4.1 Общие сведения
Данная программа предназначена для графического решения задач линейного программирования.
Для начала работы с программой необходимо запустить файл graph_simplex.exe.
Для запуска программы выбрать вкладку «Задача». В появившемся окне ввести информацию из задачи в новую симплекс-таблицу, после чего нажать «ОК». Далее следует выбрать выбрать критерий минимизации и максимизации, после чего на главном окне появятся графическое решение и уравнения решения данной задачи
Для получения справочной информации по программе следует после запуска программы щелкнуть по вкладке «Справка».
Работу программы можно посмотреть в приложении Б.
4.2 Работа с помощью
В программном продукте предоставлена справка, в которой написано назначение программы и информация о разработчике.
Для вызова справки нужно выбрать на панели инструментов пункт «Справка».
1) Справка «О программе» (рисунок 4).
Рисунок 4 - Справка «О программе»
4.3 Наиболее вероятные ошибки
В процессе работы с программой появляются сообщения об ошибках, случае если не все поля заполнены.
Окно ошибки при не правильном выборе количества ограничений показано на рисунке 5:
Рисунок 5 - Окно ошибки при не правильном выборе количества ограничений
Заключение
В курсовом проекте изложен теоретический материал по теме «Графическое решение задач линейного программирования», приведен пример решения задач данным методом.
Результатом курсового проекта является программный продукт, выполненный в среде программирования Borland Delphi 7, с использованием дополнительных компонентов, и разработан по всем правилам разработки программного продукта.
Были получены и закреплены знания по дисциплине «Математические методы». Полученные знания и навыки за время выполнения курсового проекта в дальнейшем будут применяться в разработке программ.
Таким образом, цель курсового проекта достигнута, задачи выполнены.
Приложение A
Текст программы
program graph_simplex;
{$IFDEF VER240}
{$R 'theory.res' '..\docs\theory.rc'}
{$ELSE}
{$R '..\bin\theory.res'}
{$ENDIF}
uses
Forms,
NewTaskFormUnit in 'forms\NewTaskForm\NewTaskFormUnit.pas' {NewTaskForm},
MainFormUnit in 'forms\MainForm\MainFormUnit.pas' {MainForm},
TaskSizeFormUnit in 'forms\TaskSizeForm\TaskSizeFormUnit.pas' {TaskSizeForm},
AboutFormUnit in 'forms\AboutForm\AboutFormUnit.pas' {AboutForm};
{$R *.res}
begin
Application.Initialize;
{$IF CompilerVersion > 18.5}
Application.MainFormOnTaskbar := True;
{$IFEND}
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
unit MainFormUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, Menus, ExtCtrls,
ActnList, StdCtrls, MSimplexMath, ComCtrls,
Math, ToolWin, ImgList, Buttons, OleCtrls, ActiveX,
MSHTML, SHDocVw;
type
TPointd = record
x: Double;
y: Double;
end;
TMainForm = class(TForm)
MainMenu: TMainMenu;
miTask: TMenuItem;
miExit: TMenuItem;
miHelp: TMenuItem;
miAbout: TMenuItem;
LeftPanel: TPanel;
PaintBox: TPaintBox;
miNewTask: TMenuItem;
N1: TMenuItem;
ActionList: TActionList;
acNewTask: TAction;
BottomPanel: TPanel;
tbScale: TTrackBar;
ScaleLabel: TLabel;
TaskRichEdit: TRichEdit;
BottomPanel2: TPanel;
cbDrawDirectFunctionDomain: TCheckBox;
cbDrawGrid: TCheckBox;
Bevel1: TBevel;
Bevel2: TBevel;
ToolBar: TToolBar;
ToolButton1: TToolButton;
ToolButton2: TToolButton;
ToolButton3: TToolButton;
cbDrawFunctionDomain: TCheckBox;
ImageList: TImageList;
bmp1: TMenuItem;
acSaveBmp: TAction;
SaveDialog: TSaveDialog;
TaskSpeedButton: TSpeedButton;
TheorySpeedButton: TSpeedButton;
TheoryPanel: TPanel;
TheoryWebBrowser: TWebBrowser;
cbDrawDirectVector: TCheckBox;
TaskTypeComboBox: TComboBox;
procedure miExitClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure PaintBoxPaint(Sender: TObject);
procedure acNewTaskExecute(Sender: TObject);
procedure miAboutClick(Sender: TObject);
procedure tbScaleChange(Sender: TObject);
procedure cbDrawDirectFunctionDomainClick(Sender: TObject);
procedure cbDrawGridClick(Sender: TObject);
procedure cbDrawFunctionDomainClick(Sender: TObject);
procedure acSaveBmpExecute(Sender: TObject);
procedure cbDrawDirectVectorClick(Sender: TObject);
procedure TaskSpeedButtonClick(Sender: TObject);
procedure TheorySpeedButtonClick(Sender: TObject);
procedure TaskTypeComboBoxChange(Sender: TObject);
private
FM: Integer;
FTaskType: Integer;
A: TMatrix;
B: TVector;
C: TVector;
S: array of Integer;
что x1 >= 0; x2 >= 0;
FX1X2Positive: boolean;
sx, sy: Double;
FTaskSolved: Boolean;
FTaskInfinite: Boolean;
FWidthdiv2: Integer;
FHeightdiv2: Integer;
FGraphScale: Double;
FPaintBuffer: TBitMap;
FDrawTaskGraph: Boolean;
procedure DrawGraph;
procedure SolveTask;
procedure DrawFunctionDomain;
procedure DrawGrid;
function TestForInfinite(ALine1, ALine2: TVector; AMinMaxValue: Double): Boolean;
procedure DrawDirectVector;
function LineToPoint(a1, b1, c1: Double; a2, b2, c2: Double; var x,y: Double):Boolean;
function GetSignStr(Index: Integer): string;
function PointBelongsRest(x, y: Double; ARestIndex: Integer; x1x2positive: boolean): boolean;
function PointBelongsRestDomain(x, y: Double; x1x2positive: boolean): boolean;
procedure WMErasebkgnd(var Msg: TWMErasebkgnd); message WM_ERASEBKGND;
function GetGraphScale: Double;
public
property GraphScale: Double read GetGraphScale;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
uses
TaskSizeFormUnit, NewTaskFormUnit, AboutFormUnit;
function GetTempDirPath: string;
var
EnvStr: string;
ReturnSize: integer;
begin
SetLength(EnvStr, 256);
ReturnSize:=GetEnvironmentVariable('temp', PChar(EnvStr), 256);
SetLength(EnvStr, returnsize);
if returnsize > 0 then begin
Result:=EnvStr;
end else begin
Result:='';
end;
end;
function CheckForSlash(AString: string): string;
var
LString: string;
begin
if AString <> '' then begin
LString:=Trim(AString);
if LString[Length(LString)] <> PathDelim then begin
LString:=LString + PathDelim;
end;
Result:=LString;
end else begin
Result:='';
end;
end;
procedure WriteInRichEd(RichEd: TRichEdit; S: string; Color: TColor; ASize: Integer; Style: TFontStyles);
begin
RichEd.SelStart := Length(RichEd.Text);
RichEd.SelAttributes.Color := Color;
RichEd.SelAttributes.Style := Style;
RichEd.SelAttributes.Size := ASize;
RichEd.SelText := S;
end;
function PointInRect(APoint: TPoint; ARect: TRect): Boolean;
begin
Result := (APoint.X > ARect.Left) and (APoint.Y > ARect.Top) and (APoint.X < ARect.Right) and (APoint.Y < ARect.Bottom);
end;
function CheckForNil(AValue: Double): Double;
begin
if AValue = 0 then
begin
Result := 1;
end else
begin
Result := AValue;
end;
end;
function CheckOne(AValue: Double): string;
begin
if AValue = 1 then
begin
Result := '';
end else
begin
if AValue = - 1 then
begin
Result := '-';
end else
begin
Result := FloatToStr(AValue);
end;
end;
end;
function CheckMinusPlus(AValue: Double): string;
begin
if AValue < 0 then
begin
Result := CheckOne(AValue);
end else
begin
Result := '+' + CheckOne(AValue);
end;
end;
function TMainForm.GetSignStr(Index: Integer): string;
begin
case S[Index] of
0: Result := '=';
1: Result := '>=';
2: Result := '<=';
end;
end;
true,
function TMainForm.LineToPoint(a1, b1, c1: Double; a2, b2, c2: Double; var x,y: Double):Boolean;
var
d: Double;
dx: Double;
dy: Double;
begin
d := a1 * b2 - b1 * a2;
if d <> 0 then
begin
Result := true;
dx := -c1 * b2 + b1 * c2;
dy := -a1 * c2 + c1 * a2;
x := - dx / d;
y := - dy / d;
end else
begin
Result := false;
end;
end;
procedure TMainForm.acNewTaskExecute(Sender: TObject);
var
i: Integer;
LNewTaskForm: TNewTaskForm;
LTaskSizeForm: TTaskSizeForm;
begin
LTaskSizeForm := TTaskSizeForm.Create(nil);
try
if LTaskSizeForm.ShowModal = mrOk then
begin
LNewTaskForm := TNewTaskForm.Create(nil);
try
LNewTaskForm.N := 2;
FM := LTaskSizeForm.M;
LNewTaskForm.M := LTaskSizeForm.M;
if LNewTaskForm.ShowModal = mrOk then
begin
TaskTypeComboBox.Enabled := true;
FTaskType := LNewTaskForm.cbTaskType.ItemIndex;
TaskTypeComboBox.ItemIndex := LNewTaskForm.cbTaskType.ItemIndex;
SetLength(S, FM);
for i := 0 to FM - 1 do
begin
S[i] := LNewTaskForm.Sign[i];
end;
A := LNewTaskForm.NMatrix;
B := LNewTaskForm.Vectorb;
C := LNewTaskForm.Vectorc;
SolveTask;
FDrawTaskGraph := true;
Repaint;
end;
finally
LNewTaskForm.Free;
end;
end;
finally
LTaskSizeForm.Free;
end;
end;
procedure TMainForm.acSaveBmpExecute(Sender: TObject);
begin
if SaveDialog.Execute then
begin
FPaintBuffer.SaveToFile(SaveDialog.FileName);
end;
end;
procedure TMainForm.cbDrawDirectFunctionDomainClick(Sender: TObject);
begin
Repaint;
end;
procedure TMainForm.cbDrawDirectVectorClick(Sender: TObject);
begin
Repaint;
end;
procedure TMainForm.cbDrawFunctionDomainClick(Sender: TObject);
begin
Repaint;
end;
procedure TMainForm.cbDrawGridClick(Sender: TObject);
begin
Repaint;
end;
// Процедура рисования направляющего вектора
procedure TMainForm.DrawDirectVector;
var
x, y: Double;
x1, y1: Double;
x2, y2: Double;
x3, y3: Double;
xp, yp: Double;
LAlpha: Double;
xp1, yp1: Double;
begin
if (C[0] = 0) and (C[1] = 0) then
begin
Exit;
end;
x := C[0];
y := C[1];
if x <> 0 then x1 := x / sqrt(sqr(x) + sqr(y));
if y <> 0 then y1 := y / sqrt(sqr(x) + sqr(y));
x := x1;
y := y1;
if FWidthdiv2 < FHeightdiv2 then
begin
xp := FWidthdiv2 + (x * FWidthdiv2);
yp := FHeightdiv2 + ( - y * FWidthdiv2);
end else
begin
xp := FWidthdiv2 + (x * FHeightdiv2);
yp := FHeightdiv2 + ( - y * FHeightdiv2);
end;
// Рисуем линию
FPaintBuffer.Canvas.Pen.Width := 2;
FPaintBuffer.Canvas.Pen.Color := clRed;
FPaintBuffer.Canvas.Font.Color := clRed;
FPaintBuffer.Canvas.MoveTo(FWidthdiv2, FHeightdiv2);
FPaintBuffer.Canvas.LineTo(Round(xp), Round(yp));
// Рисуем стрелки
xp1 := - 1 * x * 20;
yp1 := y * 20;
LAlpha := 15 * pi / 180;
x := xp1 * Cos(LAlpha) - yp1 * Sin(LAlpha);
y := xp1 * Sin(LAlpha) + yp1 * Cos(LAlpha);
x2 := xp + x;
y2 := yp + y;
FPaintBuffer.Canvas.MoveTo(Round(xp), Round(yp));
FPaintBuffer.Canvas.LineTo(Round(x2), Round(y2));
x3 := x2;
y3 := y2;
LAlpha := - 15 * pi / 180;
x := xp1 * Cos(LAlpha) - yp1 * Sin(LAlpha);
y := xp1 * Sin(LAlpha) + yp1 * Cos(LAlpha);
x2 := xp + x;
y2 := yp + y;
FPaintBuffer.Canvas.MoveTo(Round(xp), Round(yp));
FPaintBuffer.Canvas.LineTo(Round(x2), Round(y2));
FPaintBuffer.Canvas.MoveTo(Round(x2), Round(y2));
FPaintBuffer.Canvas.LineTo(Round(x3), Round(y3));
end;
procedure TMainForm.DrawFunctionDomain;
var
j: Integer;
x, y: Double;
LAlpha: Double;
x1, y1: Double;
x2, y2: Double;
x3, y3: Double;
p1, p2: TPoint;
LAngle: Double;
OfsX, OfsY: Double;
LPointIndex: Integer;
LSegmentLength: Double;
LDomainDirection: Integer;
LPoints: array[1..4] of TPointd;
begin
P1(x1; y1) Рё P2(x2; y2)
x = (x1 + x2) / 2; y = (y1 + y2) / 2;
{P1P2}.
(l,m): l(x-x0)+m(y-y0)=0.
for j := 0 to FM - 1 do
begin
if (A[j, 0] = 0) and (A[j, 1] = 0) then
begin
Continue;
end;
// 0 - '=';
// 1 - '>=';
// 2 - '<=';
if S[j] <> 0 then
begin
LPointIndex := 1;
if A[j, 1] <> 0 then
begin
x := FWidthdiv2 / GraphScale;
y := (B[j] - (A[j, 0] * x)) / A[j, 1];
if Abs(y) <= (FHeightdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
LPointIndex := LPointIndex + 1;
end;
end;
if A[j, 1] <> 0 then
begin
x := - FWidthdiv2 / GraphScale;
y := (B[j] - (A[j, 0] * x)) / A[j, 1];
if Abs(y) <= (FHeightdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
LPointIndex := LPointIndex + 1;
end;
end;
if A[j, 0] <> 0 then
begin
y := FHeightdiv2 / GraphScale;
x := (B[j] - (A[j, 1] * y)) / A[j, 0];
if Abs(x) <= (FWidthdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
LPointIndex := LPointIndex + 1;
end;
end;
if A[j, 0] <> 0 then
begin
y := - FHeightdiv2 / GraphScale;
x := (B[j] - (A[j, 1] * y)) / A[j, 0];
if Abs(x) <= (FWidthdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
end;
end;
x1 := LPoints[1].x;
y1 := LPoints[1].y;
x2 := LPoints[2].x;
y2 := LPoints[2].y;
if A[j, 0] <> 0 then
begin
x := x1 + 0.25;
y := ((x - x1) / A[j, 0]) * A[j, 1] + y1;
end else
begin
y := y1 + 0.25;
x := ((y - y1) / A[j, 1]) * A[j, 0] + x1;
end;
case S[j] of
1: begin // 1 - '>=';
if ((A[j, 0] * x) + (A[j, 1] * y)) >= B[j] then
begin
LDomainDirection := 1;
end else
begin
LDomainDirection := - 1;
end;
end;
2: begin // 2 - '<=';
if ((A[j, 0] * x) + (A[j, 1] * y)) <= B[j] then
begin
LDomainDirection := 1;
end else
begin
LDomainDirection := - 1;
end;
end;
end;
FPaintBuffer.Canvas.Pen.Width := 1;
FPaintBuffer.Canvas.Pen.Color := clBlue;
FPaintBuffer.Canvas.Pen.Style := psSolid;
if x1 > x2 then
begin
x3 := x2;
y3 := y2;
x2 := x1;
y2 := y1;
x1 := x3;
y1 := y3;
end;
OfsX := x1 * GraphScale;
OfsY := y1 * GraphScale;
LSegmentLength := Sqrt(Sqr(y2 - y1) + Sqr(x2 - x1));
if cbDrawFunctionDomain.Checked then
begin
LAlpha := 0;
while True do
begin
x3 := OfsX + (x2 - x1) * LAlpha;
y3 := OfsY + (y2 - y1) * LAlpha;
LAlpha := LAlpha + 7 / LSegmentLength;
if A[j, 0] <> 0 then
begin
x := x3 + 2 * LDomainDirection;
y := ((x - x3) / A[j, 0]) * A[j, 1] + y3;
end else
begin
y := y3 + 2 * LDomainDirection;
x := ((y - y3) / A[j, 1]) * A[j, 0] + x3;
end;
p1.X := FWidthdiv2 + Round(x3);
p1.Y := FHeightdiv2 + Round(- y3);
p2.X := FWidthdiv2 + Round(x);
p2.Y := FHeightdiv2 + Round(- y);
if (PointBelongsRestDomain(x / GraphScale, y / GraphScale, FX1X2Positive)) or
(PointBelongsRest(x / GraphScale, y / GraphScale, j, FX1X2Positive) and (not FTaskSolved) and (not FTaskInfinite)) then
begin
if FPaintBuffer.Canvas.Pixels[p2.X, p2.Y] <> clMoneyGreen then
begin
FPaintBuffer.Canvas.Brush.Color := clMoneyGreen;
FPaintBuffer.Canvas.Brush.Style := bsSolid;
FPaintBuffer.Canvas.FloodFill(p2.X, p2.Y, clWhite, fsSurface);
end;
end;
if y2 < y1 then
begin
if (p2.X > FPaintBuffer.Width) or (p2.Y > FPaintBuffer.Height) then
begin
Break;
end;
end else
begin
if (p2.X > FPaintBuffer.Width) or (p2.Y < 0) then
begin
Break;
end;
end;
end;
end;
if cbDrawDirectFunctionDomain.Checked then
begin
LAlpha := 0;
while True do
begin
x3 := OfsX + (x2 - x1) * LAlpha;
y3 := OfsY + (y2 - y1) * LAlpha;
LAlpha := LAlpha + 7 / LSegmentLength;
if A[j, 0] <> 0 then
begin
LAngle := ArcTan(A[j, 1] / A[j, 0]) * 180 / pi;
if Abs(LAngle) <= 45 then
begin
if LAngle < 0 then x := x3 + 10 * - LDomainDirection else x := x3 + 10 * LDomainDirection;
y := ((x - x3) / A[j, 0]) * A[j, 1] + y3;
end else
begin
if LAngle < 0 then y := y3 + 10 * - LDomainDirection else y := y3 + 10 * LDomainDirection;
x := ((y - y3) / A[j, 1]) * A[j, 0] + x3;
end;
end else
begin
y := y3 + 10 * LDomainDirection;
x := ((y - y3) / A[j, 1]) * A[j, 0] + x3;
end;
p1.X := FWidthdiv2 + Round(x3);
p1.Y := FHeightdiv2 + Round(- y3);
p2.X := FWidthdiv2 + Round(x);
p2.Y := FHeightdiv2 + Round(- y);
FPaintBuffer.Canvas.MoveTo(p1.X, p1.Y);
FPaintBuffer.Canvas.LineTo(p2.X, p2.Y);
if y2 < y1 then
begin
if (p2.X > FPaintBuffer.Width) or (p2.Y > FPaintBuffer.Height) then
begin
Break;
end;
end else
begin
if (p2.X > FPaintBuffer.Width) or (p2.Y < 0) then
begin
Break;
end;
end;
end;
end;
end;
end;
end;
procedure TMainForm.DrawGraph;
var
MaxX: Double;
MaxY: Double;
x, y: Double;
x1, y1: Double;
x2, y2: Double;
i, j: Integer;
MaxValue1: Double;
MaxValue2: Double;
LPointIndex: Integer;
LPoints: array[1..4] of TPointd;
begin
if FDrawTaskGraph then
begin
// Р'ычисляем масштаб графика
MaxX := 0;
MaxY := 0;
for i := 0 to FM - 1 do
begin
if (A[i, 0] = 0) and (A[i, 1] = 0) then
begin
Continue;
end;
if A[i, 0] <> 0 then
begin
x := B[i] / A[i, 0];
end else
begin
x := 0;
end;
if A[i, 1] <> 0 then
begin
y := B[i] / A[i, 1];
end else
begin
y := 0;
end;
if Abs(x) > MaxX then
begin
MaxX := Abs(x);
end;
if Abs(y) > MaxY then
begin
MaxY := Abs(y);
end;
end;
if MaxX <> 0 then
begin
MaxValue1 := (FWidthdiv2 div 2) / MaxX;
end else
begin
MaxValue1 := 1.7e308;
end;
if MaxY <> 0 then
begin
MaxValue2 := (FHeightdiv2 div 2) / MaxY;
end else
begin
MaxValue2 := 1.7e308;
end;
if MaxValue1 < MaxValue2 then
begin
FGraphScale := MaxValue1;
end else
begin
FGraphScale := MaxValue2;
end;
if FGraphScale >= 1000 then
begin
FGraphScale := (FWidthdiv2 div 2) / 3;
end;
end else
begin
FGraphScale := 50;
end;
// Рисуем сетку
DrawGrid;
// Рисуем ось координат
FPaintBuffer.Canvas.Pen.Width := 3;
FPaintBuffer.Canvas.Pen.Color := clBlack;
FPaintBuffer.Canvas.Font.Color := clBlack;
FPaintBuffer.Canvas.Font.Style := [fsBold];
FPaintBuffer.Canvas.MoveTo(FWidthdiv2, FPaintBuffer.Height);
FPaintBuffer.Canvas.LineTo(FWidthdiv2, 0);
FPaintBuffer.Canvas.LineTo(FWidthdiv2 - 5, 10);
FPaintBuffer.Canvas.LineTo(FWidthdiv2 + 5, 10);
FPaintBuffer.Canvas.LineTo(FWidthdiv2, 0);
FPaintBuffer.Canvas.TextOut(FWidthdiv2 + 15, 2, 'x2');
FPaintBuffer.Canvas.MoveTo(0, FHeightdiv2);
FPaintBuffer.Canvas.LineTo(FPaintBuffer.Width, FHeightdiv2);
FPaintBuffer.Canvas.LineTo(FPaintBuffer.Width - 10, FHeightdiv2 - 5);
FPaintBuffer.Canvas.LineTo(FPaintBuffer.Width - 10, FHeightdiv2 + 5);
FPaintBuffer.Canvas.LineTo(FPaintBuffer.Width, FHeightdiv2);
FPaintBuffer.Canvas.TextOut(FPaintBuffer.Width - 20, FHeightdiv2 - 25, 'x1');
FPaintBuffer.Canvas.Font.Style := [];
if FDrawTaskGraph then
begin
// Рисуем прямые ограничений
for j := 0 to FM - 1 do
begin
if (A[j, 0] = 0) and (A[j, 1] = 0) then
begin
Continue;
end;
LPointIndex := 1;
if A[j, 1] <> 0 then
begin
x := FWidthdiv2 / GraphScale;
y := (B[j] - (A[j, 0] * x)) / A[j, 1];
if Abs(y) <= (FHeightdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
LPointIndex := LPointIndex + 1;
end;
end;
if A[j, 1] <> 0 then
begin
x := - FWidthdiv2 / GraphScale;
y := (B[j] - (A[j, 0] * x)) / A[j, 1];
if Abs(y) <= (FHeightdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
LPointIndex := LPointIndex + 1;
end;
end;
if A[j, 0] <> 0 then
begin
y := FHeightdiv2 / GraphScale;
x := (B[j] - (A[j, 1] * y)) / A[j, 0];
if Abs(x) <= (FWidthdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
LPointIndex := LPointIndex + 1;
end;
end;
if A[j, 0] <> 0 then
begin
y := - FHeightdiv2 / GraphScale;
x := (B[j] - (A[j, 1] * y)) / A[j, 0];
if Abs(x) <= (FWidthdiv2 / GraphScale) then
begin
LPoints[LPointIndex].x := x;
LPoints[LPointIndex].y := y;
end;
end;
x1 := LPoints[1].x;
y1 := LPoints[1].y;
x2 := LPoints[2].x;
y2 := LPoints[2].y;
FPaintBuffer.Canvas.Pen.Width := 2;
FPaintBuffer.Canvas.MoveTo(FWidthdiv2 + Round(x1 * GraphScale), FHeightdiv2 + Round(- y1 * GraphScale));
FPaintBuffer.Canvas.LineTo(FWidthdiv2 + Round(x2 * GraphScale), FHeightdiv2 + Round(- y2 * GraphScale));
FPaintBuffer.Canvas.Font.Color := clRed;
FPaintBuffer.Canvas.Font.Style := [fsBold];
FPaintBuffer.Canvas.Brush.Style := bsClear;
if A[j, 1] <> 0 then
begin
x1 := 0;
y1 := (B[j] - (A[j, 0] * x1)) / A[j, 1];
FPaintBuffer.Canvas.Ellipse((FWidthdiv2 + Round(x1 * GraphScale)) - 3, FHeightdiv2 + Round(- y1 * GraphScale) - 3, (FWidthdiv2 + Round(x1 * GraphScale)) + 3, FHeightdiv2 + Round(- y1 * GraphScale) + 3);
FPaintBuffer.Canvas.TextOut((FWidthdiv2 + Round(x1 * GraphScale)) - 20, FHeightdiv2 + Round(- y1 * GraphScale), Chr(Ord('A') + j) + '1');
end;
if A[j, 0] <> 0 then
begin
y2 := 0;
x2 := (B[j] - (A[j, 1] * y2)) / A[j, 0];
FPaintBuffer.Canvas.Ellipse((FWidthdiv2 + Round(x2 * GraphScale)) - 3, FHeightdiv2 + Round(- y2 * GraphScale) - 3, (FWidthdiv2 + Round(x2 * GraphScale)) + 3, FHeightdiv2 + Round(- y2 * GraphScale) + 3);
FPaintBuffer.Canvas.TextOut((FWidthdiv2 + Round(x2 * GraphScale)) - 3, FHeightdiv2 + Round(- y2 * GraphScale) - 20, Chr(Ord('A') + j) + '2');
end;
end;
DrawFunctionDomain;
if cbDrawDirectVector.Checked then
begin
DrawDirectVector;
end;
if (FTaskSolved) and (cbDrawDirectVector.Checked) and ((C[0] <> 0) or (C[1] <> 0)) then
begin
if C[1] <> 0 then
begin
x1 := - Round(FWidthdiv2 / GraphScale);
if C[1] <> 0 then y1 := (- C[0] * (x1 - sx)) / C[1] + sy;
x2 := Round(FWidthdiv2 / GraphScale);
if C[1] <> 0 then y2 := (- C[0] * (x2 - sx)) / C[1] + sy;
end else
begin
y1 := - Round(FHeightdiv2 / GraphScale);
if C[0] <> 0 then x1 := (- C[1] * (y1 - sy)) / C[0] + sx;
y2 := Round(FHeightdiv2 / GraphScale);
if C[0] <> 0 then x2 := (- C[1] * (y2 - sy)) / C[0] + sx;
end;
FPaintBuffer.Canvas.Pen.Width := 2;
FPaintBuffer.Canvas.Pen.Color := clRed;
FPaintBuffer.Canvas.MoveTo(FWidthdiv2 + Round(x1 * GraphScale), FHeightdiv2 + Round(- y1 * GraphScale));
FPaintBuffer.Canvas.LineTo(FWidthdiv2 + Round(x2 * GraphScale), FHeightdiv2 + Round(- y2 * GraphScale));
end;
FPaintBuffer.Canvas.Pen.Color := clGreen;
FPaintBuffer.Canvas.Brush.Color := clGreen;
FPaintBuffer.Canvas.Ellipse((FWidthdiv2 + Round(sx * GraphScale)) - 3, FHeightdiv2 + Round(- sy * GraphScale) - 3, (FWidthdiv2 + Round(sx * GraphScale)) + 3, FHeightdiv2 + Round(- sy * GraphScale) + 3);
end;
end;
procedure TMainForm.DrawGrid;
var
i: Integer;
LGridStep: Double;
LGridCount: Integer;
LScaleFactor: Double;
begin
for i := 1 to 30 do
begin
LGridStep := GraphScale * i;
if ((LGridStep >= 25) and (LGridStep <= 30)) or (LGridStep > 30) then
begin
Break;
end;
end;
LScaleFactor := LGridStep / GraphScale;
if FHeightdiv2 > FWidthdiv2 then
begin
LGridCount := Round(FHeightdiv2 / LGridStep);
end else
begin
LGridCount := Round(FWidthdiv2 / LGridStep);
end;
FPaintBuffer.Canvas.Font.Color := clBlack;
FPaintBuffer.Canvas.Pen.Color := clBlue;
FPaintBuffer.Canvas.Pen.Style := psDot;
FPaintBuffer.Canvas.Pen.Width := 1;
if cbDrawGrid.Checked then
begin
for i := 1 to LGridCount do
begin
// Горизонтальные линии
FPaintBuffer.Canvas.MoveTo(0, FHeightdiv2 - Round(LGridStep) * i);
FPaintBuffer.Canvas.LineTo(FPaintBuffer.Width, FHeightdiv2 - Round(LGridStep) * i);
FPaintBuffer.Canvas.MoveTo(0, FHeightdiv2 + Round(LGridStep) * i);
FPaintBuffer.Canvas.LineTo(FPaintBuffer.Width, FHeightdiv2 + Round(LGridStep) * i);
// Р'ертикальные линии
FPaintBuffer.Canvas.MoveTo(FWidthdiv2 - Round(LGridStep) * i, 0);
FPaintBuffer.Canvas.LineTo(FWidthdiv2 - Round(LGridStep) * i, FPaintBuffer.Height);
FPaintBuffer.Canvas.MoveTo(FWidthdiv2 + Round(LGridStep) * i, 0);
FPaintBuffer.Canvas.LineTo(FWidthdiv2 + Round(LGridStep) * i, FPaintBuffer.Height);
end;
end;
for i := 1 to LGridCount do
begin
FPaintBuffer.Canvas.TextOut(FWidthdiv2 - Round(LGridStep) * i, FHeightdiv2, IntToStr(Round(- i * LScaleFactor)));
FPaintBuffer.Canvas.TextOut(FWidthdiv2 + Round(LGridStep) * i, FHeightdiv2, IntToStr(Round(i * LScaleFactor)));
FPaintBuffer.Canvas.TextOut(FWidthdiv2 + 5, FHeightdiv2 - Round(LGridStep) * i, IntToStr(Round(i * LScaleFactor)));
FPaintBuffer.Canvas.TextOut(FWidthdiv2 + 5, FHeightdiv2 + Round(LGridStep) * i, IntToStr(Round(- i * LScaleFactor)));
end;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
FPaintBuffer := TBitMap.Create;
FDrawTaskGraph := false;
FTaskInfinite := false;
FX1X2Positive := true;
end;
procedure TMainForm.WMErasebkgnd(var Msg: TWMErasebkgnd);
begin
end;
procedure TMainForm.miAboutClick(Sender: TObject);
var
LAboutForm: TAboutForm;
begin
LAboutForm := TAboutForm.Create(nil);
try
LAboutForm.ShowModal;
finally
LAboutForm.Free;
end;
end;
procedure TMainForm.miExitClick(Sender: TObject);
begin
Close;
end;
procedure TMainForm.PaintBoxPaint(Sender: TObject);
begin
FPaintBuffer.Canvas.Pen.Color := clWhite;
FPaintBuffer.Canvas.Brush.Color := clWhite;
FPaintBuffer.Canvas.Rectangle(0, 0, FPaintBuffer.Width, FPaintBuffer.Height);
DrawGraph;
PaintBox.Canvas.Draw(0, 0, FPaintBuffer);
end;
function TMainForm.PointBelongsRest(x, y: Double; ARestIndex: Integer; x1x2positive: boolean): boolean;
begin
if (x1x2positive) and ((x < 0) or (y < 0)) then
begin
Result := False;
Exit;
end;
Result := True;
case S[ARestIndex] of
0: begin // 1 - '=';
if not (((A[ARestIndex, 0] * x) + (A[ARestIndex, 1] * y)) = B[ARestIndex]) then
begin
Result := False;
end;
end;
1: begin // 1 - '>=';
if not (((A[ARestIndex, 0] * x) + (A[ARestIndex, 1] * y)) >= B[ARestIndex]) then
begin
Result := False;
end;
end;
2: begin // 2 - '<=';
if not (((A[ARestIndex, 0] * x) + (A[ARestIndex, 1] * y)) <= B[ARestIndex]) then
begin
Result := False;
end;
end;
end;
end;
function TMainForm.PointBelongsRestDomain(x, y: Double; x1x2positive: boolean): boolean;
var
i: Integer;
begin
if (x1x2positive) and ((x < 0) or (y < 0)) then
begin
Result := False;
Exit;
end;
Result := True;
for i := 0 to FM - 1 do
begin
case S[i] of
0: begin // 1 - '=';
if not (((A[i, 0] * x) + (A[i, 1] * y)) = B[i]) then
begin
Result := False;
end;
end;
1: begin // 1 - '>=';
if not (((A[i, 0] * x) + (A[i, 1] * y)) >= B[i]) then
begin
Result := False;
end;
end;
2: begin // 2 - '<=';
if not (((A[i, 0] * x) + (A[i, 1] * y)) <= B[i]) then
begin
Result := False;
end;
end;
end;
end;
end;
// Процедура решения задачи
procedure TMainForm.SolveTask;
var
x, y: Double;
i, j: Integer;
LLine1: TVector;
LLine2: TVector;
LMinMaxValue: Double;
procedure GetLine(ALine1: TVector; Andex: Integer);
begin
ALine1[0] := A[Andex, 0];
ALine1[1] := A[Andex, 1];
ALine1[2] := B[Andex];
end;
begin
TaskRichEdit.Clear;
WriteInRichEd(TaskRichEdit, 'Уравнения ограничений: ', clNavy, 12, [fsBold]);
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('');
for i := 0 to FM - 1 do
begin
if A[i, 0] <> 0 then
begin
WriteInRichEd(TaskRichEdit, CheckOne(A[i, 0]), clNavy, 12, []);
WriteInRichEd(TaskRichEdit, 'x1', clBlack, 12, []);
if A[i, 1] <> 0 then
begin
WriteInRichEd(TaskRichEdit, CheckMinusPlus(A[i, 1]), clNavy, 12, []);
WriteInRichEd(TaskRichEdit, 'x2', clBlack, 12, []);
end;
end else
begin
if A[i, 1] <> 0 then
begin
WriteInRichEd(TaskRichEdit, CheckOne(A[i, 1]), clNavy, 12, []);
WriteInRichEd(TaskRichEdit, 'x2', clBlack, 12, []);
end;
end;
WriteInRichEd(TaskRichEdit, GetSignStr(i), clNavy, 12, []);
WriteInRichEd(TaskRichEdit, FloatToStr(B[i]), clNavy, 12, []);
if (A[i, 0] <> 0) and (A[i, 1] <> 0) then
begin
WriteInRichEd(TaskRichEdit, ' (' + Chr(Ord('A') + i) + '1', clRed, 8, [fsBold]);
WriteInRichEd(TaskRichEdit, Chr(Ord('A') + i) + '2)', clRed, 8, [fsBold]);
end else
begin
if (A[i, 0] <> 0) then
begin
WriteInRichEd(TaskRichEdit, ' (' + Chr(Ord('A') + i) + '2)', clRed, 8, [fsBold]);
end;
if (A[i, 1] <> 0) then
begin
WriteInRichEd(TaskRichEdit, ' (' + Chr(Ord('A') + i) + '1)', clRed, 8, [fsBold]);
end;
end;
TaskRichEdit.Lines.Add('');
end;
TaskRichEdit.Lines.Add('');
WriteInRichEd(TaskRichEdit, 'x1>=', clBlack, 12, []);
WriteInRichEd(TaskRichEdit, '0', clNavy, 12, []);
WriteInRichEd(TaskRichEdit, '; x2>=', clBlack, 12, []);
WriteInRichEd(TaskRichEdit, '0', clNavy, 12, []);
WriteInRichEd(TaskRichEdit, ';', clBlack, 12, []);
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('');
WriteInRichEd(TaskRichEdit, 'Целевая функция: ', clNavy, 12, [fsBold]);
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('');
if C[0] <> 0 then
begin
WriteInRichEd(TaskRichEdit, CheckOne(C[0]), clNavy, 12, []);
WriteInRichEd(TaskRichEdit, 'x1', clBlack, 12, []);
if C[1] <> 0 then
begin
WriteInRichEd(TaskRichEdit, CheckMinusPlus(C[1]), clNavy, 12, []);
WriteInRichEd(TaskRichEdit, 'x2', clBlack, 12, []);
end;
end else
begin
if C[1] <> 0 then
begin
WriteInRichEd(TaskRichEdit, CheckOne(C[1]), clNavy, 12, []);
WriteInRichEd(TaskRichEdit, 'x2', clBlack, 12, []);
end;
end;
if FTaskType = 0 then
begin
WriteInRichEd(TaskRichEdit, '->Max', clBlack, 12, []);
end else
begin
WriteInRichEd(TaskRichEdit, '->Min', clBlack, 12, []);
end;
// Находим решение задачи
FTaskSolved := false;
LMinMaxValue := 1.7e308;
case FTaskType of
0: LMinMaxValue := -1.7e308;
1: LMinMaxValue := 1.7e308;
end;
SetLength(LLine1, 3);
SetLength(LLine2, 3);
for i := 0 to FM - 1 do
begin
for j := 0 to FM - 1 do
begin
if i <> j then
begin
if LineToPoint(A[i, 0], A[i, 1], B[i], A[j, 0], A[j, 1], B[j], x, y) then
begin
if PointBelongsRestDomain(x, y, FX1X2Positive) then
begin
// ShowMessage(FloatToStr(LMinMaxValue) + ' : ' + FloatToStr(x * C[0] + y * C[1]));
if ((LMinMaxValue < (x * C[0] + y * C[1])) and (FTaskType = 0)) or
((LMinMaxValue > (x * C[0] + y * C[1])) and (FTaskType = 1)) then
begin
sx := x;
sy := y;
FTaskSolved := true;
LMinMaxValue := x * C[0] + y * C[1];
GetLine(LLine1, i);
GetLine(LLine2, j);
end;
end;
end;
end;
end;
for j := 0 to FM - 1 do
begin
x := 0;
if A[j, 1] <> 0 then
begin
y := B[j] / CheckForNil(A[j, 1]);
if PointBelongsRestDomain(x, y, FX1X2Positive) then
begin
if ((LMinMaxValue < (x * C[0] + y * C[1])) and (FTaskType = 0)) or
((LMinMaxValue > (x * C[0] + y * C[1])) and (FTaskType = 1)) then
begin
sx := x;
sy := y;
FTaskSolved := true;
LMinMaxValue := x * C[0] + y * C[1];
GetLine(LLine1, j);
LLine2[0] := 1;
LLine2[1] := 0;
LLine2[2] := 0;
end;
end;
end;
x := B[j] / CheckForNil(A[j, 0]);
y := 0;
if A[j, 0] <> 0 then
begin
if PointBelongsRestDomain(x, y, FX1X2Positive) then
begin
if ((LMinMaxValue < (x * C[0] + y * C[1])) and (FTaskType = 0)) or
((LMinMaxValue > (x * C[0] + y * C[1])) and (FTaskType = 1)) then
begin
sx := x;
sy := y;
FTaskSolved := true;
LMinMaxValue := x * C[0] + y * C[1];
GetLine(LLine1, j);
LLine2[0] := 0;
LLine2[1] := 1;
LLine2[2] := 0;
end;
end;
end;
end;
end;
x := 0;
y := 0;
if PointBelongsRestDomain(x, y, FX1X2Positive) then
begin
if ((LMinMaxValue < (x * C[0] + y * C[1])) and (FTaskType = 0)) or
((LMinMaxValue > (x * C[0] + y * C[1])) and (FTaskType = 1)) then
begin
sx := x;
sy := y;
FTaskSolved := true;
LMinMaxValue := x * C[0] + y * C[1];
LLine1[0] := 1;
LLine1[1] := 0;
LLine1[2] := 0;
LLine2[0] := 0;
LLine2[1] := 1;
LLine2[2] := 0;
end;
end;
FTaskInfinite := TestForInfinite(LLine1, LLine2, LMinMaxValue);
Finalize(LLine2);
Finalize(LLine1);
if (C[0] = 0) and (C[1] = 0) then
begin
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('-------------------------');
WriteInRichEd(TaskRichEdit, 'Целевая функция не задана!', clMaroon, 12, [fsBold]);
end else
begin
if FTaskSolved then
begin
if FTaskInfinite then
begin
FTaskSolved := false;
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('-------------------------');
WriteInRichEd(TaskRichEdit, .', clMaroon, 12, [fsBold]);
end else
begin
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('-------------------------');
WriteInRichEd(TaskRichEdit', clNavy, 12, [fsBold]);
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('');
if FTaskType = 0 then
begin
WriteInRichEd(TaskRichEdit, 'Целевая функция достигает своего максимального значения в точке:', clNavy, 10, [fsBold]);
end else
begin
WriteInRichEd(TaskRichEdit, 'Целевая функция достигает своего минимального значения в точке:', clNavy, 10, [fsBold]);
end;
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('');
WriteInRichEd(TaskRichEdit, 'x1', clBlack, 12, []);
WriteInRichEd(TaskRichEdit, '=' + FloatToStr(sx), clNavy, 12, []);
TaskRichEdit.Lines.Add('');
WriteInRichEd(TaskRichEdit, 'x2', clBlack, 12, []);
WriteInRichEd(TaskRichEdit, '=' + FloatToStr(sy), clNavy, 12, []);
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('');
WriteInRichEd(TaskRichEdit, 'Р--начение целевой функции:', clNavy, 10, [fsBold]);
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('');
WriteInRichEd(TaskRichEdit, 'f(x1, x2) = ', clBlack, 12, []);
WriteInRichEd(TaskRichEdit, FloatToStr(LMinMaxValue), clNavy, 12, []);
end;
end else
begin
TaskRichEdit.Lines.Add('');
TaskRichEdit.Lines.Add('-------------------------');
WriteInRichEd(TaskRichEdit, 'Р--адача РЅРµ имеет допустимого решения! Рў.Рє. ее ограничения несовместны.', clMaroon, 12, [fsBold]);
end;
end;
end;
procedure TMainForm.TaskSpeedButtonClick(Sender: TObject);
begin
TheoryPanel.Visible := False;
PaintBox.Visible := True;
FPaintBuffer.Width := PaintBox.Width;
FPaintBuffer.Height := PaintBox.Height;
FWidthdiv2 := FPaintBuffer.Width div 2;
FHeightdiv2 := FPaintBuffer.Height div 2;
Repaint;
end;
procedure TMainForm.TaskTypeComboBoxChange(Sender: TObject);
begin
if FTaskType <> TaskTypeComboBox.ItemIndex then
begin
FTaskType := TaskTypeComboBox.ItemIndex;
SolveTask;
Repaint;
end;
end;
function TMainForm.TestForInfinite(ALine1, ALine2: TVector; AMinMaxValue: Double): Boolean;
var
x, y: Double;
i, j: Integer;
x1, y1: Double;
x2, y2: Double;
LAlpha1: Double;
LAlpha2: Double;
LLines: array[0..1] of TVector;
begin
Result := False;
LLines[0] := ALine1;
LLines[1] := ALine2;
for j := 0 to 1 do
begin
if (LLines[j][0] <> 0) or (LLines[j][1] <> 0) then
begin
// ALine1[0]*x + ALine1[1]*y = ALine1[2]
if LLines[j][1] <> 0 then
begin
x1 := - 1;
y1 := (LLines[j][2] - LLines[j][0] * x1) / LLines[j][1];
x2 := 1;
y2 := (LLines[j][2] - LLines[j][0] * x2) / LLines[j][1];
end else
begin
y1 := - 1;
x1 := (LLines[j][2] - LLines[j][1] * y1) / LLines[j][0];
y2 := 1;
x2 := (LLines[j][2] - LLines[j][1] * y2) / LLines[j][0];
end;
end;
LAlpha1 := 0;
LAlpha2 := 0;
for i := 0 to 1000 do
begin
x := x1 + (x2 - x1) * LAlpha1;
y := y1 + (y2 - y1) * LAlpha1;
LAlpha1 := LAlpha1 + 10;
if PointBelongsRestDomain(x, y, FX1X2Positive) then
begin
if FTaskType = 0 then
begin
Result := (x * C[0] + y * C[1]) >= AMinMaxValue;
end else begin
Result := (x * C[0] + y * C[1]) <= AMinMaxValue;
end;
if Result then
begin
Exit;
end;
end;
x := x1 + (x2 - x1) * LAlpha2;
y := y1 + (y2 - y1) * LAlpha2;
LAlpha2 := LAlpha2 - 10;
if PointBelongsRestDomain(x, y, FX1X2Positive) then
begin
if FTaskType = 0 then
begin
Result := (x * C[0] + y * C[1]) >= AMinMaxValue;
end else begin
Result := (x * C[0] + y * C[1]) <= AMinMaxValue;
end;
if Result then
begin
Exit;
end;
end;
end;
end;
end;
procedure TMainForm.TheorySpeedButtonClick(Sender: TObject);
var
LTempDirPath: string;
LResourceStream: TResourceStream;
begin
PaintBox.Visible := False;
TheoryPanel.Visible := True;
LResourceStream := TResourceStream.Create(HInstance, 'THEORY', RT_RCDATA);
try
LTempDirPath := CheckForSlash(GetTempDirPath);
LResourceStream.SaveToFile(LTempDirPath + 'theory.mht');
TheoryWebBrowser.Navigate(LTempDirPath + 'theory.mht');
Подобные документы
Требования к функциям, выполняемым системой, к программно-аппаратному и техническому обеспечению, к надежности и хранению информации. Схема взаимодействия модулей. Структурная схема программы. Руководство пользователю и программисту, вероятные ошибки.
курсовая работа [423,1 K], добавлен 24.03.2014Структура взаимодействия входной и выходной информации. Требования к программно-аппаратному окружению, к эргономике и технической эстетике интерфейса пользователя. Эскиз и спецификация типовых объектов управления графического интерфейса, тестирование.
курсовая работа [2,0 M], добавлен 16.02.2016Проектирование программы для предприятия ООО "Чудо свечи" в среде программирования Borland Delphi. Произведение расчета системы методом аддитивной оптимизации. Требования к функциям, выполняемым системой, к программному и аппаратному обеспечению.
курсовая работа [2,8 M], добавлен 27.02.2015Особенности задач линейного программирования. Симплексный метод решения задач линейного программирования. Обоснование выбора языка, инструментария программирования, перечень идентификаторов и блок-схема алгоритма. Логическая схема работы программы.
дипломная работа [2,4 M], добавлен 13.08.2011Структура взаимодействия входной, выходной информации. Требования к программно-аппаратному окружению, эргономике. Эскиз, спецификация типовых объектов управления графического интерфейса. Руководство системного программиста, настройка и проверка программы.
курсовая работа [2,6 M], добавлен 02.09.2013Практические навыки моделирования задач линейного программирования и их решения графическим и симплекс-методом с использованием прикладной программы SIMC. Моделирование транспортных задач и их решение методом потенциалов с помощью программы TRAN2.
контрольная работа [199,8 K], добавлен 15.06.2009Сущность линейного программирования. Математическая формулировка задачи ЛП и алгоритм ее решения с помощью симплекс-метода. Разработка программы для планирования производства с целью обеспечения максимальной прибыли: блок-схема, листинг, результаты.
курсовая работа [88,9 K], добавлен 11.02.2011Требования к функциям и задачам, выполняемым системой "Подбор кредита ОАО "Россельхозбанк". Проектирование архитектуры программного продукта. Структурная схема программного продукта. Описание компонент программного обеспечения. План менеджмента проекта.
курсовая работа [684,0 K], добавлен 03.05.2015Постановка задачи нелинейного программирования. Определение стационарных точек и их типа. Построение линий уровней, трехмерного графика целевой функции и ограничения. Графическое и аналитическое решение задачи. Руководство пользователя и схема алгоритма.
курсовая работа [2,5 M], добавлен 17.12.2012Требования к разрабатываемой программе и к выполняемым ею функциям. Алгоритмы взаимодействия с реестром, поиска, открытия, чтения и удаления ключа. Запросы к исходным кодам и языкам программирования. Проведение экономических расчетов и охрана труда.
дипломная работа [6,5 M], добавлен 10.10.2011