private void btnModelo2_Click(object sender, EventArgs e)
        {
            GRBEnv   Ambinte   = new GRBEnv();
            GRBModel Modelo    = new GRBModel(Ambinte);
            Random   Aleatorio = new Random(4);
            int      m         = 1600;

            GRBVar[,] X = new GRBVar[m, m];
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    X[i, j] = Modelo.AddVar(0, 1, Aleatorio.Next(1, 20), GRB.BINARY, "x_" + i.ToString() + "_" + j.ToString());
                }
            }
            Modelo.ModelSense = GRB.MAXIMIZE;
            GRBLinExpr Expressao = new GRBLinExpr();

            for (int i = 0; i < m; i++)
            {
                Expressao.Clear();
                for (int j = 0; j < m; j++)
                {
                    Expressao.AddTerm(1, X[i, j]);
                }
                Modelo.AddConstr(Expressao == 1, "Vendedor_" + i);
            }

            for (int j = 0; j < m; j++)
            {
                Expressao.Clear();
                for (int i = 0; i < m; i++)
                {
                    Expressao.AddTerm(1, X[i, j]);
                }
                Modelo.AddConstr(Expressao == 1, "Regiao_" + j);
            }
            Stopwatch Cronometro = new Stopwatch();

            Cronometro.Start();
            Modelo.Optimize();
            Cronometro.Stop();
            MessageBox.Show("O valor do lucro é: " + Modelo.ObjVal.ToString());
            MessageBox.Show("O tempo para resolver foi de: " + Cronometro.ElapsedMilliseconds.ToString() + " ms");
            MessageBox.Show("Se quiser saber a alocação que gera esse lucro é só me pagar");
            //for (int j = 0; j < m; j++)
            //{
            //    for (int i = 0; i < m; i++)
            //    {
            //        if(X[i,j].X>0)
            //        {
            //            MessageBox.Show("O vendedor " + i + " é alocado para a região " + j);
            //        }
            //    }
            //}
            Modelo.Write("C:\\Teste\\Modelo2.lp");
        }
        //model y=x1+x2
        static public void AddCons2Vars(GRBModel m, List <GRBVar> pickvars)
        {
            double[,] coeff = new double[4, 4] {
                { 1, 1, -1, 0 }, { 1, -1, 1, 0 }, { -1, 1, 1, 0 }, { -1, -1, -1, 2 }
            };
            GRBLinExpr lincon = new GRBLinExpr();
            int        i = 0, j = 0;

            for (i = 0; i < 4; i++)
            {
                lincon.Clear();
                for (j = 0; j < 3; j++)
                {
                    lincon.AddTerm(coeff[i, j], pickvars[j]);
                }
                lincon.AddConstant(coeff[i, 3]);
                m.AddConstr(lincon >= 0, "conslin2");
            }
        }
        public MasterModelOutputs buildModel(
            InputData inputData,
            int nCUT,
            MasterModelParameters masterModelParameters,
            string outputFolder
            )
        {
            try
            {
                // Create an empty environment, set options and start
                GRBEnv env = new GRBEnv(true);
                env.Set("LogFile", "LogFileGurobiModel.log");
                env.Start();

                int            T      = 4;
                List <T_param> Tlist2 = inputData.TList.FindAll(tl => tl.T >= 2);
                List <T_param> Tlist3 = inputData.TList.FindAll(tl => tl.T >= 3);

                // Create empty Gurobi model
                GRBModel gModel = new GRBModel(env);

                // Create an empty linear expression object.
                //Parameters and variables will be added and then used to add model components
                //(Objective Function and Constraints).
                GRBLinExpr expr1 = 0.0;
                GRBLinExpr expr2 = 0.0;

                // Crear la variables
                GRBVar[] Make1 = gModel.AddVars(inputData.ProdList.Count, GRB.CONTINUOUS);
                GRBVar[] Inv1  = gModel.AddVars(inputData.ProdList.Count, GRB.CONTINUOUS);
                GRBVar[] Sell1 = gModel.AddVars(inputData.ProdList.Count, GRB.CONTINUOUS);

                //MAKE1 VARNAME
                inputData.ProdList.ForEach(pl => {
                    int ixP            = inputData.ProdList.IndexOf(pl);
                    Make1[ixP].VarName = "MAKE1_Prod: " + pl.PROD;
                });

                //INV1 VARNAME
                inputData.ProdList.ForEach(pl => {
                    int ixP           = inputData.ProdList.IndexOf(pl);
                    Inv1[ixP].VarName = "INV1_Prod: " + pl.PROD;
                });

                //MAKE1 VARNAME
                inputData.ProdList.ForEach(pl => {
                    int ixP            = inputData.ProdList.IndexOf(pl);
                    Sell1[ixP].VarName = "SELL1_Prod: " + pl.PROD;
                });

                //MAKE1 => 0 (constrain)
                //GRB.CONTINUOUS
                for (int a = 0; a < Make1.Length; a++)
                {
                    expr1.Clear();
                    expr1.AddTerm(1, Make1[a]);
                    gModel.AddConstr(expr1, GRB.GREATER_EQUAL, 0, ">=0");
                }

                //INV1 => 0 (constrain)
                for (int a = 0; a < Inv1.Length; a++)
                {
                    expr1.Clear();
                    expr1.AddTerm(1, Inv1[a]);
                    gModel.AddConstr(expr1, GRB.GREATER_EQUAL, 0, ">=0");
                }

                //SELL1 => 0 (constrain)
                for (int a = 0; a < Sell1.Length; a++)
                {
                    expr1.Clear();
                    expr1.AddTerm(1, Sell1[a]);
                    gModel.AddConstr(expr1, GRB.GREATER_EQUAL, 0, ">=0");
                }

                //SELL1 <= market[p,1]
                expr1.Clear();
                inputData.ProdList.ForEach(pl => {
                    double market = inputData
                                    .MarketList
                                    .Find(ml =>
                                          ml.PROD.Equals(pl.PROD) &&
                                          ml.T.Equals(1)).MARKET;

                    int ixP = inputData.ProdList.IndexOf(pl);

                    expr1.Clear();
                    expr1.AddTerm(1, Sell1[ixP]);
                    gModel.AddConstr(expr1, GRB.LESS_EQUAL, market, "<=Market");
                });

                GRBVar Min_Stage2_Profit = gModel.AddVar(double.MinValue, double.MaxValue, masterModelParameters.Min_Stage2_Profit, GRB.CONTINUOUS, "Min_Stage2_Profit");

                //Funcion objetivo
                //maximize Expected_Profit:
                //sum { s in SCEN}
                //prob[s] *
                //sum { p in PROD} (revenue[p, 1, s] * Sell1[p] -
                //prodcost[p] * Make1[p] - invcost[p] * Inv1[p]) +
                //Min_Stage2_Profit;
                expr1.Clear();
                inputData.ScenList.ForEach(sl =>
                {
                    double prob = inputData.ProbList.Find(x => x.SCEN.Equals(sl.SCEN)).PROB;

                    inputData.ProdList.ForEach(pl => {
                        double revenue = inputData
                                         .RevenueList
                                         .Find(rl =>
                                               rl.PROD.Equals(pl.PROD) &&
                                               rl.T.Equals(1) &&
                                               rl.SCEN.Equals(sl.SCEN))
                                         .REVENUE;

                        int ixP        = inputData.ProdList.IndexOf(pl);
                        double invcost = inputData.InvCostList.Find(inv => inv.PROD.Equals(pl.PROD)).INVCOST;

                        double prodcost = inputData.ProdCostList.Find(inv => inv.PROD.Equals(pl.PROD)).PRODCOST;

                        expr1.AddTerm(prob * revenue, Sell1[ixP]);
                        expr1.AddTerm(-prob * prodcost, Make1[ixP]);
                        expr1.AddTerm(-prob * invcost, Inv1[ixP]);
                        expr1.AddTerm(1, Min_Stage2_Profit);
                    });
                });

                //Insertar funcion objetivo
                gModel.SetObjective(expr1, GRB.MAXIMIZE);

                //subj to Cut_Defn {k in 1..nCUT}:  KE ESTA PASANDO
                // Min_Stage2_Profit <=
                //    sum { t in 2..T, s in SCEN}
                //    time_price[t, s, k] * avail[t] +
                //    sum { p in PROD, s in SCEN}
                //    bal2_price[p, s, k] * (-Inv1[p]) +
                //    sum { p in PROD, t in 2..T, s in SCEN}
                //    sell_lim_price[p, t, s, k] * market[p, t];
                expr1.Clear();
                double sumPriceAvail  = 0;
                double sumPriceMarket = 0;
                expr1.AddTerm(1, Min_Stage2_Profit);
                for (int k = 1; k <= nCUT; k++)
                {
                    //    sum { t in 2..T, s in SCEN}
                    //    time_price[t, s, k] * avail[t] +
                    Tlist2.ForEach(tl =>
                    {
                        inputData.ScenList.ForEach(sl =>
                        {
                            double timePrice = masterModelParameters.timePriceList.Find(x => x.T.Equals(tl.T) &&
                                                                                        x.SCEN.Equals(sl.SCEN) &&
                                                                                        x.nCUT.Equals(k)).TIMEPRICE;

                            double avail = inputData.AvailList.Find(al => al.T.Equals(tl.T)).AVAIL;

                            sumPriceAvail += timePrice * avail;
                        });
                    });

                    //    sum { p in PROD, t in 2..T, s in SCEN}
                    //    sell_lim_price[p, t, s, k] * market[p, t];
                    inputData.ProdList.ForEach(pl => {
                        Tlist2.ForEach(tl => {
                            inputData.ScenList.ForEach(sl =>
                            {
                                double sellLimPrice = masterModelParameters.sellLimPriceList.Find(slpl => slpl.PROD.Equals(pl.PROD) &&
                                                                                                  slpl.T.Equals(tl.T) &&
                                                                                                  slpl.SCEN.Equals(sl.SCEN) &&
                                                                                                  slpl.nCUT.Equals(k)).SELLLIMPRICE;

                                double market = inputData.MarketList.Find(ml => ml.PROD.Equals(pl.PROD) &&
                                                                          ml.T.Equals(tl.T)).MARKET;

                                sumPriceMarket += sellLimPrice * market;
                            });
                        });
                    });

                    //  sum { p in PROD, s in SCEN}
                    //  bal2_price[p, s, k] * (-Inv1[p]) +
                    inputData.ProdList.ForEach(pl =>
                    {
                        inputData.ScenList.ForEach(sl =>
                        {
                            double bal2Price = masterModelParameters.balance2PriceList.Find(bp => bp.PROD.Equals(pl.PROD) &&
                                                                                            bp.SCEN.Equals(sl.SCEN) && bp.nCUT.Equals(k)).BALANCE2PRICE;

                            int ixP = inputData.ProdList.IndexOf(pl);
                            expr1.AddTerm(bal2Price, Inv1[ixP]);
                        });
                    });
                }
                gModel.AddConstr(expr1, GRB.LESS_EQUAL, sumPriceAvail + sumPriceMarket, "Cut_Defn");

                //subject to Time1:
                //sum { p in PROD} (1 / rate[p]) * Make1[p] <= avail[1];
                expr1.Clear();
                inputData.ProdList.ForEach(pl =>
                {
                    double rate      = 1 / inputData.RateList.Find(rl => rl.PROD.Equals(pl.PROD)).RATE;
                    double avail     = inputData.AvailList.Find(al => al.T.Equals(1)).AVAIL;
                    double rateAvail = avail / rate;
                    int ixP          = inputData.ProdList.IndexOf(pl);

                    gModel.AddConstr(Make1[ixP], GRB.GREATER_EQUAL, rateAvail, "TIME1");
                });


                //subject to Balance1 { p in PROD}:
                //Make1[p] + inv0[p] = Sell1[p] + Inv1[p];
                expr1.Clear();
                inputData.ProdList.ForEach(pl => {
                    expr1.Clear();

                    int ixP = inputData.ProdList.IndexOf(pl);
                    expr1.AddTerm(1, Sell1[ixP]);
                    expr1.AddTerm(1, Inv1[ixP]);
                    expr1.AddTerm(-1, Make1[ixP]);

                    double inv0 = inputData.Inv0List.Find(il => il.PROD.Equals(pl.PROD)).INV0;

                    gModel.AddConstr(inv0, GRB.EQUAL, expr1, "Balance1");
                });

                //carpeta donde se expande el modelo master
                gModel.Write(outputFolder + "Master_Model.lp");

                // RESOLVER EL MODELO
                try
                {
                    Console.WriteLine("Solving the master model with gurobi..");
                    gModel.Optimize();

                    if (gModel.Status == 2)
                    {
                        for (int m = 0; m < Make1.Length; m++)
                        {
                            Console.WriteLine("Make1 Var: " + Make1[m].VarName + " = " + Make1[m].X);
                        }

                        for (int m = 0; m < Inv1.Length; m++)
                        {
                            Console.WriteLine("Inv1 Var: " + Inv1[m].VarName + " = " + Inv1[m].X);
                        }

                        for (int m = 0; m < Sell1.Length; m++)
                        {
                            Console.WriteLine("Sell Var: " + Sell1[m].VarName + " = " + Sell1[m].X);
                        }
                    }

                    gModel.Dispose();
                    env.Dispose();

                    return(new MasterModelOutputs()
                    {
                        make1 = Make1,
                        sell1 = Sell1,
                        inv1 = Inv1,
                        expectedProfit = gModel.ObjVal,
                        gModel = gModel
                    });
                }
                catch { Console.WriteLine("ERROR SOLVING THE MODEL"); }

                gModel.Dispose();
                env.Dispose();
            }
            catch (GRBException ex)
            {
                Console.WriteLine("Error code: " + ex.ErrorCode + ". " + ex.Message);
            }

            return(new MasterModelOutputs());
        }
