Z λ³€ν™˜(Z-Transform)

Z λ³€ν™˜(Z-Transform)

κ°œμš”

Z λ³€ν™˜μ€ λΌν”ŒλΌμŠ€ λ³€ν™˜(Laplace Transform)의 이산 μ‹œκ°„(discrete-time) λŒ€μ‘ κ°œλ…μž…λ‹ˆλ‹€. μ°¨λΆ„ 방정식(difference equation)을 λŒ€μˆ˜ λ°©μ •μ‹μœΌλ‘œ λ³€ν™˜ν•˜μ—¬, λ³΅μ†Œ $z$ ν‰λ©΄μ—μ„œ 이산 μ‹œκ°„ LTI μ‹œμŠ€ν…œμ„ 뢄석할 수 있게 ν•΄μ€λ‹ˆλ‹€. Z λ³€ν™˜μ€ μ‹œμŠ€ν…œ μ•ˆμ •μ„±, 주파수 응닡, 전달 ν•¨μˆ˜ 결정에 κ°•λ ₯ν•œ 도ꡬλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. 이 λ ˆμŠ¨μ—μ„œλŠ” Z λ³€ν™˜ 이둠, μ„±μ§ˆ, μ—­λ³€ν™˜ 방법, 그리고 λ””μ§€ν„Έ μ‹œμŠ€ν…œ 뢄석 μ‘μš©μ„ λ‹€λ£Ήλ‹ˆλ‹€.

ν•™μŠ΅ λͺ©ν‘œ: - μ–‘λ°©ν–₯(bilateral) 및 단방ν–₯(unilateral) Z λ³€ν™˜μ„ μ •μ˜ν•˜κ³  κ³„μ‚°ν•˜κΈ° - 수렴 μ˜μ—­(ROC, Region of Convergence)κ³Ό κ·Έ 의미 μ΄ν•΄ν•˜κΈ° - μ‹œμŠ€ν…œ 뢄석을 μœ„ν•œ Z λ³€ν™˜ μ„±μ§ˆ μ μš©ν•˜κΈ° - λ‹€μ–‘ν•œ λ°©λ²•μœΌλ‘œ μ—­ Z λ³€ν™˜ κ³„μ‚°ν•˜κΈ° - 전달 ν•¨μˆ˜, 극점(poles), 영점(zeros)을 μ΄μš©ν•˜μ—¬ LTI μ‹œμŠ€ν…œ λΆ„μ„ν•˜κΈ° - Z λ³€ν™˜κ³Ό DTFT 및 λΌν”ŒλΌμŠ€ λ³€ν™˜μ˜ 관계 μ΄ν•΄ν•˜κΈ°

μ„ μˆ˜ ν•™μŠ΅: 06. 이산 푸리에 λ³€ν™˜


1. Z λ³€ν™˜μ˜ μ •μ˜

1.1 μ–‘λ°©ν–₯ Z λ³€ν™˜(Bilateral Z-Transform)

이산 μ‹œκ°„ μ‹ ν˜Έ $x[n]$의 μ–‘λ°©ν–₯(두 λ°©ν–₯) Z λ³€ν™˜μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

$$\boxed{X(z) = \mathcal{Z}\{x[n]\} = \sum_{n=-\infty}^{\infty} x[n] \, z^{-n}}$$

μ—¬κΈ°μ„œ $z$λŠ” λ³΅μ†Œ λ³€μˆ˜λ‘œ, $z = r \, e^{j\omega}$μž…λ‹ˆλ‹€.

1.2 단방ν–₯ Z λ³€ν™˜(Unilateral Z-Transform)

단방ν–₯(ν•œ λ°©ν–₯) Z λ³€ν™˜μ€ 초기 쑰건이 μžˆλŠ” 인과 μ‹ ν˜Έμ™€ μ‹œμŠ€ν…œμ— μ‚¬μš©λ©λ‹ˆλ‹€:

$$X(z) = \sum_{n=0}^{\infty} x[n] \, z^{-n}$$

이 ν˜•νƒœλŠ” 특히 λΉ„μ˜(non-zero) 초기 쑰건이 μžˆλŠ” μ°¨λΆ„ 방정식을 ν’€ λ•Œ μœ μš©ν•©λ‹ˆλ‹€.

1.3 직관적 이해: zλŠ” 무엇인가?

λ³΅μ†Œ λ³€μˆ˜ $z = r \, e^{j\omega}$λŠ” λ‹€μŒκ³Ό 같이 λΆ„ν•΄λ©λ‹ˆλ‹€: - $|z| = r$: μ›μ μœΌλ‘œλΆ€ν„°μ˜ 반경(μ§€μˆ˜ 가쀑을 톡해 수렴 μ œμ–΄) - $\angle z = \omega$: 각도(μ£ΌνŒŒμˆ˜μ— λŒ€μ‘) - λ‹¨μœ„μ›(unit circle) μœ„($r = 1$, $z = e^{j\omega}$): Z λ³€ν™˜μ€ DTFT둜 좕약됨

1.4 μ£Όμš” Z λ³€ν™˜ 쌍(Common Z-Transform Pairs)

μ‹ ν˜Έ $x[n]$ Z λ³€ν™˜ $X(z)$ ROC
$\delta[n]$ $1$ λͺ¨λ“  $z$
$u[n]$ (λ‹¨μœ„ 계단) $\frac{z}{z-1} = \frac{1}{1-z^{-1}}$ $|z| > 1$
$a^n u[n]$ $\frac{z}{z-a} = \frac{1}{1-az^{-1}}$ $|z| > |a|$
$-a^n u[-n-1]$ $\frac{z}{z-a} = \frac{1}{1-az^{-1}}$ $|z| < |a|$
$n a^n u[n]$ $\frac{az}{(z-a)^2} = \frac{az^{-1}}{(1-az^{-1})^2}$ $|z| > |a|$
$\cos(\omega_0 n) u[n]$ $\frac{z(z-\cos\omega_0)}{z^2 - 2z\cos\omega_0 + 1}$ $|z| > 1$
$r^n \cos(\omega_0 n) u[n]$ $\frac{z(z - r\cos\omega_0)}{z^2 - 2rz\cos\omega_0 + r^2}$ $|z| > r$
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

def compute_z_transform_examples():
    """Compute and verify common Z-transform pairs."""
    # Example 1: x[n] = (0.8)^n * u[n]
    a = 0.8
    N = 50
    n = np.arange(N)
    x = a ** n  # Causal exponential

    # Z-transform: X(z) = 1 / (1 - 0.8 * z^{-1}), |z| > 0.8
    # Evaluate on unit circle (should give DTFT)
    omega = np.linspace(-np.pi, np.pi, 1024)
    z_unit = np.exp(1j * omega)

    # X(z) on unit circle
    X_formula = 1.0 / (1.0 - a * z_unit ** (-1))

    # DTFT (direct computation from samples)
    X_dtft = np.zeros(len(omega), dtype=complex)
    for k in range(N):
        X_dtft += x[k] * np.exp(-1j * omega * k)

    # Compare
    fig, axes = plt.subplots(2, 1, figsize=(12, 8))

    axes[0].plot(omega / np.pi, np.abs(X_formula), 'b-', linewidth=2,
                 label='Z-transform formula')
    axes[0].plot(omega / np.pi, np.abs(X_dtft), 'r--', linewidth=1,
                 label=f'DTFT (N={N} terms)')
    axes[0].set_title(r'$x[n] = 0.8^n u[n]$: Magnitude on Unit Circle')
    axes[0].set_xlabel(r'$\omega / \pi$')
    axes[0].set_ylabel(r'$|X(e^{j\omega})|$')
    axes[0].legend()
    axes[0].grid(True, alpha=0.3)

    axes[1].plot(omega / np.pi, np.angle(X_formula), 'b-', linewidth=2,
                 label='Z-transform formula')
    axes[1].plot(omega / np.pi, np.angle(X_dtft), 'r--', linewidth=1,
                 label=f'DTFT (N={N} terms)')
    axes[1].set_title('Phase on Unit Circle')
    axes[1].set_xlabel(r'$\omega / \pi$')
    axes[1].set_ylabel('Phase (radians)')
    axes[1].legend()
    axes[1].grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('ztransform_unit_circle.png', dpi=150)
    plt.show()

compute_z_transform_examples()

2. 수렴 μ˜μ—­(ROC, Region of Convergence)

2.1 μ •μ˜

ROCλŠ” Z λ³€ν™˜μ˜ 합이 μˆ˜λ ΄ν•˜λŠ” λͺ¨λ“  $z$ κ°’μ˜ μ§‘ν•©μž…λ‹ˆλ‹€:

$$\text{ROC} = \left\{ z \in \mathbb{C} : \sum_{n=-\infty}^{\infty} |x[n]| \, |z|^{-n} < \infty \right\}$$

ROCλŠ” 항상 z ν‰λ©΄μ—μ„œ ν™˜ν˜•(annular) μ˜μ—­μž…λ‹ˆλ‹€(원점을 μ€‘μ‹¬μœΌλ‘œ ν•œ 두 동심원 μ‚¬μ΄μ˜ 고리):

$$R^{-} < |z| < R^{+}$$

