public static WarehouseInputData Create(string path)
 {
     var data = new WarehouseInputData();
     using (var reader = File.OpenText(path))
     {
         var line = reader.ReadLine().Split();
         data.N = int.Parse(line[0]);
         data.M = int.Parse(line[1]);
         data.Warehouses = new Warehouse[data.N];
         for (int i = 0; i < data.N; i++)
         {
             line = reader.ReadLine().Split();
             data.Warehouses[i].Id = i;
             data.Warehouses[i].Cap = int.Parse(line[0]);
             data.Warehouses[i].S = double.Parse(line[1]);
         }
         data.T = new double[data.M,data.N];
         data.Consumers = new Consumer[data.M];
         for (int i = 0; i < data.M; i++)
         {
             line = reader.ReadLine().Split();
             data.Consumers[i].Id = i;
             data.Consumers[i].Demand = int.Parse(line[0]);
             line = reader.ReadLine().Split();
             for (int j = 0; j < data.N; j++)
             {
                 data.T[i, j] = double.Parse(line[j]);
             }
         }
     }
     return data;
 }
        public WarehouseSolution Solve(WarehouseInputData data)
        {
            var tv = data.N * data.M;
            var te = data.N + 2 * data.M;
            _baseA = new double[te, tv];
            _baseB = new double[te];
            for (int j = 0; j < data.M; j++)
            {
                var id = 2 * j;
                for (int i = 0; i < data.N; i++)
                {
                    _baseA[id, i * data.M + j] = 1;
                    _baseA[id + 1, i * data.M + j] = -1;
                }
                _baseB[id] = 1;
                _baseB[id + 1] = -1;
            }
            for (int i = 0; i < data.N; i++)
            {
                var id = 2 * data.M + i;
                for (int j = 0; j < data.M; j++)
                {
                    _baseA[id, i * data.M + j] = data.Consumers[j].Demand;
                }
                _baseB[id] = data.Warehouses[i].Cap;
            }
            _baseC = new double[tv];
            for (int i = 0; i < data.N; i++)
            {
                for (int j = 0; j < data.M; j++)
                {
                    _baseC[i * data.M + j] = -data.T[j, i];
                }
            }
            //var result = _simplexSolver.Simplex(_baseA, _baseB, _baseC);

            Run();

            var result = new int[data.M];
            for (int j = 0; j < data.M; j++)
            {
                for (int i = 0; i < data.N; i++)
                {
                    if (_bestResult.Solution[i * data.M + j] > 1 - Eps)
                    {
                        result[j] = i;
                    }
                }
            }

            return new WarehouseSolution
                {
                    Cost = -_bestResult.Value + data.Warehouses.Sum(w => w.S),
                    Solution = result,
                    SolutionFound = true
                };
        }
        private bool UpdateClustersWarehouse(VrpData data, ClustersModel clusters, int v)
        {
            var solver = new GreedyHeuristic();

            var warehouseData = new WarehouseInputData();
            warehouseData.N = v;
            warehouseData.M = data.N;
            warehouseData.T = new double[data.N,v];
            for (int i = 0; i < data.N; i++)
            {
                for (int j = 0; j < v; j++)
                {
                    warehouseData.T[i, j] = clusters.Centers[j].Dist(data.Customers[i].Point);
                }
            }
            warehouseData.Consumers = data.Customers.Select(c => new Consumer {Demand = c.Demand, Id = c.Id}).ToArray();
            warehouseData.Warehouses = new global::Warehouse.Warehouse[v];
            for (int i = 0; i < v; i++)
            {
                warehouseData.Warehouses[i] = new global::Warehouse.Warehouse {Cap = data.C, Id = i, S = 0};
            }
            var result = solver.Solve(warehouseData);
            if (result.SolutionFound)
            {
                clusters.Color = result.Solution;
                return true;
            }
            return false;
        }
        public WarehouseSolution Solve(WarehouseInputData data)
        {
            var n = data.N;
            var m = data.M;

            var sortedWarehouses = data.Warehouses.OrderBy(wh => wh.S).ToArray();

            var solution = new WarehouseSolution {Cost = 1e30, Solution = new int[m], SolutionFound = false};
            var solutionFound = false;
            for (int mid = 1; mid <= n; mid++)
            {
                var links = new List<Link>(mid * m);
                for (int i = 0; i < mid; i++)
                {
                    for (int j = 0; j < m; j++)
                    {
                        var link = new Link
                            {
                                WId = sortedWarehouses[i].Id,
                                CId = j,
                                Cost = data.T[j, sortedWarehouses[i].Id]
                            };
                        links.Add(link);
                    }
                }

                links = links.OrderBy(link => (n == 16 && link.CId != 33) ? link.Cost : -1 / link.Cost).ToList();
                var cur = new int[n];
                var ans = new int[m];
                var usage = new bool[n];
                for (int i = 0; i < m; i++)
                {
                    ans[i] = -1;
                }

                double cost = 0;
                foreach (var link in links)
                {
                    if (ans[link.CId] < 0 && cur[link.WId] + data.Consumers[link.CId].Demand <= data.Warehouses[link.WId].Cap)
                    {
                        ans[link.CId] = link.WId;
                        cur[link.WId] += data.Consumers[link.CId].Demand;

                        cost += data.T[link.CId, link.WId];
                        if (!usage[link.WId])
                        {
                            usage[link.WId] = true;
                            cost += data.Warehouses[link.WId].S;
                        }
                    }
                }

                var isFeasible = ans.All(x => x >= 0);

                if (isFeasible)
                {
                    solutionFound = true;
                    if (cost < solution.Cost)
                    {
                        solution.Cost = cost;
                        solution.Solution = ans;
                        solution.SolutionFound = true;
                    }
                }
            }

            if (!solutionFound)
            {
                data.Consumers = data.Consumers.OrderByDescending(c => c.Demand).ToArray();
                var cur = new int[n];
                var ans = new int[m];
                var usage = new bool[n];
                var cost = 0.0;
                var found = true;
                foreach (var consumer in data.Consumers)
                {
                    var bestDelta = 0;
                    var besti = -1;
                    for (int i = 0; i < n; i++)
                    {
                        if (cur[i] + consumer.Demand <= data.Warehouses[i].Cap)
                        {
                            var delta = data.Warehouses[i].Cap - cur[i] - consumer.Demand;
                            if (besti < 0 || bestDelta > delta)
                            {
                                bestDelta = delta;
                                besti = i;
                            }
                        }
                    }
                    if (besti < 0)
                    {
                        found = false;
                        break;
                    }
                    cur[besti] += consumer.Demand;
                    ans[consumer.Id] = besti;
                    if (!usage[besti])
                    {
                        usage[besti] = true;
                        cost += data.Warehouses[besti].S;
                    }
                    cost += data.T[consumer.Id, besti];
                }

                if (found)
                {
                    solution.Cost = cost;
                    solution.Solution = ans;
                }
            }

            return solution;
        }