Esempio n. 4
0
        static void Main(string[] args)
        {
            //Deserializar o arquivo Json para o c#
            //JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            var        json      = File.ReadAllText("C:\\Users\\ruany\\Documents\\dissertacao\\gerador-instancias\\instanciaT11E8D10F6.json");
            Parametros instancia = JsonConvert.DeserializeObject <Parametros>(json);

            // matrizes que irão guardar as soluções do Relax and Fix
            double[,,] matriz_RaF_x = new double[instancia.crew, instancia.task, instancia.date];
            double[,] matriz_RaF_x3 = new double[instancia.task, instancia.date];
            double[,] matriz_RaF_x2 = new double[instancia.task, instancia.date];
            double[] matriz_RaF_x4 = new double[instancia.task];
            double[,,] matriz_RaF_x5 = new double[instancia.crew, instancia.task, instancia.date];
            double[,] matriz_RaF_x6  = new double[instancia.task, instancia.date];
            double[,] matriz_RaF_y   = new double[instancia.crew, instancia.date];
            double[,,] matriz_RaF_z  = new double[instancia.crew, instancia.task, instancia.date];
            double[,] matriz_RaF_z1  = new double[instancia.crew, instancia.task];
            double[,,] matriz_RaF_w  = new double[instancia.crew, instancia.technical_place, instancia.date];
            double[,,,] matriz_RaF_v = new double[instancia.crew, instancia.technical_place, instancia.technical_place, instancia.date];
            double[,,] matriz_RaF_w1 = new double[instancia.crew, instancia.technical_place, instancia.date];
            double[,,] matriz_RaF_w2 = new double[instancia.crew, instancia.technical_place, instancia.date];

            //tempo por iteração
            double tempo_iteracao, tempo_total;
            //status de cada iteração
            int status_RF;
            //lista
            List <double> lista_RF = new List <double>();
            double        soma_RF  = 0;

            //função Relax and Fix
            void modelo_RelaxAndFixData(int iteracao)
            {
                //Modelo
                GRBEnv   ambiente = new GRBEnv();
                GRBModel modelo   = new GRBModel(ambiente);

                //número grande
                int M = 1000;

                //Variáveis

                //fração da tarefa i que o membro de equipe n completa na data j
                GRBVar[,,] x = new GRBVar[instancia.crew, instancia.task, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            x[n, i, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "x_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //fração da tarefa i que é completada na data j
                GRBVar[,] x3 = new GRBVar[instancia.task, instancia.date];
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        x3[i, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "x3_" + i + "_" + j);
                    }
                }
                //1 se alguma tarefa i é completada na data j
                GRBVar[,] x2 = new GRBVar[instancia.task, instancia.date];
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        x2[i, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "x2_" + i + "_" + j);
                    }
                }
                //1 se a tarefa i é concluída dentro do horizonte de planejamento
                GRBVar[] x4 = new GRBVar[instancia.task];
                for (int i = 0; i < instancia.task; i++)
                {
                    x4[i] = modelo.AddVar(0, 1, instancia.c[i] * 2, GRB.CONTINUOUS, "x4_" + i);
                }
                //variável fantasma
                GRBVar[] vf = new GRBVar[instancia.task];
                for (int i = 0; i < instancia.task; i++)
                {
                    vf[i] = modelo.AddVar(1, 1, instancia.c[i] * 2, GRB.BINARY, "vf_" + i);
                }
                //1 se o membro de equipe n está trabalhando na tarefa i na data j mas não na data j+1
                GRBVar[,,] x5 = new GRBVar[instancia.crew, instancia.task, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            x5[n, i, j] = modelo.AddVar(0, 1, 0.1, GRB.CONTINUOUS, "x5_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //1 se parte da tarefa i é completada na data j mas não na data j+1
                GRBVar[,] x6 = new GRBVar[instancia.task, instancia.date];
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        x6[i, j] = modelo.AddVar(0, 1, 0.9, GRB.CONTINUOUS, "x6_" + i + "_" + j);
                    }
                }
                //1 se o membro da equipe n vai trabalhar na data j
                GRBVar[,] y = new GRBVar[instancia.crew, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        y[n, j] = modelo.AddVar(0, 1, instancia.hours_per_shift, GRB.CONTINUOUS, "y_" + n + "_" + j);
                    }
                }
                //1 se membro da equipe n trabalha na tarefa i na data j
                GRBVar[,,] z = new GRBVar[instancia.crew, instancia.task, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            z[n, i, j] = modelo.AddVar(0, 1, 0.5, GRB.CONTINUOUS, "z_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //1 se o membro de equipe n trabalha na tarefa i
                GRBVar[,] z1 = new GRBVar[instancia.crew, instancia.task];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        z1[n, i] = modelo.AddVar(0, 1, 0.1, GRB.CONTINUOUS, "z1_" + n + "_" + i);
                    }
                }
                //1 se o membro de equipe n trabalha no local técnico p na data j
                GRBVar[,,] w = new GRBVar[instancia.crew, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            w[n, p, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "w_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //1 se o membro de equipe n precisa de transporte entre o local técnico o e o local q na instancia.date j
                GRBVar[,,,] v = new GRBVar[instancia.crew, instancia.technical_place, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int q = 0; q < instancia.technical_place; q++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                v[n, p, q, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "v_" + n + "_" + p + "_" + q + "_" + j);
                            }
                        }
                    }
                }
                //se a equipe n precisa de transporte para o local técnico p de outro local técnico na data j
                GRBVar[,,] w1 = new GRBVar[instancia.crew, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            w1[n, p, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "w1_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //se a equipe n precisa de transporte do local técnico p para outro local técnico
                GRBVar[,,] w2 = new GRBVar[instancia.crew, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            w2[n, p, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "w2_" + n + "_" + p + "_" + j);
                        }
                    }
                }

                //Função objetivo
                modelo.ModelSense = GRB.MINIMIZE;


                //Restrições
                GRBLinExpr exp  = 0.0;
                GRBLinExpr exp2 = 0.0;
                GRBLinExpr exp3 = 0.0;

                //Restrições com relação a tarefa

                //restrição 2
                //a tarefa deve ser concluída dentro do horizonte de planejamento
                for (int i = 0; i < instancia.task; i++)
                {
                    exp.Clear();
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.AddTerm(1, x[n, i, j]);
                        }
                    }
                    modelo.AddConstr(exp == x4[i], "R2_" + i);
                }
                //restrição 3
                //o número total de horas por turno não deve ser excedido
                for (int j = 0; j < instancia.date; j++)
                {
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        exp.Clear();
                        exp2.Clear();
                        exp3.Clear();
                        for (int i = 0; i < instancia.task; i++)
                        {
                            exp.AddTerm(instancia.c[i], x[n, i, j]);
                        }
                        for (int p = 0; p < instancia.technical_place; p++)
                        {
                            exp2.AddTerm(2 * instancia.tm[p], w[n, p, j]);
                            exp2.AddTerm(-instancia.tm[p], w1[n, p, j]);
                            exp2.AddTerm(-instancia.tm[p], w2[n, p, j]);
                        }
                        for (int p = 0; p < instancia.technical_place; p++)
                        {
                            for (int q = 0; q < instancia.technical_place; q++)
                            {
                                exp3.AddTerm(instancia.tr[p, q], v[n, p, q, j]);
                            }
                        }
                        modelo.AddConstr(exp + exp2 + exp3 <= instancia.hours_per_shift, "R3_" + j + "_" + n);
                    }
                }
                //restrição 4
                //a soma das frações das tarefas locadas  não pode exceder o total para completar a tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, x[n, i, j]);
                        }
                        modelo.AddConstr(x2[i, j] >= exp, "R4_" + i + "_" + j);
                    }
                }
                //restrição 5
                //soma de das frações dos membros e equipe num dado dia deve ser igual a x3
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, x[n, i, j]);
                        }
                        modelo.AddConstr(x3[i, j] == exp, "R5_" + i + "_" + j);
                    }
                }
                //restrição 6
                //a tarefa i deve ser completada dentro do horizonte de planejamento se gi=1
                for (int i = 0; i < instancia.task; i++)
                {
                    modelo.AddConstr(x4[i] >= instancia.g[i], "R6_" + i);
                }
                //restrição 7
                //fração da tarefa que é completada num dado dia não deve exceder X4
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(x4[i] >= x[n, i, j], "R7_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 8
                //um membro de equipe não pode ser locado a uma tarefa em um dia em que ele não trabalha
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(y[n, j] >= z[n, i, j], "R8_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 9
                //se o membro de equipe é locado para uma tarefa então z=1
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z[n, i, j] >= x[n, i, j], "R9_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 10
                //a variável z não pode ser 1 se a equipe n não trabalha num dado dia
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z[n, i, j] <= M * x[n, i, j], "R10_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 11
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z1[n, i] >= z[n, i, j], "R11_" + n + "_" + i + "_" + j);
                        }
                    }
                }

                //Restrições de gerenciemanto

                //restrição 12
                //preferencalmente uma tarefa deve concluida pela mesma pessoa que começou trabalhando nela
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date - 1; j++)
                        {
                            modelo.AddConstr(x5[n, i, j] >= z[n, i, j] - z[n, i, j + 1], "R12_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 13
                //uma penalidade será dada ao planejamento se a tarefa i é completada em dias não consecutivos
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date - 1; j++)
                    {
                        modelo.AddConstr(x6[i, j] >= x2[i, j] - x2[i, j + 1], "R13_" + i + "_" + j);
                    }
                }
                //restrição 14
                //o número mínimo de membros de equipe que podem trabalhar simultaneamente em uma tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, z[n, i, j]);
                        }
                        modelo.AddConstr(exp >= instancia.d1[i] * x2[i, j], "R14_" + i + "_" + j);
                    }
                }
                //restrição 15
                //o número máximo de membros de equipe que podem trablhar simultaneamente em uma tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, z[n, i, j]);
                        }
                        modelo.AddConstr(exp <= instancia.d2[i] * x2[i, j], "R15_" + i + "_" + j);
                    }
                }
                //restrição 16
                //número mínimo de membros para trabalhar em um tarefa deve ser respeitado
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(x[n, i, j] <= x3[i, j] / instancia.d1[i], "R16_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 17
                //membros de equipe não podem trabalhar em dias em que eles não estão disponíveis
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z[n, i, j] <= instancia.e[n, j], "R17_" + n + "_" + i + "_" + j);
                        }
                    }
                }

                //Restrições com relação a competência

                //restrição 18
                //a combinação do nível de competencias de todos os membros
                //de equipe deve ser suficiente para cada tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        for (int k = 0; k < instancia.competencies; k++)
                        {
                            exp.Clear();
                            for (int n = 0; n < instancia.crew; n++)
                            {
                                exp.AddTerm(instancia.bm3[n, k], z[n, i, j]);
                            }
                            modelo.AddConstr(exp >= x2[i, j] * instancia.bo[i, k] * instancia.level_total, "R18_" + i + "_" + j + "_" + k);
                        }
                    }
                }
                //restrição 19
                //pelo menos um membro de equipe deve ter nível 3 de competencia para a tarefa i
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        for (int k = 0; k < instancia.competencies; k++)
                        {
                            exp.Clear();
                            for (int n = 0; n < instancia.crew; n++)
                            {
                                exp.AddTerm(instancia.bm[n, k], z[n, i, j]);
                            }
                            modelo.AddConstr(exp >= x2[i, j] * instancia.bo[i, k], "R19_" + i + "_" + j + "_" + k);
                        }
                    }
                }
                //restrição 20
                //pelo menos um mebro de equipe tem nível de competencia 3 se vários membros de equipe trabalham na mesma tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        for (int k = 0; k < instancia.competencies; k++)
                        {
                            exp.Clear();
                            exp2.Clear();
                            for (int n = 0; n < instancia.crew; n++)
                            {
                                exp.AddTerm(instancia.bm[n, k], x[n, i, j]);
                                exp2.AddTerm(instancia.bm2[n, k], x[n, i, j]);
                            }
                            modelo.AddConstr(exp >= exp2 * (double)(1 / instancia.d1[i]), "R20_" + i + "_" + j + "_" + k);
                        }
                    }
                }

                //Restrições com relação ao transporte

                //restrição 21
                //cada membro de equipe trabalha em um local técnico em que a tarefa está localizada
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int i = 0; i < instancia.task; i++)
                            {
                                exp.AddTerm(instancia.tp[i, p], z[n, i, j]);
                            }
                            modelo.AddConstr(w[n, p, j] <= exp, "R21_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 22
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int i = 0; i < instancia.task; i++)
                            {
                                exp.AddTerm(instancia.tp[i, p], z[n, i, j]);
                            }
                            modelo.AddConstr(w[n, p, j] * M >= exp, "R22_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 23
                //o membro de equipe só é transportado entre os locais técnicos que as tarefas dele estão localizadas
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int q = 0; q < instancia.technical_place; q++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(exp <= w[n, p, j] * M, "R23_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 24
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int q = 0; q < instancia.technical_place; q++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(exp <= w[n, q, j] * M, "R24_" + n + "_" + q + "_" + j);
                        }
                    }
                }
                //restrição 25
                //se o membro de equipe trabalha em mais do que um local técninco durante o turno
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int q = 0; q < instancia.technical_place; q++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(w1[n, q, j] == exp, "R25_" + n + "_" + q + "_" + j);
                        }
                    }
                }
                //restrição 26
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int q = 0; q < instancia.technical_place; q++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(w2[n, p, j] == exp, "R26_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 27
                //cada membro de equipe pode apenas ser transportado de e para cada local técnico uma vez por dia
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(w1[n, p, j] <= 1, "R27_" + n + "_" + p + "_" + j);
                        }
                    }
                }

                //restrição 28
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(w2[n, p, j] <= 1, "R28_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 29
                //funcionário será transportado apenas uma vez do e para o depósito
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int p = 0; p < instancia.technical_place; p++)
                        {
                            exp.AddTerm(2, w[n, p, j]);
                            exp.AddTerm(-1, w1[n, p, j]);
                            exp.AddTerm(-1, w2[n, p, j]);
                        }
                        modelo.AddConstr(exp == 2 * y[n, j], "R29_" + n + "_" + j);
                    }
                }

                //variáveis a serem fixadas
                if (iteracao != 0)
                {
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        //fixar variável y
                        for (int j = 0; j < iteracao - 1; j++)
                        {
                            y[n, j].Set(GRB.DoubleAttr.LB, matriz_RaF_y[n, j]);
                            y[n, j].Set(GRB.DoubleAttr.UB, matriz_RaF_y[n, j]);

                            //fixar variável z
                            for (int i = 0; i < instancia.task; i++)
                            {
                                z[n, i, j].Set(GRB.DoubleAttr.LB, matriz_RaF_z[n, i, j]);
                                z[n, i, j].Set(GRB.DoubleAttr.UB, matriz_RaF_z[n, i, j]);
                            }
                        }
                    }
                }

                //varivais binárias
                //variável z
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        z[n, i, iteracao].Set(GRB.CharAttr.VType, GRB.BINARY);
                    }
                }
                //variável y
                for (int n = 0; n < instancia.crew; n++)
                {
                    y[n, iteracao].Set(GRB.CharAttr.VType, GRB.BINARY);
                }
                //variável x4
                for (int i = 0; i < instancia.task; i++)
                {
                    x4[i].Set(GRB.CharAttr.VType, GRB.BINARY);
                }
                //variável x5
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < iteracao; j++)
                        {
                            x5[n, i, j].Set(GRB.CharAttr.VType, GRB.BINARY);
                        }
                    }
                }
                //variável x6
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < iteracao; j++)
                    {
                        x6[i, j].Set(GRB.CharAttr.VType, GRB.BINARY);
                    }
                }
                //variável z1
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        z1[n, i].Set(GRB.CharAttr.VType, GRB.BINARY);
                    }
                }
                //variável w
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < iteracao; j++)
                        {
                            w[n, p, j].Set(GRB.CharAttr.VType, GRB.BINARY);
                        }
                    }
                }
                //variável v
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int q = 0; q < instancia.technical_place; q++)
                        {
                            for (int j = 0; j < iteracao; j++)
                            {
                                v[n, p, q, j].Set(GRB.CharAttr.VType, GRB.BINARY);
                            }
                        }
                    }
                }
                //variável w1
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < iteracao; j++)
                        {
                            w1[n, p, j].Set(GRB.CharAttr.VType, GRB.BINARY);
                        }
                    }
                }
                //variável w2
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < iteracao; j++)
                        {
                            w2[n, p, j].Set(GRB.CharAttr.VType, GRB.BINARY);
                        }
                    }
                }

                //otimizar modelo
                modelo.Set(GRB.DoubleParam.TimeLimit, tempo_iteracao);
                modelo.Update();
                modelo.Optimize();
                tempo_total -= modelo.Get(GRB.DoubleAttr.Runtime);

                //atualizar
                int solverStatus = modelo.Get(GRB.IntAttr.Status);

                if (modelo.SolCount == 0 || solverStatus == 3)
                {
                    status_RF = 999999;
                    return;
                }
                else
                {
                    //salvar a salocao
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        for (int i = 0; i < instancia.task; i++)
                        {
                            //variável z
                            matriz_RaF_z[n, i, iteracao] = z[n, i, iteracao].X;
                        }
                        //variável y
                        matriz_RaF_y[n, iteracao] = y[n, iteracao].X;
                    }
                    // se estiver na última iteracao salvar nas matizes o valor das variáveis
                    if (iteracao == instancia.date)
                    {
                        //variável x
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int i = 0; i < instancia.task; i++)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    matriz_RaF_x[n, i, j] = x[n, i, j].X;
                                }
                            }
                        }
                        //variável x3
                        for (int i = 0; i < instancia.task; i++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                matriz_RaF_x3[i, j] = x3[i, j].X;
                            }
                        }
                        //vairável x2
                        for (int i = 0; i < instancia.task; i++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                matriz_RaF_x2[i, j] = x2[i, j].X;
                            }
                        }
                        //variável x4
                        for (int i = 0; i < instancia.task; i++)
                        {
                            matriz_RaF_x4[i] = x4[i].X;
                        }
                        //variável x5
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int i = 0; i < instancia.task; i++)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    matriz_RaF_x5[n, i, j] = x5[n, i, j].X;
                                }
                            }
                        }
                        //variável x6
                        for (int i = 0; i < instancia.task; i++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                matriz_RaF_x6[i, j] = x6[i, j].X;
                            }
                        }
                        //variável z1
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int i = 0; i < instancia.task; i++)
                            {
                                matriz_RaF_z1[n, i] = z1[n, i].X;
                            }
                        }
                        //variável w
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    matriz_RaF_w[n, p, j] = w[n, p, j].X;
                                }
                            }
                        }
                        //variável v
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                for (int q = 0; q < instancia.technical_place; q++)
                                {
                                    for (int j = 0; j < instancia.date; j++)
                                    {
                                        matriz_RaF_v[n, p, q, j] = v[n, p, q, j].X;
                                    }
                                }
                            }
                        }
                        //variável w1
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    matriz_RaF_w1[n, p, j] = w1[n, p, j].X;
                                }
                            }
                        }
                        //variável w2
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    matriz_RaF_w2[n, p, j] = w2[n, p, j].X;
                                }
                            }
                        }
                    }
                }
                if (iteracao == instancia.date)
                {
                    double funcaoObjetivo;
                    funcaoObjetivo = modelo.Get(GRB.DoubleAttr.ObjVal);
                    Console.WriteLine("Solução atual:" + funcaoObjetivo.ToString());
                    lista_RF.Add(funcaoObjetivo);
                    soma_RF += funcaoObjetivo;
                }
            }

            //Relaz and Fix

            //Stopwatch para contar o tempo
            Stopwatch relogio = new Stopwatch();

            tempo_total = 3600;
            relogio.Start();
            for (int j = 0; j < instancia.date; j++)
            {
                status_RF      = 0;
                tempo_iteracao = tempo_total / (instancia.date - j + 1);
                modelo_RelaxAndFixData(j);
                if (status_RF != 0)
                {
                    lista_RF.Add(99999999);
                    soma_RF += 99999999;
                }
            }
            relogio.Stop();
            Console.WriteLine("tempo total de:" + (relogio.ElapsedMilliseconds / 1000).ToString() + "segundos");
            Console.ReadKey();
        }
