실행 시간 예측 문서의 그림 생성 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
# 실행 시간 예측 문서의 그림을 만든다: 45_burst-prediction_fig1.svg
# 실행: ~/.venvs/vault-plots/bin/python 45_burst-prediction_plot.py (matplotlib, numpy 필요)
import os
import matplotlib
matplotlib.use("svg")
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import font_manager
HERE = os.path.dirname(os.path.abspath(__file__))
PREFIX = "45_burst-prediction"
INK = "#888888" # 밝은 테마와 어두운 테마 모두에서 보이는 회색
C = ["#3b82c4", "#d9622b", "#3a9a5b", "#9b59b6", "#c49a1b"]
_fonts = {f.name for f in font_manager.fontManager.ttflist}
FONT = next((n for n in ["Apple SD Gothic Neo", "NanumGothic", "Noto Sans CJK KR"] if n in _fonts), "DejaVu Sans")
plt.rcParams.update({
"font.family": FONT, "mathtext.fontset": "dejavusans",
"font.size": 11, "axes.unicode_minus": False, "svg.fonttype": "path", "svg.hashsalt": PREFIX,
"axes.edgecolor": INK, "axes.labelcolor": INK, "xtick.color": INK, "ytick.color": INK,
"text.color": INK, "legend.frameon": False,
"axes.facecolor": "none", "figure.facecolor": "none", "savefig.transparent": True,
"axes.spines.top": False, "axes.spines.right": False,
})
def save(fig, k):
fig.savefig(os.path.join(HERE, f"{PREFIX}_fig{k}.svg"), bbox_inches="tight", metadata={"Date": None})
plt.close(fig)
from fractions import Fraction as Fr
def expo(T, alpha, S1):
S, out = Fr(S1), [Fr(S1)]
for t in T:
S = alpha * t + (1 - alpha) * S # S_{n+1} = a T_n + (1-a) S_n
out.append(S)
return out
def simple(T):
return [Fr(sum(T[:k]), k) for k in range(1, len(T) + 1)] # S_{k+1} = (T_1 + ... + T_k) / k
T = [6, 4, 6, 4, 13, 13, 13]
n_actual = np.arange(1, len(T) + 1)
n_pred = np.arange(1, len(T) + 2)
# 그림 1: 실제 버스트와 α별 지수 평균, 단순 평균
fig, ax = plt.subplots(figsize=(6, 3.6))
ax.plot(n_actual, T, "o", color=INK, ms=7, label="실제 $T_n$", zorder=5)
for i, a in enumerate([Fr(1, 5), Fr(1, 2), Fr(4, 5)]):
S = [float(x) for x in expo(T, a, 10)]
ax.plot(n_pred, S, "-", marker=".", color=C[i], lw=1.6, label=f"지수 평균 α = {float(a):.1f}")
ax.plot(n_pred[1:], [float(x) for x in simple(T)], "--", marker=".", color=C[3], lw=1.4, label="단순 평균")
ax.set_xlabel("$n$ (몇 번째 버스트)")
ax.set_ylabel("시간")
ax.set_xticks(n_pred)
ax.set_ylim(2, 15)
ax.legend(loc="center left", bbox_to_anchor=(1.01, 0.5), fontsize=9)
save(fig, 1)
if __name__ == "__main__":
assert expo(T, Fr(1, 2), 10) == [10, 8, 6, 6, 5, 9, 11, 12] # 문서 표
S08 = expo(T, Fr(4, 5), 10)
S02 = expo(T, Fr(1, 5), 10)
# 13으로 뛴 뒤 α가 클수록 빨리 따라간다: n = 8에서 0.8 > 0.5 > 0.2 > 단순 평균
assert S08[7] > 12 > S02[7] > simple(T)[-1]
assert simple(T)[-1] == Fr(59, 7)
print("ALL CHECKS PASSED")