Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

W23 실습 · 캐리커처 모형 — 쐐기가 묶인 비율을 집어낸다

노트북은 예측 → 계산 → 대조 세 부분으로 고정한다. 새 개념은 도입하지 않는다. 본문에서 이미 유도한 것을 수치로 확인할 뿐이다.

1. 예측 (코드를 쓰기 전에)

아래 칸을 먼저 채운다. 계산하지 않는다.

계산 계획: 가계별 해는 (eq-w23-8)·(eq-w23-9)·(eq-w23-10)의 경우 나누기를 코드로 그대로 쌓는다. 검증용으로 몇 가계는 ss 격자 위에서 u(y1s)+βu(y2+Rs)u(y_1-s)+\beta u(y_2+Rs)를 직접 최대화한다. 집계 성향은 모든 가계에 ±Δ\pm\Delta를 주고 중앙차분한다. TT기간은 VT(W)=lnWV_T(W)=\ln W부터 Vt(W)=maxc{lnc+βVt+1(R(Wc))}V_t(W)=\max_c\{\ln c+\beta V_{t+1}(R(W-c))\}WW 격자 위에서 — 그리드 최대화, 선형 보간. 불확실성은 (eq-w23-14)를 c1c_1에 대한 이분법(200회)으로 푼다.

  1. 가계 N=10,000N=10{,}000y1=1y_1=1, y2U[0.6,2.0]y_2\sim U[0.6,\,2.0], bˉ=0\bar b=0으로 뽑고 β=0.96\beta=0.96, R=1.04R=1.04로 각자 풀면, 묶인 비율은 Pr(y2>0.9984)=(2.00.9984)/1.40.715\Pr(y_2>0.9984)=(2.0-0.9984)/1.4\approx0.715이고, 균일 이전 Δ=103\Delta=10^{-3}에 대한 집계 성향은 κ10.715+0.285/1.96=0.861\kappa_1\approx0.715+0.285/1.96=0.861, κ20.285/(1.04×1.96)=0.140\kappa_2\approx0.285/(1.04\times1.96)=0.140이며, 쐐기 κ1Rκ2\kappa_1-R\kappa_2는 묶인 비율과 소수 셋째 자리까지 일치한다.

    예측: ____

  2. TT기간 로그 문제를 역진귀납(W12의 벨만 연산자를 TT번 적용)으로 풀면 1기 성향은 T=2,10,40T=2,10,40에서 0.510, 0.119, 0.0500.510,\ 0.119,\ 0.050 — (eq-w23-13)의 닫힌형과 소수 셋째 자리까지 맞고, RR을 1.02로 바꿔도 변하지 않는다.

    예측: ____

  3. 한도 없는 세계에서 y2=1.5±εy_2=1.5\pm\varepsilon: ε=01.0\varepsilon=0\to1.0에서 κ1\kappa_10.5100.5940.510\to0.594로 오르지만 κ1Rκ2\kappa_1-R\kappa_210-3 이내에서 0이고, (eq-w23-12)로 역산한 ω^0\hat\omega\approx0, β^\hat\beta0.960.680.96\to0.68로 떨어진다.

    예측: ____

2. 계산

패키지 호출로 답을 내지 않는다. 경우 나누기·격자 최대화·역진귀납·이분법을 차례로 직접 쌓는다.

# 도구와 한국어 글꼴, 그리고 두 기간 모형의 파라미터를 쌓는다
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager

_cands = ['Apple SD Gothic Neo', 'AppleGothic', 'NanumGothic', 'Noto Sans CJK KR', 'Malgun Gothic']
_have = {f.name for f in font_manager.fontManager.ttflist}
for _f in _cands:
    if _f in _have:
        plt.rcParams['font.family'] = _f
        break
plt.rcParams['axes.unicode_minus'] = False

BETA, R, Y1, BBAR = 0.96, 1.04, 1.0, 0.0


def solve2p(y1, y2, bbar, beta=BETA, r=R):
    """(eq-w23-8)·(eq-w23-9)·(eq-w23-10)의 경우 나누기를 식 그대로 쌓는다"""
    c1u = (y1 + y2 / r) / (1.0 + beta)        # 묶이지 않은 해
    bound = (y1 - c1u) < -bbar                # 묶임 조건 s^u < -b̄
    c1 = np.where(bound, y1 + bbar, c1u)
    s = np.where(bound, -bbar, y1 - c1u)
    c2 = y2 + r * s
    mu = np.where(bound, 1.0 / c1 - beta * r / c2, 0.0)
    return c1, c2, s, mu, bound, c1u


