mcpField
C
cuopt-numerical-optimization-api-python

cuopt-numerical-optimization-api-python

github.com/nvidiaデータ・データベース3.8k1.7k 回インストール今日更新
リポジトリ

cuopt-numerical-optimization-api-python について

cuopt-numerical-optimization-api-pythonは、NVIDIA cuOptのPython APIで最適化問題をモデル化し、解くためのスキルです。LP、MILP、QPの選択や定式化、ソルバー状態の確認、一般的なモデル化問題の診断を開発者向けに案内します。

主な機能

  1. 01LP、MILP、QPモデルの構築
  2. 02目的関数と変数に基づく問題種別の選択
  3. 03ソルバーパラメーターと時間制限の設定
  4. 04求解状態とLP/QPの双対値の確認
  5. 05モデル化パターンと参考例の利用

活用シーン

  1. 01資源制約下での生産計画
  2. 02施設選択や人員割り当てなどの離散的な判断
  3. 03ポートフォリオ分散や最小二乗問題の求解

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/nvidia/skills --skill cuopt-numerical-optimization-api-python

インストール後、Claude Code で/cuopt-numerical-optimization-api-pythonを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

BENCHMARK.md
skill-card.md
skill.oms.sig
assets/
README.md
assets/least_squares/
model.py
README.md
assets/lp_basic/
model.py
README.md
assets/lp_duals/
model.py
README.md
assets/lp_warmstart/
model.py
README.md
assets/maximization_workaround/
model.py
README.md
assets/milp_basic/
incumbent_callback.py
model.py
README.md
assets/milp_production_planning/
model.py
README.md
assets/mps_solver/
model.py
README.md
results.md
assets/mps_solver/data/
README.md
sample.mps
assets/portfolio/
model.py
README.md
benchmark/
evals.json
SOURCES.md
evals/
evals.json
references/
qp_examples.md

詳細

cuOpt 数値最適化スキル(Python)

NVIDIA cuOpt の GPU アクセラレーション対応ソルバーを使用して、LP、MILP、QP の問題をモデル化して解きます。Python API の構成(Problem、SolverSettings、solve)は3種類の問題クラスで共通であり、異なるのは目的関数の形式といくつかのルールだけです。

開始する前に

利用可能であれば定式化の概要(パラメーター、制約、決定変数、目的関数)を使用してください。ない場合は、決定変数、目的関数、制約を尋ねてください。その後、問題の種類(LP/MILP/QP — 以下を参照)と変数の型を確認してください。

LP、MILP、QP の選び方

目的関数と変数から判断します。

目的関数が……変数が……使用するもの
線形(c_i * x_i の合計)すべて連続変数LP
線形整数変数またはバイナリ変数を含むMILP
二乗(x*x)または交差(x*y)項を含む連続変数(整数 QP はサポートされません)QP(ベータ版)

問題が許す場合は、LP を優先してください。LP はより速く解け、最適性の保証も強力です。問題の性質上、整数値やはい/いいえの判断が必要な場合に限り、MILP を使用してください。目的関数が真に二次形式(分散、二乗誤差、運動エネルギー)の場合に限り、QP を使用してください。

特に注意が必要な問題の種類: 複数期間の計画と目標計画は、誤解しやすい問題です。レートと制約が適切な期間または優先度に適用されていることを再確認してください(AGENTS.md:コードを書く前に理解を確認してください)。

  • LP を使用するのは、すべての量を意味のある形で小数にできる場合です。例:フロー、比率、レート、金額、時間、材料のトン数など。
  • MILP を使用するのは、問題に離散的な対象の個数、はい/いいえの選択、またはどちらか一方の判断が含まれる場合です(例:施設を開設するかどうか、人をシフトに割り当てる、トラックの台数)。
  • QP を使用するのは、目的関数で分散、二乗誤差、または x*x や x*y 項を含む式を最小化する場合です(ポートフォリオ最適化、最小二乗法、正則化回帰)。

説明から整数変数か連続変数かを判断する

問題で説明されている内容に基づいて、変数の型を選んでください。

問題の説明/概念変数の型例
離散的な対象(個数)INTEGER作業員、自動車、トラック、機械、パイロット、施設、製造するユニット(「ユニット」が個別の品目を意味する場合)、研修生、車両
はい/いいえ、またはオン/オフINTEGER(バイナリ、lb=0 ub=1)施設を開設する、機械を稼働させる、製品ラインを生産する、人をシフトに割り当てる
小数にできる量CONTINUOUSトン、リットル、金額、時間、kWh、容量に対する割合、フロー量、重量
レートまたは割合CONTINUOUS利用率、パーセンテージ、予算に占める割合
不明確名詞が数えられるもの(作業員、自動車など)なら INTEGER を優先し、測定量(鋼材の量、労働時間など)なら CONTINUOUS を優先してください。「全体の」「整数の」「個数」と明示されている場合は INTEGER を使用します。

