Gurobi チュートリアル - C++ API の概要

C++ API の概要

  このセクションでは、Gurobi C++ インターフェイスを紹介します。このマニュアルは、インターフェイスで公開されるクラスと、これらのクラスの最も重要なメソッドの簡単な概要から始まります。その後、利用可能なすべてのクラスとメソッドの包括的な紹介が続きます。

  Gurobi Optimizer を初めて使用する場合は、クイック スタート ガイドまたはサンプル チュートリアルから始めることをお勧めします。これらのドキュメントでは、ここで説明するクラスとメソッドの使用方法の具体的な例が提供されます。

環境Environment

  Gurobi C++ インターフェイスを使用する最初のステップは、環境オブジェクトを作成することです。GRBEnv クラスを使用して環境を表します。環境は、一連の最適化実行に関連するすべてのデータのコンテナーとして機能します。通常、プログラムに必要な環境オブジェクトは 1 つだけです。

  より高度な使用例では、空の環境で初期化されていない環境を作成し、特定の要件に必要なすべてのオプションをプログラムで設定できます。詳細については、「環境」セクションを参照してください。

モデル

  環境内に 1 つ以上の最適化モデルを作成できます。各モデルは GRBModel クラスのオブジェクトとして表されます。モデルは、一連の決定変数 (GRBVar クラスのオブジェクト)、これらの変数の線形または二次目的関数 (GRBModel::setObjective を使用して指定)、およびこれらの変数に対する一連の制約 (GRBConstr、GRBQConstr、GRBSOS クラスのオブジェクト) で構成されます。 、または GRBGenConstr) 。各変数には、下限値、上限値、タイプ (連続、バイナリなど) が関連付けられています。各線形または二次制約には、関連する意味 (以下、以上、または等しい) と右側の値があります。変数、制約、目標の詳細については、このセクションを参照してください。

  線形制約は、線形式 (GRBLinExpr クラスのオブジェクト) を構築し、これらの式間の関係を指定することによって指定されます (たとえば、ある式が別の式と等しい必要があります)。二次制約も同様の方法で構築されますが、二次式 (GRBQuadExpr クラスのオブジェクト) を使用します。

  最適化モデルを指定するには、(適切な GRBModel コンストラクターを使用して) ファイルからすべてを一度にロードするか、最初に GRBModel クラスの空のオブジェクトを構築してから GRBModel::addVar または GRBModel::addVars を呼び出して追加の変数を追加します。 GRBModel::addConstr、GRBModel::addQConstr、GRBModel::addSOS、または任意の GRBModel::addGenConstrXxx メソッドを使用して制約を追加します。モデルは動的なエンティティであるため、いつでも変数や制約を追加または削除できます。

  モデルを最適化するクラスをよく指します。線形目的関数、線形制約、および連続変数を備えたモデルは、線形計画法 (LP) です。目的が 2 次の場合、モデルは 2 次計画法 (QP) になります。制約が 2 次である場合、モデルは 2 次制約手続き (QCP) です。QCP の特殊なケースとして、凸制約のある QCP、非凸制約のある QCP、双線形計画法、および 2 次円錐計画法 (SOCP) について言及することがあります。モデルに整数変数、半連続変数、半整数変数、特別順序セット (SOS) 制約、または一般制約が含まれている場合、そのモデルは混合整数プログラム (MIP) です。また、混合整数線形計画法 (MILP)、混合整数二次計画法 (MIQP)、混合整数二次制約計画法 (MIQCP)、混合整数 2 次円錐計画法 (MISOCP) などの MIP の特殊なケースについても議論することがあります。Gurobi オプティマイザーは、これらすべてのモデル クラスを処理します。

モデルを解く モデルを解く

  モデルを構築した後、GRBModel::optimize を呼び出して解を計算できます。デフォルトでは、optimize は同時オプティマイザーを使用して LP モデルを解決し、バリア アルゴリズムを使用して凸目標を持つ QP モデルと凸制約を持つ QCP モデルを解決し、それ以外の場合はブランチ アンド カット アルゴリズムを使用します。解はモデルの一連のプロパティに保存されます。これらのプロパティは、GRBModel、GRBVar、GRBConstr、GRBQConstr、GRBSOS、および GRBGenConstr クラスのプロパティ クエリ メソッドのセットを使用してクエリできます。

  Gurobi アルゴリズムはモデルの状態を注意深く追跡するため、GRBModel::optimize の呼び出しは、モデルが最後に最適化されてから関連データが変更された場合にのみさらなる最適化を実行します。以前に計算された解情報を破棄し、モデルを変更せずに最適化を最初から開始したい場合は、GRBModel::reset を呼び出すことができます。

  MIP モデルを解決した後、GRBModel::fixedModel を呼び出して、関連する固定モデルを計算できます。このモデルは、整数変数が MIP ソリューションの値に固定されていることを除いて、元のモデルと同一です。モデルに SOS 制約が含まれている場合、これらの制約に表示される連続変数の一部も固定される可能性があります。一部のアプリケーションでは、この固定モデルに関する情報 (二重変数、感度情報など) を計算すると便利な場合がありますが、この情報をどのように解釈するかには注意する必要があります。