THR = R * (BETA * Y1 + (1 + BETA) * BBAR)
print('글꼴:', plt.rcParams['font.family'][0])
print(f'묶임 문턱  y2 > R[βy1+(1+β)b̄] = {THR:.4f}    (y1={Y1}, b̄={BBAR})')
print(f'대표적 개인의 성향 1/(1+β) = {1 / (1 + BETA):.4f}')
글꼴: Apple SD Gothic Neo
묶임 문턱  y2 > R[βy1+(1+β)b̄] = 0.9984    (y1=1.0, b̄=0.0)
대표적 개인의 성향 1/(1+β) = 0.5102

예측 1. 두 기간 해를 (eq-w23-8)·(eq-w23-9)·(eq-w23-10) 그대로 쌓고, 같은 답이 ss 격자 최대화에서도 나오는지 본 뒤, 가계 1만을 뽑아 집계 성향을 중앙차분한다.

# 검증 — 몇 가계는 s 격자 위에서 u(y1-s)+βu(y2+Rs)를 직접 최대화해 같은 답인지 본다
sg = np.linspace(-BBAR, Y1 - 1e-7, 400001)
print(f"{'y2':>6}{'c1u':>9}{'c1':>9}{'c2':>9}{'μ':>9}{'R̃':>10}"
      f"{'격자 s':>11}{'|차|':>10}   묶임")
for yy2 in (0.9, 1.2, 1.5, 2.0):
    c1, c2, s, mu, bd, c1u = solve2p(Y1, yy2, BBAR)
    s_grid = sg[np.argmax(np.log(Y1 - sg) + BETA * np.log(yy2 + R * sg))]
    rt = float(c2) / (BETA * float(c1))          # 잠재 이자율 R̃ = c2/(βc1)
    print(f'{yy2:6.1f}{float(c1u):9.3f}{float(c1):9.3f}'
          f'{float(c2):9.3f}{float(mu):9.3f}{rt:10.4f}{s_grid:11.5f}'
          f'{abs(s_grid - float(s)):10.1e}   {"예" if bd else "아니오"}')
print('격자 최대화와 닫힌형이 같은 s를 준다 — 경우 나누기가 맞다')
    y2      c1u       c1       c2        μ        R̃       격자 s       |차|   묶임
   0.9    0.952    0.952    0.950    0.000    1.0400    0.04827   6.6e-07   아니오
   1.2    1.099    1.000    1.200    0.168    1.2500    0.00000   0.0e+00   예
   1.5    1.246    1.000    1.500    0.334    1.5625    0.00000   0.0e+00   예
   2.0    1.491    1.000    2.000    0.501    2.0833    0.00000   0.0e+00   예
격자 최대화와 닫힌형이 같은 s를 준다 — 경우 나누기가 맞다
# 예측 1 — 가계 1만을 뽑아 각자 풀고, 모두에게 ±Δ를 주어 집계 성향을 중앙차분한다
rng = np.random.default_rng(2023)
N, DELTA = 10000, 1e-3
y2 = rng.uniform(0.6, 2.0, N)
bound = solve2p(Y1, y2, BBAR)[4]
frac = float(bound.mean())


def C1bar(y1v, y2v):
    """모든 가계에 같은 소득을 주었을 때의 집계 1기 소비"""
    return float(solve2p(y1v, y2v, BBAR)[0].mean())


kap1 = (C1bar(Y1 + DELTA, y2) - C1bar(Y1 - DELTA, y2)) / (2 * DELTA)
kap2 = (C1bar(Y1, y2 + DELTA) - C1bar(Y1, y2 - DELTA)) / (2 * DELTA)
wedge = kap1 - R * kap2
print(f'묶인 가계 {int(bound.sum())} / {N}   비율 {frac:.4f}   (모집단 값 {(2.0 - THR) / 1.4:.4f})')
print(f'κ1 = {kap1:.4f}    κ2 = {kap2:.4f}    Rκ2 = {R * kap2:.4f}')
print(f'쐐기 κ1-Rκ2 = {wedge:.4f}   묶인 비율 = {frac:.4f}   차 = {wedge - frac:+.2e}')
print(f'역산 (eq-w23-12): ω̂ = {wedge:.4f}   β̂ = {(1 - kap1) / (R * kap2):.4f}   (참값 β = {BETA})')
print(f'대표적 개인이라면 κ1 = {1 / (1 + BETA):.4f} — 수준 차 '
      f'{kap1 - 1 / (1 + BETA):.4f}는 전부 분포에서 온다')
