コード例 #1
0
 private void SetupGurobiEnvironmentAndModel()
 {
     // Model
     env   = new GRBEnv();
     model = new GRBModel(env);
     model.Set(GRB.StringAttr.ModelName, "diet");
 }
コード例 #2
0
    ///<summary>Create a batch request for given problem file</summary>
    static string newbatchrequest(string filename)
    {
        string batchID = "";
        // Start environment, create Model object from file
        GRBEnv env = setupbatchenv();

        env.Start();
        GRBModel model = new GRBModel(env, filename);

        try {
            // Set some parameters
            model.Set(GRB.DoubleParam.MIPGap, 0.01);
            model.Set(GRB.IntParam.JSONSolDetail, 1);

            // Define tags for some variables to access their values later
            int count = 0;
            foreach (GRBVar v in model.GetVars())
            {
                v.VTag = "Variable" + count;
                count += 1;
                if (count >= 10)
                {
                    break;
                }
            }

            // Submit batch request
            batchID = model.OptimizeBatch();

            // Dispose of model and env
        } finally {
            model.Dispose();
            env.Dispose();
        }
        return(batchID);
    }
コード例 #3
0
        static void SolvePrimal(GRBEnv env, HashSet <string> nodes_set, List <Arc> arcs)
        {
            GRBModel m = new GRBModel(env);

            Dictionary <string, GRBVar> distances = new Dictionary <string, GRBVar>(); // pi

            foreach (string node in nodes_set)
            {
                distances[node] = m.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "distance." + node);
            }
            m.Update();
            distances[ORIGIN].Set(GRB.DoubleAttr.Obj, -1);
            distances[DESTINATION].Set(GRB.DoubleAttr.Obj, 1);
            m.Set(GRB.IntAttr.ModelSense, -1);

            Dictionary <Arc, GRBConstr> constrs = new Dictionary <Arc, GRBConstr>();

            foreach (Arc a in arcs)
            {
                constrs[a] = m.AddConstr(distances[a.dest] <= distances[a.source] + a.length, "distance_con." + a.source + "." + a.dest);
            }

            m.Update();
            m.Write("shortest_path.lp");
            m.Optimize();

            foreach (var pair in distances)
            {
                Console.WriteLine("distance to {0} is {1}", pair.Key, pair.Value.Get(GRB.DoubleAttr.X));
            }

            foreach (var pair in constrs)
            {
                GRBConstr con = pair.Value;
                if (con.Get(GRB.DoubleAttr.Pi) > 0.5)
                {
                    Console.WriteLine("Arc {0}, {1} is in shortest path", pair.Key.source, pair.Key.dest);
                }
            }
            Console.WriteLine("Length of shortest path is {0}", m.Get(GRB.DoubleAttr.ObjVal));
            m.Dispose();
        }
コード例 #4
0
ファイル: GurobiJspModel.cs プロジェクト: ALICE-InRu/Code
        private GRBVar[,] _x; // starting time of job j on machine a

        #endregion Fields

        #region Constructors

        public GurobiJspModel(ProblemInstance prob, string name, int tmlim_min)
        {
            _n = prob.NumJobs;
            _m = prob.NumMachines;
            Info = "Starting gurobi optimisation";
            _fileName = String.Format("jssp.{0}.log", name);

            // Model
            try
            {
                _env = new GRBEnv(_fileName);
                if (tmlim_min > 0)
                    _env.Set(GRB.DoubleParam.TimeLimit, tmlim_min*60); // time limit is set to seconds!
                _env.Set(GRB.IntParam.LogToConsole, 0);

                _model = new GRBModel(_env);
                _model.Set(GRB.StringAttr.ModelName, "jsp");
            }
            catch (GRBException e)
            {
                Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
            }

            DecisionVariables();
            ProcessingOrder(prob.Procs, prob.Sigma);
            DisjunctiveCondition(prob.Procs);
            Objective(prob.Procs, prob.Sigma);

            //TrueOptimumDecVars = Optimise(out TrueOptimum);
            //if (TrueOptimum > 0) // Objective cutoff
            //    _model.GetEnv().Set(GRB.DoubleParam.Cutoff, TrueOptimum + 0.5);
            /* Indicates that you aren't interested in solutions whose objective values
                 * are worse than the specified value. If the objective value for the optimal
                 * solution is better than the specified cutoff, the solver will return the
                 * optimal solution. Otherwise, it will terminate with a CUTOFF status.
                 */
            // seems to be only for LP relaxation, not MIP objective
        }
コード例 #5
0
        public void BuildAndSolveDietLp()
        {
            DietLpProblem = new DietLpProblem();

            SetupGurobiEnvironmentAndModel();

            DietLpProblem.SetupDecisionVariables(model);

            // The objective is to minimize the costs
            model.Set(GRB.IntAttr.ModelSense, 1);
            // Update model to integrate new variables
            model.Update();

            DietLpProblem.AddNutritionConstraints(model);

            OptimizeAndPrintSolution();

            AddLimitDiaryConstraint();

            OptimizeAndPrintSolution();

            DisposeModelAndEnvironment();
        }
コード例 #6
0
 public void SetRuntimeOptions()
 {
     model.Set(GRB.DoubleParam.TimeLimit, parameters.time_limit);
     model.Set(GRB.IntParam.SolutionLimit, parameters.max_solutions);
 }
