블록선도의 개념¶
제어 시스템을 설계하거나 분석할 때, 블록선도는 시스템의 구성 요소와 이들 간의 상호 작용을 시각적으로 표현하는 데 매우 유용하다. 전압, 전류, 모멘트, 토크 등의 물리적인 신호를 수학적으로 옮긴 뒤, 이를 입력과 출력으로 가지는 전송 경로로 나타내는 것이 블록선도이며, 이때 각 블록은 보통 전달함수로 표기한다. 블록선을 연결하는 합성점과 분기점, 그리고 피드백 경로 역시 시스템 거동을 단순화하고 구조적 특징을 파악하기 쉽게 도와준다.
블록선도 간소화 규칙은 여러 개의 전송 블록과 합성점, 분기점 등을 최소 개수로 재배열하여, 원래의 입력–출력 관계를 유지하면서도 복잡도를 낮추는 일련의 절차이다. 간소화 과정에서 가장 중요한 사항은, 어떤 방식으로 합치거나 옮겨도 최종 입력과 최종 출력 사이의 전달함수가 동일하게 유지되어야 한다는 것이다.
블록선도가 한눈에 파악하기 어려울 만큼 복잡해지면, 이 규칙들을 단계적으로 적용해가면서 시스템의 구조를 재정렬한다. 결과적으로 시스템 분석이 용이해지고, 수식화 과정도 간결해진다.
직렬 결합¶
두 개 이상의 블록이 직렬로 연결되어 있을 때 이들을 하나의 블록으로 합성하면, 각 블록의 전달함수들을 곱한 형태로 나타낼 수 있다. 예를 들어 블록 \(G_1(s)\)과 \(G_2(s)\)가 직렬로 연결되어 있다고 하자. 출력으로 나오는 신호는 입력 신호에 두 블록의 효과가 순차적으로 곱해진 형태가 되므로, 직렬 결합된 블록의 등가 전달함수는
가 된다.
더 나아가 직렬 결합이 \(n\)개 블록으로 확장된 상황이라면, 단순히 모든 전달함수를 곱하여 하나의 등가 블록으로 표현할 수 있다. 실제 블록선도를 간소화할 때 직렬 결합은 쉽게 인지 가능하기 때문에, 가장 먼저 적용하기 좋은 규칙이기도 하다.
병렬 결합¶
동일한 입력 신호가 여러 개의 블록에 분기되어 동시에 전달되고, 각 블록의 출력이 더해지거나 빼지는 형태를 병렬 결합이라 한다. 병렬 결합은 하나의 합성점에서 블록별 출력이 합쳐지는 구조가 되는데, 두 블록 \(G_1(s)\)과 \(G_2(s)\)가 병렬 결합되어 있다고 하면, 그 합성점에서 나온 합성 출력은
로 나타날 수 있다.
병렬 결합은 입력이 동일하되 처리되는 경로가 여러 개이며, 결과적으로 각 경로의 출력이 합성점을 통해 더해진다. 병렬 결합의 간소화 규칙은 각 블록을 합산 관계로 합쳐버리기 때문에, 실제 블록선도 상에서의 병렬 구조를 빠르게 하나의 큰 블록으로 묶을 수 있다.
피드백 루프¶
블록선도 간소화에서 핵심적인 부분은 피드백 루프를 간단하게 표현하는 것이다. 가장 기본적인 단일 루프 피드백 구조는, 순방향 블록이 \(G(s)\)이고, 피드백 경로가 \(H(s)\)인 경우를 예로 들 수 있다. 이때 시스템의 폐루프 전달함수는
가 된다.
블록선도를 처리하다 보면 위와 같은 형태의 피드백 루프가 여럿 등장하거나, 피드백 경로 안에 병렬 및 직렬 결합이 동시에 나타나는 등 복합적 형태가 발생할 수 있다. 이러한 상황에서 가장 기본이 되는 간소화 규칙이 바로 위 식을 활용해, 여러 개의 블록과 피드백 경로를 단순화하여 하나의 폐루프 블록으로 치환하는 것이다.
예시 블록선도¶
아래는 가장 단순한 형태의 직렬 결합과 피드백 루프를 포함하는 블록선도 예시를 Mermaid 문법으로 표현한 것이다.
이 블록선도에서는 입력이 블록 G1(s)를 거쳐 G2(s)로 전달되고, 최종 합성점에서 출력 Y가 나온다. 동시에 출력은 H(s) 경로를 통해 부호가 반전된 형태로 다시 G1(s)의 입력으로 돌아오는 단순 피드백 구조이다.
이와 같이 간단한 구조라도, 간소화 규칙에 따라 블록선을 재배열하면 하나의 단일 블록으로 치환하여 분석을 쉽게 할 수 있다. 시스템 전체에 대한 전달함수는 위에서 언급한 기본 피드백 공식에 따라 \(G_1(s) , G_2(s)\)와 \(H(s)\)의 조합으로 간단히 표현 가능하다.
합성점 이동¶
블록선도에서 합성점의 위치는 신호 흐름을 바꾸지 않는 선에서 자유롭게 조정할 수 있다. 다만 합성점 앞이나 뒤에 존재하는 블록이 곱해지는지 또는 나누어지는지에 따라, 실제로 합성점을 이동할 때 관계식이 달라진다. 합성점 이동의 원리는 ‘합성점으로 들어오는 모든 신호가 합쳐진 후 블록을 통과시키는 것’과 ‘각 신호가 개별적으로 블록을 통과한 뒤 그 출력들을 다시 합성점에서 더하거나 빼는 것’이 동일한 결과를 가져오는지 확인하는 과정이다.
예를 들어 합성점이 블록 \(G(s)\) 뒤쪽에 있다고 하자. 해당 합성점으로 들어오는 두 신호 중 하나는 블록 \(G(s)\)를 통과하기 전의 신호, 다른 하나는 블록 \(G(s)\) 이후의 신호라고 하면, 이를 동일한 형태로 재배열하려면 모든 신호가 동일한 위치에서 블록을 통과해야 한다.
블록 \(G(s)\) 앞쪽에 합성점을 옮길 때, 합성점의 각 신호에 공통으로 \(G(s)\)가 곱해져야 한다면, 합성점에서 합해지는 항 각각에 대해 블록 \(G(s)\)를 곱해주어야 한다. 즉, 합성점이 블록 뒤에 있던 상황을 블록 앞쪽으로 이동하기 위해서는
이와 같은 기본 성질을 이용한다. 만약 합성점에서 두 신호가 뺄셈으로 결합된다면, 마찬가지로 \(x_1 G(s) - x_2 G(s)\) 형태로 표현되는지 확인하면서 이동해야 한다.
병렬 피드백 경로가 있거나, 여러 개의 합성점이 중첩된 복잡한 구조에서도 이 원리를 반복적으로 적용하여 합성점들의 위치를 조정할 수 있다. 복잡한 구조를 재배치하다 보면, 한 합성점을 한 번에 옮기는 것보다는 여러 단계로 나누어 조금씩 조정하는 편이 전체 블록선도를 더 깔끔하게 간소화하는 데 유리하다.
분기점 이동¶
분기점 역시 이동이 가능하다. 분기점에서 갈라진 신호가 블록을 몇 개 거친 뒤 다시 합성점에서 만나거나, 혹은 다른 분기점과 또 겹칠 수 있다. 이때 분기점을 한 위치에서 다른 위치로 옮긴다고 가정했을 때, 분기 후 각 신호가 얼마만큼 증폭 혹은 감쇠되는지를 제대로 고려해야 한다.
블록 \(H(s)\)가 분기점 뒤에만 존재하다가 분기점 앞쪽으로 옮겨질 경우, 원래는 \(x\)라는 신호가 분기된 뒤 일부만 \(H(s)\)를 통과했다면, 분기점이 \(H(s)\)의 앞쪽으로 옮겨진 뒤에는 모든 경로가 \(H(s)\)를 거치게 될 수도 있다. 이를 보정하기 위해서는 기존 신호 경로와 동일한 효과를 유지하도록, 분기 전후 관계를 고려한 등가 표현식을 만들어야 한다.
분기점 이동의 핵심은 분기된 각 신호에 대해 블록이 작용하는 부분을 적절히 배분하여, 결국 최종 출력 신호가 동일하게 되도록 만드는 것이다. 분기점 이동은 합성점 이동 규칙과 결합하여, 블록선도 상에서 직관적으로 나타나지 않는 상호 작용을 더 명료하게 정리하는 과정에서도 활용된다.
중첩된 피드백 구조¶
실제 시스템을 다루다 보면, 단일 루프 피드백에 추가로 내부 루프가 존재하거나, 피드백 경로 안에 다시 피드백이 걸리는 형태의 중첩된 폐루프 구조를 종종 접한다. 이런 구조들은 직렬, 병렬, 단일 피드백 규칙만으로 간단히 처리하기 쉽지 않으므로, 여러 합성점 이동과 분기점 이동, 그리고 부분 피드백 루프를 순서대로 축소해나가는 접근이 요구된다.
\(G_1(s)\)와 \(G_2(s)\)가 연속적으로 존재하고, 그 사이에 피드백이 존재하는 형태를 먼저 간소화한 뒤, 그 결과물과 외부에 있는 또 다른 피드백 루프를 합쳐 단일 블록으로 치환하는 식이다. 수차례의 루프 축소와 합성점, 분기점 이동을 적절히 반복함으로써, 결국 복잡한 블록선도를 하나의 큰 피드백 블록 혹은 그보다 간단한 직병렬 병합 형태로 표현할 수 있다.
예를 들어 내부 루프가 \(G_{\mathrm{in}}(s)\)와 \(H_{\mathrm{in}}(s)\)로 구성되어 있고, 외부 루프가 \(G_{\mathrm{out}}(s)\)와 \(H_{\mathrm{out}}(s)\)로 구성되어 있다고 가정하면, 내부 루프만 떼어서 다음과 같은 형태로 표현한다.
이를 단일 블록 \(T_{\mathrm{in}}(s)\)으로 치환하고, 그 치환 블록과 외부 루프 \(G_{\mathrm{out}}(s)\), \(H_{\mathrm{out}}(s)\)를 다시 피드백 구조로 간소화하면, 최종 폐루프 전달함수를
와 같이 단계적으로 구할 수 있다.
이러한 구조적 재배열이 쉬워지면, 복잡해 보이던 블록선도의 전체 흐름을 효율적으로 파악할 수 있고, 필요한 경우 원하는 부분만 구체적으로 해석하거나, 설계 변수 최적화 등을 더 편리하게 적용할 수 있다.
다중 루프 피드백¶
복잡한 블록선도를 다루다 보면, 단일 폐루프 외에도 내부 루프, 외부 루프가 동시에 존재하거나, 여러 개의 피드백 경로가 서로 엮여 있는 다중 루프 피드백 구조가 자주 등장한다. 이러한 다중 루프 피드백 구조에서 전체 시스템을 단순화하기 위해서는, 가능한 내부 루프부터 하나씩 축소하고, 축소된 결과를 바탕으로 외부 루프를 차례로 접합해가는 단계적 접근이 유용하다.
예를 들어 내부 루프가 \(G_{\mathrm{in}}(s)\), \(H_{\mathrm{in}}(s)\)로 구성되고, 바깥에 또 다른 루프가 \(G_{\mathrm{out}}(s)\), \(H_{\mathrm{out}}(s)\)로 구성된 형태라면, 먼저 내부 루프를 단일 블록
으로 치환한다. 이후 \(T_{\mathrm{in}}(s)\)와 외부 루프의 \(G_{\mathrm{out}}(s)\), \(H_{\mathrm{out}}(s)\)가 만드는 큰 폐루프를
로 간단히 정리할 수 있다.
이 과정을 확장하여 내부 루프가 연속적으로 중첩되어 있거나, 내부 루프 위에 또 다른 분기점이 존재하는 복합적 상태에서도, 결국은 가장 안쪽에 있는 피드백부터 축소한 뒤 겉으로 나가면서 점진적으로 등가 블록을 형성해간다.
피드포워드 경로¶
피드백 루프 외에도, 출력에서 입력 방향과 같은 순방향으로 우회하는 피드포워드(Feedforward) 경로가 존재할 수 있다. 이러한 피드포워드 경로는 일반적으로 시스템이 예상치 못한 교란에 대해 선제적으로 반응하게 하거나, 특정 동작 상태에서 에러를 줄이기 위해 설계되는 경우가 많다.
블록선도에서 피드포워드 경로는 대개 외부 신호 또는 시스템 내부 신호를 중간 지점에서 취해, 별도의 블록을 통해 출력 쪽 합성점으로 보내는 형태로 나타난다. 피드포워드 경로가 있으면 단순한 폐루프 공식만으로 시스템의 전체 전달함수를 표현하기가 쉽지 않으므로, 먼저 피드포워드 경로를 포함한 순방향 경로와 피드백 경로를 확인한 뒤, 합성점이나 분기점 이동 규칙 등을 적극적으로 활용해 블록선을 재배열해가며 구조를 단순화한다.
피드포워드 경로를 포함한 블록선도 간소화의 핵심은, 순방향 경로와 피드백 경로가 서로 중복되거나 반복해서 나타나는 부분을 식별해, 한꺼번에 처리할 수 있는 요소를 먼저 정리해 나가는 것이다. 병렬 결합, 직렬 결합, 내부 피드백 축소 과정을 순차적으로 반복하여 피드포워드가 추가된 시스템의 등가 전달함수를 도출할 수 있다.
양방향 결합 구조¶
때로는 단순 피드백/피드포워드를 넘어, 입출력이 서로 얽혀 두 방향 모두로 상호작용하는 양방향 결합 구조가 나타나기도 한다. 예를 들어 어떤 출력이 다른 출력의 입력이 되기도 하고, 반대로 그 출력이 다시 원래의 입력에 피드백되는 형태의 상호 연결된 MIMO(Multi-Input Multi-Output) 블록선도에서 종종 확인된다.
이런 양방향 결합 시스템에서 블록선도를 단순화하려면, 개별 단일 입력–출력 루프의 축소가 아니라, 시스템 전체에 대한 행렬 형태의 전달함수를 고려해야 한다. 즉, 각 입력에 대해 여러 출력이 어떻게 반응하는지를 행렬 전달함수
로 나타내는 방식을 활용하고, 이 행렬 연산을 통해 시스템 간소화를 진행한다. 행렬 전후에 합성점이나 분기점이 존재하는 경우에도, 마찬가지로 합성점 이동, 분기점 이동의 원리를 확장 적용하여 시스템 전체를 관찰해야 한다.
양방향 결합 구조를 재배열할 때에는, 한 신호가 다수의 경로로 갈라지거나, 다수의 신호가 하나의 블록으로 합쳐지는 상황에서 기존 블록들이 행렬 연산과 어떻게 결합되는지를 면밀히 살펴야 한다. 필요한 경우, 스칼라 전달함수를 행렬 전달함수로 승격하여 표현하고, 해당 행렬에 더하기 혹은 곱하기가 일관되게 적용되는지 점검하면서 블록선도를 축소한다.
Mason의 공식 (Mason’s Rule)¶
블록선도 간소화 규칙은 직관적으로 접근하기 쉬운 반면, 경로가 매우 복잡하게 얽혀 있을 때는 하나하나 단계를 거쳐가며 합성점과 분기점을 이동하는 방식이 꽤 번거로울 수 있다. 이럴 때 신호 흐름선을 그래프로 인식하고, 그래프 이론에 기반하여 폐루프 및 순방향 경로를 한꺼번에 분석할 수 있도록 한 것이 Mason의 공식이다.
Mason의 공식은 노드(node)와 분지(branch) 개념을 통해 그래프를 정의하고, 모든 순방향 경로(Forward Path), 루프(Loop), 경로 간 공통 노드 공유 여부 등을 한 번에 계산함으로써 신호 흐름 그래프의 전이 함수를 구하는 방법이다. 전통적인 블록선도 역시 신호 흐름 그래프로 볼 수 있기 때문에, 복잡한 다중 루프가 있는 블록선도에서 Mason의 공식을 적용해 단시간에 전달함수를 도출하기도 한다.
Mason의 공식을 한 줄로 요약하면, 모든 순방향 경로 이득의 합을 분자로 두고, 루프 이득과 상호 루프 상쇄 효과 등을 반영한 항을 분모에 둠으로써 전체 전달함수를 구하는 기법이다. 간략히 표현하면
와 같이 나타내고, 여기에서 – \(P_k\)는 \(k\)번째 순방향 경로 이득 – \(\Delta\)는 전체 루프에 대한 개략적인 보정값(1 - 모든 루프 이득 + 상호작용 항) – \(\Delta_k\)는 \(k\)번째 순방향 경로가 포함되지 않는 루프들에 대한 보정값
등으로 정의된다.
Mason의 공식은 신호 흐름 그래프 이론을 전제로 하므로, 블록선도를 신호 흐름 그래프로 치환하거나, 원래부터 신호 흐름 그래프로 표현된 모델을 다룰 때 그 유용성이 크게 부각된다. 특히 여러 순방향 경로가 서로 다른 합성점을 통과하고, 거기에다 여러 피드백 루프가 중첩된 형태일 때, 블록선도를 간소화하는 대신 Mason의 공식을 빠르게 적용하여 전달함수를 일괄적으로 계산하는 방식을 쓰기도 한다.
복잡한 예시 구조¶
아래 다이어그램으로 그려진 예시는, 두 개의 내부 루프와 피드포워드 경로가 동시에 포함된 비교적 복잡한 구조를 단순화하는 과정을 시각화한 것이다.
이 블록선도는 다음의 요소를 포함한다. 피드백1(내부 루프1): sum1 → H1(s) → G3(s) → sum1 피드백2(내부 루프2): sum2 → H2(s) → sum1 피드포워드: 입력 A에서 sum2로 직접 이어지는 Gf(s)
순차적으로 접근하려면 먼저 피드백1을 sum1 지점에서 축소하고, 그 결과물로 sum1을 단순화한 뒤, 피드백2가 결합된 전체 경로를 정리하는 과정을 거친다. 이후 피드포워드 블록 Gf(s)를 병합시키면, 최종적으로 입력 A와 출력 Y 간 전달함수를 하나의 폐루프 형태로 표현할 수 있다. 이 과정에서 합성점 이동, 분기점 이동, 내부 루프 폐쇄 등 일련의 규칙을 유연하게 적용해야 한다.
Mason의 공식 적용 예시¶
Mason의 공식은 신호 흐름 그래프(Signal Flow Graph) 상에서 직접 전달 경로와 루프(Loop)를 식별한 뒤, 각 경로 이득과 루프 이득을 정리하여 전체 전달함수를 한 번에 구하는 기법이다. 복잡한 다중 피드백 구조에서 합성점과 분기점을 계속 옮기며 블록선도를 축소해가는 방식이 번거로울 경우, Mason의 공식을 적용하면 계산 과정을 크게 단순화할 수 있다.
신호 흐름 그래프 상에서 노드(node)가 블록선도의 각 지점에 대응하고, 노드 사이를 연결하는 간선(edge)이 블록(전달함수)에 대응한다고 볼 수 있다. 예컨대 입력 노드를 1번, 출력 노드를 N번이라고 하면, 1번 노드에서 N번 노드로 가는 모든 순방향 경로(Forward Path)를 찾아 이득을 구하고, 각 루프(Loop)의 이득과 서로 다른 루프들이 공유하는 노드에 따른 상호작용 항을 계산한다.
Mason의 공식에 따른 전체 전달함수는
와 같은 꼴이 되며, \(P_k\)는 \(k\)번째 순방향 경로 이득, \(\Delta\)는 모든 루프를 고려한 ‘한꺼번에 반영된 루프 결합 이득 보정 항’, \(\Delta_k\)는 \(k\)번째 순방향 경로가 포함되지 않는 루프들만 고려한 루프 이득 보정 항 을 의미한다.
Mason의 공식을 적용하는 순서 개략¶
먼저 신호 흐름 그래프에서 입력 노드와 출력 노드를 정의한다. 그 다음 입력 노드에서 시작해 출력 노드까지 이어지는 모든 순방향 경로를 찾고, 각 경로를 구성하는 간선(전달함수)의 곱으로 \(P_k\)를 계산한다. 모든 루프를 식별하고, 각 루프의 이득(해당 루프를 이루는 간선들의 전달함수 곱)을 구한다. 루프들 간에 공통 노드가 있으면 상호 간섭(Non-Touching) 여부를 체크하여, 상호 루프가 Touching 관계인지 혹은 Non-Touching 관계인지를 구분한다. Non-Touching 루프들의 조합에 대한 이득을 루프 이득에 반영하여 \(\Delta\)를 구성한다. 각 순방향 경로별로, 해당 경로가 이용하는 노드를 제외하고 계산되는 루프 이득을 모아 \(\Delta_k\)를 구성한다. 마지막으로 Mason의 공식을 통해 전체 전달함수 \(T\)를 도출한다.
Mason의 공식 간단 구현 예 (C++)¶
아래 예제 코드에서는, Mason의 공식을 통해 다중 루프가 있는 간단한 신호 흐름 그래프의 전체 전달함수를 자동으로 계산하는 방식을 간략히 시연한다. 실제 블록선도 내 노드 번호나 간선 리스트, 전달함수의 구체적 형태에 따라 코드는 달라질 수 있으나, 이 예시는 일반적인 접근 방식을 파악하는 데 목적이 있다.
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
// 전달함수(또는 배수를 나타내는) 정보를 단순화하여 double 로 가정
// 실제 응용에서는 symbolic 표현이나 분수 객체를 사용하기도 함
// 구조체: 그래프의 간선
struct Edge {
int from;
int to;
double gain;
};
// Mason 공식 계산 클래스
class MasonSolver {
private:
int numNodes;
vector<Edge> edges;
int inputNode;
int outputNode;
// 순방향 경로, 루프 이득 저장용
vector<vector<int>> forwardPaths;
vector<vector<int>> loops;
vector<double> forwardPathGains;
vector<double> loopGains;
public:
MasonSolver(int n, int in, int out) : numNodes(n), inputNode(in), outputNode(out) {}
void addEdge(int f, int t, double g) {
edges.push_back({f, t, g});
}
// 모든 순방향 경로 및 루프 탐색 (DFS 활용 가능)
// 여기서는 데모 목적의 간단한 방식으로 기술
void findForwardPaths() {
// 실제 구현에서는 모든 경로를 찾기 위한 DFS 혹은 백트래킹 방법 사용
// 데모: 간단 가정
// 예: 직접 하드코딩, 테스트 데이터 기반
// forwardPaths.push_back({1, 2, 4}); 식으로 경로 노드 인덱스 넣을 수 있음
// ...
}
void findLoops() {
// 마찬가지로 모든 단일 루프 혹은 결합 루프 찾는 과정
// ...
}
// 주어진 노드 시퀀스를 바탕으로 이득 계산 (간선 곱)
double pathGain(const vector<int>& path) {
double g = 1.0;
for (size_t i = 0; i < path.size() - 1; i++) {
// path[i]에서 path[i+1]로 가는 간선의 gain을 찾아 곱해줌
double segmentGain = 1.0;
for (auto &e : edges) {
if (e.from == path[i] && e.to == path[i+1]) {
segmentGain = e.gain;
break;
}
}
g *= segmentGain;
}
return g;
}
// 각 루프 간 Non-Touching 여부 확인 (간단판)
bool isNonTouching(const vector<int>& loop1, const vector<int>& loop2) {
// loop1과 loop2가 공통 노드가 없으면 Non-Touching
for (auto &n1 : loop1) {
for (auto &n2 : loop2) {
if (n1 == n2) return false;
}
}
return true;
}
// Mason의 공식에 따라 전체 전달함수 계산
double computeOverallGain() {
// 1) 순방향 경로 이득 계산
forwardPathGains.clear();
for (auto &fp : forwardPaths) {
forwardPathGains.push_back(pathGain(fp));
}
// 2) 루프 이득 계산
loopGains.clear();
for (auto &lp : loops) {
loopGains.push_back(pathGain(lp));
}
// 3) 전체 델타(Δ) 계산
// Δ = 1 - (합: 모든 루프 이득) + (합: Non-Touching 루프 쌍 곱) - ...
// 여기서는 단순 1, 단일 루프까지만 적용
double delta = 1.0;
double sumLoopGains = 0.0;
for (auto g : loopGains) {
sumLoopGains += g;
}
delta -= sumLoopGains; // 단순 처리
// 4) 각 순방향 경로별 Δ_k 계산
// Δ_k = Δ에서 해당 순방향 경로가 포함하는 루프를 제외한 나머지를 반영
// 여기서는 데모 코드이므로 단순 1로 처리 가능
// 실제론 loop 와 path 의 노드 공유 여부를 분석해 Non-Touching 조합 반영
double numerator = 0.0;
for (size_t i = 0; i < forwardPaths.size(); i++) {
double pk = forwardPathGains[i];
double delta_k = 1.0; // 데모용
numerator += pk * delta_k;
}
return numerator / delta;
}
};
int main() {
// 예: 노드 수 5개, 입력 노드 1, 출력 노드 5라 가정
MasonSolver solver(5, 1, 5);
// 간선 추가 (예시)
solver.addEdge(1, 2, 2.0);
solver.addEdge(2, 3, 3.0);
solver.addEdge(3, 4, 4.0);
solver.addEdge(4, 5, 2.0);
// 피드백 루프 등 추가
solver.addEdge(3, 2, -1.0);
// 이 아래 findForwardPaths(), findLoops() 등을 구현한 뒤 호출
// 여기서는 생략 혹은 직접 하드코딩 가능
double totalGain = solver.computeOverallGain();
cout << "Overall Transfer Function Gain (Mason's Rule) = " << totalGain << endl;
return 0;
}
위 예시 코드는 Mason의 공식을 구현하기 위한 스케치에 가깝다. 실전에서는 블록선도를 구성하는 모든 노드와 간선을 완전 탐색하여 순방향 경로와 모든 루프, 그리고 루프 간의 Non-Touching 관계 등을 정밀하게 계산하는 알고리즘을 구현해야 한다. 특히 \(\Delta_k\) 항을 포함해, \(k\)번째 순방향 경로와 Touching 관계에 있는 루프만 제외한 나머지 루프들로 구성된 Non-Touching 세트의 이득을 합산하는 과정이 필수다.
Mason의 공식을 구현함으로써, 블록선도가 매우 복잡해도 그래프 이론적 해석을 통해 전체 전달함수를 직접 계산할 수 있게 된다. 합성점 이동이나 분기점 이동으로 간소화 과정을 일일이 거치지 않고도, 순방향 경로와 루프들을 식별하기만 하면 비교적 빠르고 체계적으로 결과를 얻을 수 있다.