묶인 가계 7162 / 10000   비율 0.7162   (모집단 값 0.7154)
κ1 = 0.8610    κ2 = 0.1392    Rκ2 = 0.1448
쐐기 κ1-Rκ2 = 0.7162   묶인 비율 = 0.7162   차 = +1.85e-05
역산 (eq-w23-12): ω̂ = 0.7162   β̂ = 0.9600   (참값 β = 0.96)
대표적 개인이라면 κ1 = 0.5102 — 수준 차 0.3508는 전부 분포에서 온다
# 소비함수의 꺾임과 집계 성향을 그린다
gy2 = np.linspace(0.6, 2.0, 561)
cc, ccu = solve2p(Y1, gy2, BBAR)[0], (Y1 + gy2 / R) / (1 + BETA)
fig, (axL, axR) = plt.subplots(1, 2, figsize=(9.8, 3.8))
axT = axL.twinx()
axT.hist(y2, bins=45, color='#e8e8e8', zorder=0)
axT.set_ylabel('가계 수')
axL.set_zorder(axT.get_zorder() + 1)
axL.patch.set_visible(False)
axL.plot(gy2, ccu, ls='--', lw=1.2, color='#3b6ea5', label=r'원하던 $c_1^{u}$')
axL.plot(gy2, cc, lw=1.9, color='#c0392b', label=r'실현 $c_1=\min(c_1^{u},\,y_1+\bar b)$')
axL.axvline(THR, ls=':', color='k', lw=1.1)
axL.text(THR + 0.03, 0.78, f'문턱 {THR:.4f}', fontsize=9)
axL.set_xlabel('2기 소득 $y_2$ [화폐]')
axL.set_ylabel('1기 소비 $c_1$ [화폐]')
axL.set_ylim(0.75, 1.55)
axL.legend(loc='upper left', fontsize=8)
axL.set_title(f'표본에서 묶인 비율 {frac:.3f}')
vals = [kap1, R * kap2, wedge, frac]
axR.bar(range(4), vals, 0.55, color=['#3b6ea5', '#d98c3f', '#c0392b', '#7f8c8d'])
for i, v in enumerate(vals):
    axR.text(i, v + 0.02, f'{v:.3f}', ha='center', fontsize=9)
axR.set_xticks(range(4))
axR.set_xticklabels([r'$\kappa_1$', r'$R\kappa_2$', '쐐기', '묶인 비율'])
axR.set_ylim(0, 1.05)
axR.set_title('쐐기가 묶인 비율과 만난다')
plt.tight_layout()
plt.show()
<Figure size 980x380 with 3 Axes>

예측 2. 지평을 되살린다. VT(W)=lnWV_T(W)=\ln W에서 시작해 Vt(W)=maxc{lnc+βVt+1(R(Wc))}V_t(W)=\max_c\{\ln c+\beta V_{t+1}(R(W-c))\}WW 격자 위에서 역진하고, 1기 정책의 기울기를 (eq-w23-13)의 닫힌형과 겹친다. 자원은 W=y1+t2yt/Rt1W=y_1+\sum_{t\ge2}y_t/R^{t-1}이므로 c1/y1\partial c_1/\partial y_1은 정책의 WW에 대한 기울기다.

# 예측 2 — W 격자 위의 벨만 연산자를 쌓는다
LNW = np.linspace(np.log(0.02), np.log(200.0), 161)   # 자원 W의 로그 격자
TH = np.linspace(1e-4, 1 - 1e-4, 4001)                # 소비 비율 c/W 격자


def Vinterp(x, vg):
    """lnW 격자 위 선형 보간 — 격자 밖은 끝 기울기로 잇는다"""
    v = np.interp(x, LNW, vg)
    s0 = (vg[1] - vg[0]) / (LNW[1] - LNW[0])
    s1 = (vg[-1] - vg[-2]) / (LNW[-1] - LNW[-2])
    v = np.where(x < LNW[0], vg[0] + s0 * (x - LNW[0]), v)
    return np.where(x > LNW[-1], vg[-1] + s1 * (x - LNW[-1]), v)


def backward(T, r):
    """V_T(W)=ln W 에서 시작해 벨만 연산자를 T-2번 적용하고 V_2를 돌려준다"""
    V, W = LNW.copy(), np.exp(LNW)[:, None]
    for _ in range(T - 2):
        val = np.log(TH[None, :] * W) + BETA * Vinterp(np.log(r * W * (1 - TH[None, :])), V)
        V = val.max(axis=1)
    return V