複数のソリューション、目的、シナリオ

  デフォルトでは、Gurobi オプティマイザーは、単一の目的関数を持つ単一のモデルに対して実証済みの最適なソリューションを見つけることが目標であると想定します。Gurobi は、これらの前提を緩和できる次の機能を提供します。

  • ソリューション プール: より多くのソリューションを見つけることができます。
  • 複数のシナリオ: 複数の関連モデルのソリューションを見つけることができます。
  • 複数の目的: 複数の目的関数を指定し、それらの間のトレードオフを制御できます。

実現不可能なモデル

  モデルが実現不可能であることが判明した場合、いくつかの選択肢があります。操作不能の原因の診断、操作不能の修正、またはその両方を試みることができます。実行不可能の原因の診断に使用できる情報を取得するには、GRBModel::computeIIS を呼び出して、還元不可能な不整合サブシステム (IIS) を計算します。この方法は連続モデルと MIP モデルの両方で使用できますが、MIP バージョンは非常に高価になる可能性があることに注意してください。このメソッドは、IIS プロパティのセットを設定します。

  実現不可能性を修正するには、GRBModel::feasRelax を呼び出してモデルの実現可能性緩和を計算します。この緩和により、制約違反の大きさを最小限に抑える解決策を見つけることができます。

属性のクエリと変更属性のクエリと変更

  Gurobi モデルに関連する情報のほとんどは、一連のプロパティに保存されます。一部のプロパティはモデルの変数に関連付けられ、一部はモデルの制約に関連付けられ、一部はモデル自体に関連付けられます。簡単な例として、最適化モデルを解決すると、X 変数属性が設定されます。Gurobi オプティマイザーによって計算される X などのプロパティはユーザーが直接変更できませんが、変数の下限 (LB プロパティ) などの他のプロパティは変更できます。

  GRBVar::get、GRBConstr::get、GRBQConstr::get、GRBSOS::get、GRBGenConstr::get、または GRBModel::get を使用して属性をクエリし、GRBVar::set、GRBConstr::set、GRBQConstr を使用して以下を変更します。 : セット、GRBGenConstr::set または GRBModel::set。属性はタイプごとに列挙型のセット (GRB_CharAttr、GRB_DoubleAttr、GRB_IntAttr、GRB_StringAttr) にグループ化されます。get() メソッドと set() メソッドはオーバーロードされるため、プロパティの型によって戻り値の型が決まります。したがって、constr.get(GRB.DoubleAttr.RHS) は double を返しますが、constr.get(GRB.CharAttr.Sense) は文字を返します。

  変数または制約のセットのプロパティ値を取得する場合は、通常、関連付けられた GRBModel オブジェクトの配列メソッドを使用する方が効率的です。GRBModel::get メソッドには、変数または制約配列のプロパティ値をクエリまたは変更できるようにするシグネチャが含まれています。

プロパティの完全なリストは、プロパティ セクションの追加のモデル変更情報にあります。

  既存のモデルに対するほとんどの変更は、プロパティ インターフェイスを通じて行われます (変数の範囲の変更、制約の右側など)。主な例外は、制約行列と目的関数の変更です。

  制約行列はいくつかの方法で変更できます。1 つ目は、GRBModel オブジェクトの chgCoeffs メソッドを呼び出して、個々の行列係数を変更することです。このメソッドは、既存の非ゼロ値を変更したり、既存の非ゼロ値をゼロに設定したり、新しい非ゼロ値を作成したりするために使用できます。モデルから変数または制約を (GRBModel::remove メソッド経由で) 削除すると、制約行列も変更されます。削除された制約または変数に関連付けられたゼロ以外の値は、制約または変数自体とともに削除されます。

  モデルの目的関数は、いくつかの方法で変更することもできます。最も簡単な方法は、ターゲット関数をキャプチャする式 (GRBLinExpr または GRBQuadExpr オブジェクト) を構築し、その式をメソッド GRBModel::setObjective に渡すことです。ターゲットを変更する場合は、新しい GRBLinExpr または GRBQuadExpr オブジェクトを使用して setObjective を再度呼び出すだけです。

  線形目的関数の場合、setObjective の代わりに、Obj 変数プロパティを使用して個々の線形目的関数を変更することもできます。

  変数に区分線形目標がある場合は、GRBModel::setPWLObj メソッドを使用して指定できます。このメソッドは、関連する変数ごとに 1 回呼び出されます。Gurobi シンプレックス ソルバーには、凸区分線形目的関数のアルゴリズム サポートが含まれているため、連続モデルの場合、この機能を使用するとパフォーマンスが大幅に向上するはずです。以前に指定した区分線形目的関数をクリアするには、対応する変数の Obj プロパティを 0 に設定するだけです。

