27 用linprog、fmincon求 解线性规划问题(matlab程序)

1. 简述

① linprog函数:

求解线性规划问题,求目标函数的最小值,

[x,y]= linprog(c,A,b,Aeq,beq,lb,ub)

求最大值时,c加上负号:-c

② intlinprog函数:

求解混合整数线性规划问题,

[x,y]= intlinprog(c,intcon,A,b,Aeq,beq,lb,ub)

与linprog相比,多了参数intcon,代表了整数决策变量所在的位置

优化问题中最常见的,就是线性/整数规划问题 。即使赛题中有非线性目标/约束,第一想法也应是将其转化为线性

直白点说,只要决定参加数模比赛,学会建立并求解线性/整数规划问题是非常必要的。

本期主要阐述用Matlab软件 求解此类问题的一般步骤,后几期会逐步增加用Mathematica、AMPL、CPLEX、Gurobi、Python等软件求解的教程。


或许你已经听说或掌握了linprog等函数 ,实际上,它只是诸多求解方法 中的一种,且有一定的局限性

我的每期文章力求**"阅完可上手"并"知其所以然"** 。因此,在讲解如何应用linprog等函数语法前,有必要先了解:

  • 什么赛题适用线性/整数规划?
  • 如何把非线性形式线性化?
  • 如何查看某函数的语法?
  • 有哪几种求解方法?

把握好这四个问题 ,有时候比仅仅会用linprog等函数求解更重要。

一、什么赛题适用线性/整数规划

当题目中提到**"怎样分配"、"XX最大/最合理"、"XX尽量多/少"等词汇时**。具体有:

1. 生产安排

目标: 总利润最大;**约束:**原材料、设备限制;

2. 销售运输

目标: 运费等成本最低;**约束:**从某产地(产量有限制)运往某销地的运费不同;

3. 投资收益等

目标: 总收益最大;**约束:**不同资产配置下收益率/风险不同,总资金有限;

对于整数规划 ,除了通常要求变量为整数 外,典型的还有指派/背包等问题 (决策变量有0-1变量)。

二、如何把非线性形式线性化

在比赛时,遇到非线性形式是家常便饭。此时若能够线性化该问题 ,绝对是你数模论文的加分项

我在之前写的线性化文章中提到:如下非线性形式,均可实现线性化

总的来说, 具有 分段 函数形式、 绝对值 函数形式、 最小/大值 函数形式、 逻辑或 形式、 含有0-1变量的乘积 形式、 混合整数 形式以及 分式目标函数 ,均可实现 线性化

而实现线性化的主要手段 主要就两点,一是引入0-1变量 ,二是引入很大的整数M 。具体细节请参见之前写的线性化文章

三、如何查看函数所有功能

授之以鱼,不如授之以渔。

学习linprog等函数最好的方法,无疑是看Matlab官方帮助文档。 本文仅是抛砖引玉地举例说明几个函数的基础用法,更多细节参见帮助文档。步骤是:

  • 调用linprog等函数前需要事先安装"OptimizationToolbox"工具箱;
  • 在Matlab命令窗口输入"doc linprog ",便可查看语法 ,里面有丰富的例子;
  • 也可直接查看官方给的PDF帮助文档 ,后台回复"线性规划"可获取。

2. 代码

主程序:

%% 解线性规划问题

%f(x)=-5x(1)+4x(2)+2x(3)

f=[-5,4,2]; %函数系数

A=[6,-1,1;1,2,4]; %不等式系数

b=[8;10]; %不等式右边常数项

l=[-1,0,0]; %下限

u=[3,2,inf]; %上限

%%%%用linprog求解

[xol,fol]=linprog(f,A,b,[],[],l,u)

%%%%用fmincon求解

x0=[0,0,0];

f1214=inline('-5*x(1)+4*x(2)+2*x(3)','x');

[xoc,foc]=fmincon(f1214,x0,A,b,[],[],l,u)

子程序:

function [x,fval,exitflag,output,lambda]=linprog(f,A,B,Aeq,Beq,lb,ub,x0,options)

%LINPROG Linear programming.

% X = LINPROG(f,A,b) attempts to solve the linear programming problem:

%

% min f'*x subject to: A*x <= b

% x

%

% X = LINPROG(f,A,b,Aeq,beq) solves the problem above while additionally

% satisfying the equality constraints Aeq*x = beq. (Set A=[] and B=[] if

% no inequalities exist.)

%

% X = LINPROG(f,A,b,Aeq,beq,LB,UB) defines a set of lower and upper

% bounds on the design variables, X, so that the solution is in

% the range LB <= X <= UB. Use empty matrices for LB and UB

% if no bounds exist. Set LB(i) = -Inf if X(i) is unbounded below;

% set UB(i) = Inf if X(i) is unbounded above.

%