def policy1(W, V2, r, rounds=4):
    """1기 정책 — c/W 격자를 네 번 조여 최대점을 찾는다"""
    lo, hi = 1e-7, 1 - 1e-7
    for _ in range(rounds):
        th = np.linspace(lo, hi, 1001)
        val = np.log(th * W) + BETA * Vinterp(np.log(r * W * (1 - th)), V2)
        j, d = int(np.argmax(val)), (hi - lo) / 1000.0
        lo, hi = max(th[j] - d, 1e-9), min(th[j] + d, 1 - 1e-9)
    return 0.5 * (lo + hi) * W


print(f'격자 {LNW.size} × {TH.size}, 조이기 {4}회 — 보간은 선형, 최대화는 격자')
격자 161 × 4001, 조이기 4회 — 보간은 선형, 최대화는 격자
# 역진귀납의 1기 성향을 (eq-w23-13)의 닫힌형과 겹친다
HH = 1e-3
bi = {}
print(f"{'R':>6}{'T':>5}{'W0':>9}{'역진귀납':>12}{'닫힌형':>11}{'차':>11}")
for r in (1.04, 1.02):
    for T in (2, 10, 40):
        V2 = backward(T, r)
        W0 = sum(r ** -k for k in range(T))       # y_t=1 (t=1..T)의 현재가치
        bi[(r, T)] = (policy1(W0 + HH, V2, r) - policy1(W0 - HH, V2, r)) / (2 * HH)
        cf = (1 - BETA) / (1 - BETA ** T)
        print(f'{r:6.2f}{T:5d}{W0:9.3f}{bi[(r, T)]:12.4f}{cf:11.4f}{bi[(r, T)] - cf:+11.1e}')
print('R 1.04→1.02의 차: ' + ',  '.join(
    f'T={T}: {bi[(1.02, T)] - bi[(1.04, T)]:+.1e}' for T in (2, 10, 40)))
print('묶인 가계의 성향은 지평과 무관하게 1 — 순위는 살고 수준은 살지 않는다')
     R    T       W0        역진귀납        닫힌형          차
  1.04    2    1.962      0.5102     0.5102   -3.9e-07
  1.04   10    8.435      0.1193     0.1193   -1.3e-05
  1.04   40   20.584      0.0497     0.0497   -5.8e-06
  1.02    2    1.980      0.5102     0.5102   +1.4e-06
  1.02   10    9.162      0.1194     0.1193   +7.5e-06
  1.02   40   27.903      0.0497     0.0497   -7.8e-07
R 1.04→1.02의 차: T=2: +1.8e-06,  T=10: +2.0e-05,  T=40: +5.1e-06
묶인 가계의 성향은 지평과 무관하게 1 — 순위는 살고 수준은 살지 않는다
# 지평에 대한 성향 곡선을 그린다
Ts = np.arange(2, 51)
fig, ax = plt.subplots(figsize=(6.2, 3.9))
ax.plot(Ts, (1 - BETA) / (1 - BETA ** Ts), color='#3b6ea5',
        label=r'닫힌형 $(1-\beta)/(1-\beta^{T})$')
ax.axhline(1 - BETA, ls=':', color='#3b6ea5', lw=1.1)
ax.text(33, 1 - BETA + 0.03, rf'$1-\beta={1 - BETA:.2f}$', fontsize=9, color='#3b6ea5')
ax.axhline(1.0, color='#c0392b', lw=1.6)
ax.text(27, 1.03, '묶인 가계: 1 (지평과 무관)', fontsize=9, color='#c0392b', ha='center')
for T in (2, 10, 40):
    ax.plot([T], [bi[(1.04, T)]], 'o', color='k', ms=5, zorder=3)
    ax.annotate(f'$T={T}$: {bi[(1.04, T)]:.3f}', xy=(T, bi[(1.04, T)]),
                xytext=(T + 2, bi[(1.04, T)] + 0.08), fontsize=9)
ax.set_xlabel('지평 $T$ (기간 수)')
ax.set_ylabel(r'1기 성향 $\partial c_1/\partial y_1$')
ax.set_xlim(0, 54)
ax.set_ylim(-0.03, 1.14)
ax.legend(loc='center right', fontsize=8)
ax.set_title('역진귀납 점이 닫힌형 곡선 위에 앉는다')
plt.tight_layout()
plt.show()
<Figure size 620x390 with 1 Axes>