2.2 ROC μ„±μ§ˆ

  1. ROCμ—λŠ” $X(z)$의 극점(poles)이 ν¬ν•¨λ˜μ§€ μ•ŠμŒ
  2. μœ ν•œ 지속 μ‹ ν˜Έ(finite-duration signals): ROCλŠ” 전체 z 평면($z = 0$ 및/λ˜λŠ” $z = \infty$ μ œμ™Έ κ°€λŠ₯)
  3. 였λ₯Έμͺ½ μ‹ ν˜Έ(right-sided signals) ($x[n] = 0$, $n < N_1$): ROCλŠ” 원 μ™ΈλΆ€: $|z| > R^{-}$
  4. μ™Όμͺ½ μ‹ ν˜Έ(left-sided signals) ($x[n] = 0$, $n > N_2$): ROCλŠ” 원 λ‚΄λΆ€: $|z| < R^{+}$
  5. μ–‘λ°©ν–₯ μ‹ ν˜Έ(two-sided signals): ROCλŠ” ν™˜ν˜• 고리
  6. DTFT 쑴재: ROCκ°€ λ‹¨μœ„μ› $|z| = 1$을 포함할 κ²½μš°μ—λ§Œ 쑴재
  7. 인과적이고 μ•ˆμ •μ μΈ μ‹œμŠ€ν…œ: ROCκ°€ λ‹¨μœ„μ› μ™ΈλΆ€κΉŒμ§€ 포함; λͺ¨λ“  극점은 λ‹¨μœ„μ› 내뢀에 μœ„μΉ˜

2.3 ROC와 μ‹ ν˜Έ μœ ν˜•: λ™μΌν•œ X(z), λ‹€λ₯Έ μ‹ ν˜Έ

Z λ³€ν™˜ $X(z) = \frac{1}{1 - az^{-1}}$은 ROC에 따라 두 κ°€μ§€ λ‹€λ₯Έ μ‹ ν˜Έμ— λŒ€μ‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

  • ROC: $|z| > |a|$ $\implies$ $x[n] = a^n u[n]$ (인과적, 였λ₯Έμͺ½ μ‹ ν˜Έ)
  • ROC: $|z| < |a|$ $\implies$ $x[n] = -a^n u[-n-1]$ (반인과적, μ™Όμͺ½ μ‹ ν˜Έ)

이 λ•Œλ¬Έμ— ROCκ°€ ν•„μˆ˜μ μž…λ‹ˆλ‹€: ROC 없이 $X(z)$ λ‹¨λ…μœΌλ‘œλŠ” $x[n]$을 μœ μΌν•˜κ²Œ κ²°μ •ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

def visualize_roc():
    """Visualize ROC for different signal types."""
    fig, axes = plt.subplots(1, 3, figsize=(15, 5))

    theta = np.linspace(0, 2 * np.pi, 200)

    # Case 1: Causal signal x[n] = 0.7^n u[n], ROC: |z| > 0.7
    ax = axes[0]
    # Unit circle
    ax.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=1)
    # Pole at z = 0.7
    ax.plot(0.7, 0, 'rx', markersize=12, markeredgewidth=2, label='Pole')
    # ROC: |z| > 0.7 (shade exterior)
    r_roc = 0.7
    circle = plt.Circle((0, 0), r_roc, fill=True, color='lightblue',
                         alpha=0.5, label=f'ROC: |z| > {r_roc}')
    ax.add_patch(circle)
    ax.fill_between(np.cos(theta) * 2, np.sin(theta) * 2,
                    alpha=0.2, color='green')
    ax.set_xlim(-2, 2)
    ax.set_ylim(-2, 2)
    ax.set_aspect('equal')
    ax.set_title(r'Causal: $0.7^n u[n]$' + '\nROC: |z| > 0.7')
    ax.axhline(0, color='gray', linewidth=0.5)
    ax.axvline(0, color='gray', linewidth=0.5)
    ax.legend(fontsize=8)
    ax.grid(True, alpha=0.3)

    # Case 2: Anti-causal signal, ROC: |z| < 0.7
    ax = axes[1]
    ax.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=1)
    ax.plot(0.7, 0, 'rx', markersize=12, markeredgewidth=2, label='Pole')
    circle = plt.Circle((0, 0), r_roc, fill=True, color='lightgreen',
                         alpha=0.5, label=f'ROC: |z| < {r_roc}')
    ax.add_patch(circle)
    ax.set_xlim(-2, 2)
    ax.set_ylim(-2, 2)
    ax.set_aspect('equal')
    ax.set_title(r'Anti-causal: $-0.7^n u[-n-1]$' + '\nROC: |z| < 0.7')
    ax.axhline(0, color='gray', linewidth=0.5)
    ax.axvline(0, color='gray', linewidth=0.5)
    ax.legend(fontsize=8)
    ax.grid(True, alpha=0.3)

    # Case 3: Two-sided signal, ROC: annular ring
    ax = axes[2]
    ax.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=1)
    ax.plot(0.5, 0, 'rx', markersize=12, markeredgewidth=2, label='Poles')
    ax.plot(1.5, 0, 'rx', markersize=12, markeredgewidth=2)
    # ROC: 0.5 < |z| < 1.5
    for r in [0.5, 1.5]:
        ax.plot(r * np.cos(theta), r * np.sin(theta), 'b--', linewidth=1)
    # Shade annular region
    theta_fill = np.linspace(0, 2 * np.pi, 100)
    r_inner, r_outer = 0.5, 1.5
    ax.fill_between(
        np.concatenate([r_inner * np.cos(theta_fill),
                        r_outer * np.cos(theta_fill[::-1])]),
        np.concatenate([r_inner * np.sin(theta_fill),
                        r_outer * np.sin(theta_fill[::-1])]),
        alpha=0.3, color='yellow', label='ROC: 0.5 < |z| < 1.5'
    )
    ax.set_xlim(-2, 2)
    ax.set_ylim(-2, 2)
    ax.set_aspect('equal')
    ax.set_title('Two-sided signal\nROC: 0.5 < |z| < 1.5')
    ax.axhline(0, color='gray', linewidth=0.5)
    ax.axvline(0, color='gray', linewidth=0.5)
    ax.legend(fontsize=8)
    ax.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('roc_visualization.png', dpi=150)
    plt.show()

visualize_roc()

3. Z λ³€ν™˜μ˜ μ„±μ§ˆ(Properties of the Z-Transform)

3.1 μ„ ν˜•μ„±(Linearity)

$$a \, x_1[n] + b \, x_2[n] \quad \xleftrightarrow{\mathcal{Z}} \quad a \, X_1(z) + b \, X_2(z)$$

ROC: 적어도 $\text{ROC}_1 \cap \text{ROC}_2$ (극점-영점 상쇄가 λ°œμƒν•˜λ©΄ 더 클 수 있음).

3.2 μ‹œκ°„ 이동(Time Shifting)

$$x[n - n_0] \quad \xleftrightarrow{\mathcal{Z}} \quad z^{-n_0} X(z)$$

ROC: $X(z)$와 동일 ($z = 0$ λ˜λŠ” $z = \infty$ μΆ”κ°€/제거 κ°€λŠ₯).

μ§€μ—° μ—°μ‚°μž $z^{-1}$은 λ””μ§€ν„Έ μ‹œμŠ€ν…œμ˜ κΈ°λ³Έ μš”μ†Œμž…λ‹ˆλ‹€. ν•œ μƒ˜ν”Œμ˜ 지연은 $z^{-1}$ κ³±μ…ˆμœΌλ‘œ ν‘œν˜„λ©λ‹ˆλ‹€.

3.3 z μ˜μ—­μ—μ„œμ˜ μŠ€μΌ€μΌλ§(Scaling in the z-Domain)

$$a^n x[n] \quad \xleftrightarrow{\mathcal{Z}} \quad X(z/a)$$

ROC: $|a| \cdot R^{-} < |z| < |a| \cdot R^{+}$ (ROCκ°€ $|a|$만큼 μŠ€μΌ€μΌλ§λ¨).

3.4 μ‹œκ°„ μ—­μ „(Time Reversal)

$$x[-n] \quad \xleftrightarrow{\mathcal{Z}} \quad X(z^{-1})$$

ROC: $1/R^{+} < |z| < 1/R^{-}$ (ROCκ°€ 역전됨).

3.5 z μ˜μ—­μ—μ„œμ˜ λ―ΈλΆ„(Differentiation in z-Domain)

$$n \, x[n] \quad \xleftrightarrow{\mathcal{Z}} \quad -z \frac{dX(z)}{dz}$$

$n \cdot a^n$ κ΄€λ ¨ λ³€ν™˜ λ„μΆœμ— μœ μš©ν•©λ‹ˆλ‹€.

3.6 μ»¨λ³Όλ£¨μ…˜(Convolution)

$$x_1[n] * x_2[n] \quad \xleftrightarrow{\mathcal{Z}} \quad X_1(z) \cdot X_2(z)$$

ROC: 적어도 $\text{ROC}_1 \cap \text{ROC}_2$.

μ‹œμŠ€ν…œ λΆ„μ„μ—μ„œ κ°€μž₯ μ€‘μš”ν•œ μ„±μ§ˆμž…λ‹ˆλ‹€: μ‹œκ°„ μ˜μ—­μ˜ μ»¨λ³Όλ£¨μ…˜μ΄ z μ˜μ—­μ—μ„œ κ³±μ…ˆμœΌλ‘œ λ³€ν™˜λ©λ‹ˆλ‹€.

3.7 μ΄ˆκΈ°κ°’ 정리(Initial Value Theorem, 인과 μ‹ ν˜Έ)

$$x[0] = \lim_{z \to \infty} X(z)$$

3.8 μ΅œμ’…κ°’ 정리(Final Value Theorem)

$(1 - z^{-1})X(z)$의 λͺ¨λ“  극점이 λ‹¨μœ„μ› 내뢀에 μžˆλŠ” 경우:

$$\lim_{n \to \infty} x[n] = \lim_{z \to 1} (1 - z^{-1}) X(z)$$

3.9 μ„±μ§ˆ μš”μ•½ν‘œ

