54 人が閲覧(直近 30 日) AI

決定変数・目的関数・制約条件とは?違いと定式化の手順を例題で解説

決定変数・目的関数・制約条件とは?違いと定式化の手順を例題で解説

決定変数とは、数理最適化で「自分が値を決める未知数」のことです。生産台数・発注量・誰をどのシフトに入れるか、といった意思決定そのものを x などの変数で表します。目的関数はその決定変数を入れると良し悪しが1つの数値で返ってくる式で、利益なら最大化、コストなら最小化します。制約条件は、機械の稼働時間や予算のように決定変数が守らなければならない式です。この3つを数式に書き下す作業を定式化と呼び、ソルバーは制約条件を満たす決定変数の中から目的関数が最も良くなる値を探します。本記事では3要素の違いと取り違えやすい用語、生産計画の例題での定式化、PuLP 4.0とExcelソルバーへの写し方、定式化でつまずく典型パターンを順に説明します。

まとめ

決定変数は決める値、目的関数はその決め方を採点する式、制約条件は決め方の許される範囲です。最適解は制約条件をすべて満たす範囲から選ばれるため、資源の上限などを書き忘れると、現実には実行できない計画や、目的関数がどこまでも良くなる「非有界」が返ることがあります。決定変数は連続・整数・0-1の3種類から選び、台数や人数を連続変数で解いて四捨五入すると制約違反の解が出ることがあります。回帰分析の目的変数(予測したい値)は決定変数とも目的関数とも別物で、機械学習の損失関数は目的関数の一種です。用語を混ぜないことが定式化の第一歩です。PythonならPuLP、手元の表計算ならExcelソルバーで同じ3要素をそのまま書けますが、PuLPは2026年9月25日公開の4.0で変数の作り方が変わったため、古いサンプルは動きません。

決定変数とは:ソルバーに値を決めさせる未知数

決定変数(decision variable)は、定式化する人が「ここを決めたい」と指定し、ソルバーが値を埋める変数です。製品Aの生産台数を xA、倉庫iから店舗jへの輸送量を xij のように、1つの意思決定に1つの変数を割り当てます。問題の規模は決定変数数に加え、制約数や係数の非ゼロ要素数でも表します。倉庫10か所と店舗200店の全組に輸送量を1つずつ置く場合、決定変数は2,000個です。

決定変数を置くときは「数が決まれば計画が1つに定まるか」を確認します。生産台数だけを変数にすると、どの日に作るかは決まりません。日別の計画が欲しいなら「製品×日」の変数 xA,1、xA,2…を置く必要があり、ここで変数の粒度を誤ると後から制約条件を書けなくなります。

連続変数・整数変数・0-1変数の違い

種類 取れる値 典型例 問題の分類
連続変数 実数(例 0≦x) 原料の配合量・輸送量(t) 式が線形なら線形計画(LP)
整数変数 …, -2, -1, 0, 1, 2, …(上下限で制限) 生産台数・トラック台数 整数計画(IP)
0-1変数 0 または 1 工場を建てるか・Aさんを月曜に入れるか 整数計画(IP)

連続変数と整数変数が混在する問題は混合整数計画(MIP)と呼ばれます。このうち目的関数と制約式が線形のものが混合整数線形計画(MILP)です。0-1変数は「やる/やらない」を表すのに使い、「工場を建てない(y=0)なら生産量は0」という条件を x ≦ 1000y のように書けるのが強みです。整数変数数は計算負荷の一因ですが、計算時間は制約の構造や定式化にも左右されます。数量の大小だけで連続変数に置き換えず、端数を許容できる業務かを確認してください。

決定変数と目的変数・説明変数の違い

「目的変数」は回帰分析や機械学習の用語で、売上や故障の有無など予測したい値を指します。説明変数は予測に使う入力(気温・曜日など)です。実験で設定する温度のように人が操作できる説明変数もありますが、どちらもモデルの中では「入力と予測対象」という役割で、最適化の対象ではありません。決定変数は逆に、観測されるのではなく自分が決める値です。名前が似ていますが、目的変数は目的関数とも別物で、「目的変数=決定変数」と読み替えると定式化が破綻します。

