修改代码及README

This commit is contained in:
2025-11-02 20:47:28 +08:00
parent 64ca5e257a
commit b6a9feddc7
14 changed files with 1785 additions and 236 deletions
+62 -31
View File
@@ -30,41 +30,70 @@ except Exception as e:
def standard_to_canonical(A_s, B_s, C_s):
"""
将一个 2x2 的标准状态空间系统 (A_s, B_s, C_s) 转换为控制器规范型参数。
此实现基于论文附录 D.2 的推导,
通过计算特征多项式和可控性矩阵来找到变换矩阵 T_c。
参数:
A_s (np.ndarray): 2x2 状态矩阵
B_s (np.ndarray): 2x1 输入矩阵
C_s (np.ndarray): 1x2 观测矩阵
返回:
dict: 包含 'a0', 'a1', 'b0', 'b1' 的字典
"""
dx = A_s.shape[0]
if dx != 2:
raise ValueError("此转换函数仅为 dx=2 的情况实现。")
# 确保输入是 numpy 数组
A_s = np.asarray(A_s)
B_s = np.asarray(B_s)
C_s = np.asarray(C_s)
if A_s.shape != (2, 2) or B_s.shape != (2, 1) or C_s.shape != (1, 2):
raise ValueError(f"输入维度不正确: A_s {A_s.shape}, B_s {B_s.shape}, C_s {C_s.shape}")
# 1. 计算特征多项式系数: p(λ) = λ^2 + a1*λ + a0
# 1. 计算特征多项式系数 (来自 Ac)
# p(λ) = λ^2 - tr(A_s)λ + det(A_s)
# 规范型 p(λ) = λ^2 + a1*λ + a0
# 比较系数: a1 = -tr(A_s), a0 = det(A_s)
a1_true = -np.trace(A_s)
a0_true = np.linalg.det(A_s)
# 2. 构造转换矩阵 T_c
I = np.eye(dx)
f1 = (A_s + a1_true * I) @ B_s
# 2. 构造转换矩阵 T_c^{-1} = [f1, f2]
I = np.eye(2)
# 根据附录 D.2 (1157), f_k = (A_s + a_{d-1}I)f_{k+1} + ...
f2 = B_s
Tc_inv = np.hstack([f1, f2])
if np.linalg.matrix_rank(Tc_inv) < dx:
raise np.linalg.LinAlgError("系统 (A_s, B_s) 不是可控的,无法转换为控制器规范型。")
Tc = np.linalg.inv(Tc_inv)
# 3. 转换 C 矩阵: C_c = C_s * T_c
C_c = C_s @ Tc
f1 = (A_s + a1_true * I) @ B_s
Tc_inv = np.hstack([f1, f2]) # 这是 T_c
print(f"[standard_to_canonical] 恢复的 T_c (即 Tc_inv):\n{Tc_inv}")
# 3. 检查可控性 (Controllability)
if np.linalg.matrix_rank(Tc_inv) < 2:
raise ValueError("系统不可控 (Uncontrollable), 无法转换为控制器规范型。")
# 4. 计算转换矩阵 T_c (这是 T_c^{-1})
Tc = np.linalg.inv(Tc_inv) # 这是 T_c^{-1}
print(f"[standard_to_canonical] 恢复的 T_c^{{-1}} (即 Tc):\n{Tc}\n")
# 5. 应用变换找到 C_c = [b0, b1] (来自 Cc)
# 正确的公式是 C_c = C_s * T_c
# 在我们的变量名中, T_c 是 Tc_inv
C_c = C_s @ Tc_inv # 这是正确行 (C_s * T_c)
b0_true = C_c[0, 0]
b1_true = C_c[0, 1]
true_params = {'a0': a0_true, 'a1': a1_true, 'b0': b0_true, 'b1': b1_true}
print("\n--- Ground Truth 转换结果 ---")
print(f"真实规范型参数: {true_params}")
return true_params
# 打印矩阵
print(f"[standard_to_canonical] 计算得到的规范型参数:")
print(f" a0: {a0_true}, a1: {a1_true}, b0: {b0_true}, b1: {b1_true}\n")
return {
'a0': a0_true,
'a1': a1_true,
'b0': b0_true,
'b1': b1_true
}
# =========================================================================
# 可视化函数
@@ -192,7 +221,7 @@ if __name__ == '__main__':
# --- 2. 仿真数据 ---
print("\n--- (步骤 2) 生成仿真数据 ---")
T_steps, sigma_proc, sigma_meas = 400, 0.3, 0.5
T_steps, sigma_proc, sigma_meas = 800, 0.05, 0.05
u_data, y_data = simulate_lti_data(
A_true, B_true, C_true, D_true, T_steps, sigma_proc, sigma_meas,
rng_seed=int(sim_key[0])
@@ -219,9 +248,9 @@ if __name__ == '__main__':
print("\n--- 运行规范型模型 MCMC (在真实值附近初始化) ---")
mcmc_key_c, mcmc_key = jax.random.split(mcmc_key)
# --- (修改) 在真实值附近添加小的随机扰动 (±10%) ---
# --- (修改) 在真实值附近添加小的随机扰动 (±30%) ---
init_key = init_noise_key_c # 使用独立的 key
noise_scale = 0.1 # 10% 的扰动
noise_scale = 0.3 # 30% 的扰动
init_params_c_noisy = {}
for param_name, true_value in true_params_c.items():
# 确保即使 true_value 为 0 也有扰动,添加一个小的基准值
@@ -250,16 +279,17 @@ if __name__ == '__main__':
u_data_jax,
y_data_jax,
sigma_proc,
init_params=init_params_c_noisy # <-- 使用带扰动的初始值
sigma_meas,
init_params = None # <-- 使用带扰动的初始值
)
if choice in [2, 3]: # 运行标准型
print("\n--- 运行标准型模型 MCMC (在真实值附近初始化) ---")
mcmc_key_s, mcmc_key = jax.random.split(mcmc_key)
# --- (修改) 在真实值附近添加小的随机扰动 (±10%) ---
# --- (修改) 在真实值附近添加小的随机扰动 (±30%) ---
init_key = init_noise_key_s # 使用独立的 key
noise_scale = 0.1 # 10% 的扰动
noise_scale = 0.3 # 30% 的扰动
init_params_s_noisy = {}
for param_name, true_value in true_params_s.items():
# 确保即使 true_value 为 0 也有扰动
@@ -276,6 +306,7 @@ if __name__ == '__main__':
u_data_jax,
y_data_jax,
sigma_proc,
sigma_meas,
init_params=init_params_s_noisy # <-- 使用带扰动的初始值
)