μ„±μ§ˆ μ‹œκ°„ μ˜μ—­ Z μ˜μ—­ ROC
μ„ ν˜•μ„± $ax_1 + bx_2$ $aX_1 + bX_2$ $\supseteq R_1 \cap R_2$
μ‹œκ°„ 이동 $x[n-n_0]$ $z^{-n_0}X(z)$ $R$ (κ²½μš°μ— 따라 $\pm$ 0, $\infty$)
μŠ€μΌ€μΌλ§ $a^n x[n]$ $X(z/a)$ $|a| \cdot R$
μ—­μ „ $x[-n]$ $X(1/z)$ $1/R$
λ―ΈλΆ„ $nx[n]$ $-z\frac{dX}{dz}$ $R$
μ»¨λ³Όλ£¨μ…˜ $x_1 * x_2$ $X_1 X_2$ $\supseteq R_1 \cap R_2$
λˆ„μ  $\sum_{k=-\infty}^{n} x[k]$ $\frac{X(z)}{1-z^{-1}}$ $R \cap \{|z|>1\}$
def demonstrate_z_properties():
    """Numerically verify Z-transform properties."""
    # Test signal: x[n] = 0.8^n * u[n], truncated to 100 samples
    N = 100
    a = 0.8
    n = np.arange(N)
    x = a ** n

    # Evaluate Z-transforms on the unit circle
    omega = np.linspace(-np.pi, np.pi, 512)
    z = np.exp(1j * omega)

    def zt_on_circle(signal, omega_vals):
        """Compute Z-transform on unit circle (= DTFT)."""
        z_vals = np.exp(1j * omega_vals)
        result = np.zeros(len(omega_vals), dtype=complex)
        for k in range(len(signal)):
            result += signal[k] * z_vals ** (-k)
        return result

    # Property 1: Time shift
    m = 5
    x_shifted = np.zeros(N + m)
    x_shifted[m:m + N] = x

    X_orig = zt_on_circle(x, omega)
    X_shifted_direct = zt_on_circle(x_shifted, omega)
    X_shifted_property = np.exp(-1j * omega * m) * X_orig

    # Property 2: Convolution
    h = 0.5 ** n  # Another causal exponential
    y_conv = np.convolve(x[:50], h[:50])  # Linear convolution

    X_x = zt_on_circle(x[:50], omega)
    H_z = zt_on_circle(h[:50], omega)
    Y_product = X_x * H_z
    Y_conv_direct = zt_on_circle(y_conv, omega)

    fig, axes = plt.subplots(2, 2, figsize=(14, 10))

    # Time shift verification
    axes[0, 0].plot(omega / np.pi, np.abs(X_shifted_direct), 'b-',
                    linewidth=2, label='Direct')
    axes[0, 0].plot(omega / np.pi, np.abs(X_shifted_property), 'r--',
                    linewidth=1, label='z^{-m} X(z)')
    axes[0, 0].set_title(f'Time Shift Property (m={m}): Magnitude')
    axes[0, 0].legend()
    axes[0, 0].grid(True, alpha=0.3)

    axes[0, 1].plot(omega / np.pi,
                    np.abs(X_shifted_direct - X_shifted_property), 'k-')
    axes[0, 1].set_title(f'Time Shift Error')
    axes[0, 1].set_ylabel('|Error|')
    axes[0, 1].grid(True, alpha=0.3)

    # Convolution verification
    axes[1, 0].plot(omega / np.pi, np.abs(Y_conv_direct), 'b-',
                    linewidth=2, label='Z{x*h}')
    axes[1, 0].plot(omega / np.pi, np.abs(Y_product), 'r--',
                    linewidth=1, label='X(z)H(z)')
    axes[1, 0].set_title('Convolution Property: Magnitude')
    axes[1, 0].legend()
    axes[1, 0].grid(True, alpha=0.3)

    axes[1, 1].plot(omega / np.pi, np.abs(Y_conv_direct - Y_product), 'k-')
    axes[1, 1].set_title('Convolution Property Error')
    axes[1, 1].set_ylabel('|Error|')
    axes[1, 1].grid(True, alpha=0.3)

    for ax in axes.flat:
        ax.set_xlabel(r'$\omega / \pi$')

    plt.tight_layout()
    plt.savefig('z_properties.png', dpi=150)
    plt.show()

demonstrate_z_properties()

4. μ—­ Z λ³€ν™˜(Inverse Z-Transform)

4.1 ν˜•μ‹μ  μ •μ˜

$$x[n] = \frac{1}{2\pi j} \oint_C X(z) \, z^{n-1} \, dz$$

μ—¬κΈ°μ„œ $C$λŠ” ROC λ‚΄μ—μ„œ 원점을 λ‘˜λŸ¬μ‹ΈλŠ” λ°˜μ‹œκ³„ λ°©ν–₯ κ²½λ‘œμž…λ‹ˆλ‹€.

μ‹€μ œλ‘œλŠ” μ„Έ κ°€μ§€ 방법이 일반적으둜 μ‚¬μš©λ©λ‹ˆλ‹€:

4.2 방법 1: λΆ€λΆ„ λΆ„μˆ˜ μ „κ°œ(Partial Fraction Expansion)

유리 ν•¨μˆ˜ $X(z) = B(z)/A(z)$에 λŒ€ν•΄, λ‹¨μˆœ λΆ„μˆ˜λ‘œ λΆ„ν•΄ν•©λ‹ˆλ‹€:

$$X(z) = \sum_i \frac{A_i}{1 - p_i z^{-1}} + \cdots$$

각 항은 μ•Œλ €μ§„ μ—­ Z λ³€ν™˜μ„ κ°€μ§€λ©°, ROCκ°€ 각 항이 인과적인지 λ°˜μΈκ³Όμ μΈμ§€λ₯Ό κ²°μ •ν•©λ‹ˆλ‹€.

μ˜ˆμ‹œ:

$$X(z) = \frac{1}{(1 - 0.5z^{-1})(1 - 0.8z^{-1})}, \quad |z| > 0.8$$

λΆ€λΆ„ λΆ„μˆ˜ μ „κ°œ:

$$X(z) = \frac{A}{1 - 0.5z^{-1}} + \frac{B}{1 - 0.8z^{-1}}$$

ν’€λ©΄: $A = \frac{-5}{3}$, $B = \frac{8}{3}$

ROCκ°€ $|z| > 0.8$μ΄λ―€λ‘œ(두 극점 λͺ¨λ‘ ROC λ‚΄λΆ€), 두 ν•­ λͺ¨λ‘ 인과적:

$$x[n] = \left(-\frac{5}{3}(0.5)^n + \frac{8}{3}(0.8)^n\right) u[n]$$

def partial_fraction_inverse_z():
    """Inverse Z-transform via partial fraction expansion."""
    # X(z) = 1 / ((1 - 0.5 z^{-1})(1 - 0.8 z^{-1}))
    # Numerator: [1] (in z^{-1} form)
    # Denominator: (1 - 0.5 z^{-1})(1 - 0.8 z^{-1})
    #            = 1 - 1.3 z^{-1} + 0.4 z^{-2}

    # Using scipy.signal for partial fractions
    # Express as H(z) = B(z)/A(z) in descending powers of z
    # B(z) = 1
    # A(z) = 1 - 1.3 z^{-1} + 0.4 z^{-2}

    b = [1.0]                   # Numerator coefficients
    a = [1.0, -1.3, 0.4]       # Denominator coefficients

    # Partial fraction expansion
    # scipy uses z (not z^{-1}), so we need to be careful
    # Convert to z-form: multiply num/den by z^2
    b_z = [0, 0, 1]            # z^0 (need to match length)
    a_z = [1, -1.3, 0.4]       # z^2 - 1.3z + 0.4

    residues, poles, remainder = signal.residuez(b, a)

    print("Partial Fraction Expansion")
    print("=" * 50)
    print(f"X(z) = 1 / ((1 - 0.5z^-1)(1 - 0.8z^-1))")
    print(f"\nPoles: {poles}")
    print(f"Residues: {residues}")
    print(f"Remainder: {remainder}")

    # Reconstruct x[n]
    N = 30
    n = np.arange(N)

    # From partial fractions (causal, ROC: |z| > 0.8)
    x_pf = np.zeros(N)
    for r, p in zip(residues, poles):
        x_pf += np.real(r * p ** n)

    # Direct computation via scipy.signal (impulse response)
    _, x_impulse = signal.dimpulse(signal.dlti(b, a, dt=1), n=N)
    x_impulse = np.squeeze(x_impulse)

    fig, ax = plt.subplots(figsize=(12, 5))
    ax.stem(n, x_pf, linefmt='b-', markerfmt='bo', basefmt='k-',
            label='Partial fractions')
    ax.plot(n, x_impulse, 'rx', markersize=8, label='scipy dimpulse')
    ax.set_title('Inverse Z-Transform via Partial Fractions')
    ax.set_xlabel('n')
    ax.set_ylabel('x[n]')
    ax.legend()
    ax.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('inverse_z_partial.png', dpi=150)
    plt.show()

partial_fraction_inverse_z()

4.3 방법 2: κΈ΄ λ‚˜λˆ—μ…ˆ(Long Division, λ©±κΈ‰μˆ˜ μ „κ°œ)

$B(z^{-1})$을 $A(z^{-1})$둜 λ‚˜λˆ„μ–΄ $z^{-n}$의 κ³„μˆ˜λ₯Ό κ΅¬ν•˜λ©΄, 이 κ³„μˆ˜λ“€μ΄ $x[n]$의 값이 λ©λ‹ˆλ‹€.

μ˜ˆμ‹œ:

$$X(z) = \frac{1}{1 - 1.5z^{-1} + 0.5z^{-2}}$$

$z^{-1}$μ—μ„œμ˜ κΈ΄ λ‚˜λˆ—μ…ˆ:

$$\frac{1}{1 - 1.5z^{-1} + 0.5z^{-2}} = 1 + 1.5z^{-1} + 1.75z^{-2} + 1.875z^{-3} + \cdots$$