両者は組み合わせて使えます。需要予測モデルで店舗ごとの来週の販売数(目的変数)を予測し、その予測値を制約条件の右辺に入れて、発注量(決定変数)を最適化する、という分担が典型です。予測と意思決定をつなぐ位置づけは数理最適化とは?3要素・アルゴリズム・機械学習との違いをPythonで解説で整理しています。

目的関数とは:最大化・最小化する評価指標

目的関数(objective function)は、決定変数の値を入れると「その計画がどれだけ良いか」を1つの数値で返す式です。利益・売上・充足率は最大化、コスト・移動距離・残業時間は最小化します。例えば製品Aの利益が1台3千円、Bが5千円なら、目的関数は 3xA + 5xB(千円)です。

最大化と最小化は符号を反転すれば入れ替えられます。SciPyの scipy.optimize.linprog は公式リファレンスで「minimize a linear objective function」と定義されており、最小化しか受け付けません。利益を最大化したいときは係数に -1 を掛けて渡し、得られた最小値の符号を戻します。関数ごとの違いはPythonの最適化ライブラリscipy.optimizeの使い方|minimize・least_squaresの選び方【SciPy 1.18対応】で扱っています。

単一目的と多目的:目的関数を1本にまとめる方法

「コストは下げたいが、配送の遅れも減らしたい」のように評価指標が2つ以上ある問題は多目的最適化です。PuLPで単一の目的関数として扱う場合は、例えば次の2つの方法があります。Gurobiのように、複数の目的を重みや優先順位で指定できるソルバーもあります。

  • 重み付き和:コスト+α×遅延時間 のように重みを掛けて足す。αは「遅延1時間を何円と見なすか」という経営判断で、単位を円にそろえると説明しやすい。
  • 制約条件へ移す:遅延時間は「合計10時間以内」という制約条件にし、目的関数はコストだけにする。上限を動かして解き直すと、コストと遅延のトレードオフが表で見える。

重みを勘で決めると、片方の指標がほぼ無視される解が出ることがあります。まず制約条件へ移す方法で両端の値を確認してから重みを決めるほうが、関係者に説明できる結果になります。

目的関数と評価関数・損失関数の違い

評価関数は、解の良し悪しを測る関数を広く指す言い方で、遺伝的アルゴリズムや焼きなまし法では目的関数とほぼ同じ意味で使われます(遺伝的アルゴリズムでは「適応度関数」とも呼びます)。損失関数(loss function)は機械学習の用語で、予測値と正解のずれを測る関数です。学習はモデルのパラメータを決定変数として損失関数を最小化する最適化問題なので、損失関数は「機械学習における目的関数の一種」と位置づけられます。目的関数は最大化・最小化する関数の総称で、利益やコストのような業務指標も、学習時の損失も含む広い概念です。

制約条件とは:決定変数が守るべき条件

制約条件(constraint)は、決定変数が取ってよい値の範囲を式で表したものです。機械の稼働時間が週41時間なら「2xA + 4xB ≦ 41」、1日に最低3人の出勤が必要なら「その日の出勤者の合計 ≧ 3」と書きます。すべての制約条件を満たす決定変数の組を実行可能解、その集まりを実行可能領域と呼び、ソルバーはこの領域の中で目的関数が最も良くなる点(最適解)を探します。

等式制約・不等式制約・変数の範囲

制約条件は形で3つに分かれます。「生産量=出荷量+在庫増」のような等式制約、「使用時間 ≦ 上限」のような不等式制約、そして「0 ≦ x ≦ 100」のような変数の上下限です。変数の上下限は制約条件の一種ですが、ツールでは別の引数で指定することが多く、既定値に注意が要ります。SciPyの linprog は bounds の既定が (0, None)、つまり何も書かなければ決定変数は0以上として扱われます。一方PuLP 4.0の add_variable は lowBound の既定が None で、下限を書かないと負の値も取れる変数になります。同じモデルでもツールによって非負制約の有無が変わるので、移植するときは下限を明示してください。

