主要内容

用命名索引变量创建优化的初始点

此示例演示如何为具有指定索引变量的优化问题创建初始点。对于命名索引变量,通常指定初始点的最简单方法是使用findindex函数。

这是一个涉及混合生油和成品油的多期库存问题。目标是在生产和库存能力以及混合油“硬度”的各种限制条件下实现利润最大化。这道题取自Williams[1]。

问题描述

这个问题涉及两种生植物油和三种生非植物油,生产商可以将它们提炼成食用油。该制造商每月可以提炼多达200吨的植物油,以及多达250吨的非植物油。制造商可以储存每1000吨原料油,这是有益的,因为购买原料油的成本取决于月份和油的类型。每一种油都有一种叫做“硬度”的品质。调和油的硬度是组成油的线性加权硬度。

由于加工的限制,制造商限制在任何一个月提炼的油的数量不超过三种。另外,如果一个月内提炼出一种油,至少要提炼20吨。最后,如果一种植物油在一个月内提炼出来,那么非植物油也必须提炼出来。

收入是每吨石油销售的一个常数。成本是购买油的成本,按油和月不同而不同,每个月每吨油的储存成本是固定的。精炼油没有成本,但制造商不能储存精炼油(必须出售)。

输入问题数据

为计划期间和油创建命名的索引变量。

月份= {“1月”“2”“3”“4”“可能”“6月”};油= {“veg1”“veg2”“non1”“non2”“非刑”};Vegoils = {“veg1”“veg2”};非蔬菜= {“non1”“non2”“非刑”};

创建具有存储和使用参数的变量。

Maxstore = 1000;每种油的最大储存量Maxuseveg = 200;最大植物油用量Maxusenon = 250;最大非植物油用量Minuseraw = 20;最低原料油用量Maxnraw = 3;混合油中原料油的最大数量售价= 150;成品油和调和油的销售价格存储成本= 5;每期每油量的储存费用%股尾= 500;问题开始和结束时的库存Hmin = 3;%成品油最低硬度Hmax = 6;%成品油的最大硬度

指定原料油的硬度作为这个矢量。

H = [8.8,6.1,2,4.2,5.0];

指定原料油的成本如下所示。数组中的每一行表示一个月的原油价格。第一行表示1月份的成本,最后一行表示6月份的成本。

成本数据= [...110 120 130 110 115 130 130 110 90 115 110 140 130 100 95 120 110 110 120 120 125 100 120 150 110 105 90 100 140 80 135];

创建变量

创建这些问题变量:

  • 销售,每个月售出的每种油的数量

  • 商店,每个月底每种油的储存量

  • ,即每个月购买每种油的数量

此外,为了考虑每个月精炼和销售的油的数量和最小产量的限制,创建一个辅助二进制变量意在1正好是一个月卖出一桶油的时间。

卖出= optimvar(“卖出”月,油,下界的, 0);购买= optimvar(“买入”月,油,下界的, 0);Store = optimvar(“存储”月,油,下界的0,“UpperBound”, maxstore);Induse = optimvar(”意在“月,油,“类型”“整数”...下界的0,“UpperBound”1);

说出每个月售出的石油总量生产

产出= sum(sell,2);

创建目标

为了创建问题的目标函数,计算收入,并减去购买和储存油的成本。

创建一个最优化问题的最大化,并包括目标函数作为客观的财产。

问题=优化问题(“ObjectiveSense”“最大化”);概率。目标= sum(sales *produce) - sum(sum(costdata.*buy)) - sum(sum(storecost*store));

客观表达相当长。如果你愿意,你可以用showexpr (prob.Objective)命令。

创建约束

这个问题有几个需要设置的约束条件。

6月份每个油的储存量是500通过使用下界和上界来设置这个约束。

存储(“6月”:)。LowerBound = 500;存储(“6月”:)。UpperBound = 500;

制造商不能提炼超过maxuseveg任何月份都有植物油。使用设置此约束和所有后续约束约束和方程的表达式

Vegoiluse = sell(:, vegoils);Vegused = sum(vegoiluse, 2) <= maxuseveg;

制造商不能提炼超过maxusenon任何月份都可以使用非植物油。

Nonvegoiluse = sell(:,非蔬菜);Nonvegused = sum(nonvegoiluse,2) <= maxusenon;

