Program.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.IO;
  8. namespace MinElKuzminEkz
  9. {
  10. internal class Program
  11. {
  12. private static StreamWriter traceWriter;
  13. private static StreamWriter debugWriter;
  14. public static void Main(string[] args)
  15. {
  16. try
  17. {
  18. // Открываем файлы для записи trace и debug логов
  19. traceWriter = new StreamWriter("trace_log.txt");
  20. debugWriter = new StreamWriter("debug_log.txt");
  21. // Добавляем слушателя для Trace
  22. Trace.Listeners.Add(new TextWriterTraceListener(traceWriter));
  23. Trace.AutoFlush = true;
  24. // Добавляем слушателя для Debug
  25. Debug.Listeners.Add(new TextWriterTraceListener(debugWriter));
  26. Debug.AutoFlush = true;
  27. Trace.WriteLine("Файл успешно считан");
  28. // Чтение данных из файла
  29. string[] lines = File.ReadAllLines("C:\\Users\\7\\source\\repos\\methodMinimalElKuzmin\\methodMinimalElKuzmin\\test.txt");
  30. // Инициализация массивов на основе данных из файла
  31. int[] a = Array.ConvertAll(lines[0].Split(','), int.Parse);
  32. int[] b = Array.ConvertAll(lines[1].Split(','), int.Parse);
  33. double[,] costs = new double[3, 3];
  34. // Заполнение матриц costs и supply_plan
  35. int index = 2; // начинаем с третьей строки файла
  36. for (int i = 0; i < 3; i++)
  37. {
  38. string[] costValues = lines[index].Split(',');
  39. for (int j = 0; j < 3; j++)
  40. {
  41. costs[i, j] = double.Parse(costValues[j]);
  42. }
  43. index++;
  44. }
  45. Trace.WriteLine("Матрица инициализирована");
  46. if (Utility.CheckClosure(a, b))
  47. {
  48. Console.WriteLine("Транспортная задача является закрытой");
  49. }
  50. else
  51. {
  52. Console.WriteLine("Транспортная задача является открытой");
  53. }
  54. // Применение метода
  55. int[,] supply_plan = Utility.MinElementMethod(a, b, costs); //MinElementMethod
  56. // Вывод плана поставок
  57. for (int i = 0; i < supply_plan.GetLength(0); i++)
  58. {
  59. for (int j = 0; j < supply_plan.GetLength(1); j++)
  60. {
  61. Console.Write($"{supply_plan[i, j]} ");
  62. }
  63. Console.WriteLine();
  64. }
  65. // Проверка на вырожденность опорного плана
  66. if (Utility.CheckIfVyrozhdeno(supply_plan))
  67. {
  68. Console.WriteLine("Опорный план вырожденный.");
  69. }
  70. else
  71. {
  72. Console.WriteLine("Опорный план невырожденный.");
  73. }
  74. // Расчёт целевой функции
  75. Console.WriteLine($"Целевая функция: {Utility.CalculateCelevayaFunction(costs, supply_plan)}");
  76. Console.WriteLine("Опорный план оптимален.");
  77. Trace.WriteLine("Программа успешно завершила рассчет");
  78. }
  79. catch (Exception ex)
  80. {
  81. Trace.WriteLine($"Error: {ex.Message}");
  82. Console.WriteLine($"Error: {ex.Message}");
  83. }
  84. finally
  85. {
  86. // Закрываем файлы после использования
  87. traceWriter.Close();
  88. debugWriter.Close();
  89. Console.ReadKey();
  90. }
  91. }
  92. }
  93. //класс utility
  94. public static class Utility
  95. {
  96. public static bool CheckClosure(int[] a, int[] b)
  97. {
  98. int sum_a = a.Sum();
  99. int sum_b = b.Sum();
  100. Debug.WriteLine($"Проверка на закрытость задачи: A = {sum_a}, B = {sum_b}");
  101. return sum_a == sum_b;
  102. }
  103. public static bool CheckIfVyrozhdeno(int[,] supply_plan)
  104. {
  105. int n = supply_plan.GetLength(0);
  106. int m = supply_plan.GetLength(1);
  107. int kolvo_polozh_komponent = 0;
  108. for (int i = 0; i < n; i++)
  109. {
  110. for (int j = 0; j < m; j++)
  111. {
  112. if (supply_plan[i, j] > 0)
  113. {
  114. kolvo_polozh_komponent++;
  115. }
  116. }
  117. }
  118. Debug.WriteLine($"Проверка вырожденности A = {kolvo_polozh_komponent}, B = {n + m - 1}");
  119. return kolvo_polozh_komponent != n + m - 1;
  120. }
  121. public static double CalculateCelevayaFunction(double[,] costs, int[,] supply_plan)
  122. {
  123. double result = 0;
  124. for (int i = 0; i < costs.GetLength(0); i++)
  125. {
  126. for (int j = 0; j < costs.GetLength(1); j++)
  127. {
  128. if (supply_plan[i, j] > 0)
  129. {
  130. result += costs[i, j] * supply_plan[i, j];
  131. }
  132. }
  133. }
  134. Debug.WriteLine($"Рассчет целевой фунции = {result}");
  135. return result;
  136. }
  137. public static int[,] MinElementMethod(int[] a, int[] b, double[,] costs)
  138. {
  139. int n = a.Length;
  140. int m = b.Length;
  141. int[,] supply_plan = new int[n, m]; // матрица для опорного плана
  142. bool[,] bools_suply_plan = new bool[n, m];
  143. while (!CheckIfMatrixAllTrue(bools_suply_plan))
  144. {
  145. List<(int, int)> positions = FindMinElementPositions(costs, bools_suply_plan);
  146. int min_j = int.MaxValue;
  147. int index_of_min_j = -1;
  148. for (int k = 0; k < positions.Count; k++)
  149. {
  150. if (positions[k].Item2 < min_j)
  151. {
  152. min_j = positions[k].Item2;
  153. index_of_min_j = k;
  154. }
  155. }
  156. int min_i = positions.ElementAt(index_of_min_j).Item1;
  157. int value = Math.Min(a[min_i], b[min_j]);
  158. a[min_i] -= value;
  159. b[min_j] -= value;
  160. supply_plan[min_i, min_j] = value;
  161. bools_suply_plan[min_i, min_j] = true;
  162. if (a[min_i] == 0)
  163. {
  164. for (int j = 0; j < m; j++)
  165. {
  166. if (bools_suply_plan[min_i, j] == false)
  167. {
  168. bools_suply_plan[min_i, j] = true;
  169. }
  170. }
  171. }
  172. else if (b[min_j] == 0)
  173. {
  174. for (int i = 0; i < n; i++)
  175. {
  176. if (bools_suply_plan[i, min_j] == false)
  177. {
  178. bools_suply_plan[i, min_j] = true;
  179. }
  180. }
  181. }
  182. }
  183. Debug.WriteLine($"Метод минимального элемента : опорный план инициализирован");
  184. return supply_plan;
  185. }
  186. public static bool CheckIfMatrixAllTrue(bool[,] bools)
  187. {
  188. for (int i = 0; i < bools.GetLength(0); i++)
  189. {
  190. for (int j = 0; j < bools.GetLength(1); j++)
  191. {
  192. if (bools[i, j] == false)
  193. {
  194. return false;
  195. }
  196. }
  197. }
  198. return true;
  199. }
  200. public static List<(int, int)> FindMinElementPositions(double[,] costs, bool[,] bools)
  201. {
  202. List<(int, int)> positions = new List<(int, int)>();
  203. double min = double.MaxValue;
  204. for (int i = 0; i < costs.GetLength(0); i++)
  205. {
  206. for (int j = 0; j < costs.GetLength(1); j++)
  207. {
  208. if (bools[i, j] == false && costs[i, j] < min)
  209. {
  210. min = costs[i, j];
  211. positions.Clear();
  212. positions.Add((i, j));
  213. }
  214. else if (bools[i, j] == false && costs[i, j] == min)
  215. {
  216. positions.Add((i, j));
  217. }
  218. }
  219. }
  220. return positions;
  221. }
  222. }
  223. }