コード例 #7
0
    static void Main()
    {
        try {
            // Sample data
            // Sets of days and workers
            string[] Shifts =
                new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
                               "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
                               "Sun14" };
            string[] Workers =
                new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };

            int nShifts  = Shifts.Length;
            int nWorkers = Workers.Length;

            // Number of workers required for each shift
            double[] shiftRequirements =
                new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };

            // Amount each worker is paid to work one shift
            double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 };

            // Worker availability: 0 if the worker is unavailable for a shift
            double[,] availability =
                new double[, ] {
                { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
                { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
                { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
                { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
                { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
            };

            // Model
            GRBEnv   env   = new GRBEnv();
            GRBModel model = new GRBModel(env);
            model.Set(GRB.StringAttr.ModelName, "assignment");

            // Assignment variables: x[w][s] == 1 if worker w is assigned
            // to shift s. Since an assignment model always produces integer
            // solutions, we use continuous variables and solve as an LP.
            GRBVar[,] x = new GRBVar[nWorkers, nShifts];
            for (int w = 0; w < nWorkers; ++w)
            {
                for (int s = 0; s < nShifts; ++s)
                {
                    x[w, s] =
                        model.AddVar(0, availability[w, s], pay[w], GRB.CONTINUOUS,
                                     Workers[w] + "." + Shifts[s]);
                }
            }

            // The objective is to minimize the total pay costs
            model.Set(GRB.IntAttr.ModelSense, 1);

            // Update model to integrate new variables
            model.Update();

            // Constraint: assign exactly shiftRequirements[s] workers
            // to each shift s
            for (int s = 0; s < nShifts; ++s)
            {
                GRBLinExpr lhs = 0.0;
                for (int w = 0; w < nWorkers; ++w)
                {
                    lhs.AddTerm(1.0, x[w, s]);
                }
                model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
            }

            // Optimize
            model.Optimize();
            int status = model.Get(GRB.IntAttr.Status);
            if (status == GRB.Status.UNBOUNDED)
            {
                Console.WriteLine("The model cannot be solved "
                                  + "because it is unbounded");
                return;
            }
            if (status == GRB.Status.OPTIMAL)
            {
                Console.WriteLine("The optimal objective is " +
                                  model.Get(GRB.DoubleAttr.ObjVal));
                return;
            }
            if ((status != GRB.Status.INF_OR_UNBD) &&
                (status != GRB.Status.INFEASIBLE))
            {
                Console.WriteLine("Optimization was stopped with status " + status);
                return;
            }

            // Do IIS
            Console.WriteLine("The model is infeasible; computing IIS");
            model.ComputeIIS();
            Console.WriteLine("\nThe following constraint(s) "
                              + "cannot be satisfied:");
            foreach (GRBConstr c in model.GetConstrs())
            {
                if (c.Get(GRB.IntAttr.IISConstr) == 1)
                {
                    Console.WriteLine(c.Get(GRB.StringAttr.ConstrName));
                }
            }

            // Dispose of model and env
            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: " + e.ErrorCode + ". " +
                              e.Message);
        }
    }
コード例 #8
0
    static void Main()
    {
        try {
            // Sample data
            // Sets of days and workers
            string[] Shifts =
                new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
                               "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
                               "Sun14" };
            string[] Workers =
                new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };

            int nShifts  = Shifts.Length;
            int nWorkers = Workers.Length;

            // Number of workers required for each shift
            double[] shiftRequirements =
                new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };

            // Worker availability: 0 if the worker is unavailable for a shift
            double[,] availability =
                new double[, ] {
                { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
                { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
                { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
                { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
                { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
            };

            // Model
            GRBEnv   env   = new GRBEnv();
            GRBModel model = new GRBModel(env);
            model.Set(GRB.StringAttr.ModelName, "assignment");

            // Assignment variables: x[w][s] == 1 if worker w is assigned
            // to shift s. This is no longer a pure assignment model, so we must
            // use binary variables.
            GRBVar[,] x = new GRBVar[nWorkers, nShifts];
            for (int w = 0; w < nWorkers; ++w)
            {
                for (int s = 0; s < nShifts; ++s)
                {
                    x[w, s] =
                        model.AddVar(0, availability[w, s], 0, GRB.BINARY,
                                     Workers[w] + "." + Shifts[s]);
                }
            }

            // Slack variables for each shift constraint so that the shifts can
            // be satisfied
            GRBVar[] slacks = new GRBVar[nShifts];
            for (int s = 0; s < nShifts; ++s)
            {
                slacks[s] =
                    model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
                                 Shifts[s] + "Slack");
            }

            // Variable to represent the total slack
            GRBVar totSlack = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
                                           "totSlack");

            // Variables to count the total shifts worked by each worker
            GRBVar[] totShifts = new GRBVar[nWorkers];
            for (int w = 0; w < nWorkers; ++w)
            {
                totShifts[w] = model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS,
                                            Workers[w] + "TotShifts");
            }

            // Update model to integrate new variables
            model.Update();

            GRBLinExpr lhs;

            // Constraint: assign exactly shiftRequirements[s] workers
            // to each shift s, plus the slack
            for (int s = 0; s < nShifts; ++s)
            {
                lhs = new GRBLinExpr();
                lhs.AddTerm(1.0, slacks[s]);
                for (int w = 0; w < nWorkers; ++w)
                {
                    lhs.AddTerm(1.0, x[w, s]);
                }
                model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
            }

            // Constraint: set totSlack equal to the total slack
            lhs = new GRBLinExpr();
            for (int s = 0; s < nShifts; ++s)
            {
                lhs.AddTerm(1.0, slacks[s]);
            }
            model.AddConstr(lhs == totSlack, "totSlack");

            // Constraint: compute the total number of shifts for each worker
            for (int w = 0; w < nWorkers; ++w)
            {
                lhs = new GRBLinExpr();
                for (int s = 0; s < nShifts; ++s)
                {
                    lhs.AddTerm(1.0, x[w, s]);
                }
                model.AddConstr(lhs == totShifts[w], "totShifts" + Workers[w]);
            }

            // Objective: minimize the total slack
            model.SetObjective(1.0 * totSlack);

            // Optimize
            int status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
            if (status != GRB.Status.OPTIMAL)
            {
                return;
            }

            // Constrain the slack by setting its upper and lower bounds
            totSlack.Set(GRB.DoubleAttr.UB, totSlack.Get(GRB.DoubleAttr.X));
            totSlack.Set(GRB.DoubleAttr.LB, totSlack.Get(GRB.DoubleAttr.X));

            // Variable to count the average number of shifts worked
            GRBVar avgShifts =
                model.AddVar(0, GRB.INFINITY, 0, GRB.CONTINUOUS, "avgShifts");

            // Variables to count the difference from average for each worker;
            // note that these variables can take negative values.
            GRBVar[] diffShifts = new GRBVar[nWorkers];
            for (int w = 0; w < nWorkers; ++w)
            {
                diffShifts[w] = model.AddVar(-GRB.INFINITY, GRB.INFINITY, 0,
                                             GRB.CONTINUOUS, Workers[w] + "Diff");
            }

            // Update model to integrate new variables
            model.Update();

            // Constraint: compute the average number of shifts worked
            lhs = new GRBLinExpr();
            for (int w = 0; w < nWorkers; ++w)
            {
                lhs.AddTerm(1.0, totShifts[w]);
            }
            model.AddConstr(lhs == nWorkers * avgShifts, "avgShifts");

            // Constraint: compute the difference from the average number of shifts
            for (int w = 0; w < nWorkers; ++w)
            {
                model.AddConstr(totShifts[w] - avgShifts == diffShifts[w],
                                Workers[w] + "Diff");
            }

            // Objective: minimize the sum of the square of the difference from the
            // average number of shifts worked
            GRBQuadExpr qobj = new GRBQuadExpr();
            for (int w = 0; w < nWorkers; ++w)
            {
                qobj.AddTerm(1.0, diffShifts[w], diffShifts[w]);
            }
            model.SetObjective(qobj);

            // Optimize
            status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
            if (status != GRB.Status.OPTIMAL)
            {
                return;
            }

            // Dispose of model and env
            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: " + e.ErrorCode + ". " +
                              e.Message);
        }
    }
コード例 #9
0
        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();
                }
            }
        }
コード例 #10
0
ファイル: bilinear_cs.cs プロジェクト: praveingk/p4fire
    static void Main()
    {
        try {
            GRBEnv   env   = new GRBEnv("bilinear.log");
            GRBModel model = new GRBModel(env);

            // Create variables

            GRBVar x = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "x");
            GRBVar y = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "y");
            GRBVar z = model.AddVar(0.0, GRB.INFINITY, 0.0, GRB.CONTINUOUS, "z");

            // Set objective

            GRBLinExpr obj = x;
            model.SetObjective(obj, GRB.MAXIMIZE);

            // Add linear constraint: x + y + z <= 10

            model.AddConstr(x + y + z <= 10, "c0");

            // Add bilinear inequality: x * y <= 2

            model.AddQConstr(x * y <= 2, "bilinear0");

            // Add bilinear equality: x * z + y * z == 1

            model.AddQConstr(x * z + y * z == 1, "bilinear1");

            // Optimize model

            try {
                model.Optimize();
            } catch (GRBException e) {
                Console.WriteLine("Failed (as expected) " + e.ErrorCode + ". " + e.Message);
            }

            model.Set(GRB.IntParam.NonConvex, 2);
            model.Optimize();

            Console.WriteLine(x.VarName + " " + x.X);
            Console.WriteLine(y.VarName + " " + y.X);
            Console.WriteLine(z.VarName + " " + z.X);

            Console.WriteLine("Obj: " + model.ObjVal + " " + obj.Value);

            x.Set(GRB.CharAttr.VType, GRB.INTEGER);
            model.Optimize();

            Console.WriteLine(x.VarName + " " + x.X);
            Console.WriteLine(y.VarName + " " + y.X);
            Console.WriteLine(z.VarName + " " + z.X);

            Console.WriteLine("Obj: " + model.ObjVal + " " + obj.Value);

            // Dispose of model and env

            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
        }
    }
