Java-Gurobi学习笔记(三)

最近碰到了一个有趣的问题,类似于着色问题。

有24个格子可以给我们填色,我们填色的种类有三种,分别为:黄色、蓝色、红色,每种颜色的每次填色时占用的格子数目不一样,分别为,黄色占1格,蓝色占2格,红色占4格。

除此之外,我们还有限制条件是:(1)每种颜色不可以连续着色,如要连续着色,必须在两次着色中间空一格空白格子。(2)每种着色必须至少着色一次,最多着色6次。(3)所有着色所有占据的格子不能超过24这个上限。

我们求解的目标是:着色的总次数最大是多少呢?

我们把问题抽象为一个MIP模型。建立一下模型

我们设置72个变量,就是Xij,当X11为1时表示第一个格子的被第一种资源所占用,但是这样设计有个缺陷,无法通过求解的Xij去准确知到第几个格子如何着色。这部分是以后要改善的问题。

(1.1)代表优化目标,所有的Xij的相加值最大,代表累积的着色次数最大

从(1.2)开始都是限制条件。

(1.2)代表每个格子只能被一种类型着色

(1.3)代表相邻之间着色的类型不可以一样

(1.4)代表所有着色类型所占的格子总数不可以超过24

(1.5)——(1.7)代表每种着色业务数量至少为1,不超过6

(1.8)代表i,j都是整数,且Xij只能取0或1

Java代码如下(比较粗糙,基本功能可以完成):

public optimal() {
        try {
            GRBEnv grbEnv = new GRBEnv("coloring");
            grbModel =new GRBModel(grbEnv);

            grbVars = new ArrayList<>();

            for (int i = 0; i < 24; i++) {
                for (int j = 0; j < 3; j++) {

                    x[i][j]  = grbModel.addVar(0,1,0,GRB.BINARY,"x_"+(i+1)+"_"+(j+1));
                    grbVars.add(x[i][j]);
                    x_total[i*3 + j] = x[i][j];
                }

            }


            /*constr1*/
            for (int i = 0; i < 24; i++) {
                GRBLinExpr expr1 = new GRBLinExpr();
                expr1.addTerms(new double[]{1,1,1},x[i]);
                grbModel.addConstr(expr1,LESS_EQUAL,1,"expr1"+i);
            }

            /*constr2*/
            for (int i = 0; i < 23; i++) {
                for (int j = 0; j < 3 ; j++) {
                    GRBLinExpr expr2 = new GRBLinExpr();
                    GRBVar[] grbVars1 = {x[i][j],x[i+1][j]};
                    expr2.addTerms(new double[]{1,1},grbVars1);
                    grbModel.addConstr(expr2,LESS_EQUAL,1,"expr2_"+i+j);
                }
            }

            /*constr3*/
            GRBLinExpr expr3 = new GRBLinExpr();
            double[] expr3_coffe = new double[72];
            for (int i = 0; i < 24; i++) {
                expr3_coffe[i*3 + 0] = 1;
                expr3_coffe[i*3 + 1] = 2;
                expr3_coffe[i*3 + 2] = 4;
            }
            expr3.addTerms(expr3_coffe,x_total);
            grbModel.addConstr(expr3,LESS_EQUAL,24,"expr3");


            /*constr4*/
            double[] expr4_coffe = new double[24];
            for (int i = 0; i < 24; i++) {
                expr4_coffe[i] = 1;
            }
            GRBVar[][] grbVars_main = new GRBVar[3][24];
            GRBVar[] grbVars1 = new GRBVar[24];
            GRBVar[] grbVars2 = new GRBVar[24];
            GRBVar[] grbVars4 = new GRBVar[24];
            for (int i = 0; i < 24; i++) {
                grbVars1[i] = x[i][0];
                grbVars2[i] = x[i][1];
                grbVars4[i] = x[i][2];
            }
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 24; j++) {
                    if(i == 0){
                        grbVars_main[i][j] = grbVars1[j];
                    } else if (i == 1) {
                        grbVars_main[i][j] = grbVars2[j];
                    }else {
                        grbVars_main[i][j] = grbVars4[j];
                    }

                }
            }
            for (int i = 0; i < 3; i++) {
                GRBLinExpr expr4 = new GRBLinExpr();
                expr4.addTerms(expr4_coffe,grbVars_main[i]);
                if(i == 0){
                    grbModel.addConstr(0,LESS_EQUAL,expr4,"expr4_"+i+"_"+1);
                    grbModel.addConstr(expr4,LESS_EQUAL,5,"expr4_"+i+"_"+2);
                }else if(i == 1){
                    grbModel.addConstr(0,LESS_EQUAL,expr4,"expr4_"+i+"_"+1);
                    grbModel.addConstr(expr4,LESS_EQUAL,3,"expr4_"+i+"_"+2);
                }else {
                    grbModel.addConstr(0,LESS_EQUAL,expr4,"expr4_"+i+"_"+1);
                    grbModel.addConstr(expr4,LESS_EQUAL,3,"expr4_"+i+"_"+2);
                }


            }




            /*target*/
            double[] target_coffe = new double[72];
            for (int i = 0; i < 72; i++) {
                target_coffe[i] = 1;

            }
            GRBLinExpr target = new GRBLinExpr();
            target.addTerms(target_coffe,x_total);

            grbModel.setObjective(target,GRB.MAXIMIZE);

            grbModel.optimize();

            int type1_count = 0;
            int type2_count = 0;
            int type3_count = 0;
            int seq_ini[] = new int[72];
            int seq_final[] = new int[(int) grbModel.get(GRB.DoubleAttr.ObjVal)];
            for (int i = 0; i < x_total.length; i++) {
                if(x_total[i].get(GRB.DoubleAttr.X) == 1){
                    if(i % 3 == 0){
                        type1_count++;
                        seq_ini[i] = 1;
                    } else if (i % 3 == 1) {
                        type2_count++;
                        seq_ini[i] = 2;
                    }else {
                        type3_count++;
                        seq_ini[i] = 4;
                    }
                }
            }
            int temp = 0;
            for (int i = 0; i < seq_ini.length; i++) {
                if(seq_ini[i] != 0){
                    seq_final[temp] = seq_ini[i];
                    temp++;
                }
            }


            //输出结果
            System.out.println("最优解为:" + grbModel.get(GRB.DoubleAttr.ObjVal));
            System.out.println("Type1的数量为:"+type1_count );
            System.out.println("Type2的数量为:"+type2_count );
            System.out.println("Type3的数量为:"+type3_count );
            System.out.println("业务的顺序为:"+ Arrays.toString(seq_final));
            for (int i = 0; i < x_total.length; i++) {
                System.out.println(x_total[i].get(GRB.StringAttr.VarName) + "=" +         
                       x_total[i].get(GRB.DoubleAttr.X));


            }
            

            //处理模型和环境
            grbModel.dispose();
            grbEnv.dispose();

        }catch (Exception e){
            e.printStackTrace();
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

super_Novaa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值