Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СОДЕРЖАНИЕ тпр.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
775.69 Кб
Скачать

3.2 Ручная реализация венгерского метода

Приведение матрицы стоимостей, в результате приведения по столбцам и строкам была получена матрица С0

Тогда план, построенный методом северо-западного угла в нулевых клетках имеет вид:

Суммарная невязка:∆0=0+0+0+0+0+25+0+0+17+8+0+0=50;

∆0!=0 => переход на первый шаг первой итерации:

1 .1 :

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

1.3: h=min(невыделенный элемент С0)=min(17,7,1,19,7,32,14,29)=1; Тогда:

Переход на 1.1

1 .1:

Найден 0 с положительной невязкой в строке. Переход на 1.2

1.2: θ=min(25,8,30)=8; Тогда:

∆1=∆0-2*θ=34!=0. Переход на 2.1

2 .1

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

2.3: h=min(16,13,10,6,6,7,3,31)=3; Тогда:

Переход на 2.1

2 .1:

Найден 0 с положительной невязкой в строке. Переход на 2.2

2.2: θ=min(17,17,47,22)=17; Тогда:

∆2=∆1-2*θ=0 => План оптимален. Его стоимость F=2614

Конец решения.

3.3 Машинные эксперименты с программной системой

Перед вычислениями был проведён проверочный запуск программы, скриншот которой представлен на рисунке 3.1

Рисунок 3.1 – Проверочный прогон программы.

Прогон вычислений программы приведен на рисунке 3.2

Рисунок 3.2 – Прогон вычислений программы.

3.4 Качественная интерпретация полученных результатов

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

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

Заключение

В ходе выполнения курсового проекта были описаны метод северо-западного угла для нахождения опорного решения и распределительный метод для нахождения оптимального решения. Разработаны структурные схемы алгоритмов, реализующих методы северо-западного угла и распределительного. Написаны на языке Си и отлажены на Intel-совместимой ЭВМ программы реализации северо-западного угла и распределительного. Разработаны программы организации диалога, ведения файловых архивов исходных данных и результатов расчетов, графического представления результатов. Выполнены ручные расчеты по оптимизации закупки топлива в соответствии с венгерским и распределительным методами, а опорное решение найти методом северо-западного угла.

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

Список литературы:

1. Г.А. Черноморов - Методические указания по выполнению курсовой работы дисциплины “Системный анализ и исследование операций”/ Новочерк. гос. техн. ун-т. Новочеркасск: НГТУ, 1998. С. 76.

2. Зайченко Ю.П. - Исследование операций. -Киев: Вища шк., 1979.-392с.

3. Венцель Е.С. Исследование операций.- М.: Советское радио, 1972. -552с

Приложение А - Структурная схема алгоритма нахождения опорного решения методом северо-западного угла

Приложение В – Структурная схема алгоритма нахождения оптимального решения распределительным методом.

Приложение С - Листинг программы.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.IO;

namespace trnsport

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

class Point

{

private int x;

private int y;

public Point(int i, int j)

{

x = i;

y = j;

}

public int GetX()

{

return x;

}

public int GetY()

{

return y;

}

}

void equal(ref double[][] a, double[][] b)

{

for (int i = 0; i < b.Length; i++)

{

for (int j = 0; j < b[i].Length; j++)

{

a[i][j] = b[i][j];

}

}

}

bool numof1(double[][] f, int fi, int fj)

{

int s=0;

for (int i = 0; i < f.Length; i++)

{

if (f[i][fj] == 1) s++;

if (s >= 2) return false;

}

s=0;

for (int j = 0; j < f[0].Length; j++)

{

if (f[fi][j] == 1) s++;

if (s >= 2) return false;

}

return true;

}

bool circleOfEnumerizing(ref double[][] f, int circleLength, int curi, int curj, ref List<Point> c)

{

bool cir;

int r=circleLength+1;

double[][] f1 = new double[f.Length][];

for (int i = 0; i < f.Length; i++)

{

f1[i] = new double[f[i].Length];

}

equal(ref f1, f);

if (circleLength % 2 == 0)

{

for (int i = 0; i < f1.Length; i++)

{

if (f1[i][curj]==1)

{

f1[i][curj]=3;

cir=circleOfEnumerizing(ref f1, r,i,curj,ref c);

if (cir)

{

c.Add(new Point(curi, curj));

return true;

}

else equal(ref f1,f);

}

if (f1[i][curj] == 2 && circleLength>1)

{

c.Add(new Point(curi, curj));

return true;

}

}

return false;

}

else

{

for (int i = 0; i < f1[0].Length; i++)

{

if (f1[curi][i] == 1)

{

f1[curi][i] = 3;

cir = circleOfEnumerizing(ref f1, r, curi, i, ref c);

if (cir)

{

if(circleLength>1)c.Add(new Point(curi, curj));

return true;

}

else equal(ref f1,f);

}

}

return false;

}

}