目安: 量が「いくつの もの か」(人、車両、品目、場所)を示すなら、INTEGER を使用してください。「どれだけの量か」(質量、体積、金額、時間)を示す場合、またはレートの場合は、問題で整数値が明示的に求められていない限り、CONTINUOUS を使用してください。

クイックリファレンス:Python API

LP の例
from cuopt.linear_programming.problem import Problem, CONTINUOUS, MAXIMIZE
from cuopt.linear_programming.solver_settings import SolverSettings

# Create problem
problem = Problem("MyLP")

# Decision variables
x = problem.addVariable(lb=0, vtype=CONTINUOUS, name="x")
y = problem.addVariable(lb=0, vtype=CONTINUOUS, name="y")

# Constraints
problem.addConstraint(2*x + 3*y <= 120, name="resource_a")
problem.addConstraint(4*x + 2*y <= 100, name="resource_b")

# Objective
problem.setObjective(40*x + 30*y, sense=MAXIMIZE)

# Solve
settings = SolverSettings()
settings.set_parameter("time_limit", 60)
problem.solve(settings)

# Check status (CRITICAL: use PascalCase!)
if problem.Status.name in ["Optimal", "PrimalFeasible"]:
    print(f"Objective: {problem.ObjValue}")
    print(f"x = {x.getValue()}")
    print(f"y = {y.getValue()}")
MILP の例(整数変数を含む)
from cuopt.linear_programming.problem import Problem, CONTINUOUS, INTEGER, MINIMIZE

problem = Problem("FacilityLocation")

# Binary variable (integer with bounds 0-1)
open_facility = problem.addVariable(lb=0, ub=1, vtype=INTEGER, name="open")

# Continuous variable
production = problem.addVariable(lb=0, vtype=CONTINUOUS, name="production")

# Linking constraint: can only produce if facility is open
problem.addConstraint(production <= 1000 * open_facility, name="link")

# Objective: fixed cost + variable cost
problem.setObjective(500*open_facility + 2*production, sense=MINIMIZE)

# MILP-specific settings
settings = SolverSettings()
settings.set_parameter("time_limit", 120)
settings.set_parameter("mip_relative_gap", 0.01)  # 1% optimality gap

problem.solve(settings)

# Check status
if problem.Status.name in ["Optimal", "FeasibleFound"]:
    print(f"Open facility: {open_facility.getValue() > 0.5}")
    print(f"Production: {production.getValue()}")
QP の例(ベータ版 — MINIMIZE のみ)
from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
from cuopt.linear_programming.solver_settings import SolverSettings

# Portfolio variance minimization
problem = Problem("Portfolio")
x1 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_a")
x2 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_b")
x3 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_c")

# Quadratic objective (variance) — MUST be MINIMIZE
problem.setObjective(
    0.04*x1*x1 + 0.02*x2*x2 + 0.01*x3*x3
    + 0.02*x1*x2 + 0.01*x1*x3 + 0.016*x2*x3,
    sense=MINIMIZE,
)

# Linear constraints
problem.addConstraint(x1 + x2 + x3 == 1, name="budget")
problem.addConstraint(0.12*x1 + 0.08*x2 + 0.05*x3 >= 0.08, name="min_return")

problem.solve(SolverSettings())
if problem.Status.name in ["Optimal", "PrimalFeasible"]:
    print(f"Variance: {problem.ObjValue}")

QP のルール:

  • MINIMIZE のみ — 二次目的関数で MAXIMIZE を指定すると、ソルバーは拒否します。f(x) を最大化するには、-f(x) を最小化してください。
  • 連続変数のみ — 整数 QP はサポートされていません。
  • 凸問題では Q は PSD(半正定値)である必要があります。そうでない場合、ソルバーが最適ではない停留点を返すことがあります。
  • ベータ版 — API は変更される可能性があります。一般的な凸 QP では本番環境で利用できる品質として扱えますが、時折変更があることを想定してください。

最小二乗法、最大化の代替方法、行列形式の例については、references/qp_examples.md を参照してください。

重要:ステータスの確認

ステータス値には PascalCase を使用します。すべて大文字ではありません:

# ✅ CORRECT
if problem.Status.name in ["Optimal", "FeasibleFound"]:
    print(problem.ObjValue)

# ❌ WRONG - will silently fail!
if problem.Status.name == "OPTIMAL":  # Never matches!
    print(problem.ObjValue)

LP のステータス値: Optimal、NoTermination、NumericalError、PrimalInfeasible、DualInfeasible、IterationLimit、TimeLimit、PrimalFeasible

MILP のステータス値: Optimal、FeasibleFound、Infeasible、Unbounded、TimeLimit、NoTermination

