0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで学ぶポケモン耐久調整の最適解とラグランジュ法

Last updated at Posted at 2025-10-31

image.png

1. 記号と前提(Notation and Assumptions)

耐久値(damage resistance)はポケモンの
HP(体力)・防御(Defense)・特防(Special Defense) に依存する。
努力値 (EV) の影響を連続量として扱い、最適化解析を行う。


1.1 変数定義(Definitions)

B = 基礎HP(努力値0のとき)
C = 基礎防御
D = 基礎特防
x_H = HPへの努力値による増分
x_B = 防御への努力値による増分
x_D = 特防への努力値による増分

したがって、

HP  = B + x_H
Def = C + x_B
SpD = D + x_D

1.2 ダメージ率と耐久指標

被ダメージ量は攻撃威力 A に比例し、防御値に反比例する:

Dmg_phys ∝ A / Def
Dmg_spec ∝ A / SpD

最大HPに対する被ダメージ率は:

R_phys ∝ 1 / (HP * Def)
R_spec ∝ 1 / (HP * SpD)

よって、耐久の大小は積の大きさで決まる:

物理耐久:  E_phys = HP * Def
特殊耐久:  E_spec = HP * SpD
総合耐久:  S = HP * Def + HP * SpD = HP * (Def + SpD)

1.3 努力値の制約

x_H + x_B + x_D = T
x_H, x_B, x_D ≥ 0

2. 物理耐久最大化(HP×Def)

目的関数:

f(x_H) = (B + x_H)(C + T - x_H)

微分:

f'(x_H) = (C + T - x_H) - (B + x_H)
        = (C + T - B) - 2x_H

停留点:

f'(x_H) = 0 ⇒ x_H* = (C + T - B)/2

代入すると:

HP*  = (B + C + T)/2
Def* = (B + C + T)/2

したがって HP = Def のとき物理耐久最大
特殊耐久についても同様に HP = SpD が最適。


3. 総合耐久最大化(HP×(Def + SpD))

目的関数:

S = (B + x_H)[(C + x_B) + (D + x_D)]

制約:

x_H + x_B + x_D = T

3.1 ラグランジュ関数

L = (B + x_H)(C + x_B) + (B + x_H)(D + x_D)
    - λ(x_H + x_B + x_D - T)

3.2 偏微分と停留条件

∂L/∂x_H:

(C + x_B) + (D + x_D) - λ = 0
⇒ Def + SpD = λ        ...(1)

∂L/∂x_B:

(B + x_H) - λ = 0
⇒ HP = λ               ...(2)

∂L/∂x_D:

(B + x_H) - λ = 0
⇒ HP = λ               ...(3)

3.3 条件整理

(2)(3) より λ = HP。
これを (1) に代入すると:

Def + SpD = HP

これが真の最適条件。


4. 結論(Optimal Condition)

最適化の結果:

Def + SpD = HP

これは「限界効用均等化条件」
すなわち、HPを1上げたときの総合耐久増加量と、防御・特防を1上げたときの増加量が一致する点。


5. EV配分比(Practical Ratio)

対称性(Def ≈ SpD)を仮定すると:

Def ≈ SpD ≈ HP / 2

したがって、実数値の比は:

HP : Def : SpD = 2 : 1 : 1

HPに振ると防御・特防の両方が強化されるため、
HPの価値は他の2倍と見なされる。


実例をクレセリアに適用して証明形式で展開する。

1. 前提

Lv50、性格:ずぶとい、個体値31、努力値総量510。
基礎値:

B_HP = 120, B_Def = 120, B_SpD = 130

基礎式(レベル50):

HP = floor((B_HP*2 + IV + EV/4) * 50/100) + 60
Def = floor((B_Def*2 + IV + EV/4) * 50/100) + 5
SpD = floor((B_SpD*2 + IV + EV/4) * 50/100) + 5

2. 定数化

IV=31 を代入。

HP = floor((240 + 31 + EV_H/4) * 0.5) + 60 = 180.5 + EV_H/8 + 60 ≈ 240 + EV_H/8
Def = floor((240 + 31 + EV_B/4) * 0.5) + 5 ≈ 125 + EV_B/8
SpD = floor((260 + 31 + EV_D/4) * 0.5) + 5 ≈ 136 + EV_D/8

3. 物理耐久関数

T_phys = HP × Def = (240 + EV_H/8) × (125 + EV_B/8)

制約:EV_H + EV_B = 510(仮)
EV_B = 510 − EV_H を代入:

T_phys = (240 + EV_H/8) × (125 + (510 − EV_H)/8)
       = (240 + EV_H/8) × (188.75 − EV_H/8)
       = 240×188.75 + (188.75 − 240)EV_H/8 − (EV_H)^2/64

微分して 0:

dT/dEV_H = (−51.25)/8 − 2EV_H/64 = 0
⇒ EV_H = 2040/2 = 1020 → 超過(上限510)

よって端点評価。T_phys は凹関数なので最大は EV_H=EV_B で均等配分。
理論上の最大点近傍:EV_H ≈ EV_B。
HP=防御 の条件成立。


4. 特殊耐久

同様に

T_spec = HP × SpD = (240 + EV_H/8) × (136 + EV_D/8)

EV_D = 510 − EV_H
→ 同様の微分により HP=特防 が最適。


5. 総合耐久(両面)

合成指標:

T_sum = HP×Def + HP×SpD
       = HP×(Def + SpD)
       = (240 + EV_H/8) × [(125 + EV_B/8) + (136 + EV_D/8)]

