2-14 CPLEXの最適化ノード[レコード設定タブ]
![CPLEXの最適化ノード.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F223763%2F707691a2-a903-0b46-6199-e75a78ad8463.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=2aa3841877ddc0c92e42b7cd8c5edd86)
1.ノードの目的
Modelerからの入力をつかってCPLEXで最適化を行います。
2.解説動画(4分)
3.クイックスタート
一時間ごとの電力需要データから最大消費電力を最小化する、蓄電池への充放電を算出します。
[線グラフ]ノードでもデータを確認しておきます。日中帯は需要が多く、夜間や朝は少ないということがわかります。
[可変長ファイル]ノードに[CPLEXの最適化ノード]ノードと[テーブル]ノードを順番に接続します。
[CPLEXの最適化ノード]ノードをダブルクリックして編集します。[OPLモデル]に以下のOPLモデルのコードを入力します。このコードはあらかじめCPLEX Optimization Studioなどで作成しておきます。
//①既知の情報の定義///////////////////////////////////////////////////////////////////////////
//1時間毎の電力需要量
tuple TDemands{
int time;
float demand;
}
{TDemands}Demands=...;
float BatteryCapacity = 500; //蓄電池の容量
float ChargeDemandsEfficiency = 100; //時間あたりに充放電できる量
float BatteryInit = 0; //蓄電池充電量初期値
//②決定変数と決定式///////////////////////////////////////////////////////////////////////////
//決定変数
dvar float BatteryInput[d in Demands]; //充放電量
//決定式
dexpr float BatteryCharge[d in Demands] = BatteryInit + sum(d2 in Demands:d2.time<=d.time)BatteryInput[d2]; //バッテリー残量
dexpr float Consumption[d in Demands] = d.demand+ BatteryInput[d]; //電力消費量
dexpr float MaxConsumption = max(d in Demands) Consumption[d]; //電力消費の最大値
//③目的関数の定義///////////////////////////////////////////////////////////////////////////
minimize MaxConsumption;//電力消費を最小化する
//④制約条件の定義///////////////////////////////////////////////////////////////////////////
subject to{
forall(d in Demands){
Consumption[d] >= 0; //電力消費量はマイナスにならない
BatteryCharge[d] <= BatteryCapacity; //バッテリー容量以上の電力は充電できない
if(d.time==1){ //バッテリーからの放電量は充電されている量以下である
BatteryInput[d] >= -BatteryInit;
}else{
BatteryInput[d] >= -BatteryCharge[item(Demands,d.time-1)];
}
BatteryInput[d] <= ChargeDemandsEfficiency; //バッテリーへの充電量は時間当たり上限がある
BatteryInput[d] >= -ChargeDemandsEfficiency; //バッテリーからの放電量は時間当たり上限がある
}
}
なお、上のOPLモデルの意味は以下の記事で解説しています。
CPLEXで蓄電池をつかったピーク消費電力最小化 - Qiita
そして、[入力データ]タブの設定をします。
[データソース]が入力CSVであることを確認します。
次に、[入力データに対応するOPLのタプルセット名]にOPLモデルでデータ・ファイルから読み込んでいたタプルを指定します。ここでは「Demands」になります。
そして、[入力マッピング]でOPLモデルのタプルの列名の「time」、「demand」とModelerからの入力データの列名の「TIME」、「DEMAND」マッピングを行います。「demand」のデータ型は[浮動小数点]であることに注意してください。
次に、[出力]タブの設定をします。
[出力モード]は[決定変数]を選びます。
[OPLでの目的関数値の変数名]に「MaxConsumption」を入力します。これが最適化結果でスカラー値なので、すべての行に同じ値が入ります。
[出力に使用する目的関数値のフィールド名]に「最大電力消費量」を入力します。これが最適化値の列名になります。
[出力タプル]にデータ・ファイルから読み込んでいたタプルを指定します。ここでは「Demands」になります。結果的にはModelerから入力したデータになっています。これでtimeとdemandの列が出力されます(Modelerからの入力ではなくtupleからの出力なので、小文字で定義されています)
そして、[変数の出力]でOPLモデルの決定変数の「BatteryInput」を「充放電」として、決定式の「BatteryCharge」を「バッテリー残量」として、「Consumption」を「電力消費量」として出力しています。これらはすべてfloatなので[データ型]は[浮動小数点]にします。
なお、「BatteryInput」、「BatteryCharge」、「Consumption」はいずれも、出力タプルである「Demands」に基づく配列なのでこのように一緒に出力が可能です。
[出力ノード]を実行すると最適化の結果を参照できます。
需要が少ないときに充電をして、需要が多いときに放電することによって、消費量のピークを抑えています。
最後に[線グラフ]ノードでもデータを確認しておきます。朝の需要が少ないときに充電をして、日中帯は需要が多いときには放電することによって、消費量のピークを抑えていることがわかります。
4.Tips
需要の予測をModelerで行って、そのまま[CPLEXの最適化]ノードで最適化することももちろん可能です。
電力需要予測は以下の記事のストリームで行いましたので、このストリームを流用します。
SPSS Modelerで電力需要を予測する - Qiita
このストリームに[条件抽出]ノードを接続し、「'$FutureFlag' = 1」の条件で予測結果のみに絞り込みます。
次に、今回のCPLEXのモデルで必要としている「TIME」という連番の列を追加します。
[入力データ]のタブの入力フィールドで、「demand」への入力データとして、ここでは上側95%区間の予測値「$TSUCI-DEMAND」を選んでみました。
[CPLEXの最適化]ノードの出力からはCPLEXからのみの出力となるので、「TS」などの元々あった情報も出力するためには、[レコード結合]でつなぐ必要があります。重複項目はフィルターします。
後は、[テーブル]ノードと[線グラフ]ノードもコピーしてくれば完成です。
結果を見てみましょう。各時間にどのくらい充放電すればよいかが決まりました。そして月間の最大電力消費量は185.980に抑えられることがわかりました。
5.参考情報
- テスト環境
- Modeler 18.4
- Windows 11 64bit
サンプルストリーム
電力ピーク最適化3.str
利用データ
右クリックでリンク先を保存してください。
demand0501.csv
過去電力需要.csv
【リレー連載】わたしの推しノード –最強のラスボス「CPELXの最適化ノード」が予測の次の最終ステージで実力を解放 | IBM ソリューション ブログ
こちらはシフト作成で「CPELXの最適化ノード」使っている記事です。
ノードのヘルプ
SPSS Modeler 逆引きストリーム集(データ加工)
SPSS Modeler ノードリファレンス目次