PM_Process.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. // 函数功能:伪谱法具体实现过程
  2. // 输入:input:结构体
  3. // 输出:output:结构体
  4. // 方法:参考伪谱法的官方文献
  5. // 编写:李兆亭,2019 / 12 / 11
  6. // C++版本:李兆亭,2020/08/31
  7. #include <iostream>
  8. #include <armadillo>
  9. #include <time.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include "GPM.h"
  13. using namespace std;
  14. using namespace arma;
  15. output0* PM_Process(input0* input, functions1 functions, int *iteration_final) {
  16. uvec unit0; unit0 << 1 << endr;
  17. int IsStop = 0; // 伪谱法停止标识
  18. int iteration = 1; // 代数标识
  19. output0* output = new output0[100]; // 输出初始化
  20. int Sign_start = 1; // 检查正确标识符
  21. // 零、用户给定参数检查
  22. //Intput_add(input);
  23. Dismission_check(input, &Sign_start);
  24. int testmode = (*input).setup.testmode;
  25. // Dismission_check(input, Sign_start);
  26. if (Sign_start == 0) {
  27. return output;
  28. }
  29. // 一、参数本地化
  30. setup0 setup = (*input).setup;
  31. mesh1 mesh = setup.mesh; // 初始网格信息
  32. auxdata1 auxdata = setup.auxdata; // 公用参数信息
  33. guess0 guess = setup.guess; // 初始猜测值
  34. char* method = setup.method; // 伪谱法的方法
  35. NLP1 NLP = setup.NLP; // NLP求解器设置
  36. ///////////////////////////////////////////////////////////////////////////
  37. int(*Dynamics_temp1)(mat*, mat*, auxdata1, mat*, mat*, mat*) = functions.continous1;
  38. int(*Dynamics_temp2)(cx_mat*, mat*, auxdata1, mat*, mat*, mat*) = functions.continous2;
  39. int(*Dynamics_temp3)(mat*, cx_mat*, auxdata1, mat*, mat*, mat*) = functions.continous3;
  40. int(*Objective_temp)(input0*, double*, mat*) = functions.endpoint;
  41. /////////////////////////////////////////////////////////////////////////////
  42. char* interp_method = setup.interp.method;
  43. char* deri_supplier = setup.derivatives.supplier; // 导数计算方式
  44. int is_FSE = setup.feature.FSE; // 是否做终端状态估计
  45. int niu = setup.derivatives.number; // 至多v阶导数有全变分,至多(v - 1)阶导数可微
  46. double CC = setup.mesh.refinement.Conservative_coefficient; // 网格细化的保守系数
  47. int colpointsmax = mesh.colpointsmax; // 网格细化产生新interval下的最大配置点数目
  48. int interval_num = mesh.phase.inter_num; // 段p内的间隔数目, 整数, % 总间隔数目
  49. vec Npoints = mesh.phase.colpoints; // 段p内的配置点数目,整数数组,长度与间隔数目相等
  50. // 输入时间归一化
  51. double t0 = min(guess.phase.time); // 时间初值
  52. double tf = max(guess.phase.time); // 时间最大值
  53. vec T_guess1 = Normal(guess.phase.time, tf, t0); // 时间归一化
  54. vec interval_points_ratio = mesh.phase.i_proportion; // 初始网格由人工设置,为和为2、长度为间隔数的正向量
  55. // 问题中的常值量
  56. int length_state = (size(guess.phase.state))(1);
  57. int length_control = (size(guess.phase.control))(1);
  58. int length_path;
  59. if (setup.bounds.phase.path.lower.is_empty()){
  60. length_path = 0;
  61. }
  62. else {
  63. length_path = setup.bounds.phase.path.lower.n_rows;
  64. }
  65. int length_integral;
  66. if (setup.bounds.phase.integral.lower.is_empty()) {
  67. length_integral = 0;
  68. }
  69. else {
  70. length_integral = setup.bounds.phase.integral.lower.n_cols;
  71. }
  72. int length_event = (size(setup.bounds.phase.event.lower))(0);
  73. int length_parameter = (size(setup.auxdata.parameter))(0);
  74. // 状态、控制参数归一化
  75. mat U_guess1 = guess.phase.control;
  76. mat state_guess1 = guess.phase.state;
  77. // 待优化参数初始化
  78. vec parameter = auxdata.parameter;
  79. // 打印等级
  80. int print_level = NLP.ipoptoptions.print_level;
  81. // 二、伪谱法流程
  82. // 1 根据初始猜测值生成初始网格
  83. mat Col_Points, MeshGrid, Ts1_Te1;
  84. Col_Points = Points_Choose(method); // 配置点类型选择,由方法确定
  85. Mesh_initial(colpointsmax, interval_num, Npoints, Col_Points, interval_points_ratio, &MeshGrid, &Ts1_Te1);// 根据网格信息,生成具体网格
  86. // 差分步长
  87. double eps0 = 1e-8;
  88. /*MeshGrid = MeshGrid_nextstep;
  89. Ts1_Te1 = Ts1_Te1_nextstep;
  90. tf = tf_ans;
  91. t0 = t0_ans;
  92. Y_ans1 = Y_ans;
  93. U_ans1 = U_ans;*/
  94. vec T_old1, time_ans1;
  95. uvec N_Col, N_interp;
  96. mat Y_old1, U_old1, Y_ans1, U_ans1, D_phase, deta_t_interval, deta_t_in_col, temp;
  97. sp_mat Jacb_struct0;
  98. Jacb_struct_info0 Jacb_struct_info;
  99. Grad_struct_info0 Grad_struct_info;
  100. sp_mat I_Z_struct0;
  101. temp.reset();
  102. int length_Z0, length_F0;
  103. while (IsStop == 0) {
  104. // 迭代初值
  105. if (iteration == 1) { // 第0次,猜测值作为初始值
  106. T_old1 = T_guess1;
  107. Y_old1 = state_guess1;
  108. U_old1 = U_guess1;
  109. }
  110. else { // 第i次,上一步的新值作为初值
  111. T_old1 = time_ans1;
  112. Y_old1 = Y_ans1;
  113. U_old1 = U_ans1;
  114. }
  115. //Y_old1.print("Y_old1");
  116. //U_old1.print("U_old1");
  117. printf("当前为第 %ld 代;\n", iteration);
  118. // 2 计算各量微分近似及相关矩阵
  119. interval_num = (size(MeshGrid))(0);
  120. uvec N = ones<uvec>(interval_num);
  121. N_initial(MeshGrid.col(0), &N, interval_num); // 每个间隔内的配点阶数
  122. Method2Nk(method, N, &N_Col); // 配置点数目
  123. N_Col2interp(method, N_Col, &N_interp); // 配置点数目到插值点数目的转换
  124. D_pro(&MeshGrid, interval_num, &N_interp, &N_Col, &D_phase); // 微分矩阵
  125. field<mat> D_phasei(interval_num, 1);
  126. mat U_phase1(sum(N_interp), length_control);
  127. mat Y_phase1(sum(N_interp), length_state);
  128. D_M2Cell(&D_phase, interval_num, &N_interp, &D_phasei);
  129. UY_pro(MeshGrid, U_old1, Y_old1, T_old1, Ts1_Te1, N_interp, interval_num, interp_method, &U_phase1, &Y_phase1);
  130. deta_t_interval = Ts1_Te1.col(1) - Ts1_Te1.col(0);
  131. deta_t_in_col.reset();
  132. for (int i = 0; i < interval_num; i++) {
  133. temp = repelem(deta_t_interval.row(i), N_Col(i), 1);
  134. deta_t_in_col = join_cols(deta_t_in_col, temp);
  135. }
  136. // 计算每个间隔最后一个插值点的序号, 并在积分矩阵上剔除
  137. uvec last_interp = ones<uvec>(interval_num);
  138. uvec last_col = ones<uvec>(interval_num);
  139. int temp1;
  140. for (int i = 1; i <= interval_num; i++) {
  141. temp1 = sum(N_interp.rows(0, i - 1));
  142. last_interp(i - 1, 0) = temp1;
  143. last_col(i - 1, 0) = temp1 - i;
  144. }
  145. //计算n >= 2个间隔的第1个点的序号
  146. uvec first_col = ones<uvec>((interval_num - 1));
  147. for (int i = 1; i <= (interval_num - 1); i++) {
  148. first_col(i - 1) = sum(N_Col.rows(0, i - 1)) + 1;
  149. }
  150. // 积分权重矩阵
  151. mat W_phase;
  152. W_pro(method, &N, &N_Col, interval_num, &W_phase);
  153. // 3、生成NLP变量、约束和目标
  154. // NLP变量
  155. int Col_total = sum(N_Col);
  156. vec Z0;
  157. Z_pro(Y_phase1, U_phase1, parameter, last_interp, Col_total, length_state, length_control, tf, t0, &Z0);
  158. length_Z0 = Z0.n_rows;
  159. // NLP约束
  160. length_F0 = Col_total*length_state + Col_total*length_path + length_integral + length_event; // NLP约束数目
  161. // NLP梯度结构计算
  162. if (iteration == 1) {
  163. Grad_struct_solve(Z0, deta_t_in_col, Col_total, auxdata, W_phase, length_state, length_control,
  164. length_integral, &Grad_struct_info, length_parameter, Dynamics_temp1, Objective_temp);
  165. if (length_integral != 0) {
  166. IZstruct(Z0, Col_total, length_state, length_control, length_integral, W_phase, auxdata, &I_Z_struct0, Dynamics_temp1);
  167. }
  168. else {
  169. I_Z_struct0.reset();
  170. }
  171. }
  172. // 生成变量的范围边界
  173. vec Fmin, Fmax, Zmin, Zmax;
  174. Fmin_pro(*input, Col_total, length_state, length_path, length_integral, length_event, &Fmin);
  175. Fmax_pro(*input, Col_total, length_state, length_path, length_integral, length_event, &Fmax);
  176. Zmin_pro(*input, Col_total, &Zmin);
  177. Zmax_pro(*input, Col_total, &Zmax);
  178. // 4 计算NLP的雅可比矩阵
  179. // 雅克比结构(稀疏形式表达)
  180. if (iteration == 1) {
  181. Jacb_struct_pro0(Z0, D_phase, first_col, deta_t_in_col, length_event, length_path, length_parameter,Col_total, auxdata, W_phase,
  182. length_state, length_control, length_integral, length_F0,interval_num, last_interp, Dynamics_temp1, Objective_temp, &Jacb_struct0);
  183. Jacb_solve(Jacb_struct0, Col_total, length_event, length_path, length_state, length_control, length_integral, length_parameter, &Jacb_struct_info);
  184. }
  185. // 5 利用IPOPT求解NLP问题
  186. int var_num = length_Z0; // 变量数目
  187. int constraint_num = length_F0; // 约束数目
  188. int nnz_jac = Jacb_struct0.n_nonzero; // 雅可比矩阵非零数目
  189. int nnz_h = 2; // 海森矩阵非零数目
  190. vec z_ans, zl_temp, zu_temp, lambda_temp;
  191. int iter_num;
  192. double cpu_time;
  193. ipopt_apply(var_num, constraint_num, nnz_jac, nnz_h, Z0, Fmin, Fmax, Zmin, Zmax, auxdata, W_phase, deta_t_in_col, Col_total,
  194. length_state, length_control, Grad_struct_info, length_integral, eps0, D_phase, first_col, length_path, length_event,
  195. Jacb_struct0, D_phasei, N_Col, I_Z_struct0, interval_num, length_Z0, length_parameter, Jacb_struct_info, deri_supplier, length_F0, NLP,
  196. Dynamics_temp1, Objective_temp,
  197. &z_ans, &zl_temp, &zu_temp, &lambda_temp, &iter_num, &cpu_time);
  198. cout << "" << endl;
  199. cout << "第" << iteration << "次求解过程,求解器迭代次数为:" << iter_num << "。" << endl;
  200. cout << "同时所需CPU时间为:" << cpu_time << "s。" << endl;
  201. cout << "" << endl;
  202. // cout << parameter << endl;
  203. // 优化结果的性能指标
  204. double Objective_ans;
  205. Objective_ipopt(z_ans, deta_t_in_col, Col_total, auxdata, W_phase, length_state, length_control, length_parameter, Dynamics_temp1, Objective_temp, &Objective_ans);
  206. // 当前结果约束评估??
  207. // 结果输出到output
  208. mat Y_phase_ans1, U_phase_ans1;
  209. int Col_total_state = length_state*(Col_total + 1);
  210. int Col_total_control = length_control*Col_total;
  211. if (length_parameter != 0) {
  212. parameter = z_ans.rows(Col_total_state + Col_total_control + 3 - 1, Col_total_state + Col_total_control + 2 + length_parameter - 1);
  213. }
  214. else {
  215. parameter.reset();
  216. }
  217. double tf_ans = z_ans(Col_total_state + Col_total_control + 2 - 1);
  218. double t0_ans = z_ans(Col_total_state + Col_total_control + 1 - 1);
  219. auxdata.parameter = parameter;
  220. (*input).setup.auxdata = auxdata;
  221. Z2YU_interval(z_ans, Col_total, length_state, length_control, &Y_phase_ans1, &U_phase_ans1); // 将NLP变量分间隔重组为元胞
  222. // 6 结果处理
  223. // 时间域上的收缩、扩张
  224. vec Time_interval_ans;
  225. Time2Newtime(Ts1_Te1, MeshGrid, tf, t0, t0_ans, tf_ans, interval_num, Col_total, last_col, &Time_interval_ans); // 对应新时间下的间隔信息(未归一化)
  226. // 生成输出到output的实际时间、状态、控制
  227. mat Y_ans = Y_phase_ans1;
  228. vec time_ans = zeros(Col_total + 1, 1);
  229. mat U_ans = zeros(Col_total + 1, length_control);
  230. time_ans.rows(0, Col_total - 1) = Time_interval_ans;
  231. U_ans.rows(0, Col_total - 1) = U_phase_ans1;
  232. // 对边界点进行处理(LGR需要)
  233. U_ans.row(Col_total) = U_phase_ans1.row(Col_total - 1);
  234. time_ans.row(Col_total) = tf_ans;
  235. uvec first_col1 = join_cols(unit0, first_col) - 1;
  236. vec tf_ans0; tf_ans0 << tf_ans << endr;
  237. mat Ts_Te_ans = join_rows(Time_interval_ans.rows(first_col1), join_cols(Time_interval_ans.rows(first_col1.rows(1, interval_num - 1)), tf_ans0));
  238. mat Ts1_Te1_ans = Normal(Ts_Te_ans, tf_ans, t0_ans); // 起终点时间矩阵归一化
  239. time_ans1 = Normal(time_ans, tf_ans, t0_ans); // 时间信息归一化
  240. // 终端误差状态估计
  241. mat FSE;
  242. FSE.reset();
  243. if (is_FSE) { // 会报错,tf_ans的值有问题
  244. FinalStateEstimate(U_ans, Y_ans, MeshGrid, t0_ans, tf_ans, N, method, time_ans,
  245. interval_num, Ts1_Te1_ans, auxdata, length_state, length_control, interp_method, Dynamics_temp1, &FSE);
  246. }
  247. // 结果评价与网格细化策略
  248. mat Ts1_Te1_nextstep, MeshGrid_nextstep, inum_interval_increase;
  249. struct error0 error;
  250. result_assess(&MeshGrid_nextstep, &Ts1_Te1_nextstep, &error, &inum_interval_increase,
  251. U_ans, Y_ans, MeshGrid, time_ans1, t0_ans, tf_ans,
  252. N, mesh, Col_Points, method,
  253. interval_num, Ts1_Te1_ans, auxdata,
  254. length_state, length_control, niu, print_level, testmode, CC, Dynamics_temp1);
  255. double max_re_error = error.max_re_error_max;
  256. vec re_error_max = error.re_error_max;
  257. // 雅克比矩阵结构重构
  258. Jacb_struct_Re(Jacb_struct_info, MeshGrid_nextstep, length_state, length_control, length_path, length_event, length_integral, length_parameter, &Jacb_struct0);
  259. // 乘子更新(暂时不做)
  260. // output输出赋值
  261. output[iteration].result.time = time_ans;
  262. output[iteration].result.state = Y_ans;
  263. output[iteration].result.control = U_ans;
  264. output[iteration].result.objective = Objective_ans;
  265. output[iteration].result.mesh_N = MeshGrid.col(0).t();
  266. output[iteration].result.mesh_time = Ts_Te_ans;
  267. output[iteration].result.auxdata = auxdata;
  268. output[iteration].re_error_max = re_error_max;
  269. output[iteration].Final_State_Estimation = FSE;
  270. (*iteration_final) = iteration;
  271. // 信息输出
  272. output[iteration].result.max_re_error = max_re_error;
  273. if (print_level != 0) {
  274. cout << " 当前最大相对误差为" << max_re_error << endl;
  275. if (is_FSE) {
  276. cout << " 终端偏差预估值为 " << FSE.row(0) - Y_ans.row(Y_ans.n_rows - 1) << " " << endl;
  277. }
  278. }
  279. iteration = iteration + 1;
  280. // 7 是否满足终止条件
  281. if (max_re_error <= mesh.tolerance || iteration > mesh.maxiterration) {
  282. if (max_re_error <= mesh.tolerance) {
  283. cout << "相对误差满足要求,迭代终止;" << endl;
  284. }
  285. else if (iteration >= mesh.maxiterration) {
  286. cout << "迭代次数超过用户设定值,迭代终止;" << endl;
  287. }
  288. IsStop = 1;
  289. }
  290. cout << " " << endl;
  291. // 8 参数更新
  292. MeshGrid = MeshGrid_nextstep;
  293. Ts1_Te1 = Ts1_Te1_nextstep;
  294. tf = tf_ans;
  295. t0 = t0_ans;
  296. Y_ans1 = Y_ans;
  297. U_ans1 = U_ans;
  298. }
  299. return output;
  300. }