制約:

EV_H + EV_B + EV_D = 510

ラグランジュ:

L = (240 + EV_H/8)[(261 + (EV_B + EV_D)/8)] − λ(EV_H + EV_B + EV_D − 510)

偏微分:

∂L/∂EV_H = (261 + (EV_B + EV_D)/8)/8 − λ = 0
∂L/∂EV_B = (240 + EV_H/8)/8 − λ = 0
∂L/∂EV_D = (240 + EV_H/8)/8 − λ = 0

2式目3式目から EV_B=EV_D (防御=特防)
これを1式目に代入して整理すると:

261 + (2EV_B)/8 = 2(240 + EV_H/8)
⇒ Def + SpD = 2HP

したがって理論条件:

HP : Def : SpD = 2 : 1 : 1

6. 実数例(Lv50)

  • H220 → EV_H=220, EV_B=92, EV_D=196
    → HP=221, Def=179, SpD=179
    → HP : Def : SpD ≈ 2 : 1.62 : 1.62 ≒ 2 : 1 : 1

→ 条件近似的に満足。


7. 数値シミュレーション

# ================================================================
# Program Name: creselia_def_spd_3d_simulation.py
# Creation Date: 20251031
# Overview: 3D simulation of Cresselia’s Def–SpD durability surface (HP fixed)
# Usage: Run this in Google Colab or Jupyter to visualize Def–SpD balance
# ================================================================

# 必要ライブラリのインストール
!pip install matplotlib numpy

# ---------------------------------------------------------------
# 日本語+英語コメントで初心者向け説明
# 目的:HPを固定して、防御(Def)・特防(SpD)の配分により
#       総合耐久 (HP×(Def+SpD)) がどう変化するかを3Dで可視化
# English: This script visualizes the durability surface for Defense and Sp.Def
#           with fixed HP EV (Cresselia, Lv50, Bold nature).
# ---------------------------------------------------------------

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# === 定数設定 (Parameter Settings) ===
B_HP, B_Def, B_SpD = 120, 120, 130   # 種族値 Base Stats
IV = 31                               # 個体値 Individual Value
EV_total = 510                        # 努力値総量
EV_HP_fixed = 220                     # HP effort fixed (H220型想定)

# === ステータス計算関数 (Stat Calculation Functions) ===
def stat_hp(ev):
    # HPステータス(Lv50換算)
    return 240 + ev / 8

def stat_def(ev):
    # 防御ステータス(Lv50換算)
    return 125 + ev / 8

def stat_spd(ev):
    # 特防ステータス(Lv50換算)
    return 136 + ev / 8

# === 格子点生成 (Grid Generation) ===
ev_b = np.arange(0, 256, 4)  # Defense Effort
ev_d = np.arange(0, 256, 4)  # Sp.Def Effort
EV_B, EV_D = np.meshgrid(ev_b, ev_d)

# HP Effort は固定。総和制約により残りを Def+SpD へ
EV_H = EV_HP_fixed
# 残り努力値が範囲を超える点は除外
valid_mask = (EV_B + EV_D) <= (EV_total - EV_H)

# === 耐久力関数 (Durability Function) ===
HP = stat_hp(EV_H)
Def = stat_def(EV_B)
SpD = stat_spd(EV_D)
T = HP * (Def + SpD)          # 総合耐久 Total Durability
T = np.where(valid_mask, T, np.nan)  # 制約外をNaNに

# === 最大点探索 (Find Maximum Point) ===
max_idx = np.nanargmax(T)
row, col = np.unravel_index(max_idx, T.shape)
best = (T[row, col], ev_b[col], ev_d[row])
print(f"Maximum Durability ≈ {best[0]:.2f}")
print(f"Optimal EV: Def={best[1]}, SpD={best[2]}, HP fixed={EV_H}")

# === 3Dプロット (3D Plot) ===
fig = plt.figure(figsize=(9,7))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(EV_B, EV_D, T, cmap='viridis', linewidth=0, alpha=0.85)
ax.scatter(best[1], best[2], best[0], color='red', s=50, label='Optimal Point')

ax.set_xlabel('EV_Def')
ax.set_ylabel('EV_SpD')
ax.set_zlabel('Total Durability (HP×(Def+SpD))')
ax.set_title("Cresselia Durability Surface (Def–SpD, HP fixed)")
ax.legend()
plt.show()

# === 2D等高線図 (Contour Map) ===
plt.figure(figsize=(8,6))
cp = plt.contourf(EV_B, EV_D, T, levels=25, cmap='plasma')
plt.colorbar(cp, label='Total Durability')
plt.scatter(best[1], best[2], color='red', label='Optimal Point')
plt.xlabel('EV_Def')
plt.ylabel('EV_SpD')
plt.title('Cresselia Def–SpD Durability Contour Map (HP=220 fixed)')
plt.legend()
plt.show()

→ 出力例(近似):

最大値 ≈ EV_H=220, EV_B=92, EV_D=196

image.png
すなわち H220 B92 D196 が理論上の最適点。


8. 結論

目的 条件式 最適EV配分 比率 耐久特徴
物理特化 HP=防御 H252B252 1:1 物理最強
特殊特化 HP=特防 H252D252 1:1 特殊最強
総合耐久 Def+SpD=2HP H220B92D196 2:1:1 両刀最適

証明的にも数値的にも、クレセリアのH220 B92 D196は理論上の総合耐久最大点

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?