当前位置:   article > 正文

数学建模——线性规划类_python数学建模线性规划代码

python数学建模线性规划代码

一.线性规划

1.算法

【1】通用代码

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

例如:

max需要加负号变成min、>=需要加负号变成<=

matlab

(1)基于求解器

  1. %    LP1_1_1.m
  2. f=[-2;-3;5];
  3. a=[-2,5,-1;1,3,1];b=[-10;12];
  4. aeq=[1,1,1];beq=7;
  5. [x,y]=linprog(f,a,b,aeq,beq,zeros(3,1));
  6. x,y=-y    %最大值
  7. x =
  8. 6.4286
  9. 0.5714
  10. 0
  11. y =
  12. 14.5714
  13. % 说明:在x1 x2 x3 = 6.4286 0.5714 0 的情况下,maxz = 14.5714

(2)基于问题

con中根据符号分类

  1. % LP1_1_2.m
  2. clc,clear
  3. prob=optimproblem('ObjectiveSense','max')
  4. x=optimvar('x',3,'LowerBound',0);
  5. prob.Objective=2*x(1)+3*x(2)-5*x(3);
  6. prob.Constraints.con1=x(1)+x(2)+x(3)==7;
  7. prob.Constraints.con2=2*x(1)-5*x(2)+x(3)>=10;
  8. prob.Constraints.con3=x(1)+3*x(2)+x(3)<=12;
  9. [sol,fval,flag,out]=solve(prob),sol,x;
  10. x=sol.x,y=fval

python

  1. #    线性规划模型.py
  2. from scipy.optimize import linprog
  3. import numpy as np
  4. c=np.array([-2,-3,5])
  5. a=[[-2,5,-1],[1,3,1]]
  6. b=[[-10],[12]]
  7. aeq=[[1,1,1]]
  8. beq=[7]
  9. lb=[0,0,0]
  10. ub=[None]*len(c)
  11. bound=tuple(zip(lb,ub))
  12. res=linprog(c,a,b,aeq,beq,bound,method='simplex',options={"disp":True})
  13. print("最优解:",res.x)
  14. print("目标函数最小值:",res.fun)
  15. print("目标函数最大值:",-res.fun)
  16. print(res)
  17. 最优解: [6.42857143 0.57142857 0. ]
  18. 目标函数最小值: -14.571428571428571
  19. 目标函数最大值: 14.571428571428571
  20. con: array([0.])
  21. fun: -14.571428571428571
  22. message: 'Optimization terminated successfully.'
  23. nit: 3
  24. slack: array([0. , 3.85714286])
  25. status: 0
  26. success: True
  27. x: array([6.42857143, 0.57142857, 0. ])

【2】可以转化为线性规划

