オリジナル
・Wikipedia の線形計画法の例
・English
(本日の)Gemini先生へ
Wikipedia の線形計画法の例を具体的な数値でお願いします。
(途中省略)
# SymPy を使用して線形計画法の制約領域および最適解を算出・プロットするプログラム
import sympy as sp
from sympy.plotting import plot_implicit, PlotGrid
# 1. 変数と目的関数・制約条件の定義
x1, x2 = sp.symbols('x1 x2', real=True)
# 目的関数: Z = 3*x1 + 5*x2
Z = 3 * x1 + 5 * x2
# 制約条件の不等式群
inequalities = [
x1 + x2 <= 10, # 農地制限
2 * x1 + x2 <= 16, # 肥料制限
x1 + 2 * x2 <= 18, # 殺虫剤制限
x1 >= 0, # 非負制約 (x1)
x2 >= 0 # 非負制約 (x2)
]
# 2. 実行可能領域の頂点(交点)を計算
# 境界線の方程式
eq1 = sp.Eq(x1 + x2, 10)
eq2 = sp.Eq(2 * x1 + x2, 16)
eq3 = sp.Eq(x1 + 2 * x2, 18)
eq4 = sp.Eq(x1, 0)
eq5 = sp.Eq(x2, 0)
# 交点候補の計算
candidates = [
sp.solve([eq4, eq5], (x1, x2)), # (0, 0)
sp.solve([eq2, eq5], (x1, x2)), # (8, 0)
sp.solve([eq1, eq2], (x1, x2)), # (6, 4)
sp.solve([eq1, eq3], (x1, x2)), # (2, 8)
sp.solve([eq4, eq3], (x1, x2)) # (0, 9)
]
# 制約をすべて満たす頂点のみを抽出し、各点での利益 Z を評価
feasible_vertices = []
for pt in candidates:
if all(ineq.subs(pt) for ineq in inequalities):
z_val = Z.subs(pt)
feasible_vertices.append((pt[x1], pt[x2], z_val))
# 3. 最適解の探索
optimal_point = max(feasible_vertices, key=lambda v: v[2])
print(f"実行可能頂点一覧 (x1, x2, Z): {feasible_vertices}")
print(f"最適解: 小麦 x1 = {optimal_point[0]}, 大麦 x2 = {optimal_point[1]}")
print(f"最大利益: {optimal_point[2]} 万円")
# 4. 実行可能領域の視覚化 (SymPy の plot_implicit を使用)
feasibility_region = sp.And(*inequalities)
p = plot_implicit(
feasibility_region,
(x1, -1, 12),
(x2, -1, 12),
title="Feasible Region (Linear Programming)",
xlabel="x1 (Wheat)",
ylabel="x2 (Barley)",
show=True
)
実行結果
実行可能頂点一覧 (x1, x2, Z): [(0, 0, 0), (8, 0, 24), (6, 4, 38), (2, 8, 46), (0, 9, 45)]
最適解: 小麦 x1 = 2, 大麦 x2 = 8
最大利益: 46 万円
(計算過程のポイント省略)
作図して下さい。
(さらに)Gemini先生へ
Wikipedia「線形計画法」の農家の例 をおすすめのモジュールでsympyで教えて下さい。
SymPy には線形計画法を解くための最適化モジュール sympy.solvers.simplex が用意されており、その中の lpmax 関数 を使うのが最も直接的でおすすめです。
以前紹介した「交点をすべて解いて比較するコード」よりもシンプルに、問題の設定式をそのまま渡すだけで厳密な解(有理数解)を直接算出してくれます。
...
(途中抜粋)
・sympy.solvers.simplex.lpmax を使ったコード
# SymPy の最適化モジュール (simplex) を使用した線形計画法の解法
from sympy import symbols, Ge, Le
from sympy.solvers.simplex import lpmax
# 1. 変数の定義
x1, x2 = symbols('x1 x2', real=True)
# 2. 目的関数(最大化したい利益 Z)
Z = 3 * x1 + 5 * x2
# 3. 制約条件(不等式のリスト)
# Le は <= (Less than or Equal), Ge は >= (Greater than or Equal) を表します
constraints = [
Le(x1 + x2, 10), # 農地制限: x1 + x2 <= 10
Le(2 * x1 + x2, 16), # 肥料制限: 2*x1 + x2 <= 16
Le(x1 + 2 * x2, 18), # 殺虫剤制限: x1 + 2*x2 <= 18
Ge(x1, 0), # 非負制約: x1 >= 0
Ge(x2, 0) # 非負制約: x2 >= 0
]
# 4. 単体法(Simplex法)で最大値を計算
max_value, optimal_dict = lpmax(Z, constraints)
# 結果の表示
print(f"最大利益 (Z): {max_value} 万円")
print(f"最適解: 小麦 x1 = {optimal_dict[x1]} km², 大麦 x2 = {optimal_dict[x2]} km²")
実行結果
最大利益 (Z): 46 万円
最適解: 小麦 x1 = 2 km², 大麦 x2 = 8 km²
このモジュール(lpmax)のポイント
○直感的: 数式(目的関数と制約不等式の配列)をそのまま渡すだけで計算してくれます。
○厳密解(分数/整数): 数値計算ライブラリ(SciPy等)と異なり、シンボリック計算エンジンである SymPy のため、小数近似(2.00000001 など)ではなく「正確な整数・分数」として解を返してくれます。
いつもと違うおすすめです。
sympy のdoc
・sympy.solvers.simplex.lpmax(f, constr)
https://docs.sympy.org/latest/modules/solvers/solvers.html#sympy.solvers.simplex.lpmax