λ”°λΌμ„œ $x[0] = 1$, $x[1] = 1.5$, $x[2] = 1.75$, $x[3] = 1.875$, ...

def long_division_inverse_z():
    """Inverse Z-transform via long division."""
    # X(z) = B(z^{-1}) / A(z^{-1})
    b = np.array([1.0])
    a = np.array([1.0, -1.5, 0.5])

    N = 20
    x = np.zeros(N)

    # Long division algorithm
    remainder = np.zeros(len(b) + N)
    remainder[:len(b)] = b

    for n in range(N):
        x[n] = remainder[0] / a[0]
        for k in range(len(a)):
            if k < len(remainder):
                remainder[k] -= x[n] * a[k]
        remainder = np.roll(remainder, -1)
        remainder[-1] = 0

    # Verify with scipy
    _, x_scipy = signal.dimpulse(signal.dlti(b, a, dt=1), n=N)
    x_scipy = np.squeeze(x_scipy)

    print("Long Division Inverse Z-Transform")
    print("=" * 40)
    print(f"X(z) = 1 / (1 - 1.5z^(-1) + 0.5z^(-2))")
    print(f"\n{'n':>4s} | {'x[n] (long div)':>16s} | {'x[n] (scipy)':>14s}")
    print("-" * 40)
    for i in range(min(10, N)):
        print(f"{i:4d} | {x[i]:16.6f} | {x_scipy[i]:14.6f}")

long_division_inverse_z()

4.4 방법 3: 경둜 적뢄(Contour Integration, 유수 정리)

$$x[n] = \sum_{\text{poles } p_k \text{ inside } C} \text{Res}\left[X(z) z^{n-1}, p_k\right]$$

$z = p_k$μ—μ„œμ˜ λ‹¨μˆœ 극점에 λŒ€ν•΄:

$$\text{Res}\left[X(z)z^{n-1}, p_k\right] = \lim_{z \to p_k} (z - p_k) X(z) z^{n-1}$$


5. 전달 ν•¨μˆ˜ H(z)

5.1 μ •μ˜

μ°¨λΆ„ λ°©μ •μ‹μœΌλ‘œ κΈ°μˆ λ˜λŠ” LTI μ‹œμŠ€ν…œμ— λŒ€ν•΄:

$$\sum_{k=0}^{N} a_k \, y[n-k] = \sum_{k=0}^{M} b_k \, x[n-k]$$

전달 ν•¨μˆ˜(transfer function)λŠ”:

$$\boxed{H(z) = \frac{Y(z)}{X(z)} = \frac{\sum_{k=0}^{M} b_k z^{-k}}{\sum_{k=0}^{N} a_k z^{-k}} = \frac{B(z)}{A(z)}}$$

z μ˜μ—­μ—μ„œμ˜ 좜λ ₯은 λ‹¨μˆœνžˆ:

$$Y(z) = H(z) \cdot X(z)$$

5.2 μž„νŽ„μŠ€ 응닡과 전달 ν•¨μˆ˜

μž„νŽ„μŠ€ 응닡(impulse response) $h[n]$은 $H(z)$의 μ—­ Z λ³€ν™˜μž…λ‹ˆλ‹€:

$$h[n] = \mathcal{Z}^{-1}\{H(z)\}$$

$Y(z) = H(z) X(z)$이고 z μ˜μ—­μ˜ κ³±μ…ˆμ΄ μ‹œκ°„ μ˜μ—­μ˜ μ»¨λ³Όλ£¨μ…˜μ— λŒ€μ‘ν•˜λ―€λ‘œ:

$$y[n] = h[n] * x[n] = \sum_{k=-\infty}^{\infty} h[k] \, x[n-k]$$

5.3 μ˜ˆμ‹œ: 1μ°¨ μ‹œμŠ€ν…œ

$$y[n] = 0.9 \, y[n-1] + x[n]$$

전달 ν•¨μˆ˜:

$$H(z) = \frac{1}{1 - 0.9z^{-1}} = \frac{z}{z - 0.9}$$

  • $z = 0.9$μ—μ„œ 극점 ν•˜λ‚˜
  • $z = 0$μ—μ„œ 영점 ν•˜λ‚˜ ($z^{-1}$ ν˜•μ‹μ—μ„œμ˜ 자λͺ…ν•œ 영점)
def transfer_function_example():
    """Analyze a first-order digital system."""
    # y[n] = 0.9 * y[n-1] + x[n]
    # H(z) = 1 / (1 - 0.9 z^{-1})
    b = [1.0]
    a = [1.0, -0.9]

    # Create discrete-time system
    sys = signal.dlti(b, a, dt=1)

    # Impulse response
    t_imp, h = signal.dimpulse(sys, n=40)
    h = np.squeeze(h)

    # Step response
    t_step, s = signal.dstep(sys, n=40)
    s = np.squeeze(s)

    # Frequency response
    w, H = signal.freqz(b, a, worN=1024)

    fig, axes = plt.subplots(2, 2, figsize=(14, 10))

    # Impulse response
    axes[0, 0].stem(np.arange(len(h)), h, linefmt='b-', markerfmt='bo',
                    basefmt='k-')
    axes[0, 0].set_title('Impulse Response h[n]')
    axes[0, 0].set_xlabel('n')
    axes[0, 0].set_ylabel('h[n]')
    axes[0, 0].grid(True, alpha=0.3)

    # Step response
    axes[0, 1].stem(np.arange(len(s)), s, linefmt='r-', markerfmt='ro',
                    basefmt='k-')
    axes[0, 1].set_title('Step Response')
    axes[0, 1].set_xlabel('n')
    axes[0, 1].set_ylabel('y[n]')
    axes[0, 1].grid(True, alpha=0.3)

    # Magnitude response
    axes[1, 0].plot(w / np.pi, 20 * np.log10(np.abs(H)), 'b-', linewidth=2)
    axes[1, 0].set_title('Magnitude Response |H(e^jw)|')
    axes[1, 0].set_xlabel(r'$\omega / \pi$')
    axes[1, 0].set_ylabel('Magnitude (dB)')
    axes[1, 0].grid(True, alpha=0.3)

    # Phase response
    axes[1, 1].plot(w / np.pi, np.unwrap(np.angle(H)), 'r-', linewidth=2)
    axes[1, 1].set_title('Phase Response')
    axes[1, 1].set_xlabel(r'$\omega / \pi$')
    axes[1, 1].set_ylabel('Phase (radians)')
    axes[1, 1].grid(True, alpha=0.3)

    plt.suptitle(r'System: $y[n] = 0.9\,y[n-1] + x[n]$', fontsize=14)
    plt.tight_layout()
    plt.savefig('transfer_function.png', dpi=150)
    plt.show()

transfer_function_example()

6. z ν‰λ©΄μ˜ 극점과 영점(Poles and Zeros in the z-Plane)

6.1 μ •μ˜

유리(rational) 전달 ν•¨μˆ˜μ— λŒ€ν•΄:

$$H(z) = \frac{b_0 + b_1 z^{-1} + \cdots + b_M z^{-M}}{a_0 + a_1 z^{-1} + \cdots + a_N z^{-N}} = G \cdot \frac{\prod_{k=1}^{M}(z - z_k)}{\prod_{k=1}^{N}(z - p_k)}$$

  • 영점(zeros) ($z_k$): $H(z) = 0$이 λ˜λŠ” $z$ κ°’ (λΆ„μžμ˜ κ·Ό)
  • 극점(poles) ($p_k$): $H(z) \to \infty$κ°€ λ˜λŠ” $z$ κ°’ (λΆ„λͺ¨μ˜ κ·Ό)
  • $G$: 이득 인자(gain factor)

6.2 극점-영점 도식(Pole-Zero Plot)

def pole_zero_analysis():
    """Analyze a system using pole-zero plots."""
    # Second-order system (resonator)
    # H(z) = 1 / (1 - 2r cos(w0) z^{-1} + r^2 z^{-2})
    r = 0.9       # Pole radius (< 1 for stability)
    w0 = np.pi / 4  # Resonant frequency (pi/4 = fs/8)

    b = [1.0]
    a = [1.0, -2 * r * np.cos(w0), r ** 2]

    # Find poles and zeros
    zeros = np.roots(b)
    poles = np.roots(a)

    print("Pole-Zero Analysis")
    print("=" * 50)
    print(f"Zeros: {zeros}")
    print(f"Poles: {poles}")
    print(f"Pole magnitudes: {np.abs(poles)}")
    print(f"Pole angles: {np.angle(poles) / np.pi} * pi")
    print(f"Stable: {all(np.abs(poles) < 1)}")

    # Pole-zero plot and frequency response
    fig, axes = plt.subplots(1, 2, figsize=(14, 6))

    # Pole-zero plot
    ax = axes[0]
    theta = np.linspace(0, 2 * np.pi, 200)
    ax.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=1,
            label='Unit circle')

    # Plot zeros
    if len(zeros) > 0:
        ax.plot(np.real(zeros), np.imag(zeros), 'bo', markersize=10,
                label=f'Zeros ({len(zeros)})')

    # Plot poles
    ax.plot(np.real(poles), np.imag(poles), 'rx', markersize=12,
            markeredgewidth=2, label=f'Poles ({len(poles)})')

    ax.set_xlim(-1.5, 1.5)
    ax.set_ylim(-1.5, 1.5)
    ax.set_aspect('equal')
    ax.set_title('Pole-Zero Plot')
    ax.set_xlabel('Real')
    ax.set_ylabel('Imaginary')
    ax.axhline(0, color='gray', linewidth=0.5)
    ax.axvline(0, color='gray', linewidth=0.5)
    ax.legend()
    ax.grid(True, alpha=0.3)

    # Frequency response
    ax = axes[1]
    w, H = signal.freqz(b, a, worN=1024)
    ax.plot(w / np.pi, 20 * np.log10(np.abs(H)), 'b-', linewidth=2)
    ax.axvline(w0 / np.pi, color='red', linestyle='--', alpha=0.5,
               label=f'Resonant freq = {w0/np.pi:.2f}pi')
    ax.set_title('Magnitude Response')
    ax.set_xlabel(r'$\omega / \pi$')
    ax.set_ylabel('Magnitude (dB)')
    ax.legend()
    ax.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('pole_zero.png', dpi=150)
    plt.show()