なお「x > 0」のような厳密な不等号(等号なし)は線形計画では書けません。「0より大きい」は最小ロット1台なら x ≧ 1、連続量なら x ≧ 0.001 のように、業務上の最小単位に置き換えます。

ハード制約とソフト制約の違いとペナルティによる表現

ハード制約は破ってはいけない条件(法定の休憩時間・トラックの積載上限)、ソフト制約はできれば守りたい条件(希望休・担当エリアの固定)です。PuLPで書いた制約条件はすべてハード制約として扱われるため、ソフト制約は「違反量」を表す補助変数を置き、最小化する目的関数には正のペナルティを加え、最大化する目的関数からは差し引いて表現します。

例えば希望休をハード制約で書くと、希望が重なった週は人員の下限を満たせず、ソルバーは解なし(実行不可能)を返します。希望休の違反件数だけを最小化すれば、違反が不要な週は0件、避けられない週は最小件数の解を探せます。他の指標と重み付きで合算する場合、違反件数の最小化は保証されません。シフト作成で解が出ないときは、まず希望条件をハード制約で書いていないかを疑います。

3要素の関係を例題で確認:生産計画の定式化

3要素がどう組み合わさるかを、最小の例題で確認します。製品AとBを作る工場で、条件は次のとおりです。

項目 製品A(1台) 製品B(1台) 上限
利益 3千円 5千円 -
機械時間 2時間 4時間 41時間
材料 3kg 2kg 35kg

これを3要素に分けて書くと、次の定式化になります。

  • 決定変数:xA, xB(製品A・Bの生産台数。0以上の整数)
  • 目的関数:最大化 3xA + 5xB(利益・千円)
  • 制約条件:2xA + 4xB ≦ 41(機械時間)、3xA + 2xB ≦ 35(材料)

最適解は xA=6、xB=7 で利益は53千円です。このとき機械時間は40時間、材料は32kgを使い、どちらも上限の内側に収まっています。

手順として一般化すると、(1)決めたいもの=決定変数を列挙して単位を付ける、(2)評価指標を1つ選んで目的関数にする、(3)守るべき条件を「左辺=決定変数の式、右辺=定数」の形で書き出す、(4)決定変数の種類(連続・整数・0-1)と上下限を決める、の4段階です。(1)より先に目的関数を考え始めると、目的関数に登場する量が決定変数なのかデータなのかが曖昧なまま進んでしまいます。

整数の決定変数を四捨五入してはいけない理由

同じ例題を連続変数として解くと、最適解は xA=7.25、xB=6.625(利益54.875千円)になります。これを四捨五入して (7, 7) にすると、機械時間は 2×7 + 4×7 = 42時間で上限41時間を超え、実行不可能です。切り捨てた (7, 6) は制約を満たしますが利益は51千円で、整数で解いた最適解の53千円より2千円低くなります。台数や人数のように端数が意味を持たない決定変数は、最初から整数変数として宣言してソルバーに解かせるのが正解です。

PuLP 4.0とExcelソルバーで3要素を書く方法

定式化ができれば、あとはツールの書式に写すだけです。ここでは前章の例題をPuLPで実装し、Excelソルバーでは3要素と入力欄の対応を説明します。PuLPの位置づけや他ツールとの比較はORツールとは?主要6ツールの比較と選び方【ライセンス・費用・得意問題】を参照してください。

PuLP 4.0での書き方(3.x系から変わった点)

PuLPは2026年9月25日に4.0.0が公開され、Python 3.12以上が必須になりました(PyPIのPuLP 4.0.0)。公式の移行ガイドが挙げる破壊的変更のうち、定式化に直接関わるのは次の3点です。

  • 決定変数は LpVariable(...) ではなく、問題オブジェクトの prob.add_variable(...) で作る(問題を先に作る必要がある)
  • prob.solve() の戻り値が整数のステータスから LpSolveStats オブジェクトに変わり、状態は stats.status_str で読む
  • CBCソルバーが同梱されなくなり PULP_CBC_CMD は削除。pip install "pulp[cbc]" でCBCを入れ、COIN_CMD を使う