% X = LINPROG(f,A,b,Aeq,beq,LB,UB,X0) sets the starting point to X0. This

% option is only available with the active-set algorithm. The default

% interior point algorithm will ignore any non-empty starting point.

%

% X = LINPROG(PROBLEM) finds the minimum for PROBLEM. PROBLEM is a

% structure with the vector 'f' in PROBLEM.f, the linear inequality

% constraints in PROBLEM.Aineq and PROBLEM.bineq, the linear equality

% constraints in PROBLEM.Aeq and PROBLEM.beq, the lower bounds in

% PROBLEM.lb, the upper bounds in PROBLEM.ub, the start point

% in PROBLEM.x0, the options structure in PROBLEM.options, and solver

% name 'linprog' in PROBLEM.solver. Use this syntax to solve at the

% command line a problem exported from OPTIMTOOL.

%

% [X,FVAL] = LINPROG(f,A,b) returns the value of the objective function

% at X: FVAL = f'*X.

%

% [X,FVAL,EXITFLAG] = LINPROG(f,A,b) returns an EXITFLAG that describes

% the exit condition. Possible values of EXITFLAG and the corresponding

% exit conditions are

%

% 3 LINPROG converged to a solution X with poor constraint feasibility.

% 1 LINPROG converged to a solution X.

% 0 Maximum number of iterations reached.

% -2 No feasible point found.

% -3 Problem is unbounded.

% -4 NaN value encountered during execution of algorithm.

% -5 Both primal and dual problems are infeasible.

% -7 Magnitude of search direction became too small; no further

% progress can be made. The problem is ill-posed or badly

% conditioned.

% -9 LINPROG lost feasibility probably due to ill-conditioned matrix.

%

% [X,FVAL,EXITFLAG,OUTPUT] = LINPROG(f,A,b) returns a structure OUTPUT

% with the number of iterations taken in OUTPUT.iterations, maximum of

% constraint violations in OUTPUT.constrviolation, the type of

% algorithm used in OUTPUT.algorithm, the number of conjugate gradient

% iterations in OUTPUT.cgiterations (= 0, included for backward

% compatibility), and the exit message in OUTPUT.message.

%

% [X,FVAL,EXITFLAG,OUTPUT,LAMBDA] = LINPROG(f,A,b) returns the set of

% Lagrangian multipliers LAMBDA, at the solution: LAMBDA.ineqlin for the

% linear inequalities A, LAMBDA.eqlin for the linear equalities Aeq,

% LAMBDA.lower for LB, and LAMBDA.upper for UB.

%

% NOTE: the interior-point (the default) algorithm of LINPROG uses a

% primal-dual method. Both the primal problem and the dual problem

% must be feasible for convergence. Infeasibility messages of

% either the primal or dual, or both, are given as appropriate. The

% primal problem in standard form is

% min f'*x such that A*x = b, x >= 0.

% The dual problem is

% max b'*y such that A'*y + s = f, s >= 0.

%

% See also QUADPROG.

% Copyright 1990-2018 The MathWorks, Inc.

% If just 'defaults' passed in, return the default options in X

% Default MaxIter, TolCon and TolFun is set to [] because its value depends

% on the algorithm.

defaultopt = struct( ...

'Algorithm','dual-simplex', ...

'Diagnostics','off', ...

'Display','final', ...

'LargeScale','on', ...

'MaxIter',[], ...

'MaxTime', Inf, ...

'Preprocess','basic', ...

'TolCon',[],...

'TolFun',[]);

if nargin==1 && nargout <= 1 && strcmpi(f,'defaults')

x = defaultopt;

return

end

% Handle missing arguments

if nargin < 9

options = [];

% Check if x0 was omitted and options were passed instead

if nargin == 8

if isa(x0, 'struct') || isa(x0, 'optim.options.SolverOptions')

options = x0;

x0 = [];

end

else

x0 = [];

if nargin < 7

ub = [];

if nargin < 6

lb = [];

if nargin < 5

Beq = [];

if nargin < 4

Aeq = [];

end

end

end

end

end

end

% Detect problem structure input

problemInput = false;

if nargin == 1

if isa(f,'struct')

problemInput = true;

[f,A,B,Aeq,Beq,lb,ub,x0,options] = separateOptimStruct(f);

else % Single input and non-structure.

error(message('optim:linprog:InputArg'));

end

end

% No options passed. Set options directly to defaultopt after

allDefaultOpts = isempty(options);

% Prepare the options for the solver

options = prepareOptionsForSolver(options, 'linprog');

if nargin < 3 && ~problemInput

error(message('optim:linprog:NotEnoughInputs'))

end

% Define algorithm strings

thisFcn = 'linprog';

algIP = 'interior-point-legacy';

algDSX = 'dual-simplex';

algIP15b = 'interior-point';

% Check for non-double inputs

