补充3 需求分配和工厂选址模型(工厂和仓库同时选址)——基于java和cplex的实现

本文详细阐述了供应链网络设计中的关键步骤,包括识别潜在地点、需求分配模型、生产设施选址模型和有产能约束的更复杂模型。通过线性和整数规划解决选址和分配问题,使用Java和CPLEX工具进行建模与求解,以最小化成本或最大化利润为目标。案例涉及工厂、仓库的产能和运输成本,以及市场需求满足等实际因素。
摘要由CSDN通过智能技术生成

这一部分是第二部分的供应链网络的设计(二)供应链的网络设计第六部分在区域内识别潜在地点的模型。

目录

一、所需输入

 二、将需求分配给现有生产设施的需求分配模型

三、生产设施选址模型

四、更复杂的、有能力约束的生产设施选址模型

1.单一供货源、有能力约束的工厂选址模型

 2.工厂和仓库同时选址

(1)理论模型

  (2)基于java和cplex的案例


        在确定了潜在设施地点后,管理者就要决定具体的设施选址并进行产能分配。除了设施选址,管理者还要决定如何将每个市场的需求分配给各个设施。进行产能分配时必须考虑到响应时间方面的顾客服务约束。随着成本和市场的变化,需求分配决策可定期进行调整。在网络设计时,通常选址决策和分配决策时同时进行的。

一、所需输入

        在这一阶段,管理者需要了解以下信息:每个市场的需求、期望的响应时间、建立一个设施的固定成本、劳动力和物料的可变成本、库存持有成本、各潜在地点和市场间的运输成本、产品销售价格、税收和关税、潜在设施产能。根据以上各中成本以及税收和关税数据,就可以了解在每个地点建立设施的年固定成本,以及每个潜在地点为每个市场提供一单位供给的可变成本。

        下面以两个电脑设备制造商MoonLight公司和SunShine公司为例来说明相关的网络优化模型。MoonLight公司专注于美国东部的市场,SunShine公司专注于美国西部的市场。

        每个工厂的产能、市场需求、运送没钱单位产品的可变成本和运输成本,以及每个工厂的年固定成本如下表所示。        

 二、将需求分配给现有生产设施的需求分配模型

        管理者利用该模型将需求在现有生产设施间进行分配。虽然生产设施的地点和产能变化很少,但随着需求和成本的变化,分配给每个设施的需求可以更频繁地改变。需求分配模型需要以下输入:        

         该模型假设所有工厂都是运行的,所以不管实际产量如何,固定成本都会发生。目标是将来自不同市场的需求分配给不同的工厂以使设施、运输和库存的总成本变小。决策变量定义如下:

        需求分配问题可以表述为以下线性规划问题:

        约束条件为:

         

         第一个约束条件是为确保所有的市场需求得到满足;第二个约束条件是为确保工厂产量不超过其产能。

        这里的求解方法可参考补充1的内容,过程和结果在这里就省略了。

三、生产设施选址模型

        管理者可利用这个模型进行新生产设施的选址,或者决定哪些生产设施应该关闭或继续开工。最有选址和产能分配问题与前面讨论的区域配置问题非常类似。唯一的区别在于这里使用的不是一个区域所发生的成本和关税,而是具体地点的成本和关税。

        算法实现过程简单,参见补充一。

四、更复杂的、有能力约束的生产设施选址模型

        现在介绍更复杂的有能力约束的生产设施选址模型。第一个模型主要用于一个市场仅由一个工厂来供货的情况。第二个模型解决的问题可概括为,在供应链中工厂和市场之间增加了一个仓库环节,所有工厂和仓库的选址都应使生产和配送的总成本最小。

1.单一供货源、有能力约束的工厂选址模型

        在某些情况下,企业希望将供应链网络设计成一个市场仅由一个工厂供货,这称为单一供货源(single source)。企业之所以会强行假如这个约束,是因为它能降低网络协调的复杂度,而且对每个设施的柔性要求较低。针对这一约束条件,需要对前面讨论的工厂选址模型进行一些调整。决策变量重新定义如下:

        那么,该决策问题可以表述为以下整数规划问题:

         

         约束条件为:

        

        第一个和第二个约束条件强制规定每个市场都是由一个工厂来供货。

         这里的求解过程和前面一样,具体求解方法请参考1。

 2.工厂和仓库同时选址

