最適化問題の確認または変更
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
です。また、既定のオプションがわかります。
ソルバーを変更するには、solve
で名前と値のペア 'Solver'
を設定します。異なるソルバーで使用できるオプションを確認するには、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
またはドット表記を使用してオプションを設定し、名前と値のペア 'Options'
でオプションを solve
に渡します。詳細については、一般的に使用される最適化オプション: 調整とトラブルシューティングを参照してください。例を続けます。
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.
範囲を確認します。B
の各行に 1 つずつ、値 1 の下限が 21 個存在していなければなりません。x
は大規模な配列であるため、範囲をコマンド ラインに表示する代わりに、ファイルに書き込みます。
writebounds(x,'xbounds.txt')
ファイル xbounds.txt
で 1 <=
のすべてのインスタンスを検索します。値 1 の下限は、変数 x(1,1,1)
、x(2,2,2)
、…、x(9,9,9)
内の 9 つのみです。この不一致を調べるには、下限を設定しているコードを調べます。
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