msg = isoptimargdbl(upper(thisFcn), {'f','A','b','Aeq','beq','LB','UB', 'X0'}, ...

f, A, B, Aeq, Beq, lb, ub, x0);

if ~isempty(msg)

error('optim:linprog:NonDoubleInput',msg);

end

% After processing options for optionFeedback, etc., set options to default

% if no options were passed.

if allDefaultOpts

% Options are all default

options = defaultopt;

end

if nargout > 3

computeConstrViolation = true;

computeFirstOrderOpt = true;

% Lagrange multipliers are needed to compute first-order optimality

computeLambda = true;

else

computeConstrViolation = false;

computeFirstOrderOpt = false;

computeLambda = false;

end

% Algorithm check:

% If Algorithm is empty, it is set to its default value.

algIsEmpty = ~isfield(options,'Algorithm') || isempty(options.Algorithm);

if ~algIsEmpty

Algorithm = optimget(options,'Algorithm',defaultopt,'fast',allDefaultOpts);

OUTPUT.algorithm = Algorithm;

% Make sure the algorithm choice is valid

if ~any(strcmp({algIP; algDSX; algIP15b},Algorithm))

error(message('optim:linprog:InvalidAlgorithm'));

end

else

Algorithm = algDSX;

OUTPUT.algorithm = Algorithm;

end

% Option LargeScale = 'off' is ignored

largescaleOn = strcmpi(optimget(options,'LargeScale',defaultopt,'fast',allDefaultOpts),'on');

if ~largescaleOn

[linkTag, endLinkTag] = linkToAlgDefaultChangeCsh('linprog_warn_largescale');

warning(message('optim:linprog:AlgOptsConflict', Algorithm, linkTag, endLinkTag));

end

% Options setup

diagnostics = strcmpi(optimget(options,'Diagnostics',defaultopt,'fast',allDefaultOpts),'on');

switch optimget(options,'Display',defaultopt,'fast',allDefaultOpts)

case {'final','final-detailed'}

verbosity = 1;

case {'off','none'}

verbosity = 0;

case {'iter','iter-detailed'}

verbosity = 2;

case {'testing'}

verbosity = 3;

otherwise

verbosity = 1;

end

% Set the constraints up: defaults and check size

[nineqcstr,nvarsineq] = size(A);

[neqcstr,nvarseq] = size(Aeq);

nvars = max([length(f),nvarsineq,nvarseq]); % In case A is empty

if nvars == 0

% The problem is empty possibly due to some error in input.

error(message('optim:linprog:EmptyProblem'));

end

if isempty(f), f=zeros(nvars,1); end

if isempty(A), A=zeros(0,nvars); end

if isempty(B), B=zeros(0,1); end

if isempty(Aeq), Aeq=zeros(0,nvars); end

if isempty(Beq), Beq=zeros(0,1); end

% Set to column vectors

f = f(:);

B = B(:);

Beq = Beq(:);

if ~isequal(length(B),nineqcstr)

error(message('optim:linprog:SizeMismatchRowsOfA'));

elseif ~isequal(length(Beq),neqcstr)

error(message('optim:linprog:SizeMismatchRowsOfAeq'));

elseif ~isequal(length(f),nvarsineq) && ~isempty(A)

error(message('optim:linprog:SizeMismatchColsOfA'));

elseif ~isequal(length(f),nvarseq) && ~isempty(Aeq)

error(message('optim:linprog:SizeMismatchColsOfAeq'));

end

[x0,lb,ub,msg] = checkbounds(x0,lb,ub,nvars);

if ~isempty(msg)

exitflag = -2;

x = x0; fval = []; lambda = [];

output.iterations = 0;

output.constrviolation = [];

output.firstorderopt = [];

output.algorithm = ''; % not known at this stage

output.cgiterations = [];

output.message = msg;

if verbosity > 0

disp(msg)

end

return

end

if diagnostics

% Do diagnostics on information so far

gradflag = []; hessflag = []; constflag = false; gradconstflag = false;

non_eq=0;non_ineq=0; lin_eq=size(Aeq,1); lin_ineq=size(A,1); XOUT=ones(nvars,1);

funfcn{1} = []; confcn{1}=[];

diagnose('linprog',OUTPUT,gradflag,hessflag,constflag,gradconstflag,...

XOUT,non_eq,non_ineq,lin_eq,lin_ineq,lb,ub,funfcn,confcn);

end

% Throw warning that x0 is ignored (true for all algorithms)

if ~isempty(x0) && verbosity > 0

fprintf(getString(message('optim:linprog:IgnoreX0',Algorithm)));

end

if strcmpi(Algorithm,algIP)

% Set the default values of TolFun and MaxIter for this algorithm

defaultopt.TolFun = 1e-8;

defaultopt.MaxIter = 85;