private void exec_Click(object sender, EventArgs e)

{

String[] h0 = A.Text.Split('\n');

String[] h1 = B.Text.Split('\n');

String[] h = C.Text.Split('\n');

int m = h0.Length;

int n = h1.Length;

String[] q;

double[] a = new double[m];

double[] b = new double[n];

double[][] c = new double[m][];

double[][] x = new double[m][];

double[][] f = new double[m][];

for (int i = 0; i < n; i++)

{

try

{

b[i] = Convert.ToDouble(h1[i]);

}

catch (Exception ex)

{

X.Text = "Ошибка!\nЗначения нужд потребителей введены некорректно. Исправьте ошибку и повторите попытку";

return;

}

}

for (int i = 0; i < m; i++)

{

try

{

q = h[i].Split(' ');

}

catch (Exception ex)

{

X.Text = "Ошибка!\nРазмерность матрицы стоимостей перевозок единицы товара не соответствует количеству поставщиков и/или потребителей. Возможно, вы пропустили некоторые строки/столбцы. Исправьте ошибку и повторите попытку";

return;

}

try

{

a[i] = Convert.ToDouble(h0[i]);

}

catch (Exception ex)

{

X.Text = "Ошибка!\nЗначения запасов поставщиков введены некорректно. Исправьте ошибку и повторите попытку";

return;

}

c[i] = new double[n];

x[i] = new double[n];

f[i] = new double[n];

for (int j = 0; j < n; j++)

{

try

{

c[i][j] = Convert.ToDouble(q[j]);

}

catch (Exception ex)

{

X.Text = "Ошибка!\nЗначения стоимостей перевозок единицы товара введены некорректно. Исправьте ошибку и повторите попытку";

return;

}

x[i][j] = 0;

f[i][j] = 0;

}

}

double bal = 0;

for (int i = 0; i < m; i++)

{

bal += a[i];

}

for (int i = 0; i < n; i++)

{

bal -= b[i];

}

if (Math.Abs(bal)>0.0000000001)

{

X.Text = "Ошибка!\nЗадача несбалансирована. Исправьте ошибку (сбалансируйте задачу) и повторите попытку";

return;

}

List<Point> circle = new List<Point>();

int ai = 0, bj = 0, quanOfVar = 0;

double p;

double[] ta = a, tb = b;

do

{

p = Math.Min(ta[ai], tb[bj]);

ta[ai] -= p;

tb[bj] -= p;

x[ai][bj] = p;

f[ai][bj] = 1;

if (ta[ai] == 0)

{

ai++;

}

if (tb[bj] == 0)

{

bj++;

}

quanOfVar++;

}

while (ai <= m - 1 && bj <= n - 1);

quanOfVar = m + n - 1 - quanOfVar;

bool is1r1c;

for (int k = 0; k < quanOfVar; k++)

{

is1r1c = false;

for (int i = 0; i < m; i++)

{

for (int j = 0; j < n; j++)

{

if (f[i][j] == 0 && numof1(f, i, j))

{

is1r1c = true;

f[i][j] = 1;

}

if (is1r1c) break;

}

if (is1r1c) break;

}

}

bool isopt;

bool isNegative;

double[][] f1 = new double[f.Length][];

for (int i = 0; i < f.Length; i++)

{

f1[i] = new double[f[i].Length];

}

double mincount, cost;

int numofmatr = 0, numofc=0;

do

{

numofmatr++;

isopt = true;

isNegative = false;

for (int i = 0; i < m; i++)

{

for (int j = 0; j < n; j++)

{

equal(ref f1, f);

numofc++;

circle.Clear();

if (f[i][j] == 0)

{

circle.Add(new Point(i,j));

f1[i][j] = 2;

cost = 0;

bool err=circleOfEnumerizing(ref f1, 1, i, j, ref circle);

for (int k = 0; k < circle.Count; k++)

{

cost+=c[circle[k].GetX()][circle[k].GetY()] * Math.Pow(-1, k);

}

isNegative = (cost < 0);

}

if (isNegative) break;

}

if (isNegative) break;

}

if (isNegative)

{

mincount = x[circle[1].GetX()][circle[1].GetY()];

isopt = false;

for (int i = 1; i < circle.Count/2; i++)

{

mincount=(Math.Min(mincount, x[circle[2*i+1].GetX()][circle[2*i+1].GetY()]));

}

bool v = true;

f[circle[0].GetX()][circle[0].GetY()] = 1;

for (int i = 0; i < circle.Count; i++)

{

x[circle[i].GetX()][circle[i].GetY()]+=mincount*Math.Pow(-1,i);

if (x[circle[i].GetX()][circle[i].GetY()] == 0 && v && i%2==1)

{

f[circle[i].GetX()][circle[i].GetY()] = 0;

v = false;

}

}

}

}

while (!isopt);

double s = 0;

int maxstr = 0;

for (int i = 0; i < m; i++)

{

for (int j = 0; j < n; j++)

{

if (Convert.ToString(x[i][j]).Length > maxstr) maxstr = Convert.ToString(x[i][j]).Length;

}

}

maxstr += 1;

X.Text = "Количество итераций=" + Convert.ToString(numofmatr) + "\nКоличество посчитанных циклов=" + Convert.ToString(numofc) + "\n\nМатрица перевозок:\n\n";

for (int i = 0; i < m; i++)

{

for (int j = 0; j < n; j++)

{

for (int d = 0; d < maxstr - Convert.ToString(x[i][j]).Length; d++) X.Text += ' ';

X.Text += Convert.ToString(x[i][j]);

s += x[i][j]*c[i][j];

}

X.Text += '\n';

}

X.Text += "\nОбщая стоимость перевозки=" + Convert.ToString(s);

}

