Main Content

最適化式

最適化式とは

最適化式は、最適化変数の多項式結合または有理結合です。

x = optimvar('x',3,3); % a 3-by-3 variable named 'x'
expr1 = sum(x,1) % add the columns of x, get a row vector
expr2 = sum(x,2) % add the rows of x, get a column vector
expr3 = sum(sum(x.*randn(3))) % add the elements of x multiplied by random numbers
expr4 = randn(3)*x % multiply a random matrix times x
expr5 = sum(sum(x*diag(1:3))) % multiply the columns of x by their column number and sum the result
expr6 = sum(sum(x.*x)) % sum of the squares of all the variables

最適化式は、最適化変数に対する、変数の転置や連結など多数の MATLAB® 演算の結果としても得られます。最適化式に対してサポートされている演算の一覧については、最適化変数および式でサポートされる演算を参照してください。

最後に、fcn2optimexpr を最適化変数に作用する MATLAB 関数に適用した結果、最適化式になる場合があります。詳細については、非線形関数から最適化式への変換を参照してください。

最適化モデリング関数では、複素数、Inf、または NaN 値は指定できません。演算によりこのような式が得られた場合、式は表示できません。詳細については、式に Inf または NaN が含まれるを参照してください。

目的関数の式

目的関数は、サイズが 1 行 1 列の式です。

y = optimvar('y',5,3);
expr = sum(y,2); % a 5-by-1 vector
expr2 = [1:5]*expr;

expr はベクトルであるため、目的関数には適していません。式 expr2 は、目的関数に適しています。

メモ

多項式、有理式、および初等関数 (exp など) で構成されていない非線形関数がある場合は、その関数を fcn2optimexpr を使用して最適化式に変換します。詳細については、非線形関数から最適化式への変換最適化変数および式でサポートされる演算を参照してください。

式を目的関数として問題に含めるには、ドット表記を使用するか、または問題を作成するときにその目的関数を含めます。

prob = optimproblem;
prob.Objective = expr2;
% or equivalently
prob = optimproblem('Objective',expr2);

式をループで作成するには、optimexpr によって返される空の式から始めます。

x = optimvar('x',3,3,'Type','integer','LowerBound',0,'UpperBound',1);
y = optimvar('y',3,3);
expr = optimexpr;
for i = 1:3
    for j = 1:3
        expr = expr + y(j,i) - x(i,j);
    end
end
show(expr)
  y(1, 1) + y(2, 1) + y(3, 1) + y(1, 2) + y(2, 2) + y(3, 2) + y(1, 3) + y(2, 3) + y(3, 3)
- x(1, 1) - x(2, 1) - x(3, 1) - x(1, 2) - x(2, 2) - x(3, 2) - x(1, 3) - x(2, 3) - x(3, 3)

expr は、ループを使用せずに作成できます。

