using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace MinElKuzminEkz { internal class Program { private static StreamWriter traceWriter; private static StreamWriter debugWriter; public static void Main(string[] args) { try { // Открываем файлы для записи trace и debug логов traceWriter = new StreamWriter("trace_log.txt"); debugWriter = new StreamWriter("debug_log.txt"); // Добавляем слушателя для Trace Trace.Listeners.Add(new TextWriterTraceListener(traceWriter)); Trace.AutoFlush = true; // Добавляем слушателя для Debug Debug.Listeners.Add(new TextWriterTraceListener(debugWriter)); Debug.AutoFlush = true; Trace.WriteLine("Файл успешно считан"); // Чтение данных из файла string[] lines = File.ReadAllLines("C:\\Users\\7\\source\\repos\\methodMinimalElKuzmin\\methodMinimalElKuzmin\\test.txt"); // Инициализация массивов на основе данных из файла int[] a = Array.ConvertAll(lines[0].Split(','), int.Parse); int[] b = Array.ConvertAll(lines[1].Split(','), int.Parse); double[,] costs = new double[3, 3]; // Заполнение матриц costs и supply_plan int index = 2; // начинаем с третьей строки файла for (int i = 0; i < 3; i++) { string[] costValues = lines[index].Split(','); for (int j = 0; j < 3; j++) { costs[i, j] = double.Parse(costValues[j]); } index++; } Trace.WriteLine("Матрица инициализирована"); if (Utility.CheckClosure(a, b)) { Console.WriteLine("Транспортная задача является закрытой"); } else { Console.WriteLine("Транспортная задача является открытой"); } // Применение метода int[,] supply_plan = Utility.MinElementMethod(a, b, costs); //MinElementMethod // Вывод плана поставок for (int i = 0; i < supply_plan.GetLength(0); i++) { for (int j = 0; j < supply_plan.GetLength(1); j++) { Console.Write($"{supply_plan[i, j]} "); } Console.WriteLine(); } // Проверка на вырожденность опорного плана if (Utility.CheckIfVyrozhdeno(supply_plan)) { Console.WriteLine("Опорный план вырожденный."); } else { Console.WriteLine("Опорный план невырожденный."); } // Расчёт целевой функции Console.WriteLine($"Целевая функция: {Utility.CalculateCelevayaFunction(costs, supply_plan)}"); Console.WriteLine("Опорный план оптимален."); Trace.WriteLine("Программа успешно завершила рассчет"); } catch (Exception ex) { Trace.WriteLine($"Error: {ex.Message}"); Console.WriteLine($"Error: {ex.Message}"); } finally { // Закрываем файлы после использования traceWriter.Close(); debugWriter.Close(); Console.ReadKey(); } } } //класс utility public static class Utility { public static bool CheckClosure(int[] a, int[] b) { int sum_a = a.Sum(); int sum_b = b.Sum(); Debug.WriteLine($"Проверка на закрытость задачи: A = {sum_a}, B = {sum_b}"); return sum_a == sum_b; } public static bool CheckIfVyrozhdeno(int[,] supply_plan) { int n = supply_plan.GetLength(0); int m = supply_plan.GetLength(1); int kolvo_polozh_komponent = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (supply_plan[i, j] > 0) { kolvo_polozh_komponent++; } } } Debug.WriteLine($"Проверка вырожденности A = {kolvo_polozh_komponent}, B = {n + m - 1}"); return kolvo_polozh_komponent != n + m - 1; } public static double CalculateCelevayaFunction(double[,] costs, int[,] supply_plan) { double result = 0; for (int i = 0; i < costs.GetLength(0); i++) { for (int j = 0; j < costs.GetLength(1); j++) { if (supply_plan[i, j] > 0) { result += costs[i, j] * supply_plan[i, j]; } } } Debug.WriteLine($"Рассчет целевой фунции = {result}"); return result; } public static int[,] MinElementMethod(int[] a, int[] b, double[,] costs) { int n = a.Length; int m = b.Length; int[,] supply_plan = new int[n, m]; // матрица для опорного плана bool[,] bools_suply_plan = new bool[n, m]; while (!CheckIfMatrixAllTrue(bools_suply_plan)) { List<(int, int)> positions = FindMinElementPositions(costs, bools_suply_plan); int min_j = int.MaxValue; int index_of_min_j = -1; for (int k = 0; k < positions.Count; k++) { if (positions[k].Item2 < min_j) { min_j = positions[k].Item2; index_of_min_j = k; } } int min_i = positions.ElementAt(index_of_min_j).Item1; int value = Math.Min(a[min_i], b[min_j]); a[min_i] -= value; b[min_j] -= value; supply_plan[min_i, min_j] = value; bools_suply_plan[min_i, min_j] = true; if (a[min_i] == 0) { for (int j = 0; j < m; j++) { if (bools_suply_plan[min_i, j] == false) { bools_suply_plan[min_i, j] = true; } } } else if (b[min_j] == 0) { for (int i = 0; i < n; i++) { if (bools_suply_plan[i, min_j] == false) { bools_suply_plan[i, min_j] = true; } } } } Debug.WriteLine($"Метод минимального элемента : опорный план инициализирован"); return supply_plan; } public static bool CheckIfMatrixAllTrue(bool[,] bools) { for (int i = 0; i < bools.GetLength(0); i++) { for (int j = 0; j < bools.GetLength(1); j++) { if (bools[i, j] == false) { return false; } } } return true; } public static List<(int, int)> FindMinElementPositions(double[,] costs, bool[,] bools) { List<(int, int)> positions = new List<(int, int)>(); double min = double.MaxValue; for (int i = 0; i < costs.GetLength(0); i++) { for (int j = 0; j < costs.GetLength(1); j++) { if (bools[i, j] == false && costs[i, j] < min) { min = costs[i, j]; positions.Clear(); positions.Add((i, j)); } else if (bools[i, j] == false && costs[i, j] == min) { positions.Add((i, j)); } } } return positions; } } }