pole_zero_analysis()

6.3 극점과 영점 μœ„μΉ˜μ˜ 효과

μœ„μΉ˜ 효과
λ‹¨μœ„μ› 근처의 극점 극점 κ°λ„μ—μ„œμ˜ 주파수 응닡에 λ‚ μΉ΄λ‘œμš΄ 피크
λ‹¨μœ„μ› μœ„μ˜ 영점 영점 κ°λ„μ—μ„œ 영(null) 이득
λ‹¨μœ„μ› λ‚΄λΆ€μ˜ 극점 μ•ˆμ •μ , κ°μ†Œν•˜λŠ” μž„νŽ„μŠ€ 응닡
λ‹¨μœ„μ› μ™ΈλΆ€μ˜ 극점 λΆˆμ•ˆμ •, μ¦κ°€ν•˜λŠ” μž„νŽ„μŠ€ 응닡
λ‹¨μœ„μ› μœ„μ˜ 극점 경계 μ•ˆμ •, 지속적 진동
μ›μ μ˜ 극점 순수 μ§€μ—° (FIR λ™μž‘)
케레 λ³΅μ†Œ 극점 곡진 (진동적 κ°μ†Œ)

6.4 극점-영점 μƒν˜Έμž‘μš© 탐색

def pole_zero_effects():
    """Show how pole/zero locations affect frequency response."""
    fig, axes = plt.subplots(3, 2, figsize=(14, 14))

    configurations = [
        {
            'title': 'Lowpass (pole near z=1)',
            'b': [1.0], 'a': [1.0, -0.9]
        },
        {
            'title': 'Highpass (pole near z=-1)',
            'b': [1.0, -1.0], 'a': [1.0, -0.9]
        },
        {
            'title': 'Bandpass (complex conjugate poles)',
            'b': [1.0, 0, -1.0],
            'a': [1.0, -2 * 0.9 * np.cos(np.pi / 4), 0.81]
        },
        {
            'title': 'Notch (zeros on unit circle)',
            'b': [1.0, -2 * np.cos(np.pi / 4), 1.0],
            'a': [1.0, -2 * 0.9 * np.cos(np.pi / 4), 0.81]
        },
        {
            'title': 'All-pass (poles/zeros reciprocal)',
            'b': [0.5, 1.0],
            'a': [1.0, 0.5]
        },
        {
            'title': 'Comb filter (pole at z^N=r^N)',
            'b': [1.0],
            'a': np.concatenate([[1.0], np.zeros(7), [-0.8]])
        },
    ]

    for ax_row, config in zip(axes.flat, configurations):
        b, a = np.array(config['b']), np.array(config['a'])

        w, H = signal.freqz(b, a, worN=1024)
        ax_row.plot(w / np.pi, 20 * np.log10(np.abs(H) + 1e-12),
                    'b-', linewidth=2)
        ax_row.set_title(config['title'])
        ax_row.set_xlabel(r'$\omega / \pi$')
        ax_row.set_ylabel('Magnitude (dB)')
        ax_row.set_ylim(-40, 30)
        ax_row.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('pole_zero_effects.png', dpi=150)
    plt.show()

pole_zero_effects()

7. μ•ˆμ •μ„± 뢄석(Stability Analysis)

7.1 BIBO μ•ˆμ •μ„±(BIBO Stability)

인과적 LTI μ‹œμŠ€ν…œμ΄ μœ κ³„ μž…λ ₯-μœ κ³„ 좜λ ₯(BIBO, Bounded-Input Bounded-Output) μ•ˆμ •μΈ ν•„μš”μΆ©λΆ„μ‘°κ±΄:

$$\sum_{n=0}^{\infty} |h[n]| < \infty$$

Z λ³€ν™˜ κ΄€μ μ—μ„œ, 인과적 μ‹œμŠ€ν…œμ΄ BIBO μ•ˆμ •μΈ ν•„μš”μΆ©λΆ„μ‘°κ±΄:

$$\boxed{\text{$H(z)$의 λͺ¨λ“  극점이 λ‹¨μœ„μ› μ—„κ²©νžˆ 내뢀에 μœ„μΉ˜: } |p_k| < 1 \, \forall k}$$

7.2 μ•ˆμ •μ„± 쑰건

극점 μœ„μΉ˜ μ•ˆμ •μ„± μž„νŽ„μŠ€ 응닡
λͺ¨λ“  $|p_k| < 1$ μ•ˆμ • 영으둜 수렴
일뢀 $|p_k| = 1$ (λ‹¨μˆœ) 경계 μ•ˆμ • μœ κ³„, λΉ„μ†Œλ©Έ
μž„μ˜ $|p_k| > 1$ λΆˆμ•ˆμ • λ¬΄ν•œ 증가
$|p_k| = 1$ (쀑볡) λΆˆμ•ˆμ • $n^{m-1}$처럼 증가

7.3 μ•ˆμ •μ„± 검사

def stability_analysis():
    """Analyze stability of several systems."""
    systems = [
        {
            'name': 'Stable: y[n] = 0.5*y[n-1] + x[n]',
            'b': [1.0], 'a': [1.0, -0.5]
        },
        {
            'name': 'Marginally stable: y[n] = y[n-1] + x[n]',
            'b': [1.0], 'a': [1.0, -1.0]
        },
        {
            'name': 'Unstable: y[n] = 1.1*y[n-1] + x[n]',
            'b': [1.0], 'a': [1.0, -1.1]
        },
        {
            'name': 'Stable oscillator: r=0.9, w0=pi/4',
            'b': [1.0],
            'a': [1.0, -2 * 0.9 * np.cos(np.pi / 4), 0.81]
        },
        {
            'name': 'Unstable oscillator: r=1.05, w0=pi/4',
            'b': [1.0],
            'a': [1.0, -2 * 1.05 * np.cos(np.pi / 4), 1.05**2]
        },
    ]

    fig, axes = plt.subplots(len(systems), 2, figsize=(14, 3 * len(systems)))

    for i, sys_info in enumerate(systems):
        b, a = np.array(sys_info['b']), np.array(sys_info['a'])
        poles = np.roots(a)
        max_pole_mag = np.max(np.abs(poles))

        stability = "STABLE" if max_pole_mag < 1 else \
                    "MARGINALLY STABLE" if np.isclose(max_pole_mag, 1) else \
                    "UNSTABLE"

        # Pole-zero plot
        ax_pz = axes[i, 0]
        theta = np.linspace(0, 2 * np.pi, 200)
        ax_pz.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=0.5)
        ax_pz.plot(np.real(poles), np.imag(poles), 'rx', markersize=10,
                   markeredgewidth=2)
        ax_pz.set_xlim(-1.5, 1.5)
        ax_pz.set_ylim(-1.5, 1.5)
        ax_pz.set_aspect('equal')
        ax_pz.set_title(f'{sys_info["name"]}\n[{stability}] max|pole|={max_pole_mag:.3f}')
        ax_pz.axhline(0, color='gray', linewidth=0.5)
        ax_pz.axvline(0, color='gray', linewidth=0.5)
        ax_pz.grid(True, alpha=0.3)

        # Impulse response
        ax_ir = axes[i, 1]
        N = 40
        h = np.zeros(N)
        h[0] = b[0] / a[0]
        for n in range(1, N):
            h[n] = (b[n] if n < len(b) else 0)
            for k in range(1, min(n + 1, len(a))):
                h[n] -= a[k] * h[n - k]
            h[n] /= a[0]

        color = 'green' if stability == "STABLE" else \
                'orange' if stability == "MARGINALLY STABLE" else 'red'
        ax_ir.stem(np.arange(N), h, linefmt=f'{color[0]}-',
                   markerfmt=f'{color[0]}o', basefmt='k-')
        ax_ir.set_title(f'Impulse Response')
        ax_ir.set_xlabel('n')
        ax_ir.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('stability.png', dpi=150)
    plt.show()

stability_analysis()

7.4 주리 μ•ˆμ •μ„± κ²€μ •(Jury Stability Test)

닀항식 $A(z) = a_0 z^N + a_1 z^{N-1} + \cdots + a_N$에 λŒ€ν•΄, 주리 μ•ˆμ •μ„± 검정은 λͺ…μ‹œμ μœΌλ‘œ 근을 κ³„μ‚°ν•˜μ§€ μ•Šκ³ λ„ λͺ¨λ“  근이 λ‹¨μœ„μ› 내뢀에 μžˆλŠ”μ§€ ν•„μš”μΆ©λΆ„μ‘°κ±΄μ„ μ œκ³΅ν•©λ‹ˆλ‹€.

ν•„μš” 쑰건 (λΉ λ₯Έ 확인): 1. $A(1) > 0$ 2. $(-1)^N A(-1) > 0$ 3. $|a_N| < |a_0|$