コード例 #11
0
        public HttpResponseMessage Optimize(string RunName)
        {
            using (var dbConn = new ApplicationDbContext())
            {
                //Variables for students, semesters, courses, and course/semester offerings
                students = dbConn.StudentPreferences.Where(m => m.IsActive == true).Include(m => m.Courses).Include(m => m.Student.CompletedCourses).OrderByDescending(m => m.Student.CompletedCourses.Count()).ToArray();
                crssems = dbConn.CourseSemesters.Where(m => m.IsActive == true).Include(m => m.Course).Include(m => m.Semester).ToArray();
                courses = crssems.Select(m => m.Course).Distinct().ToArray();
                sems = crssems.Select(m => m.Semester).Distinct().OrderBy(m => m.Type).OrderBy(m => m.Year).ToArray();

                var completed = dbConn.CompletedCourses.ToList();
                try
                {
                    GRBEnv env = new GRBEnv("mip1.log");
                    GRBModel model = new GRBModel(env);
                    model.Set(GRB.StringAttr.ModelName, "Course Optimizer");
                    GRBVar[,] slacks = new GRBVar[courses.Length, sems.Length];

                    //Assignment of student, course, and semester.  Student must have a desire to take the coure, has not taken the course, and the course is offered to be included
                    GRBVar[,,] CourseAllocation = new GRBVar[students.Length, courses.Length, sems.Length];
                    for (int i = 0; i < students.Length; i++)
                    {
                        for (int j = 0; j < courses.Length; j++)
                        {
                            for (int k = 0; k < sems.Length; k++)
                            {
                                if (students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID) && crssems.Contains(crssems.SingleOrDefault(m => m.Course == courses[j] && m.Semester == sems[k])))
                                    CourseAllocation[i, j, k] = model.AddVar(0, 1, 1, GRB.BINARY, "students." + (i + 1).ToString() + "_Course." + (j + 1).ToString() + "_Semester." + (k + 1).ToString());
                                else
                                    CourseAllocation[i, j, k] = model.AddVar(0, 0, 1, GRB.BINARY, "students." + (i + 1).ToString() + "_Course." + (j + 1).ToString() + "_Semester." + (k + 1).ToString());
                            }
                        }
                    }
                    model.Set(GRB.IntAttr.ModelSense, 1);
                    model.Update();

                    //MUST TAKE DESIRED COURSE ONLY ONCE
                    //Constrains the students to only take courses they desire once and for when the course is offered and does not allow a repeat of a course in another semester
                    for (int i = 0; i < students.Length; i++)
                    {
                        for (int j = 0; j < courses.Length; j++)
                        {
                            if (students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID))
                            {
                                GRBLinExpr constStudentDesiredCourses = 0.0;
                                for (int k = 0; k < sems.Length; k++)
                                {
                                    if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year))
                                        constStudentDesiredCourses.AddTerm(1.0, CourseAllocation[i, j, k]);
                                }
                                String sStudentDesiredCourses = "DesiredCourse." + j + 1 + "_Student." + i + 1;
                                model.AddConstr(constStudentDesiredCourses == 1, sStudentDesiredCourses);
                            }
                        }

                        //MAX COURSES PER SEMESTER
                        //Constrains the students to only have a maximum number of 2 courses per semester.
                        for (int k = 0; k < sems.Length; k++)
                        {
                            GRBLinExpr constMaxPerSem = 0.0;
                            for (int j = 0; j < courses.Length; j++)
                            {
                                if (!completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID) && (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year)))
                                    constMaxPerSem.AddTerm(1, CourseAllocation[i, j, k]);
                            }
                            String sCourseSem = "maxCourseStudent." + i + 1 + "_Semester." + k + 1;
                            model.AddConstr(constMaxPerSem <= MAX_COURSES_PER_SEMESTER, sCourseSem);
                        }

                        //PREREQUISITES
                        //Constrains the students to take prerequisite courses prior to taking a course that needs the prerequisite
                        for (int j = 0; j < courses.Length; j++)
                        {
                            if (courses[j].Prerequisites.Any() && students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID))
                            {

                                foreach (var prereq in courses[j].Prerequisites)
                                {
                                    int prereqIndex = Array.IndexOf(courses, prereq);
                                    GRBLinExpr coursePrereqConst1 = 0.0;
                                    GRBLinExpr coursePrereqConst2 = 0.0;
                                    if (!completed.Any(m => m.GaTechId == students[i].GaTechId && m.Course.ID == prereq.ID))
                                    {

                                        for (int k = 0; k < sems.Length; k++)
                                        {

                                            if (prereqIndex >= 0)
                                            {
                                                coursePrereqConst1.AddTerm(k + 1, CourseAllocation[i, prereqIndex, k]);
                                                coursePrereqConst2.AddTerm(k, CourseAllocation[i, j, k]);
                                            }
                                        }
                                    }
                                    model.AddConstr(coursePrereqConst1, GRB.LESS_EQUAL, coursePrereqConst2, "PREREQ_Student" + i + "_Course+" + j + "_Prereq" + prereqIndex);

                                }

                            }
                        }
                    }

                    //SENIORITY
                    //Students are already ordered from dB query by seniority in descending order and puts a preference to senior students over the next student that desires that
                    //same course with less seniority.
                    for (int j = 0; j < courses.Length; j++)
                    {
                        for (int i = 0; i < students.Length - 1; i++)
                        {
                            if (students[i].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID))
                            {
                                int SemsRemain = (students[i].Courses.Count - students[i].Student.CompletedCourses.Count) / 2 + (students[i].Courses.Count - students[i].Student.CompletedCourses.Count) % 2;
                                for (int n = i + 1; n < students.Length; n++)
                                {
                                    if (students[n].Courses.Contains(courses[j]) && !completed.Any(m => m.GaTechId == students[n].GaTechId && courses[j].ID == m.Course_ID))
                                    {
                                        GRBLinExpr​ seniority = 0.0;
                                        for (int k = 0; k < sems.Length; k++)
                                        {
                                            if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year))
                                            {
                                                if (k <= SemsRemain)
                                                {
                                                    seniority​.AddTerm(1.0, CourseAllocation[i, j, k]);
                                                    seniority​.AddTerm(-1.0, CourseAllocation​[n, j, k]);
                                                }
                                                else
                                                {
                                                    seniority​.AddTerm(-1.0, CourseAllocation[i, j, k]);
                                                    seniority​.AddTerm(1.0, CourseAllocation​[n, j, k]);
                                                }
                                            }
                                        }
                                        model.AddConstr(seniority, GRB.GREATER_EQUAL, 0, "Seniority for Student." + students[i] + "_Course." + courses[j]);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    //Add the slack variable for all semester & course offerings then constrain the maximum number of students
                    //to take a couse in a semester.
                    for (int k = 0; k < sems.Length; k++)
                    {
                        for (int j = 0; j < courses.Length; j++)
                        {
                            if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year))
                            {
                                slacks[j, k] = model.AddVar(0, GRB.INFINITY, 0, GRB.INTEGER, sems[k].Type.ToString() + "." + sems[k].Year.ToString() + "." + courses[j].Name + ".Slacks");
                                GRBLinExpr constMaxStudCrsSem = 0.0;
                                for (int i = 0; i < students.Length; i++)
                                {
                                    if (!completed.Any(m => m.GaTechId == students[i].GaTechId && courses[j].ID == m.Course_ID))
                                        constMaxStudCrsSem.AddTerm(1.0, CourseAllocation[i, j, k]);
                                }
                                model.Update();
                                constMaxStudCrsSem.AddTerm(-1.0, slacks[j, k]);
                                model.AddConstr(constMaxStudCrsSem <= crssems.Single(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year).StudentLimit, sems[k].Type.ToString() + "." + sems[k].Year.ToString() + "." + courses[j].Name);
                            }
                        }
                    }

                    //Add total slack to the optimization model for all courses in the semesters they are offered.
                    GRBVar totSlack = model.AddVar(0, GRB.INFINITY, 0, GRB.INTEGER, "totSlack");
                    GRBLinExpr lhs = new GRBLinExpr();
                    lhs.AddTerm(-1.0, totSlack);
                    for (int j = 0; j < courses.Length; j++)
                    {
                        for (int k = 0; k < sems.Length; k++)
                        {
                            if (crssems.Any(m => m.Course.ID == courses[j].ID && m.Semester.Type == sems[k].Type && m.Semester.Year == sems[k].Year))
                                lhs.AddTerm(1.0, slacks[j, k]);
                        }
                    }
                    model.Update();
                    model.AddConstr(lhs, GRB.EQUAL, 0, "totSlack");

                    // Objective: minimize the total slack
                    GRBLinExpr obj = new GRBLinExpr();
                    obj.AddTerm(1.0, totSlack);
                    model.SetObjective(obj);

                    //Optimize the model to minimize the total slack and maximize students to course offerings based on input variables and constraints.
                    model.Optimize();

                    //Write Results optimization results to database
                    writeResults(CourseAllocation, students, courses, sems, crssems, dbConn, Convert.ToInt32(model.Get(GRB.DoubleAttr.ObjVal)), RunName);

                    //Clean-Up
                    model.Dispose();
                    env.Dispose();
            }
                catch (Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An Error occured while running the optimization.");
            }
            }
            return Request.CreateResponse(HttpStatusCode.OK);
        }
