Задача о распределении средств между предприятиями

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

АЛТАЙСКИЙ ПРОМЫШЛЕННО-ЭКОНОМИЧЕСКИИ КОЛЛЕДЖ

Специальность программное обеспечение вычислительной техники и автоматизированных систем

Группа 11По071

КУРСОВАЯ РАБОТА

На тему

Задача о распределении средств между предприятиями

Студент:

Консультанты: Любицкая О.Н, Захарова О.А

“__” Мая 2009г.

БАРНАУЛ Оглавление

Введение. 3

Сущность математического метода.. 5

1.1 Характеристика математического метода, применимого для решения задачи   5

1.2 Аналитическое решение задачи.. 11

Решение задачи в среде визуального программирования Delphi 15

2.1 Анализ процесса обработки информации и выбор структур данных для ее хранения.. 15

2.2 Разработка основных алгоритмов решения задачи.. 17

2.3 Построение графа состояний интерфейса.. 19

2.3 Разработка форм ввода-вывода информации.. 20

2.5 Контрольный пример. 23

Заключение. 30

Список использованных источников.. 32

Приложение А.. 33

Введение

Тема курсовой работы: задача о распределении средств между предприятиями.

Вопрос о грамотном распределении инвестируемых средств в различные предприятия стоял всегда, но в последнее время он встал ещё жестче. Обилие фирм, предприятий, концернов и т. д., которые одновременно почти нереально про инвестировать, да и не все предприятия способны задействовать все вложенные в них средства. А ведь, несмотря на все сложности нужно инвестировать предприятия и развивать промышленность в целом и получать максимальный прирост прибыли предприятия от вложенных средств.

Тут и встаёт вопрос о том, как с наибольшей выгодой вложить средства, а также как с наименьшими затратами получить наибольший прирост прибыли предприятий в которые были вложены инвестиции. Для этого выдающимися учёными был разработан метод динамического программирования в сфере оптимизации и распределения средств между предприятиями.

Из всего вышесказанного легко понять актуальность данной темы в современном мире, особенно во времена мирового экономического кризиса, когда нужен четкий план развития предприятий и жесткий контроль за выполнением найденного оптимального плана распределения средств между предприятиями.

Целью курсовой работы является автоматизация процесса нахождения оптимального плана распределения инвестиций между несколькими предприятиями, который бы позволил предприятиям получать от вложенных в них инвестиций максимальный прирост прибыли, как на одном предприятии, так и в совокупности на всех предприятиях в целом.

Задачей данной курсовой работы стало изучение материала по данному математическому методу. Еще одной из основных задач курсовой работы явилась возможности овладеть данным методом нахождения оптимального плана распределения  инвестиций между предприятиями, и получение углубленных знаний в данной сфере экономической оптимизации и математического планирования. Ещё одной задачей стало получение профессиональных навыков, а также опыта создания программного продукта, автоматизирующего достаточно сложный процесс в экономической сфере,  разработанный в среде программирования Delphi 7 на языке программирования Object Pascal (Delphi начиная с Delphi 7). А также закрепление материала по дисциплине «Математические методы» и закрепление полученных навыков программирования в среде программирования Delphi.

Разработанный программный продукт является эргономичным, что позволит использовать его даже на малопроизводительных персональных компьютерах. Так же интерфейс программного продукта является интуитивным, гармоничным и привлекательным, благодаря этому им может пользоваться даже начинающий пользователь. Ещё одой особенностью данного программного продукта является высокое быстродействие. Так же в программе имеется множество подсказок, которые позволят пользователю с легкостью пользоваться программным продуктом и легко его освоить.

Разработанный программный продукт на данном этапе жизненного цикла способен находить оптимальный план распределения инвестиций только между тремя предприятиями, но для количества условных единиц вкладываемых средств ограничений нет.

Сущность математического метода

1.1 Характеристика математического метода, применимого для решения задачи

Данный математический метод изложен во многих литературных источниках, но наиболее подробно он описан в учебном материале “Математическое программирование в примерах и задачах” автор И.Л. Акулич. Весь дальнейший материал взят из указанного источника.

Динамическое программирование – это математический метод поиска оптимального управления, специально приспособленный к многошаговым процессам. Рассмотрим пример такого процесса.

Пусть планируется инвестирование N предприятий. Здесь шагом является инвестирование одного предприятия. На развитие предприятий выделяются средства, которые должны быть как-то распределены между этими предприятиями. В процессе их функционирования выделенные средства частично расходуются. Каждое предприятие приносит некоторый доход, зависящий от вложенных средств. Поэтому имеющиеся средства могут перераспределяться между предприятиями: каждому из них выделяется какая-то доля средств.

Ставится вопрос: как распределять имеющиеся средства между предприятиями, чтобы суммарный доход от всех предприятий был максимальным?

Перед нами типичная задача динамического программирования, в которой рассматривается управляемый процесс – функционирование группы предприятий. Управление процессом состоит в распределении (и перераспределении) средств. Управляющим воздействием (УВ) является выделение каких-то средств каждому из предприятий в начале года.

УВ на каждом шаге должно выбираться с учетом всех его последствий в дальнейшем. УВ должно быть дальновидным, с учетом перспективы. Нет смысла выбирать на рассматриваемом шаге наилучшее УВ, если в дальнейшем это помешает получить наилучшие результаты других шагов. УВ на каждом шаге надо выбирать “c заглядыванием в будущее”, иначе возможны серьезные ошибки.

