Files
Baysian_Canonical_Identific…/generateGroudTruth.py
T

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)