예측 3. 확실성(A2)을 뺀다. 한도를 없애고 y2=yˉ2+ηy_2=\bar y_2+\eta, η=±ε\eta=\pm\varepsilon 등확률로 두어 (eq-w23-14)를 c1c_1에 대한 이분법으로 푼다. 수준 κ1\kappa_1과 쐐기 κ1Rκ2\kappa_1-R\kappa_2가 서로 다르게 움직이는지 본다.

# 예측 3 — 확실성을 뺀다. (eq-w23-14)를 c1에 대한 이분법 200회로 푼다
def c1_unc(y1, yb2, eps, beta=BETA, r=R, iters=200):
    """1/c1 = βR·E[1/(ȳ2+η+R(y1-c1))], η=±ε 등확률, 한도 없음"""
    lo, hi = 1e-9, y1 + (yb2 - eps) / r - 1e-9      # 나쁜 상태에서도 c2>0
    for _ in range(iters):
        mid = 0.5 * (lo + hi)
        c2 = yb2 + np.array([-eps, eps]) + r * (y1 - mid)
        if 1.0 / mid - beta * r * np.mean(1.0 / c2) > 0:
            lo = mid                                 # 좌변이 크다 → c1을 키운다
        else:
            hi = mid
    return 0.5 * (lo + hi)


YB2 = 1.5
print(f'ε=0 이분법 해     c1 = {c1_unc(Y1, YB2, 0.0):.8f}')
print(f'확실성 닫힌형 (eq-w23-8) = {(Y1 + YB2 / R) / (1 + BETA):.8f}')
ε=0 이분법 해     c1 = 1.24607535
확실성 닫힌형 (eq-w23-8) = 1.24607535
# ε 격자에서 집계 성향과 역산 모수를 쌓는다 (한도가 없으므로 ω=0인 세계다)
HU, unc = 1e-4, []
print(f"{'ε':>6}{'c1':>10}{'κ1':>10}{'Rκ2':>10}{'쐐기':>13}{'ω̂':>10}{'β̂':>10}")
for e in (0.0, 0.25, 0.5, 0.75, 1.0):
    c = c1_unc(Y1, YB2, e)
    a1 = (c1_unc(Y1 + HU, YB2, e) - c1_unc(Y1 - HU, YB2, e)) / (2 * HU)
    a2 = (c1_unc(Y1, YB2 + HU, e) - c1_unc(Y1, YB2 - HU, e)) / (2 * HU)
    unc.append((e, c, a1, a2))
    print(f'{e:6.2f}{c:10.4f}{a1:10.4f}{R * a2:10.4f}{a1 - R * a2:+13.1e}'
          f'{a1 - R * a2:10.4f}{(1 - a1) / (R * a2):10.4f}')
print('κ1은 오르고 쐐기는 0에 붙어 있다 — 신중성은 참을성 부족으로 오독되되 제약으로는 아니다')
     ε        c1        κ1       Rκ2           쐐기        ω̂        β̂
  0.00    1.2461    0.5102    0.5102     -2.3e-12   -0.0000    0.9600
  0.25    1.2219    0.5197    0.5197     +1.2e-12    0.0000    0.9241
  0.50    1.1545    0.5427    0.5427     +1.3e-12    0.0000    0.8426
  0.75    1.0548    0.5695    0.5695     +3.2e-12    0.0000    0.7558
  1.00    0.9334    0.5943    0.5943     +3.6e-12    0.0000    0.6827
κ1은 오르고 쐐기는 0에 붙어 있다 — 신중성은 참을성 부족으로 오독되되 제약으로는 아니다
# 모멘트 평면에 허용 삼각형·신중성 궤적·표본 점을 그린다
fig, ax = plt.subplots(figsize=(5.8, 5.6))
ax.fill([0, 0.5, 1], [1, 0.5, 1], color='#ededed', zorder=0)
xx = np.linspace(0, 1, 201)
for om in (0.0, 0.25, 0.5, 0.75):
    keep = (om + xx <= 1 + 1e-9) & (om + xx >= 1 - xx - 1e-9)
    ax.plot(xx[keep], (om + xx)[keep], color='#9aa0a6', lw=0.9, zorder=1)
    ax.text(1 - om, 1.015, rf'$\omega={om}$', fontsize=8, color='#6b6b6b',
            ha='right' if om == 0.0 else 'center')
