Main Content

optimeq

空の最適化等式配列の作成

R2019b 以降

説明

optimeq を使用して、等式のセットを初期化します。

ヒント

完全なワークフローについては、問題ベースの最適化ワークフローまたは方程式を解くための問題ベースのワークフローを参照してください。

eq = optimeq(N) は、N 行 1 列の空の最適化等式の配列を作成します。eq を使用して等式を作成するループを初期化します。得られた等式は、最適化問題の制約として、または方程式問題の方程式として使用します。

eq = optimeq(cstr) は、文字ベクトルの cell 配列または string ベクトル cstr によってインデックス付けされる空の最適化等式の配列を作成します。

cstr が 1 行 ncstr 列の場合 (ここで、ncstrcstr の要素数)、eq も 1 行 ncstr 列です。それ以外の場合、eq は ncstr 行 1 列です。

eq = optimeq(cstr1,N2,...,cstrk) または eq = optimeq({cstr1,cstr2,...,cstrk}) または eq = optimeq([N1,N2,...,Nk]) は、cstrN の引数のすべての組み合わせについて、空の最適化等式の ncstr1 x N2 x ... x ncstrk の配列を作成します。ここで、ncstrcstr の要素数です。

すべて折りたたむ

在庫モデルの等式制約を作成します。各期間の開始時点の商品の在庫は、前期間の終了時点の在庫と等しくなります。各期間で、在庫は buy ずつ増加し、sell ずつ減少します。変数 stock は、期間の終了時点の在庫です。

N = 12;
stock = optimvar('stock',N,1,'Type','integer','LowerBound',0);
buy = optimvar('buy',N,1,'Type','integer','LowerBound',0);
sell = optimvar('sell',N,1,'Type','integer','LowerBound',0);
initialstock = 100;

stockbalance = optimeq(N,1);

for t = 1:N
    if t == 1
        enterstock = initialstock;
    else
        enterstock = stock(t-1);
    end
    stockbalance(t) = stock(t) == enterstock + buy(t) - sell(t);
end

show(stockbalance)
(1, 1)

  -buy(1) + sell(1) + stock(1) == 100

(2, 1)

  -buy(2) + sell(2) - stock(1) + stock(2) == 0

(3, 1)

  -buy(3) + sell(3) - stock(2) + stock(3) == 0

(4, 1)

  -buy(4) + sell(4) - stock(3) + stock(4) == 0

(5, 1)

  -buy(5) + sell(5) - stock(4) + stock(5) == 0

(6, 1)

  -buy(6) + sell(6) - stock(5) + stock(6) == 0

(7, 1)

  -buy(7) + sell(7) - stock(6) + stock(7) == 0

(8, 1)

  -buy(8) + sell(8) - stock(7) + stock(8) == 0

(9, 1)

  -buy(9) + sell(9) - stock(8) + stock(9) == 0

(10, 1)

  -buy(10) + sell(10) - stock(9) + stock(10) == 0

(11, 1)

  -buy(11) + sell(11) - stock(10) + stock(11) == 0

(12, 1)

  -buy(12) + sell(12) - stock(11) + stock(12) == 0

制約を最適化問題に含めます。

prob = optimproblem;
prob.Constraints.stockbalance = stockbalance;

ループを使用する代わりに、変数に対する行列演算を使用して、同じ制約を作成できます。

stockbalance2 = optimeq(12, 1);
t = 2:12;
stockbalance2(t) = stock(t) == stock(t-1) + buy(t) - sell(t);
stockbalance2(1) = stock(1) == initialstock + buy(1) - sell(1);

新しい制約を表示します。これは stockbalance の制約と同じです。

show(stockbalance2)
(1, 1)

  -buy(1) + sell(1) + stock(1) == 100

(2, 1)

  -buy(2) + sell(2) - stock(1) + stock(2) == 0

(3, 1)

  -buy(3) + sell(3) - stock(2) + stock(3) == 0

(4, 1)

  -buy(4) + sell(4) - stock(3) + stock(4) == 0

(5, 1)

  -buy(5) + sell(5) - stock(4) + stock(5) == 0

(6, 1)

  -buy(6) + sell(6) - stock(5) + stock(6) == 0

(7, 1)

  -buy(7) + sell(7) - stock(6) + stock(7) == 0

(8, 1)

  -buy(8) + sell(8) - stock(7) + stock(8) == 0

(9, 1)

  -buy(9) + sell(9) - stock(8) + stock(9) == 0

(10, 1)

  -buy(10) + sell(10) - stock(9) + stock(10) == 0

(11, 1)

  -buy(11) + sell(11) - stock(10) + stock(11) == 0

(12, 1)

  -buy(12) + sell(12) - stock(11) + stock(12) == 0

ループでの制約の作成は、行列演算による制約の作成より多くの時間を要することがあります。

空港間の物品配送を扱う問題のために、インデックス付き等式を作成します。まず、空港を表すインデックスを作成します。

