Slavik9510

Untitled

Apr 24th, 2023 (edited)
753
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 20.13 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Xml.Linq;
  8.  
  9. namespace DO_Lab4
  10. {
  11.     public static class MyExtensions
  12.     {
  13.         public static void Fill<T>(this T[,] array, T value)
  14.         {
  15.             for (int i = 0; i < array.GetLength(0); i++)
  16.             {
  17.                 for (int j = 0; j < array.GetLength(1); j++)
  18.                 {
  19.                     array[i, j] = value;
  20.                 }
  21.             }
  22.         }
  23.         public static void Remove(this ref Direction value, Direction flags)
  24.         {
  25.             value = value & ~flags;
  26.         }
  27.         public static void Add(this ref Direction value, Direction flags)
  28.         {
  29.             value |= flags;
  30.         }
  31.         public static bool Contains(this Direction value, Direction flag)
  32.         {
  33.             return (value & flag) != Direction.None;
  34.         }
  35.  
  36.     }
  37.     [Flags]
  38.     public enum Direction
  39.     {
  40.         None = 0,
  41.         Left = 1,
  42.         Right = 2,
  43.         Up = 4,
  44.         Down = 8,
  45.         All = 16
  46.     }
  47.     class Vertex
  48.     {
  49.         public int Row;
  50.         public int Column;
  51.         public Direction AcceptableDirections;
  52.         public Vertex(int row, int column, Direction directions)
  53.         {
  54.             this.Row = row;
  55.             this.Column = column;
  56.             AcceptableDirections = directions;
  57.         }
  58.         public override bool Equals(object obj)
  59.         {
  60.             if (obj == null || GetType() != obj.GetType())
  61.             {
  62.                 return false;
  63.             }
  64.  
  65.             Vertex other = (Vertex)obj;
  66.             return (Row == other.Row && Column == other.Column);
  67.         }
  68.     }
  69.     struct Consumer
  70.     {
  71.         public int transportationCosts;
  72.         public int metNeeds;
  73.         public int sign;
  74.     }
  75.  
  76.     internal class PotencialMethod
  77.     {
  78.         int[] needs;
  79.         int[] stocks;
  80.         int[] u;
  81.         int[] v;
  82.         Consumer[,] consumers;
  83.  
  84.         //------------------------
  85.         private void printArr()
  86.         {
  87.             for (int i = 0; i < consumers.GetLength(0) + 1; i++)
  88.             {
  89.                 if (i < consumers.GetLength(0))
  90.                 {
  91.                     for (int j = 0; j < consumers.GetLength(1) + 1; j++)
  92.                     {
  93.                         if (j < consumers.GetLength(1))
  94.                         {
  95.                             Console.Write($"{consumers[i, j].transportationCosts} / {consumers[i, j].metNeeds,-4} ");
  96.                         }
  97.                         else
  98.                         {
  99.                             Console.WriteLine(stocks[i]);
  100.                         }
  101.                     }
  102.                 }
  103.                 else
  104.                 {
  105.                     for (int j = 0; j < needs.Length; j++)
  106.                     {
  107.                         Console.Write($"{needs[j],3} ");
  108.                     }
  109.                 }
  110.             }
  111.  
  112.             int sum = 0;
  113.             for (int i = 0; i < consumers.GetLength(0); i++)
  114.             {
  115.                 for (int j = 0; j < consumers.GetLength(1); j++)
  116.                 {
  117.                     sum += consumers[i, j].transportationCosts * consumers[i, j].metNeeds;
  118.                 }
  119.             }
  120.  
  121.             //Console.WriteLine("\nSUM  = " + sum);
  122.         }
  123.  
  124.         private void printSigns()
  125.         {
  126.             for (int i = 0; i < consumers.GetLength(0); i++)
  127.             {
  128.                 for (int j = 0; j < consumers.GetLength(1); j++)
  129.                 {
  130.                     Console.Write($"{consumers[i, j].sign,-3} ");
  131.                 }
  132.                 Console.WriteLine();
  133.             }
  134.         }
  135.         //------------------------
  136.         public PotencialMethod(string path)
  137.         {
  138.             string[] data = File.ReadAllLines(path);
  139.             stocks = new int[data.Length - 1];
  140.             u = new int[stocks.Length];
  141.             Array.Fill(u, int.MinValue);
  142.             needs = new int[data.Last().Split(' ').Length];
  143.             v = new int[needs.Length];
  144.             Array.Fill(v, int.MinValue);
  145.  
  146.             consumers = new Consumer[stocks.Length, needs.Length];
  147.  
  148.             for (int i = 0; i < consumers.GetLength(0); i++)
  149.             {
  150.                 for (int j = 0; j < consumers.GetLength(1); j++)
  151.                 {
  152.                     //consumers[i, j].metNeeds = 0;
  153.                 }
  154.             }
  155.  
  156.             for (int i = 0; i < data.Length; i++)
  157.             {
  158.                 string[] current = data[i].Split(' ');
  159.                 if (i < data.Length - 1)
  160.                 {
  161.                     for (int j = 0; j < current.Length; j++)
  162.                     {
  163.                         if (j < current.Length - 1)
  164.                         {
  165.                             consumers[i, j].transportationCosts = int.Parse(current[j]);
  166.                         }
  167.                         else
  168.                         {
  169.                             stocks[i] = int.Parse(current[j]);
  170.                         }
  171.                     }
  172.                 }
  173.                 else
  174.                 {
  175.                     for (int j = 0; j < current.Length; j++)
  176.                     {
  177.                         needs[j] = int.Parse(current[j]);
  178.                     }
  179.                 }
  180.             }
  181.  
  182.             // minimumElementMethod();
  183.             //printArr();
  184.         }
  185.  
  186.         private (int, int) findMin()
  187.         {
  188.             int min = int.MaxValue;
  189.             int iVal = -1, jVal = -1;
  190.  
  191.             for (int i = 0; i < consumers.GetLength(0); i++)
  192.             {
  193.                 if (stocks[i] == 0) continue;
  194.  
  195.                 for (int j = 0; j < consumers.GetLength(1); j++)
  196.                 {
  197.                     if (needs[j] != 0 && consumers[i, j].transportationCosts < min)
  198.                     {
  199.                         min = consumers[i, j].transportationCosts;
  200.                         iVal = i;
  201.                         jVal = j;
  202.                     }
  203.                 }
  204.             }
  205.             return (iVal, jVal);
  206.         }
  207.         private void minimumElementMethod()
  208.         {
  209.             bool isSolved = false;
  210.  
  211.             while (!isSolved)
  212.             {
  213.                 (int iVal, int jVal) = findMin();
  214.  
  215.                 int valueToTransport = Math.Min(stocks[iVal], needs[jVal]);
  216.                 consumers[iVal, jVal].metNeeds = valueToTransport;
  217.                 stocks[iVal] -= valueToTransport;
  218.                 needs[jVal] -= valueToTransport;
  219.  
  220.                 isSolved = true;
  221.                 for (int i = 0; i < needs.Length; i++)
  222.                 {
  223.                     if (needs[i] != 0)
  224.                     {
  225.                         isSolved = false;
  226.                         break;
  227.                     }
  228.                 }
  229.             }
  230.         }
  231.         private int findMostPopulatedRow()
  232.         {
  233.             int zeroPotencialRow = 0, max = 0;
  234.             for (int i = 0; i < consumers.GetLength(0); i++)
  235.             {
  236.                 int sum = 0;
  237.                 for (int j = 0; j < consumers.GetLength(1); j++)
  238.                 {
  239.                     if (consumers[i, j].metNeeds > 0)
  240.                     {
  241.                         sum++;
  242.                     }
  243.                 }
  244.                 if (i == 0)
  245.                 {
  246.                     max = sum;
  247.                 }
  248.                 if (i > 1 && sum > max)
  249.                 {
  250.                     zeroPotencialRow = i;
  251.                     max = sum;
  252.                 }
  253.             }
  254.             return zeroPotencialRow;
  255.         }
  256.         private void calcPotencials()
  257.         {
  258.             for (int i = 0; i < u.Length; i++)
  259.             {
  260.                 u[i] = int.MinValue;
  261.             }
  262.             for (int i = 0; i < v.Length; i++)
  263.             {
  264.                 v[i] = int.MinValue;
  265.             }
  266.             int zeroPotencialRow = findMostPopulatedRow();
  267.             u[zeroPotencialRow] = 0;
  268.             bool isSolved = false;
  269.             while (!isSolved)
  270.             {
  271.                 for (int i = 0; i < consumers.GetLength(0); i++)
  272.                 {
  273.                     for (int j = 0; j < consumers.GetLength(1); j++)
  274.                     {
  275.                         if (consumers[i, j].metNeeds == 0) continue;
  276.  
  277.                         if (v[j] == int.MinValue && u[i] != int.MinValue)
  278.                         {
  279.                             v[j] = consumers[i, j].transportationCosts - u[i];
  280.                         }
  281.                         else if (u[i] == int.MinValue && v[j] != int.MinValue)
  282.                         {
  283.                             u[i] = consumers[i, j].transportationCosts - v[j];
  284.                         }
  285.                     }
  286.                 }
  287.                 isSolved = true;
  288.                 for (int i = 0; i < u.Length; i++)
  289.                 {
  290.                     if (u[i] == int.MinValue)
  291.                     {
  292.                         isSolved = false;
  293.                         break;
  294.                     }
  295.                 }
  296.                 if (isSolved)
  297.                 {
  298.                     for (int i = 0; i < v.Length; i++)
  299.                     {
  300.                         if (v[i] == int.MinValue)
  301.                         {
  302.                             isSolved = false;
  303.                             break;
  304.                         }
  305.                     }
  306.                 }
  307.             }
  308.         }
  309.         private void calcDeltas()
  310.         {
  311.             for (int i = 0; i < consumers.GetLength(0); i++)
  312.             {
  313.                 for (int j = 0; j < consumers.GetLength(1); j++)
  314.                 {
  315.                     consumers[i, j].sign = u[i] + v[j] - consumers[i, j].transportationCosts;
  316.                 }
  317.             }
  318.         }
  319.         private bool findMaxDelta(out int row, out int column)
  320.         {
  321.             bool isSolved = true;
  322.             int maxDelta = -1;
  323.             row = -1; column = -1;
  324.             for (int i = 0; i < consumers.GetLength(0); i++)
  325.             {
  326.                 for (int j = 0; j < consumers.GetLength(1); j++)
  327.                 {
  328.                     if (consumers[i, j].sign > 0)
  329.                     {
  330.                         isSolved = false;
  331.                         if (maxDelta == -1)
  332.                         {
  333.                             maxDelta = consumers[i, j].sign;
  334.                             row = i;
  335.                             column = j;
  336.                         }
  337.                         else if (consumers[i, j].sign >= maxDelta)
  338.                         {
  339.                             maxDelta = consumers[i, j].sign;
  340.                             row = i;
  341.                             column = j;
  342.                         }
  343.                     }
  344.                 }
  345.             }
  346.             return isSolved;
  347.         }
  348.         private Direction calcDirections(int row, int column, Direction forbidden = Direction.None)
  349.         {
  350.             Direction acceptable = Direction.None;
  351.  
  352.             for (int i = 0; i < consumers.GetLength(0); i++)
  353.             {
  354.                 if (i == row) continue;
  355.                 if (consumers[i, column].metNeeds > 0)
  356.                 {
  357.                     if (i < row)
  358.                     {
  359.                         acceptable.Add(Direction.Up);
  360.                         i = row;
  361.                     }
  362.                     else
  363.                     {
  364.                         acceptable.Add(Direction.Down);
  365.                         break;
  366.                     }
  367.                 }
  368.             }
  369.  
  370.             for (int j = 0; j < consumers.GetLength(1); j++)
  371.             {
  372.                 if (j == column) continue;
  373.  
  374.                 if (consumers[row, j].metNeeds > 0)
  375.                 {
  376.                     if (j < column)
  377.                     {
  378.                         acceptable.Add(Direction.Left);
  379.                         j = column;
  380.                     }
  381.                     else
  382.                     {
  383.                         acceptable.Add(Direction.Right);
  384.                         break;
  385.                     }
  386.                 }
  387.             }
  388.             acceptable.Remove(forbidden);
  389.             return acceptable;
  390.         }
  391.         private Vertex findNextVertex(Vertex vertex)
  392.         {
  393.             if (vertex.AcceptableDirections == Direction.None)
  394.             {
  395.                 throw new Exception("Немає допустимих напрямків");
  396.             }
  397.             if (vertex.AcceptableDirections.Contains(Direction.Up))
  398.             {
  399.                 for (int i = vertex.Row - 1; i >= 0; i--)
  400.                 {
  401.                     if (consumers[i, vertex.Column].metNeeds > 0)
  402.                     {
  403.                         vertex.AcceptableDirections.Remove(Direction.Up);
  404.                         return new Vertex(i, vertex.Column, calcDirections(i, vertex.Column, forbidden: Direction.Down));
  405.                     }
  406.                 }
  407.             }
  408.             else if (vertex.AcceptableDirections.Contains(Direction.Down))
  409.             {
  410.                 for (int i = vertex.Row + 1; i <= consumers.GetLength(0); i++)
  411.                 {
  412.                     if (consumers[i, vertex.Column].metNeeds > 0)
  413.                     {
  414.                         vertex.AcceptableDirections.Remove(Direction.Down);
  415.                         return new Vertex(i, vertex.Column, calcDirections(i, vertex.Column, forbidden: Direction.Up));
  416.                     }
  417.                 }
  418.             }
  419.             else if (vertex.AcceptableDirections.Contains(Direction.Left))
  420.             {
  421.                 for (int j = vertex.Column - 1; j >= 0; j--)
  422.                 {
  423.                     if (consumers[vertex.Row, j].metNeeds > 0)
  424.                     {
  425.                         vertex.AcceptableDirections.Remove(Direction.Left);
  426.                         return new Vertex(vertex.Row, j, calcDirections(vertex.Row, j, forbidden: Direction.Right));
  427.                     }
  428.                 }
  429.             }
  430.             else //Right
  431.             {
  432.                 for (int j = vertex.Column + 1; j <= consumers.GetLength(1); j++)
  433.                 {
  434.                     if (consumers[vertex.Row, j].metNeeds > 0)
  435.                     {
  436.                         vertex.AcceptableDirections.Remove(Direction.Right);
  437.                         return new Vertex(vertex.Row, j, calcDirections(vertex.Row, j, forbidden: Direction.Left));
  438.                     }
  439.                 }
  440.             }
  441.             return new Vertex(-1, -1, Direction.None); //Щоб забрати warning
  442.         }
  443.         private void removeUnnecessaryVertices(List<Vertex> cycleVertices)
  444.         {
  445.             for (int i = 2; i < cycleVertices.Count; i++)
  446.             {
  447.                 bool rowsMatched = cycleVertices[i].Row == cycleVertices[i - 1].Row && cycleVertices[i - 1].Row == cycleVertices[i - 2].Row;
  448.                 bool columnsMatched = cycleVertices[i].Column == cycleVertices[i - 1].Column && cycleVertices[i - 1].Column == cycleVertices[i - 2].Column;
  449.                 if (rowsMatched || columnsMatched)
  450.                 {
  451.                     // Знайдено три однакових значення підряд
  452.                     // Видалення середнього елемента
  453.                     int indexToRemove = i - 1;
  454.                     cycleVertices.RemoveAt(indexToRemove);
  455.                     // Зменшення лічильника циклу, щоб продовжити перевірку
  456.                     //!!!!!!!!!!!!!!!!!!!
  457.                     //i = 2;
  458.                     i--;
  459.                 }
  460.             }
  461.  
  462.         }
  463.         private List<Vertex> buildCycle(int row, int column)
  464.         {
  465.             bool isSolved = false;
  466.             List<Vertex> cycleVertices = new List<Vertex>();
  467.             int oldVal = consumers[row, column].metNeeds;
  468.             consumers[row, column].metNeeds = int.MaxValue;
  469.             cycleVertices.Add(new Vertex(row, column, calcDirections(row, column)));
  470.  
  471.             while (!isSolved)
  472.             {
  473.                 while (cycleVertices.Last().AcceptableDirections == Direction.None)
  474.                 {
  475.                     cycleVertices.Remove(cycleVertices.Last());
  476.                     if (cycleVertices.Count == 0)
  477.                     {
  478.                         Console.WriteLine("ERORRRRRRRRR 1");
  479.                         Environment.Exit(1);
  480.                     }
  481.                 }
  482.                 Vertex possibleNext = findNextVertex(cycleVertices.Last());
  483.                 if (possibleNext.Equals(cycleVertices.First()))
  484.                 {
  485.                     isSolved = true;
  486.                     consumers[row, column].metNeeds = oldVal;
  487.                 }
  488.                 else if (possibleNext.AcceptableDirections != Direction.None)
  489.                 {
  490.                     cycleVertices.Add(possibleNext);
  491.                 }
  492.             }
  493.             removeUnnecessaryVertices(cycleVertices);
  494.             return cycleVertices;
  495.         }
  496.         private bool checkForDegeneracy()
  497.         {
  498.             int count = 0;
  499.             foreach (Consumer consumer in consumers)
  500.             {
  501.                 if (consumer.metNeeds != 0)
  502.                 {
  503.                     count++;
  504.                 }
  505.             }
  506.             return count != consumers.GetLength(0) + consumers.GetLength(1) - 1;
  507.         }
  508.         private void recalculateTransportation(List<Vertex> cycleVertices)
  509.         {
  510.             int min = -1;
  511.             for (int i = 1; i < cycleVertices.Count; i++)
  512.             {
  513.                 if (i % 2 == 0) continue;
  514.                 int currentRow = cycleVertices[i].Row;
  515.                 int currentColumn = cycleVertices[i].Column;
  516.                 if (i == 1)
  517.                 {
  518.                     min = consumers[currentRow, currentColumn].metNeeds;
  519.                 }
  520.                 else if (consumers[currentRow, currentColumn].metNeeds < min)
  521.                 {
  522.                     min = consumers[currentRow, currentColumn].metNeeds;
  523.                 }
  524.             }
  525.  
  526.             for (int i = 0; i < cycleVertices.Count; i++)
  527.             {
  528.                 int currentRow = cycleVertices[i].Row;
  529.                 int currentColumn = cycleVertices[i].Column;
  530.                 if (i % 2 == 0)
  531.                 {
  532.                     consumers[currentRow, currentColumn].metNeeds += min;
  533.                 }
  534.                 else
  535.                 {
  536.                     consumers[currentRow, currentColumn].metNeeds -= min;
  537.                 }
  538.             }
  539.         }
  540.         public void Solve()
  541.         {
  542.             minimumElementMethod();
  543.             //printArr();
  544.             // bool t = checkForDegeneracy();
  545.             bool isSolved = false;
  546.             while (!isSolved)
  547.             {
  548.                 bool t = checkForDegeneracy();
  549.                 if (t)
  550.                 {
  551.                     Console.WriteLine("Матриця вироджена, можливо не кiнцевий розвязок");
  552.                     int currentSum = 0;
  553.                     for (int i = 0; i < consumers.GetLength(0); i++)
  554.                     {
  555.                         for (int j = 0; j < consumers.GetLength(1); j++)
  556.                         {
  557.                             currentSum += consumers[i, j].transportationCosts * consumers[i, j].metNeeds;
  558.                         }
  559.                     }
  560.                     Console.WriteLine($"SUM = {currentSum}");
  561.                     Environment.Exit(2);
  562.                 }
  563.                 calcPotencials();
  564.                 calcDeltas();
  565.                 isSolved = findMaxDelta(out int row, out int column);
  566.                 if (isSolved)
  567.                 {
  568.                     break;
  569.                 }
  570.                 var cycleVertices = buildCycle(row, column);
  571.                 recalculateTransportation(cycleVertices);
  572.                 printArr();
  573.                 Console.WriteLine();
  574.                 Console.WriteLine();
  575.             }
  576.  
  577.             int sum = 0;
  578.             for (int i = 0; i < consumers.GetLength(0); i++)
  579.             {
  580.                 for (int j = 0; j < consumers.GetLength(1); j++)
  581.                 {
  582.                     sum += consumers[i, j].transportationCosts * consumers[i, j].metNeeds;
  583.                 }
  584.             }
  585.             Console.WriteLine($"SUM = {sum}");
  586.         }
  587.     }
  588. }
  589.  
Advertisement
Add Comment
Please, Sign In to add comment