# 신호 흐름선도와 경로 방식

신호 흐름선도는 시스템 내에서 신호가 흐르는 과정을 노드와 가지(branch)로 시각화하여 표현하는 방법이다. 전통적인 블록선도(block diagram)보다 복잡한 시스템을 좀 더 명료하고 분석적으로 다룰 수 있다는 장점을 가진다. 특히 경로 방식(path approach)을 적용하면 블록선도에서 일일이 줄이는 과정을 거치지 않고도 최종 전달함수를 효율적으로 구할 수 있다.

#### 신호 흐름선도의 구성 요소

신호 흐름선도는 크게 노드(node)와 가지(branch)로 이루어진다. 노드는 일반적으로 하나의 신호 변수나 중간 합점(summing junction)을 의미한다. 노드 사이를 연결하는 선분을 가지라 하며, 이 가지에는 방향이 있고, 그 방향을 따라 신호가 한 노드에서 다른 노드로 전파된다. 가지에 대응하는 전달 특성을 가지이득(branch gain)이라 부른다.

예를 들어 입력 노드가 $X(s)$, 출력 노드가 $Y(s)$라 할 때, 특정 노드 $N\_i$에서 다른 노드 $N\_j$로의 가지이득을 $G\_{ij}(s)$라 쓰면, 흐름선도 상에서 $N\_i$에서 $N\_j$ 방향 화살표가 있고 그 위에 $G\_{ij}(s)$라는 형태로 명시된다.

신호 흐름선도의 분석에서 노드의 합점(sum node)은 여러 개의 가지가 들어오거나 나가는 지점일 수 있다. 흔히 $N\_j$로 들어오는 가지이득들을 $G\_{kj}(s)$라 하고, 그 노드에 들어오는 신호를 모두 합산하여 해당 노드 변수 $X\_j$로 표현한다면

$$
X\_j = \sum G\_{kj}(s) X\_k
$$

와 같이 기록할 수 있다.

#### 경로와 루프

신호 흐름선도에서 경로(path)란 입력 노드에서 출력 노드로 이어지는 연속된 가지들의 사슬이다. 만약 어떤 가지의 방향이 경로 상의 흐름과 반대 방향이거나 가지가 끊어져 있다면, 그것은 유효한 경로가 아니다. 여러 개의 경로가 있을 수 있으며, 각 경로마다 고유한 경로이득(path gain)을 정의할 수 있다. 경로이득은 경로 위에 놓인 모든 가지이득을 곱한 형태로 주어진다.

루프(loop)는 어떤 노드에서 시작하여 다시 같은 노드로 돌아오는 폐루푸 경로를 말한다. 모든 가지가 같은 방향을 유지하며 순환해야 하며, 루프에 해당하는 각 가지이득을 모두 곱한 값을 루프이득(loop gain)이라 한다. 루프끼리 노드를 공유하지 않으면 서로 독립 루프(disjoint loop)라고 한다.

#### Mason의 이득 공식

신호 흐름선도에서 가장 많이 쓰이는 결과 중 하나가 Mason의 공식(Mason’s Gain Formula)이다. 복잡한 흐름선도에서 단일 입력 $X(s)$와 단일 출력 $Y(s)$ 사이의 전달함수 $T(s)$를 유도하는 데 매우 편리하다. Mason의 공식은 아래와 같이 표현된다.

$$
T(s) = \frac{Y(s)}{X(s)}  = \frac{\sum P\_i \Delta\_i}{\Delta\_0}
$$

$\Delta\_0$는 전체 흐름선도의 1-루프, 2-루프, 3-루프 이상의 조합을 반영하는 식이다. $P\_i$는 입력에서 출력까지 이어지는 $i$번째 경로이득이며, $\Delta\_i$는 해당 경로와 공통 노드를 갖지 않는 루프들의 결합요인을 고려하는 항이다. 구체적으로

$$
\Delta\_0  = 1  - (\text{모든 단일 루프이득의 합})  + (\text{두 개씩 분리된 루프이득의 곱})  - (\text{세 개씩 분리된 루프이득의 곱})  + \cdots
$$

$\Delta\_i$는 경로 $P\_i$에 공통되는 노드를 갖는 루프를 제외하고 나머지 독립 루프들이 만드는 항을 위와 같은 규칙에 따라 더하고 빼서 얻는다.

#### 간단한 신호 흐름선도 예시

아래는 입력 $X$에서 출력 $Y$로 흐르는 신호 흐름선도를 mermaid로 간단히 나타낸 것이다.