Действительно, предположим, что в рассмотренной группе предприятий одни заняты выпуском предметов потребления, а другие производят для этого машины. Причем целью является получение максимального объема выпуска предметов потребления. Пусть планируются капиталовложения первому предприятию. Исходя из их узких интересов данного шага, мы должны были бы все средства вложить в производство предметов потребления, пустить имеющиеся машины на полную мощность и добиться максимального объема прибыли. Но правильным ли будет такое решение в целом? Очевидно, нет. Имея в виду будущее, необходимо выделить какую-то долю средств и на производство машин. При этом объем продукции за первый год, естественно, снизится, зато будут созданы условия, позволяющие увеличивать ее производство в дальнейшем.

В формализме решения задач методом динамического программирования будут использоваться следующие обозначения:

N – число шагов.

– вектор, описывающий состояние системы на k-м шаге.

– начальное состояние, т. е. состояние на 1-м шаге.

– конечное состояние, т. е. состояние на последнем шаге.

Xk – область допустимых состояний на k-ом шаге.

– вектор УВ на k-ом шаге, обеспечивающий переход системы из состояния xk-1 в состояние xk.

Uk – область допустимых УВ на k-ом шаге.

Wk – величина выигрыша, полученного в результате реализации k-го шага.

S – общий выигрыш за N шагов.

 – вектор оптимальной стратегии управления или ОУВ за N шагов.

Sk+1() – максимальный выигрыш, получаемый при переходе из любого состояния в конечное состояние  при оптимальной стратегии управления начиная с (k+1)-го шага.

S1() – максимальный выигрыш, получаемый за N шагов при переходе системы из начального состояния  в конечное  при реализации оптимальной стратегии управления . Очевидно, что S = S1(), если  – фиксировано.

Метод динамического программирования опирается на условие отсутствия последействия и условие аддитивности целевой функции.

Условие отсутствия последействия. Состояние , в которое перешла система за один k-й шаг, зависит от состояния  и выбранного УВ  и не зависит от того, каким образом система пришла в состояние , то есть

Аналогично, величина выигрыша Wk зависит от состояния  и выбранного УВ , то есть

Условие аддитивности целевой функции. Общий выигрыш за N шагов вычисляется по формуле

Определение. Оптимальной стратегией управления  называется совокупность УВ , то есть , в результате реализации которых система за N шагов переходит из начального состояния  в конечное  и при этом общий выигрыш S принимает наибольшее значение.

Условие отсутствия последствий позволяет сформулировать принцип оптимальности Беллмана.

Принцип оптимальности. Каково бы ни было допустимое состояние системы   перед очередным i-м шагом, надо выбрать допустимое УВ  на этом шаге так, чтобы выигрыш Wi на i-м шаге плюс оптимальный выигрыш на всех последующих шагах был максимальным.

В качестве примера постановки задачи оптимального управления продолжим рассмотрение задачи управления финансированием группы предприятий. Пусть группе предприятий  выделяются соответственно средства: совокупность этих значений можно считать управлением на i-м шаге, то есть . Управление  процессом в целом представляет собой совокупность всех шаговых управлений, то есть .

Управление может быть хорошим или плохим, эффективным или неэффективным. Эффективность управления   оценивается показателем S. Возникает вопрос: как выбрать шаговые управления  , чтобы величина S обратилась в максимум?

Поставленная задача является задачей оптимального управления, а управление, при котором показатель S достигает максимума, называется оптимальным. Оптимальное управление  многошаговым процессом состоит из совокупности оптимальных шаговых управлений:

Таким образом, перед нами стоит задача: определить оптимальное управление на каждом шаге  (i=1,2,...N) и, значит, оптимальное управление всем процессом .

Мы отметили, что планируя многошаговый процесс, необходимо выбирать УВ на каждом шаге с учетом его дальнейших последствий на еще предстоящих шагах. Однако, из этого правила есть исключение. Среди всех шагов существует один, который может планироваться без "заглядывания в будущее". Какой это шаг? Очевидно, последний — после него других шагов нет. Этот шаг, единственный из всех, можно планировать так, чтобы он как таковой принес наибольшую выгоду. Спланировав оптимально этот последний шаг, можно к нему пристраивать предпоследний, к предпоследнему — предпредпоследний и т.д.

Поэтому процесс динамического программирования на 1-м этапе раз­ворачивается от конца к началу, то есть раньше всех планируется последний, N-й шаг. А как его спланировать, если мы не знаем, чем кончился предпоследний? Очевидно, нужно сделать все возможные предположения о том, чем кончился предпоследний, (N — 1)-й шаг, и для каждого из них найти такое управление, при котором выигрыш (доход) на послед­нем шаге был бы максимален. Решив эту задачу, мы найдем условно оптимальное управление (УОУ) на N-м шаге, т.е. управление, которое надо применить, если (N — 1)-й шаг закончился определенным образом.

Предположим, что эта процедура выполнена, то есть для каждого исхода (N — 1)-го шага мы знаем УОУ на N-м шаге и соответствующий ему условно оптимальный выигрыш (УОВ). Теперь мы можем оптимизировать управление на предпоследнем, (N — 1)-м шаге. Сделаем все возможные предположения о том, чем кончился предпредпоследний, то есть (N — 2)-й шаг, и для каждого из этих предположений найдем такое управление на (N — 1)-м шаге, чтобы выигрыш за последние два шага (из которых последний уже оптимизирован) был максимален. Далее оптимизируется управление на (N — 2)-м шаге, и т.д.