调和油的硬度必须从Hmin到hmax

Hardmin = sum(repmat(h, 6,1).*sell, 2) >= hmin*produce;Hardmax = sum(repmat(h, 6,1).*sell, 2) <= hmax*produce;

月底储存的每一种油的量等于月初的量,加上买入的量,减去卖出的量。

: initstockbal = 500 +买(1)= =销售(1:)+存储(1:);stockbal =商店(1:5:)+购买(:2:6)= =销售(:2:6)+存储(:2:6);

如果一种油是在一个月内提炼出来的,那至少是这样minuseraw百分之二十的石油必须提炼和出售。

Minuse = sell >= minuseraw*induse;

确保意在当相应的油被精炼时,变量为1。

maxusevg = sell(:, vegoils) <= maxusevg *induse(:, vegoils);Maxusenv = sell(:,非蔬菜)<= maxusenon*induse(:,非蔬菜);

制造商不能卖超过maxnraw每月加油。

Maxnuse = sum(induse, 2) <= maxnraw;

如果一种植物油被精炼,油非刑还必须经过提炼和销售。

Deflogic1 = sum(induse(:,vegoils), 2) <= induse(:,“非刑”) *元素个数(vegoils);

在问题中包含约束表达式。

prov . constraints .vegused = vegused;probv . constraints .nonvegused =非vegused;probv . constraints .hardmin = hardmin;probv . constraints .hardmax = hardmax;probe . constraints .initstockbal = initstockbal;probal . constraints .stockbal = stockbal;probo . constraints .minuse =负;prov . constraints .maxusev = maxusev;prov . constraints .maxusenv = maxusenv;probe . constraints .maxnuse = maxnuse; prob.Constraints.deflogic1 = deflogic1;

解决问题

要显示使用初始点和不使用初始点之间的最终差异,请将选项设置为不使用启发式。然后解决问题。

Opts = optimoptions(“intlinprog”“启发式”“没有”);[sol1,fval1,exitstatus1,output1] = solve(prob,“选项”选择)
使用intlinprog解决问题。LP:最佳目标值为-1.075130e+05。切割生成:应用41个戈莫里切割,2个覆盖切割,1个mir切割和1个clique切割。下界为-1.047522e+05。分支和边界:节点总num int整数相对探索时间(s)解决方案fval gap (%) 12 0.31 1 -7.635370e+04 3.684085e+01 30 0.33 2 -9.960370e+04 4.899086e+00 56 0.36 3 -9.996667e+04 4.51821818e +00 73 0.37 4 -9.998889e+04 4.494990e+00 74 0.37 5 -9.998889e+04 4.494990e+00 112 0.40 6 -1.002139e+05 4.260380e+00 366 0.47 7 -1.002139e+05 2.284781e+00 466 0.49 8 -1.002787e+05 2.284781e+00 693 0.59 9 -1.002787e+05 1.590834e+00 693 0.59 -1.002787e+05 2.229029e-03找到最优解。Intlinprog停止是因为目标值在一个间隙公差的最优值,选项。RelativeGapTolerance = 0.0001(默认值)。intcon变量是公差范围内的整数,选项。IntegerTolerance = 1e-05(默认值)。
sol1 =带字段的结构:购买:[6x5倍]induuse: [6x5倍]sell: [6x5倍]store: [6x5倍]
Fval1 = 1.0028e+05
exitstatus1 = OptimalSolution
output1 =带字段的结构:relativegap: 0.0022 absolutegap: 2 numfeaspoints: 9 numnodes: 693 constrviolation: 1.9753e-11消息:'最佳解决方案找到....'intlinprog'

使用起始点

对于这个问题,使用初始点可以节省分支和边界迭代。创建一个正确尺寸的初始点。

x0。买= zeros(size(buy)); x0.induse = zeros(size(induse)); x0.store = zeros(size(store)); x0.sell = zeros(size(sell));

设置初始点只卖植物油veg2非植物油非刑.若要适当地设置此初始点,请使用findindex函数。

numMonths = size(induse,1);[idxMonths,idxOils] = findindex(induse,1:numMonths,{“veg2”“非刑”});x0.induse(idxMonths,idxOils) = 1;

最大限度地满足植物油和非植物油的限制。