コード例 #12
0
    static void Main()
    {
        try {
            // Sample data
            // Sets of days and workers
            string[] Shifts =
                new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
                               "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
                               "Sun14" };
            string[] Workers =
                new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };

            int nShifts  = Shifts.Length;
            int nWorkers = Workers.Length;

            // Number of workers required for each shift
            double[] shiftRequirements =
                new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };

            // Amount each worker is paid to work one shift
            double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 };

            // Worker availability: 0 if the worker is unavailable for a shift
            double[,] availability =
                new double[, ] {
                { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
                { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
                { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
                { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
                { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
            };

            // Model
            GRBEnv   env   = new GRBEnv();
            GRBModel model = new GRBModel(env);
            model.Set(GRB.StringAttr.ModelName, "assignment");

            // Assignment variables: x[w][s] == 1 if worker w is assigned
            // to shift s. Since an assignment model always produces integer
            // solutions, we use continuous variables and solve as an LP.
            GRBVar[,] x = new GRBVar[nWorkers, nShifts];
            for (int w = 0; w < nWorkers; ++w)
            {
                for (int s = 0; s < nShifts; ++s)
                {
                    x[w, s] =
                        model.AddVar(0, availability[w, s], pay[w], GRB.CONTINUOUS,
                                     Workers[w] + "." + Shifts[s]);
                }
            }

            // The objective is to minimize the total pay costs
            model.Set(GRB.IntAttr.ModelSense, 1);

            // Update model to integrate new variables
            model.Update();

            // Constraint: assign exactly shiftRequirements[s] workers
            // to each shift s
            LinkedList <GRBConstr> reqCts = new LinkedList <GRBConstr>();
            for (int s = 0; s < nShifts; ++s)
            {
                GRBLinExpr lhs = 0.0;
                for (int w = 0; w < nWorkers; ++w)
                {
                    lhs.AddTerm(1.0, x[w, s]);
                }
                GRBConstr newCt =
                    model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
                reqCts.AddFirst(newCt);
            }

            // Optimize
            model.Optimize();
            int status = model.Get(GRB.IntAttr.Status);
            if (status == GRB.Status.UNBOUNDED)
            {
                Console.WriteLine("The model cannot be solved "
                                  + "because it is unbounded");
                return;
            }
            if (status == GRB.Status.OPTIMAL)
            {
                Console.WriteLine("The optimal objective is " +
                                  model.Get(GRB.DoubleAttr.ObjVal));
                return;
            }
            if ((status != GRB.Status.INF_OR_UNBD) &&
                (status != GRB.Status.INFEASIBLE))
            {
                Console.WriteLine("Optimization was stopped with status " + status);
                return;
            }

            // Add slack variables to make the model feasible
            Console.WriteLine("The model is infeasible; adding slack variables");

            // Set original objective coefficients to zero
            model.SetObjective(new GRBLinExpr());

            // Add a new slack variable to each shift constraint so that the shifts
            // can be satisfied
            LinkedList <GRBVar> slacks = new LinkedList <GRBVar>();
            foreach (GRBConstr c in reqCts)
            {
                GRBColumn col = new GRBColumn();
                col.AddTerm(1.0, c);
                GRBVar newvar =
                    model.AddVar(0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, col,
                                 c.Get(GRB.StringAttr.ConstrName) + "Slack");
                slacks.AddFirst(newvar);
            }

            // Solve the model with slacks
            model.Optimize();
            status = model.Get(GRB.IntAttr.Status);
            if ((status == GRB.Status.INF_OR_UNBD) ||
                (status == GRB.Status.INFEASIBLE) ||
                (status == GRB.Status.UNBOUNDED))
            {
                Console.WriteLine("The model with slacks cannot be solved "
                                  + "because it is infeasible or unbounded");
                return;
            }
            if (status != GRB.Status.OPTIMAL)
            {
                Console.WriteLine("Optimization was stopped with status " + status);
                return;
            }

            Console.WriteLine("\nSlack values:");
            foreach (GRBVar sv in slacks)
            {
                if (sv.Get(GRB.DoubleAttr.X) > 1e-6)
                {
                    Console.WriteLine(sv.Get(GRB.StringAttr.VarName) + " = " +
                                      sv.Get(GRB.DoubleAttr.X));
                }
            }

            // Dispose of model and env
            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: " + e.ErrorCode + ". " +
                              e.Message);
        }
    }
コード例 #13
0
ファイル: workforce3_cs.cs プロジェクト: revisalo/cr2
    static void Main()
    {
        try {

          // Sample data
          // Sets of days and workers
          string[] Shifts =
          new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
              "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
              "Sun14" };
          string[] Workers =
          new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };

          int nShifts = Shifts.Length;
          int nWorkers = Workers.Length;

          // Number of workers required for each shift
          double[] shiftRequirements =
          new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };

          // Amount each worker is paid to work one shift
          double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 };

          // Worker availability: 0 if the worker is unavailable for a shift
          double[,] availability =
          new double[,] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
              { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
              { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
              { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
              { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
              { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
              { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };

          // Model
          GRBEnv env = new GRBEnv();
          GRBModel model = new GRBModel(env);
          model.Set(GRB.StringAttr.ModelName, "assignment");

          // Assignment variables: x[w][s] == 1 if worker w is assigned
          // to shift s. Since an assignment model always produces integer
          // solutions, we use continuous variables and solve as an LP.
          GRBVar[,] x = new GRBVar[nWorkers,nShifts];
          for (int w = 0; w < nWorkers; ++w) {
        for (int s = 0; s < nShifts; ++s) {
          x[w,s] =
              model.AddVar(0, availability[w,s], pay[w], GRB.CONTINUOUS,
                           Workers[w] + "." + Shifts[s]);
        }
          }

          // The objective is to minimize the total pay costs
          model.Set(GRB.IntAttr.ModelSense, 1);

          // Update model to integrate new variables
          model.Update();

          // Constraint: assign exactly shiftRequirements[s] workers
          // to each shift s
          LinkedList<GRBConstr> reqCts = new LinkedList<GRBConstr>();
          for (int s = 0; s < nShifts; ++s) {
        GRBLinExpr lhs = 0.0;
        for (int w = 0; w < nWorkers; ++w)
          lhs += x[w,s];
        GRBConstr newCt =
            model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
        reqCts.AddFirst(newCt);
          }

          // Optimize
          model.Optimize();
          int status = model.Get(GRB.IntAttr.Status);
          if (status == GRB.Status.UNBOUNDED) {
        Console.WriteLine("The model cannot be solved "
            + "because it is unbounded");
        return;
          }
          if (status == GRB.Status.OPTIMAL) {
        Console.WriteLine("The optimal objective is " +
            model.Get(GRB.DoubleAttr.ObjVal));
        return;
          }
          if ((status != GRB.Status.INF_OR_UNBD) &&
          (status != GRB.Status.INFEASIBLE)) {
        Console.WriteLine("Optimization was stopped with status " + status);
        return;
          }

          // Add slack variables to make the model feasible
          Console.WriteLine("The model is infeasible; adding slack variables");

          // Set original objective coefficients to zero
          model.SetObjective(new GRBLinExpr());

          // Add a new slack variable to each shift constraint so that the shifts
          // can be satisfied
          LinkedList<GRBVar> slacks = new LinkedList<GRBVar>();
          foreach (GRBConstr c in reqCts) {
        GRBColumn col = new GRBColumn();
        col.AddTerm(1.0, c);
        GRBVar newvar =
            model.AddVar(0, GRB.INFINITY, 1.0, GRB.CONTINUOUS, col,
                         c.Get(GRB.StringAttr.ConstrName) + "Slack");
        slacks.AddFirst(newvar);
          }

          // Solve the model with slacks
          model.Optimize();
          status = model.Get(GRB.IntAttr.Status);
          if ((status == GRB.Status.INF_OR_UNBD) ||
          (status == GRB.Status.INFEASIBLE) ||
          (status == GRB.Status.UNBOUNDED)) {
        Console.WriteLine("The model with slacks cannot be solved "
            + "because it is infeasible or unbounded");
        return;
          }
          if (status != GRB.Status.OPTIMAL) {
        Console.WriteLine("Optimization was stopped with status " + status);
        return;
          }

          Console.WriteLine("\nSlack values:");
          foreach (GRBVar sv in slacks) {
        if (sv.Get(GRB.DoubleAttr.X) > 1e-6) {
          Console.WriteLine(sv.Get(GRB.StringAttr.VarName) + " = " +
              sv.Get(GRB.DoubleAttr.X));
        }
          }

          // Dispose of model and env
          model.Dispose();
          env.Dispose();

        } catch (GRBException e) {
          Console.WriteLine("Error code: " + e.ErrorCode + ". " +
          e.Message);
        }
    }
コード例 #14
0
    static void Main()
    {
        try{
            // Sample data
            int      groundSetSize = 10;
            double[] objCoef = new double[] { 32, 32, 15, 15, 6, 6, 1, 1, 1, 1 };
            double[] knapsackCoef = new double[] { 16, 16, 8, 8, 4, 4, 2, 2, 1, 1 };
            double   Budget = 33;
            int      e, status, nSolutions;

            // Create environment
            GRBEnv env = new GRBEnv("poolsearch_cs.log");

            // Create initial model
            GRBModel model = new GRBModel(env);
            model.ModelName = "poolsearch_cs";

            // Initialize decision variables for ground set:
            // x[e] == 1 if element e is chosen
            GRBVar[] Elem = model.AddVars(groundSetSize, GRB.BINARY);
            model.Set(GRB.DoubleAttr.Obj, Elem, objCoef, 0, groundSetSize);

            for (e = 0; e < groundSetSize; e++)
            {
                Elem[e].VarName = string.Format("El{0}", e);
            }

            // Constraint: limit total number of elements to be picked to be at most
            // Budget
            GRBLinExpr lhs = new GRBLinExpr();
            for (e = 0; e < groundSetSize; e++)
            {
                lhs.AddTerm(knapsackCoef[e], Elem[e]);
            }
            model.AddConstr(lhs, GRB.LESS_EQUAL, Budget, "Budget");

            // set global sense for ALL objectives
            model.ModelSense = GRB.MAXIMIZE;

            // Limit how many solutions to collect
            model.Parameters.PoolSolutions = 1024;

            // Limit the search space by setting a gap for the worst possible solution that will be accepted
            model.Parameters.PoolGap = 0.10;

            // do a systematic search for the k-best solutions
            model.Parameters.PoolSearchMode = 2;

            // save problem
            model.Write("poolsearch_cs.lp");

            // Optimize
            model.Optimize();

            // Status checking
            status = model.Status;

            if (status == GRB.Status.INF_OR_UNBD ||
                status == GRB.Status.INFEASIBLE ||
                status == GRB.Status.UNBOUNDED)
            {
                Console.WriteLine("The model cannot be solved " +
                                  "because it is infeasible or unbounded");
                return;
            }
            if (status != GRB.Status.OPTIMAL)
            {
                Console.WriteLine("Optimization was stopped with status {0}", status);
                return;
            }

            // Print best selected set
            Console.WriteLine("Selected elements in best solution:");
            Console.Write("\t");
            for (e = 0; e < groundSetSize; e++)
            {
                if (Elem[e].X < .9)
                {
                    continue;
                }
                Console.Write("El{0} ", e);
            }
            Console.WriteLine();

            // Print number of solutions stored
            nSolutions = model.SolCount;
            Console.WriteLine("Number of solutions found: {0}", nSolutions);

            // Print objective values of solutions
            for (e = 0; e < nSolutions; e++)
            {
                model.Parameters.SolutionNumber = e;
                Console.Write("{0} ", model.PoolObjVal);
                if (e % 15 == 14)
                {
                    Console.WriteLine();
                }
            }
            Console.WriteLine();

            // Print fourth best set if available
            if (nSolutions >= 4)
            {
                model.Parameters.SolutionNumber = 3;

                Console.WriteLine("Selected elements in fourth best solution:");
                Console.Write("\t");
                for (e = 0; e < groundSetSize; e++)
                {
                    if (Elem[e].Xn < .9)
                    {
                        continue;
                    }
                    Console.Write("El{0} ", e);
                }
                Console.WriteLine();
            }

            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: {0}. {1}", e.ErrorCode, e.Message);
        }
    }
コード例 #15
0
        public static void build_initial_model(bool lp_relax)
        {
            env = new GRBEnv(true);
            env.Set("LogFile", "Recoloracao.log");
            env.Set(GRB.IntParam.LogToConsole, 0);
            env.Start();

            model           = new GRBModel(env);
            model.ModelName = "Recoloracao";
            model.Set(GRB.IntParam.Threads, 1);
            model.Set(GRB.IntParam.Method, 1);
            model.Set(GRB.DoubleParam.TimeLimit, 1800);

            X = new GRBVar[input.nVertices, input.nCores];
            var obj = new GRBLinExpr();

            for (int i = 0; i < input.nVertices; i++)
            {
                for (int j = 0; j < input.nCores; j++)
                {
                    string nome = "X_ " + i.ToString() + "_c " + j.ToString();

                    if (lp_relax)
                    {
                        X[i, j] = model.AddVar(0.0, 1.0, 1.0, GRB.CONTINUOUS, nome);
                    }
                    else
                    {
                        X[i, j] = model.AddVar(0.0, 1.0, 1.0, GRB.BINARY, nome);
                    }

                    if (input.caminhoColorido[i] != j + 1)
                    {
                        obj.AddTerm(1, X[i, j]);
                    }
                }
            }

            model.SetObjective(obj, GRB.MINIMIZE);

            // Restrição 1
            for (int i = 0; i < input.nVertices; i++)
            {
                GRBLinExpr soma = new GRBLinExpr();

                for (int c = 0; c < input.nCores; c++)
                {
                    soma.AddTerm(1.0, X[i, c]);
                }

                model.AddConstr(soma, GRB.EQUAL, 1, "Cor vértice" + i);
            }

            // Restrição 2
            for (int p = 0; p < input.nVertices - 2; p++)
            {
                for (int r = p + 2; r < input.nVertices; r++)
                {
                    for (int q = p + 1; q < r; q++)
                    {
                        for (int k = 0; k < input.nCores; k++)
                        {
                            model.AddConstr(X[p, k] - X[q, k] + X[r, k], GRB.LESS_EQUAL, 1, "p" + p + "-q" + q + "-r" + r + "-k" + k);
                        }
                    }
                }
            }
        }
コード例 #16
0
ファイル: diet_cs.cs プロジェクト: revisalo/cr2
    static void Main()
    {
        try {

          // Nutrition guidelines, based on
          // USDA Dietary Guidelines for Americans, 2005
          // http://www.health.gov/DietaryGuidelines/dga2005/
          string[] Categories =
          new string[] { "calories", "protein", "fat", "sodium" };
          int nCategories = Categories.Length;
          double[] minNutrition = new double[] { 1800, 91, 0, 0 };
          double[] maxNutrition = new double[] { 2200, GRB.INFINITY, 65, 1779 };

          // Set of foods
          string[] Foods =
          new string[] { "hamburger", "chicken", "hot dog", "fries",
              "macaroni", "pizza", "salad", "milk", "ice cream" };
          int nFoods = Foods.Length;
          double[] cost =
          new double[] { 2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89,
              1.59 };

          // Nutrition values for the foods
          double[,] nutritionValues = new double[,] {
          { 410, 24, 26, 730 },   // hamburger
          { 420, 32, 10, 1190 },  // chicken
          { 560, 20, 32, 1800 },  // hot dog
          { 380, 4, 19, 270 },    // fries
          { 320, 12, 10, 930 },   // macaroni
          { 320, 15, 12, 820 },   // pizza
          { 320, 31, 12, 1230 },  // salad
          { 100, 8, 2.5, 125 },   // milk
          { 330, 8, 10, 180 }     // ice cream
          };

          // Model
          GRBEnv env = new GRBEnv();
          GRBModel model = new GRBModel(env);
          model.Set(GRB.StringAttr.ModelName, "diet");

          // Create decision variables for the nutrition information,
          // which we limit via bounds
          GRBVar[] nutrition = new GRBVar[nCategories];
          for (int i = 0; i < nCategories; ++i) {
        nutrition[i] =
            model.AddVar(minNutrition[i], maxNutrition[i], 0, GRB.CONTINUOUS,
                         Categories[i]);
          }

          // Create decision variables for the foods to buy
          GRBVar[] buy = new GRBVar[nFoods];
          for (int j = 0; j < nFoods; ++j) {
        buy[j] =
            model.AddVar(0, GRB.INFINITY, cost[j], GRB.CONTINUOUS, Foods[j]);
          }

          // The objective is to minimize the costs
          model.Set(GRB.IntAttr.ModelSense, 1);

          // Update model to integrate new variables
          model.Update();

          // Nutrition constraints
          for (int i = 0; i < nCategories; ++i) {
        GRBLinExpr ntot = 0.0;
        for (int j = 0; j < nFoods; ++j)
          ntot += nutritionValues[j,i] * buy[j];
        model.AddConstr(ntot == nutrition[i], Categories[i]);
          }

          // Solve
          model.Optimize();
          PrintSolution(model, buy, nutrition);

          Console.WriteLine("\nAdding constraint: at most 6 servings of dairy");
          model.AddConstr(buy[7] + buy[8] <= 6.0, "limit_dairy");

          // Solve
          model.Optimize();
          PrintSolution(model, buy, nutrition);

          // Dispose of model and env
          model.Dispose();
          env.Dispose();

        } catch (GRBException e) {
          Console.WriteLine("Error code: " + e.ErrorCode + ". " +
          e.Message);
        }
    }
コード例 #17
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);
            }
        }