Одним словом, на каждом шаге ищется такое управление, которое обеспечивает оптимальное продолжение процесса относительно достигнутого в данный момент состояния. Этот принцип выбора управления, называется принципом оптимальности. Самоуправление, обеспечивающее оптимальное продолжение процесса относительно заданного состояния, называется УОУ на данном шаге.

Теперь предположим, что УОУ на каждом шаге нам известно: мы знаем, что делать дальше, в каком бы состоянии ни был процесс к началу каждого шага. Тогда мы можем найти уже не "условное", а действительно оптимальное управление на каждом шаге.

Действительно, пусть нам известно начальное состояние процесса. Теперь мы уже знаем, что делать на первом шаге: надо применить УОУ, найденное для первого шага и начального состояния. В результате этого управления после первого шага система перейдет в другое состояние; но для этого состояния мы знаем УОУ и г д. Таким образом, мы найдем оптимальное управление процессом, приводящее к максимально возможному выигрышу.

Таким образом, в процессе оптимизации управления методом динамического программирования многошаговый процесс "проходится" дважды: первый раз — от конца к началу, в результате чего находятся УОУ на каждом шаге и оптимальный выигрыш (тоже условный) на всех шагах, начиная с данного и до конца процесса; второй раз — от начала к концу, в результате чего находятся оптимальные управления на всех шагах процесса.

Можно сказать, что процедура построения оптимального управления методом динамического программирования распадается на две стадии: предварительную и окончательную. На предварительной стадии для каждого шага определяется УОУ зависящее от состояния системы (достигнутого в результате предыдущих шагов), и условно оптимальный выигрыш на всех оставшихся шагах, начиная с данного, также зависящий от состояния. На окончательной стадии определяется (безусловное) оптимальное управление для каждого шага. Предварительная (условная) оптимизация производится по шагам в обратном порядке: от последнего шага к первому; окончательная (безусловная) оптимизация — также по шагам, но в естественном порядке: от первого шага к последнему. Из двух стадий оптимизации несравненно более важной и трудоемкой является первая. После окончания первой стадии выполнение второй трудности не представляет: остается только "прочесть" рекомендации, уже заготовленные на первой стадии.

1.2 Аналитическое решение задачи

Рассмотрим задачу, когда инвестор выделяет средства в размере 5 условных единиц, которые должны быть распределены между тремя предприятиями.

Требуется, используя принцип оптимальности Беллмана, построить план распределения инвестиций между предприятиями, обеспечивающий наибольшую общую прибыль, если каждое предприятие при инвестировании в него средств X у.е. приносит прибыль Pi (x) у.е. (i = l, 2 и 3) последующим данным, приведённым в таблице 1.

Таблица 1 – Исходные данные.

Инвестируемые средства (у.е.)

Общая прибыль (у.е.)

Х

P1(x)

P2(x)

P3(x)

1

3,22

3,33

4,27

2

3,57

4,87

7,64

3

4

5,26

10,25

4

4,12

7,34

15,93

5

4,85

9,49

16,12

Составим математическую модель задачи:

а) Число шагов в данной задаче равно 3.

б) Пусть S - количество средств, имеющихся в наличии перед данным шагом, и характеризующих состояние системы на каждом шаге.

в) Управление на i -ом шаге (i = l,2,3) выберем X, - количество средств, инвестируемых в i -ое предприятие.

д) Выигрыш Pi (Xi) на i -ом шаге - это прибыль, которую приносит I -oe предприятие при инвестировании в него средств Xi. Если через выигрыш в целом обозначить общую прибыль W, то

W = P1 (x1) + P2 (x2) + P3(x3).

е) Если в наличии имеются средства в количестве S у.е. и в i -oe предприятие инвестируется X у.е., то для дальнейшего инвестирования остается (S-X) у.е.. Таким образом, если на i -ом шаге система находилась в состоянии S и выбрано управление X, то на (i +1) -ом шаге система будет находиться в состоянии (S-X), и, следовательно, функция перехода в новое состояние имеет вид: Fi (S-X) = S-X.

ж) На последнем (i=3) шаге оптимальное управление соответствует количеству средств, имеющихся в наличии, а выигрыш равен доходу, приносимым последним предприятием:

Xi (S) = S. Wi (S) = Pi (S).

к) Согласно принципу оптимальности Беллмана, управление на каждом шаге нужно выбирать так, чтобы оптимальной была сумма выигрышей на всех оставшихся до конца процесса шагах, включая выигрыш на данном шаге.

Основное функциональное управление примет вид:

Wi (S) = maxx<=s {Pi (X) + Wi+1 (S - X)}

Проведём пошаговую оптимизацию, по результатам которой заполним таблицу 2.

Таблица 2 – Итоговые данные.

S

i = 3

i = 2

i = 1

X3 (s)

W3 (s)

X2 (s)

W2 (s)

X1 (s)

W1 (s)

1

1

4,27

0

4,27

-

-

2

2

7,64

0

7,64

-

-

3

3

10,25

1

10,97

-

-

4

4

15,93

0

15,93

-

-

5

5

16,12

1

19,26

0

19,26

В первой колонке таблицы записываются возможные состояния системы, в верхней строке - номера шагов с оптимальным управлением и выигрышем на каждом шаге, начиная с последнего. Так как для последнего шага i = 3 функциональное уравнение имеет вид:

 X3 (S) = S,

 W3 (S) = P3 (S),

то две колонки таблицы, соответствующие i = 3, заполняются автоматически по таблице исходных данных.

На шаге i = 2 основное функциональное управление примет вид:

W2 (S) = maxx<=s {P2 (X) + W3 (S - X)}

Поэтому для проведения оптимизации на этом шаге заполним таблицу 3 для различных состояний S при шаге i = 3.

Таблица 3 – Второй шаг обработки.

S

X

S-X

P2 (x)

W3 (s-x)

P2 (x) + W3 (s-x)

W2 (s)

1

0

1

0

4,27

4,27

4,27

1

0

3,33

0

3,33

2

0

2

0

7,64

7,64

7,64

1

1

3,33

4,27

7,6

2

0

4,87

0

4,87

3

0

3

0

10,25

10,25

10,97

1

2

3,33

7,64

10,97

2

1

4,87

4,27

9,14

3

0

5,26

0

5,26

4

0

4

0

15,93

15,93

15,93

1

3

3,33

10,25

13,58

2

2

4,87

7,64

12,51

3

1

5,26

4,27

9,53

4

0

7,34

0

7,34

5

0

5

0

16,12

16,12

19,26

1

4

3,33

15,93

19,26

2

3

4,87

10,25

15,12

3

2

5,26

7,64

12,9

4

1

7,34

4,27

11,61

5

0

9,49

0

9,49

На шаге i = 1 основное функциональное управление примет вид:

W1 (S) = maxx<=s {P1 (X) + W2 (S - X)},

а состояние системы перед первым шагом S = 5, поэтому для проведения оптимизации на этом шаге заполним таблицу 4.

Таблица 4 – Первый шаг обработки.

S

X

S-X

P1 (x)

W2 (s-x)

P1 (x) + W2 (s-x)

W1 (s)

5

0

5

0

19,26

19,26

19,26

1

4

3,22

15,93

19,15

2

3

3,57

10,97

14,54

3

2

4

7,64

11,76

4

1

4,12

4,27

8,27

5

0

4,85

0

4,85

Видно, что наибольшее значение выигрыша составляет 19,26. При этом оптимальное управление на первом шаге составляет X1 (S1)=0 при этом S1=5, на втором шаге X2 (S2)=1 при этом S2=S1–X1=5 и на третьем шаге X3(S3)=4 при этом S3=S2–X2=4. Это означает, что (0, 1, 4) - оптимальный план распределения инвестиций между предприятиями.

Таким образом, для получения наибольшей обшей прибыли в размере 19,26 у.е., необходимо вложить 1 у.е. во второе предприятие и 4 у.е. в третье предприятие.

Решение задачи в среде визуального программирования Delphi

2.1 Анализ процесса обработки информации и выбор структур данных для ее хранения

Для подбора структур данных и переменных, необходимых для решения поставленной задачи использовался учебный материал “Алгоритмы + структуры данных = программы” автора Н. Вирт.

Для хранения промежуточных и итоговых данных в массивах описан новый тип plan, это запись, состоящая из двух полей целочисленного и вещественного типа с именами x и ws соответственно.

Для хранения первичных данных используется двумерный массив вещественного типа, состоящий из 250 столбцов и 3 строк. Для хранения рассчитанных итоговых данных используется двумерный массив типа plan, состоящий из 250 столбцов и 3 строк. Для промежуточного хранения рассчитываемых данных используется одномерный массив типа plan, состоящий из 250 столбцов.

Также для хранения промежуточных значений количества выделяемых средств и максимальной прибыли при данном значении выделяемых средств используются переменные вещественного типа px и wx соответственно.

Для хранения количества инвестируемых средств используется переменная s целочисленного типа. Для хранения информации о количестве шагов использована переменная shag целочисленного типа.

Переменные целочисленного типа kc и kr используются для циклической обработки двумерных массивов, они указывают на количество столбцов и строк в обрабатываемых массивах.

Переменная вещественного типа max используется для нахождения максимального значения прибыли во время промежуточных расчетов. Для хранения коэффициента X при максимальном значении прибыли используется переменная целочисленного типа a.

Дополнительная переменная вещественного типа prib используется для подсчёта и вывода пользователю максимальной прибыли, которую можно будет получить при реализации найденного оптимального плана. Переменные целочисленного типа i, j используются как счетчики в циклических операторах при обработке двумерных массивов.

2.2 Разработка основных алгоритмов решения задачи

При разработке основного алгоритма решения применялись такие учебные пособия, как: “Математическое программирование. Теория алгоритмов” автор М. Муну, “Элементы динамического программирования” Е. С. Вентцель, “Введение в методы оптимизации” М. Аоки.

При изучении материала из вышеперечисленных пособий была выявлена особенность задач распределения инвестиций между предприятиями. Эта особенность заключается в том, что первый и последний шаги на первом этапе оптимизации можно выделить отдельно от общего алгоритма. Используя эту особенность, при разработке программного продукта происходит увеличение количества кода программы, но быстродействие хоть и незначительно, но увеличивается особенно это заметно, если количество инвестируемых средств достаточно высоко.

На первом этапе использования программы пользователь вводит первичные данные, то есть количество инвестируемых средств, после чего по нажатию кнопки “Применить параметры” генерируется таблица, куда пользователь должен ввести основные данные (показатель прироста прибыли в зависимости от вложенных средств).

После заполнения таблицы пользователю нужно нажать кнопку “Первичная обработка” после чего запустится проверка корректности введённых данных, которая протекает в три этапа.

На первом этапе проверяется, заполнены ли все поля таблицы или нет, если да, то программа переходит ко второму этапу проверки, если нет, то выводится соответствующее сообщение пользователю.

