Gurobi(グロビ)は、線形計画・整数計画・二次計画・非線形計画を解く商用の数理最適化ソルバーです。Pythonからは公式パッケージのgurobipyで使い、pip install gurobipyの1行で導入できます。ただしpipで入るのは2,000変数までのサイズ制限付きライセンスで、しかも本番利用(商用)はできません。この記事では、gurobipy 13.0.3を実際にインストールして動かした結果をもとに、導入手順・ライセンスと価格・基本のコード・つまずきやすい点を順に説明します。
まとめ:GurobiをPythonで使う要点
- Gurobiとは:2008年設立のGurobi Optimization社が開発する商用ソルバー。LP・MILP・QP・MIQP・QCP・MIQCPに加え、13.0ではNLP・MINLPも扱う。
- インストール:
python -m pip install gurobipy。最新は13.0.3(2026年8月25日)で、対応はPython 3.10〜3.14。Python 3.15ではまだ入らない。 - 無料で使える範囲:pip同梱のライセンスは2,000変数・2,000線形制約(二次項があれば200変数)まで。超えると
optimize()の時点でエラー10010になる。学生・教職員は無制限のアカデミックライセンスを無料で取れる。 - 価格:商用ライセンスの価格は公開されておらず、見積もり制。商用ユーザーには30日間の無料トライアルがある。
- 選ぶ基準:大規模なMIPを業務で解き、サポートも必要ならGurobi。製品に組み込んで無償で配りたいなら、HiGHS・SCIP・OR-Toolsを先に検討する。
以下、Gurobiの位置付けから順に見ていきます。最適化の基本用語(決定変数・目的関数・制約条件)が初めての場合は、先に決定変数・目的関数・制約条件の違いと定式化の手順を読むと、コードの意味を追いやすくなります。
Gurobi(グロビ)とは:商用の数理最適化ソルバー
Gurobiは、目的関数と制約条件で書いた最適化モデルを受け取り、最適解を計算するソフトウェア(ソルバー)です。モデルを書く道具ではなく解く道具なので、PythonではgurobipyのAPIで直接モデルを書くか、PuLPやPyomoのようなモデリングツールから呼び出します。数理最適化そのものの考え方は数理最適化の3要素とアルゴリズムの解説にまとめています。
Gurobiで解ける問題の種類(LP・MIP・二次・非線形)
公式リファレンスは、Gurobi 13.0が扱うモデルとして次の8種類を挙げています。業務で多いのは、生産計画・シフト作成・配送計画のように「何個作るか」「誰を割り当てるか」を整数で決めるMILP(混合整数線形計画)です。
| 略称 | 問題の種類 | 例 |
|---|---|---|
| LP | 線形計画 | 原料の配合比 |
| MILP | 混合整数線形計画 | 生産計画・勤務シフト |
| QP/MIQP | 二次計画(整数を含む) | ポートフォリオの分散最小化 |
| QCP/MIQCP | 二次制約付き計画 | リスク上限付きの配分 |
| NLP/MINLP | 非線形計画(整数を含む) | log・sin・指数を含むモデル |
非線形制約について公式は「大域的最適解を目標に解く」と説明しています。13.0では、整数変数を含まない連続の非線形問題向けに局所最適解を速く探すNLバリア法がプレビューとして入りました(Gurobi 13.0のリリースノート)。
開発元・日本の窓口と対応言語
開発元のGurobi Optimizationは2008年に、Zonghao Gu・Edward Rothberg・Robert Bixbyの3人が設立しました。製品名は3人の姓の最初の2文字(Gu・Ro・Bi)をつなげたものです。日本では総代理店の株式会社オクトーバー・スカイが、2025年10月1日に社名を株式会社Gurobi Japanへ変更しました。日本語の見積もりやサポートの窓口はここです。
13.0.3の対応プラットフォーム表では、PythonのほかC・C++・Java(JDK 8・11・17・21・25)・.NET(8.0/10.0)・MATLAB・Rから使えます。OSはWindows・Linux(x86-64/arm64)・macOS(universal2)です。メジャー版は公開から3年サポートされ、リリースとサポートの履歴では13.0.0(2025年11月)のサポート終了が2028年11月、11.0系は2026年11月に終わります。
GurobiのPython向けインストール手順(pip・conda)
公式サポートのGurobiをPythonへインストールする手順では、pip・conda・オフラインの3通りが案内されています。手元のPythonで試すだけならpipが最短です。Anacondaを使っている場合はconda install -c gurobi gurobiを使います。
pipによるgurobipyの導入と動作確認
64ビット版のPythonで次を実行します。pip版にはライセンス管理ツール(grbgetkey)が含まれないので、Named-Userなどgrbgetkeyでライセンスを取得する方式では、別途ライセンスツールのパッケージかフルインストーラーが要ります。WLSではgrbgetkeyを使わず、ダウンロードしたライセンスファイルを配置できます。
python -m pip install gurobipy
python -c "import gurobipy as gp; print(gp.gurobi.version())"
# (13, 0, 3)
最初にモデルを解くと、ログの1行目にRestricted license - for non-production use only - expires 2027-11-29と出ます。これがpip同梱のサイズ制限ライセンスで、末尾の日付がこのライセンスの有効期限です。
対応するPythonのバージョン(3.15はまだ入らない)
PyPIのgurobipyで配布されている13.0.3のwheelは、CPython 3.10・3.11・3.12・3.13・3.14と、フリースレッド版の3.14tです。2026年10月に出たPython 3.15でpip install gurobipyを実行すると、次のように失敗しました。
ERROR: Could not find a version that satisfies the requirement gurobipy (from versions: none)
ERROR: No matching distribution found for gurobipy
このエラーはパッケージ名の誤りではなく、3.15向けのwheelが無いことが原因です。uvで入れると「cp315のwheelが無い」と理由まで表示されます。2026年9月28日に公開された次期版のベータ14.0.0b1もwheelは3.11〜3.14までで、Python 3.10は対象から外れました。仮想環境を作るときは、当面3.11〜3.14を選ぶのが安全です。
行列API(addMVar)に必要なNumPy・SciPyの追加導入
NumPy配列で係数を渡す行列APIは、numpyとscipyに依存します。gurobipyの依存関係ではこの2つがmatrixapiという追加オプション扱いで、pip install gurobipyだけでは入りません。scipyが無い環境でc @ xのように行列と変数を掛けると、ModuleNotFoundError: No module named 'scipy'で止まりました。行列APIを使う場合は最初から次の形で入れます。
python -m pip install "gurobipy[matrixapi]"
Gurobiのライセンスと価格
Gurobiのライセンスは、無料の3種類と、用途で分かれた有償の商用ライセンスがあります。公式のPricing and Licensingページの内容を整理すると次のとおりです。
無料で使える3つのライセンス
| 種類 | 対象 | 規模の上限 | 商用利用 |
|---|---|---|---|
| サイズ制限ライセンス | 誰でも(pip・conda同梱) | 2,000変数・2,000線形制約 | 不可 |
| アカデミックライセンス | 学位授与機関の学生・教職員 | なし | 不可 |
| 商用の無料トライアル | 企業の評価用 | なし(30日間) | 評価のみ |
サイズ制限ライセンスは学習・試作・評価のための「non-production use(本番以外の用途)」に限られます。社内の業務システムで毎日計画を解く使い方は、モデルが小さくても対象外です。
アカデミックライセンスには、1台のPCに紐づくNamed-Userと、クラウド経由で認証するWLS(Web License Service)があります。どちらも取得時に大学のネットワークから接続する必要があり、WLSは有効期限を延ばすときにも学内ネットワークへの接続が求められます。研究室の共有サーバー向けには、トークンサーバーで管理するAcademic Siteライセンスもあります。
サイズ制限ライセンスの上限と境界値の実測結果
上限ちょうどと1つ超えたモデルを作って解き、どこで止まるかを確かめました。変数を2,000個にしたモデルと2,001個にしたモデルを順に解くコードです。
import gurobipy as gp
from gurobipy import GRB
for n in (2000, 2001):
with gp.Env(params={"OutputFlag": 0}) as env, gp.Model(env=env) as m:
x = m.addVars(n, ub=1.0)
m.setObjective(x.sum(), GRB.MAXIMIZE)
m.addConstr(x.sum() <= 10)
try:
m.optimize()
print(n, "OK", m.ObjVal)
except gp.GurobiError as e:
print(n, e.errno, e)
2000 OK 10.0
2001 10010 Model too large for size-limited license; visit https://gurobi.com/unrestricted for more information
制約と二次項についても同じ方法で確かめた結果が次の表です。
| モデル | 上限ちょうど | 1つ超えた場合 |
|---|---|---|
| 変数(線形) | 2,000個で求解できる | 2,001個でエラー10010 |
| 線形制約 | 2,000本まで | 2,001本でエラー10010 |
| 二次の目的関数 | 200変数で求解できる | 201変数でエラー10010 |
エラーはaddVars()で変数を作った時点ではなく、optimize()を呼んだ時点で出ます。データを全部読み込んでモデルを組み立て終わってから失敗するので、本番に近いデータで試すときは、求解前にm.update()で追加した変数を反映してから、m.NumVarsとm.NumConstrsを確認してください。二次項があるモデルでは変数上限が200個になる点にも注意が必要です。輸送問題なら工場数×店舗数、シフト作成なら人数×日数×シフト種別が変数の数になり、50人×30日×3シフトの4,500変数で上限を超えます。
商用ライセンスの種類と価格の決まり方
商用ライセンスの金額は公式サイトに載っておらず、どの形態も「Request a Quote(見積もり依頼)」です。価格は、どの形態でどれだけ使うかで変わります。
| 形態 | 紐づく対象 | 向いている使い方 |
|---|---|---|
| Named User | 1人の利用者と1台のマシン | 分析者が手元で解く |
| Single-Machine | マシン | サーバーでの定期バッチ |
| WLS | クラウド認証 | Docker・Kubernetes |
| Floating | 社内のトークンサーバー | チームで同時利用 |
| Compute Server | 専用サーバー | 多数のジョブを並列実行 |
| Single-Use | 1台のマシン(同時1求解) | 同時実行の少ない単一サーバー |
| Instant Cloud | AWS・Azure上の実行環境 | 自前サーバーを持たない運用 |
見積もりを取る前に、利用者の人数、実行するマシンの台数とコンテナ利用の有無、同時に解くジョブの数を整理しておくと、形態がすぐ決まります。導入判断の前には、30日間の無料トライアルで自社のモデルを実際に解き、求解時間を測っておくべきです。
gurobipyの使い方:モデル作成から求解まで
gurobipyのコードは「モデルを作る→変数を足す→目的関数を決める→制約を足す→解く→結果を読む」の順で書きます。以下のコードの検証環境は、macOS 26.6.2(Intel)・Python 3.13.14・gurobipy 13.0.3です。出力は求解ログの一部を省略して掲載しています。
生産計画の整数計画モデル(addVar・setObjective・addConstr)
椅子1脚の利益が3,000円、机1台が5,000円で、木材と作業時間に上限がある場合に、利益が最大になる生産数を求めます。
import gurobipy as gp
from gurobipy import GRB
m = gp.Model("production")
x = m.addVar(vtype=GRB.INTEGER, name="chair") # 椅子の生産数
y = m.addVar(vtype=GRB.INTEGER, name="table") # 机の生産数
m.setObjective(3000 * x + 5000 * y, GRB.MAXIMIZE) # 利益を最大化
m.addConstr(2 * x + 4 * y <= 40, name="wood") # 木材は40単位まで
m.addConstr(3 * x + 2 * y <= 30, name="labor") # 作業時間は30時間まで
m.optimize()
if m.Status == GRB.OPTIMAL:
print(m.ObjVal, x.X, y.X)
Restricted license - for non-production use only - expires 2027-11-29
Gurobi Optimizer version 13.0.3 build v13.0.3rc0 (mac64[x86] - Darwin 25.6.0 25G83)
...
Optimal solution found (tolerance 1.00e-04)
Best objective 5.200000000000e+04, best bound 5.200000000000e+04, gap 0.0000%
52000.0 4.0 8.0
椅子4脚・机8台で利益52,000円が最適です。addVarのvtypeを省くと連続変数になり、GRB.BINARYにすると0か1の変数になります。変数の値は.X、目的関数値はm.ObjValで読みます。
添字付き変数による輸送モデル(addVars・quicksum・multidict)
実務のモデルでは「工場×店舗」のような組み合わせごとに変数を作ります。addVarsに添字のリストを2つ渡すと、全組み合わせの変数がtupledictとして返ります。2工場から3店舗へ運ぶ輸送費を最小にする例です。
import gurobipy as gp
from gurobipy import GRB
plants, supply = gp.multidict({"札幌": 30, "大阪": 50})
stores, demand = gp.multidict({"東京": 35, "名古屋": 25, "福岡": 20})
cost = {("札幌", "東京"): 8, ("札幌", "名古屋"): 10, ("札幌", "福岡"): 14,
("大阪", "東京"): 6, ("大阪", "名古屋"): 4, ("大阪", "福岡"): 7}
with gp.Env(params={"OutputFlag": 0}) as env, gp.Model("transport", env=env) as m:
x = m.addVars(plants, stores, name="ship")
m.setObjective(gp.quicksum(cost[p, s] * x[p, s] for p in plants for s in stores), GRB.MINIMIZE)
m.addConstrs((x.sum(p, "*") <= supply[p] for p in plants), name="supply")
m.addConstrs((x.sum("*", s) == demand[s] for s in stores), name="demand")
m.optimize()
print(m.ObjVal)
for (p, s), v in x.items():
if v.X > 1e-6:
print(p, s, v.X)
510.0
札幌 東京 30.0
大阪 東京 5.0
大阪 名古屋 25.0
大阪 福岡 20.0
x.sum(p, "*")は「工場pから出る全店舗分の合計」を表し、制約を1行で書けます。addConstrsはジェネレーター式を受け取って制約をまとめて追加します。gp.Env(params={"OutputFlag": 0})で環境を作ってからモデルを作ると、求解ログだけでなく先ほどのライセンス表示も出なくなります。m.Params.OutputFlag = 0をモデル作成後に設定する方法では、ライセンス表示は止まりませんでした。
データがpandasのDataFrameにある場合は、公式の追加パッケージgurobipy-pandasを使うと、列から変数や制約を作れます。
NumPy配列で書く行列API(addMVar)
係数が行列で手元にあるなら、addMVarで変数のベクトルを作り、@演算子で式を書けます。先ほどの生産計画を行列で書き直すと次のようになります(実行にはgurobipy[matrixapi]が必要です)。
import numpy as np
import gurobipy as gp
from gurobipy import GRB
A = np.array([[2, 4], [3, 2]])
b = np.array([40, 30])
c = np.array([3000, 5000])
with gp.Env(params={"OutputFlag": 0}) as env, gp.Model(env=env) as m:
x = m.addMVar(2, vtype=GRB.INTEGER, name="x")
m.setObjective(c @ x, GRB.MAXIMIZE)
m.addConstr(A @ x <= b)
m.optimize()
print(m.ObjVal, x.X)
52000.0 [4. 8.]
係数を行列として効率よく構築できるモデルでは、行列APIで制約をまとめて追加すると、1本ずつ追加する方法より組み立て時間を短縮できる場合があります。
求解でつまずいたときの確認手順
gurobipyで多い失敗は、解が無いのに値を読もうとして落ちるケースと、実行不能の原因が分からないケースです。
Statusによる終了状態と解の有無の判定
optimize()は解が無くても例外を出さずに終わります。そのままm.ObjValやx.Xを読むと、13.0.3ではAttributeError: Unable to retrieve attribute 'ObjVal'で止まりました。値を読む前にm.Statusを確かめます。
| 定数 | 値 | 意味 |
|---|---|---|
| GRB.OPTIMAL | 2 | 最適解が見つかった |
| GRB.INFEASIBLE | 3 | 制約を全部満たす解が無い |
| GRB.INF_OR_UNBD | 4 | 実行不能か非有界のどちらか |
| GRB.UNBOUNDED | 5 | 目的関数をいくらでも良くできる |
| GRB.TIME_LIMIT | 9 | 時間制限で打ち切った |
| GRB.LOCALLY_OPTIMAL | 18 | 局所最適解(13.0のNLバリア法) |
TIME_LIMITで打ち切った場合も、それまでに見つかった解があれば値を読めます。解の有無はm.SolCountが1以上かどうかで判定します。
computeIISによる実行不能原因の絞り込み
制約が矛盾しているとStatusが3(INFEASIBLE)になります。computeIIS()を呼ぶと、制約や変数の上下限から、どの要素を1つ除いても実行可能になる既約な実行不能部分系(IIS)を特定できます。ただし、要素数が最少の組とは限りません。サイズ制限ライセンスでも使えました。
import gurobipy as gp
from gurobipy import GRB
with gp.Env(params={"OutputFlag": 0}) as env, gp.Model(env=env) as m:
x = m.addVar(name="x")
y = m.addVar(name="y")
m.addConstr(x + y >= 10, name="need")
m.addConstr(x <= 3, name="capx")
m.addConstr(y <= 4, name="capy")
m.setObjective(x + y, GRB.MINIMIZE)
m.optimize()
print(m.Status)
if m.Status == GRB.INFEASIBLE:
m.computeIIS()
print([c.ConstrName for c in m.getConstrs() if c.IISConstr])
3
['need', 'capx', 'capy']
「合計10以上」と「xは3以下・yは4以下」が両立しないことが分かります。IISに含まれる制約や変数の上下限を調べると、矛盾に関係するデータを絞り込めます。m.write("model.lp")でモデルをLP形式のテキストに書き出すと、制約を目で確認できます。
TimeLimit・MIPGapによる求解終了条件の設定
大きな整数計画は、最適性の証明までに長い時間がかかることがあります。業務では「10秒以内」「最適値との差1%以内」で打ち切る設定がよく使われます。60品目のナップサック問題で試したコードです。
import random
import gurobipy as gp
from gurobipy import GRB
random.seed(0)
n = 60
w = [random.randint(10, 60) for _ in range(n)] # 重さ
v = [random.randint(10, 90) for _ in range(n)] # 価値
with gp.Env(params={"OutputFlag": 0}) as env, gp.Model(env=env) as m:
m.Params.TimeLimit = 10 # 10秒で打ち切る
m.Params.MIPGap = 0.01 # 上界との差が1%以内なら終了
x = m.addVars(n, vtype=GRB.BINARY)
m.setObjective(gp.quicksum(v[i] * x[i] for i in range(n)), GRB.MAXIMIZE)
m.addConstr(gp.quicksum(w[i] * x[i] for i in range(n)) <= 500)
m.optimize()
if m.SolCount > 0:
print(m.Status, m.ObjVal, m.ObjBound, m.MIPGap)
else:
print(m.Status, "実行可能解は未発見")
2 1353.0 1353.0 0.0
ObjVal(見つかった解の値)とObjBound(これ以上は良くならない上界)が一致しているので、この規模では最適性まで証明できています。打ち切った場合は両者の差がMIPGapに残るので、解の品質を数字で説明できます。
Gurobi 13.0の主な変更点と14.0ベータ
現行の13.0系(13.0.0は2025年11月)で、Python利用者に関係する変更は次の3つです。
- NLバリア法(プレビュー):連続の非線形問題の局所最適解を、大域ソルバーより速く探す。
OptimalityTarget=1で有効にし、結果はLOCALLY_OPTIMALで返る。 - PDHG法:大規模なLP向けの一次法。
Method=6で指定し、13.0.2からNVIDIA GPUでの実行が正式機能になった。GPUで動かせるのはLinux(x86-64/arm64)で、NVIDIA製GPUとドライバーが前提になる。 - tuplelist.select()の警告:13.0.2から、引数が足りない呼び出しに非推奨の警告が出る。
次期メジャーの14.0は、PyPIで2026年9月28日にベータ版の14.0.0b1が公開されています。対応PythonがPython 3.11以上に変わったので、3.10で動かしている環境は14.0へ上げる前にPythonの更新が必要です。正式版の公開時期は発表されていません。
Gurobiを選ぶ場面・選ばない場面
Gurobiが向いているのは、変数が数万〜数百万の整数計画を業務で繰り返し解き、求解時間とベンダーサポートにお金を払う価値がある場合です。逆に、次の場合はGurobiを第一候補にしません。
- 自社製品に組み込んで顧客に無償で配る:組み込みや再配布の可否と条件はGurobiとの契約で決まるので、事前の確認が要る。無償で再配布できるソルバーを選ぶならHiGHSやSCIP(Apache 2.0)が候補になる。HiGHSのソースはMITだが、HiPOを含む配布バイナリはApache 2.0になるため、再配布する構成のライセンスを確認する。SCIPをPythonから使う手順はSCIPソルバーとPySCIPOptの使い方で解説している。
- 変数が数百程度で速度が問題にならない:無料ソルバーで自社モデルの求解時間を測り、業務の時間制約を満たすか確かめる。PuLP 4はソルバーを同梱しなくなったので、
pip install "pulp[cbc]"などでソルバーも一緒に入れて始める(PuLPで最小化問題を解く手順)。 - スケジューリングや組合せの制約が中心:制約プログラミングのCP-SATが強い(Google OR-ToolsのCP-SATの使い方)。
公開ベンチマークで比べにくい点にも注意が必要です。ソルバーの比較で長く参照されてきたアリゾナ州立大学のMittelmannベンチマークから、Gurobiは2024年8月に撤退し、結果が削除されました。CPLEXとXpressも2018年に撤退しているので、現在の公開表では主要商用ソルバー同士の比較ができません。採用を決める前に、無料トライアルで自社のモデルを解いて時間を測るのが確実です。
モデリングの書き方を変えずにソルバーだけ差し替える方法もあります。PuLP 4.0.1でprob.solve(pulp.GUROBI(msg=False))と指定すると、gurobipy経由でGurobiが使われました(先の生産計画で同じ52,000円の解)。無料ソルバーで作ったモデルをGurobiで解き直して速度差を確かめられます。ツールごとの比較はOR-Tools・Gurobiなど主要6ツールの比較と選び方にまとめています。最適化モデルを業務システムに組み込む開発を外部に依頼する場合は、フルスクラッチ開発の支援内容も参考にしてください。
よくある質問
Gurobiはいくらですか?
商用ライセンスの価格は公開されておらず、利用形態(Named User・Floating・WLSなど)と規模に応じた見積もりになります。日本ではGurobi Japanが窓口です。学位授与機関の学生・教職員は無料、企業は30日間の無料トライアルで評価できます。
Gurobiの読み方は?「グロビ」とは何ですか?
Gurobiは「グロビ」と読みます。創業者3人(Gu・Rothberg・Bixby)の姓の最初の2文字をつなげた名前で、数理最適化ソルバー「Gurobi Optimizer」を指します。
Gurobiは無料で使えますか?
pipで入るサイズ制限ライセンスなら無料で使えますが、2,000変数・2,000線形制約(二次項があれば200変数)までで、本番の業務利用はできません。認められた学位授与機関の学生・教職員は、研究・教育・授業のために、モデル規模の制限が無いアカデミックライセンスを無料で取得できます。商用利用や大学の業務運用には使えません。
どのPythonバージョンで使えますか?
gurobipy 13.0.3はPython 3.10〜3.14(フリースレッド版の3.14tを含む)に対応しています。Python 3.15向けの配布物はまだ無く、pipでのインストールは失敗します。
Pythonで最適化ソルバーを使うにはどうすればよいですか?
Gurobiならpip install gurobipyで導入し、Model・addVar・setObjective・addConstr・optimizeの順に書きます。無料で始めたい場合は、PuLPやOR-Toolsで同じ考え方のモデルを書けます。PuLPで書いたモデルは、ソルバー指定をpulp.GUROBI()に変えるだけでGurobiで解けます。