PuLP 3.x系のサンプルにある LpVariable("x", lowBound=0) 形式の変数宣言は、PuLP 4.0.0 で実行すると TypeError: LpVariable.__init__() got an unexpected keyword argument 'lowBound' で止まります。4.0での例題は次のとおりです(PuLP 4.0.0・cbcbox 2.935で実行確認)。

import pulp

prob = pulp.LpProblem("seisan", pulp.LpMaximize)

# 決定変数:製品A・Bの生産台数(0以上の整数)
x_a = prob.add_variable("x_A", lowBound=0, cat=pulp.LpInteger)
x_b = prob.add_variable("x_B", lowBound=0, cat=pulp.LpInteger)

# 目的関数:利益(千円)を最大化
prob += 3 * x_a + 5 * x_b, "profit"

# 制約条件:機械時間41時間・材料35kgまで
prob += 2 * x_a + 4 * x_b <= 41, "machine_hours"
prob += 3 * x_a + 2 * x_b <= 35, "material_kg"

stats = prob.solve(pulp.COIN_CMD(msg=False))
print(stats.status_str)
print("x_A =", x_a.value(), "x_B =", x_b.value())
print("profit =", pulp.value(prob.objective))
Optimal
x_A = 6.0 x_B = 7.0
profit = 53.0

コードの3ブロックが、そのまま決定変数・目的関数・制約条件に対応しています。prob += に不等式を渡すと制約条件、式だけを渡すと目的関数として登録される点がPuLPの書き方の要所です。3.x系で書かれた既存コードの移行手順や最小化問題の例はPuLPとは?Pythonで最小化問題を解く手順と3.3系で非推奨になったAPIで扱っています。

Excelソルバーでの対応関係

Excelソルバーでは3要素が画面の入力欄に対応します。Microsoftのサポートページ自体が変数セルを「決定変数セル」と呼んでおり、対応関係は次のとおりです。

  • 目的関数:「目的の設定」に、目的関数を計算する数式のセル(例:=3*B2+5*C2)を指定し、「最大」か「最小」を選ぶ
  • 決定変数:「変数セルの変更」に、生産台数などを入れるセル範囲を指定する
  • 制約条件:「制約条件の対象」の「追加」で、<=・=・>= の条件を登録する。整数の決定変数は関係で「int」、0-1変数は「bin」を選ぶ

解決方法は3種類あり、目的関数と制約式が変数について線形なら「シンプレックス LP」(SUM・SUMPRODUCTでも変数同士の積や変数による除算は非線形)、IF・CHOOSE・LOOKUP以外の関数を使う滑らかな非線形モデルなら既定の「GRG 非線形」、変数セルに依存するIF・CHOOSE・LOOKUPを含むなら「エボリューショナリー」を選びます。変数セルは最大200個までと公式に明記されているので、前述の2,000変数の輸送計画はExcelソルバーでは扱えません。決定変数が200個を超えそうになったら、PuLPなどのコードに移る目安です。

定式化でつまずく3つのパターンと直し方

ソルバーが期待どおりの答えを返さないときは、終了ステータスとログを確認します。ここでは、定式化を見直す代表例として、実行不可能・非有界・業務に合わない最適解を扱います。

実行不可能(Infeasible)の原因と制約の矛盾の確認

例題に「製品Bは受注分の12台を必ず作る(xB ≧ 12)」を加えると、PuLPは Infeasible を返します。Bを12台作るだけで機械時間が48時間必要になり、上限41時間と両立しないためです。小さなモデルでは制約を外して解き直すと原因を絞れます。ただし、独立した矛盾が複数あると1本の削除では解けないため、制約群ごとの切り分けも必要です。外すと解ける制約がソフト制約で表せる条件なら、前述のペナルティ方式に書き換えるのが根本的な直し方です。