QP のステータス値: LP と同じです。QP のデバッグでは、f"Actual status: '{problem.Status.name}'" を出力し、Q が PSD であることと、変数のスケールが適切であることを確認してください。

よくあるモデリングパターン

バイナリ選択
# Select exactly k items from n
items = [problem.addVariable(lb=0, ub=1, vtype=INTEGER) for _ in range(n)]
problem.addConstraint(sum(items) == k)
Big-M によるリンク
# If y=1, then x <= 100; if y=0, x can be anything up to M
M = 10000
problem.addConstraint(x <= 100 + M*(1 - y))
「〜するなら、〜も必ず生産する」という条件

問題文に「X を行うなら Y も必ず行う」とある場合は、(i)バイナリ変数のリンクと(ii)Y が実際に生産されることの両方を制約してください:

# y_X <= y_Y (if we do X, we must "do" Y)
problem.addConstraint(y_X <= y_Y)
# Production of Y when Y is chosen: produce at least 1 (or a minimum) when y_Y=1
problem.addConstraint(production_Y >= 1 * y_Y)  # or min_amount * y_Y

そうしないと、ソルバーは y_Y=1 かつ production_Y=0 に設定できてしまい、バイナリ変数のリンクは満たすものの、本来の意図に沿わない結果になります。

大きな式の構築

多数の項を + で連結すると、API の再帰制限に達することがあります。目的関数と制約の構築には、LinearExpression を使用してください:

from cuopt.linear_programming.problem import LinearExpression

# Build as list of (vars, coeffs) instead of v1*c1 + v2*c2 + ...
vars_list = [x, y, z]
coeffs_list = [
    1.0,
    2.0,
    3.0,
]
expr = LinearExpression(vars_list, coeffs_list, constant=0.0)
problem.addConstraint(expr <= 100)

例については、このスキルの assets/ にある参照モデルを参照してください。

区分線形(SOS2)
# Approximate nonlinear function with breakpoints
# Use lambda variables that sum to 1, at most 2 adjacent non-zero

ソルバーの設定

settings = SolverSettings()

# Time limit
settings.set_parameter("time_limit", 60)

# MILP gap tolerance (stop when within X% of optimal)
settings.set_parameter("mip_relative_gap", 0.01)

# Logging
settings.set_parameter("log_to_console", 1)

よくある問題

問題考えられる原因解決方法
ステータスが常に "OPTIMAL" になる大文字・小文字の指定が誤っている"OPTIMAL" ではなく "Optimal" を使用する
整数変数の値が小数になるCONTINUOUS として定義されているvtype=INTEGER を使用する
実行不可能制約が競合している制約のロジックを確認する
非有界上下限が設定されていない変数の上下限を追加する
解くのに時間がかかる問題が大きい時間制限を設定し、ギャップ許容値を大きくする
最大再帰深度大きな式を + で連結しているLinearExpression(vars_list, coeffs_list, constant) を使用する
MAXIMIZE を指定した QP が拒否されるQP は MINIMIZE のみをサポートしている目的関数を反転し、-f(x) を最小化する
QP が最適解を返さないQ が PSD でない、または変数のスケールが適切でないQ が PSD であることを確認し、変数のスケールを同程度に調整する

双対値の取得(LP/QP)

双対値と縮約費用は LP と QP で返されます。二次制約を含む問題では返されず(すべての値が NaN になります)、制約がすべて線形の場合にのみ取得してください。MILP では双対値は返されません。

if problem.Status.name == "Optimal":
    constraint = problem.getConstraint("resource_a")   # linear constraint
    print(f"Dual value: {constraint.DualValue}")       # NaN if the model has quadratic constraints

参照モデル

すべての参照モデルは、このスキルの assets/ ディレクトリにあります。新しいアプリケーションを構築する際の参考にしてください。参照モデル自体は編集しないでください。

最小/標準的な例(LP、MILP、QP)
モデル種類説明
lp_basicLP最小限の LP:変数、制約、目的関数、求解
lp_dualsLP双対値と縮約費用
lp_warmstartLP類似問題のための PDLP ウォームスタート
milp_basicMILP最小限の MIP。暫定解コールバックの例を含む
milp_production_planningMILPリソース制約を含む生産計画
portfolioQPポートフォリオの分散を最小化。予算と最小リターンの制約を含む
least_squaresQP(x-3)² + (y-4)² を最小化(最も近い点)
maximization_workaroundQP-f(x) を最小化して二次関数を最大化
その他の参照モデル
モデル種類説明
mps_solverLP/MILP標準 MPS ファイル形式の任意の問題を解く

モデルを一覧表示する簡単なコマンド: ls assets/(このスキルのディレクトリから実行)。

エスカレーションする場合

次の場合は、トラブルシューティングと診断のガイダンスを利用してください:

  • 実行不可能で、その理由を特定できない
  • 数値上の問題がある

コメント