生物医学网络科学Biomedical Network Science
Example01 / 12

用 Kalman 秩判据检验可控性

所属专题
网络可控性与稳定性
下载
Notebook · .py

系统 dx/dt = A x + B u,A[i, j] != 0 表示有向边 j -> i;B 的每一列是一个独立输入,作用在一个驱动节点上。 可控性矩阵 C = [B, AB, A^2 B, …, A^{N-1} B],满秩(rank = N)则可控。 检查三种情形:(a) 链 0->1->2->3 只驱动节点 0;(b) 星 0->1, 0->2, 0->3 只驱动节点 0; (c) 星形再加驱动节点 2、3。解读:(a) 可控,(b) 不可控(叶子只能收到同一信号的不同倍数),(c) 可控。

Output输出图

用 Kalman 秩判据检验可控性:输出图 1

Output文字输出

链, 驱动{0}         rank = 4 / 4  -> 可控
星, 驱动{0}         rank = 2 / 4  -> 不可控
星, 驱动{0,2,3}     rank = 4 / 4  -> 可控

Code代码

# 系统 dx/dt = A x + B u,A[i, j] != 0 表示有向边 j -> i;B 的每一列是一个独立输入,作用在一个驱动节点上。
# 可控性矩阵 C = [B, AB, A^2 B, ..., A^{N-1} B],满秩(rank = N)则可控。
# 检查三种情形:(a) 链 0->1->2->3 只驱动节点 0;(b) 星 0->1, 0->2, 0->3 只驱动节点 0;
# (c) 星形再加驱动节点 2、3。解读:(a) 可控,(b) 不可控(叶子只能收到同一信号的不同倍数),(c) 可控。
import numpy as np

def system_matrix(edges, n, seed=0):
    rng = np.random.default_rng(seed)
    A = np.zeros((n, n))
    for u, v in edges:
        A[v, u] = rng.uniform(0.5, 1.5)        # 随机非零权重
    return A

def input_matrix(drivers, n):
    B = np.zeros((n, len(drivers)))
    for j, d in enumerate(drivers):
        B[d, j] = 1.0
    return B

def ctrb_rank(A, B):
    n = A.shape[0]
    C = np.hstack([np.linalg.matrix_power(A, k) @ B for k in range(n)])
    return np.linalg.matrix_rank(C)

chain = [(0, 1), (1, 2), (2, 3)]
star = [(0, 1), (0, 2), (0, 3)]
cases = []
for name, edges, drv in [("链, 驱动{0}", chain, [0]), ("星, 驱动{0}", star, [0]), ("星, 驱动{0,2,3}", star, [0, 2, 3])]:
    r = ctrb_rank(system_matrix(edges, 4), input_matrix(drv, 4))
    cases.append((edges, drv, r))
    print("%-16s rank = %d / 4  -> %s" % (name, r, "可控" if r == 4 else "不可控"))

import networkx as nx
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 3, figsize=(10, 3.4))
titles = ["chain, drive {0}", "star, drive {0}", "star, drive {0,2,3}"]
for ax, (edges, drv, r), title in zip(axes, cases, titles):
    G = nx.DiGraph(edges)
    pos = {0: (0, 0), 1: (1, 0), 2: (2, 0), 3: (3, 0)} if edges is chain else {0: (0, 0), 1: (1, 1), 2: (1, 0), 3: (1, -1)}
    nx.draw_networkx_edges(G, pos, ax=ax, edge_color="0.5", arrows=True, arrowsize=14, node_size=400)
    nx.draw_networkx_nodes(G, pos, ax=ax, node_size=400, node_color=["tab:red" if v in drv else "0.85" for v in G])
    nx.draw_networkx_labels(G, pos, ax=ax, font_size=9)
    ax.set_title("%s\nrank = %d / 4 (%s)" % (title, r, "controllable" if r == 4 else "not controllable"), fontsize=10)
    ax.axis("off"); ax.margins(0.2)
plt.tight_layout(); plt.show()

Run在浏览器中运行

首次加载 Python 环境约需 20–40 秒;可以修改参数后重新运行。

用 Kalman 秩判据检验可控性