检查或修改优化问题
使用 show
或 write
检查问题
创建优化问题后,您可以使用 show
检查其表示。对于较大的问题,请改用 write
。例如,
prob = optimproblem; x = optimvar('x',2,'LowerBound',0); prob.Objective = x(1) - 2*x(2); prob.Constraints.cons1 = x(1) + 2*x(2) <= 4; prob.Constraints.cons2 = -x(1) + x(2) <= 1; show(prob)
OptimizationProblem : Solve for: x minimize : x(1) - 2*x(2) subject to cons1: x(1) + 2*x(2) <= 4 subject to cons2: -x(1) + x(2) <= 1 variable bounds: 0 <= x(1) 0 <= x(2)
此次检查展示了问题的基本要素,例如问题是求最小化还是最大化,以及变量边界。检查显示变量中使用的索引名称(如果有)。检查并未表明变量是否为整数值。
更改默认求解器或选项
为了尝试改进解或解速度,请检查并更改默认求解器或选项。
要查看默认求解器和选项,请使用 optimoptions(prob)
。例如,
rng default x = optimvar('x',3,'LowerBound',0); expr = sum((rand(3,1).*x).^2); prob = optimproblem('Objective',expr); prob.Constraints.lincon = sum(sum(randn(size(x)).*x)) <= randn; options = optimoptions(prob)
options = lsqlin options: Options used by current Algorithm ('interior-point'): (Other available algorithms: 'trust-region-reflective') Set properties: No options set. Default properties: Algorithm: 'interior-point' ConstraintTolerance: 1.0000e-08 Display: 'final' LinearSolver: 'auto' MaxIterations: 200 OptimalityTolerance: 1.0000e-08 StepTolerance: 1.0000e-12 Show options not used by current Algorithm ('interior-point')
该问题的默认求解器是 lsqlin
,您可以看到默认选项。
要更改求解器,请在 'Solver'
中设置 solve
名称-值对。要查看不同求解器适用的选项,请使用 optimoptions
将当前选项传递给不同的求解器。例如,继续这个问题,
options = optimoptions('quadprog',options)
options = quadprog options: Options used by current Algorithm ('interior-point-convex'): (Other available algorithms: 'trust-region-reflective') Set properties: ConstraintTolerance: 1.0000e-08 MaxIterations: 200 OptimalityTolerance: 1.0000e-08 StepTolerance: 1.0000e-12 Default properties: Algorithm: 'interior-point-convex' Display: 'final' LinearSolver: 'auto' Show options not used by current Algorithm ('interior-point-convex')
要更改选项,请使用 optimoptions
或点符号来设置选项,并将选项传递给 solve
名称-值对中的 'Options'
。请参阅常用的优化选项:调整和故障排除。继续这个示例,
options.Display = 'iter'; sol = solve(prob,'Options',options,'Solver','quadprog');
Iter Fval Primal Infeas Dual Infeas Complementarity 0 1.500359e+00 3.068423e-01 2.275437e+00 2.500000e-01 1 1.728717e-01 0.000000e+00 7.719860e-03 3.637874e-02 2 2.604108e-02 0.000000e+00 0.000000e+00 5.245260e-03 3 7.822161e-03 0.000000e+00 2.775558e-17 1.407915e-03 4 2.909218e-03 0.000000e+00 6.938894e-18 2.070784e-04 5 1.931264e-03 0.000000e+00 1.734723e-18 2.907724e-05 6 1.797508e-03 0.000000e+00 2.602085e-18 4.083167e-06 7 1.775398e-03 0.000000e+00 4.336809e-19 5.102453e-07 8 1.772971e-03 0.000000e+00 2.632684e-19 3.064243e-08 9 1.772848e-03 0.000000e+00 5.228973e-19 4.371356e-11 Minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance.
纠正错误指定的问题
要检查您的问题是否正确,请检查其所有方面。例如,通过运行此脚本创建一个优化问题来求解数独问题。
x = optimvar('x',9,9,9,'LowerBound',0,'UpperBound',1); cons1 = sum(x,1) == 1; cons2 = sum(x,2) == 1; cons3 = sum(x,3) == 1; prob = optimproblem; prob.Constraints.cons1 = cons1; prob.Constraints.cons2 = cons2; prob.Constraints.cons3 = cons3; mul = ones(1,1,9); mul = cumsum(mul,3); prob.Objective = sum(sum(sum(x,1),2).*mul); cons4 = optimconstr(3,3,9); for u = 1:3 for v = 1:3 arr = x(3*(u-1)+1:3*(u-1)+3,3*(v-1)+1:3*(v-1)+3,:); cons4(u,v,:) = sum(sum(arr,1),2) <= ones(1,1,9); end end prob.Constraints.cons4 = cons4; B = [1,2,2; 1,5,3; 1,8,4; 2,1,6; 2,9,3; 3,3,4; 3,7,5; 4,4,8; 4,6,6; 5,1,8; 5,5,1; 5,9,6; 6,4,7; 6,6,5; 7,3,7; 7,7,6; 8,1,4; 8,9,8; 9,2,3; 9,5,4; 9,8,2]; for u = 1:size(B,1) x.LowerBound(B(u,1),B(u,1),B(u,1)) = 1; end
该脚本有一些错误,您可以通过检查变量、目标和约束来发现这些错误。首先,检查变量 x
。
x
x = 9×9×9 OptimizationVariable array with properties: Array-wide properties: Name: 'x' Type: 'continuous' IndexNames: {{} {} {}} Elementwise properties: LowerBound: [9×9×9 double] UpperBound: [9×9×9 double] See variables with show. See bounds with showbounds.
该显示表明变量的类型是连续的。该变量应为整数值。更改类型。
x.Type = 'integer'
x = 9×9×9 OptimizationVariable array with properties: Array-wide properties: Name: 'x' Type: 'integer' IndexNames: {{} {} {}} Elementwise properties: LowerBound: [9×9×9 double] UpperBound: [9×9×9 double] See variables with show. See bounds with showbounds.
检查边界。应该有 21 个下界,值为 1,B
的每一行一个。因为 x
是一个大数组,所以将边界写入文件而不是在命令行上显示它们。
writebounds(x,'xbounds.txt')
在文件 xbounds.txt
中搜索 1 <=
的所有实例。在变量 x(1,1,1)
、x(2,2,2)
、…、x(9,9,9)
中,只有 9 个下界的值为 1。为了调查这种差异,请检查设置下界的代码:
for u = 1:size(B,1) x.LowerBound(B(u,1),B(u,1),B(u,1)) = 1; end
循环内的行应该说 x.LowerBound(B(u,1),B(u,2),B(u,3)) = 1;
。将所有下界重置为零,然后运行更正后的代码。
x.LowerBound = 0; for u = 1:size(B,1) x.LowerBound(B(u,1),B(u,2),B(u,3)) = 1; end writebounds(x,'xbounds.txt')
xbounds.txt
现在具有正确的下界数量,即 1。
检查目标函数。目标函数表达式很大,因此将表达式写入文件中。
write(prob.Objective,'objectivedescription.txt')
x(1, 1, 1) + x(2, 1, 1) + x(3, 1, 1) + x(4, 1, 1) + x(5, 1, 1) + x(6, 1, 1) + x(7, 1, 1) + x(8, 1, 1) + x(9, 1, 1) + x(1, 2, 1) + x(2, 2, 1) + x(3, 2, 1) + x(4, 2, 1) + x(5, 2, 1) + x(6, 2, ... 9*x(7, 8, 9) + 9*x(8, 8, 9) + 9*x(9, 8, 9) + 9*x(1, 9, 9) + 9*x(2, 9, 9) + 9*x(3, 9, 9) + 9*x(4, 9, 9) + 9*x(5, 9, 9) + 9*x(6, 9, 9) + 9*x(7, 9, 9) + 9*x(8, 9, 9) + 9*x(9, 9, 9)
目标函数看起来合理,因为它是标量表达式的总和。
将约束写入文件以供检查。
write(prob.Constraints.cons1,'cons1.txt') write(prob.Constraints.cons2,'cons2.txt') write(prob.Constraints.cons3,'cons3.txt') write(prob.Constraints.cons4,'cons4.txt')
检查 cons4.txt
,您会发现一个错误。所有的约束都是不等式而不是等式。更正创建此约束的代码行,并将更正后的约束放入问题中。
cons4 = optimconstr(3,3,9); for u = 1:3 for v = 1:3 arr = x(3*(u-1)+1:3*(u-1)+3,3*(v-1)+1:3*(v-1)+3,:); cons4(u,v,:) = sum(sum(arr,1),2) == ones(1,1,9); end end prob.Constraints.cons4 = cons4;
经过这些改变之后,您就可以成功求解问题了。
sol = solve(prob); x = round(sol.x); y = ones(size(x)); for k = 2:9 y(:,:,k) = k; % multiplier for each depth k end S = x.*y; % multiply each entry by its depth S = sum(S,3); % S is 9-by-9 and holds the solved puzzle drawSudoku(S)
变量名称重复
如果您重新创建一个变量,但已经有一个使用旧变量的表达式,那么在将表达式合并到单个问题中时可能会出现错误。请参阅变量名称不允许重复。
另请参阅
show
| showbounds
| write
| writebounds
| OptimizationConstraint
| OptimizationVariable
| OptimizationProblem
| OptimizationExpression