(1)理论模型

        如果要设计的是从供应商到顾客的整个供应链网络,则要考虑一种更为普遍的工厂选址模型。让我们考虑这样一种供应链,其中供应商为工厂供应原材料,工厂想仓库供货,仓库在供货给市场。所有工厂及仓库的选址和产能分配决策必须同时确定。可以用多个仓库来满足一个市场的需求,也可以用多个工厂来对仓库进行补货。同时假设已经对计量单位进行了适当的调整,是的供应源提供的一个单位输入可以生产一个单位的产成品。该模型要求已知以下变量:        

         该模型的目标是找到可以使固定成本和可变成本之和最小的工厂和仓库的选址以及各点之间的运输量。决策变量定义如下:

         该决策问题可以表述为以下整数规划问题:

   

        该目标函数是使服从以下约束条件的供应链网络的固定成本和可变成本之和最小:

        上式的约束条件规定一个供应商运出的总量不能超过该供应商的产能。

 

        上式的约束条件规定从一个工厂运出的数量不能超出其所接受的原材料数量。

         

         上式的约束条件规定工厂所生产的数量不能超出其产能。

        上式的约束条件规定从一个仓库的运出的数量不能超出启聪工厂所接受到的数量。

 

        上式的约束条件规定从一个仓库运出的数量不能超过其产能。

        上式的约束条件规定运送给一个顾客的数量必须满足其需求。

         

        上式的约束条件规定每个工厂或仓库要么开工,要么关闭。

 (2)基于java和cplex的案例

        数据是瞎编的,代码思路大概如下,可能某个细节出错导致模型不可解,用的时候检查一下代码,也可在评论区指出错误。

public class ComplexData {
    //市场j的年需求
    double[] demands = {10,8,14,6,7,11};
    //工厂的潜在产能
    double[] productivity = {5,8,13,10,9};
    //供应商的供应能力
    double[] supplyCapacity = {20,20,20};
    //潜在仓库的产能
    double[] storeCapacity = {8,10,15,20,21,20};
    //工厂的固定成本
    double[] factoryFixedCost = {7650,3500,5000,4100,2200};
    //仓库的固定成本
    double[] storeFixedCost = {800,850,900,870,920,850};
    //从供货源运送一单位原材料到工厂i的成本
    double[][] supToComCost = {
            {2200,1500,600,1800,1200},
            {1600,2000,1300,700,600},
            {1700,1000,900,850,1250},
    };
    //从工厂到仓库的成本
    double[][] ComToStrCost = {
            {2200,1500,600,1800,1200,900},
            {1600,2000,1300,700,600,500},
            {1700,1000,900,850,1250,700},
            {1100,300,550,850,1250,700},
            {2500,1572,1320,980,750,1650},
    };
    //从仓库运送到市场的成本
    double[][] StrToMarCost = {
            {850,640,520,450,600,700},
            {500,600,550,350,450,580},
            {1200,1150,550,800,950,700},
            {1350,1150,550,800,950,650},
            {1503,520,550,800,600,840},
            {1235,950,750,1800,300,900},
    };
    //供应商的数量
    int supplierNumber = supplyCapacity.length;
    //潜在工厂选址的数量
    int companyNumber = productivity.length;
    //市场的数量
    int marketNumber = demands.length;
    //仓库的数量
    int storeNumber = storeCapacity.length;
}
import ilog.concert.IloException;
import ilog.concert.IloNumExpr;
import ilog.concert.IloNumVar;
import ilog.concert.IloNumVarType;
import ilog.cplex.IloCplex;

public class ComplexModel {
    ComplexData data;

    public ComplexModel(ComplexData data) {
        this.data = data;
    }

    //定义cplexn内部对象
    IloCplex model;
    //定义变量
    //yi变量
    public IloNumVar[] yi;
    //ye变量
    public IloNumVar[] ye;
    //xej变量
    public IloNumVar[][] xej;
    //xie变量
    public IloNumVar[][] xie;
    //xhi变量
    public IloNumVar[][] xhi;