ax.plot([0.10, 0.5], [0.10, 0.5], ls='--', lw=0.8, color='#9aa0a6', zorder=1)
u = np.array([[R * a2, a1] for _, _, a1, a2 in unc])
ax.plot(u[:, 0], u[:, 1], '-o', color='#d98c3f', ms=4, lw=2.2, zorder=2,
        label=r'신중성 궤적 ($\varepsilon=0\to1$)')
ax.text(0.58, 0.42, rf'$\varepsilon=0$: $\kappa_1$={unc[0][2]:.3f}, '
        rf'$\hat\beta$={(1 - unc[0][2]) / (R * unc[0][3]):.2f}' + '\n'
        + rf'$\varepsilon=1$: $\kappa_1$={unc[-1][2]:.3f}, '
        rf'$\hat\beta$={(1 - unc[-1][2]) / (R * unc[-1][3]):.2f}',
        fontsize=8.5, color='#d98c3f', va='top')
ax.plot([R * kap2], [kap1], 'o', color='#c0392b', ms=7, zorder=3, label='표본 1만 가계')
ax.annotate('', xy=(R * kap2, R * kap2), xytext=(R * kap2, kap1),
            arrowprops=dict(arrowstyle='<->', color='#c0392b', lw=1.0))
ax.text(R * kap2 + 0.02, 0.5 * (kap1 + R * kap2), f'쐐기 = {wedge:.3f}',
        fontsize=9, color='#c0392b', va='center')
ax.set_xlabel(r'$R\kappa_2$ — 예고소득 반응 $\times R$')
ax.set_ylabel(r'$\kappa_1$ — 현재소득 반응')
ax.set_xlim(0, 1.06)
ax.set_ylim(0.10, 1.10)
ax.set_aspect('equal')
ax.legend(loc='lower right', fontsize=8)
plt.tight_layout()
plt.show()
<Figure size 580x560 with 1 Axes>
# 예측 항목 세 개에 대응하는 수치를 한자리에 모은다
print(f'[예측 1] 묶인 비율 {frac:.4f} (예측 0.715) · κ1 = {kap1:.4f} (0.861) · '
      f'κ2 = {kap2:.4f} (0.140)')
print(f'         쐐기 {wedge:.4f} vs 묶인 비율 {frac:.4f} — 차 {wedge - frac:+.1e}, '
      f'β̂ = {(1 - kap1) / (R * kap2):.4f}')
print('[예측 2] 역진귀납 T=2,10,40: ' + ', '.join(f'{bi[(1.04, T)]:.3f}' for T in (2, 10, 40))
      + ' (예측 0.510, 0.119, 0.050)')
print(f'         닫힌형과의 최대 차 '
      f'{max(abs(bi[(1.04, T)] - (1 - BETA) / (1 - BETA ** T)) for T in (2, 10, 40)):.1e} · '
      f'R=1.02와의 최대 차 {max(abs(bi[(1.02, T)] - bi[(1.04, T)]) for T in (2, 10, 40)):.1e}')
print(f'[예측 3] κ1 {unc[0][2]:.3f} → {unc[-1][2]:.3f} (예측 0.510 → 0.594) · '
      f'최대 |쐐기| = {max(abs(a1 - R * a2) for _, _, a1, a2 in unc):.1e}')
print(f'         ω̂ = {unc[-1][2] - R * unc[-1][3]:+.4f} (예측 0) · '
      f'β̂ {(1 - unc[0][2]) / (R * unc[0][3]):.2f} → '
      f'{(1 - unc[-1][2]) / (R * unc[-1][3]):.2f} (예측 0.96 → 0.68)')
[예측 1] 묶인 비율 0.7162 (예측 0.715) · κ1 = 0.8610 (0.861) · κ2 = 0.1392 (0.140)
         쐐기 0.7162 vs 묶인 비율 0.7162 — 차 +1.9e-05, β̂ = 0.9600
[예측 2] 역진귀납 T=2,10,40: 0.510, 0.119, 0.050 (예측 0.510, 0.119, 0.050)
         닫힌형과의 최대 차 1.3e-05 · R=1.02와의 최대 차 2.0e-05
[예측 3] κ1 0.510 → 0.594 (예측 0.510 → 0.594) · 최대 |쐐기| = 3.6e-12
         ω̂ = +0.0000 (예측 0) · β̂ 0.96 → 0.68 (예측 0.96 → 0.68)

3. 대조

예측과 계산이 어긋난 지점을 적는다. 어느 쪽이 틀렸는지 판정한다.

예측결과어긋남원인

본문 확인: 어긋났으면 (eq-w23-9)·(eq-w23-12)·(eq-w23-13)로 돌아간다.