Example #1
0
        private void BreakHandling(GRBModel model, int numberOfRoutes, GRBVar[][] v)
        {
            for (int i = 1; i < visitDurations.Length; i++)
            {
                if (!input.Visits[i - 1].IsBreak)
                {
                    continue;
                }

                var visit       = input.Visits[i - 1];
                var breakRoutes = new List <int>();
                for (var day = 0; day < input.Days.Length; day++)
                {
                    var s = visit.SantaId + day * input.Santas.Length;
                    model.AddGenConstrOr(v[s][i], v[s].Take(i - 1).Skip(1).ToArray(), null); // assignment if used
                    breakRoutes.Add(s);
                }

                // break cannot be visited by another santa
                foreach (var nonBreakRoute in Enumerable.Range(0, numberOfRoutes).Except(breakRoutes))
                {
                    model.AddConstr(v[nonBreakRoute][i] == 0, null);
                }
            }
        }
        //linearize a condition f. For example, f=k1+k2*k3+k4, it would return f=u1+u2+u3, where u1=k1, u2=k2*k3, u3=k4
        //Furthermore, this function could identify if f has a constant term. If so, it would mark out that f has a constant term in the array consflag.
        static public List <GRBVar> LinearConstrain(GRBModel m, GRBVar[] Uvar, GRBVar[] UFvar, UInt32[, ,] ConS, int[] conlen, int ind, GRBVar[] keyvar, GRBVar[] ivvar, int[] loc1, GRBVar[] kvf, GRBVar[] vvf, GRBVar[] Wvar, int[] locw, List <GRBVar> LinFlagRes)
        {
            List <GRBVar> LinVar = new List <GRBVar>()
            {
            };
            List <GRBVar> LinVarFlag = new List <GRBVar>()
            {
            };
            List <GRBVar> TempVarFlag = new List <GRBVar>()
            {
            };                                                //store the flag variables of the variables appearing in a monimial
            List <GRBVar> TempVar = new List <GRBVar>()
            {
            };                                            //store the assignment variables of the variables appearing in a monimial
            int weight = 0;
            int i, j, k;
            int t;
            int loc   = 0;
            int locf  = 0;
            int loc_w = locw[0];

            loc  = loc1[0];
            locf = loc1[1];
            for (j = 0; j < conlen[ind]; j++)
            {
                //for the j-th monomial
                //Cons[ind,j,0-2]stores the iv variable appearing in the monimial
                //Cons[ind,j,3-5]stores the key variable appearing in the monimial
                weight = 0;
                TempVar.Clear();
                TempVarFlag.Clear();
                for (i = 0; i < 96; i++)
                {
                    t      = (int)((ConS[ind, j, (i >> 5)] >> (i & 0x1f)) & 0x01);
                    weight = weight + t;
                    if (t == 1)
                    {
                        TempVar.Add(ivvar[i]);
                        TempVarFlag.Add(vvf[i]);
                    }
                }
                for (i = 0; i < 96; i++)
                {
                    t      = (int)((ConS[ind, j, (i >> 5) + 3] >> (i & 0x1f)) & 0x01);
                    weight = weight + t;
                    if (t == 1)
                    {
                        TempVar.Add(keyvar[i]);
                        TempVarFlag.Add(kvf[i]);
                    }
                }
                //if weight ==1, it is a monomial of degree one, then we only replace it with a new variable
                if (weight == 1)
                {
                    m.AddConstr(Uvar[loc] == TempVar[0], "SingleBit" + loc.ToString());
                    m.AddConstr(UFvar[locf] == TempVarFlag[0], "SingleBit" + loc.ToString());
                    LinVar.Add(Uvar[loc]);
                    LinFlagRes.Add(UFvar[locf]);
                    loc++;
                    locf++;
                }
                //if weight>1, then it is a nonlinear monomial and we should linearize it accroding to the rule of AND in our paper.
                if (weight > 1)
                {
                    GRBVar[] PickVars = new GRBVar[TempVar.Count];
                    for (i = 0; i < TempVar.Count; i++)
                    {
                        PickVars[i] = TempVar[i];

                        //Wvar[loc_w+i]= TempVar[i]^TempVarFlag[i]
                        GRBVar[] tempor = new GRBVar[2] {
                            TempVar[i], TempVarFlag[i]
                        };
                        m.AddGenConstrOr(Wvar[loc_w + i], tempor, "tempor" + i.ToString());//变元与变元的标志相或
                    }
                    GRBVar[] tempm = new GRBVar[TempVar.Count];


                    //Wvar[loc_w+l]=min(Wvar[loc_w],Wvar[loc_w+1],...,Wvar[loc_w+l-1]), where l is the number variables appearing in the monomial
                    for (i = 0; i < TempVar.Count; i++)
                    {
                        tempm[i] = Wvar[loc_w + i];
                    }
                    loc_w = loc_w + TempVar.Count;
                    m.AddGenConstrMin(Wvar[loc_w], tempm, 1, "linmin" + loc_w.ToString());
                    loc_w++;


                    for (i = 0; i < TempVar.Count; i++)
                    {
                        tempm[i] = TempVarFlag[i];
                    }
                    //Wvar[loc_w]=max(TempVarFlag[0],TempVarFlag[1],...,TempVarFlag[l-1]), where l is the number variables appearing in the monomial
                    m.AddGenConstrMax(Wvar[loc_w], tempm, 0, "linmaxFlag" + loc_w.ToString());
                    loc_w++;


                    GRBVar[] tempminFlag = new GRBVar[2] {
                        Wvar[loc_w - 1], Wvar[loc_w - 2]
                    };
                    //UFvar[loc] is the final flag variable of the monomial
                    m.AddGenConstrMin(UFvar[locf], tempminFlag, 1, "minFlag" + loc.ToString());
                    //Uvar[loc] is the final assignment variable of the monomial
                    m.AddGenConstrMin(Uvar[loc], PickVars, 0, "Linearity" + loc.ToString());
                    LinVar.Add(Uvar[loc]);
                    LinFlagRes.Add(UFvar[locf]);
                    loc++;
                    locf++;
                }
            }
            loc1[0] = loc;
            loc1[1] = locf;
            locw[0] = loc_w;
            return(LinVar);
        }
    static void Main()
    {
        try {
            // Example data:
            //   e.g. {0, n+1, 2} means clause (x0 or ~x1 or x2)
            int[,] Clauses = new int[, ]
            {
                { 0, n + 1, 2 }, { 1, n + 2, 3 },
                { 2, n + 3, 0 }, { 3, n + 0, 1 },
                { n + 0, n + 1, 2 }, { n + 1, n + 2, 3 },
                { n + 2, n + 3, 0 }, { n + 3, n + 0, 1 }
            };

            int i, status;

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

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

            // Initialize decision variables and objective

            GRBVar[] Lit    = new GRBVar[NLITERALS];
            GRBVar[] NotLit = new GRBVar[NLITERALS];
            for (i = 0; i < NLITERALS; i++)
            {
                Lit[i]    = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, string.Format("X{0}", i));
                NotLit[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, string.Format("notX{0}", i));
            }

            GRBVar[] Cla = new GRBVar[NCLAUSES];
            for (i = 0; i < NCLAUSES; i++)
            {
                Cla[i] = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, string.Format("Clause{0}", i));
            }

            GRBVar[] Obj = new GRBVar[NOBJ];
            for (i = 0; i < NOBJ; i++)
            {
                Obj[i] = model.AddVar(0.0, 1.0, 1.0, GRB.BINARY, string.Format("Obj{0}", i));
            }

            // Link Xi and notXi
            GRBLinExpr lhs;
            for (i = 0; i < NLITERALS; i++)
            {
                lhs = new GRBLinExpr();
                lhs.AddTerm(1.0, Lit[i]);
                lhs.AddTerm(1.0, NotLit[i]);
                model.AddConstr(lhs, GRB.EQUAL, 1.0, string.Format("CNSTR_X{0}", i));
            }

            // Link clauses and literals
            for (i = 0; i < NCLAUSES; i++)
            {
                GRBVar[] clause = new GRBVar[3];
                for (int j = 0; j < 3; j++)
                {
                    if (Clauses[i, j] >= n)
                    {
                        clause[j] = NotLit[Clauses[i, j] - n];
                    }
                    else
                    {
                        clause[j] = Lit[Clauses[i, j]];
                    }
                }
                model.AddGenConstrOr(Cla[i], clause, string.Format("CNSTR_Clause{0}", i));
            }

            // Link objs with clauses
            model.AddGenConstrMin(Obj[0], Cla, GRB.INFINITY, "CNSTR_Obj0");
            lhs = new GRBLinExpr();
            for (i = 0; i < NCLAUSES; i++)
            {
                lhs.AddTerm(1.0, Cla[i]);
            }
            model.AddGenConstrIndicator(Obj[1], 1, lhs, GRB.GREATER_EQUAL, 4.0, "CNSTR_Obj1");

            // Set global objective sense
            model.ModelSense = GRB.MAXIMIZE;

            // Save problem
            model.Write("genconstr_cs.mps");
            model.Write("genconstr_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 result
            double objval = model.ObjVal;

            if (objval > 1.9)
            {
                Console.WriteLine("Logical expression is satisfiable");
            }
            else if (objval > 0.9)
            {
                Console.WriteLine("At least four clauses can be satisfied");
            }
            else
            {
                Console.WriteLine("Not even three clauses can be satisfied");
            }

            // Dispose of model and environment
            model.Dispose();
            env.Dispose();
        } catch (GRBException e) {
            Console.WriteLine("Error code: {0}. {1}", e.ErrorCode, e.Message);
        }
    }