(1)绝对值

  1. %    LP_abs.m
  2. clc,clear
  3. c=[1,2,3,4]';
  4. a=[1,-1,-1,1;1,-1,1,-3;1,-1,-2,3];
  5. b=[-2,-1,-1/2]';
  6. prob=optimproblem;
  7. u=optimvar('u',4,'LowerBound',0);
  8. v=optimvar('v',4,'LowerBound',0);
  9. prob.Objective=sum(c'*(u+v));
  10. prob.Constraints.con=a*(u-v)<=b;
  11. [sol,fval,flag,out]=solve(prob)
  12. x=sol.u-sol.v,minz=fval
  13. x =
  14. -2
  15. 0
  16. 0
  17. 0
  18. minz =
  19. 2.0000

(2)min(max(q*x))

(见风投案例模型二)

2.风投案例

【0】题目描述

【1】模型一

模型一:设定风险度的最大接受值,在不太冒险的情况下选择最大收益。

(1)matlab

  1. %    LP_fengtou_1.m
  2. clc,clear
  3. t=0;hold on
  4. while t<0.05
  5. c=[-0.05,-0.27,-0.19,-0.185,-0.185];
  6. A=[zeros(4,1),diag([0.025,0.015,0.055,0.026])];
  7. b=t*ones(4,1);
  8. Aeq=[1,1.01,1.02,1.045,1.065];beq=1;
  9. lb=zeros(5,1);
  10. [x,Q]=linprog(c,A,b,Aeq,beq,lb);
  11. Q=-Q;
  12. plot(t,Q,'*k');
  13. t=t+0.001;
  14. end
  15. xlabel('t'),ylabel('Q')

选择曲线的转折点作为最优投资组合。

输出转折点见模型一python代码:

鼠标在图上确定大致坐标,在循环中加入条件输出。

(2)python

  1. #    风投案例.py
  2. from scipy.optimize import linprog
  3. import numpy as np
  4. from numpy import ones,diag,c_,zeros
  5. import matplotlib.pyplot as plt
  6. plt.rc('font',size=16)
  7. c=np.array([-0.05,-0.27,-0.19,-0.185,-0.185])
  8. A=c_[zeros(4),diag([0.025,0.015,0.055,0.026])]
  9. Aeq=[[1,1.01,1.02,1.045,1.065]]
  10. beq=[1]
  11. a=0
  12. aa=[]
  13. ss=[]
  14. while a<0.05:
  15. b=ones(4)*a
  16. res = linprog(c, A, b, Aeq, beq)
  17. x=res.x
  18. Q=-res.fun
  19. aa.append(a)
  20. ss.append(Q)
  21. #输出转折点
  22. if a==0.006:
  23. print("x=", x)
  24. print("Q=", Q)
  25. a=a+0.001
  26. plt.plot(aa,ss,'r*')
  27. plt.xlabel('$a$')
  28. plt.ylabel('$Q$',rotation=90)
  29. plt.savefig('模型一.png',dpi=500)
  30. plt.show()
  31. x= [0. 0.24 0.4 0.10909091 0.22122066]
  32. Q= 0.20190763977806234(万元)

【2】模型二

模型二的目标函数:使各项目中风险最大的一项风险最小。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import cvxpy as cp
  4. plt.rc('font',size=16)
  5. x=cp.Variable(6,pos=True)
  6. obj=cp.Minimize(x[5])
  7. a1=np.array([0.025,0.015,0.055,0.026])
  8. a2=np.array([0.05,0.27,0.19,0.185,0.185])
  9. a3=np.array([1,1.01,1.02,1.045,1.065])
  10. k=0.05
  11. kk=[]
  12. ss=[]
  13. while k<0.27:
  14. con=[cp.multiply(a1,x[1:5])-x[5]<=0,
  15. 0.05*x[0]+0.27*x[1]+0.19*x[2]+0.185*x[3]+0.185*x[4]>=k,
  16. x[0]+1.01*x[1]+1.02*x[2]+1.045*x[3]+1.065*x[4]==1]
  17. prob=cp.Problem(obj,con)
  18. prob.solve(solver='CVXOPT')
  19. #输出转折点
  20. if abs(k-0.21)<0.0005:
  21. print("x=",x.value)
  22. print("风险=",prob.value)
  23. kk.append(k)
  24. ss.append(prob.value)
  25. k=k+0.005
  26. plt.plot(kk,ss,'r*')
  27. plt.xlabel('$k$')
  28. plt.ylabel('$R$',rotation=90)
  29. plt.savefig('模型二.png',dpi=500)
  30. plt.show()
  31. x= [2.09147087e-08 3.08874349e-01 5.14790372e-01 1.40396702e-01
  32. 1.52452147e-02 7.72185738e-03]
  33. 风险= 0.00772185738406626

【3】模型三

模型三:风险与收益的加权线性组合。

(1)matlab

  1. clc,clear
  2. M=10000;prob=optimproblem;
  3. x=optimvar('x',6,1,'LowerBound',0);
  4. r=[0.05,0.28,0.21,0.23,0.25];
  5. p=[0,0.01,0.02,0.045,0.065];
  6. q=[0,0.025,0.015,0.055,0.026]';
  7. %w=0:0.1:1;
  8. w=[0.766,0.767,0.810,0.811,0.824,0.825,0.962,0.963,1.0];
  9. V=[];%风险
  10. Q=[];%收益
  11. X=[];%最优解
  12. prob.Constraints.con1=(1+p)*x(1:end-1)==M;
  13. prob.Constraints.con2=q(2:end).*x(2:end-1)<=x(end);
  14. for i=1:length(w)
  15. prob.Objective=w(i)*x(end)-(1-w(i))*(r-p)*x(1:end-1);
  16. [sol,fval,flag,out]=solve(prob);
  17. xx=sol.x;
  18. V=[V,max(q.*xx(1:end-1))];
  19. Q=[Q,(r-p)*xx(1:end-1)];
  20. X=[X;xx'];
  21. plot(V,Q,'*-');grid on
  22. xlabel('风险');ylabel('收益')
  23.     X
  24. end
  25. V,Q,format
  26. w=(权重)
  27.     [0.766,    0.767,    0.810,    0.811,    0.824,    0.825,    0.962,    0.963,    1.0];
  28. V =(风险)
  29. 247.5248 92.2509 92.2509 78.4929 78.4929 59.3960 59.3960 0 0
  30. Q =(收益)
  31. 1.0e+03 *
  32. 2.6733 2.1648 2.1648 2.1060 2.1060 2.0162 2.0162 0.5000 0.5000
  33. X =
  34. 1.0e+04 *
  35. 0 0.9901 0 0 0 0.0248
  36. 0 0.3690 0.6150 0 0 0.0092
  37. 0 0.3690 0.6150 0 0 0.0092
  38. 0 0.3140 0.5233 0.1427 0 0.0078
  39. 0 0.3140 0.5233 0.1427 0 0.0078
  40. 0 0.2376 0.3960 0.1080 0.2284 0.0059(转折点处的X值)
  41. 0 0.2376 0.3960 0.1080 0.2284 0.0059
  42. 1.0000 0 0 0 0 0
  43. 1.0000 0 0 0 0 0

(2)python

  1. from scipy.optimize import linprog
  2. import matplotlib.pyplot as plt
  3. plt.rc('font',size=16)
  4. A=[[0,0.025,0,0,0,-1],[0,0,0.15,0,0,-1],[0,0,0,0.55,0,-1],[0,0,0,0,0.026,-1]]
  5. b=[0,0,0,0]
  6. Aeq=[[1,1.01,1.02,1.045,1.065,0]]
  7. beq=[1]
  8. bound=((0,None),(0,None),(0,None),(0,None),(0,None),(0,None))
  9. s=0;ss=[];aa=[]
  10. while s<=1:
  11. c=[-(1-s)*0.05,-(1-s)*0.27,-(1-s)*0.19,-(1-s)*0.185,-(1-s)*0.185,s]
  12. res=linprog(c,A,b,Aeq,beq)
  13. ss.append(s);aa.append(-res.fun)
  14. s=s+0.01
  15. plt.plot(ss,aa,'r.')
  16. plt.show()
  1. import matplotlib.pyplot as plt
  2. import cvxpy as cp
  3. import numpy as np
  4. plt.rc('font',size=16)
  5. x=cp.Variable(6)
  6. a1=np.array([0.025,0.015,0.055,0.026])
  7. a2=np.array([0.05,0.27,0.19,0.185,0.185])
  8. a3=np.array([1,1.01,1.02,1.045,1.065])
  9. con=[cp.multiply(a1,x[1:5])-x[5]<=0,a3@x[:-1]==1,x>=0]
  10. s=0;ss=[];aa=[]
  11. while s<=1:
  12. obj=cp.Minimize(s*x[-1]-(1-s)*a2@x[:-1])
  13. prob=cp.Problem(obj,con)
  14. prob.solve(solver='GLPK_MI')
  15. ss.append(s);aa.append(-prob.value)
  16. s=s+0.01
  17. plt.plot(ss,aa,'r.')
  18. plt.show()

二.整数规划

0.分类

1.通用代码

  1. %    int_LP_1.m
  2. clc,clear,prob=optimproblem;
  3. x=optimvar('x',6,'Type','integer','LowerBound',0);
  4. prob.Objective=sum(x);
  5. % 创建一个由空优化约束组成的 6×1 数组,使用 constr 初始化用于创建约束表达式的循环
  6. coon=optimconstr(6);
  7. a=[35,40,50,45,55,30];
  8. con(1)=x(1)+x(6)>=35;
  9. for i=1:5
  10. con(i+1)=x(i)+x(i+1)>=a(i+1);
  11. end
  12. prob.Constraints.con=con;
  13. [sol,fval,flag]=solve(prob)
  14. x=sol.x
  15. x =
  16. 35
  17. 5
  18. 45
  19. 0
  20. 55
  21. 0

intlinprog函数

x = intlinprog(f,intcon,A,b,Aeq,beq,lb,ub):函数相比linprog多了一个参数intcon,用于标定整数变量的位置:x1、x2为整数,即intcon = [1 2]

  1. %    int_LP_intlinprog.m
  2. c = [-40;-90];
  3. A = [9,7;7,20];
  4. b = [56;70];
  5. [x,fval] = intlinprog(c,[1 2],A,b,[],[],zeros(2,1));
  6. x,maxz=-fval
  7. x =
  8. 4.0000
  9. 2.0000
  10. maxz =
  11. 340

2.分支定界法(剪枝)

尝试一维单调

  1. %    int_branchbunch.m
  2. clear global;
  3. clear;
  4. clc;
  5. global result; % 存储所有整数解
  6. global lowerBound; % 下界
  7. global upperBound; % 上界
  8. global count; % 用以判断是否为第一次分支
  9. count = 1;
  10. f = [-40, -90];
  11. A = [8, 7;7, 20;];
  12. b = [56; 70];
  13. Aeq = [];
  14. beq = [];
  15. lbnd = [0; 0];
  16. ubnd = [inf; inf];
  17. % f = [-3 2 -5];
  18. % A = [1 2 -1;1 4 1;1 1 0;0 4 1];
  19. % b = [2;4;3;6];
  20. % Aeq = [];
  21. % beq = [];
  22. % lbnd=[0 0 0];
  23. % ubnd=[1 1 1];
  24. BinTree = createBinTreeNode({f, A, b, Aeq, beq, lbnd, ubnd});
  25. if ~isempty(result)
  26. [fval,flag]=min(result(:,end)); % result中每一行对应一个整数解及对应的函数值
  27. Result=result(flag,:);
  28. disp('该整数规划问题的最优解为:');
  29. disp(Result(1,1:end-1));
  30. disp('该整数规划问题的最优值为:');
  31. disp(Result(1,end));
  32. else
  33. disp('该整数规划问题无可行解');
  34. end
  35. function BinTree = createBinTreeNode(binTreeNode)
  36. global result;
  37. global lowerBound;
  38. global upperBound;
  39. global count;
  40. if isempty(binTreeNode)
  41. return;
  42. else
  43. BinTree{1} = binTreeNode;
  44. BinTree{2} = [];
  45. BinTree{3} = [];
  46. [x, fval, exitflag] = linprog(binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ...
  47. binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, binTreeNode{7});
  48. if count == 1
  49. % upperBound = 0; % 初始下界为空
  50. lowerBound = fval;
  51. count = 2;
  52. end
  53. if ~IsInRange(fval)
  54. return;
  55. end
  56. if exitflag == 1
  57. flag = [];
  58. % 寻找非整数解分量
  59. for i = 1 : length(x)
  60. if round(x(i)) ~= x(i)
  61. flag = i;
  62. break;
  63. end
  64. end
  65. % 分支
  66. if ~isempty(flag)
  67. lowerBound = max([lowerBound; fval]);
  68. OutputLowerAndUpperBounds();
  69. lbnd = binTreeNode{6};
  70. ubnd = binTreeNode{7};
  71. lbnd(flag, 1) = ceil(x(flag, 1)); % 朝正无穷四舍五入
  72. ubnd(flag, 1) = floor(x(flag, 1));
  73. % 进行比较,优先选择目标函数较大的进行分支
  74. [~, fval1] = linprog(binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ...
  75. binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, ubnd);
  76. [~, fval2] = linprog(binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ...
  77. binTreeNode{4}, binTreeNode{5}, lbnd, binTreeNode{7});
  78. if fval1 < fval2
  79. % 创建左子树
  80. BinTree{2} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ...
  81. binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, ubnd});
  82. % 创建右子树
  83. BinTree{3} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ...
  84. binTreeNode{4}, binTreeNode{5}, lbnd, binTreeNode{7}});
  85. else
  86. % 创建右子树
  87. BinTree{3} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ...
  88. binTreeNode{4}, binTreeNode{5}, lbnd, binTreeNode{7}});
  89. % 创建左子树
  90. BinTree{2} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ...
  91. binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, ubnd});
  92. end
  93. else
  94. upperBound = min([upperBound; fval]);
  95. OutputLowerAndUpperBounds();
  96. result = [result; [x', fval]];
  97. return;
  98. end
  99. else
  100. % 剪枝
  101. return;
  102. end
  103. end
  104. end
  105. function y = IsInRange(fval)
  106. global lowerBound;
  107. global upperBound;
  108. if isempty(upperBound) & fval >= lowerBound
  109. y = 1;
  110. else if (fval >= lowerBound & fval <= upperBound)
  111. y = 1;
  112. else
  113. y = 0;
  114. end
  115. end
  116. end
  117. function y = OutputLowerAndUpperBounds()
  118. global lowerBound;
  119. global upperBound;
  120. disp("此时下界、上界分别为");
  121. disp(lowerBound);
  122. if isempty(upperBound)
  123. disp(' 无上界')
  124. else
  125. disp(upperBound);
  126. end
  127. end
  128. 该整数规划问题的最优解为:
  129. 4 2
  130. 该整数规划问题的最优值为:
  131. -340

3.割平面法

割去小数部分,尝试二维单调

  1. function [intx,intf] = DividePlane(A,c,b,baseVector)
  2. %功能:用割平面法求解整数规划
  3. %调用格式:[intx,intf]=DividePlane(A,c,b,baseVector)
  4. %其中, A:约束矩阵;
  5. % c:目标函数系数向量;
  6. % b:约束右端向量;
  7. % baseVector:初始基向量;
  8. % intx:目标函数取最值时的自变量值;
  9. % intf:目标函数的最值;
  10. sz = size(A);
  11. nVia = sz(2);%获取有多少决策变量
  12. n = sz(1);%获取有多少约束条件
  13. xx = 1:nVia;
  14. if length(baseVector) ~= n
  15. disp('基变量的个数要与约束矩阵的行数相等!');
  16. mx = NaN;
  17. mf = NaN;
  18. return;
  19. end
  20. M = 0;
  21. sigma = -[transpose(c) zeros(1,(nVia-length(c)))];
  22. xb = b;
  23. %首先用单纯形法求出最优解
  24. while 1
  25. [maxs,ind] = max(sigma);
  26. %--------------------用单纯形法求最优解--------------------------------------
  27. if maxs <= 0 %当检验数均小于0时,求得最优解。
  28. vr = find(c~=0 ,1,'last');
  29. for l=1:vr
  30. ele = find(baseVector == l,1);
  31. if(isempty(ele))
  32. mx(l) = 0;
  33. else
  34. mx(l)=xb(ele);
  35. end
  36. end
  37. if max(abs(round(mx) - mx))<1.0e-7 %判断最优解是否为整数解,如果是整数解。
  38. intx = mx;
  39. intf = mx*c;
  40. return;
  41. else %如果最优解不是整数解时,构建切割方程
  42. sz = size(A);
  43. sr = sz(1);
  44. sc = sz(2);
  45. [max_x, index_x] = max(abs(round(mx) - mx));
  46. [isB, num] = find(index_x == baseVector);
  47. fi = xb(num) - floor(xb(num));
  48. for i=1:(index_x-1)
  49. Atmp(1,i) = A(num,i) - floor(A(num,i));
  50. end
  51. for i=(index_x+1):sc
  52. Atmp(1,i) = A(num,i) - floor(A(num,i));
  53. end
  54. Atmp(1,index_x) = 0; %构建对偶单纯形法的初始表格
  55. A = [A zeros(sr,1);-Atmp(1,:) 1];
  56. xb = [xb;-fi];
  57. baseVector = [baseVector sc+1];
  58. sigma = [sigma 0];
  59. %-------------------对偶单纯形法的迭代过程----------------------
  60. while 1
  61. %----------------------------------------------------------
  62. if xb >= 0 %判断如果右端向量均大于0,求得最优解
  63. if max(abs(round(xb) - xb))<1.0e-7
  64. %如果用对偶单纯形法求得了整数解,则返回最优整数解
  65. vr = find(c~=0 ,1,'last');
  66. for l=1:vr
  67. ele = find(baseVector == l,1);
  68. if(isempty(ele))
  69. mx_1(l) = 0;
  70. else
  71. mx_1(l)=xb(ele);
  72. end
  73. end
  74. intx = mx_1;
  75. intf = mx_1*c;
  76. return;
  77. else %如果对偶单纯形法求得的最优解不是整数解,继续添加切割方程
  78. sz = size(A);
  79. sr = sz(1);
  80. sc = sz(2);
  81. [max_x, index_x] = max(abs(round(mx_1) - mx_1));
  82. [isB, num] = find(index_x == baseVector);
  83. fi = xb(num) - floor(xb(num));
  84. for i=1:(index_x-1)
  85. Atmp(1,i) = A(num,i) - floor(A(num,i));
  86. end
  87. for i=(index_x+1):sc
  88. Atmp(1,i) = A(num,i) - floor(A(num,i));
  89. end
  90. Atmp(1,index_x) = 0; %下一次对偶单纯形迭代的初始表格
  91. A = [A zeros(sr,1);-Atmp(1,:) 1];
  92. xb = [xb;-fi];
  93. baseVector = [baseVector sc+1];
  94. sigma = [sigma 0];
  95. continue;
  96. end
  97. else %如果右端向量不全大于0,则进行对偶单纯形法的换基变量过程
  98. minb_1 = inf;
  99. chagB_1 = inf;
  100. sA = size(A);
  101. [br,idb] = min(xb);
  102. for j=1:sA(2)
  103. if A(idb,j)<0
  104. bm = sigma(j)/A(idb,j);
  105. if bm<minb_1
  106. minb_1 = bm;
  107. chagB_1 = j;
  108. end
  109. end
  110. end
  111. sigma = sigma -A(idb,:)*minb_1;
  112. xb(idb) = xb(idb)/A(idb,chagB_1);
  113. A(idb,:) = A(idb,:)/A(idb,chagB_1);
  114. for i =1:sA(1)
  115. if i ~= idb
  116. xb(i) = xb(i)-A(i,chagB_1)*xb(idb);
  117. A(i,:) = A(i,:) - A(i,chagB_1)*A(idb,:);
  118. end
  119. end
  120. baseVector(idb) = chagB_1;
  121. end
  122. %------------------------------------------------------------
  123. end
  124. %--------------------对偶单纯形法的迭代过程---------------------
  125. end
  126. else %如果检验数有不小于0的,则进行单纯形算法的迭代过程
  127. minb = inf;
  128. chagB = inf;
  129. for j=1:n
  130. if A(j,ind)>0
  131. bz = xb(j)/A(j,ind);
  132. if bz<minb
  133. minb = bz;
  134. chagB = j;
  135. end
  136. end
  137. end
  138. sigma = sigma -A(chagB,:)*maxs/A(chagB,ind);
  139. xb(chagB) = xb(chagB)/A(chagB,ind);
  140. A(chagB,:) = A(chagB,:)/A(chagB,ind);
  141. for i =1:n
  142. if i ~= chagB
  143. xb(i) = xb(i)-A(i,ind)*xb(chagB);
  144. A(i,:) = A(i,:) - A(i,ind)*A(chagB,:);
  145. end
  146. end
  147. baseVector(chagB) = ind;
  148. end
  149. M = M + 1;
  150. if (M == 1000000)
  151. disp('找不到最优解!');
  152. mx = NaN;
  153. minf = NaN;
  154. return;
  155. end
  156. end
  1. %    int_LP_divideplane.m
  2. c = [-1;-1]; % 不要加松弛变量
  3. A = [-1 1 1 0;3 1 0 1]; % 加上松弛变量
  4. b = [1;4];
  5. [x,fval] = DividePlane(A,c,b,[3 4]); % 松弛变量 3 4
  6. x,maxz=fval
  7. x =
  8. 1.0000 1.0000
  9. maxz =
  10. -2

4.匈牙利算法

【1】

【2】

  1. % int_XiongYaLi.m
  2. c = [6 7 11 2;4 5 9 8;3 1 10 4;5 9 8 2];
  3. a = zeros(8,16);
  4. for i = 1:4
  5. a(i,(i-1)*4+1:4*i) = 1;
  6. a(4+i,i:4:16) = 1;
  7. end
  8. b = ones(8,1);
  9. [x,y] = linprog(c,[],[],a,b,zeros(16,1),ones(16,1));
  10. X = reshape(x,4,4)
  11. opt = y
  12. % X =
  13. %
  14. % 0 0 0 1
  15. % 1 0 0 0
  16. % 0 1 0 0
  17. % 0 0 1 0
  18. %
  19. %
  20. % opt =
  21. %
  22. % 15
  23. A=[6 7 11 2;
  24. 4 5 9 8;
  25. 3 1 10 4;
  26. 5 9 8 2];
  27. % A = [3 8 2 10 3;8 7 2 9 7;6 4 2 7 5;8 4 2 3 5;9 10 6 9 10];
  28. B=Hungary(A);
  29. [~,b]=linear_assignment(A,B)
  30. % b =
  31. % 4 1 8 2
  32. function res=Hungary(N)
  33. %输入的矩阵应N*N的
  34. [a,~]=size(N);
  35. %第一步每一行减去当前行最小值
  36. for ii = 1:a
  37. N(ii,:)= N(ii,:)-min( N(ii,:));
  38. end
  39. %第二步每一列减去当前列最小值
  40. for ii = 1:a
  41. N(:,ii)= N(:,ii)-min( N(:,ii));
  42. end
  43. num=0;
  44. while num~=a
  45. [num,N_min,del_hang,del_lie]=line_count(N);
  46. if num ~=a
  47. for ii=1:a
  48. if del_hang(ii)~=ii
  49. N(ii,:) = N(ii,:)-N_min;
  50. end
  51. if del_lie(ii)==ii
  52. N(:,ii) = N(:,ii)+N_min;
  53. end
  54. end
  55. else
  56. res=N;
  57. end
  58. end
  59. function [num,M_min,del_hang,del_lie]=line_count(M)
  60. [a,~]=size(M);
  61. num=0;
  62. h=0;
  63. del_hang=zeros(a,1);
  64. del_lie=zeros(a,1);
  65. for ii=1:a
  66. del=ii-h;
  67. [~,b]=size(find(M(del,:)==0));
  68. if b>= 2
  69. M(del,:)=[];
  70. h=h+1;
  71. del_hang(ii)=ii; %得到被覆盖的行数
  72. num=num+1;
  73. end
  74. end
  75. l=0;
  76. for ii=1:a
  77. del=ii-l;
  78. [b,~]=size(find(M(:,del)==0));
  79. if b >=1
  80. M(:,del)=[];
  81. l=l+1;
  82. del_lie(ii)=ii; %得到被覆盖的列数
  83. num=num+1;
  84. end
  85. end
  86. M_min=min(min(M));
  87. end
  88. end
  89. function [place,res]=linear_assignment(M,N)
  90. %N是n维矩阵,N是经过Hungary处理的
  91. %M是未处理前的
  92. [a,~]=size(N);
  93. x=0;
  94. place=zeros(1,a);
  95. res=zeros(1,a);
  96. judge=zeros(1,a);
  97. while find(N==0)
  98. for ii=1:a
  99. judge(ii)=length(find(N(ii,:)==0));
  100. end
  101. judge(find(judge==0))=[];
  102. if min(judge)==1
  103. for ii=1:a
  104. if length(find(N(ii,:)==0))==1 %先选出行中只有1个0
  105. x=x+1;
  106. place(x)=ii+(find(N(ii,:)==0)-1)*a; %得到矩阵中的位置
  107. h=find(N(ii,:)==0);
  108. N(ii,:)=1./zeros(1,a);
  109. N(:,h)=1./zeros(a,1);
  110. end
  111. end
  112. end
  113. for ii=1:a
  114. judge(ii)=length(find(N(ii,:)==0));
  115. end
  116. judge(find(judge==0))=[];
  117. if min(judge)==2
  118. x=x+1;
  119. q=find(N==0);
  120. place(x)=q(1);
  121. N(mod(q(1),a),:)=1./zeros(1,a);
  122. N(:,fix(q(1)/a)+1)=1./zeros(a,1);
  123. end
  124. end
  125. [place,~]=sort(place);
  126. for ii=1:length(place)
  127. res(ii)=M(place(ii));
  128. end
  129. end

5.0-1规划

【1】intlinprog函数

0-1规划问题也可以看做区间在[0,1]的整数规划,下面利用intlinprog函数进行计算

  1. %    intlinprog_01.m
  2. c = [-3 2 -5]';
  3. A = [1 2 -1;1 4 1;1 1 0;0 4 1];
  4. b = [2;4;3;6];
  5. [x,fval] = intlinprog(c,[1 2 3],A,b,[],[],zeros(3,1),ones(3,1));
  6. x,maxz = -fval
  7. x =
  8. 1
  9. 0
  10. 1
  11. maxz =
  12. 8

【2】指派问题

(1)纯0-1整数规划
  1. c=np.array([[4,8,7,15,12],
  2. [7,9,17,14,10],
  3. [6,9,12,8,7],
  4. [6,7,14,6,10],
  5. [6,9,12,10,6]])
  6. x=cp.Variable((5,5),integer=True)
  7. obj=cp.Minimize(cp.sum(cp.multiply(c,x)))
  8. con=[0<=x,x<=1,
  9.     cp.sum(x,axis=0,keepdims=True)==1,
  10. cp.sum(x,axis=1,keepdims=True)==1]
  11. prob=cp.Problem(obj,con)
  12. prob.solve(solver='GLPK_MI')
  13. print("最优值为:",prob.value)
  14. print("最优解为:\n",x.value)
  15. 最优值为: 34.0
  16. 最优解为:
  17. [[0. 0. 1. 0. 0.]
  18. [0. 1. 0. 0. 0.]
  19. [1. 0. 0. 0. 0.]
  20. [0. 0. 0. 1. 0.]
  21. [0. 0. 0. 0. 1.]]
(2)广义指派
  1. 5*x(1)+4*x(2)<=24+y(1)M;        %M是充分大的数
  2. 7*x(1)+3*x(2)<=45+y(2)M;
  3. y(1)+y(2)=1;

i=1,2,3为三种生产方式

x(i)为产量;c(i)为每件产品的成本;k(i)为每种方式的固定成本

  1. min z=(k(1)*y(1)+c(1)*x(1))+(k(2)*y(2)+c(2)*x(2))+(k(3)*y(3)+c(3)*x(3));
  2. y(i)*m<=x(i)<=y(i)*M; %m充分小,M充分大
  3. y(i)=0 or 1;

【3】旅行商问题(TSP)

(司P31)比赛项目排序问题中,由于开始项目和结束项目没有连接,可引入虚拟项目15,与各项目的权重为0

三.非线性规划

    • 算法

【1】二次规划

目标函数二次,约束条件线性

H为实对称矩阵

[x,fval]=quadprog(H,f,A,b,Aeq,beq,lb,ub,x0)
  1. % DLP_1.m
  2. H=[4,-4;-4,8];
  3. f=[-6;3];
  4. a=[1,1;4,1];
  5. b=[3;9];
  6. [x,fval]=quadprog(H,f,a,b,[],[],zeros(2,1))
  7. x =
  8. 2.0854
  9. 0.6585
  10. fval =
  11. -5.5976
  1. % DLP_2.m
  2. x0 = [1;1];
  3. A=[1,1;4,1];
  4. b=[3;9];
  5. Aeq = [];
  6. beq = [];
  7. lb = [0;0];
  8. [x,fval] = fmincon(@fun,x0,A,b,Aeq,beq,lb)
  9. function f = fun(x)
  10. f = 2*x(1)-4*x(1)*x(2)+4*x(2)^2-6*x(1)-3*x(2)
  11. end
  12. x =
  13. 2.0000
  14. 1.0000
  15. fval =
  16. -15.0000

【2】无约束非线性规划

无约束优化问题有局部最优解的充分条件:梯度=0;Hesse矩阵正定

  1. %    NLP_nocon.m
  2. clc,clear
  3. f = @(x) x(1)^3-x(2)^3+3*x(1)^2+3*x(2)^2-9*x(1);
  4. g = @(x) -f(x);
  5. [m1,n1] = fminunc(f,[0,0])%求极小值
  6. [m2,n2] = fminsearch(g,[0,0]);%求极大值
  7. m2,n2=-n2
  8. m1 =
  9. 1.0000 -0.0000
  10. n1 =
  11. -5
  12. m2 =
  13. -3.0000 2.0000
  14. n2 =
  15. 31.0000

【3】有约束非线性规划

  1. %    NLP_con_1.m
  2. %[x,fval]=fmincon('fun1',x0,A,b,Aeq,beq,lb,ub,'fun2')
  3. [x,y]=fmincon('fun1',rand(3,1),[],[],[],[],zeros(3,1),[],'fun2')
  4. function f = fun1(x);
  5. f=sum(x.^2)+8;
  6. end
  7. function [g,h] = fun2(x)
  8. g=[-x(1)^2+x(2)-x(3)^2
  9. x(1)+x(2)^2+x(3)^3-20];
  10. h=[-x(1)-x(2)^2+2
  11. x(2)+2*x(3)^2-3];
  12. end
  13. x =
  14. 0.5522
  15. 1.2033
  16. 0.9478
  17. y =
  18. 10.6511
  1. % NLP_con_2.m
  2. clc,clear
  3. x = optimvar('x',3,'LowerBound',0);
  4. prob = optimproblem('Objective',sum(x.^2)+8);
  5. con1 = [-x(1)^2+x(2)-x(3)^2 <= 0
  6. x(1)+x(2)^2+x(3)^3 <= 20];
  7. con2 = [-x(1)-x(2)^2+2 == 0
  8. x(2)+2*x(3)^2 == 3];
  9. prob.Constraints.con1 = con1;
  10. prob.Constraints.con2 = con2;
  11. x0.x = rand(3,1);
  12. [s,f,flag,out] = solve(prob,x0);
  13. s.x,f

(1)只有等式约束

拉格朗日法

(2)一般形式

罚函数法

  1. 不等式约束g(x,i)<=0    等式约束h(x,j)=0
  2. 不等式 g(x,i)<=0 转化为 等式 max(0,g(x,i))=0
  3. 罚函数:T(x.M)=f(x)+M*sum(max(0,g(x,i)))+M*sum(h(x,j)^2)

【4】凸规划(f''>=0)

(1)判定:Hesse处处半正定

  1. %    NLP_TU.m
  2. clc,clear
  3. prob=optimproblem;
  4. x=optimvar('x',2,'LowerBound',0);
  5. prob.Objective=sum(x.^2)-4*x(1)+4;
  6. con=[-x(1)+x(2)-2<=0
  7. x(1)^2-x(2)+1<=0];
  8. prob.Constraints.con=con;
  9. x0.x=rand(2,1)
  10. [sol,fval,flag,out]=solve(prob,x0),sol.x

(2)K-T条件

只要是最优点,一定满足K-T条件

若为凸规划,则充要条件

【5】蒙特卡洛法

  1. %    MTKL.m
  2. clc,clear
  3. rng(0) %rng('shuffle')
  4. p0=0;n=10^6;tic
  5. for i=1:n
  6. x=randi([0,99],1,5);
  7. [f,g]=mengte(x);
  8. if all(g<=0)
  9. if p0<f
  10. x0=x;p0=f;
  11. end
  12. end
  13. end
  14. x0,p0,toc
  15. function [f,g]=mengte(x);
  16. f=x(1)^2+x(2)^2+3*x(3)^2+4*x(4)^2+2*x(5)^2-8*x(1)-2*x(2)-3*x(3)-x(4)-2*x(5);
  17. g=[sum(x)-400
  18. x(1)+2*x(2)+2*x(3)+x(4)+6*x(5)-800
  19. 2*x(1)+x(2)+6*x(3)-200
  20. x(3)+x(4)+5*x(5)-200];
  21. end
  22. x0 =
  23. 46 98 1 99 3
  24. p0 =
  25. 50273

2.LINGO

  1. model:
  2. sets:
  3. row/1..4/:b;
  4. col/1..5/:c1,c2,x;
  5. link(row,col):a;
  6. endsets
  7. data:
  8. c1=1,1,3,4,2;
  9. c2=-8,-2,-3,-1,-2;
  10. a=1 1 1 1 1
  11. 1 2 2 1 6
  12. 2 1 6 0 0
  13. 0 0 1 1 5;
  14. b=400,800,200,200;
  15. enddata
  16. max=@sum(col:c1*x^2+c2*x);
  17. @for(row(i):@sum(col(j):a(i,j)*x(j))<b(i));
  18. @for(col:@gin(x));
  19. @for(col:@bnd(0,x,99));
  20. end

3.案例+灵敏度分析

(司P42)

  1. clc,clear,format long g,close all
  2. syms x1 x2
  3. f=(339-0.01*x1-0.003*x2)*x1+(399-0.004*x1-0.01*x2)*x2-(400000+195*x1+225*x2);
  4. f=simplify(f);
  5. f1=diff(f,x1);f2=diff(f,x2);
  6. [x10,x20]=solve(f1,f2);
  7. x10=round(double(x10));x20=round(double(x20));
  8. f0=subs(f,{x1,x2},{x10,x20});
  9. f0=double(f0);
  10. subplot(121),fmesh(f,[0,10000,0,10000]),title('')
  11. xlabel('$x_1$','Interpreter','latex')
  12. ylabel('$X_2$','Interpreter','latex')
  13. subplot(122),L=fcontour(f,[0,10000,0,10000]);
  14. contour(L.XData,L.YData,L.ZData,'ShowText','on')
  15. xlabel('$x_1$','Interpreter','latex')
  16. ylabel('$X_2$','Interpreter','latex','Rotation',0)
  17. p1=339-0.01*x10-0.003*x20
  18. p2=399-0.004*x10-0.01*x20
  19. c=400000+195*x10+225*x20 %总支出
  20. rate=f0/c %利润
  21. x10
  22. x20

灵敏度分析

  1. clc,clear,format long g,close all
  2. syms x1 x2 a
  3. f=(339-0.01*x1-0.003*x2)*x1+(399-0.004*x1-0.01*x2)*x2-(400000+195*x1+225*x2);
  4. f=simplify(f);
  5. f1=diff(f,x1);f2=diff(f,x2);
  6. [x10,x20]=solve(f1,f2);
  7. subplot(121),fplot(x10,[0.002,0.02]),title('') %x1关于a的曲线
  8. xlabel('$x_1$','Interpreter','latex')
  9. ylabel('$X_2$','Interpreter','latex','Rotation',0)
  10. subplot(122),fplot(x20,[0.002,0.02]),title('') %x2关于a的曲线
  11. xlabel('$x_1$','Interpreter','latex')
  12. ylabel('$X_2$','Interpreter','latex','Rotation',0)
  13. dx1=diff(x10,a);dx10=subs(dx1,a,0.01);dx10=double(dx10);
  14. sx1a=dx10*0.01/4735;
  15. dx2=diff(x20,a);dx20=subs(dx2,a,0.01);dx20=double(dx20);
  16. sx2a=dx20*0.01/7043;
  17. F=subs(f,{x1,x2},{x10,x20});
  18. F=simplify(F);
  19. figure,fplot(F,[0.002,0.02]),title('')
  20. xlabel('$x_1$','Interpreter','latex')
  21. ylabel('$X_2$','Interpreter','latex','Rotation',0)
  22. Sya=-4735^2*0.01/553641;
  23. f3=subs(f,{x1,x2,a},{4735,7043,0.011});
  24. f3=double(f3);
  25. f4=subs(F,a,0.011) %近似最优利润
  26. f4=double(f4) %最优利润
  27. delta=(f4-f3)/f4 %利润的相对误差

四.多目标规划

1.多目标规划

max f1(x)=2x(1)+3x(2)
min f2(x)=x(1)+2x(2)

0.5x(1)+0.25x(2)<=8
0.2x(1)+0.2x(2)<=4
x(1)+x(2)>=10
x(1)>=0
x(2)>=0

【1】线性加权

min 0.5(-f1)+0.5(f2)
结果:
x(1)=7,x(2)=13

【2】理想点

分别求解得f1=-53,f2=10
新的目标函数 min f=[-2x(1)-3x(2)+53]^2+[x(1)+2x(2)-10]^2
结果:
x(1)=13.36,x(2)=5.28

【3】序贯

分别求解得f1=-53
加入条件-2x(1)-3x(2)=-53求f2
结果:
x(1)=7,x(2)=13
  1. clc,clear,prob=optimproblem;
  2. x=optimvar('x',2,'LowerBound',0);
  3. c1=[-2,-3];c2=[1,2];
  4. a=[0.5,0.25;0.2,0.2;1,5;-1,-1];
  5. b=[8;4;72;-10];
  6. prob.Constraints.con1=a*x<=b
  7. obj1=0.5*c1*x+0.5*c2*x
  8. prob1=prob;prob1.Objective=obj1;
  9. [sol1,fval1]=solve(prob1),sx=sol1.x
  10. f1=-c1*sx,f2=c2*sx
  11. prob21=prob;prob21.Objective=c1*x;
  12. [sol21,fval21]=solve(prob21),sx21=sol21.x
  13. prob22=prob;prob22.Objective=c2*x;
  14. [sol22,fval22]=solve(prob22),sx22=sol22.x
  15. prob23=prob;
  16. prob23.Objective=(c1*x-fval21)^2+(c2*x-fval22)^2;
  17. [sol23,fval23]=solve(prob23),sx23=sol23.x
  18. prob3=prob;prob3.Objective=c2*x;
  19. prob3.Constraints.con2=c1*x==fval21;
  20. [sol3,fval3]=solve(prob3),sx3=sol3.x

2.目标规划

正负偏差变量

软硬约束

“尽量”

优先权

序贯算法:

根据优先级排序,将目标规划分解成一系列单目标规划,依次求解

  1. clc,clear
  2. x=optimvar('x',2,'LowerBound',0);
  3. dp=optimvar('dp',4,'LowerBound',0);
  4. dm=optimvar('dm',4,'LowerBound',0);
  5. p=optimproblem('ObjectiveSense','min');
  6. p.Constraints.con1=2*sum(x)<=12;
  7. con2=[200*x(1)+300*x(2)+dm(1)-dp(1)==1500
  8. 2*x(1)-x(2)+dm(2)-dp(2)==0
  9. 4*x(1)+dm(3)-dp(3)==16
  10. 5*x(2)+dm(4)-dp(4)==15];
  11. p.Constraints.con2=con2;
  12. goal=100000*ones(3,1);
  13. mobj=[dm(1);dp(2)+dm(2);3*dp(3)+3*dm(3)+dp(4)];
  14. for i=1:3
  15. p.Constraints.con3=[mobj<=goal];
  16. p.Objective=mobj(i);
  17. [sx,fval]=solve(p);
  18. fprintf('第%d级目标计算结果如下:\n',i)
  19. fval,xx=sx.x,sdm=sx.dm,sdp=sx.dp
  20. goal(i)=fval;
  21. end

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/938582
推荐阅读
相关标签
  

闽ICP备14008679号