public static List<List<Potencial>> Potencials(float[,] result, int[,] tariffs)
        {
            List<Potencial> u = new List<Potencial>();
            u.Add(new Potencial(0, 0));
            List<Potencial> v = new List<Potencial>();
            List<BasisPoint> points = new List<BasisPoint>();
            int basisCount = 0;
            for (int i = 0; i < result.GetUpperBound(0) + 1; ++i)
            {
                for (int j = 0; j < result.GetUpperBound(1) + 1; ++j)
                {
                    if (!float.IsNaN(result[i, j]))
                    {
                        BasisPoint point = new BasisPoint(i, j);
                        points.Add(point);
                        basisCount++;
                    }
                }
            }

            if (points.Count < (result.GetUpperBound(0) + 1 + result.GetUpperBound(1)))
            {
                int x = 0, y = 0;
                foreach (BasisPoint p in points)
                {
                    foreach (BasisPoint q in points)
                    {
                        if (p == q) continue;
                        if (p.x == q.x) x++;
                        if (p.y == q.y) y++;
                    }

                    if ((x == 0) && (y == 0))
                    {
                        points.Add(new BasisPoint(p.x, p.y + 1));
                        result[p.x, p.y + 1] = 0;
                        break;
                    }
                }
            }

            int t = 0;
            while (points.Count > 0)
            {
                int basis = points.Count;
                if (t < basis - 1) t++;
                else t = 0;
                if (Existence(u, points[t].x)) v.Add(new Potencial(tariffs[points[t].x, points[t].y] - indexValue(u, points[t].x), points[t].y));
                else if (Existence(v, points[t].y)) u.Add(new Potencial(tariffs[points[t].x, points[t].y] - indexValue(v, points[t].y), points[t].x));
                if ((Existence(v, points[t].y)) && (Existence(u, points[t].x))) points.Remove(points[t]);

            }
            List<List<Potencial>> res = new List<List<Potencial>>() { u, v };
            return res;
        }
        private static bool turnUp(List<BasisPoint> points, BasisPoint min, BasisPoint qurPoint)
        {
            List<BasisPoint> qurPoints = napoln(points);
            List<BasisPoint> qurStr = new List<BasisPoint>();

            foreach (BasisPoint p in qurPoints)
            {
                if (p.y == qurPoint.y) qurStr.Add(p);
            }

            if (qurStr.Count == 0) return false;

            foreach (BasisPoint q in qurStr)
            {
                qurPoints.Remove(q);
            }

            foreach (BasisPoint q in qurStr)
            {
                foreach (BasisPoint p in qurPoints)
                {
                    if (turnDown(qurPoints, min, q)) return true;
                    else continue;
                }
            }
            return false;
        }
        public static float[,] Optimization(float[,] result, int[,] tariffs, List<List<Potencial>> potencials)
        {
            List<Delta> delts = new List<Delta>();
            for (int i = 0; i < result.GetUpperBound(0) + 1; ++i)
            {
                for (int j = 0; j < result.GetUpperBound(1) + 1; ++j)
                {
                    if (float.IsNaN(result[i, j]))
                    {
                        Delta delta = new Delta(i, j, tariffs[i, j] - (indexValue(potencials[0], i) + indexValue(potencials[1], j)));
                        delts.Add(delta);
                    }
                    else continue;
                }
            }
            a:
            Delta min = delts[0];
            int minCount = 0;
            foreach (Delta d in delts)
            {
                if (d.value < min.value) min = d;
            }
            foreach (Delta d in delts)
            {
                if (d.value == min.value) minCount++;
            }
            if (min.value >= 0) return null;
            min.zn = "+";
            List<BasisPoint> points = new List<BasisPoint>();
            for (int i = 0; i < result.GetUpperBound(0) + 1; ++i)
            {
                for (int j = 0; j < result.GetUpperBound(1) + 1; ++j)
                {
                    if (!float.IsNaN(result[i, j]))
                    {
                        BasisPoint point = new BasisPoint(i, j, result[i, j]);
                        points.Add(point);
                    }
                }
            }
            BasisPoint qurPoint = min;
            List<BasisPoint> cycle = new List<BasisPoint>();
            cycle.Add(min);
            bool turn = false;
            bool complete = false;
            bool error = false;
            while (complete != true)
            {
                if (error)
                {
                    delts.Remove(min);
                    goto a;
                }
                List<BasisPoint> qurStr = new List<BasisPoint>();
                if (turn == false)
                {
                    foreach (BasisPoint p in points)
                    {
                        if (p.x == qurPoint.x) qurStr.Add(p);
                    }

                    foreach (BasisPoint q in qurStr)
                    {
                        points.Remove(q);
                        if (q.y == min.y)
                        {
                            q.zn = "-";
                            cycle.Add(q);
                            complete = true;
                        }
                    }

                    foreach (BasisPoint q in qurStr)
                    {
                        foreach (BasisPoint p in points)
                        {
                            if (q.y == p.y)
                            {
                                if (q.value > 0.0)
                                {
                                    if (turnUp(points, min, q))
                                    {
                                        qurPoint = q;
                                        qurPoint.zn = "-";
                                        cycle.Add(qurPoint);
                                        turn = !turn;
                                        break;
                                    }
                                }
                                else error = true;
                            }
                        }
                    }
                }
                else
                {
                    foreach (BasisPoint p in points)
                    {
                        if (p.y == qurPoint.y) qurStr.Add(p);
                    }

                    foreach (BasisPoint q in qurStr)
                    {
                        points.Remove(q);
                    }

                    foreach (BasisPoint q in qurStr)
                    {
                        foreach (BasisPoint p in points)
                        {
                            if (q.x == p.x)
                            {
                                if (turnDown(points, min, q))
                                {
                                    qurPoint = q;
                                    qurPoint.zn = "+";
                                    cycle.Add(qurPoint);
                                    turn = !turn;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            List<float> end = new List<float>();
            for (int i = 0; i < result.GetUpperBound(0) + 1; ++i)
                for (int j = 0; j < result.GetUpperBound(1) + 1; ++j)
                    foreach (BasisPoint p in cycle)
                        if ((p.x == i) && (p.y == j) && (p.zn == "-")) end.Add(result[i, j]);

            for (int i = 0; i < result.GetUpperBound(0) + 1; ++i)
                for (int j = 0; j < result.GetUpperBound(1) + 1; ++j)
                    foreach (BasisPoint p in cycle)
                        if ((p.x == i) && (p.y == j))
                        {
                            if (float.IsNaN(result[i, j])) result[i, j] = 0;
                            if (p.zn == "+") result[i, j] += end.Min();
                            else result[i, j] -= end.Min();
                            if (result[i, j] == 0) result[i, j] = float.NaN;
                        }
            return result;
        }