最適化問題の確認または変更
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