Esempio n. 5
0
        public void CriarResolverModeloExato()
        {
            Ambiente          = new GRBEnv();
            Modelo            = new GRBModel(Ambiente);
            Modelo.ModelSense = GRB.MINIMIZE;
            GRBVar[] Y = new GRBVar[NumeroItens];
            GRBVar[,] X = new GRBVar[NumeroItens, NumeroItens];
            //Função objetivo (1) e Conjuntos de Restrições (5) e (6)
            for (int j = 0; j < NumeroItens; j++)
            {
                Y[j] = Modelo.AddVar(0, 1, 0, GRB.BINARY, "y_" + j.ToString());
            }
            for (int i = 0; i < NumeroItens; i++)
            {
                for (int j = 0; j < NumeroItens; j++)
                {
                    X[i, j] = Modelo.AddVar(0, 1, Itens[i].Demanda * MatrizDistancias[i, j], GRB.BINARY, "x_" + i.ToString() + "_" + j.ToString());
                }
            }

            //Restrição (2)
            GRBLinExpr expr = new GRBLinExpr();

            //expr=
            //j=0: expr=1 Y[0]
            //j=1: expr=1 Y[0] + 1 Y[1]
            //...
            //j=19: expr=1 Y[0] + 1 Y[1] + ... + 1 Y[18] + 1 Y[19]
            for (int j = 0; j < NumeroItens; j++)
            {
                expr.AddTerm(1, Y[j]);
            }
            Modelo.AddConstr(expr == NumeroMedianas, "R2");

            //Conjunto de Restrições (3)
            expr.Clear();
            //expr=
            for (int i = 0; i < NumeroItens; i++)
            {
                expr.Clear();
                for (int j = 0; j < NumeroItens; j++)
                {
                    expr.AddTerm(1, X[i, j]);
                }
                Modelo.AddConstr(expr == 1, "R3" + "_" + i.ToString());
            }

            //Conjunto de Restrições (4)
            for (int j = 0; j < NumeroItens; j++)
            {
                expr.Clear();
                for (int i = 0; i < NumeroItens; i++)
                {
                    expr.AddTerm(Itens[i].Demanda, X[i, j]);
                }
                Modelo.AddConstr(expr <= Itens[j].Capacidade * Y[j], "R4_" + j.ToString());
            }

            //conjunto de restrições (GGG)
            //for (int i = 0; i < NumeroItens; i++)
            //{
            //    for (int j = 0; j < NumeroItens; j++)
            //    {
            //        Modelo.AddConstr(MatrizDistancias[i, j] * X[i, j] <= 300, "RGGG_" + i.ToString() + "_" + j.ToString());
            //    }
            //}

            //Escrever Modelo .lp
            Modelo.Write(@"C:\Teste\ModeloPmedianas.lp");

            //Otimizar
            Modelo.Optimize();
            DistanciaTotal = Modelo.ObjVal;
            //"Ler" resultado
            int NumeroMedianasJaDefinidas            = 0;
            Dictionary <int, int> DicionarioMedianas = new Dictionary <int, int>();

            for (int j = 0; j < NumeroItens; j++)
            {
                if (Y[j].X > 0.9)
                {
                    Medianas[NumeroMedianasJaDefinidas].ItemMediana           = j;
                    Medianas[NumeroMedianasJaDefinidas].ItensAlocados         = new List <int>();
                    Medianas[NumeroMedianasJaDefinidas].DistanciaItensMediana = 0;
                    DicionarioMedianas.Add(j, NumeroMedianasJaDefinidas);
                    NumeroMedianasJaDefinidas++;
                }
            }
            for (int i = 0; i < NumeroItens; i++)
            {
                for (int j = 0; j < NumeroItens; j++)
                {
                    if (X[i, j].X > 0.9)
                    {
                        Itens[i].MedianaAlocada = DicionarioMedianas[j];
                        Medianas[DicionarioMedianas[j]].ItensAlocados.Add(i);
                        Medianas[DicionarioMedianas[j]].DistanciaItensMediana += MatrizDistancias[i, j];
                    }
                }
            }
        }
