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()); }
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(); }
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]; } } } }
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()); }
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"); }
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"); }