def jury_test(a):
    """Perform Jury stability test on polynomial coefficients."""
    a = np.array(a, dtype=float)
    N = len(a) - 1  # Polynomial order

    print("Jury Stability Test")
    print("=" * 50)
    print(f"Polynomial order: {N}")
    print(f"Coefficients: {a}")

    # Necessary conditions
    A_1 = np.polyval(a, 1)
    A_neg1 = np.polyval(a, -1)
    cond1 = A_1 > 0
    cond2 = ((-1) ** N * A_neg1) > 0
    cond3 = abs(a[-1]) < abs(a[0])

    print(f"\nNecessary conditions:")
    print(f"  A(1) = {A_1:.4f} > 0 ? {cond1}")
    print(f"  (-1)^N * A(-1) = {(-1)**N * A_neg1:.4f} > 0 ? {cond2}")
    print(f"  |a_N| = {abs(a[-1]):.4f} < |a_0| = {abs(a[0]):.4f} ? {cond3}")

    if not (cond1 and cond2 and cond3):
        print("\n  => UNSTABLE (necessary condition violated)")
        return False

    # Verify with actual roots
    roots = np.roots(a)
    max_mag = np.max(np.abs(roots))
    stable = max_mag < 1
    print(f"\nVerification: max|root| = {max_mag:.6f}")
    print(f"System is {'STABLE' if stable else 'UNSTABLE'}")
    return stable

# Test examples
print("System 1:")
jury_test([1, -1.3, 0.4])  # Stable (poles at 0.5, 0.8)
print("\nSystem 2:")
jury_test([1, -2.0, 1.1])  # Unstable

8. DTFT 및 λΌν”ŒλΌμŠ€ λ³€ν™˜κ³Όμ˜ 관계

8.1 Z λ³€ν™˜κ³Ό DTFT

DTFTλŠ” λ‹¨μœ„μ› μœ„μ—μ„œ ν‰κ°€ν•œ Z λ³€ν™˜μž…λ‹ˆλ‹€:

$$\boxed{X(e^{j\omega}) = X(z)\big|_{z=e^{j\omega}}}$$

이 κ΄€κ³„λŠ” $X(z)$의 ROCκ°€ λ‹¨μœ„μ›μ„ ν¬ν•¨ν•˜λŠ” κ²½μš°μ— μ„±λ¦½ν•©λ‹ˆλ‹€.

κ²°κ³Ό: 이산 μ‹œκ°„ μ‹œμŠ€ν…œμ˜ 주파수 응닡은:

$$H(e^{j\omega}) = H(z)\big|_{z=e^{j\omega}}$$

8.2 Z λ³€ν™˜κ³Ό λΌν”ŒλΌμŠ€ λ³€ν™˜

μƒ˜ν”Œλ§λœ μ‹ ν˜Έ $x_s(t) = \sum_n x(nT_s) \delta(t - nT_s)$에 λŒ€ν•΄, λΌν”ŒλΌμŠ€ λ³€ν™˜ $X_s(s)$와 Z λ³€ν™˜ $X(z)$ μ‚¬μ΄μ˜ κ΄€κ³„λŠ”:

$$\boxed{z = e^{sT_s}}$$

λ˜λŠ” λ™λ“±ν•˜κ²Œ:

$$s = \frac{1}{T_s} \ln z$$

μ΄λŠ” λ‹€μŒκ³Ό 같이 λŒ€μ‘ν•©λ‹ˆλ‹€: - s ν‰λ©΄μ˜ 쒌반면 ($\text{Re}(s) < 0$) $\to$ λ‹¨μœ„μ› λ‚΄λΆ€ ($|z| < 1$) - ν—ˆμˆ˜μΆ• ($\text{Re}(s) = 0$) $\to$ λ‹¨μœ„μ› ($|z| = 1$) - s ν‰λ©΄μ˜ 우반면 ($\text{Re}(s) > 0$) $\to$ λ‹¨μœ„μ› μ™ΈλΆ€ ($|z| > 1$)

8.3 H(z)λ‘œλΆ€ν„°μ˜ 주파수 응닡

νŠΉμ • 물리적 주파수 $f$ (Hz)μ—μ„œμ˜ 주파수 응닡 계산:

$$\omega = 2\pi f / f_s \quad \text{(μ •κ·œν™”λœ λ””μ§€ν„Έ 주파수)}$$ $$H(e^{j\omega}) = H(z)\big|_{z = e^{j2\pi f/f_s}}$$

def frequency_response_from_hz():
    """Compute frequency response from H(z) by evaluating on unit circle."""
    # System: H(z) = (1 + z^{-1}) / (1 - 0.5 z^{-1})
    b = [1.0, 1.0]
    a = [1.0, -0.5]

    fs = 8000  # Hz

    # Method 1: Using scipy.signal.freqz
    w, H_scipy = signal.freqz(b, a, worN=1024)
    f_hz = w * fs / (2 * np.pi)

    # Method 2: Direct evaluation on unit circle
    omega = np.linspace(0, np.pi, 1024)
    z = np.exp(1j * omega)
    H_direct = (b[0] + b[1] * z**(-1)) / (a[0] + a[1] * z**(-1))

    fig, axes = plt.subplots(2, 1, figsize=(12, 8))

    axes[0].plot(f_hz, 20 * np.log10(np.abs(H_scipy)), 'b-',
                 linewidth=2, label='scipy.signal.freqz')
    axes[0].plot(f_hz, 20 * np.log10(np.abs(H_direct)), 'r--',
                 linewidth=1, label='Direct evaluation')
    axes[0].set_title(r'Frequency Response: $H(z) = (1+z^{-1})/(1-0.5z^{-1})$')
    axes[0].set_xlabel('Frequency (Hz)')
    axes[0].set_ylabel('Magnitude (dB)')
    axes[0].legend()
    axes[0].grid(True, alpha=0.3)

    axes[1].plot(f_hz, np.unwrap(np.angle(H_scipy)) * 180 / np.pi, 'b-',
                 linewidth=2, label='scipy.signal.freqz')
    axes[1].plot(f_hz, np.unwrap(np.angle(H_direct)) * 180 / np.pi, 'r--',
                 linewidth=1, label='Direct evaluation')
    axes[1].set_xlabel('Frequency (Hz)')
    axes[1].set_ylabel('Phase (degrees)')
    axes[1].legend()
    axes[1].grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('freq_response_hz.png', dpi=150)
    plt.show()

frequency_response_from_hz()

8.4 s ν‰λ©΄μ—μ„œ z ν‰λ©΄μœΌλ‘œμ˜ 사상

def s_to_z_mapping():
    """Visualize the mapping from s-plane to z-plane."""
    fig, axes = plt.subplots(1, 2, figsize=(14, 6))
    Ts = 1.0  # Normalized sampling period

    # s-plane
    ax = axes[0]
    # Stability boundary (imaginary axis)
    sigma = np.linspace(-3, 3, 100)
    omega_s = np.linspace(-np.pi / Ts, np.pi / Ts, 100)

    ax.axvline(0, color='red', linewidth=2, label='Stability boundary')
    ax.fill_betweenx([-4, 4], -4, 0, alpha=0.1, color='green',
                      label='Stable region')
    ax.fill_betweenx([-4, 4], 0, 4, alpha=0.1, color='red',
                      label='Unstable region')

    # Constant sigma lines
    for sig in [-2, -1, -0.5, 0.5, 1, 2]:
        ax.axvline(sig, color='gray', linestyle=':', alpha=0.3)

    # Constant omega lines
    for om in np.linspace(-3, 3, 7):
        ax.axhline(om, color='gray', linestyle=':', alpha=0.3)

    ax.set_xlim(-3, 3)
    ax.set_ylim(-4, 4)
    ax.set_title('s-Plane')
    ax.set_xlabel(r'$\sigma$ (Real)')
    ax.set_ylabel(r'$j\omega$ (Imaginary)')
    ax.legend(fontsize=8)
    ax.grid(True, alpha=0.3)

    # z-plane
    ax = axes[1]
    theta = np.linspace(0, 2 * np.pi, 200)
    ax.plot(np.cos(theta), np.sin(theta), 'r-', linewidth=2,
            label='Unit circle (stability)')

    # Map constant sigma lines
    for sig in [-2, -1, -0.5, 0, 0.5, 1, 2]:
        r = np.exp(sig * Ts)
        ax.plot(r * np.cos(theta), r * np.sin(theta), '--',
                alpha=0.4, label=f'sigma={sig}' if sig in [-1, 0, 1] else '')

    ax.fill_between(np.cos(theta), np.sin(theta), alpha=0.1, color='green')

    ax.set_xlim(-3, 3)
    ax.set_ylim(-3, 3)
    ax.set_aspect('equal')
    ax.set_title(r'z-Plane ($z = e^{sT_s}$)')
    ax.set_xlabel('Real')
    ax.set_ylabel('Imaginary')
    ax.axhline(0, color='gray', linewidth=0.5)
    ax.axvline(0, color='gray', linewidth=0.5)
    ax.legend(fontsize=8)
    ax.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('s_to_z_mapping.png', dpi=150)
    plt.show()

s_to_z_mapping()

9. 주파수 μ‘λ‹΅μ˜ κΈ°ν•˜ν•™μ  해석

9.1 벑터 κ³±μœΌλ‘œμ„œμ˜ 주파수 응닡

주파수 $\omega$μ—μ„œμ˜ 주파수 응닡은 κΈ°ν•˜ν•™μ μœΌλ‘œ 계산할 수 μžˆμŠ΅λ‹ˆλ‹€:

$$|H(e^{j\omega})| = |G| \cdot \frac{\prod_{k=1}^{M} |e^{j\omega} - z_k|}{\prod_{k=1}^{N} |e^{j\omega} - p_k|}$$

$$\angle H(e^{j\omega}) = \angle G + \sum_{k=1}^{M} \angle(e^{j\omega} - z_k) - \sum_{k=1}^{N} \angle(e^{j\omega} - p_k)$$

