합성곱 연습 문서의 문제 2 풀이 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""합성곱 연습 p1·p2: 사각 펄스끼리의 합성곱.
p1: f = h = 1 (0 ≤ t < 1)이면 f * h는 0~1에서 t, 1~2에서 2 - t인 삼각형.
p2: x = 2 (0 ≤ t < 2), h = 1 (0 ≤ t < 1)이면
y = 0 (t < 0), 2t (0~1), 2 (1~2), 2(3 - t) (2~3), 0 (t > 3).
연속 합성곱은 간격 dt로 잘게 나눈 리만 합으로 근사한다.
"""
def rect(a, b, height=1.0):
return lambda t: height if a <= t < b else 0.0
def conv_at(f, h, t, lo=-1.0, hi=5.0, dt=1e-3):
n = int((hi - lo) / dt)
return sum(f(lo + (k + 0.5) * dt) * h(t - (lo + (k + 0.5) * dt)) for k in range(n)) * dt
def main() -> None:
f = h = rect(0, 1)
tri = lambda t: t if 0 <= t <= 1 else (2 - t if 1 < t <= 2 else 0.0)
for t in [-0.5, 0.25, 0.5, 1.0, 1.5, 1.9, 2.5]:
assert abs(conv_at(f, h, t) - tri(t)) < 5e-3
x, h2 = rect(0, 2, 2.0), rect(0, 1)
def y(t):
if t < 0 or t > 3:
return 0.0
if t <= 1:
return 2 * t
if t <= 2:
return 2.0
return 2 * (3 - t)
for t in [-0.5, 0.3, 0.9, 1.4, 2.0, 2.6, 3.4]:
assert abs(conv_at(x, h2, t) - y(t)) < 1e-2
h3 = rect(0, 2) # 변형 1: h 폭 2 → 꼭대기 (2, 4)인 삼각형
for t, want in [(1.0, 2.0), (2.0, 4.0), (3.0, 2.0), (4.2, 0.0)]:
assert abs(conv_at(x, h3, t) - want) < 1e-2
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()