{% @mermaid/diagram content="graph LR
X((X)) -->|G1| N1
N1 -->|G2| Y((Y))
N1 -->|H| N1" %}

이 예시에서 입력 노드 $X$에서 중간 노드 $N1$로 가지이득이 $G\_1$이고, $N1$에서 출력 노드 $Y$로 가지이득이 $G\_2$이며, $N1$에서 자기 자신으로 되돌아오는 피드백 루프의 가지이득이 $H$라고 하자.

신호 흐름선도상 경로를 확인해 보면 입력에서 출력으로 가는 단일 경로는 $X \rightarrow N1 \rightarrow Y$ 하나이며, 이 경로이득은 $G\_1 \cdot G\_2$이다. 루프는 $N1$에서 시작해 다시 $N1$로 돌아오는 경로이므로 루프이득은 $H$가 된다.

이 경우 Mason의 공식을 이용해 $T(s)$를 구하면

$$
\Delta\_0 = 1 - H
$$

경로 $P\_1$는 $G\_1 G\_2$, 해당 경로와 공통 노드를 갖지 않는 루프는 없으므로 $\Delta\_1 = 1$이다. 따라서

$$
T(s) = \frac{Y(s)}{X(s)} = \frac{P\_1 \Delta\_1}{\Delta\_0} = \frac{G\_1 G\_2}{1 - H}
$$

라 표현된다. 일반적인 블록선도 해석을 통해 구한 결과와 동일하지만, 블록선도를 여러 번 줄이는 과정을 거치지 않고도 신호 흐름선도상의 경로, 루프, 루프 간의 결합 관계만 명확히 알면 빠르게 전달함수를 얻을 수 있다.

#### 다중 경로와 다중 루프가 있는 신호 흐름선도

신호 흐름선도가 복잡해질수록 입력에서 출력으로 이어지는 경로가 여러 개 생기고, 루프도 여러 개가 존재할 수 있다. 이때 단순히 블록선도를 병렬-직렬 결합으로 줄이는 방법을 쓰기에는 많은 수의 연산과 재배치가 필요하므로, 경로 방식을 쓰는 것이 매우 유용하다. Mason의 공식에서 요구하는 모든 경로와 루프, 그리고 루프의 결합 관계(독립 루프끼리의 곱을 고려하는 항 등)를 정확히 구해내기만 하면, 전달함수를 단 한 번에 계산할 수 있다.

아래 mermaid 예시는 입력 노드 $X$와 출력 노드 $Y$ 사이에 병렬 경로가 존재하고, 내부에 루프가 2개 이상 있는 복수 경로 SFG(signal flow graph)의 예시다.

{% @mermaid/diagram content="graph LR
X((X)) -->|G1| A
X -->|G2| B
A -->|G3| C
B -->|G4| C
C -->|G5| Y((Y))
A -->|H1| A
B -->|H2| B
C -->|H3| B" %}

이 흐름선도에서 확인할 수 있는 경로들은 입력 $X$에서부터 출력 $Y$에 이르는 연속적 가지들의 사슬이다. 간단히 경로를 살펴보면

* $X \rightarrow A \rightarrow C \rightarrow Y$
* $X \rightarrow B \rightarrow C \rightarrow Y$

두 가지 주요 경로가 존재한다. 각각의 경로이득을 $P\_1$, $P\_2$라 쓰면,

* $P\_1 = G\_1 \cdot G\_3 \cdot G\_5$
* $P\_2 = G\_2 \cdot G\_4 \cdot G\_5$

로 표현된다.

루프는 어떤 노드에서 시작하여 같은 노드로 되돌아오는 순환 경로이며, 방향이 일치해야 한다. 위 mermaid 그림에는 세 개의 루프가 보인다.

* 첫 번째 루프는 $A \rightarrow A$로, 가지이득 $H\_1$만 포함하며 루프이득을 $H\_1$이라 한다.
* 두 번째 루프는 $B \rightarrow B$로, 가지이득 $H\_2$만 포함하며 루프이득을 $H\_2$라 한다.
* 세 번째 루프는 $C \rightarrow B \rightarrow C$ 경로이며, 루프이득은 $H\_3 \cdot G\_4$에 그 반대방향으로 돌아오는 $C \rightarrow B$ 가지이득이 없으므로, 다시 $B$에서 $C$로 가는 $G\_4$와 $C$에서 $B$로 가는 $H\_3$가 곱해진 값이 된다. 즉 루프이득 $L\_3 = G\_4 \cdot H\_3$라 볼 수 있다. 주의해야 할 점은 $C$에서 $B$로 가는 이득이 $H\_3$이고, $B$에서 $C$로 가는 이득이 $G\_4$인데, 서로 방향이 다르다고 해석할 수 있지만 흐름선도에서 $B \rightarrow C$는 $G\_4$, $C \rightarrow B$는 $H\_3$ 형태로 각각 한 방향 가지로 설정되어 있다. 따라서 $B \rightarrow C \rightarrow B$는 실제로 모든 가지 방향이 일관되므로 유효한 루프가 된다.

#### 독립 루프(disjoint loop)의 판별

Mason의 공식에서 루프 항($\Delta\_0$)은 모든 단일 루프이득의 합에서 시작해, 노드를 공유하지 않는 루프들의 곱을 빼고 더하고를 반복해서 구한다. 예를 들어 두 루프가 서로 공통 노드를 전혀 공유하지 않으면, 그 루프이득의 곱을 $\Delta\_0$에 포함해야 한다.

여기서는

* $A$를 맴도는 루프 $L\_1 = H\_1$,
* $B$를 맴도는 루프 $L\_2 = H\_2$,
* $B \leftrightarrow C$를 맴도는 루프 $L\_3 = G\_4 \cdot H\_3$

가 있는데, $L\_1$과 $L\_2$는 노드가 다르므로 서로 독립이다. 그러나 $L\_3$는 $B, C$를 포함하므로 $L\_2$와 노드 $B$를 공유한다. 결국 $L\_2$와 $L\_3$는 독립 루프가 아니다. $L\_1$과 $L\_3$는 노드를 공유하지 않으므로 서로 독립이다.

이 정보를 종합하여,

$$
\Delta\_0  = 1  - (L\_1 + L\_2 + L\_3) + (L\_1 \cdot L\_2 \quad \text{독립이면 곱}  ;+; L\_1 \cdot L\_3 \quad \text{독립이면 곱}  ;+; L\_2 \cdot L\_3 \quad \text{독립이면 곱}) - (\text{세 개씩 독립이면 곱}) + \cdots
$$

형식이 되는데, 이 예시에서는 $L\_2 \cdot L\_3$가 독립 루프 곱에 들어가면 안 된다. 그 결과

$$
\Delta\_0 = 1 - (H\_1 + H\_2 + G\_4 H\_3) + (H\_1 H\_2 + H\_1 G\_4 H\_3) - (\text{그 외 항은 0})
$$

가 된다.

#### 각 경로에 대한 $\Delta\_i$ 계산

각 경로 $P\_i$에 대해 공통 노드를 갖는 루프는 고려 대상에서 제외하고, 나머지 독립 루프들의 조합으로 $\Delta\_i$를 구한다.

$P\_1 = X \rightarrow A \rightarrow C \rightarrow Y$ 경로는 노드 $A$와 $C$를 포함한다. 그와 노드를 공유하는 루프는 $L\_1(A \rightarrow A)$, $L\_3(B \leftrightarrow C)$ 중 $L\_1$은 $A$ 노드가 겹치므로 제외해야 할 루프에 해당되고, $L\_3$는 $C$ 노드가 겹치므로 제외된다. $L\_2$는 $B$만 맴도므로 $P\_1$의 경로 노드와는 공유가 없다. 결국 $P\_1$에 대해 남는 독립 루프는 $L\_2$뿐이므로

$$
\Delta\_1  = 1  - L\_2  = 1  - H\_2
$$

가 된다.

$P\_2 = X \rightarrow B \rightarrow C \rightarrow Y$ 경로는 노드 $B, C$를 포함한다. 루프 $L\_2$는 $B$ 노드를, $L\_3$는 $B, C$ 노드를 포함하므로 둘 다 $P\_2$에 공통 노드를 갖는다. 즉 둘 다 제외된다. 루프 $L\_1$는 $A$만 맴도므로 $B, C$와 공유가 없어 독립적이다. 그리하여

$$
\Delta\_2  = 1  - L\_1  = 1  - H\_1
$$

가 된다.

#### Mason의 공식 적용

이제 전체 전달함수를 구하기 위한 Mason의 공식

$$
T(s)  = \frac{Y(s)}{X(s)}  = \frac{\sum P\_i \Delta\_i}{\Delta\_0}
$$

를 이용하면,

$$
T(s) = \frac{P\_1 \Delta\_1 + P\_2 \Delta\_2}{\Delta\_0}
$$

여기서

* $P\_1 = G\_1 G\_3 G\_5$
* $\Delta\_1 = 1 - H\_2$
* $P\_2 = G\_2 G\_4 G\_5$
* $\Delta\_2 = 1 - H\_1$
* $\Delta\_0 = 1 - (H\_1 + H\_2 + G\_4 H\_3) + (H\_1 H\_2 + H\_1 G\_4 H\_3)$

이므로, 대입하여 $T(s)$를 엄밀하게 표현할 수 있다. 전개를 하든, 그대로 두든 문제없이 전달함수를 명확히 정의할 수 있다. 복잡해 보이지만, 경로-루프 구조를 차근차근 따라가면 일관된 체계로 풀이가 가능하다.

#### 다중입력-다중출력(MIMO) 시스템에서의 신호 흐름선도

실제 제어시스템에서는 단일 입력-단일 출력(SISO) 구조보다 복수의 입력과 복수의 출력이 존재하는 다중입력-다중출력(MIMO) 구조가 흔히 나타난다. 이러한 경우에도 신호 흐름선도를 적용하면 시스템의 전체적인 신호 전달 관계를 시각적으로 명확히 표현할 수 있다. 다만 Mason의 공식은 기본적으로 단일 입력, 단일 출력 사이의 전달함수를 구하는 과정에 초점을 맞추고 있으므로, MIMO 문제를 다룰 때는 특정 입력 $X\_i$에서 특정 출력 $Y\_j$로 가는 전달 특성만을 신호 흐름선도로 추적하여 부분적으로 분석하는 방식이 일반적이다.

신호 흐름선도 자체는 노드와 가지를 통해 다양한 입출력을 표현할 수 있다. 예컨대 입력 노드가 $X\_1, X\_2, \dots, X\_m$개, 출력 노드가 $Y\_1, Y\_2, \dots, Y\_n$개라면, 각 입력 노드와 내부 노드, 출력 노드들 사이의 연결 관계를 가지이득(branch gain)으로 나타낸다. 내부 노드 역시 여러 합성점을 가질 수 있으며, 여러 개의 피드백 루프가 중첩되거나 서로 독립적으로 존재할 수 있다.

#### Mason의 공식 확장 적용

다중 입력-다중 출력 구조 전체를 놓고 한 번에 통합된 형태의 단일 전달함수를 정의하기는 어렵다. 보통 $G\_{ij}(s)$를 $X\_i \rightarrow Y\_j$의 전달함수로 정의하여, 각 입력-출력 쌍마다 신호 흐름선도를 따라 Mason의 공식을 독립적으로 적용하거나, 행렬 형태로 모아서 표현한다. 즉,

$$
\mathbf{G}(s)  = \begin{bmatrix} G\_{11}(s) & G\_{12}(s) & \cdots & G\_{1n}(s) \ G\_{21}(s) & G\_{22}(s) & \cdots & G\_{2n}(s) \ \vdots    & \vdots    & \ddots & \vdots    \ G\_{m1}(s) & G\_{m2}(s) & \cdots & G\_{mn}(s) \end{bmatrix}
$$

형태로 MIMO 전달함수 행렬을 구성한다. 각 $G\_{ij}(s)$는 신호 흐름선도의 $X\_i$에서 $Y\_j$로 이어지는 경로와 루프를 분석하여 얻은 결과값이다.

#### 예시를 통한 MIMO 신호 흐름선도

아래는 두 개의 입력($X\_1, X\_2$)과 두 개의 출력($Y\_1, Y\_2$)을 가지는 MIMO 구조의 단순화된 예시를 mermaid로 나타낸 것이다.

{% @mermaid/diagram content="graph LR
X1((X1)) -->|G11| N1
X2((X2)) -->|G21| N2
N1 -->|G12| Y1((Y1))
N2 -->|G22| Y2((Y2))
N1 -->|H12| N2
N2 -->|H21| N1" %}

이 그림은 크게 두 개의 내부 노드 $N\_1, N\_2$가 있고, $N\_1 \leftrightarrow N\_2$ 사이에 상호 루프 피드백 가지 $H\_{12}$, $H\_{21}$가 존재한다. $Y\_1$는 $N\_1$에서 직접 출력으로 나가며 가지이득이 $G\_{12}$, $Y\_2$는 $N\_2$에서 직접 출력으로 나가며 가지이득이 $G\_{22}$라고 설정한다. 입력 $X\_1$는 $N\_1$로, 입력 $X\_2$는 $N\_2$로 들어오는 가지이득이 각각 $G\_{11}$, $G\_{21}$이라 하자.

이때 $X\_1 \rightarrow Y\_1$ 경로를 기준으로 Mason의 공식을 적용하면, 내부 노드 $N\_1, N\_2$를 거치는 신호 흐름과 그에 따른 루프들을 파악할 수 있다. 동일한 방식으로 $X\_1 \rightarrow Y\_2$, $X\_2 \rightarrow Y\_1$, $X\_2 \rightarrow Y\_2$에 대해서도 각각 독립적으로 경로와 루프를 정리하여 전달함수를 도출한다. 모든 전달함수를 구한 뒤 적절히 행렬 형식으로 묶으면, 전체 시스템의 전달 특성이 명확하게 표현된다.

#### 행렬식 Mason 접근

MIMO 시스템에서 Mason의 공식이 확장된 형태로 직접 적용되는 경우, 각 노드를 고정된 순서로 나열하고 인접행렬(adjacency matrix) 기법을 활용하는 방법이 있다. 예를 들어 모든 노드를 $1, 2, \dots, r$이라 하고, $A\_{ij}(s)$를 $i$번째 노드에서 $j$번째 노드로 가는 가지이득이라면, 정방 행렬 $\mathbf{A}(s)$를 구성한 뒤, 이를 그래프이론의 관점에서 순환점수(cycle sum)와 경로식을 활용하여 해석할 수 있다. 그러나 이 방식을 실제 제어공학에서 직접 계산하기에는 Mason의 공식을 경로별로 적용하는 것만큼 간결하지 않을 수 있어, 일반적으로는 입력-출력 쌍별로 Mason의 공식을 따로 구하는 편이 더 직관적이다.

#### 상태방정식과 신호 흐름선도

선형 시불변 시스템에서의 상태방정식은

$$
\begin{aligned}
\dot{\mathbf{x}}(t) = A \mathbf{x}(t) + B \mathbf{u}(t)\\
\mathbf{y}(t) = C \mathbf{x}(t) + D \mathbf{u}(t)
\end{aligned}
$$

형태로 주어지며, 이를 $s$ 영역에서 라플라스 변환하면

$$
\begin{aligned}
\mathbf{X}(s) - \mathbf{x}(0) = A \mathbf{X}(s) + B \mathbf{U}(s)\\
\mathbf{Y}(s) = C \mathbf{X}(s) + D \mathbf{U}(s)
\end{aligned}
$$

로 표현한다. 상태공간 표현과 신호 흐름선도는 서로 직접적으로 연결지을 수 있다. 상태 변수 각각을 노드로 하여, 미분 방정식을 신호 흐름선도로 나타내면, 시스템 행렬 $A, B, C, D$에 대응하는 가지이득들이 흐름선도상에서 정해진다. 이렇게 구현한 신호 흐름선도를 통해 Mason의 공식을 쓰면, 상태공간 표현에서 시스템 전달함수 행렬을 유도하는 절차를 시각적으로 이해할 수 있다.

#### Mason의 공식 계산 알고리즘과 예제 코드(C++)

Mason의 공식을 이용하여 실제로 전달함수를 계산할 때에는, 먼저 흐름선도 내의 모든 노드와 가지를 파악하고, 입력과 출력 노드를 명확히 정의한 뒤 다음과 같은 절차를 진행한다.

1. 입력에서 출력으로 이어지는 모든 경로를 찾는다.
2. 모든 루프를 찾는다. 각 루프의 이득을 계산하고, 어떤 노드를 공유하는지 확인하여 독립 루프(disjoint loop)의 조합을 구한다.
3. 각 경로와 공통 노드를 공유하지 않는 독립 루프들의 조합으로 $\Delta\_i$를 계산한다.
4. $\Delta\_0$는 전체 루프에 대해 단일 루프이득 합, 독립 루프 쌍의 곱, 독립 루프 셋의 곱, 등등을 교대로 더하고 빼는 형태로 계산한다.
5. Mason의 공식으로 전달함수를 최종 산출한다.

다음은 Mason의 공식을 간단하게 구현해 보는 C++ 예시 코드다. 이 코드는 입력-출력 노드가 고정되어 있고, 그래프 정보(노드, 가지, 루프)를 개발자가 사전에 입력한다고 가정한 형태다. 실제로는 신호 흐름선도에서 루프 탐색과 독립 루프 판별을 자동화해야 하지만, 여기서는 알고리즘 개념을 보여주기 위해 함축적으로 구성했다.

```cpp
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;

// 간단한 구조체: 경로(Path)와 루프(Loop)를 표현
// 실제 구현에서는 그래프 탐색을 통해 자동으로 파악해야 한다.
struct Path {
    double gain;      // 경로이득
    vector<int> nodes; // 경로가 거치는 노드 (검증 용도)
};

struct Loop {
    double gain;       // 루프이득
    vector<int> nodes; // 루프가 거치는 노드
};

// 두 루프가 독립인지(노드 공유가 없는지) 판별하는 함수
bool isDisjoint(const Loop& L1, const Loop& L2) {
    for (auto n1 : L1.nodes) {
        for (auto n2 : L2.nodes) {
            if (n1 == n2) return false; // 노드 중복 발견
        }
    }
    return true;
}

// Mason's Gain Formula를 이용해 전달함수를 계산
// paths: 입력에서 출력으로 가는 모든 경로
// loops: 전체 그래프상의 모든 루프
// return: 최종 전달함수(스칼라값)
double computeTransferFunction(const vector<Path>& paths, const vector<Loop>& loops) {
    // 1) Delta_0 계산
    // 1-1) 모든 단일 루프이득 합
    double sumSingleLoop = 0.0;
    for (auto& L : loops) {
        sumSingleLoop += L.gain;
    }
    // 1-2) 두 루프씩 독립이면 곱을 합산(교호부호 적용 필요)
    double sumTwoLoop = 0.0;
    for (size_t i = 0; i < loops.size(); ++i) {
        for (size_t j = i + 1; j < loops.size(); ++j) {
            if (isDisjoint(loops[i], loops[j])) {
                sumTwoLoop += loops[i].gain * loops[j].gain;
            }
        }
    }
    // 1-3) 세 루프 이상 독립 조합도 일반화 가능. 여기서는 예시로 3개 독립만 처리
    double sumThreeLoop = 0.0;
    // 실제 구현에서는 3개 루프 중 서로 독립인지 확인하고 곱을 취해 부호를 적용
    
    // Delta_0 = 1 - (단일 루프 합) + (독립 루프 쌍의 곱) - (독립 루프 셋의 곱) + ...
    double Delta0 = 1.0 - sumSingleLoop + sumTwoLoop - sumThreeLoop;
    
    // 2) 각 경로에 대한 Delta_i 계산
    // 경로가 포함하는 노드와 겹치는 루프는 제외하고, 나머지 독립 루프들로 동일한 방식 계산
    // 간단 구현을 위해, 여기서는 "경로 노드와 겹치는 루프는 모두 제외" 후 남은 루프에 대해
    // 1 - (단일 루프) + (독립 쌍의 곱) ... 식을 적용한다.
    
    // 임시 함수를 정의해서 경로별 Delta_i를 계산해 본다.
    auto computeDeltaForPath = [&](const Path& P) {
        vector<Loop> pathIndependentLoops;
        for (auto& L : loops) {
            bool shared = false;
            for (auto nP : P.nodes) {
                for (auto nL : L.nodes) {
                    if (nP == nL) {
                        shared = true; 
                        break;
                    }
                }
                if (shared) break;
            }
            if (!shared) {
                pathIndependentLoops.push_back(L);
            }
        }
        double sumSingle = 0.0;
        for (auto& L : pathIndependentLoops) {
            sumSingle += L.gain;
        }
        double sumPair = 0.0;
        for (size_t i = 0; i < pathIndependentLoops.size(); ++i) {
            for (size_t j = i + 1; j < pathIndependentLoops.size(); ++j) {
                if (isDisjoint(pathIndependentLoops[i], pathIndependentLoops[j])) {
                    sumPair += pathIndependentLoops[i].gain * pathIndependentLoops[j].gain;
                }
            }
        }
        // 3개 이상 독립 루프도 유사하게 처리 가능
        double sumTriple = 0.0;
        double Delta_i = 1.0 - sumSingle + sumPair - sumTriple;
        return Delta_i;
    };
    
    // 3) 최종 전달함수를 Mason 공식으로 계산
    // T(s) = (sum of [P_i * Delta_i]) / Delta_0
    double numerator = 0.0;
    for (auto& P : paths) {
        double Delta_i = computeDeltaForPath(P);
        numerator += (P.gain * Delta_i);
    }
    
    double T = numerator / Delta0;
    return T;
}

int main() {
    // 예시: SFG가 다음과 같다고 가정
    // paths: 2개의 경로 (단순 예)
    // loops: 2개의 루프 (단순 예)
    
    vector<Path> paths {
        { 10.0, {0, 1, 2} }, // gain=10, 노드 0->1->2 (예: X->N->Y)
        { 5.0,  {0, 2}    }  // gain=5,  노드 0->2     (예: X->Y 직통)
    };
    
    vector<Loop> loops {
        { -2.0, {1} },       // gain=-2, 노드 1만 포함 (예: N->N으로 피드백)
        { 3.0,  {1, 2} }     // gain=3,  노드 1->2->1 (예: N->Y->N)
    };
    
    double T = computeTransferFunction(paths, loops);
    cout << "Computed Transfer Function = " << T << endl;
    return 0;
}
```

이 코드는 매우 단순화된 신호 흐름선도를 가정하고, 루프 탐색을 직접 작성하지 않은 상태에서, Mason의 공식을 컴퓨터가 수행할 수 있도록 보여준다. 실제 시스템에서는 신호 흐름선도의 노드를 그래프로 구현한 뒤, 모든 경로 탐색(DFS 혹은 BFS 응용), 모든 루프 탐색(DFS를 통한 사이클 검출), 독립 루프 판별 등을 자동화해야 한다. 그렇지만 이러한 자동화는 그래프 알고리즘의 일반적 적용이므로, Mason의 공식 자체를 이해하는 데에는 위와 같은 기본적 구조를 익히는 것으로 충분하다.

#### 신호 흐름선도와 블록선도 간 비교

전통적인 블록선도(block diagram)는 제어계 설계에서 매우 직관적으로 쓰인다. 한편 신호 흐름선도(signal flow graph)는 블록선도의 단점—복잡한 분기나 병렬 피드백 경로가 중첩될 때 연쇄적으로 블록 조작을 반복해야 하는 불편함—을 보완하며, Mason의 공식이라는 체계적 방법을 제공한다.

블록선도에서는 블록 간 직렬, 병렬, 피드백 구성 등 간단한 결합 형태를 점진적으로 줄여 나가면서 최종 전달함수를 얻는다. 그러나 루프가 여러 개 중첩되거나, 한 노드에서 여러 방향으로 가지가 뻗어나가면서 서로 다른 노드와 동시에 연결되는 구조가 나타나면, 블록선도만으로는 변환 과정이 번거로워진다.

반면 신호 흐름선도는 노드(node)와 방향성 가지(branch)를 사용하여, 시스템 내에서 신호가 흐르고 상호작용하는 모든 경로를 상대적으로 단순한 시각적 구조로 묘사한다. 여러 루프가 서로 영향을 주고받는 상황에서도 경로 방식(path approach)으로 접근하면, 한 번의 공식 적용(Mason’s Gain Formula)으로 최종 전달함수를 구할 수 있다.

#### 신호 흐름선도의 장점과 단점

신호 흐름선도의 장점은 다음과 같은 특성에 기인한다.

* 여러 경로와 여러 루프를 체계적으로 다룰 수 있다.
* 각 경로, 루프를 명시적으로 분리하여 고려하므로 중첩 피드백이나 병렬 경로가 많아도 Mason의 공식을 통해 정리하기 쉽다.
* 블록선도와 달리, 줄이기(reduction) 작업을 반복할 필요가 없다.

그러나 신호 흐름선도에도 몇 가지 단점이 존재한다.

* 복수의 입력과 복수의 출력이 있을 때, 각 입력-출력 쌍마다 각각의 경로와 루프 관계를 모두 기록해 주어야 하므로 도표가 커질 수 있다.
* 경로 탐색, 루프 탐색이 자동화되지 않은 경우, 큰 규모 그래프에서는 오류가 발생하기 쉽다.

결국 블록선도와 신호 흐름선도는 서로 대체 관계가 아니라, 적용 상황에 따라 상호 보완적으로 쓰인다. 간단하거나 구조가 명확한 경우에는 블록선도가 좀 더 직관적이고, 복잡도가 큰 경우에는 신호 흐름선도를 사용해 Mason의 공식을 적용하는 편이 효율적이다.

#### 폐루프 제어계 해석과 신호 흐름선도

폐루프(closed-loop) 구조의 제어계를 해석할 때, 시스템 전체 전달함수를 구하거나 특성방정식을 도출하는 과정은 매우 중요하다. 블록선도로 단일 피드백 루프만 있으면 $T(s) = \frac{G(s)}{1 + G(s)H(s)}$ 같은 형태로 단순히 표현된다. 그러나 실제로는 내부에 여러 개의 피드백 루프가 중첩되고, 경로가 병렬로 갈라지거나 합쳐지는 일이 흔하다.

신호 흐름선도를 작성하면, 모든 노드에서의 합성 관계와 가지이득을 명시적으로 드러낼 수 있다. 폐루프 해석은 곧 시스템이 가진 고유 루프의 형태, 루프이득, 루프 간 독립성 등을 분석하는 과정이 되는데, 이러한 요소들은 Mason의 공식에 그대로 반영되어 최종 전달함수에 들어가게 된다.

이 과정에서 루프 게인의 부호(sign)도 주의 깊게 파악해야 한다. 블록선도에서 +, - 합성점이 명시되는 것처럼, 신호 흐름선도에서도 가지이득이 음수인 경우가 있을 수 있으므로, 각 경로와 루프 이득을 정확히 추적해야 한다.

#### 상태공간 모델과 신호 흐름선도

선형 시불변 시스템을 상태공간(state-space) 형태로 기술했을 때, 시스템 행렬 $A, B, C, D$와 초기조건 $\mathbf{x}(0)$이 정해지면, 그 시스템을 나타내는 신호 흐름선도를 구성할 수 있다. 가장 직접적인 방법은 상태변수 각각을 노드로 놓고, 미분 방정식 $\dot{\mathbf{x}}(t) = A \mathbf{x}(t) + B \mathbf{u}(t)$, $\mathbf{y}(t) = C \mathbf{x}(t) + D \mathbf{u}(t)$에서 파생되는 각 항의 연결 관계를 가지이득으로 표현하는 것이다.

예를 들어 어떤 시스템에서 $x\_1, x\_2, \dots, x\_n$이 상태변수라면, 다음과 같은 형태의 신호 흐름선도를 생각해 볼 수 있다.

{% @mermaid/diagram content="graph LR
U((Input)) -->|B| X
X -->|A| X
X -->|C| Y((Output))" %}

보다 구체적으로는, $A$ 행렬의 각 성분이 상태변수들 간의 연결, $B$ 행렬이 입력에서 상태변수로 가는 연결, $C$ 행렬이 상태변수에서 출력으로 가는 연결, $D$ 행렬이 입력에서 직접 출력으로 가는 연결을 의미한다. 이를 통해 하나의 MIMO 신호 흐름선도가 형성되며, Mason의 공식으로 분석하면 전통적인 전입도행렬(transfer function matrix) $\mathbf{G}(s) = C(sI - A)^{-1} B + D$를 도출할 수 있다.

#### 고차 계(system)에서의 복잡도 처리

계의 차수가 올라가면(상태변수 수가 많아지거나 노드가 많아지면), 신호 흐름선도 역시 빠르게 복잡해진다. 그러나 복잡도는 단순히 블록선도를 줄이는 방식으로도 감당하기 쉽지 않다. 오히려 신호 흐름선도는 복잡한 구조가 그대로 시각화되므로 오류를 줄이는 데 도움이 되며, 컴퓨터로 그래프를 처리하는 여러 알고리즘(DFS 기반의 사이클 검출, disjoint loop 계산 등)을 이용해 자동 계산도 가능하다.

결국 고차 계를 다룰 때에도, 신호 흐름선도는 문제 구조 자체를 명확히 드러내고 Mason의 공식을 한 번에 적용할 수 있게 해 준다는 점이 강점이라 할 수 있다.

#### 신호 흐름선도의 활용 범위

신호 흐름선도와 Mason의 공식은 전통적인 선형 제어계 해석뿐 아니라, 선형 회로 이론, 디지털 필터 해석, 통신 시스템에서의 신호 경로 해석 등에도 적용 가능하다. 본질적으로 그래프 형태로 표현된 선형 연산들에 대해 적용될 수 있기 때문에, 라플라스 영역뿐 아니라 $Z$ 변환 영역에서도 비슷한 방식으로 응용된다. 예컨대 디지털 제어에서 $\mathbf{X}(z)$, $\mathbf{U}(z)$, $\mathbf{Y}(z)$ 등을 노드 변수로 정의하고, $z$ 영역에서의 이득(전달함수, $z$-도메인 이득)을 가지로 표기하면, 동일한 메커니즘으로 신호 흐름선도를 작성해 분석할 수 있다.

#### 고차 방정식 예제와 신호 흐름선도

연속시간 2차 계를 예로 들어, 미분방정식이

$$
\ddot{y}(t) + a\_1 \dot{y}(t) + a\_0 y(t) = b\_1 \dot{x}(t) + b\_0 x(t)
$$

와 같이 주어졌다고 하자. 이를 라플라스 변환하면 초기조건이 0이라 가정했을 때

$$
s^2 Y(s) + a\_1 s Y(s) + a\_0 Y(s) = b\_1 s X(s) + b\_0 X(s)
$$

가 된다. 이를 전개하면

$$
Y(s) = (b\_1 s + b\_0) X(s)
$$

이다. 전통적으로는 $G(s) = \frac{Y(s)}{X(s)} = \frac{b\_1 s + b\_0}{s^2 + a\_1 s + a\_0}$ 형태의 전달함수를 얻는다.

이 과정을 신호 흐름선도로 표현하기 위해서는, $y(t)$와 $\dot{y}(t)$, $\ddot{y}(t)$라는 물리적 해석을 노드로 직접 쓰는 대신, 보통은 $Y(s)$와 $sY(s)$, $s^2 Y(s)$ 등에 해당하는 라플라스 영역 변수를 활용하거나, 시간영역에서 상태변수 $x\_1 = y$, $x\_2 = \dot{y}$ 같은 방식을 택한다. 어떤 방식이든, 미분 연산을 가지이득으로 처리할 때 반드시 시간영역-라플라스영역 변환을 일관되게 사용해야 한다.

예를 들어, 시간영역에서

$$
x\_2(t) = \dot{y}(t)
$$

라 하고,

$$
\begin{aligned}
\dot{x}\_1(t) &= x\_2(t)\\
\dot{x}\_2(t) &= -a\_1 x\_2(t) - a\_0 x\_1(t) + b\_1 \dot{x}(t) + b\_0 x(t)
\end{aligned}
$$

와 같이 2차 미분방정식을 1차 2개로 분할해서 상태방정식을 구성할 수 있다. 이 상태공간 모형을 라플라스 영역에서 신호 흐름선도로 나타내면, 노드 $X\_1, X\_2$가 각각 $y, \dot{y}$를 표현하고, 미분항에 해당하는 가지이득들이 내부적으로 연결된다. 입력 $x(t)$에 대응하는 라플라스 변환 $X(s)$ 역시 노드로서 연결된다.

이렇게 형성된 신호 흐름선도에서 Mason의 공식을 적용하거나, 혹은 상태공간 전달함수 식 $G(s) = C(sI - A)^{-1}B + D$를 통해 동일한 결과를 얻게 된다. 신호 흐름선도의 경로-루프 계산은 이 시스템의 고유모드(고유값, 고유벡터)와 직결되는 내용이므로, 루프가 어떻게 작동하는지 파악하면 계의 극점(pole)이 어디에 존재하는지도 간접적으로 알 수 있다.

#### 신호 흐름선도의 줄이기와 변환

신호 흐름선도는 이론적으로는 Mason의 공식을 통해 단번에 전달함수를 구할 수 있지만, 때로는 흐름선도를 “더 간결한 형태”로 재배열하고 싶어질 수도 있다. 예를 들어 일부 가지가 단순 직렬, 병렬 형태로만 연결되어 있으면, 이를 먼저 합성해 주는 식으로 부분적으로 줄이는 과정이 가능하다.

노드를 다시 정의하거나, 특정 합점(summing junction)을 통합/분할함으로써 더욱 단순해진 흐름선도를 얻을 수 있다. 이 점에서 블록선도를 줄이는 것과 유사한 절차를 택할 수 있다. 차이가 있다면, 신호 흐름선도에서는 이 과정을 엄밀히 수행하더라도 Mason의 공식이 여전히 변함없이 적용된다는 것이다.

#### 신호 흐름선도에서의 부호와 위상

선형 시스템에서 피드백 신호가 위상 반전을 일으키거나, 어떤 경로에 음의 부호가 걸려 있으면, 신호 흐름선도상의 가지이득이 음수가 된다. 예컨대 피드백이 $-$ 부호라면 가지이득을 $-H(s)$와 같이 표현한다.

따라서 흐름선도 내 루프를 살필 때, 루프이득이 음수가 될 수도 있고, Mason의 공식에 들어가는 항 역시 양 또는 음 값을 모두 고려해야 한다. 이는 실제 물리계에서 위상 반전이나 부호 반전을 반영하는 중요한 사항이다. 한편 대부분의 경우 제어시스템 교과서에서는 간단히 “피드백이 음의 피드백”이라는 식으로 다루며, 흐름선도 해석 차원에서도 가지이득에 “$-H$”라고 적거나, 합점에서 $-$ 표기를 사용한다.

#### 비선형 계에서의 신호 흐름선도 적용 한계

신호 흐름선도와 Mason의 공식은 선형 계(linear system) 분석을 전제로 하며, 비선형 소자가 들어가거나 시간에 따라 파라미터가 달라지는 경우(time-varying system)에는 직접 적용하기 어렵다.

물론 국소적 선형화(local linearization)를 통해 특정 동작점 주변에서 선형 근사를 수행하면, 그 근사 모델에 대해서는 여전히 신호 흐름선도와 Mason의 공식을 적용할 수 있다. 이는 실제 제어계 설계에서 흔히 쓰이는 접근으로, 비선형 모델을 선형화한 다음, 해당 선형화 모델에 대해 전달함수를 구하고, 주파수 응답이나 안정도 판별 등의 기법을 활용한다.

신호 흐름선도와 경로 방식은 제어계 해석에서 중복된 피드백 루프나 복수 경로가 존재할 때 편리하며, 이론적으로도 Mason의 공식이 증명된 형태로 잘 정립되어 있어서 적용할 때 일관성이 있다. 선형 시스템에서 명확한 수학적 형태를 갖춘 블록선도라면, 언제든 신호 흐름선도로 변환하여 Mason의 공식을 사용할 수 있다.

비선형 요소, MIMO 구조, 상태공간 모델, 컴퓨터 알고리즘적 처리 등으로 확장해 볼 수 있으며, 실제로도 제어공학, 회로이론, 신호처리 분야에서 폭넓게 응용되고 있다.