    //求解函数
    public void solve() throws IloException {
        if(model.solve()==false){
            System.out.println(model);
            System.out.println("模型不可解");
        } else {
            System.out.println(model);
            System.out.println("目标值:"+model.getObjValue());
            System.out.println("=========选择变量===========");
            for(int i=0;i<data.companyNumber;i++){
                if (model.getValue(yi[i]) != 0) {
                    System.out.println("变量值yi[" + (i + 1) + "]");
                }
            }
            for(int i=0;i<data.companyNumber;i++){
                if (model.getValue(ye[i]) != 0) {
                    System.out.println("变量值ye[" + (i + 1) + "]");
                }
            }
            System.out.println("=========分配关系===========");
            for(int i=0;i<data.storeNumber;i++){
                for(int j=0;j<data.marketNumber;j++) {
                    if (model.getValue(xej[i][j]) != 0) {
                        System.out.println("变量值xej[" + (i + 1) + "]["+(j+1)+"]:" + model.getValue(xej[i][j]));
                    }
                }
            }
            for(int i=0;i<data.companyNumber;i++){
                for(int j=0;j<data.storeNumber;j++) {
                    if (model.getValue(xie[i][j]) != 0) {
                        System.out.println("变量值xie[" + (i + 1) + "]["+(j+1)+"]:" + model.getValue(xie[i][j]));
                    }
                }
            }
            for(int i=0;i<data.supplierNumber;i++){
                for(int j=0;j<data.companyNumber;j++) {
                    if (model.getValue(xhi[i][j]) != 0) {
                        System.out.println("变量值xhi[" + (i + 1) + "]["+(j+1)+"]:" + model.getValue(xhi[i][j]));
                    }
                }
            }
        }
    }
    //根据数学模型建立求解模型
    public void BuildModel() throws IloException{
        //初始化model
        model = new IloCplex();
        model.setOut(null);
        //定义决策变量的数据类型及取值范围
        yi = new IloNumVar[data.companyNumber];
        ye = new IloNumVar[data.storeNumber];
        xej = new IloNumVar[data.storeNumber][data.marketNumber];
        xie = new IloNumVar[data.companyNumber][data.storeNumber];
        xhi = new IloNumVar[data.supplierNumber][data.companyNumber];
        for (int i = 0; i < data.companyNumber; i++) {
            yi[i] = model.numVar(0,1, IloNumVarType.Bool, "yi[" + i + "]");
        }
        for (int i = 0; i < data.storeNumber; i++) {
            ye[i] = model.numVar(0,1, IloNumVarType.Bool, "ye[" + i + "]");
        }
        for (int i = 0; i < data.storeNumber; i++) {
            for(int j=0;j<data.marketNumber;j++) {
                xej[i][j] = model.numVar(0,Double.MAX_VALUE, IloNumVarType.Int, "xej[" + i + "]["+j+"]");
            }
        }
        for (int i = 0; i < data.companyNumber; i++) {
            for(int j=0;j<data.storeNumber;j++) {
                xie[i][j] = model.numVar(0,Double.MAX_VALUE, IloNumVarType.Int, "xie[" + i + "]["+j+"]");
            }
        }
        for (int i = 0; i < data.supplierNumber; i++) {
            for(int j=0;j<data.companyNumber;j++) {
                xhi[i][j] = model.numVar(0,Double.MAX_VALUE, IloNumVarType.Int, "xhi[" + i + "]["+j+"]");
            }
        }
        //设置目标函数
        IloNumExpr obj = model.numExpr();
        for(int i=0;i<data.companyNumber;i++){
            obj = model.sum(obj,model.prod(data.factoryFixedCost[i],yi[i]));
        }
        for (int i = 0; i < data.storeNumber; i++) {
            obj = model.sum(obj,model.prod(data.storeFixedCost[i],ye[i]));
        }
        for (int i = 0; i < data.supplierNumber; i++) {
            for (int j = 0; j < data.companyNumber; j++) {
                obj = model.sum(obj,model.prod(data.supToComCost[i][j],xhi[i][j]));
            }
        }
        for (int i = 0; i < data.companyNumber; i++) {
            for (int j = 0; j < data.storeNumber; j++) {
                obj = model.sum(obj,model.prod(data.ComToStrCost[i][j],xie[i][j]));
            }
        }
        for (int i = 0; i < data.storeNumber; i++) {
            for (int j = 0; j < data.marketNumber; j++) {
                obj = model.sum(obj,model.prod(data.StrToMarCost[i][j],xej[i][j]));
            }
        }
        model.addMinimize(obj);
        //设置约束条件1
        for (int i = 0; i < data.supplierNumber; i++) {
            IloNumExpr expr1 = model.numExpr();
            for (int j = 0; j < data.companyNumber; j++) {
                expr1 = model.sum(expr1, xhi[i][j]);
            }
            model.addLe(expr1,data.supplyCapacity[i]);
        }
        //设置约束条件2
        for (int i = 0; i < data.companyNumber; i++) {
            IloNumExpr expr1 = model.numExpr();
            for (int j = 0; j < data.supplierNumber; j++) {
                expr1 = model.sum(expr1, xhi[j][i]);
            }
            IloNumExpr expr2 = model.numExpr();
            for (int j = 0; j < data.storeNumber; j++) {
                expr2 = model.sum(expr2, xie[i][j]);
            }
            model.addGe(expr1,expr2);
        }
        //设置约束条件3
        for (int i = 0; i < data.companyNumber; i++) {
            IloNumExpr expr1 = model.numExpr();
            for (int j = 0; j < data.storeNumber; j++) {
                expr1 = model.sum(expr1,xie[i][j]);
            }
            model.addLe(expr1,model.prod(data.productivity[i],yi[i]));
        }
        //设置约束条件4
        for (int i = 0; i < data.storeNumber; i++) {
            IloNumExpr expr1 = model.numExpr();
            for (int j = 0; j < data.companyNumber; j++) {
                expr1 = model.sum(expr1,xie[j][i]);
            }
            IloNumExpr expr2 = model.numExpr();
            for (int j = 0; j < data.marketNumber; j++) {
                expr2 = model.sum(expr1,xej[i][j]);
            }
            model.addGe(expr1,expr2);
        }
        //设置约束条件5
        for (int i = 0; i < data.storeNumber; i++) {
            IloNumExpr expr1 = model.numExpr();
            for (int j = 0; j < data.marketNumber; j++) {
                expr1 = model.sum(expr1,xej[i][j]);
            }
            model.addLe(expr1,model.prod(data.storeCapacity[i],ye[i]));
        }
        //约束条件6
        for (int i = 0; i < data.marketNumber; i++) {
            IloNumExpr expr1 = model.numExpr();
            for (int j = 0; j < data.storeNumber; j++) {
                expr1 = model.sum(expr1,xej[j][i]);
            }
            model.addEq(expr1,data.demands[i]);
        }
        //约束条件7在变量定义时已满足
    }
}

        可以对前面所讨论的模型,通过改变目标函数和约束条件,将模型改为实现利润最大化,而不是成本最小化。

        还可以对前面所讨论的模型进行调整以允许在工厂和市场之间直接运输。还可以将规模经济考虑在内。这些要求会使模型求解更难。