$\omega$κ°€ $0$μ—μ„œ $\pi$κΉŒμ§€ λ³€ν™”ν•  λ•Œ, 점 $e^{j\omega}$λŠ” λ‹¨μœ„μ›μ˜ μƒλ°˜λΆ€λ₯Ό 따라 μ›€μ§μž…λ‹ˆλ‹€. ν¬κΈ°λŠ” μ˜μ κΉŒμ§€μ˜ 거리의 곱을 κ·Ήμ κΉŒμ§€μ˜ 거리의 곱으둜 λ‚˜λˆˆ κ°’μž…λ‹ˆλ‹€.

def geometric_frequency_response():
    """Visualize the geometric interpretation of frequency response."""
    # System with poles and zeros
    zeros = [0.5 + 0.5j, 0.5 - 0.5j]
    poles = [0.8 * np.exp(1j * np.pi / 3), 0.8 * np.exp(-1j * np.pi / 3)]

    # Build transfer function from poles and zeros
    b = np.real(np.poly(zeros))
    a = np.real(np.poly(poles))

    # Animate for a specific frequency
    omega_target = np.pi / 3  # Target frequency
    z_point = np.exp(1j * omega_target)

    fig, axes = plt.subplots(1, 2, figsize=(14, 6))

    # Pole-zero plot with vectors
    ax = axes[0]
    theta = np.linspace(0, 2 * np.pi, 200)
    ax.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=0.5)

    # Zeros
    for z in zeros:
        ax.plot(np.real(z), np.imag(z), 'bo', markersize=10)
        # Vector from zero to point on unit circle
        ax.annotate('', xy=(np.real(z_point), np.imag(z_point)),
                    xytext=(np.real(z), np.imag(z)),
                    arrowprops=dict(arrowstyle='->', color='blue', lw=1.5))

    # Poles
    for p in poles:
        ax.plot(np.real(p), np.imag(p), 'rx', markersize=12, markeredgewidth=2)
        ax.annotate('', xy=(np.real(z_point), np.imag(z_point)),
                    xytext=(np.real(p), np.imag(p)),
                    arrowprops=dict(arrowstyle='->', color='red', lw=1.5))

    # Point on unit circle
    ax.plot(np.real(z_point), np.imag(z_point), 'g*', markersize=15,
            label=f'e^(j*{omega_target/np.pi:.2f}*pi)')

    ax.set_xlim(-1.5, 1.5)
    ax.set_ylim(-1.5, 1.5)
    ax.set_aspect('equal')
    ax.set_title(f'Geometric Vectors at omega = {omega_target/np.pi:.2f}*pi')
    ax.legend()
    ax.grid(True, alpha=0.3)

    # Frequency response
    ax = axes[1]
    w, H = signal.freqz(b, a, worN=1024)
    ax.plot(w / np.pi, 20 * np.log10(np.abs(H) + 1e-12), 'b-', linewidth=2)
    ax.axvline(omega_target / np.pi, color='green', linestyle='--',
               linewidth=2, label=f'omega = {omega_target/np.pi:.2f}*pi')

    H_at_target = np.polyval(b, z_point) / np.polyval(a, z_point)
    ax.plot(omega_target / np.pi, 20 * np.log10(np.abs(H_at_target)),
            'g*', markersize=15)

    ax.set_title('Magnitude Response')
    ax.set_xlabel(r'$\omega / \pi$')
    ax.set_ylabel('Magnitude (dB)')
    ax.legend()
    ax.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('geometric_freq_response.png', dpi=150)
    plt.show()

geometric_frequency_response()

10. μ’…ν•© μ˜ˆμ‹œ: μ‹œμŠ€ν…œ 뢄석 νŒŒμ΄ν”„λΌμΈ

def complete_system_analysis():
    """Complete analysis of a digital system from difference equation to
    frequency response."""
    print("Complete System Analysis")
    print("=" * 60)

    # Difference equation:
    # y[n] - 1.2y[n-1] + 0.72y[n-2] = x[n] - 0.5x[n-1]
    b = [1.0, -0.5]
    a = [1.0, -1.2, 0.72]

    # 1. Transfer function
    print("\n1. Transfer function:")
    print(f"   H(z) = ({b[0]} + {b[1]}z^-1) / "
          f"({a[0]} + {a[1]}z^-1 + {a[2]}z^-2)")

    # 2. Poles and zeros
    zeros = np.roots(b)
    poles = np.roots(a)
    print(f"\n2. Zeros: {zeros}")
    print(f"   Poles: {poles}")
    print(f"   Pole magnitudes: {np.abs(poles)}")
    print(f"   Pole angles: {np.angle(poles) * 180 / np.pi} degrees")

    # 3. Stability
    stable = all(np.abs(poles) < 1)
    print(f"\n3. Stability: {'STABLE' if stable else 'UNSTABLE'}")
    print(f"   Max |pole| = {np.max(np.abs(poles)):.4f}")

    # 4. Partial fraction expansion
    r, p, k = signal.residuez(b, a)
    print(f"\n4. Partial fractions:")
    print(f"   Residues: {r}")
    print(f"   Poles: {p}")
    print(f"   Direct term: {k}")

    # 5. Impulse response (first 50 samples)
    _, h = signal.dimpulse(signal.dlti(b, a, dt=1), n=50)
    h = np.squeeze(h)

    # 6. Frequency response
    w, H = signal.freqz(b, a, worN=1024)

    # Plot everything
    fig = plt.figure(figsize=(16, 12))
    gs = fig.add_gridspec(3, 2)

    # Pole-zero plot
    ax1 = fig.add_subplot(gs[0, 0])
    theta = np.linspace(0, 2 * np.pi, 200)
    ax1.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=0.5)
    ax1.plot(np.real(zeros), np.imag(zeros), 'bo', markersize=10, label='Zeros')
    ax1.plot(np.real(poles), np.imag(poles), 'rx', markersize=12,
             markeredgewidth=2, label='Poles')
    ax1.set_xlim(-1.5, 1.5)
    ax1.set_ylim(-1.5, 1.5)
    ax1.set_aspect('equal')
    ax1.set_title('Pole-Zero Plot')
    ax1.legend()
    ax1.grid(True, alpha=0.3)

    # Impulse response
    ax2 = fig.add_subplot(gs[0, 1])
    ax2.stem(np.arange(len(h)), h, linefmt='b-', markerfmt='bo', basefmt='k-')
    ax2.set_title('Impulse Response h[n]')
    ax2.set_xlabel('n')
    ax2.grid(True, alpha=0.3)

    # Magnitude response
    ax3 = fig.add_subplot(gs[1, 0])
    ax3.plot(w / np.pi, 20 * np.log10(np.abs(H) + 1e-12), 'b-', linewidth=2)
    ax3.set_title('Magnitude Response')
    ax3.set_xlabel(r'$\omega / \pi$')
    ax3.set_ylabel('dB')
    ax3.grid(True, alpha=0.3)

    # Phase response
    ax4 = fig.add_subplot(gs[1, 1])
    ax4.plot(w / np.pi, np.unwrap(np.angle(H)) * 180 / np.pi, 'r-',
             linewidth=2)
    ax4.set_title('Phase Response')
    ax4.set_xlabel(r'$\omega / \pi$')
    ax4.set_ylabel('Degrees')
    ax4.grid(True, alpha=0.3)

    # Group delay
    ax5 = fig.add_subplot(gs[2, 0])
    _, gd = signal.group_delay((b, a), w=1024)
    ax5.plot(w / np.pi, gd, 'g-', linewidth=2)
    ax5.set_title('Group Delay')
    ax5.set_xlabel(r'$\omega / \pi$')
    ax5.set_ylabel('Samples')
    ax5.grid(True, alpha=0.3)

    # Step response
    ax6 = fig.add_subplot(gs[2, 1])
    _, s = signal.dstep(signal.dlti(b, a, dt=1), n=50)
    s = np.squeeze(s)
    ax6.stem(np.arange(len(s)), s, linefmt='m-', markerfmt='mo', basefmt='k-')
    ax6.set_title('Step Response')
    ax6.set_xlabel('n')
    ax6.grid(True, alpha=0.3)

    plt.suptitle(r'System: $y[n] - 1.2y[n-1] + 0.72y[n-2] = x[n] - 0.5x[n-1]$',
                 fontsize=14)
    plt.tight_layout()
    plt.savefig('complete_analysis.png', dpi=150)
    plt.show()

complete_system_analysis()