На втором этапе проверяется, корректны ли записи в таблице (имеются ли лишние запятые) если данные введены, верно, то программа переходит к третьему этапу проверки, если нет, то выводится соответствующее сообщение пользователю.

На третьем этапе проверяется, корректно ли заданы значения функций в зависимости, от количества инвестируемых средств или нет, если да то пользователь уже может рассчитывать оптимальный план, если же нет, то выводится соответствующее сообщение пользователю.

Для расчета оптимального плана пользователю нужно кликнуть по кнопке “Рассчитать оптимальный план” после чего запустится основной алгоритм программы, который исходя из найденной особенности, данного вида задач разбит на четыре части.

Во время работы первой части частично заполняется двумерный массив P, в котором хранятся итоговые данные. Заполнение происходит из двумерного массива Z, в котором хранятся данные из таблицы.

Во время работы второй части также частично заполняется массив P, но заполнение производится не простым считыванием массива Z, а из максимальных элементов, которые находятся путём сложения показателей прироста прибыли в зависимости от количества вкладываемых средств во всех возможных вариациях на каждом шаге оптимизации.

Во время работы третьей части производится конечное заполнение результирующего массива P путём итогового расчета максимальной прибыли из всех возможных вариаций на последнем шаге оптимизации.

После запускается четвёртая часть основного алгоритма, которая считывает данные из результирующего массива P и находит оптимальный план распределения инвестиций.

Во время работы основного алгоритма пользователю выводится информация о процессе оптимизации, и найденный оптимальный план, а также ожидаемая прибыль от найденного оптимального плана.

После чего пользователь может рассчитать новый оптимальный план.

Описанный алгоритм можно более подробно рассмотреть в приложении А.

2.3 Построение графа состояний интерфейса

Для построения графа состояний интерфейса использовался источник “В помощь программисту” автор Краснов. М..

На рисунке 1 представлен граф состояний интерфейса разработанного программного продукта.

Рисунок 1 – Граф состояний интерфейса. 2.3 Разработка форм ввода-вывода информации

На рисунке 2 представлен эскиз формы ввода-вывода.

Рисунок 2 – Эскиз формы ввода вывода.

1          Компонент TForm1, для размещения всех элементов программы;

2          Компонент TPanel1, для группировки элементов ввода и обработки первичных данных;

3          Компонент TStringGrid1, для ввода значений функций при различных значениях количества вкладываемых средств;

4          Компонент TGroupBox1, для группировки элементов управления;

5          Компонент TPanel2, для группировки элементов предназначенных для ввода количества вкладываемых средств;

6          Компонент TPanel3, для группировки элементов предназначенных для ввода количества предприятий;

7          Компонент TPanel4, для группировки элементов предназначенных для работы с первичными данными;

8          Компонент TLabel1, поясняет, что нужно вводить в поле Edit1;

9          Компонент TEdit1, для ввода количества вкладываемых средств;

10     Компонент TLabel2, поясняет, что нужно ввести в поле Edit2;

11     Компонент TEdit2, для ввода количества предприятий;

12     Компонент TButton1, для генерации таблицы;

13     Компонент TButton2, для изменения первичных данных;

14     Компонент TPanel5, для группировки элементов вывода и расчёта итоговых данных;

15     Компонент TPanel6, для улучшения визуализации интерфейса;

16     Компонент TMemo1, для вывода итоговых данных;

17     Компонент TGroupBox2, для группировки элементов управления;

18     Компонент TButton7, для очистки таблицы значений функции при различных значениях количества вкладываемых средств;

19     Компонент TPanel8, для группировки элементов предназначенных для обработки и изменения табличных данных;

20     Компонент TPanel9, для улучшения визуализации интерфейса;

21     Компонент TPanel7, для группировки элементов управления программой;

22     Компонент TButton4, для проверки правильности заполнения таблицы;

23     Компонент TButton6, для внесения изменений в табличные данные;

24     Компонент TButton5, для нахождения оптимального плана;

25     Компонент TButton8, для очистки полей ввода-вывода, обнуления значений переменных и возврат к началу для расчета нового оптимального плана;

26     Компонент TButton3, для выхода из программы;

27     Компонент TPanel10, для улучшения визуализации интерфейса;

28     Компонент TLabel3, для отображения инициалов создателя программного продукта.

2.5 Контрольный пример

При запуске программы пользователю выводится сообщение об ограничении разработанного программного продукта, которое изображено на рисунке 3.

Рисунок 3 – Сообщение об ограничении.

После подтверждения откроется главная форма программы, изображенная на рисунке 4.

Рисунок 4 – Главная форма.

После пользователь должен ввести начальные данные, чтобы сгенерировать таблицу, если пользователь не введёт значение в поле ввода, то выведется сообщение, об ошибке изображенное на рисунке 5.

Рисунок 5 – Сообщение об ошибке ввода 1.

Если пользователь случайно или специально введёт заведомо ложное значение, то выведется сообщение, об ошибке изображенное на рисунке 6.

Рисунок 6 – Сообщение об ошибке ввода 2.

После ввода корректного значения по нажатию кнопки “Применить параметры” генерируется таблица, в которую пользователь должен заполнить необходимыми данными. После чего необходимо нажать кнопку “Первичная обработка”, для проверки корректности введённых данных. Если пользователь не заполнил, хотя бы одно поле ввода ему выведется сообщение, об ошибке изображенное на рисунке 7.

Рисунок 7 – Сообщение об ошибке ввода 3.

