最適化式の初期化
このトピックでは、最適化式が適切に初期化されていない場合に発生するエラーについて説明し、エラーに対処するさまざまな方法の例を示します。
式のエラー
目的関数または非線形制約関数やそれらの式から、次のエラーを受け取ることがあります。
Unable to perform assignment because value of type 'optim.problemdef.OptimizationExpression' is not convertible to 'double'.
多くの場合、このエラーは最適化式が正しく初期化されていないことに起因しています。通常、変数 F
は、次のようにゼロの配列を宣言して標準ループ内で初期化します。
F = zeros(N,1);
しかし、F
が最適化式の場合は、optimexpr
を使用して初期化する必要があります。
F = optimexpr(N,1);
このトピックでは、適切な初期化方法の例を示します。どの方法も、内部ループを使用する関数の同じ例に基づいています。
function f = myFun(x) out = zeros(size(x)); out(1) = x(1); for i = 2:10 out(i) = (x(i) - x(i-1))^3; end f = mean(out); end
最適化変数 x
の目的関数として myFun(x)
を使用しようとすると、次のようなエラーが発生します。
x = optimvar("x",10,LowerBound=0,UpperBound=10);
prob = optimproblem(Objective=myFun(x));
Unable to perform assignment because value of type 'optim.problemdef.OptimizationVariable' is not convertible to 'double'. Error in myFun (line 3) out(1) = x(1); Caused by: Error using double Conversion to double from optim.problemdef.OptimizationVariable is not possible.
ただし、myFun
はソルバーベースの問題では目的関数として機能します。
rng default
x0 = 10*rand(10,1);
lb = zeros(10,1);
ub = 10 + lb;
[sol,fval] = fmincon(@myFun,x0,[],[],[],[],lb,ub)
Local 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. sol = 9.4226 10.0000 0.0000 5.0000 10.0000 0.0000 3.3333 6.6667 10.0000 0.0000 fval = -262.9274
この問題にはいくつかの局所的な解があるため、初期点によって異なる解が得られる可能性があります。
"like"
構文の使用による配列の初期化
zeros
に対して引数 "like"
を使用するように関数を書き換えます。このようにすると、最適化式または数値配列を入力として渡すことができます。
この方法にはいくつかの利点があります。
関数シグネチャが維持される。
解法プロセスで実行される余分なコードが導入されない。
該当する場合は自動微分が有効になる。
ソルバーベースと問題ベースのいずれのワークフローでも関数を使用できる。
fcn2optimexpr
を使用するときに静的解析が有効になる。静的解析の詳細については、最適化式の静的解析を参照してください。
function f = myFun1(x) out = zeros(size(x),"like",x); out(1) = x(1); for i = 2:10 out(i) = (x(i) - x(i-1))^3; end f = mean(out); end
問題ベースのワークフローで myFun1
を使用します。
x = optimvar("x",10,LowerBound=0,UpperBound=10); prob = optimproblem(Objective=myFun1(x)); rng default x0.x = 10*rand(10,1); [sol,fval] = solve(prob,x0)
Solving problem using fmincon. Local 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. sol = struct with fields: x: [10×1 double] fval = -262.9274
ソルバーベースのワークフローで myFun1
を使用します。
rng default
x0 = 10*rand(10,1);
lb = zeros(10,1);
ub = 10 + lb;
[sol,fval] = fmincon(@myFun1,x0,[],[],[],[],lb,ub)
Local 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. sol = 9.4226 10.0000 0.0000 5.0000 10.0000 0.0000 3.3333 6.6667 10.0000 0.0000 fval = -262.9274
関数の変更による初期配列の受け入れ
追加引数として初期値を受け入れるように、関数を書き換えます。このようにすると、最適化式または数値配列を初期値として渡すことができます。myFun2
は入力変数 out
を出力変数として使用し、ゼロ配列または最適化式のいずれかを受け入れます。
この方法にはいくつかの利点があります。
該当する場合は自動微分が有効になる。
解法プロセスで実行される余分なコードが導入されない。
ソルバーベースと問題ベースのいずれのワークフローでも関数を使用できる。
fcn2optimexpr
を使用するときに静的解析が有効になる。静的解析の詳細については、最適化式の静的解析を参照してください。
この方法の欠点は、別の関数シグネチャで関数を書き換える必要があることです。
function f = myFun2(out,x) out(1) = x(1); for i = 2:10 out(i) = (x(i) - x(i-1))^3; end f = mean(out); end
問題ベースのワークフローで myFun2
を使用します。
x = optimvar("x",10,LowerBound=0,UpperBound=10); out = optimexpr(size(x)); prob = optimproblem(Objective=myFun2(out,x)); rng default x0.x = 10*rand(10,1); [sol,fval] = solve(prob,x0)
Solving problem using fmincon. Local 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. sol = struct with fields: x: [10×1 double] fval = -262.9274
ソルバーベースのワークフローで myFun2
を使用します。
rng default
x0 = 10*rand(10,1);
lb = zeros(10,1);
ub = 10 + lb;
out = zeros(size(x0));
[sol,fval] = fmincon(@(x)myFun2(out,x),x0,[],[],[],[],lb,ub)
Local 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. sol = 9.4226 10.0000 0.0000 5.0000 10.0000 0.0000 3.3333 6.6667 10.0000 0.0000 fval = -262.9274
関数の書き換えによる適切な式の初期化
問題変数のタイプを明示的にチェックすると、式を適切に初期化することができます。この方法にはいくつかの利点があります。
該当する場合は自動微分が有効になる。
ソルバーベースと問題ベースのいずれのワークフローでも関数を使用できる。
この方法の欠点は、関数を書き換える必要があること、ソルバーの実行中にわずかなオーバーヘッドが発生すること、if
ステートメントがあるため fcn2optimexpr
を使用するときに静的解析がサポートされないということです。静的解析の詳細については、最適化式の静的解析を参照してください。
function f = myFun3(x) % Check for the data type of variable x if isa(x,'double') out = zeros(size(x)); else out = optimexpr(size(x)); end % No changes to the rest of the code out(1) = x(1); for i = 2:10 out(i) = (x(i) - x(i-1))^3; end f = mean(out); end
最適化変数および目的関数 myFun3
を使用して、問題を解きます。
x = optimvar("x",10,LowerBound=0,UpperBound=10); prob = optimproblem(Objective=myFun3(x)); rng default x0.x = 10*rand(10,1); [sol,fval] = solve(prob,x0)
Solving problem using fmincon. Local 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. sol = struct with fields: x: [10×1 double] fval = -262.9274
fmincon
および目的関数 myFun3
を使用して、問題を解きます。
rng default
x0 = 10*rand(10,1);
lb = zeros(10,1);
ub = 10 + lb;
out = zeros(size(x0));
[sol,fval] = fmincon(@myFun3,x0,[],[],[],[],lb,ub)
Local 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. sol = 9.4226 10.0000 0.0000 5.0000 10.0000 0.0000 3.3333 6.6667 10.0000 0.0000 fval = -262.9274
fcn2optimexpr
変換の使用
R2022b 以降では、fcn2optimexpr
を使用して目的関数を最適化式に変換し、その式を標準のゼロ配列を使用して初期化できます。
この方法にはいくつかの利点があります。
関数シグネチャが維持される。
該当する場合は自動微分が有効になる。
ソルバーベースと問題ベースのいずれのワークフローでも関数を使用できる。
この方法には静的解析が必要なため、MATLAB® の以前のバージョンでは正しく実行されない可能性があるほか、わずかなオーバーヘッドが発生することがあります。この例では式のエラーで示した元の関数 myFun
を使用しており、問題ベースのワークフローでは失敗します。
x = optimvar("x",10,LowerBound=0,UpperBound=10); obj = fcn2optimexpr(@myFun,x,Display="on"); prob = optimproblem(Objective=obj); rng default x0.x = 10*rand(10,1); [sol,fval] = solve(prob,x0)
The function uses only supported operators. The returned expressions use the operators on the problem variables. Solving problem using fmincon. Local 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. sol = struct with fields: x: [10×1 double] fval = -262.9274