两级可选容量的工厂-仓库-客户的选址模型是一个典型的组合优化问题,其目标是在给定的客户需求和候选设施位置的情况下,确定哪些设施应该建立以及它们应该服务哪些客户,以最小化总成本(建设和运营成本)。 下面是使用 Python 和 CPLEX 求解两级可选容量的工厂-仓库-客户选址模型的示例代码: ```python import cplex # 定义模型 model = cplex.Cplex() # 定义决策变量 y = {} for i in range(n): for j in range(m): y[i, j] = model.binary_var(name='y_{0}_{1}'.format(i, j)) x = {} for j in range(m): for k in range(l): x[j, k] = model.binary_var(name='x_{0}_{1}'.format(j, k)) s = {} for j in range(m): for k in range(l): s[j, k] = model.continuous_var(name='s_{0}_{1}'.format(j, k), lb=0) # 定义约束条件 for i in range(n): expr = cplex.SparsePair() for j in range(m): for k in range(l): expr.add(y[i, j], d[i, j, k]) model.add_constraint(expr=expr, rhs=1) for j in range(m): for k in range(l): expr = cplex.SparsePair() for i in range(n): expr.add(y[i, j], d[i, j, k]) model.add_constraint(expr=expr, rhs=s[j, k]) expr = cplex.SparsePair() for i in range(n): expr.add(y[i, j], 1) model.add_constraint(expr=expr, rhs=q[j, k] * x[j, k]) # 定义目标函数 obj = cplex.SparsePair() for j in range(m): for k in range(l): obj.add(c[j, k], x[j, k]) obj.add(cost[j, k], s[j, k]) for i in range(n): obj.add(cost[j, k] + d[i, j, k], y[i, j]) model.objective.set_sense(model.objective.sense.minimize) model.objective.set_linear(obj) # 求解模型 model.solve() # 输出结果 y_sol = model.solution.get_values([y[i, j] for i in range(n) for j in range(m)]) x_sol = model.solution.get_values([x[j, k] for j in range(m) for k in range(l)]) s_sol = model.solution.get_values([s[j, k] for j in range(m) for k in range(l)]) ``` 在这个代码中,`n` 表示客户数量,`m` 表示可选设施数量,`l` 表示每个设施可以服务的最大客户数量。`y[i, j]` 表示第 `i` 个客户是否被第 `j` 个设施服务,`x[j, k]` 表示第 `j` 个设施是否建立在第 `k` 个候选位置,`s[j, k]` 表示在第 `j` 个设施的第 `k` 个候选位置建立的容量。`d[i, j, k]` 表示第 `i` 个客户到第 `j` 个设施在第 `k` 个候选位置的运输距离,`c[j, k]` 表示在第 `k` 个候选位置建立第 `j` 个设施的成本,`cost[j, k]` 表示在第 `k` 个候选位置建立第 `j` 个设施并为第 `i` 个客户提供服务的总成本,`q[j, k]` 表示在第 `k` 个候选位置建立第 `j` 个设施的容量限制。最后使用 CPLEX 求解模型,并获取决策变量的取值作为结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值