airports = ["LAX" "JFK" "ORD"];

空港間で配送される物品を表すインデックスを作成します。

goods = ["Electronics" "Foodstuffs" "Clothing" "Raw Materials"];

各物品単位の重さを指定する配列を作成します。

weights = [1 20 5 100];

各空港間で配送される物品の量を表す変数配列を作成します。quantities(airport1,airport2,goods) は、airport1 から airport2 へ配送される goods の量を表します。

quantities = optimvar('quantities',airports,airports,goods,'LowerBound',0);

等式制約を作成します。各空港から配送される物品の重さの合計が、各空港へ配送される物品の重さの合計と等しくなるようにします。

eq = optimeq(airports);
outweight = optimexpr(size(eq));
inweight = optimexpr(size(eq));
for i = 1:length(airports)
    temp = optimexpr;
    temp2 = optimexpr;
    for j = 1:length(airports)
        for k = 1:length(goods)
            temp = temp + quantities(i,j,k)*weights(k);
            temp2 = temp2 + quantities(j,i,k)*weights(k);
        end
    end
    outweight(i) = temp;
    inweight(i) = temp2;
    eq(i) = outweight(i) == inweight(i);
end

等式を検証します。

show(eq)
(1, 'LAX')

  -quantities('JFK', 'LAX', 'Electronics') - quantities('ORD', 'LAX', 'Electronics') + quantities('LAX', 'JFK', 'Electronics') + quantities('LAX', 'ORD', 'Electronics') - 20*quantities('JFK', 'LAX', 'Foodstuffs') - 20*quantities('ORD', 'LAX', 'Foodstuffs') + 20*quantities('LAX', 'JFK', 'Foodstuffs') + 20*quantities('LAX', 'ORD', 'Foodstuffs') - 5*quantities('JFK', 'LAX', 'Clothing') - 5*quantities('ORD', 'LAX', 'Clothing') + 5*quantities('LAX', 'JFK', 'Clothing') + 5*quantities('LAX', 'ORD', 'Clothing') - 100*quantities('JFK', 'LAX', 'Raw Materials') - 100*quantities('ORD', 'LAX', 'Raw Materials') + 100*quantities('LAX', 'JFK', 'Raw Materials') + 100*quantities('LAX', 'ORD', 'Raw Materials') == 0

(1, 'JFK')

  quantities('JFK', 'LAX', 'Electronics') - quantities('LAX', 'JFK', 'Electronics') - quantities('ORD', 'JFK', 'Electronics') + quantities('JFK', 'ORD', 'Electronics') + 20*quantities('JFK', 'LAX', 'Foodstuffs') - 20*quantities('LAX', 'JFK', 'Foodstuffs') - 20*quantities('ORD', 'JFK', 'Foodstuffs') + 20*quantities('JFK', 'ORD', 'Foodstuffs') + 5*quantities('JFK', 'LAX', 'Clothing') - 5*quantities('LAX', 'JFK', 'Clothing') - 5*quantities('ORD', 'JFK', 'Clothing') + 5*quantities('JFK', 'ORD', 'Clothing') + 100*quantities('JFK', 'LAX', 'Raw Materials') - 100*quantities('LAX', 'JFK', 'Raw Materials') - 100*quantities('ORD', 'JFK', 'Raw Materials') + 100*quantities('JFK', 'ORD', 'Raw Materials') == 0

(1, 'ORD')

  quantities('ORD', 'LAX', 'Electronics') + quantities('ORD', 'JFK', 'Electronics') - quantities('LAX', 'ORD', 'Electronics') - quantities('JFK', 'ORD', 'Electronics') + 20*quantities('ORD', 'LAX', 'Foodstuffs') + 20*quantities('ORD', 'JFK', 'Foodstuffs') - 20*quantities('LAX', 'ORD', 'Foodstuffs') - 20*quantities('JFK', 'ORD', 'Foodstuffs') + 5*quantities('ORD', 'LAX', 'Clothing') + 5*quantities('ORD', 'JFK', 'Clothing') - 5*quantities('LAX', 'ORD', 'Clothing') - 5*quantities('JFK', 'ORD', 'Clothing') + 100*quantities('ORD', 'LAX', 'Raw Materials') + 100*quantities('ORD', 'JFK', 'Raw Materials') - 100*quantities('LAX', 'ORD', 'Raw Materials') - 100*quantities('JFK', 'ORD', 'Raw Materials') == 0

for ループが入れ子にならないよう、標準の MATLAB® 演算子を使用して等式を表します。到着空港のインデックスについて合計して、発送量の配列を作成します。結果を絞り込み、大きさが 1 の次元を削除します。

departing = squeeze(sum(quantities,2));

発送量の重さを計算します。

departweights = departing * weights';

同様に、到着量の重さを計算します。

arriving = squeeze(sum(quantities,1));
arriveweights = arriving*weights';