遅延アップデート 遅延アップデート

  Gurobi オプティマイザーでのモデルの変更に関して注意すべき重要な点は、変更が遅延的に実行されるということです。つまり、変更はモデルにすぐには影響しません。代わりに、それらはキューに入れられ、後で適用されます。プログラムがモデルを作成してそれを解決するだけの場合は、この動作に気付かない可能性があります。ただし、変更を適用する前にモデルに関する情報を知りたい場合には、遅延更新方法の詳細が関係する可能性があります。

  先ほど述べたように、モデルの変更 (バインディングの変更、右側の変更、ターゲットの変更など) はキューに入れられます。これらのキューに入れられた変更は、3 つの異なる方法でモデルに適用できます。1 つ目は、GRBModel::update を明示的に呼び出すことです。2 つ目は、GRBModel::optimize を呼び出すことです。3 番目の方法は、GRBModel::write を呼び出してモデルを書き出すことです。最初のケースでは、いつ変更を適用するかをきめ細かく制御できます。2 番目と 3 番目は、モデルを最適化するかディスクに書き込む前に、保留中の変更をすべて適用することを前提としています。

  なぜGurobiインターフェースはこのように動作するのでしょうか? 理由はいくつかあります。1 つ目は、このアプローチでは、変更間でモデルが変更されないため、モデルに対して複数の変更を実行することが容易になるということです。2 つ目は、特に変更にマシン間の通信が必要なコンピューティング サーバー環境では、モデルの変更の処理にコストがかかる可能性があることです。したがって、これらの変更をいつ適用するかを正確に知っておくと役立ちます。一般に、プログラムでモデルに複数の変更が必要な場合は、一連の変更を行ってから更新し、さらに変更を行ってから再度更新するというように、段階的に行う必要があります。全員が参加した後に変更を更新すると、非常にコストがかかる可能性があります。

  update の呼び出しを忘れてもプログラムはクラッシュしません。クエリは、最後に更新されたときに要求されたデータの値のみを返します。クエリしようとしているオブジェクトが存在しない場合は、NOT_IN_MODEL 例外が発生します。

  遅延更新のセマンティクスは、Gurobi の初期バージョンから変更されました。大部分のプログラムはこの変更の影響を受けませんが、問題が発生した場合は、UpdateMode パラメーターを使用して以前の動作に戻すことができます。

パラメータの管理パラメータの管理

  Gurobi オプティマイザーは、最適化プロセスの多くの詳細を制御できるパラメーターのセットを提供します。実現可能性と最適性の許容誤差、アルゴリズムの選択、MIP 検索ツリーを探索するための戦略などの要素は、最適化を開始する前に Gurobi パラメーターを変更することで制御できます。パラメータのタイプは、int、double、または string です。

  パラメータを設定する最も簡単な方法は、モデル オブジェクトの GRBModel::set メソッドを使用することです。同様に、パラメータ値は GRBModel::get を使用してクエリできます。

  GRBEnv::set を使用して、Gurobi 環境オブジェクトのパラメーターを設定することもできます。各モデルは作成時に環境の独自のコピーを取得するため、元の環境に対するパラメーターの変更は既存のモデルに影響を与えないことに注意してください。

  GRBEnv::readParams を使用してファイルからパラメータ設定のセットを読み取ることも、GRBEnv::writeParams を使用して変更されたパラメータのセットを書き込むこともできます。

  また、さまざまなパラメーター変更セットを調査して、パフォーマンスを向上させるセットを見つける自動パラメーター チューニング ツールも含まれています。GRBModel::tune を呼び出して、モデルのチューニング ツールを呼び出すことができます。詳細については、「パラメータ調整ツール」セクションを参照してください。

  Gurobi パラメータの完全なリストは「パラメータ」セクションにあります。