x = optimvar('x',3,3,'Type','integer','LowerBound',0,'UpperBound',1);
y = optimvar('y',3,3);
expr = sum(sum(y' - x));
show(expr)
  y(1, 1) + y(2, 1) + y(3, 1) + y(1, 2) + y(2, 2) + y(3, 2) + y(1, 3) + y(2, 3) + y(3, 3)
- x(1, 1) - x(2, 1) - x(3, 1) - x(1, 2) - x(2, 2) - x(3, 2) - x(1, 3) - x(2, 3) - x(3, 3)

メモ

目的関数が二乗和である場合に solve にそのように認識させるには、expr'*expr ではなく sum(expr.^2) と記述します。内部パーサーは、明示的な二乗和のみを認識します。例については、非負の線形最小二乗法、問題ベースを参照してください。

制約の式と方程式

制約は、==<=>= のいずれかの比較演算子を含む 2 つの "比較可能な式" です。方程式は、比較演算子 == を使用する 2 つの比較可能な式です。比較可能な式は同じサイズであるか、または一方の式がスカラー、つまり、サイズが 1 行 1 列でなければなりません。

x = optimvar('x',3,2,'Type','integer','LowerBound',0,'UpperBound',1);
y = optimvar('y',2,4);
z = optimvar('z');

constr1 = sum(x,2) >= z;

x のサイズは 3 行 2 列であるため、sum(x,2) のサイズは 3 行 1 列です。z がスカラー変数であるため、この式は z と比較可能です。

constr2 = y <= z;

y のサイズは 2 行 4 列です。ここでも、z がスカラー変数であるため、yz と比較可能です。

constr3 = (sum(x,1))' <= sum(y,2);

sum(x,1) のサイズは 1 行 2 列であるため、(sum(x,1))' のサイズは 2 行 1 列です。sum(y,2) のサイズは 2 行 1 列であるため、この 2 つの式は比較可能です。

メモ

多項式、有理式、および初等関数 (exp など) で構成されていない非線形関数がある場合は、その関数を fcn2optimexpr を使用して最適化式に変換します。詳細については、非線形関数から最適化式への変換最適化変数および式でサポートされる演算を参照してください。

問題に制約を含めるには、ドット表記を使用し、各制約に異なる名前を付けます。

prob = optimproblem;
prob.Constraints.constr1 = constr1;
prob.Constraints.constr2 = constr2;
prob.Constraints.constr3 = constr3;

同様に、問題に方程式を含めるには、ドット表記を使用し、各方程式に異なる名前を付けます。

prob = eqnproblem;
prob.Equations.eq1 = eq1;
prob.Equations.eq2 = eq12

また、問題を作成するときに制約や方程式を含めることもできます。たとえば、合計が 1 を超えない正の変数が 10 ペアあるとします。

x = optimvar('x',10,2,'LowerBound',0);
prob = optimproblem('Constraints',sum(x,2) <= 1);

制約式や方程式をループで作成するには、optimconstroptimeq、または optimineq によって返される空の制約式から始めます。

x = optimvar('x',3,2,'Type','integer','LowerBound',0,'UpperBound',1);
y = optimvar('y',2,4);
z = optimvar('z');
const1 = optimconstr(2);
for i = 1:2
    const1(i) = x(1,i) - x(3,i) + 2*z >= 4*(y(i,2) + y(i,3) + 2*y(i,4));
end
show(const1)
(1, 1)

  x(1, 1) - x(3, 1) + 2*z - 4*y(1, 2) - 4*y(1, 3) - 8*y(1, 4) >= 0

(2, 1)

  x(1, 2) - x(3, 2) + 2*z - 4*y(2, 2) - 4*y(2, 3) - 8*y(2, 4) >= 0

const1 は、ループを使用せずに作成できます。

x = optimvar('x',3,2,'Type','integer','LowerBound',0,'UpperBound',1);
y = optimvar('y',2,4);
z = optimvar('z');
const1 = x(1,:) - x(3,:) + 2*z >= 4*(y(:,1) + y(:,3) + 2*y(:,4))';
show(const1)
(1, 1)

  x(1, 1) - x(3, 1) + 2*z - 4*y(1, 1) - 4*y(1, 3) - 8*y(1, 4) >= 0

(1, 2)

  x(1, 2) - x(3, 2) + 2*z - 4*y(2, 1) - 4*y(2, 3) - 8*y(2, 4) >= 0

ヒント

最良のパフォーマンスを得るには、制約式ではなく、変数定義に変数範囲を含めます。また、ループを使用せずに制約を作成すると、通常はパフォーマンスが向上します。詳細については、効率的な最適化問題の作成を参照してください。

注意

問題内の各制約式は、同じ比較を使用しなければなりません。たとえば、以下のコードは、cons1<= 比較を使用し、cons2>= 比較を使用しており、cons1cons2 が同じ式内にあるため、エラーが発生します。

prob = optimproblem;
x = optimvar('x',2,'LowerBound',0);
cons1 = x(1) + x(2) <= 10;
cons2 = 3*x(1) + 4*x(2) >= 2;
prob.Constraints = [cons1;cons2]; % This line throws an error

このエラーは、制約ごとに個別の式を使用することで回避できます。

prob.Constraints.cons1 = cons1;
prob.Constraints.cons2 = cons2;

最適化変数のハンドル動作

  • OptimizationVariable オブジェクトには、"ハンドル" コピー動作があります。詳細については、ハンドル オブジェクトの動作ハンドル クラスと値クラスの比較を参照してください。ハンドル コピー動作とは、OptimizationVariable のコピーがオリジナルを指しており、独立して存在していないことを意味します。たとえば、変数 x を作成し、それを y にコピーして、y のプロパティを設定します。x に新しいプロパティ値が反映される点に注意してください。

    x = optimvar('x','LowerBound',1);
    y = x;
    y.LowerBound = 0;
    showbounds(x)
        0 <= x

参考

| | |

関連するトピック