[x,fval,lambda,exitflag,output] = lipsol(f,A,B,Aeq,Beq,lb,ub,options,defaultopt,computeLambda);

elseif strcmpi(Algorithm,algDSX) || strcmpi(Algorithm,algIP15b)

% Create linprog options object

algoptions = optimoptions('linprog', 'Algorithm', Algorithm);

% Set some algorithm specific options

if isfield(options, 'InternalOptions')

algoptions = setInternalOptions(algoptions, options.InternalOptions);

end

thisMaxIter = optimget(options,'MaxIter',defaultopt,'fast',allDefaultOpts);

if strcmpi(Algorithm,algIP15b)

if ischar(thisMaxIter)

error(message('optim:linprog:InvalidMaxIter'));

end

end

if strcmpi(Algorithm,algDSX)

algoptions.Preprocess = optimget(options,'Preprocess',defaultopt,'fast',allDefaultOpts);

algoptions.MaxTime = optimget(options,'MaxTime',defaultopt,'fast',allDefaultOpts);

if ischar(thisMaxIter) && ...

~strcmpi(thisMaxIter,'10*(numberofequalities+numberofinequalities+numberofvariables)')

error(message('optim:linprog:InvalidMaxIter'));

end

end

% Set options common to dual-simplex and interior-point-r2015b

algoptions.Diagnostics = optimget(options,'Diagnostics',defaultopt,'fast',allDefaultOpts);

algoptions.Display = optimget(options,'Display',defaultopt,'fast',allDefaultOpts);

thisTolCon = optimget(options,'TolCon',defaultopt,'fast',allDefaultOpts);

if ~isempty(thisTolCon)

algoptions.TolCon = thisTolCon;

end

thisTolFun = optimget(options,'TolFun',defaultopt,'fast',allDefaultOpts);

if ~isempty(thisTolFun)

algoptions.TolFun = thisTolFun;

end

if ~isempty(thisMaxIter) && ~ischar(thisMaxIter)

% At this point, thisMaxIter is either

% * a double that we can set in the options object or

% * the default string, which we do not have to set as algoptions

% is constructed with MaxIter at its default value

algoptions.MaxIter = thisMaxIter;

end

% Create a problem structure. Individually creating each field is quicker

% than one call to struct

problem.f = f;

problem.Aineq = A;

problem.bineq = B;

problem.Aeq = Aeq;

problem.beq = Beq;

problem.lb = lb;

problem.ub = ub;

problem.options = algoptions;

problem.solver = 'linprog';

% Create the algorithm from the options.

algorithm = createAlgorithm(problem.options);

% Check that we can run the problem.

try

problem = checkRun(algorithm, problem, 'linprog');

catch ME

throw(ME);

end

% Run the algorithm

[x, fval, exitflag, output, lambda] = run(algorithm, problem);

% If exitflag is {NaN, <aString>}, this means an internal error has been

% thrown. The internal exit code is held in exitflag{2}.

if iscell(exitflag) && isnan(exitflag{1})

handleInternalError(exitflag{2}, 'linprog');

end

end

output.algorithm = Algorithm;

% Compute constraint violation when x is not empty (interior-point/simplex presolve

% can return empty x).

if computeConstrViolation && ~isempty(x)

output.constrviolation = max([0; norm(Aeq*x-Beq, inf); (lb-x); (x-ub); (A*x-B)]);

else

output.constrviolation = [];

end

% Compute first order optimality if needed. This information does not come

% from either qpsub, lipsol, or simplex.

if exitflag ~= -9 && computeFirstOrderOpt && ~isempty(lambda)

output.firstorderopt = computeKKTErrorForQPLP([],f,A,B,Aeq,Beq,lb,ub,lambda,x);

else

output.firstorderopt = [];

end

3. 运行结果

相关推荐
测试界的酸菜鱼10 分钟前
C# NUnit 框架:高效使用指南
开发语言·c#·log4j
GDAL10 分钟前
lua入门教程 :模块和包
开发语言·junit·lua
李老头探索12 分钟前
Java面试之Java中实现多线程有几种方法
java·开发语言·面试
小沈熬夜秃头中୧⍤⃝12 分钟前
【贪心算法】No.1---贪心算法(1)
算法·贪心算法
CSXB9913 分钟前
三十四、Python基础语法(文件操作-上)
开发语言·python·功能测试·测试工具
web Rookie33 分钟前
JS类型检测大全:从零基础到高级应用
开发语言·前端·javascript
很楠不爱44 分钟前
Qt——窗口
开发语言·qt
yi碗汤园44 分钟前
【一文了解】C#基础-集合
开发语言·前端·unity·c#
木向44 分钟前
leetcode92:反转链表||
数据结构·c++·算法·leetcode·链表
阿阿越1 小时前
算法每日练 -- 双指针篇(持续更新中)
数据结构·c++·算法