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变量**)。 ## **二、如何把非线性形式线性化** 在比赛时,遇到非线性形式是家常便饭。此时若能够**线性化该问题** ,绝对是你数模论文的**加分项**。 我在[之前写的线性化文章](https://zhuanlan.zhihu.com/p/552076713 "之前写的线性化文章")中提到:**如下非线性形式,均可实现线性化**: > **总的来说,** 具有 **分段** 函数形式、 **绝对值** 函数形式、 **最小/大值** 函数形式、 **逻辑或** 形式、 **含有0-1变量的乘积** 形式、 **混合整数** 形式以及 **分式目标函数** ,均可实现 **线性化**。 而实现线性化的**主要手段** 主要就两点,一是**引入0-1变量** ,二是**引入很大的整数*M*** 。具体细节请参见之前写的[线性化文章](https://zhuanlan.zhihu.com/p/552076713 "线性化文章")。 ## **三、如何查看函数所有功能** 授之以鱼,不如授之以渔。 **学习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, \}, 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.** **运行结果** ![](https://file.jishuzhan.net/article/1685997338503417858/d7047ebe416048948cb4dd73057be1e0.png) ![](https://file.jishuzhan.net/article/1685997338503417858/72355c15ed144c229aedca74dae4124e.png)

相关推荐
purrrew3 分钟前
【数据结构_8】栈和队列
java·开发语言·数据结构
天水幼麟9 分钟前
Python学习笔记
笔记·python·学习
凤年徐14 分钟前
【C/C++】深入理解指针(二)
c语言·开发语言·c++·经验分享·笔记·指针
Hello-FPGA21 分钟前
QT 初体验
开发语言·qt
叫我DPT29 分钟前
分享一个python启动文件脚本(django示例)
数据库·python·django
_玖-幽33 分钟前
大数据分析02 基础语法差异
python·数据分析·go
coder777735 分钟前
js逆向分享
javascript·爬虫·python·算法·安全
QQ_77813297441 分钟前
从文本到视频:基于扩散模型的AI生成系统全解析(附PyTorch实现)
人工智能·pytorch·python
Cao1234567893211 小时前
扫雷-C语言版
c语言·开发语言
冠位观测者1 小时前
【Leetcode 每日一题 - 补卡】1534. 统计好三元组
数据结构·算法·leetcode