メモリ管理メモリ管理

  C++ プログラムでは、メモリ管理を常に考慮する必要があります。特に、Gurobi ライブラリとユーザー プログラムは同じ C++ ヒープを共有するため、ユーザーは Gurobi ライブラリがヒープを使用する方法についていくつかの側面を理解する必要があります。Gurobi オプティマイザーを使用する場合のメモリ管理の基本ルールは次のとおりです。

  • 動的に割り当てられた他の C++ オブジェクトと同様に、GRBEnv または GRBModel オブジェクトは、関連付けられたデストラクターを使用して解放される必要があります。言い換えれば、GRBModel オブジェクト m が与えられた場合、m を使用しなくなった場合は delete m を呼び出す必要があります。
  • GRBConstr、GRBQConstr、GRBSOS、GRBGenConstr、GRBVar オブジェクトなど、モデルに関連付けられたオブジェクトはモデルによって管理されます。特に、モデルを削除すると、関連するオブジェクトがすべて削除されます。同様に、(GRBModel::remove を使用して) モデルからオブジェクトを削除すると、そのオブジェクトも削除されます。
  • 一部の Gurobi メソッドはオブジェクトまたは値の配列を返します。たとえば、GRBModel::addVars は GRBVar オブジェクトの配列を返します。返された配列を解放するのはユーザーの責任です (delete[] を使用します)。リファレンス マニュアルには、メソッドがヒープ割り当て結果を返すタイミングが示されています。

  これらのルールの結果の 1 つは、オブジェクトが解放された後はそのオブジェクトを使用しないよう注意する必要があるということです。これは、デストラクターが明示的に呼び出される環境やモデルの場合は確かに非常に明確ですが、制約や変数の場合は、関連するモデルが削除されると暗黙的に削除されるため、それほど明確ではない場合があります。

進行状況の監視 - ログとコールバック進行状況の監視 - ログとコールバック

  最適化の進行状況は、Gurobi ログを通じて記録できます。デフォルトでは、Gurobi は出力を画面に送信します。デフォルトのロギング動作を変更するために、いくつかの簡単なコントロールを使用できます。出力を画面だけでなくファイルに送りたい場合は、GRBEnv コンストラクターでログ ファイル名を指定します。環境オブジェクトの作成後にログを別のファイルにリダイレクトする場合は、LogFile パラメーターを変更できます。DisplayInterval パラメータを使用して出力をログに記録する頻度を制御でき、OutputFlag パラメータを使用してログを完全にオフにすることができます。Gurobi ログ ファイルの詳細な説明は、「ログ」セクションにあります。

  より詳細な進行状況の監視は、GRBCallback クラスを通じて実行できます。GRBModel::setCallback メソッドを使用すると、Gurobi オプティマイザーから定期的にコールバックを受信できます。これを行うには、GRBCallback 抽象クラスをサブクラス化し、そのクラスに独自の callback() メソッドを記述します。コールバックで GRBCallback::getDoubleInfo、GRBCallback::getIntInfo、GRBCallback::getStringInfo、または GRBCallback::getSolution を呼び出して、最適化ステータスに関する追加情報を取得できます。

ソルバーの動作の変更 - コールバック ソルバーの動作の変更 - コールバック

  コールバックを使用して、Gurobi オプティマイザーの動作を変更することもできます。最も単純なコントロール コールバックは GRBCallback::abort です。これには、オプティマイザが最も早い都合の良い時点で終了する必要があります。GRBCallback::setSolution メソッドを使用すると、MIP モデルの解決中に実行可能な解決策 (または部分的な解決策) を注入できます。メソッド GRBCallback::addCut および GRBCallback::addLazy を使用すると、MIP 最適化中にそれぞれ切断面と遅延制約を追加できます。メソッド GRBCallback::stopOneMultiObj を使用すると、階層最適化プロセスを停止せずに、多目的 MIP 問題の最適化ステップの 1 つの最適化プロセスを中断できます。

バッチの最適化

  Gurobi Compute Server を使用すると、プログラムは最適化計算を専用サーバーにオフロードできます。Gurobi Cluster Manager はこの基盤に基づいて構築されており、多くの追加機能が追加されています。重要なバッチ最適化により、クライアント プログラムを使用して最適化モデルを構築し、それを (クラスター マネージャー経由で) 計算サーバーのクラスターに送信し、モデルのステータスをチェックしてそのソリューションを取得できます。Batch オブジェクトを使用すると、バッチをより簡単に処理できます。バッチの詳細については、「バッチの最適化」セクションを参照してください。

エラー処理

  Gurobi C++ ライブラリのすべてのメソッドは、GRBException タイプの例外をスローできます。例外が発生した場合、エラー コードを取得する (GRBException::getErrorCode メソッドを使用)、または例外メッセージを取得する (メソッド GRBException::getMessage を使用) ことにより、エラーに関する追加情報を取得できます。考えられるエラー戻りコードのリストは、「エラー コード」セクションにあります。

おすすめ

転載: blog.csdn.net/qq_16775293/article/details/122707172