Esempio n. 6
0
        public SubModelOutputs Build_Model(
            InputData inputData,
            string outputFolder
            )
        {
            try
            {
                // Create an empty environment, set options and start
                GRBEnv env = new GRBEnv(true);
                env.Set("LogFile", "LogFileGurobiModel.log");
                env.Start();

                int            T      = 4;
                List <T_param> Tlist2 = inputData.TList.FindAll(tl => tl.T >= 2);
                List <T_param> Tlist3 = inputData.TList.FindAll(tl => tl.T >= 3);

                // Create empty Gurobi model
                GRBModel gModel = new GRBModel(env);

                // Create an empty linear expression object.
                //Parameters and variables will be added and then used to add model components
                //(Objective Function and Constraints).
                GRBLinExpr expr1 = 0.0;
                GRBLinExpr expr2 = 0.0;

                // Crear la variables
                GRBVar[] Make = gModel.AddVars(inputData.ProdList.Count * Tlist2.Count * inputData.ScenList.Count, GRB.CONTINUOUS);
                GRBVar[] Inv  = gModel.AddVars(inputData.ProdList.Count * Tlist2.Count * inputData.ScenList.Count, GRB.CONTINUOUS);
                GRBVar[] Sell = gModel.AddVars(inputData.ProdList.Count * Tlist2.Count * inputData.ScenList.Count, GRB.CONTINUOUS);

                //MAKE VARNAME
                inputData.ProdList.ForEach(pl => {
                    Tlist2.ForEach(tl => {
                        inputData.ScenList.ForEach(sl =>
                        {
                            int ixP          = inputData.ProdList.IndexOf(pl);
                            int ixT          = Tlist2.IndexOf(tl);
                            int ixS          = inputData.ScenList.IndexOf(sl);
                            int ix           = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);
                            Make[ix].VarName = "MAKE_PROD: " + pl.PROD + " T: " + tl.T + " SCEN: " + sl.SCEN;
                        });
                    });
                });

                //INV VARNAME
                inputData.ProdList.ForEach(pl => {
                    Tlist2.ForEach(tl => {
                        inputData.ScenList.ForEach(sl =>
                        {
                            int ixP         = inputData.ProdList.IndexOf(pl);
                            int ixT         = Tlist2.IndexOf(tl);
                            int ixS         = inputData.ScenList.IndexOf(sl);
                            int ix          = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);
                            Inv[ix].VarName = "INV_PROD: " + pl.PROD + " T: " + tl.T + " SCEN: " + sl.SCEN;
                        });
                    });
                });

                //SELL VARNAME
                inputData.ProdList.ForEach(pl => {
                    Tlist2.ForEach(tl => {
                        inputData.ScenList.ForEach(sl =>
                        {
                            int ixP          = inputData.ProdList.IndexOf(pl);
                            int ixT          = Tlist2.IndexOf(tl);
                            int ixS          = inputData.ScenList.IndexOf(sl);
                            int ix           = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);
                            Sell[ix].VarName = "SELL_PROD: " + pl.PROD + " T: " + tl.T + " SCEN: " + sl.SCEN;
                        });
                    });
                });

                //MAKE => 0 (constrain)
                //GRB.CONTINUOUS
                for (int a = 0; a < Make.Length; a++)
                {
                    expr1.Clear();
                    expr1.AddTerm(1, Make[a]);
                    gModel.AddConstr(expr1, GRB.GREATER_EQUAL, 0, ">=0");
                }

                //INV => 0 (constrain)
                for (int a = 0; a < Inv.Length; a++)
                {
                    expr1.Clear();
                    expr1.AddTerm(1, Inv[a]);
                    gModel.AddConstr(expr1, GRB.GREATER_EQUAL, 0, ">=0");
                }

                //SELL => 0 (constrain)
                for (int a = 0; a < Sell.Length; a++)
                {
                    expr1.Clear();
                    expr1.AddTerm(1, Sell[a]);
                    gModel.AddConstr(expr1, GRB.GREATER_EQUAL, 0, ">=0");
                }

                //SELL <= market[p,t]
                expr1.Clear();
                inputData.ProdList.ForEach(pl => {
                    Tlist2.ForEach(tl => {
                        inputData.ScenList.ForEach(sl => {
                            double market = inputData
                                            .MarketList
                                            .Find(ml =>
                                                  ml.PROD.Equals(pl.PROD) &&
                                                  ml.T.Equals(tl.T)).MARKET;

                            int ixP = inputData.ProdList.IndexOf(pl);
                            int ixT = Tlist2.IndexOf(tl);
                            int ixS = inputData.ScenList.IndexOf(sl);

                            int index = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);
                            expr1.Clear();
                            expr1.AddTerm(1, Sell[index]);
                            gModel.AddConstr(expr1, GRB.LESS_EQUAL, market, "<=Market");
                        });
                    });
                });

                //Construir funcion objetivo
                //maximize Stage2_Profit:
                //   sum {s in SCEN} prob[s] *
                //      sum {p in PROD, t in 2..T} (revenue[p,t,s]*Sell[p,t,s] -
                //         prodcost[p]*Make[p,t,s] - invcost[p]*Inv[p,t,s]);
                expr1.Clear();
                inputData.ScenList.ForEach(s =>
                {
                    double prob = inputData.ProbList.Find(x => x.SCEN.Equals(s.SCEN)).PROB;

                    inputData.ProdList.ForEach(p =>
                    {
                        Tlist2.ForEach(tl =>
                        {
                            //SELL
                            double revenue = inputData
                                             .RevenueList
                                             .Find(r =>
                                                   r.PROD.Equals(p.PROD) &&
                                                   r.T.Equals(tl.T) &&
                                                   r.SCEN.Equals(s.SCEN)
                                                   ).REVENUE;

                            double prodCost = inputData
                                              .ProdCostList
                                              .Find(pc =>
                                                    pc.PROD.Equals(p.PROD)
                                                    ).PRODCOST;

                            double invCost = inputData
                                             .InvCostList
                                             .Find(ic =>
                                                   ic.PROD.Equals(p.PROD)
                                                   ).INVCOST;

                            int ixP = inputData.ProdList.IndexOf(p);
                            int ixT = Tlist2.IndexOf(tl);
                            int ixS = inputData.ScenList.IndexOf(s);

                            int indexVar = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);

                            expr1.AddTerm(prob * revenue, Sell[indexVar]);
                            expr1.AddTerm(-1 * prob * prodCost, Make[indexVar]);
                            expr1.AddTerm(-1 * prob * invCost, Inv[indexVar]);
                        });
                    });
                });

                //Insertar funcion objetivo
                gModel.SetObjective(expr1, GRB.MAXIMIZE);

                //Insertar Restricciones

                //subject to Time {t in 2..T, s in SCEN}:
                //sum {p in PROD} (1/rate[p]) * Make[p,t,s] <= avail[t];
                expr1.Clear();
                Tlist2.ForEach(tl => {
                    inputData.ScenList.ForEach(sl =>
                    {
                        inputData.ProdList.ForEach(pl =>
                        {
                            double rate = 1 / inputData.RateList.Find(rl => rl.PROD.Equals(pl.PROD)).RATE;

                            int ixP = inputData.ProdList.IndexOf(pl);
                            int ixT = Tlist2.IndexOf(tl);
                            int ixS = inputData.ScenList.IndexOf(sl);

                            int ixMake = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);

                            expr1.AddTerm(rate, Make[ixMake]);
                        });

                        double avail = inputData.AvailList.Find(al => al.T.Equals(tl.T)).AVAIL;
                        gModel.AddConstr(expr1, GRB.LESS_EQUAL, avail, "TIME_" + tl.T + "_" + sl.SCEN);
                    });
                });

                //subject to Balance2 { p in PROD, s in SCEN}:
                //Make[p, 2, s] + inv1[p] = Sell[p, 2, s] + Inv[p, 2, s];
                //2 => index T => 0
                expr1.Clear();
                inputData.ProdList.ForEach(pl =>
                {
                    inputData.ScenList.ForEach(sl =>
                    {
                        int ixP = inputData.ProdList.IndexOf(pl);
                        int ixT = 0;
                        int ixS = inputData.ScenList.IndexOf(sl);
                        int ix  = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);

                        double inv1 = subModelParams.inv1.Find(il => il.PROD.Equals(pl.PROD)).INV0;

                        expr1.Clear();
                        expr2.Clear();

                        //como sumar un param ????
                        expr1.AddTerm(1, Make[ix]);
                        //expr1.AddTerm(inv1, null); ???? como??? // Se despeja vars & params
                        expr1.AddTerm(-1, Sell[ix]);
                        expr1.AddTerm(-1, Inv[ix]);

                        gModel.AddConstr(expr1, GRB.EQUAL, inv1, "BALANCE2_" + pl.PROD + "_" + sl.SCEN);
                    });
                });

                //subject to Balance { p in PROD, t in 3..T, s in SCEN}:
                //Make[p, t, s] + Inv[p, t - 1, s] = Sell[p, t, s] + Inv[p, t, s];

                inputData.ProdList.ForEach(pl =>
                {
                    Tlist3.ForEach(tl =>
                    {
                        inputData.ScenList.ForEach(sl =>
                        {
                            int ixP = inputData.ProdList.IndexOf(pl);
                            int ixT = Tlist2.IndexOf(tl);
                            int ixS = inputData.ScenList.IndexOf(sl);
                            int ix  = ixVar.getIx3(ixP, ixT, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);
                            int ix2 = ixVar.getIx3(ixP, ixT - 1, ixS, inputData.ProdList.Count, Tlist2.Count, inputData.ScenList.Count);

                            expr1.Clear();
                            expr2.Clear();

                            expr1.AddTerm(1, Make[ix]);
                            expr1.AddTerm(1, Inv[ix2]);

                            expr2.AddTerm(1, Sell[ix]);
                            expr2.AddTerm(1, Inv[ix]);

                            gModel.AddConstr(expr1, GRB.EQUAL, expr2, "SUBJECT TO BALANCE");
                        });
                    });
                });

                //carpeta donde se expande el modelo
                gModel.Write(outputFolder + "Submodel_Model.lp");

                // RESOLVER EL MODELO
                try
                {
                    Console.WriteLine("Solving the sub model with gurobi..");
                    gModel.Optimize();

                    if (gModel.Status == 2)
                    {
                        for (int m = 0; m < Make.Length; m++)
                        {
                            Console.WriteLine("Make Var: " + Make[m].VarName + " = " + Make[m].X);
                        }

                        for (int m = 0; m < Inv.Length; m++)
                        {
                            Console.WriteLine("Inv Var: " + Inv[m].VarName + " = " + Inv[m].X);
                        }

                        for (int m = 0; m < Sell.Length; m++)
                        {
                            Console.WriteLine("Sell Var: " + Sell[m].VarName + " = " + Sell[m].X);
                        }
                    }

                    SubModelOutputs smo = new SubModelOutputs()
                    {
                        make         = Make,
                        sell         = Sell,
                        inv          = Inv,
                        stage2Profit = gModel.ObjVal,
                        gModel       = gModel
                    };

                    //gModel.Dispose();
                    //env.Dispose();

                    return(smo);
                }
                catch { Console.WriteLine("ERROR SOLVING THE MODEL"); }

                gModel.Dispose();
                env.Dispose();
            }

            catch (GRBException ex)
            {
                Console.WriteLine("Error code: " + ex.ErrorCode + ". " + ex.Message);
            }


            return(new SubModelOutputs());
        }
