합성곱 연습 문서의 문제 4 풀이 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""합성곱 연습 p3·p4: 임펄스와의 합성곱과 문제 4의 네 줄.
x는 0 ≤ t < 0.5에서 1인 사각 펄스(둘째 줄은 1 ≤ t < 1.5의 펄스가 하나 더 있다).
줄 1: h = 같은 펄스 → 0~1의 삼각형, 꼭대기 (0.5, 0.5)
줄 2: x가 펄스 둘 → 0~1과 1~2에 같은 삼각형 둘
줄 3: h = δ(t - 1) → x를 1만큼 옮긴 펄스, 1 ≤ t < 1.5
줄 4: h = δ(t - 0.5) + c δ(t - 1.5) → 0.5~1에 높이 1, 1.5~2에 높이 c인 펄스 둘
(c는 둘째 임펄스의 높이, 약 1/2로 둔다)
임펄스와의 합성곱은 x를 그 자리로 옮겨 놓는 일이라 식으로 바로 계산한다.
"""
def pulse(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=4.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:
x = pulse(0, 0.5)
# 줄 1
tri = lambda t: t if 0 <= t <= 0.5 else (1 - t if 0.5 < t <= 1 else 0.0)
for t in [0.1, 0.5, 0.8, 1.2]:
assert abs(conv_at(x, x, t) - tri(t)) < 5e-3
# 줄 2
x2 = lambda t: x(t) + x(t - 1)
for t in [0.5, 1.0, 1.5, 1.75]:
assert abs(conv_at(x2, x, t) - (tri(t) + tri(t - 1))) < 5e-3
assert abs(conv_at(x2, x, 1.5) - 0.5) < 5e-3
# 줄 3, 4: δ(t - a)와의 합성곱은 x(t - a)
shift = lambda f, a: (lambda t: f(t - a))
y3 = shift(x, 1)
assert y3(0.9) == 0 and y3(1.2) == 1 and y3(1.6) == 0
c = 0.5
y4 = lambda t: x(t - 0.5) + c * x(t - 1.5)
assert y4(0.7) == 1 and y4(1.2) == 0 and y4(1.7) == 0.5 and y4(2.1) == 0
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()