発送重量と到着重量が等しいという制約を作成します。

eq2 = departweights == arriveweights;

IndexNames プロパティを設定することで、等式の適切なインデックス名を含めます。

eq2.IndexNames = {airports,{}};

新しい等式を表示します。先ほどの等式と一致していますが、転置されたベクトルであることに注意してください。

show(eq2)
('LAX', 1)

  -quantities('JFK', 'LAX', 'Electronics') - quantities('ORD', 'LAX', 'Electronics') + quantities('LAX', 'JFK', 'Electronics') + quantities('LAX', 'ORD', 'Electronics') - 20*quantities('JFK', 'LAX', 'Foodstuffs') - 20*quantities('ORD', 'LAX', 'Foodstuffs') + 20*quantities('LAX', 'JFK', 'Foodstuffs') + 20*quantities('LAX', 'ORD', 'Foodstuffs') - 5*quantities('JFK', 'LAX', 'Clothing') - 5*quantities('ORD', 'LAX', 'Clothing') + 5*quantities('LAX', 'JFK', 'Clothing') + 5*quantities('LAX', 'ORD', 'Clothing') - 100*quantities('JFK', 'LAX', 'Raw Materials') - 100*quantities('ORD', 'LAX', 'Raw Materials') + 100*quantities('LAX', 'JFK', 'Raw Materials') + 100*quantities('LAX', 'ORD', 'Raw Materials') == 0

('JFK', 1)

  quantities('JFK', 'LAX', 'Electronics') - quantities('LAX', 'JFK', 'Electronics') - quantities('ORD', 'JFK', 'Electronics') + quantities('JFK', 'ORD', 'Electronics') + 20*quantities('JFK', 'LAX', 'Foodstuffs') - 20*quantities('LAX', 'JFK', 'Foodstuffs') - 20*quantities('ORD', 'JFK', 'Foodstuffs') + 20*quantities('JFK', 'ORD', 'Foodstuffs') + 5*quantities('JFK', 'LAX', 'Clothing') - 5*quantities('LAX', 'JFK', 'Clothing') - 5*quantities('ORD', 'JFK', 'Clothing') + 5*quantities('JFK', 'ORD', 'Clothing') + 100*quantities('JFK', 'LAX', 'Raw Materials') - 100*quantities('LAX', 'JFK', 'Raw Materials') - 100*quantities('ORD', 'JFK', 'Raw Materials') + 100*quantities('JFK', 'ORD', 'Raw Materials') == 0

('ORD', 1)

  quantities('ORD', 'LAX', 'Electronics') + quantities('ORD', 'JFK', 'Electronics') - quantities('LAX', 'ORD', 'Electronics') - quantities('JFK', 'ORD', 'Electronics') + 20*quantities('ORD', 'LAX', 'Foodstuffs') + 20*quantities('ORD', 'JFK', 'Foodstuffs') - 20*quantities('LAX', 'ORD', 'Foodstuffs') - 20*quantities('JFK', 'ORD', 'Foodstuffs') + 5*quantities('ORD', 'LAX', 'Clothing') + 5*quantities('ORD', 'JFK', 'Clothing') - 5*quantities('LAX', 'ORD', 'Clothing') - 5*quantities('JFK', 'ORD', 'Clothing') + 100*quantities('ORD', 'LAX', 'Raw Materials') + 100*quantities('ORD', 'JFK', 'Raw Materials') - 100*quantities('LAX', 'ORD', 'Raw Materials') - 100*quantities('JFK', 'ORD', 'Raw Materials') == 0

ループでの制約の作成は、行列演算による制約の作成より多くの時間を要することがあります。

入力引数

すべて折りたたむ

制約の次元のサイズ。正の整数として指定します。

  • constr = optimeq(N) のサイズは N 行 1 列です。

  • constr = optimeq(N1,N2) のサイズは N1N2 列です。

  • constr = optimeq(N1,N2,...,Nk) のサイズは N1 x N2 x ... x Nk です。

例: 5

データ型: double

インデックス用の名前。文字ベクトルの cell 配列または string ベクトルとして指定します。

メモ

cstr"Tp" などの string スカラーにすることはできず、["Tp" "ul"] などのベクトルにする必要があります。単一の名前を指定するには、{'Tp'} またはそれと等価の cellstr("Tp") を使用します。

例: {'red','orange','green','blue'}

例: ["red";"orange";"green";"blue"]

データ型: string | cell

出力引数

すべて折りたたむ

等式。空の OptimizationEquality 配列として返されます。eq を使用して等式を作成するループを初期化します。

以下に例を示します。

x = optimvar('x',8);
eq = optimeq(4);
for k = 1:4
    eq(k) = 5*k*(x(2*k) - x(2*k-1)) == 10 - 2*k;
end

ヒント

  • optimeq の代わりに optimconstr を使用して、最適化問題の等式制約か、方程式問題の方程式を作成できます。

バージョン履歴

R2019b で導入