101 lines
4.0 KiB
Python
101 lines
4.0 KiB
Python
import numpy as np
|
|
from scipy.linalg import solve_discrete_lyapunov
|
|
import sys
|
|
|
|
def generate_ground_truth_system(dx=2, du=1, dy=1, rng_seed=None):
|
|
"""
|
|
生成一个 "真实" 的、稳定的、可控的、可观测的 LTI 系统。
|
|
|
|
该过程遵循论文 6.2 节中描述的方法。
|
|
|
|
参数:
|
|
dx (int): 状态维度 (state dimension)
|
|
du (int): 输入维度 (input dimension)
|
|
dy (int): 输出维度 (output dimension)
|
|
rng_seed (int, optional): 用于复现的随机种子
|
|
|
|
返回:
|
|
tuple: (A, B, C, D) 矩阵
|
|
"""
|
|
|
|
# 初始化随机数生成器
|
|
if rng_seed is None:
|
|
rng = np.random.default_rng()
|
|
else:
|
|
rng = np.random.default_rng(rng_seed)
|
|
|
|
# 尝试生成一个良态的系统,最多重试 100 次
|
|
max_retries = 100
|
|
for attempt in range(max_retries):
|
|
try:
|
|
# --- 1. 生成稳定的 A 矩阵 (dx x dx) ---
|
|
# 论文图 2(b) 显示了复特征值,遵循 6.2 节的极坐标法
|
|
|
|
# 在极坐标下采样一对共轭复特征值
|
|
r_squared = rng.uniform(0, 1.0) # 采样 r^2,确保在单位圆内
|
|
r = np.sqrt(r_squared)
|
|
theta = rng.uniform(0, np.pi) # 仅在上半平面采样角度
|
|
|
|
lambda1 = r * (np.cos(theta) + 1j * np.sin(theta))
|
|
lambda2 = np.conjugate(lambda1)
|
|
|
|
# 创建对应的实数块对角矩阵
|
|
alpha, beta = lambda1.real, lambda1.imag
|
|
lambda_block = np.array([[alpha, beta],
|
|
[-beta, alpha]])
|
|
|
|
# 生成一个随机正交矩阵 V (dx x dx) [cite: 511, 584]
|
|
Z = rng.standard_normal(size=(dx, dx))
|
|
V, _ = np.linalg.qr(Z)
|
|
|
|
# 组装 A = V * Lambda_block * V^T
|
|
A = V @ lambda_block @ V.T
|
|
|
|
# --- 2. 生成 B (dx x du) 和 C (dy x dx) 矩阵 ---
|
|
# 元素从 N(0, 1) 独立采样
|
|
B = rng.standard_normal(size=(dx, du))
|
|
C = rng.standard_normal(size=(dy, dx))
|
|
|
|
# --- 3. 检查可控性和可观测性 ---
|
|
# 求解离散时间李雅普诺夫方程 (Lyapunov equation)
|
|
Wc = solve_discrete_lyapunov(A, B @ B.T) # Controllability Gramian
|
|
Wo = solve_discrete_lyapunov(A.T, C.T @ C) # Observability Gramian
|
|
|
|
# 检查 Gramian 矩阵的条件
|
|
# "拒绝主要特征值占总能量 99% 以上的系统"
|
|
eig_Wc = np.linalg.eigvalsh(Wc)
|
|
eig_Wo = np.linalg.eigvalsh(Wo)
|
|
|
|
cond_c = np.max(eig_Wc) / np.sum(eig_Wc)
|
|
cond_o = np.max(eig_Wo) / np.sum(eig_Wo)
|
|
|
|
# 如果系统是良态的,则跳出循环
|
|
if cond_c < 0.99 and cond_o < 0.99:
|
|
|
|
# --- 4. 定义 D 矩阵 (dy x du) ---
|
|
# 算例 6.3 中 D=0
|
|
D = np.zeros((dy, du))
|
|
|
|
print(f"--- 成功生成 Ground Truth 系统 (尝试次数: {attempt + 1}) ---")
|
|
print(f"特征值: {lambda1:.4f}, {lambda2:.4f}")
|
|
print(f"Gramian 能量占比: Wc={cond_c:.4f}, Wo={cond_o:.4f}")
|
|
print("A = \n", A)
|
|
print("B = \n", B)
|
|
print("C = \n", C)
|
|
print("D = \n", D)
|
|
|
|
return A, B, C, D
|
|
|
|
except np.linalg.LinAlgError:
|
|
# 李雅普诺夫方程求解器可能失败(例如,A 矩阵数值上不稳定)
|
|
print(f"尝试 {attempt + 1} 失败 (LinAlgError)。正在重试...", file=sys.stderr)
|
|
continue
|
|
|
|
# 如果循环结束仍未成功
|
|
raise RuntimeError(f"在 {max_retries} 次尝试后未能生成一个良态的系统。")
|
|
|
|
if __name__ == '__main__':
|
|
# --- 运行示例 ---
|
|
# 设置一个随机种子,以便每次运行时都能得到相同的结果
|
|
A_true, B_true, C_true, D_true = generate_ground_truth_system(rng_seed=42)
|