程序初版完成,目前收敛后结果不太对
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user