x0.sell(:,idxOils) = repmat([200,250],numMonths,1)
x0 =带字段的结构:购买:[6x5倍]induuse: [6x5倍]store: [6x5倍]sell: [6x5倍]

设定第一个月不买油的起始点。

x .buy(1,:) = 0;

满足initstockbal第一个月的限制是每种油品初始库存500,第一个月不购买,持续使用veg2而且非刑

x .store(1,:) = [500 300 500 500 250];

存货结余约束条件findindex函数。

[idxMonths,idxOils] = findindex(store,2:6,{“veg2”});x .store(idxMonths,idxOils) = [100;0;0;0;500];[idxMonths,idxOils] = findindex(store,2:6,{“veg1”“non1”“non2”});x .store(idxMonths,idxOils) = 500;[idxMonths,idxOils] = findindex(store,2:6,{“非刑”});x .store(idxMonths,idxOils) = [0;0;0;0;500];[idxMonths,idxOils] = findindex(购买,2:6,{“veg2”});x .buy(idxMonths,idxOils) = [0;100;200;200;700];[idxMonths,idxOils] = findindex(购买,2:6,{“非刑”});x .buy(idxMonths,idxOils) = [0;250;250;250;750];

检查初始点是否可行。因为约束具有不同的维度,所以设置cellfunUniformOutput到的名值对当检查不可行性时。

Inf {1} = in可行性(vegused,x0);Inf {2} = in可行性(nonvegused,x0);Inf {3} = in可行性(hardmin,x0);Inf {4} = in可行性(hardmax,x0);Inf {5} = in可行性(initstockbal,x0);Inf {6} = in可行性(stockbal,x0);Inf {7} = in可行性(减去,x0);Inf {8} = in可行性(maxusev,x0);Inf {9} = in可行性(maxusenv,x0);Inf {10} = in可行性(maxnuse,x0); inf{11} = infeasibility(deflogic1,x0); allinfeas = cellfun(@max,inf,“UniformOutput”、假);Anyinfeas = cellfun(@max,allinfeas);disp (anyinfeas)
0 0 0 0 0 0 0

所有的不可行性都为0,这表明初始点是可行的。

使用初始点重新运行问题。

[sol2,fval2,exitstatus2,output2] = solve(prob,x0, x0,“选项”选择)
使用intlinprog解决问题。LP:最佳目标值为-1.075130e+05。切割生成:应用41个戈莫里切割,2个覆盖切割,1个mir切割和1个clique切割。下界为-1.047522e+05。相对差距为166.88%。分支和绑定:节点总数int整数相对探索时间(s)解fval gap (%) 12 0.29 2 -7.635370e+04 3.684085e+01 28 0.32 3 -8.836852e+04 1.823582e+01 32 0.32 4 -9.950185e+04 5.006462e+00 60 0.34 5 -9.996667e+ 00 76 0.34 6 -9.996667e+04 4.518218e+00 76 0.34 6 -9.996667e+04 4.518218e+00 118 0.36 7 -1.002139e+05 4.260380e+00 124 0.36 8 -1.002139e+05 4.260380e+00 298 0.42 9 -1.002787e+05 1.205718e+00 593 0.50 9 -1.002787e+05 1.450126e-03找到最佳解。Intlinprog停止是因为目标值在一个间隙公差的最优值,选项。RelativeGapTolerance = 0.0001(默认值)。intcon变量是公差范围内的整数,选项。IntegerTolerance = 1e-05(默认值)。
sol2 =带字段的结构:购买:[6x5倍]induuse: [6x5倍]sell: [6x5倍]store: [6x5倍]
Fval2 = 1.0028e+05
exitstatus2 = OptimalSolution
output2 =带字段的结构:relativegap: 0.0014 absolutegap: 1 numfeaspoints: 9 numnodes: 593 constrviolation: 5.6231e-11消息:'最佳解决方案找到....'intlinprog'

这一次,解决用更少的分支步骤来找到解决方案。

流(['使用初始点需要%d个分支和绑定步骤,\nbut '...'不使用初始点,走了%d步。'), output2.numnodes output1.numnodes)
使用初始点需要593步分支绑定,而不使用初始点需要693步。

参考

威廉姆斯,H.保罗。数学规划中的模型构建。第四版。J. Wiley,奇切斯特,英国。12.1题,食品制造11999.

另请参阅

|

相关的话题