Если пользователь заполнил все поля таблицы, но ошибся при расстановке запятых, то выведется сообщение об ошибке, изображенное на рисунке 8.

Рисунок 8 – Сообщение об ошибке ввода 4.

Если пользователь неверно задал значения функции, то ему выведется соответствующее сообщение об ошибке, которое показано на рисунке 9.

Рисунок 9 – Сообщение об ошибке ввода 5.

Если все данные введены, верно, то пользователь нужно кликнуть по кнопке “Рассчитать оптимальный план”, после чего программа рассчитает оптимальный план и выведет его пользователю. После этого пользователю предоставляется возможность рассчитать новый оптимальный план по нажатию соответствующей кнопки. Также можно выйти из программы (выход доступен на любом этапе работы программы). Финальный этап работы программы изображен на рисунке 10.

Рисунок 10 – Финальное состояние главной формы.

Заключение

В процессе написания данной курсовой работы были углублены знания в таких дисциплинах, как: “Основы алгоритмизации и программирования”, “Основы программирования в среде программирования Delphi” и “Математические методы”. Также в процессе работы над курсовой работой были изучены множественные информационные источники разной предметной направленности в таких сферах, как “Объектно-ориентированное программирование”, “Алгоритмизация”, “Программирование в среде Delphi”, “Динамическое программирование” и “Экономической оптимизации”.

В результате был разработан программный продукт, который автоматизирует процесс распределения инвестиций между предприятиями.

Естественно о применении разработанного программного продукта в реальной сфере экономической оптимизации говорить не приходится, так как этот продукт является лишь учебным или, иначе говоря “тренировочным”, но его могут применять, как студенты изучающие дисциплину “Математические методы”, так и преподаватели преподающие её. Студентам программный продукт поможет решить сложные задачи, провести самоконтроль или разобраться в решении задач такого типа благодаря тому, что в процессе работы программы пользователю выводится процесс нахождения оптимального плана распределения инвестиций между предприятиями. Преподавателям же он поможет облегчить процесс проверки решений подобных задач у студентов.

В данном программном продукте есть один недостаток, который не удалось устранить из-за недостатка времени, а сам недостаток заключается в том, что найти оптимальный план распределения инвестиций можно только между тремя предприятиями. Так же имеется чисто логическое ограничение в 250 условных единиц для количества вкладываемых средств в предприятия.

В дальнейшем при наличии времени и более глубоких знаний в программировании на языке Delphi возможна доработка программного продукта и устранение его главного недостатка.

Список использованных источников

1     Акулич. И. Л. Математическое программирование в примерах и задачах / И. Л. Акулич. - учеб. пособие для студентов эконом. спец. вузов. – М.: Высшая школа. 1986.-319 с.

2     Вирт. Н. Алгоритмы + структуры данных = программы / Н. Вирт. - М.: Мир. 1985.-353 с.

3     Муну. М. Математическое программирование. Теория алгоритмов / М. Муну. - М.: Наука. 1990.-342 с.

4     Вентцель. Е. С. Элементы динамического программирования / Е. С. Вентцель. - М.: Наука 1987.-472 с.

5     Аоки. М. Введение в методы оптимизации / М. Аоки. М.: Наука. 1977.-297 с.

6     Краснов. М. В помощь программисту / М. Краснов. – учеб. пособие – СПБ.: Графа. 1999.-214 с.

Приложение А

unit Unit1;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, Grids, XPMan, ComCtrls, ExtCtrls;

type

  TForm1 = class(TForm)

    Panel1: TPanel;

    StatusBar1: TStatusBar;

    StringGrid1: TStringGrid;

    GroupBox1: TGroupBox;

    Panel2: TPanel;

    Label1: TLabel;

    Edit1: TEdit;

    Panel3: TPanel;

    Label2: TLabel;

    Edit2: TEdit;

    Panel4: TPanel;

    Button1: TButton;

    Button2: TButton;

    Button3: TButton;

    Panel5: TPanel;

    GroupBox2: TGroupBox;

    Panel7: TPanel;

    Panel6: TPanel;

    Memo1: TMemo;

    Panel8: TPanel;

    Button4: TButton;

    Panel9: TPanel;

    Button5: TButton;

    Button6: TButton;

    XPManifest1: TXPManifest;

    Button7: TButton;

    Button8: TButton;

    Panel10: TPanel;

    Label3: TLabel;

    procedure Edit1KeyPress(Sender: TObject; var Key: Char);

    procedure Edit2KeyPress(Sender: TObject; var Key: Char);

    procedure FormCreate(Sender: TObject);

    procedure Button1Click(Sender: TObject);

    procedure StringGrid1KeyPress(Sender: TObject; var Key: Char);

    procedure Button2Click(Sender: TObject);

    procedure Button3Click(Sender: TObject);

    procedure Memo1KeyPress(Sender: TObject; var Key: Char);

    procedure Button4Click(Sender: TObject);

    procedure Button5Click(Sender: TObject);

    procedure Button6Click(Sender: TObject);

    procedure Button7Click(Sender: TObject);

    procedure Button8Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

Type plan=Record

             x:byte;

             ws:real;

          End;

var

  Form1: TForm1;

  Z:array [1..250,1..3]of real;

  P:array [1..250,1..3]of plan;

  ptemp:array[0..250]of plan;

  kc,kr,shag,s,a:byte;

  prib,max:real;

implementation

{$R *.dfm}

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);

begin

Key:=#0;

end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);

begin

If not (Key in ['0'..'9',#8]) Then Key:=#0;

end;

procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);

begin

Key:=#0;

end;

procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);