非有界(Unbounded):制約条件の書き忘れ

例題から機械時間と材料の制約をどちらも書き忘れると、生産台数に上限がなくなり、PuLPは Unbounded を返します。この生産計画では資源上限の欠落が原因なので、目的関数を良くする方向にいくらでも増やせる決定変数を探し、その変数を縛る資源(時間・予算・人数)の制約を足します。一般には、制約の欠落に加え、不等号の向き、変数の上下限、目的関数の符号(最大化と最小化の取り違え)も確認します。

解は出るが現場で使えない:決定変数の粒度か目的関数の選び方の誤り

ステータスは Optimal でも、モデルに含めた条件と実際の業務が一致していなければ使えない計画になります。制約の漏れや入力データの誤りもありますが、ここでは代表例を2つ挙げます。1つは決定変数の粒度が粗すぎること(週単位で解いたので日ごとの偏りが見えない)、もう1つは目的関数が一部の指標しか見ていないこと(コスト最小化だけにしたら特定の担当者に仕事が集中した)です。前者は決定変数に時間の添字を足し、後者は偏りを制約条件の上限か目的関数のペナルティで表します。現場の担当者に解を見せて「なぜ使えないか」を聞き、その理由を3要素のどれかに翻訳するのが最短の修正ルートです。

必要な時間内に十分な解が得られない場合は、定式化の改善や時間制限・許容ギャップの設定を検討します。そのうえで、業務上許容できる解を探すヒューリスティクスも選択肢になります。考え方はヒューリスティックとは?アルゴリズムとの違いと代表手法・メタヒューリスティックまで解説で解説しています。

よくある質問

決定変数とは何ですか?

数理最適化で、ソルバーに値を決めさせる未知数のことです。生産台数・発注量・シフトの割り当てなど、意思決定そのものを変数で表します。

目的関数と制約条件の関係は?

制約条件が決定変数の取れる範囲(実行可能領域)を決め、目的関数はその範囲の中で最も良い点を選ぶ基準になります。制約条件を書き忘れると非有界になる場合がありますが、残りの制約で目的関数の改善が制限されれば、有限の最適値が得られます。

目的関数と目的変数の違いは何ですか?

目的関数は数理最適化で最大化・最小化する評価式、目的変数は回帰分析や機械学習で予測したい値です。目的変数はデータとして観測される値で、決定変数とも別物です。

目的関数と損失関数の違いは何ですか?

損失関数は機械学習で予測と正解のずれを測る関数で、学習ではこれを最小化します。このように、学習で最小化する損失関数は目的関数の一種です。目的関数はより広い概念で、学習時の損失のほか、利益やコストなども表します。

制約条件の「ハード制約」と「ソフト制約」とは何ですか?

ハード制約は必ず守る条件、ソフト制約はできれば守りたい条件です。PuLPでは、ソフト制約を違反量の補助変数とペナルティで表せます。ペナルティは最小化する目的関数に加え、最大化する目的関数からは差し引きます。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

ほか 3 件の記事からもリンクされています。

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.09 テックブログ IDCFクラウド(IDCフロンティア)不正アクセス・ランサムウェア:影響先・復旧・データは戻るか
  2. 2026.10.08 テックブログ 大阪公立大学のランサムウェア被害と仮想化基盤の停止|全授業休講に至った経緯とバックアップを守る設定
  3. 2024.11.08 テックブログ OpenAPI GeneratorでJavaコードを自動生成する方法|CLI導入からSpring・ライブラリ選択まで
  4. 2026.10.09 テックブログ ニッスイのサイバー攻撃で日水物流の入出荷停止|委託先クラウド障害に荷主が備える手順
  5. 2026.10.09 テックブログ 京王電鉄のランサムウェア被害とグループ共通基盤:決済・ポイント・予約が止まった範囲と遮断の初動

RELATED POSTS 関連記事

目次