コード例 #18
0
ファイル: workforce2_cs.cs プロジェクト: revisalo/cr2
    static void Main()
    {
        try {

          // Sample data
          // Sets of days and workers
          string[] Shifts =
          new string[] { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
              "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
              "Sun14" };
          string[] Workers =
          new string[] { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" };

          int nShifts = Shifts.Length;
          int nWorkers = Workers.Length;

          // Number of workers required for each shift
          double[] shiftRequirements =
          new double[] { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 };

          // Amount each worker is paid to work one shift
          double[] pay = new double[] { 10, 12, 10, 8, 8, 9, 11 };

          // Worker availability: 0 if the worker is unavailable for a shift
          double[,] availability =
          new double[,] { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 },
              { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
              { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
              { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
              { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 },
              { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 },
              { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };

          // Model
          GRBEnv env = new GRBEnv();
          GRBModel model = new GRBModel(env);
          model.Set(GRB.StringAttr.ModelName, "assignment");

          // Assignment variables: x[w][s] == 1 if worker w is assigned
          // to shift s. Since an assignment model always produces integer
          // solutions, we use continuous variables and solve as an LP.
          GRBVar[,] x = new GRBVar[nWorkers,nShifts];
          for (int w = 0; w < nWorkers; ++w) {
        for (int s = 0; s < nShifts; ++s) {
          x[w,s] =
              model.AddVar(0, availability[w,s], pay[w], GRB.CONTINUOUS,
                           Workers[w] + "." + Shifts[s]);
        }
          }

          // The objective is to minimize the total pay costs
          model.Set(GRB.IntAttr.ModelSense, 1);

          // Update model to integrate new variables
          model.Update();

          // Constraint: assign exactly shiftRequirements[s] workers
          // to each shift s
          for (int s = 0; s < nShifts; ++s) {
        GRBLinExpr lhs = 0.0;
        for (int w = 0; w < nWorkers; ++w)
          lhs += x[w, s];
        model.AddConstr(lhs == shiftRequirements[s], Shifts[s]);
          }

          // Optimize
          model.Optimize();
          int status = model.Get(GRB.IntAttr.Status);
          if (status == GRB.Status.UNBOUNDED) {
        Console.WriteLine("The model cannot be solved "
            + "because it is unbounded");
        return;
          }
          if (status == GRB.Status.OPTIMAL) {
        Console.WriteLine("The optimal objective is " +
            model.Get(GRB.DoubleAttr.ObjVal));
        return;
          }
          if ((status != GRB.Status.INF_OR_UNBD) &&
          (status != GRB.Status.INFEASIBLE)) {
        Console.WriteLine("Optimization was stopped with status " + status);
        return;
          }

          // Do IIS
          Console.WriteLine("The model is infeasible; computing IIS");
          LinkedList<string> removed = new LinkedList<string>();

          // Loop until we reduce to a model that can be solved
          while (true) {
        model.ComputeIIS();
        Console.WriteLine("\nThe following constraint cannot be satisfied:");
        foreach (GRBConstr c in model.GetConstrs()) {
          if (c.Get(GRB.IntAttr.IISConstr) == 1) {
            Console.WriteLine(c.Get(GRB.StringAttr.ConstrName));
            // Remove a single constraint from the model
            removed.AddFirst(c.Get(GRB.StringAttr.ConstrName));
            model.Remove(c);
            break;
          }
        }

        Console.WriteLine();
        model.Optimize();
        status = model.Get(GRB.IntAttr.Status);

        if (status == GRB.Status.UNBOUNDED) {
          Console.WriteLine("The model cannot be solved "
              + "because it is unbounded");
          return;
        }
        if (status == GRB.Status.OPTIMAL) {
          break;
        }
        if ((status != GRB.Status.INF_OR_UNBD) &&
            (status != GRB.Status.INFEASIBLE)) {
          Console.WriteLine("Optimization was stopped with status " +
              status);
          return;
        }
          }

          Console.WriteLine("\nThe following constraints were removed "
          + "to get a feasible LP:");
          foreach (string s in removed) {
        Console.Write(s + " ");
          }
          Console.WriteLine();

          // Dispose of model and env
          model.Dispose();
          env.Dispose();

        } catch (GRBException e) {
          Console.WriteLine("Error code: " + e.ErrorCode + ". " +
          e.Message);
        }
    }
コード例 #19
0
ファイル: GurobiSolver.cs プロジェクト: abaffa/FCTPChallenge
        public Dictionary <EdgePair, Double> Solve(FCTPGraph ti)
        {
            Dictionary <EdgePair, Double> edgeFlows = new Dictionary <EdgePair, Double>();
            Dictionary <String, Edge>     edgeMap   = new Dictionary <String, Edge>();
            Dictionary <String, GRBVar>   varMap    = new Dictionary <String, GRBVar>();
            String currentVar = "";

            try {
                //Model
                GRBEnv env = new GRBEnv();
                env.Set(GRB.IntParam.LogToConsole, 0);
                GRBModel model = new GRBModel(env);
                model.Set(GRB.StringAttr.ModelName, "tranportation");


                //edges
                foreach (Edge e in ti.Edges)
                {
                    String xij = edgeVarName(e.Source, e.Sink);
                    edgeMap.Add(xij, e);
                    GRBVar var = model.AddVar(0, GRB.INFINITY, e.C, GRB.CONTINUOUS, xij);
                    varMap.Add(xij, var);
                }
                //objective min Sum cij xij
                model.Set(GRB.IntAttr.ModelSense, GRB.MINIMIZE);

                //integrate variables
                model.Update();

                //supply constraints
                foreach (Node source in ti.Sources)
                {
                    GRBLinExpr sourceConstraint = new GRBLinExpr();
                    foreach (Node sink in ti.Sinks)
                    {
                        String name = edgeVarName(source.Id, sink.Id);
                        sourceConstraint.AddTerm(1, varMap[name]);
                    }
                    model.AddConstr(sourceConstraint, GRB.EQUAL, source.Amount, "");
                }
                //demand constraints
                foreach (Node sink in ti.Sinks)
                {
                    GRBLinExpr sinkConstraint = new GRBLinExpr();
                    foreach (Node source in ti.Sources)
                    {
                        String name = edgeVarName(source.Id, sink.Id);
                        sinkConstraint.AddTerm(1, varMap[name]);
                    }
                    model.AddConstr(sinkConstraint, GRB.EQUAL, sink.Amount, "");
                }
                //update constraints
                model.Update();

                model.Write("mipTranportationGurobi.lp");
                env.Set(GRB.IntParam.Threads, 1);
                model.Optimize();

                bool status = model.Get(GRB.IntAttr.Status) == GRB.Status.OPTIMAL;
                Console.WriteLine("Status: " + status);
                foreach (String s in edgeMap.Keys)
                {
                    currentVar = s;
                    double   flow = varMap[s].Get(GRB.DoubleAttr.X);
                    Edge     e    = edgeMap[s];
                    EdgePair ep   = new EdgePair(e.Source, e.Sink);
                    edgeFlows.Add(ep, flow);
                }
                model.Dispose();
            } catch (GRBException e) {
                Console.Out.WriteLine(currentVar + " - is current var");
                Console.Out.WriteLine(e.ErrorCode);
                Console.Out.WriteLine(e.ToString());
            }

            return(edgeFlows);
        }
コード例 #20
0
ファイル: diet_cs.cs プロジェクト: nachonase/docker-files
    static void Main()
    {
        try {
            // Nutrition guidelines, based on
            // USDA Dietary Guidelines for Americans, 2005
            // http://www.health.gov/DietaryGuidelines/dga2005/
            string[] Categories =
                new string[] { "calories", "protein", "fat", "sodium" };
            int      nCategories  = Categories.Length;
            double[] minNutrition = new double[] { 1800, 91, 0, 0 };
            double[] maxNutrition = new double[] { 2200, GRB.INFINITY, 65, 1779 };

            // Set of foods
            string[] Foods =
                new string[] { "hamburger", "chicken", "hot dog", "fries",
                               "macaroni", "pizza", "salad", "milk", "ice cream" };
            int      nFoods = Foods.Length;
            double[] cost   =
                new double[] { 2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89,
                               1.59 };

            // Nutrition values for the foods
            double[,] nutritionValues = new double[, ] {
                { 410, 24, 26, 730 },  // hamburger
                { 420, 32, 10, 1190 }, // chicken
                { 560, 20, 32, 1800 }, // hot dog
                { 380, 4, 19, 270 },   // fries
                { 320, 12, 10, 930 },  // macaroni
                { 320, 15, 12, 820 },  // pizza
                { 320, 31, 12, 1230 }, // salad
                { 100, 8, 2.5, 125 },  // milk
                { 330, 8, 10, 180 } // ice cream
            };

            // Model
            GRBEnv   env   = new GRBEnv();
            GRBModel model = new GRBModel(env);
            model.Set(GRB.StringAttr.ModelName, "diet");

            // Create decision variables for the nutrition information,
            // which we limit via bounds
            GRBVar[] nutrition = new GRBVar[nCategories];
            for (int i = 0; i < nCategories; ++i)
            {
                nutrition[i] =
                    model.AddVar(minNutrition[i], maxNutrition[i], 0, GRB.CONTINUOUS,
                                 Categories[i]);
            }

            // Create decision variables for the foods to buy
            GRBVar[] buy = new GRBVar[nFoods];
            for (int j = 0; j < nFoods; ++j)
            {
                buy[j] =
                    model.AddVar(0, GRB.INFINITY, cost[j], GRB.CONTINUOUS, Foods[j]);
            }

            // The objective is to minimize the costs
            model.Set(GRB.IntAttr.ModelSense, 1);

            // Update model to integrate new variables
            model.Update();

            // Nutrition constraints
            for (int i = 0; i < nCategories; ++i)
            {
                GRBLinExpr ntot = 0.0;
                for (int j = 0; j < nFoods; ++j)
                {
                    ntot.AddTerm(nutritionValues[j, i], buy[j]);
                }
                model.AddConstr(ntot == nutrition[i], Categories[i]);
            }

            // Solve
            model.Optimize();
            PrintSolution(model, buy, nutrition);

            Console.WriteLine("\nAdding constraint: at most 6 servings of dairy");
            model.AddConstr(buy[7] + buy[8] <= 6.0, "limit_dairy");

            // Solve
            model.Optimize();
            PrintSolution(model, buy, nutrition);

            // Dispose of model and env
            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: " + e.ErrorCode + ". " +
                              e.Message);
        }
    }
コード例 #21
0
ファイル: facility_cs.cs プロジェクト: nachonase/docker-files
    static void Main()
    {
        try {
            // Warehouse demand in thousands of units
            double[] Demand = new double[] { 15, 18, 14, 20 };

            // Plant capacity in thousands of units
            double[] Capacity = new double[] { 20, 22, 17, 19, 18 };

            // Fixed costs for each plant
            double[] FixedCosts =
                new double[] { 12000, 15000, 17000, 13000, 16000 };

            // Transportation costs per thousand units
            double[,] TransCosts =
                new double[, ] {
                { 4000, 2000, 3000, 2500, 4500 },
                { 2500, 2600, 3400, 3000, 4000 },
                { 1200, 1800, 2600, 4100, 3000 },
                { 2200, 2600, 3100, 3700, 3200 }
            };

            // Number of plants and warehouses
            int nPlants     = Capacity.Length;
            int nWarehouses = Demand.Length;

            // Model
            GRBEnv   env   = new GRBEnv();
            GRBModel model = new GRBModel(env);
            model.Set(GRB.StringAttr.ModelName, "facility");

            // Plant open decision variables: open[p] == 1 if plant p is open.
            GRBVar[] open = new GRBVar[nPlants];
            for (int p = 0; p < nPlants; ++p)
            {
                open[p] = model.AddVar(0, 1, FixedCosts[p], GRB.BINARY, "Open" + p);
            }

            // Transportation decision variables: how much to transport from
            // a plant p to a warehouse w
            GRBVar[,] transport = new GRBVar[nWarehouses, nPlants];
            for (int w = 0; w < nWarehouses; ++w)
            {
                for (int p = 0; p < nPlants; ++p)
                {
                    transport[w, p] =
                        model.AddVar(0, GRB.INFINITY, TransCosts[w, p], GRB.CONTINUOUS,
                                     "Trans" + p + "." + w);
                }
            }

            // The objective is to minimize the total fixed and variable costs
            model.Set(GRB.IntAttr.ModelSense, 1);

            // Update model to integrate new variables
            model.Update();

            // Production constraints
            // Note that the right-hand limit sets the production to zero if
            // the plant is closed
            for (int p = 0; p < nPlants; ++p)
            {
                GRBLinExpr ptot = 0.0;
                for (int w = 0; w < nWarehouses; ++w)
                {
                    ptot.AddTerm(1.0, transport[w, p]);
                }
                model.AddConstr(ptot <= Capacity[p] * open[p], "Capacity" + p);
            }

            // Demand constraints
            for (int w = 0; w < nWarehouses; ++w)
            {
                GRBLinExpr dtot = 0.0;
                for (int p = 0; p < nPlants; ++p)
                {
                    dtot.AddTerm(1.0, transport[w, p]);
                }
                model.AddConstr(dtot == Demand[w], "Demand" + w);
            }

            // Guess at the starting point: close the plant with the highest
            // fixed costs; open all others

            // First, open all plants
            for (int p = 0; p < nPlants; ++p)
            {
                open[p].Set(GRB.DoubleAttr.Start, 1.0);
            }

            // Now close the plant with the highest fixed cost
            Console.WriteLine("Initial guess:");
            double maxFixed = -GRB.INFINITY;
            for (int p = 0; p < nPlants; ++p)
            {
                if (FixedCosts[p] > maxFixed)
                {
                    maxFixed = FixedCosts[p];
                }
            }
            for (int p = 0; p < nPlants; ++p)
            {
                if (FixedCosts[p] == maxFixed)
                {
                    open[p].Set(GRB.DoubleAttr.Start, 0.0);
                    Console.WriteLine("Closing plant " + p + "\n");
                    break;
                }
            }

            // Use barrier to solve root relaxation
            model.GetEnv().Set(GRB.IntParam.Method, GRB.METHOD_BARRIER);

            // Solve
            model.Optimize();

            // Print solution
            Console.WriteLine("\nTOTAL COSTS: " + model.Get(GRB.DoubleAttr.ObjVal));
            Console.WriteLine("SOLUTION:");
            for (int p = 0; p < nPlants; ++p)
            {
                if (open[p].Get(GRB.DoubleAttr.X) == 1.0)
                {
                    Console.WriteLine("Plant " + p + " open:");
                    for (int w = 0; w < nWarehouses; ++w)
                    {
                        if (transport[w, p].Get(GRB.DoubleAttr.X) > 0.0001)
                        {
                            Console.WriteLine("  Transport " +
                                              transport[w, p].Get(GRB.DoubleAttr.X) +
                                              " units to warehouse " + w);
                        }
                    }
                }
                else
                {
                    Console.WriteLine("Plant " + p + " closed!");
                }
            }

            // Dispose of model and env
            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
        }
    }
コード例 #22
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();
        }
コード例 #23
0
 private void SetupGurobiEnvironmentAndModel()
 {
     // Model
     env = new GRBEnv();
     model = new GRBModel(env);
     model.Set(GRB.StringAttr.ModelName, "diet");
 }
コード例 #24
0
ファイル: facility_cs.cs プロジェクト: revisalo/cr2
    static void Main()
    {
        try {

          // Warehouse demand in thousands of units
          double[] Demand = new double[] { 15, 18, 14, 20 };

          // Plant capacity in thousands of units
          double[] Capacity = new double[] { 20, 22, 17, 19, 18 };

          // Fixed costs for each plant
          double[] FixedCosts =
          new double[] { 12000, 15000, 17000, 13000, 16000 };

          // Transportation costs per thousand units
          double[,] TransCosts =
          new double[,] { { 4000, 2000, 3000, 2500, 4500 },
              { 2500, 2600, 3400, 3000, 4000 },
              { 1200, 1800, 2600, 4100, 3000 },
              { 2200, 2600, 3100, 3700, 3200 } };

          // Number of plants and warehouses
          int nPlants = Capacity.Length;
          int nWarehouses = Demand.Length;

          // Model
          GRBEnv env = new GRBEnv();
          GRBModel model = new GRBModel(env);
          model.Set(GRB.StringAttr.ModelName, "facility");

          // Plant open decision variables: open[p] == 1 if plant p is open.
          GRBVar[] open = new GRBVar[nPlants];
          for (int p = 0; p < nPlants; ++p) {
        open[p] = model.AddVar(0, 1, FixedCosts[p], GRB.BINARY, "Open" + p);
          }

          // Transportation decision variables: how much to transport from
          // a plant p to a warehouse w
          GRBVar[,] transport = new GRBVar[nWarehouses,nPlants];
          for (int w = 0; w < nWarehouses; ++w) {
        for (int p = 0; p < nPlants; ++p) {
          transport[w,p] =
              model.AddVar(0, GRB.INFINITY, TransCosts[w,p], GRB.CONTINUOUS,
                           "Trans" + p + "." + w);
        }
          }

          // The objective is to minimize the total fixed and variable costs
          model.Set(GRB.IntAttr.ModelSense, 1);

          // Update model to integrate new variables
          model.Update();

          // Production constraints
          // Note that the right-hand limit sets the production to zero if
          // the plant is closed
          for (int p = 0; p < nPlants; ++p) {
        GRBLinExpr ptot = 0.0;
        for (int w = 0; w < nWarehouses; ++w)
          ptot += transport[w,p];
        model.AddConstr(ptot <= Capacity[p] * open[p], "Capacity" + p);
          }

          // Demand constraints
          for (int w = 0; w < nWarehouses; ++w) {
        GRBLinExpr dtot = 0.0;
        for (int p = 0; p < nPlants; ++p)
          dtot += transport[w,p];
        model.AddConstr(dtot == Demand[w], "Demand" + w);
          }

          // Guess at the starting point: close the plant with the highest
          // fixed costs; open all others

          // First, open all plants
          for (int p = 0; p < nPlants; ++p) {
        open[p].Set(GRB.DoubleAttr.Start, 1.0);
          }

          // Now close the plant with the highest fixed cost
          Console.WriteLine("Initial guess:");
          double maxFixed = -GRB.INFINITY;
          for (int p = 0; p < nPlants; ++p) {
        if (FixedCosts[p] > maxFixed) {
          maxFixed = FixedCosts[p];
        }
          }
          for (int p = 0; p < nPlants; ++p) {
        if (FixedCosts[p] == maxFixed) {
          open[p].Set(GRB.DoubleAttr.Start, 0.0);
          Console.WriteLine("Closing plant " + p + "\n");
          break;
        }
          }

          // Use barrier to solve root relaxation
          model.GetEnv().Set(GRB.IntParam.Method, GRB.METHOD_BARRIER);

          // Solve
          model.Optimize();

          // Print solution
          Console.WriteLine("\nTOTAL COSTS: " + model.Get(GRB.DoubleAttr.ObjVal));
          Console.WriteLine("SOLUTION:");
          for (int p = 0; p < nPlants; ++p) {
        if (open[p].Get(GRB.DoubleAttr.X) == 1.0) {
          Console.WriteLine("Plant " + p + " open:");
          for (int w = 0; w < nWarehouses; ++w) {
            if (transport[w,p].Get(GRB.DoubleAttr.X) > 0.0001) {
              Console.WriteLine("  Transport " +
                  transport[w,p].Get(GRB.DoubleAttr.X) +
                  " units to warehouse " + w);
            }
          }
        } else {
          Console.WriteLine("Plant " + p + " closed!");
        }
          }

          // Dispose of model and env
          model.Dispose();
          env.Dispose();

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