begin

If not (Key in ['0'..'9',',',#8]) Then Key:=#0;

end;

procedure TForm1.Button3Click(Sender: TObject);

begin

close;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

StringGrid1.Cells[0,0]:='X';

StringGrid1.Cells[0,1]:='F1(x)';

StringGrid1.Cells[1,0]:='1';

StringGrid1.Enabled:=false;

Button2.Enabled:=false;

Button4.Enabled:=false;

Button5.Enabled:=false;

Button6.Enabled:=false;

Button7.Visible:=false;

Button8.Enabled:=false;

Memo1.Enabled:=false;

Showmessage('Текущая версия программы предназначена для распределения инвестиций, только между 3-мя предприятиями!');

Edit2.Enabled:=false;

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

Edit1.Enabled:=true;

{Edit2.Enabled:=true;}

Button1.Enabled:=true;

Button2.Enabled:=false;

Button4.Enabled:=false;

Button7.Visible:=false;

StringGrid1.Enabled:=false;

end;

procedure TForm1.Button6Click(Sender: TObject);

begin

StringGrid1.Enabled:=true;

Button5.Enabled:=false;

Button6.Enabled:=false;

Button2.Enabled:=true;

Button4.Enabled:=true;

Button7.Visible:=true;

end;

procedure TForm1.Button7Click(Sender: TObject);

var i,j:byte;

begin

For i:=1 to StringGrid1.ColCount-1 do

   For j:=1 to StringGrid1.RowCount-1 do

       StringGrid1.Cells[i,j]:='';

Button7.Visible:=false;

end;

procedure TForm1.Button8Click(Sender: TObject);

var i,j:byte;

begin

For i:=1 to StringGrid1.ColCount-1 do

   For j:=1 to StringGrid1.RowCount-1 do

       StringGrid1.Cells[i,j]:='';

Edit1.Text:='3';

Edit2.Text:='3';

Edit1.Enabled:=true;

{Edit2.Enabled:=true;}

StringGrid1.ColCount:=2;

StringGrid1.RowCount:=2;

StringGrid1.Cells[0,0]:='X';

StringGrid1.Cells[0,1]:='F1(x)';

StringGrid1.Cells[1,0]:='1';

StringGrid1.Enabled:=false;

Button1.Enabled:=true;

Button5.Enabled:=false;

Button8.Enabled:=false;

Memo1.Enabled:=false;

shag:=0; prib:=0; max:=0; kc:=0; kr:=0; s:=0; a:=0;

Memo1.Clear;

end;

procedure TForm1.Button1Click(Sender: TObject);

Var i:byte;

begin

If (Edit1.Text='')

   Then Showmessage('Введите количество вкладываемых средств!')

   Else If ((Edit1.Text='0')or(Edit1.Text='1')or(Edit1.Text='2'))

           Then Showmessage('Для количества вкладываемых средств нужно ввести значение больше 2 у.е.!')

           Else If (Length(Edit1.Text)>3)

                   Then Begin Showmessage('Для количества вкладываемых средств слишком большое значение!'); Edit1.Clear; End

                   Else If (StrToInt(Edit1.Text)>250)

                           Then Showmessage('Для количества вкладываемых средств слишком большое значение!')

                           Else If (Edit2.Text='')

                                   Then Showmessage('Введите колличество предприятий!')

                                   Else If (Edit2.Text='0')

                                           Then Showmessage('Для количества предприятий нужно ввести значение отличное от нуля!')

                                           Else If (Length(Edit2.Text)>1)

                                                    Then Begin Showmessage('Для колличества предприятий слишком большое значение!'); Edit2.Clear; End

                                                    Else If (StrToInt(Edit2.Text)>3)

                                                             Then Showmessage('Для колличества предприятий слишком большое значение!')

                                                             Else

   Begin

      StringGrid1.ColCount:=StrToInt(Edit1.Text)+1;

      StringGrid1.RowCount:=StrToInt(Edit2.Text)+1;

      kc:=StrToInt(Edit1.Text);

      kr:=StrToInt(Edit2.Text);

      For i:=2 to StringGrid1.ColCount-1 do

         StringGrid1.Cells[i,0]:=IntToStr(i);

      For i:=2 to StringGrid1.RowCount-1 do

         StringGrid1.Cells[0,i]:='F'+IntToStr(i)+'(x)';

      StringGrid1.Enabled:=true;

      Edit1.Enabled:=false;

      {Edit2.Enabled:=false;}

      Button1.Enabled:=false;

      Button2.Enabled:=true;

      Button4.Enabled:=true;

   End;

end;

procedure TForm1.Button4Click(Sender: TObject);

Var i,j,x,count:byte;

    b1,b2,b3,b4:boolean;

    str:string;

begin

str:='';

b1:=false; b2:=false; b3:=false; b4:=false; count:=0;

For i:=1 to StringGrid1.ColCount-1 do

   For j:=1 to StringGrid1.RowCount-1 do

      If (StringGrid1.Cells[i,j]='') Then b1:=true;

If b1 Then Showmessage('Не все поля таблицы заполнены!')

      Else Begin

              For i:=1 to StringGrid1.ColCount-1 do

                 For j:=1 to StringGrid1.RowCount-1 do

                    Begin

                       If (Length(StringGrid1.Cells[i,j])>5) Then Begin b2:=true; StringGrid1.Cells[i,j]:=''; End;

                    End;

              If b2 Then Showmessage('В таблицу внесено слищком большое число прироста прибыли предприятия')

                    Else Begin

                            For i:=1 to StringGrid1.ColCount-1 do

                               For j:=1 to StringGrid1.RowCount-1 do

                                  Begin

                                     str:=StringGrid1.Cells[i,j];

                                     For x:=1 to Length(str) do

                                        If (str[x]=',') Then inc(count);

                                     If ((count>1)or(str[1]=',')or(str[Length(str)]=',')) Then b3:=true;

                                     str:=''; count:=0;

                                  End;

                            If b3 Then Begin Showmessage('В таблице неверно расставлены запятые!'); Button7.Visible:=true; End

                                  Else Begin

                                          j:=1;

                                          Repeat

                                             For i:=1 to StringGrid1.ColCount-2 do

                                                If ((StrToFloat(StringGrid1.Cells[i,j]))>(StrToFloat (StringGrid1.Cells[i+1,j])))

                                                    Then b4:=true;

                                             inc(j);

                                          Until (j=StringGrid1.RowCount);

                                          If b4 Then Begin Showmessage('Числовые данные в таблице заданы неверно!'); Button7.Visible:=true; End

                                                Else Begin

                                                       Button2.Enabled:=false;

                                                       Button4.Enabled:=false;

                                                       Button6.Enabled:=true;

                                                       Button5.Enabled:=true;

                                                       Button7.Visible:=false;

                                                       StringGrid1.Enabled:=false;

                                                     End;

                                       End;

                         End;

           End;

end;

procedure TForm1.Button5Click(Sender: TObject);

Var i,j:byte;

    px,wx:real;

begin

prib:=0;

Memo1.Clear;

Memo1.Enabled:=true;

Button6.Enabled:=false;

Button8.Enabled:=true;

{-------------------Обработка первого шага------------------------------}

For i:=1 to kc do

   For j:=1 to kr do

       Z[i,j]:=StrToFloat(StringGrid1.Cells[i,j]);

shag:=kr;

Memo1.Lines.Add('Количество вкладываемых средств: '+IntToStr(kc)+' у.е.');

Memo1.Lines.Add('Количество шагов оптимизации: '+IntToStr(shag));

Memo1.Lines.Add('');

For i:=1 to kc do

   Begin

      P[i,shag].x:=i;

      P[i,shag].ws:=Z[i,shag];

   End;

Memo1.Lines.Add('===================================================');

{-------------------Обработка второго шага------------------------------}

s:=1; j:=1;

Repeat

    For i:=0 to s do

       Begin

         If (i<>0)

             Then Begin If (i=s) Then Begin px:=Z[i,shag-1]; wx:=0; End

                                 Else Begin px:=Z[i,shag-1]; wx:=P[s-i,shag].ws; End;

                  End

                  Else Begin px:=0; wx:=P[s-i,shag].ws; End;

         Memo1.Lines.Add('| '+FloatToStr(px)+' | '+'x = '+IntToStr(i)+' | '+FloatToStr(wx)+' |');

         ptemp[i].x:=i; ptemp[i].ws:=px+wx;

         Memo1.Lines.Add('W(s) = '+FloatToStr(px+wx));

        End;

    max:=ptemp[0].ws; a:=0;

    For i:=0 to s do

       If ptemp[i].ws>max Then Begin max:=ptemp[i].ws; a:=i; End;

    inc(j);

    P[j-1,2]:=ptemp[a];

Memo1.Lines.Add('===================================================');

    inc(s);

Until s=(kc+1);

shag:=2; s:=kc; j:=1;

Repeat

    For i:=0 to s do

       Begin

         If (i<>0)

             Then Begin If (i=s) Then Begin px:=Z[i,shag-1]; wx:=0; End

                                 Else Begin px:=Z[i,shag-1]; wx:=P[s-i,shag].ws; End;

                  End

                  Else Begin px:=0; wx:=P[s-i,shag].ws; End;

         Memo1.Lines.Add('| '+FloatToStr(px)+' | '+'x = '+IntToStr(i)+' | '+FloatToStr(wx)+' |');

         ptemp[i].x:=i; ptemp[i].ws:=px+wx;

         Memo1.Lines.Add('W(s) = '+FloatToStr(px+wx));

        End;

    max:=ptemp[0].ws; a:=0;

    For i:=0 to s do

       If ptemp[i].ws>max Then Begin max:=ptemp[i].ws; a:=i; End;

    inc(j);

    P[j-1,1]:=ptemp[a];

Memo1.Lines.Add('===================================================');

    inc(s);

Until s=(kc+1);

shag:=1; s:=kc; j:=1;

Repeat

   max:=P[j,shag].ws;

   For i:=1 to s do

       If P[i,shag].ws>max Then Begin max:=P[i,shag].ws; a:=i; End;

   Memo1.Lines.Add(IntToStr(shag)+' предприятию выделить '+FloatToStr(P[a,shag].x)+' у.е.');

   prib:=prib+P[a,shag].ws;

   s:=s-P[a,shag].x;

   inc(shag);

Until shag=kr;

For i:=1 to kc do

   If P[i,shag].x=s

      Then Memo1.Lines.Add(IntToStr(shag)+' предприятию выделить '+FloatToStr(P[i,shag].x)+' у.е.');

Memo1.Lines.Add('');

Memo1.Lines.Add('Ожидаемая прибыль: '+FloatToStr(prib)+' у.е.');

end;

Initialization

shag:=0; prib:=0; max:=0; kc:=0; kr:=0; s:=0; a:=0; end.