private void sc_Click(object sender, EventArgs e)

{

SaveFileDialog sfd = new SaveFileDialog();

sfd.Filter = "Текстовые Файлы(*.txt)|*.txt";

sfd.ShowDialog();

string s_f = sfd.FileName;

sfd.Dispose();

StreamWriter x;

try

{

x = new StreamWriter(s_f, false);

}

catch (Exception)

{

return;

}

x.WriteLine(C.Lines.Length);

for (int i = 0; i < C.Lines.Length; i++)

{

x.WriteLine(C.Lines[i]);

}

x.WriteLine(A.Lines.Length);

for (int i = 0; i < A.Lines.Length; i++)

{

x.WriteLine(A.Lines[i]);

}

x.WriteLine(B.Lines.Length);

for (int i = 0; i < B.Lines.Length; i++)

{

x.WriteLine(B.Lines[i]);

}

x.Close();

}

private void lc_Click(object sender, EventArgs e)

{

OpenFileDialog sfd = new OpenFileDialog();

sfd.Filter = "Текстовые Файлы(*.txt)|*.txt";

sfd.ShowDialog();

string s_f = sfd.FileName;

sfd.Dispose();

StreamReader x;

try

{

x = new StreamReader(s_f, false);

}

catch (ArgumentException)

{

return;

}

catch (FileNotFoundException)

{

X.Text = "Ошибка! Файл не найден";

return;

}

string tmp = x.ReadLine();

C.Text = "";

A.Text = "";

B.Text = "";

int n = 0;

try

{

n = Convert.ToInt16(tmp);

}

catch (Exception)

{

X.Text = "Ошибка чтения файла! Возможно файл не является архивом начальных условий программы. Попробуйте загрузить другой файл или ввести данные вручную!";

return;

}

tmp = "";

for (int i = 0; i < n; i++)

{

tmp += x.ReadLine();

if (i<n-1) tmp+="\n";

}

C.Text = tmp;

tmp = x.ReadLine();

try

{

n = Convert.ToInt16(tmp);

}

catch (Exception)

{

X.Text = "Ошибка чтения файла! Возможно файл не является архивом начальных условий программы. Попробуйте загрузить другой файл или ввести данные вручную!";

return;

}

tmp = "";

for (int i = 0; i < n; i++)

{

A.Text+= x.ReadLine();

if (i < n - 1) A.Text += "\n";

}

tmp = x.ReadLine();

try

{

n = Convert.ToInt16(tmp);

}

catch (Exception)

{

X.Text = "Ошибка чтения файла! Возможно файл не является архивом начальных условий программы. Попробуйте загрузить другой файл или ввести данные вручную!";

return;

}

tmp = "";

for (int i = 0; i < n; i++)

{

B.Text += x.ReadLine();

if (i < n - 1) B.Text += "\n";

}

x.Close();

}

private void sx_Click(object sender, EventArgs e)

{

SaveFileDialog sfd = new SaveFileDialog();

sfd.Filter = "Текстовые Файлы(*.txt)|*.txt";

sfd.ShowDialog();

string s_f = sfd.FileName;

sfd.Dispose();

StreamWriter x;

try

{

x = new StreamWriter(s_f, false);

}

catch (Exception)

{

return;

}

for (int i = 0; i < X.Lines.Length; i++)

{

x.WriteLine(X.Lines[i]);

}

x.Close();

}

}

}

41