11. μš”μ•½

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Z λ³€ν™˜(Z-Transform)                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚  μ •μ˜:                                                           β”‚
│    X(z) = Σ x[n] z^{-n}     z = r * e^{jω}                    │
β”‚                                                                  β”‚
β”‚  ROC (수렴 μ˜μ—­):                                                β”‚
β”‚    - μ‹ ν˜Έλ₯Ό μœ μΌν•˜κ²Œ κ²°μ • (같은 X(z), λ‹€λ₯Έ ROC β†’               β”‚
β”‚      λ‹€λ₯Έ x[n])                                                  β”‚
β”‚    - 인과적: |z| > R⁻  (원 μ™ΈλΆ€)                               β”‚
β”‚    - 반인과적: |z| < R⁺ (원 λ‚΄λΆ€)                              β”‚
β”‚    - μ–‘λ°©ν–₯: R⁻ < |z| < R⁺ (ν™˜ν˜• 고리)                        β”‚
β”‚                                                                  β”‚
β”‚  μ£Όμš” μ„±μ§ˆ:                                                      β”‚
β”‚    - μ‹œκ°„ 이동: x[n-m] ↔ z^{-m} X(z)                          β”‚
β”‚    - μ»¨λ³Όλ£¨μ…˜: x₁*xβ‚‚ ↔ X₁(z)Β·Xβ‚‚(z)                           β”‚
β”‚    - z^{-1} = ν•œ μƒ˜ν”Œ μ§€μ—°                                      β”‚
β”‚                                                                  β”‚
β”‚  전달 ν•¨μˆ˜:                                                      β”‚
β”‚    H(z) = Y(z)/X(z) = B(z)/A(z)                                β”‚
β”‚    극점 β†’ λΆ„λͺ¨μ˜ κ·Ό                                              β”‚
β”‚    영점 β†’ λΆ„μžμ˜ κ·Ό                                              β”‚
β”‚                                                                  β”‚
β”‚  μ•ˆμ •μ„± (인과 μ‹œμŠ€ν…œ):                                           β”‚
β”‚    λͺ¨λ“  극점이 λ‹¨μœ„μ› λ‚΄λΆ€ ↔ BIBO μ•ˆμ •                          β”‚
β”‚                                                                  β”‚
β”‚  관계:                                                           β”‚
β”‚    λ‹¨μœ„μ› μœ„μ˜ Z λ³€ν™˜ = DTFT: X(e^{jΟ‰}) = X(z)|_{z=e^{jΟ‰}}    β”‚
β”‚    z = e^{sTs}둜 Z λ³€ν™˜κ³Ό λΌν”ŒλΌμŠ€ λ³€ν™˜ μ—°κ²°                   β”‚
β”‚                                                                  β”‚
β”‚  μ—­λ³€ν™˜ 방법:                                                    β”‚
β”‚    1. λΆ€λΆ„ λΆ„μˆ˜ β†’ μ•Œλ €μ§„ 쌍                                     β”‚
β”‚    2. κΈ΄ λ‚˜λˆ—μ…ˆ β†’ λ©±κΈ‰μˆ˜                                        β”‚
β”‚    3. 경둜 적뢄 β†’ 유수 정리                                     β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

12. μ—°μŠ΅ 문제

μ—°μŠ΅ 문제 1: Z λ³€ν™˜ 계산

각각에 λŒ€ν•΄ Z λ³€ν™˜μ„ κ³„μ‚°ν•˜κ³  ROCλ₯Ό λͺ…μ‹œν•˜μ‹œμ˜€:

(a) $x[n] = (0.5)^n u[n] + (0.8)^n u[n]$

(b) $x[n] = (0.6)^n u[n] - 2(0.6)^n u[n-3]$

(c) $x[n] = n(0.9)^n u[n]$

(d) $x[n] = (0.7)^{|n|}$ (μ–‘λ°©ν–₯)

μ—°μŠ΅ 문제 2: μ—­ Z λ³€ν™˜

λΆ€λΆ„ λΆ„μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 각각에 λŒ€ν•œ $x[n]$을 κ΅¬ν•˜μ‹œμ˜€:

(a) $X(z) = \frac{z}{(z-0.5)(z-0.8)}, \quad |z| > 0.8$

(b) $X(z) = \frac{z}{(z-0.5)(z-0.8)}, \quad |z| < 0.5$

(c) $X(z) = \frac{z^2}{(z-0.5)(z-0.8)}, \quad |z| > 0.8$

(d) $X(z) = \frac{1+2z^{-1}}{1-z^{-1}+0.5z^{-2}}, \quad |z| > 0.707$

μ—°μŠ΅ 문제 3: μ‹œμŠ€ν…œ 뢄석

λ‹€μŒ μ°¨λΆ„ 방정식이 μ£Όμ–΄μ‘Œμ„ λ•Œ: $y[n] = 0.8y[n-1] - 0.64y[n-2] + x[n] + x[n-1]$

(a) $H(z)$λ₯Ό κ΅¬ν•˜κ³  극점-영점 도식을 μŠ€μΌ€μΉ˜ν•˜μ‹œμ˜€.

(b) μ‹œμŠ€ν…œμ΄ μ•ˆμ •μ μΈκ°€? 이유λ₯Ό μ„€λͺ…ν•˜μ‹œμ˜€.

(c) λΆ€λΆ„ λΆ„μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μž„νŽ„μŠ€ 응닡 $h[n]$을 κ΅¬ν•˜μ‹œμ˜€.

(d) 주파수 응닡(크기 및 μœ„μƒ)을 κ³„μ‚°ν•˜κ³  λ„μ‹ν™”ν•˜μ‹œμ˜€.

(e) 이 μ‹œμŠ€ν…œμ€ μ €μ—­ 톡과, κ³ μ—­ 톡과, λŒ€μ—­ 톡과, λŒ€μ—­ μ €μ§€ ν•„ν„° 쀑 μ–΄λŠ 것인가?

μ—°μŠ΅ 문제 4: μ•ˆμ •μ„± νŒμ •

근을 직접 κ³„μ‚°ν•˜μ§€ μ•Šκ³  각 μ‹œμŠ€ν…œμ˜ μ•ˆμ •μ„±μ„ κ²°μ •ν•˜μ‹œμ˜€:

(a) $H(z) = \frac{1}{1 - 0.5z^{-1} + 0.06z^{-2}}$

(b) $H(z) = \frac{z^2}{z^2 - 1.4z + 0.85}$

(c) $H(z) = \frac{1}{1 - 1.8\cos(0.4\pi)z^{-1} + 0.81z^{-2}}$

주리 μ•ˆμ •μ„± 검정을 μ‚¬μš©ν•˜κ³  Python으둜 κ²€μ¦ν•˜μ‹œμ˜€.

μ—°μŠ΅ 문제 5: ROC와 μ‹ ν˜Έ κ²°μ •

Z λ³€ν™˜μ΄ $X(z) = \frac{2z^2 - 1.5z}{z^2 - 0.9z + 0.2}$일 λ•Œ:

(a) κ°€λŠ₯ν•œ λͺ¨λ“  ROCλ₯Ό κ΅¬ν•˜μ‹œμ˜€.

(b) 각 ROC에 λŒ€ν•΄ λŒ€μ‘ν•˜λŠ” μ‹ ν˜Έ $x[n]$ (인과적, 반인과적, λ˜λŠ” μ–‘λ°©ν–₯)을 κ²°μ •ν•˜μ‹œμ˜€.

(c) μ–΄λŠ ROCμ—μ„œ DTFTκ°€ μ‘΄μž¬ν•˜λŠ”κ°€?

μ—°μŠ΅ 문제 6: 전달 ν•¨μˆ˜ 섀계

λ‹€μŒ 사양을 κ°€μ§„ 2μ°¨ λ””μ§€ν„Έ μ‹œμŠ€ν…œμ„ μ„€κ³„ν•˜μ‹œμ˜€: - 곡진 주파수: $\omega_0 = \pi/3$ rad/sample - λŒ€μ—­ν­: $\Delta\omega \approx 0.1$ rad/sample - κ³΅μ§„μ—μ„œ λ‹¨μœ„ 이득

(a) $z = re^{\pm j\omega_0}$에 극점을 놓고 μ›ν•˜λŠ” λŒ€μ—­ν­μ„ μœ„ν•œ $r$을 μ„ νƒν•˜μ‹œμ˜€. (힌트: $r$이 1에 κ°€κΉŒμšΈ λ•Œ λŒ€μ—­ν­ $\approx 2(1-r)$)

(b) κ³΅μ§„μ—μ„œ λ‹¨μœ„ 이득을 μ–»κΈ° μœ„ν•œ μ˜μ μ„ λ†“μœΌμ‹œμ˜€.

(c) Python으둜 κ΅¬ν˜„ν•˜κ³  주파수 응닡을 λ„μ‹ν™”ν•˜μ‹œμ˜€.

(d) 곡진 μ£ΌνŒŒμˆ˜μ™€ λ‹€λ₯Έ 주파수λ₯Ό ν¬ν•¨ν•œ μ‹ ν˜Έλ‘œ ν…ŒμŠ€νŠΈν•˜μ‹œμ˜€.

μ—°μŠ΅ 문제 7: λ””μ§€ν„Έ λ°œμ§„κΈ° κ΅¬ν˜„

λ””μ§€ν„Έ λ°œμ§„κΈ°λŠ” λ‹€μŒ μ°¨λΆ„ 방정식을 μ‚¬μš©ν•˜μ—¬ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€:

$$y[n] = 2\cos(\omega_0) y[n-1] - y[n-2]$$

(a) $H(z)$와 극점을 κ΅¬ν•˜μ‹œμ˜€. 극점은 어디에 μœ„μΉ˜ν•˜λŠ”κ°€?

(b) μ™œ 이 μ‹œμŠ€ν…œμ΄ 경계 μ•ˆμ •μΈκ°€? μœ ν•œ 정밀도 μ‚°μˆ μ—μ„œ μ‹€μ œλ‘œ μ–΄λ–€ 일이 λ°œμƒν•˜λŠ”κ°€?

(c) Python으둜 λ°œμ§„κΈ°λ₯Ό κ΅¬ν˜„ν•˜κ³  8000 Hz μƒ˜ν”Œλ§ λ ˆμ΄νŠΈμ—μ„œ 440 Hz μŒμ„ μƒμ„±ν•˜μ‹œμ˜€. 10000 μƒ˜ν”Œ 이후 직접 사인 계산과 λΉ„κ΅ν•˜μ‹œμ˜€.


13. 더 읽을 거리

  • Oppenheim, Schafer. Discrete-Time Signal Processing, 3rd ed. Chapters 3, 5.
  • Proakis, Manolakis. Digital Signal Processing, 4th ed. Chapters 3-4.
  • Haykin, Van Veen. Signals and Systems, 2nd ed. Chapter 8.
  • Roberts, M. J. Signals and Systems, Chapter 10.
  • Phillips, Parr, Riskin. Signals, Systems, and Transforms, 5th ed. Chapters 8-9.

이전: 06. 이산 푸리에 λ³€ν™˜ | λ‹€μŒ: 08. λ””μ§€ν„Έ ν•„ν„° 기초

to navigate between lessons