Esempio n. 7
0
        static void Main(string[] args)
        {
            string[] filePaths = Directory.GetFiles(@"./", "*.json");

            foreach (string arquivo in filePaths)
            {
                //Deserializar o arquivo Json para o c#
                var        json      = File.ReadAllText(arquivo);
                Parametros instancia = JsonConvert.DeserializeObject <Parametros>(json);

                //Modelo
                GRBEnv   ambiente = new GRBEnv();
                GRBModel modelo   = new GRBModel(ambiente);
                modelo.ModelName = "Crew Scheduling Problem";

                //número grande
                int M = 1000;

                //Variáveis

                //fração da tarefa i que o membro de equipe n completa na data j
                GRBVar[,,] x = new GRBVar[instancia.crew, instancia.task, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            x[n, i, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "x_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //fração da tarefa i que é completada na data j
                GRBVar[,] x3 = new GRBVar[instancia.task, instancia.date];
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        x3[i, j] = modelo.AddVar(0, 1, 0, GRB.CONTINUOUS, "x3_" + i + "_" + j);
                    }
                }
                //1 se alguma tarefa i é completada na data j
                GRBVar[,] x2 = new GRBVar[instancia.task, instancia.date];
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        x2[i, j] = modelo.AddVar(0, 1, 0, GRB.BINARY, "x2_" + i + "_" + j);
                    }
                }
                //1 se a tarefa i é concluída dentro do horizonte de planejamento
                GRBVar[] x4 = new GRBVar[instancia.task];
                for (int i = 0; i < instancia.task; i++)
                {
                    x4[i] = modelo.AddVar(0, 1, -instancia.c[i] * 2, GRB.BINARY, "x4_" + i);
                }
                //variável fantasma
                GRBVar[] vf = new GRBVar[instancia.task];
                for (int i = 0; i < instancia.task; i++)
                {
                    vf[i] = modelo.AddVar(1, 1, instancia.c[i] * 2, GRB.BINARY, "vf_" + i);
                }
                //1 se o membro de equipe n está trabalhando na tarefa i na data j mas não na data j+1
                GRBVar[,,] x5 = new GRBVar[instancia.crew, instancia.task, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            x5[n, i, j] = modelo.AddVar(0, 1, 0.1, GRB.BINARY, "x5_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //1 se parte da tarefa i é completada na data j mas não na data j+1
                GRBVar[,] x6 = new GRBVar[instancia.task, instancia.date];
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        x6[i, j] = modelo.AddVar(0, 1, 0.9, GRB.BINARY, "x6_" + i + "_" + j);
                    }
                }
                //1 se o membro da equipe n vai trabalhar na data j
                GRBVar[,] y = new GRBVar[instancia.crew, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        y[n, j] = modelo.AddVar(0, 1, instancia.hours_per_shift, GRB.BINARY, "y_" + n + "_" + j);
                    }
                }
                //1 se membro da equipe n trabalha na tarefa i na data j
                GRBVar[,,] z = new GRBVar[instancia.crew, instancia.task, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            z[n, i, j] = modelo.AddVar(0, 1, 0.5, GRB.BINARY, "z_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //1 se o membro de equipe n trabalha na tarefa i
                GRBVar[,] z1 = new GRBVar[instancia.crew, instancia.task];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        z1[n, i] = modelo.AddVar(0, 1, 0.1, GRB.BINARY, "z1_" + n + "_" + i);
                    }
                }
                //1 se o membro de equipe n trabalha no local técnico p na data j
                GRBVar[,,] w = new GRBVar[instancia.crew, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            w[n, p, j] = modelo.AddVar(0, 1, 0, GRB.BINARY, "w_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //1 se o membro de equipe n precisa de transporte entre o local técnico o e o local q na instancia.date j
                GRBVar[,,,] v = new GRBVar[instancia.crew, instancia.technical_place, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int q = 0; q < instancia.technical_place; q++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                v[n, p, q, j] = modelo.AddVar(0, 1, 0, GRB.BINARY, "v_" + n + "_" + p + "_" + q + "_" + j);
                            }
                        }
                    }
                }
                //se a equipe n precisa de transporte para o local técnico p de outro local técnico na data j
                GRBVar[,,] w1 = new GRBVar[instancia.crew, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            w1[n, p, j] = modelo.AddVar(0, 1, 0, GRB.BINARY, "w1_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //se a equipe n precisa de transporte do local técnico p para outro local técnico
                GRBVar[,,] w2 = new GRBVar[instancia.crew, instancia.technical_place, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            w2[n, p, j] = modelo.AddVar(0, 1, 0, GRB.BINARY, "w2_" + n + "_" + p + "_" + j);
                        }
                    }
                }

                //Função objetivo
                modelo.ModelSense = GRB.MINIMIZE;

                //Restrições
                GRBLinExpr exp  = 0.0;
                GRBLinExpr exp2 = 0.0;
                GRBLinExpr exp3 = 0.0;

                //Restrições com relação a tarefa

                //restrição 2
                //a tarefa deve ser concluída dentro do horizonte de planejamento
                for (int i = 0; i < instancia.task; i++)
                {
                    exp.Clear();
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.AddTerm(1, x[n, i, j]);
                        }
                    }
                    modelo.AddConstr(exp == x4[i], "R2_" + i);
                }
                //restrição 3
                //o número total de horas por turno não deve ser excedido
                for (int j = 0; j < instancia.date; j++)
                {
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        exp.Clear();
                        exp2.Clear();
                        exp3.Clear();
                        for (int i = 0; i < instancia.task; i++)
                        {
                            exp.AddTerm(instancia.c[i], x[n, i, j]);
                        }
                        for (int p = 0; p < instancia.technical_place; p++)
                        {
                            exp2.AddTerm(2 * instancia.tm[p], w[n, p, j]);
                            exp2.AddTerm(-instancia.tm[p], w1[n, p, j]);
                            exp2.AddTerm(-instancia.tm[p], w2[n, p, j]);
                        }
                        for (int p = 0; p < instancia.technical_place; p++)
                        {
                            for (int q = 0; q < instancia.technical_place; q++)
                            {
                                exp3.AddTerm(instancia.tr[p, q], v[n, p, q, j]);
                            }
                        }
                        modelo.AddConstr(exp + exp2 + exp3 <= instancia.hours_per_shift, "R3_" + j + "_" + n);
                    }
                }
                //restrição 4
                //a soma das frações das tarefas locadas  não pode exceder o total para completar a tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, x[n, i, j]);
                        }
                        modelo.AddConstr(x2[i, j] >= exp, "R4_" + i + "_" + j);
                    }
                }
                //restrição 5
                //soma de das frações dos membros e equipe num dado dia deve ser igual a x3
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, x[n, i, j]);
                        }
                        modelo.AddConstr(x3[i, j] == exp, "R5_" + i + "_" + j);
                    }
                }
                //restrição 6
                //a tarefa i deve ser completada dentro do horizonte de planejamento se gi=1
                for (int i = 0; i < instancia.task; i++)
                {
                    modelo.AddConstr(x4[i] >= instancia.g[i], "R6_" + i);
                }
                //restrição 7
                //fração da tarefa que é completada num dado dia não deve exceder X4
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(x4[i] >= x[n, i, j], "R7_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 8
                //um membro de equipe não pode ser locado a uma tarefa em um dia em que ele não trabalha
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(y[n, j] >= z[n, i, j], "R8_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 9
                //se o membro de equipe é locado para uma tarefa então z=1
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z[n, i, j] >= x[n, i, j], "R9_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 10
                //a variável z não pode ser 1 se a equipe n não trabalha num dado dia
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z[n, i, j] <= M * x[n, i, j], "R10_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 11
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z1[n, i] >= z[n, i, j], "R11_" + n + "_" + i + "_" + j);
                        }
                    }
                }

                //Restrições de gerenciemanto

                //restrição 12
                //preferencalmente uma tarefa deve concluida pela mesma pessoa que começou trabalhando nela
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date - 1; j++)
                        {
                            modelo.AddConstr(x5[n, i, j] >= z[n, i, j] - z[n, i, j + 1], "R12_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 13
                //uma penalidade será dada ao planejamento se a tarefa i é completada em dias não consecutivos
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date - 1; j++)
                    {
                        modelo.AddConstr(x6[i, j] >= x2[i, j] - x2[i, j + 1], "R13_" + i + "_" + j);
                    }
                }
                //restrição 14
                //o número mínimo de membros de equipe que podem trabalhar simultaneamente em uma tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, z[n, i, j]);
                        }
                        modelo.AddConstr(exp >= instancia.d1[i] * x2[i, j], "R14_" + i + "_" + j);
                    }
                }
                //restrição 15
                //o número máximo de membros de equipe que podem trablhar simultaneamente em uma tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            exp.AddTerm(1, z[n, i, j]);
                        }
                        modelo.AddConstr(exp <= instancia.d2[i] * x2[i, j], "R15_" + i + "_" + j);
                    }
                }
                //restrição 16
                //número mínimo de membros para trabalhar em um tarefa deve ser respeitado
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(x[n, i, j] <= x3[i, j] / instancia.d1[i], "R16_" + n + "_" + i + "_" + j);
                        }
                    }
                }
                //restrição 17
                //membros de equipe não podem trabalhar em dias em que eles não estão disponíveis
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(z[n, i, j] <= instancia.e[n, j], "R17_" + n + "_" + i + "_" + j);
                        }
                    }
                }

                //Restrições com relação a competência

                //restrição 18
                //a combinação do nível de competencias de todos os membros
                //de equipe deve ser suficiente para cada tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        for (int k = 0; k < instancia.competencies; k++)
                        {
                            exp.Clear();
                            for (int n = 0; n < instancia.crew; n++)
                            {
                                exp.AddTerm(instancia.bm3[n, k], z[n, i, j]);
                            }
                            modelo.AddConstr(exp >= x2[i, j] * instancia.bo[i, k] * instancia.level_total, "R18_" + i + "_" + j + "_" + k);
                        }
                    }
                }
                //restrição 19
                //pelo menos um membro de equipe deve ter nível 3 de competencia para a tarefa i
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        for (int k = 0; k < instancia.competencies; k++)
                        {
                            exp.Clear();
                            for (int n = 0; n < instancia.crew; n++)
                            {
                                exp.AddTerm(instancia.bm[n, k], z[n, i, j]);
                            }
                            modelo.AddConstr(exp >= x2[i, j] * instancia.bo[i, k], "R19_" + i + "_" + j + "_" + k);
                        }
                    }
                }
                //restrição 20
                //pelo menos um mebro de equipe tem nível de competencia 3 se vários membros de equipe trabalham na mesma tarefa
                for (int i = 0; i < instancia.task; i++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        for (int k = 0; k < instancia.competencies; k++)
                        {
                            exp.Clear();
                            exp2.Clear();
                            for (int n = 0; n < instancia.crew; n++)
                            {
                                exp.AddTerm(instancia.bm[n, k], x[n, i, j]);
                                exp2.AddTerm(instancia.bm2[n, k], x[n, i, j]);
                            }
                            modelo.AddConstr(exp >= exp2 * (double)(1 / instancia.d1[i]), "R20_" + i + "_" + j + "_" + k);
                        }
                    }
                }

                //Restrições com relação ao transporte

                //restrição 21
                //cada membro de equipe trabalha em um local técnico em que a tarefa está localizada
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int i = 0; i < instancia.task; i++)
                            {
                                exp.AddTerm(instancia.tp[i, p], z[n, i, j]);
                            }
                            modelo.AddConstr(w[n, p, j] <= exp, "R21_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 22
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int i = 0; i < instancia.task; i++)
                            {
                                exp.AddTerm(instancia.tp[i, p], z[n, i, j]);
                            }
                            modelo.AddConstr(w[n, p, j] * M >= exp, "R22_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 23
                //o membro de equipe só é transportado entre os locais técnicos que as tarefas dele estão localizadas
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int q = 0; q < instancia.technical_place; q++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(exp <= w[n, p, j] * M, "R23_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 24
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int q = 0; q < instancia.technical_place; q++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(exp <= w[n, q, j] * M, "R24_" + n + "_" + q + "_" + j);
                        }
                    }
                }
                //restrição 25
                //se o membro de equipe trabalha em mais do que um local técninco durante o turno
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int q = 0; q < instancia.technical_place; q++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int p = 0; p < instancia.technical_place; p++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(w1[n, q, j] == exp, "R25_" + n + "_" + q + "_" + j);
                        }
                    }
                }
                //restrição 26
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            exp.Clear();
                            for (int q = 0; q < instancia.technical_place; q++)
                            {
                                exp.AddTerm(1, v[n, p, q, j]);
                            }
                            modelo.AddConstr(w2[n, p, j] == exp, "R26_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 27
                //cada membro de equipe pode apenas ser transportado de e para cada local técnico uma vez por dia
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(w1[n, p, j] <= 1, "R27_" + n + "_" + p + "_" + j);
                        }
                    }
                }

                //restrição 28
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int p = 0; p < instancia.technical_place; p++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            modelo.AddConstr(w2[n, p, j] <= 1, "R28_" + n + "_" + p + "_" + j);
                        }
                    }
                }
                //restrição 29
                //funcionário será transportado apenas uma vez do e para o depósito
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int j = 0; j < instancia.date; j++)
                    {
                        exp.Clear();
                        for (int p = 0; p < instancia.technical_place; p++)
                        {
                            exp.AddTerm(2, w[n, p, j]);
                            exp.AddTerm(-1, w1[n, p, j]);
                            exp.AddTerm(-1, w2[n, p, j]);
                        }
                        modelo.AddConstr(exp == 2 * y[n, j], "R29_" + n + "_" + j);
                    }
                }

                //aleatório
                int    semente   = 0;
                Random aleatorio = new Random(semente);
                //relógio
                Stopwatch relogio = new Stopwatch();

                //variável para contar quantidade de soluções sem melhoria
                int sem_melhoria = 0;
                //variável para guardar melhor scenário
                int melhorCenario = 0;
                //variável para guardar número de cenários
                int num_scenarios = 5;

                //função que gera números aleatórios sem repetir
                int[] AleatorioaSemRepetir(int quantidade, int minimo, int maximo)
                {
                    int sorteado;

                    int[]      NoRepet = new int[quantidade];
                    int        posicao = 0;
                    List <int> guarda  = new List <int>();

                    while (posicao < quantidade)
                    {
                        sorteado = aleatorio.Next(minimo, maximo);
                        if (!guarda.Contains(sorteado))
                        {
                            guarda.Add(sorteado);
                            NoRepet[posicao] = sorteado;
                            posicao++;
                        }
                    }
                    return(NoRepet);
                }

                //pega a primeira solução factível do gurobi
                relogio.Start();
                modelo.Parameters.SolutionLimit = 1;
                modelo.Optimize();

                //matriz para guardar melhor z
                double[,,] melhor_z = new double[instancia.crew, instancia.task, instancia.date];
                for (int n = 0; n < instancia.crew; n++)
                {
                    for (int i = 0; i < instancia.task; i++)
                    {
                        for (int j = 0; j < instancia.date; j++)
                        {
                            melhor_z[n, i, j] = z[n, i, j].X;
                        }
                    }
                }
                //melhor FO
                double bestFO = modelo.ObjVal;

                //mudar o gurobi para voltar a resolver o problema por completo
                modelo.Parameters.SolutionLimit = 2000000000;
                modelo.Set(GRB.DoubleParam.TimeLimit, 7200);

                //função fix and optimize para datas
                void multiCenariosFixAndOptimizeData(int num_scenarios)
                {
                    // variável para guardar número de cenários
                    int scenarios = 0;

                    //seta o parâmetro do modelo para multiplos scenários
                    modelo.NumScenarios = num_scenarios;
                    //quantas datas ficarão fixas
                    int datasFixas = instancia.date - 2;

                    //vetros que irá guardar datas sorteadas para serem fixas
                    int[] vetorDatas = new int[datasFixas];
                    //criar os cenários a serem otimizados pelo Gurobi
                    while (scenarios < num_scenarios)
                    {
                        modelo.Parameters.ScenarioNumber = scenarios;
                        //sorteia datas que serão fixadas
                        vetorDatas = AleatorioaSemRepetir(datasFixas, 0, instancia.date);
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            for (int i = 0; i < instancia.task; i++)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    if (vetorDatas.Contains(j))
                                    {
                                        z[n, i, j].ScenNUB = melhor_z[n, i, j];
                                        z[n, i, j].ScenNLB = melhor_z[n, i, j];
                                    }
                                    else
                                    {
                                        z[n, i, j].Start = melhor_z[n, i, j];
                                    }
                                }
                            }
                        }
                        semente++;
                        scenarios++;
                    }
                    // Solve multi-scenario model
                    modelo.Optimize();
                    // descobrir qual melhor cenário
                    for (int s = 0; s < num_scenarios; s++)
                    {
                        modelo.Parameters.ScenarioNumber = s;
                        // o comando modelo.ScenNObjVal devolve o valor da função objetivo do cenário atual
                        double atual_FO = modelo.ScenNObjVal;
                        if (atual_FO < bestFO)
                        {
                            //atualiza melhor cenário e melhor FO
                            bestFO        = atual_FO;
                            melhorCenario = s;
                        }
                        else
                        {
                            sem_melhoria++;
                        }
                    }
                    //atualiza a melhor solução de z
                    modelo.Parameters.ScenarioNumber = melhorCenario;
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        for (int i = 0; i < instancia.task; i++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                melhor_z[n, i, j] = z[n, i, j].ScenNX;
                            }
                        }
                    }
                }

                // Fix and Optimize Datas

                //int num_scenarios = 5;
                //while (sem_melhoria < 20)
                //{
                //    multiCenariosFixAndOptimizeData(num_scenarios);
                //    //escreve no console os cenários e suas respectivas FOs
                //    for (int i = 0; i < num_scenarios; i++)
                //    {
                //        modelo.Parameters.ScenarioNumber = i;
                //        Console.WriteLine("Solucao para cenario" + i.ToString() + ":" + modelo.ScenNObjVal.ToString());
                //    }

                //}
                //relogio.Stop();
                ////a variável novoModelo recebe o modelo com melhor cenário
                //modelo.Parameters.ScenarioNumber = melhorCenario;
                //System.Console.WriteLine("Melhor FO:" + modelo.ObjVal.ToString());
                //System.Console.WriteLine($"Tempo total {relogio.ElapsedMilliseconds / 1000} segundos");

                //Função Fix and Optimize equipes
                void multiCenariosFixAndOptimizeEquipes(int num_scenarios)
                {
                    // variável para guardar número de cenários
                    int scenarios = 0;

                    //seta o parâmetro do modelo para multiplos scenários
                    modelo.NumScenarios = num_scenarios;
                    //quantas datas ficarão fixas
                    int equipesFixas = instancia.crew - 2;

                    //vetros que irá guardar datas sorteadas para serem fixas
                    int[] vetorEquipes = new int[equipesFixas];
                    //criar os cenários a serem otimizados pelo Gurobi
                    while (scenarios < num_scenarios)
                    {
                        modelo.Parameters.ScenarioNumber = scenarios;
                        //sorteia datas que serão fixadas
                        vetorEquipes = AleatorioaSemRepetir(equipesFixas, 0, instancia.crew);
                        foreach (int n in vetorEquipes)
                        {
                            for (int i = 0; i < instancia.task; i++)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    z[n, i, j].ScenNUB = melhor_z[n, i, j];
                                    z[n, i, j].ScenNLB = melhor_z[n, i, j];
                                }
                            }
                        }
                        semente++;
                        scenarios++;
                    }
                    // Solve multi-scenario model
                    modelo.Optimize();
                    // descobrir qual melhor cenário
                    for (int s = 0; s < num_scenarios; s++)
                    {
                        modelo.Parameters.ScenarioNumber = s;
                        // o comando modelo.ScenNObjVal devolve o valor da função objetivo do cenário atual
                        double atual_FO = modelo.ScenNObjVal;
                        if (atual_FO < bestFO)
                        {
                            //atualiza melhor cenário e melhor FO
                            bestFO        = atual_FO;
                            melhorCenario = s;
                        }
                        else
                        {
                            sem_melhoria++;
                        }
                    }
                    modelo.Parameters.ScenarioNumber = melhorCenario;
                    //atualiza a melhor solução de z
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        for (int i = 0; i < instancia.task; i++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                melhor_z[n, i, j] = z[n, i, j].ScenNX;
                            }
                        }
                    }
                }

                // Fix and Optimize equipes

                //int num_scenarios = 5;
                //while (sem_melhoria < 20)
                //{
                //    multiCenariosFixAndOptimizeEquipes(num_scenarios);
                //    //escreve no console os cenários e suas respectivas FOs
                //    for (int i = 0; i < num_scenarios; i++)
                //    {
                //        modelo.Parameters.ScenarioNumber = i;
                //        Console.WriteLine("Solucao para cenario" + i.ToString() + ":" + modelo.ScenNObjVal.ToString());
                //    }

                //}
                //relogio.Stop();
                ////a variável novoModelo recebe o modelo com melhor cenário
                //modelo.Parameters.ScenarioNumber = melhorCenario;
                //System.Console.WriteLine("Melhor FO:" + modelo.ObjVal.ToString());
                //System.Console.WriteLine($"Tempo total {relogio.ElapsedMilliseconds / 1000} segundos");

                // Função Fix and Optimize Tarefas

                void multiCenariosFixAndOptimizeTarefas(int num_scenarios)
                {
                    // variável para guardar número de cenários
                    int scenarios = 0;

                    //seta o parâmetro do modelo para multiplos scenários
                    modelo.NumScenarios = num_scenarios;
                    //quantas datas ficarão fixas
                    int tarefasFixas = instancia.task - 2;

                    //vetros que irá guardar datas sorteadas para serem fixas
                    int[] vetorTarefas = new int[tarefasFixas];

                    //criar os cenários a serem otimizados pelo Gurobi
                    while (scenarios < num_scenarios)
                    {
                        modelo.Parameters.ScenarioNumber = scenarios;
                        //sorteia datas que serão fixadas
                        vetorTarefas = AleatorioaSemRepetir(tarefasFixas, 0, instancia.task);
                        for (int n = 0; n < instancia.crew; n++)
                        {
                            foreach (int i in vetorTarefas)
                            {
                                for (int j = 0; j < instancia.date; j++)
                                {
                                    z[n, i, j].ScenNUB = melhor_z[n, i, j];
                                    z[n, i, j].ScenNLB = melhor_z[n, i, j];
                                }
                            }
                        }
                        semente++;
                        scenarios++;
                    }
                    // Solve multi-scenario model
                    modelo.Optimize();
                }

                // Fix and Optimize tarefas


                while (sem_melhoria < 50)
                {
                    //desfixar variáveis z
                    for (int n = 0; n < instancia.crew; n++)
                    {
                        for (int i = 0; i < instancia.task; i++)
                        {
                            for (int j = 0; j < instancia.date; j++)
                            {
                                z[n, i, j].LB = 0.0;
                                z[n, i, j].UB = 1.0;
                            }
                        }
                    }
                    multiCenariosFixAndOptimizeTarefas(num_scenarios);
                    for (int s = 0; s < num_scenarios; s++)
                    {
                        modelo.Parameters.ScenarioNumber = s;
                        double atualFO = modelo.ScenNObjVal;
                        if (atualFO < bestFO)
                        {
                            bestFO        = atualFO;
                            melhorCenario = s;
                            for (int n = 0; n < instancia.crew; n++)
                            {
                                for (int i = 0; i < instancia.task; i++)
                                {
                                    for (int j = 0; j < instancia.date; j++)
                                    {
                                        melhor_z[n, i, j] = z[n, i, j].ScenNX;
                                    }
                                }
                            }
                        }
                    }
                    //escreve no console os cenários e suas respectivas FOs
                    for (int i = 0; i < num_scenarios; i++)
                    {
                        modelo.Parameters.ScenarioNumber = i;
                        Console.WriteLine("Solucao para cenario " + i.ToString() + ":" + modelo.ScenNObjVal.ToString());
                    }
                }
                relogio.Stop();
                //a variável novoModelo recebe o modelo com melhor cenário
                modelo.Parameters.ScenarioNumber = melhorCenario;
                System.Console.WriteLine("Melhor FO:" + modelo.ScenNObjVal.ToString());
                System.Console.WriteLine("Melhor FO:" + bestFO.ToString());
                System.Console.WriteLine($"Tempo total {relogio.ElapsedMilliseconds / 1000} segundos");

                // Seta classe Resultados
                Resultado resultado = new Resultado();
                resultado.nome     = arquivo;
                resultado.segundos = relogio.ElapsedMilliseconds / 1000;
                resultado.valor    = modelo.ObjVal;
                string output = JsonConvert.SerializeObject(resultado);
                System.IO.File.AppendAllText("final.txt", output);
            }
        }
        public void ModeloDARP()
        {
            string Agora = Convert.ToString(DateTime.Now);

            string[] a  = Agora.Split(' ');
            string[] a0 = a[0].Split('/');
            string[] a1 = a[1].Split(':');
            Agora = a0[0] + "_" + a0[1] + "_" + a0[2] + "_" + a1[0] + "_" + a1[1] + "_" + a1[2];

            /// Calcundo algumas constantes que usamos na linearização da carga e janela de tempo
            double[,,] M = new double[problema.NumeroDeCarros, problema.TamanhoMaximo, problema.TamanhoMaximo];
            double[,,] U = new double[problema.NumeroDeCarros, problema.TamanhoMaximo, problema.TamanhoMaximo];

            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 0; i < problema.TamanhoMaximo; i++)
                {
                    for (int j = 0; j < problema.TamanhoMaximo; j++)
                    {
                        M[k, i, j] = Math.Max(0, problema.usuario[i].InstanteSaida + problema.usuario[i].Duracao + +problema.Distancias[i, j] - problema.usuario[j].InstanteChegada);
                        U[k, i, j] = Math.Min(frota.Capacidade, frota.Capacidade + problema.usuario[i].Carga);
                    }
                }
            }

            ///////////////
            ///////////////
            string nome    = Convert.ToString(problema.NumeroDeClientes) + '_' + Convert.ToString(problema.NumeroDeCarros) + "_" + Convert.ToString(frota.Capacidade);
            string caminho = @"C:\Users\hcspe\Documents\Doutorado\TeseUberPool\Classe_Rotas_SARP\MSCordeau\saidas\";
            // Model
            GRBEnv   env   = new GRBEnv(caminho + "outputSARPTeste(" + Agora + "_" + nome + ").log");
            GRBModel model = new GRBModel(env);


            model.Set(GRB.StringAttr.ModelName, "SARPTeste");
            model.Set(GRB.DoubleParam.TimeLimit, 3600);
            ///// Declaração de variáveis

            // Variável x
            GRBVar[,,] x = new GRBVar[problema.NumeroDeCarros, problema.TamanhoMaximo, problema.TamanhoMaximo];
            for (int i = 0; i < problema.TamanhoMaximo; i++)
            {
                for (int j = 0; j < problema.TamanhoMaximo; j++)
                {
                    for (int k = 0; k < problema.NumeroDeCarros; k++)
                    {
                        x[k, i, j] = model.AddVar(0, 1, problema.Distancias[i, j], GRB.BINARY, "x" + k + "_" + i + "_" + j);
                        if (i == problema.TamanhoMaximo)
                        {
                            x[k, i, j].UB = 0.0;
                        }
                    }
                }
            }

            // Variável B do tempo no nó i
            GRBVar[,] B = new GRBVar[problema.NumeroDeCarros, problema.TamanhoMaximo];
            for (int i = 0; i < problema.TamanhoMaximo; i++)
            {
                for (int k = 0; k < problema.NumeroDeCarros; k++)
                {
                    B[k, i] = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "B" + i + "_" + k);
                }
            }

            // Variavel Q da carga no nó i
            GRBVar[,] Q = new GRBVar[problema.NumeroDeCarros, problema.TamanhoMaximo];
            for (int i = 0; i < problema.TamanhoMaximo; i++)
            {
                for (int k = 0; k < problema.NumeroDeCarros; k++)
                {
                    Q[k, i] = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "Q" + i + "_" + k);
                }
            }

            // Varivavel L tempo de viagem do usuario quando passa por i
            GRBVar[,] L = new GRBVar[problema.NumeroDeCarros, problema.TamanhoMaximo];
            for (int i = 0; i < problema.TamanhoMaximo; i++)
            {
                for (int k = 0; k < problema.NumeroDeCarros; k++)
                {
                    L[k, i] = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "L" + i + "_" + k);
                }
            }



            ///////////////////////// Senso do modelo
            model.Set(GRB.IntAttr.ModelSense, GRB.MINIMIZE);

            ///////////////////////// Restrições
            // Add constraints


            // Restrição 2
            GRBLinExpr soma2;
            GRBLinExpr soma3;

            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 1; i <= problema.NumeroDeClientes; i++)
                {
                    soma2 = 0;
                    soma3 = 0;
                    for (int j = 0; j < problema.TamanhoMaximo; j++)
                    {
                        soma2.AddTerm(1, x[k, i, j]);
                        soma3.AddTerm(1, x[k, problema.NumeroDeClientes + i, j]);
                    }
                    string st = "Rt2" + i + k;
                    model.AddConstr(soma2 - soma3 == 0, st);
                    soma2.Clear();
                    soma3.Clear();
                }
            }

            // Restrição 1
            GRBLinExpr soma = 0.0;

            for (int i = 1; i <= problema.NumeroDeClientes; i++)
            {
                for (int j = 0; j < problema.TamanhoMaximo; j++)
                {
                    for (int k = 0; k < problema.NumeroDeCarros; k++)
                    {
                        soma.AddTerm(1, x[k, i, j]);
                    }
                }
                model.AddConstr(soma == 1, "Rt1" + "_" + i);
                soma.Clear();
            }



            // Restrição 3;
            GRBLinExpr soma4 = 0;

            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int j = 0; j < problema.TamanhoMaximo; j++)
                {
                    soma4.AddTerm(1, x[k, 0, j]);
                }
                model.AddConstr(soma4 == 1, "Rt3" + "_" + k);
                soma4.Clear();
            }

            // Restrição 4;
            GRBLinExpr soma5 = 0;
            GRBLinExpr soma6 = 0;

            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 0; i < problema.TamanhoMaximo - 1; i++)
                {
                    for (int j = 0; j < problema.TamanhoMaximo; j++)
                    {
                        soma5.AddTerm(1, x[k, j, i]);
                        soma6.AddTerm(1, x[k, i, j]);
                    }
                    model.AddConstr(soma5 - soma6 == 0, "Rt4" + i + k);
                    soma5.Clear();
                    soma6.Clear();
                }
            }

            // Restrição 5
            GRBLinExpr soma7 = 0;

            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 0; i < problema.TamanhoMaximo; i++)
                {
                    soma7.AddTerm(1, x[k, i, problema.TamanhoMaximo - 1]);
                }
                model.AddConstr(soma7 == 1, "Rt5" + k);
                soma7.Clear();
            }

            // Restrição 7 Atualizar Q
            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 0; i < problema.TamanhoMaximo; i++)
                {
                    for (int j = 0; j < problema.TamanhoMaximo; j++)
                    {
                        model.AddConstr(Q[k, j] >= Q[k, i] + problema.usuario[j].Carga - U[k, i, j] * (1 - x[k, i, j]), "Rt7_" + k + "_" + i + "_" + j);
                    }
                }
            }

            // Restrição 8 Atualizar B
            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 0; i < problema.TamanhoMaximo; i++)
                {
                    for (int j = 0; j < problema.TamanhoMaximo; j++)
                    {
                        model.AddConstr(B[k, j] >= B[k, i] + problema.usuario[i].Duracao + problema.Distancias[i, j] - M[k, i, j] * (1 - x[k, i, j]), "Rt6_" + k + "_" + i + "_" + j);
                    }
                }
            }

            // Restrição 9 atualizar L
            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 1; i <= problema.NumeroDeClientes; i++)
                {
                    model.AddConstr(L[k, i] == B[k, problema.NumeroDeClientes + i] - B[k, i] - problema.usuario[i].Duracao, "Rt8_" + k + "_" + i);
                }
            }

            // Restrição 10 Intervalo do B limitado por T
            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                model.AddConstr(B[k, problema.TamanhoMaximo - 1] - B[k, 0] <= problema.LarguraHorizonte, "Rt9_" + k);
            }

            // Restrição 11 janela de B
            for (int k = 0; k < problema.NumeroDeCarros; k++)
            {
                for (int i = 0; i < problema.TamanhoMaximo; i++)
                {
                    model.AddConstr(problema.usuario[i].InstanteChegada <= B[k, i], "RtjanelaBe_" + k + "_" + i);
                    model.AddConstr(B[k, i] <= problema.usuario[i].InstanteSaida, "RtjanelaBl_" + k + "_" + i);
                }
            }

            // Restrição 12 janela de L
            for (int i = 1; i <= problema.NumeroDeClientes; i++)
            {
                for (int k = 0; k < problema.NumeroDeCarros; k++)
                {
                    model.AddConstr(problema.Distancias[i, problema.NumeroDeClientes + i] <= L[k, i], "Rt10e_" + i + "_" + k);
                    model.AddConstr(L[k, i] <= problema.TempoMaximoViagemUsuario, "Rt10l_" + i + "_" + k);
                }
            }

            // Restrição 12 janela Q
            for (int i = 1; i < problema.TamanhoMaximo; i++)
            {
                for (int k = 0; k < problema.NumeroDeCarros; k++)
                {
                    model.AddConstr(Math.Max(0, problema.usuario[i].Carga) <= Q[k, i], "Rt11e_" + i + "_" + k);
                    model.AddConstr(Q[k, i] <= Math.Min(problema.frota[0].Capacidade, problema.frota[0].Capacidade + problema.usuario[i].Carga), "Rt11l_" + i + "_" + k);
                }
            }

            string Str = Convert.ToString(problema.NumeroDeClientes) + "_" + Convert.ToString(problema.NumeroDeCarros) + Convert.ToString(problema.frota[0].Capacidade);

            // Escrever o modelo lp
            string caminho1 = @"C:\Users\hcspe\Documents\Doutorado\TeseUberPool\Classe_Rotas_SARP\MSCordeau\modelos\Modelo";

            model.Write(Str + "_" + Agora + ".lp");

            // Otimizar o modelo
            model.Optimize();

            // Arquivos
            // modelo.Write("C:\Users\hellen\Dropbox\DNA sequencing\codes\DNA_Sequencing_2\Modelos\modelo.lp")
            // modelo.Write("C:\Users\hellen\Dropbox\DNA sequencing\codes\DNA_Sequencing_2\Modelos\modelo.mps")

            string caminho2 = @"C:\Users\hcspe\Documents\Doutorado\TeseUberPool\Classe_Rotas_SARP\MSCordeau\solucoes\modelo.ilp";

            if (model.Get(GRB.IntAttr.Status) == GRB.Status.INFEASIBLE)
            {
                model.ComputeIIS();    //computa o modelo ilp, infactível linear problem;
                model.Write(caminho2);
            }

            string caminho3 = @"C:\Users\hcspe\Documents\Doutorado\TeseUberPool\Classe_Rotas_SARP\MSCordeau\solucoes\solucaoModelo";

            // procurar infactibilidade
            if (model.Get(GRB.IntAttr.Status) != GRB.Status.INFEASIBLE)
            {
                if (model.SolCount != 0)
                {
                    model.Write(caminho3 + Str + "_" + Agora + ".sol");
                    // modelo.Write("C:\Users\hellen\Dropbox\DNA sequencing\codes\DNA_Sequencing_2\Solucoes\solucao.mst")

                    problema.SolucaoExata = new int[problema.NumeroDeCarros - 1, problema.TamanhoMaximo, problema.TamanhoMaximo];

                    int qtdnNula = 0;
                    for (int k = 0; k < problema.NumeroDeCarros; k++)
                    {
                        for (int i = 0; i < problema.TamanhoMaximo; i++)
                        {
                            for (int j = 0; j < problema.TamanhoMaximo; j++)
                            {
                                problema.SolucaoExata[k, i, j] = Convert.ToInt32(x[k, i, j].X);
                                if (x[k, i, j].X != 0)
                                {
                                    qtdnNula += 1;
                                }
                            }
                        }
                    }

                    problema.SolucaoExataNaoNula = new int[qtdnNula, 3];
                    int   cont = 0;
                    int[] QtdAtendimentosCarro = new int[problema.NumeroDeCarros - 1];
                    for (int k = 0; k < problema.NumeroDeCarros; k++)
                    {
                        for (int i = 0; i < problema.TamanhoMaximo; i++)
                        {
                            for (int j = 0; j < problema.TamanhoMaximo; j++)
                            {
                                if (x[k, i, j].X != 0)
                                {
                                    problema.SolucaoExataNaoNula[cont, 0] = k;
                                    problema.SolucaoExataNaoNula[cont, 1] = i;
                                    problema.SolucaoExataNaoNula[cont, 2] = j;
                                    problema.SolucaoExataNaoNula[cont, 3] = Convert.ToInt32(x[k, i, j].X);
                                    cont += 1;
                                    if (k == 0)
                                    {
                                        QtdAtendimentosCarro[k] += 1;
                                    }
                                    if (k == 1)
                                    {
                                        QtdAtendimentosCarro[k] += 1;
                                    }
                                }
                            }
                        }
                    }

                    frota.Ocupacao = new double[problema.NumeroDeCarros, qtdnNula];

                    for (int i = 0; i < qtdnNula; i++)
                    {
                        if (problema.usuario[problema.SolucaoExataNaoNula[i, 1]].Carga > 0)
                        {
                            problema.usuario[i].TempoDeViagem = L[problema.SolucaoExataNaoNula[i, 0], problema.SolucaoExataNaoNula[i, 1]].X;
                        }
                    }

                    ///////// Escrever os extras, no caso tempo usuario viagem

                    string caminho4 = @"C:\Users\hcspe\Documents\Doutorado\TeseUberPool\Classe_Rotas_SARP\MSCordeau\Extras\";
                    caminho4 = caminho4 + Str + "_" + Agora + ".txt";

                    Stream       entrada  = File.Create(caminho4);
                    StreamWriter escritor = new StreamWriter(entrada);

                    escritor.WriteLine("Tempo Usuario Viagem");
                    for (int i = 0; i < qtdnNula; i++)
                    {
                        escritor.Write(Convert.ToString(problema.usuario[i].TempoDeViagem) + " ");
                    }
                    escritor.WriteLine("   ");

                    entrada.Close();
                    escritor.Close();
                }
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            GRBEnv   Ambiente = new GRBEnv();
            GRBModel Modelo   = new GRBModel(Ambiente);
            int      Tamanho  = 4;

            GRBVar[,,] X = new GRBVar[Tamanho, Tamanho, Tamanho];
            for (int i = 0; i < Tamanho; i++)
            {
                for (int j = 0; j < Tamanho; j++)
                {
                    for (int k = 0; k < Tamanho; k++)
                    {
                        X[i, j, k] = Modelo.AddVar(0, 1, 0, GRB.BINARY, "X_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString());
                    }
                }
            }
            GRBLinExpr Expressao = new GRBLinExpr();

            //Criar restrições de que em cada célula exatamente 1 número é alocado
            for (int i = 0; i < Tamanho; i++)
            {
                for (int j = 0; j < Tamanho; j++)
                {
                    Expressao.Clear();
                    for (int k = 0; k < Tamanho; k++)
                    {
                        Expressao.AddTerm(1, X[i, j, k]);
                    }
                    Modelo.AddConstr(Expressao == 1, "SingularidadeDaCelula_" + i.ToString() + "_" + j.ToString());
                }
            }
            //Criar restrições de que cada número, em cada linha, é alocado uma única vez
            for (int i = 0; i < Tamanho; i++)
            {
                for (int k = 0; k < Tamanho; k++)
                {
                    Expressao.Clear();
                    for (int j = 0; j < Tamanho; j++)
                    {
                        Expressao.AddTerm(1, X[i, j, k]);
                    }
                    Modelo.AddConstr(Expressao == 1, "SingularidadeNaLinha_" + i.ToString() + "_" + k.ToString());
                }
            }
            //Criar restrições de que cada número, em cada coluna, é alocado uma única vez
            for (int j = 0; j < Tamanho; j++)
            {
                for (int k = 0; k < Tamanho; k++)
                {
                    Expressao.Clear();
                    for (int i = 0; i < Tamanho; i++)
                    {
                        Expressao.AddTerm(1, X[i, j, k]);
                    }
                    Modelo.AddConstr(Expressao == 1, "SingularidadeNaColuna_" + j.ToString() + "_" + k.ToString());
                }
            }

            Modelo.Write("C:\\Teste\\Sudoku.lp");
            Modelo.Optimize();
            Modelo.Write("C:\\Teste\\Sudoku.sol");
        }
Esempio n. 10
0
        public void CriarResolverProblema()
        {
            Ambiente      = new GRBEnv(@"C:\Teste\ModeloPDP.log");
            Modelo        = new GRBModel(Ambiente);
            GRBVar[,,] X  = new GRBVar[QuantidadeNos, QuantidadeNos, QuantidadeVeiculos];
            GRBVar[,,,] Y = new GRBVar[QuantidadeNos, QuantidadeNos, QuantidadeVeiculos, QuantidadeRequisicoes];
            GRBVar[,,] Z  = new GRBVar[QuantidadeNos, QuantidadeNos, QuantidadeVeiculos];
            //função objetivo, (10) e (11)
            for (int k = 0; k < QuantidadeVeiculos; k++)
            {
                for (int i = 0; i < QuantidadeNos; i++)
                {
                    for (int j = 0; j < QuantidadeNos; j++)
                    {
                        if (i != j)
                        {
                            X[i, j, k] = Modelo.AddVar(0, 1, MatrizDistancias[i, j] * Veiculos[k].CustoPorDistancia, GRB.BINARY, "x_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString());
                        }
                    }
                }
            }
            for (int r = 0; r < QuantidadeRequisicoes; r++)
            {
                for (int k = 0; k < QuantidadeVeiculos; k++)
                {
                    for (int i = 0; i < QuantidadeNos; i++)
                    {
                        for (int j = 0; j < QuantidadeNos; j++)
                        {
                            if (i != j)
                            {
                                Y[i, j, k, r] = Modelo.AddVar(0, 1, 0, GRB.BINARY, "y_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString() + "_" + r.ToString());
                            }
                        }
                    }
                }
            }
            for (int k = 0; k < QuantidadeVeiculos; k++)
            {
                for (int i = 0; i < QuantidadeNos; i++)
                {
                    for (int j = 0; j < QuantidadeNos; j++)
                    {
                        if (i != j)
                        {
                            Z[i, j, k] = Modelo.AddVar(0, 1, 0, GRB.BINARY, "z_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString());
                        }
                    }
                }
            }
            GRBLinExpr expr  = new GRBLinExpr();
            GRBLinExpr expr1 = new GRBLinExpr();
            GRBLinExpr expr2 = new GRBLinExpr();

            //Conjunto (1)
            for (int k = 0; k < QuantidadeVeiculos; k++)
            {
                expr.Clear();
                int OrigemAtual = Veiculos[k].Origem;
                for (int j = 0; j < QuantidadeNos; j++)
                {
                    if (j != OrigemAtual)
                    {
                        expr.AddTerm(1, X[OrigemAtual, j, k]);
                    }
                }
                Modelo.AddConstr(expr <= 1, "R1_" + k.ToString());
            }
            //Conjunto (2)
            for (int k = 0; k < QuantidadeVeiculos; k++)
            {
                expr1.Clear();
                expr2.Clear();
                int OrigemAtual  = Veiculos[k].Origem;
                int DestinoAtual = Veiculos[k].Destino;
                for (int j = 0; j < QuantidadeNos; j++)
                {
                    if (j != OrigemAtual)
                    {
                        expr1.AddTerm(1, X[OrigemAtual, j, k]);
                    }
                }
                for (int j = 0; j < QuantidadeNos; j++)
                {
                    if (j != DestinoAtual)
                    {
                        expr2.AddTerm(1, X[j, DestinoAtual, k]);
                    }
                }
                Modelo.AddConstr(expr1 == expr2, "R2_" + k.ToString());
            }
            // conjunto (3)

            for (int k = 0; k < QuantidadeVeiculos; k++)
            {
                int OrigemAtual  = Veiculos[k].Origem;
                int DestinoAtual = Veiculos[k].Destino;
                for (int i = 0; i < QuantidadeNos; i++)
                {
                    if (i != OrigemAtual && i != DestinoAtual)
                    {
                        expr1.Clear();
                        expr2.Clear();
                        for (int j = 0; j < QuantidadeNos; j++)
                        {
                            if (j != i)
                            {
                                expr1.AddTerm(1, X[i, j, k]);
                            }
                        }
                        for (int j = 0; j < QuantidadeNos; j++)
                        {
                            if (i != j)
                            {
                                expr2.AddTerm(1, X[j, i, k]);
                            }
                        }
                        Modelo.AddConstr(expr1 - expr2 == 0, "R3_" + k.ToString() + "_" + i.ToString());
                    }
                }
            }
            //conjunto (4)
            for (int r = 0; r < QuantidadeRequisicoes; r++)
            {
                int ColetaAtual = Requisicoes[r].Coleta;
                expr.Clear();
                for (int k = 0; k < QuantidadeVeiculos; k++)
                {
                    for (int j = 0; j < QuantidadeNos; j++)
                    {
                        if (j != ColetaAtual)
                        {
                            expr.AddTerm(1, Y[ColetaAtual, j, k, r]);
                        }
                    }
                }
                Modelo.AddConstr(expr == 1, "R4_" + r.ToString());
            }
            //conjunto (5)
            for (int r = 0; r < QuantidadeRequisicoes; r++)
            {
                int EntregaAtual = Requisicoes[r].Entrega;
                expr.Clear();
                for (int k = 0; k < QuantidadeVeiculos; k++)
                {
                    for (int j = 0; j < QuantidadeNos; j++)
                    {
                        if (j != EntregaAtual)
                        {
                            expr.AddTerm(1, Y[j, EntregaAtual, k, r]);
                        }
                    }
                }
                Modelo.AddConstr(expr == 1, "R5_" + r.ToString());
            }
            //conjunto (6)
            //faremos depois

            //conjunto (7)
            for (int k = 0; k < QuantidadeVeiculos; k++)
            {
                for (int r = 0; r < QuantidadeRequisicoes; r++)
                {
                    int ColetaAtual  = Requisicoes[r].Coleta;
                    int EntregaAtual = Requisicoes[r].Entrega;
                    for (int i = 0; i < QuantidadeNos; i++)
                    {
                        if (i != ColetaAtual && i != EntregaAtual)
                        {
                            expr1.Clear();
                            expr2.Clear();
                            for (int j = 0; j < QuantidadeNos; j++)
                            {
                                if (j != i)
                                {
                                    expr1.AddTerm(1, Y[i, j, k, r]);
                                }
                            }
                            for (int j = 0; j < QuantidadeNos; j++)
                            {
                                if (j != i)
                                {
                                    expr2.AddTerm(1, Y[j, i, k, r]);
                                }
                            }
                            Modelo.AddConstr(expr1 - expr2 == 0, "R7_" + k.ToString() + "_" + r.ToString() + "_" + i.ToString());
                        }
                    }
                }
            }
            //conjunto (8)
            for (int i = 0; i < QuantidadeNos; i++)
            {
                for (int j = 0; j < QuantidadeNos; j++)
                {
                    if (i != j)
                    {
                        for (int k = 0; k < QuantidadeVeiculos; k++)
                        {
                            for (int r = 0; r < QuantidadeRequisicoes; r++)
                            {
                                Modelo.AddConstr(Y[i, j, k, r] <= X[i, j, k], "R8_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString() + "_" + r.ToString());
                            }
                        }
                    }
                }
            }
            //conjunto (9)
            for (int k = 0; k < QuantidadeVeiculos; k++)
            {
                for (int i = 0; i < QuantidadeNos; i++)
                {
                    for (int j = 0; j < QuantidadeNos; j++)
                    {
                        if (i != j)
                        {
                            expr.Clear();
                            for (int r = 0; r < QuantidadeRequisicoes; r++)
                            {
                                expr.AddTerm(Requisicoes[r].Quantidade, Y[i, j, k, r]);
                            }
                            Modelo.AddConstr(expr <= Veiculos[k].Capacidade * X[i, j, k], "R9_" + k.ToString() + "_" + i.ToString() + "_" + j.ToString());
                        }
                    }
                }
            }
            //Conjunto (12)
            for (int i = 0; i < QuantidadeNos; i++)
            {
                for (int j = 0; j < QuantidadeNos; j++)
                {
                    for (int k = 0; k < QuantidadeNos; k++)
                    {
                        if (i != j)// && i!=Veiculos[k].Origem && j!=Veiculos[k].Destino)
                        {
                            Modelo.AddConstr(X[i, j, k] <= Z[i, j, k], "R12_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString());
                        }
                    }
                }
            }
            //Conjunto (13)
            for (int i = 0; i < QuantidadeNos; i++)
            {
                for (int j = 0; j < QuantidadeNos; j++)
                {
                    for (int k = 0; k < QuantidadeNos; k++)
                    {
                        if (i != j && i != Veiculos[k].Origem && j != Veiculos[k].Destino)
                        {
                            Modelo.AddConstr(Z[i, j, k] + Z[j, i, k] == 1, "R13_" + i.ToString() + "_" + j.ToString() + "_" + k.ToString());
                        }
                    }
                }
            }
            //conjunto (14)
            for (int i = 0; i < QuantidadeNos; i++)
            {
                for (int j = 0; j < QuantidadeNos; j++)
                {
                    for (int l = 0; l < QuantidadeNos; l++)
                    {
                        for (int k = 0; k < QuantidadeNos; k++)
                        {
                            if (i != j && j != l && l != i && i != Veiculos[k].Origem && j != Veiculos[k].Origem && l != Veiculos[k].Destino)
                            {
                                Modelo.AddConstr(Z[i, j, k] + Z[j, l, k] + Z[l, i, k] <= 2, "R14_" + i.ToString() + "_" + j.ToString() + "_" + l.ToString() + "_" + k.ToString());
                            }
                        }
                    }
                }
                //1 -> 5 -> 3 -> 7 -> 2 -> 1
                //z_1_5=1; z_1_3=1; z_1_7=1; z_1_2=1
                //z_3_7=1; z_3_2=1; z_3_1;
                //z_7_2=1; z_7_1=1
                //z_1_3 + z_3_7 + z_7_1 <= 2
            }
            //Modelo.Parameters.TimeLimit = 60;
            //Modelo.Parameters.MIPGap = 0.05;
            Modelo.Optimize();
            MessageBox.Show(Modelo.ObjVal.ToString());
            Modelo.Write("C:\\Teste\\ModeloPDP.lp");
            Modelo.Write("C:\\Teste\\ModeloPDP.sol");
        }