MATRIX.CPP
上传用户:zengbais
上传日期:2022-08-08
资源大小:49k
文件大小:28k
开发平台:

C++ Builder

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <string.h>
  4. #include <fstream.h>
  5. // 本程序实现matrix类
  6. // 对matrix类的定义
  7. #include "matrix.h"
  8. matrix::matrix(buffer * b): // 缺省构造函数,产生0行0列空矩阵
  9. rownum(0),colnum(0),istrans(0),isneg(0),issym(0)
  10. {
  11. if(b){ // 如用户给出b,则使用b作为数据缓存
  12. buf=b;
  13. buf->alloc(0);
  14. }
  15. else // 否则,产生一个新的缓存,类别是当前缺省的缓存类
  16. buf = getnewbuffer(0);
  17. }
  18. matrix::matrix(size_t n, buffer * b): // 产生n阶单位方阵
  19. rownum(n),colnum(1),istrans(0),isneg(0),issym(0)
  20. {
  21. if(b){ // 如用户给出b,则使用b作为数据缓存
  22. buf=b;
  23. buf->alloc(n);
  24. }
  25. else // 否则,产生一个新的缓存,类别是当前缺省的缓存类
  26. buf = getnewbuffer(n);
  27. }
  28. matrix unit(size_t n) // 产生n阶单位矩阵
  29. {
  30. if(n==0) throw TMESSAGE("n must larger than 0n");
  31. matrix m(n,n);
  32. for(size_t i=0; i<n; i++)
  33. for(size_t j=0; j<n; j++)
  34. if(i==j) m.set(i,j,1.0);
  35. else m.set(i,j,0.0);
  36. m.issym = 1;
  37. return m;
  38. }
  39. matrix::matrix(size_t r, size_t c, buffer * b):
  40. rownum(r),colnum(c),istrans(0),isneg(0),issym(0)
  41. {
  42. if(b){ // 如用户给出b,则使用b作为数据缓存
  43. buf=b;
  44. buf->alloc(r*c);
  45. }
  46. else // 否则,产生一个新的缓存,类别是当前缺省的缓存类
  47. buf = getnewbuffer(r*c);
  48. }
  49. matrix::matrix(matrix& m) // 拷贝构造函数
  50. {
  51. rownum = m.rownum; // 拷贝行数与列数
  52. colnum = m.colnum;
  53. istrans = m.istrans; // 拷贝转置标记
  54. isneg = m.isneg; // 拷贝负值标记
  55. issym = m.issym; // 拷贝对称标记
  56. buf = m.buf; // 设置指向相同缓存的指针
  57. buf->refnum++; // 缓存的引用数增1
  58. }
  59. matrix::matrix(const char * filename, buffer * b): // 从数据文件构造矩阵
  60. istrans(0), isneg(0), issym(0)
  61. {
  62. char label[10];
  63. ifstream in(filename); // 打开文件流
  64. in >> label; // 文件开始必须有matrix关键词
  65. if(strcmp(label, "matrix")!=0) throw TMESSAGE("format error!");
  66. in >> rownum >> colnum; // 读取行数和列数
  67. if(!in.good()) throw TMESSAGE("read file error!");
  68. // 申请或产生缓存
  69. if(b) { buf=b;
  70. buf->alloc(rownum*colnum);
  71. }
  72. else buf = getnewbuffer(rownum*colnum);
  73. size_t line;
  74. for(size_t i=0; i<rownum; i++) { // 依次按行读取
  75. in >> line; // 读行号
  76. if(line != i+1) throw TMESSAGE("format error!");
  77. in.width(sizeof(label));
  78. in >> label; // 行号后跟冒号
  79. if(label[0] != ':') throw TMESSAGE("format error!");
  80. DOUBLE a;
  81. for(size_t j=0; j<colnum; j++) { // 读取一行数据
  82. in >> a;
  83. set(i,j,a);
  84. }
  85. if(!in.good()) throw TMESSAGE("read file error!");
  86. }
  87. checksym(); // 检查是否为对称阵
  88. }
  89. matrix::matrix(void * data, size_t r, size_t c, buffer * b):
  90. rownum(r),colnum(c),istrans(0),isneg(0),issym(0) // 数据构造函数
  91. {
  92. if(b){
  93. buf=b;
  94. buf->alloc(r*c);
  95. }
  96. else
  97. buf = getnewbuffer(r*c);
  98. DOUBLE * d = (DOUBLE *)data;
  99. for(size_t i=0; i<r*c; i++)  // 这里进行数据拷贝,因此原数据的内存是可以释放的
  100. buf->set(i,d[i]);
  101. checksym(); // 检查是否为对称阵
  102. }
  103. DOUBLE matrix::operator()(size_t r, size_t c)
  104. {
  105. if(r>= rownum || c>= colnum)
  106. throw TMESSAGE("Out range!");
  107. return value(r,c);
  108. }
  109. matrix& matrix::operator=(matrix& m)  // 赋值重载
  110. {
  111. rownum = m.rownum; //  行数和列数的拷贝
  112. colnum = m.colnum;
  113. istrans = m.istrans; // 转置标志的拷贝
  114. isneg = m.isneg; // 取负标志的拷贝
  115. issym = m.issym; // 对称标志的拷贝
  116. if(buf == m.buf)  // 如果原缓存与m的缓存一样,则返回
  117. return (*this);
  118. buf->refnum--; // 原缓存不同,则原缓存的引用数减1
  119. if(!buf->refnum)delete buf; // 减1后的原缓存如果引用数为0,则删除原缓存
  120. buf = m.buf; // 将原缓存指针指向m的缓存
  121. buf->refnum++; // 新缓存的引用数增1
  122. checksym(); // 检查是否为对称阵
  123. return (*this); // 返回自己的引用
  124. }
  125. matrix& matrix::operator=(DOUBLE a) // 通过赋值运算符将矩阵所有元素设为a
  126. {
  127. if(rownum == 0 || colnum == 0) return (*this);
  128. for(size_t i=0; i<rownum; i++)
  129. for(size_t j=0; j<colnum; j++)
  130. set(i,j,a);
  131. if(rownum == colnum)issym = 1;
  132. return (*this);
  133. }
  134. matrix matrix::operator-() // 矩阵求负,产生负矩阵
  135. {
  136. matrix mm(*this);
  137. mm.neg();
  138. return mm;
  139. }
  140. ostream& operator<<(ostream& o, matrix& m) // 流输出运算符
  141. {
  142. // 先输出关键字matrix,然后是行号,制表符,列号,换行
  143. o << "matrix " << m.rownum << 't' << m.colnum << endl;
  144. for(size_t i=0; i<m.rownum; i++) { // 依次输出各行
  145. o<< (i+1) <<':'; // 行号后跟冒号。注意输出的行号是从1开始
  146. // 是内部编程的行号加1
  147. size_t k=8; // 后面输入一行的内容,每次一行数字超过八个时
  148. // 就换一行
  149. for(size_t j=0; j<m.colnum; j++) {
  150. o<<'t'<<m.value(i,j);
  151. if(--k==0) {
  152. k=8;
  153. o<<endl;
  154. }
  155. }
  156. o<<endl; // 每行结束时也换行
  157. }
  158. return o;
  159. }
  160. istream& operator>>(istream& in, matrix& m) // 流输入运算符
  161. {
  162. char label[10];
  163. in.width(sizeof(label));
  164. in >> label; // 输入matrix关键字
  165. if(strcmp(label, "matrix")!=0)
  166. throw TMESSAGE("format error!n");
  167. in >> m.rownum >> m.colnum; // 输入行号和列号
  168. if(!in.good()) throw TMESSAGE("read file error!");
  169. m.buf->refnum--; // 原缓存引用数减1
  170. if(!m.buf->refnum) delete m.buf; // 如原缓存引用数为0,则删去原缓存
  171. m.isneg = m.istrans = 0; // 转置和取负标志清零
  172. m.buf = getnewbuffer(m.rownum*m.colnum); // 按缺省子类产生新缓存
  173. size_t line; // 按矩阵行输入
  174. for(size_t i=0; i<m.rownum; i++) {
  175. in >> line; // 先输入行号
  176. if(line != i+1) throw TMESSAGE("format error!n");
  177. in.width(sizeof(label)); // 行号后应跟冒号
  178. in >> label;
  179. if(label[0] != ':') throw TMESSAGE("format error!n");
  180. DOUBLE a; // 随后是本行的各个数值
  181. for(size_t j=0; j<m.colnum; j++) {
  182. in >> a;
  183. m.set(i,j,a);
  184. }
  185. if(!in.good()) throw TMESSAGE("read file error!");
  186. }
  187. m.checksym(); // 检查是否为对称阵
  188. return in;
  189. }
  190. matrix& matrix::operator*=(DOUBLE a) // 矩阵数乘常数a,结果放在原矩阵
  191. {
  192. for(size_t i=0; i<rownum; i++)
  193. for(size_t j=0; j<colnum; j++)
  194. set(i,j,a*value(i,j));
  195. return (*this);
  196. }
  197. matrix matrix::operator*(DOUBLE a) // 矩阵数乘常数a,原矩阵内容不变,返回一新矩阵
  198. {
  199. matrix m(rownum, colnum);
  200. for(size_t i=0; i<rownum; i++)
  201. for(size_t j=0; j<colnum; j++)
  202. m.set(i,j,a*value(i,j));
  203. return m;
  204. }
  205. matrix matrix::operator+(matrix& m) // 矩阵相加,产生一新的矩阵并返回它
  206. {
  207. if(rownum != m.rownum || colnum != m.colnum) // 对应行列必须相同
  208. throw TMESSAGE("can not do add of matrixn");
  209. matrix mm(rownum, colnum); // 产生一同自己同形的矩阵
  210. DOUBLE a;
  211. for(size_t i=0; i<rownum; i++) // 求和
  212. for(size_t j=0; j<colnum; j++)
  213. {
  214. a = value(i,j)+m.value(i,j);
  215. mm.set(i,j,a);
  216. }
  217. mm.checksym(); // 检查是否为对称阵
  218. return mm;
  219. }
  220. matrix& matrix::operator+=(matrix &m) // 矩阵求和,自己内容改变为和
  221. {
  222. DOUBLE a;
  223. for(size_t i=0; i<rownum; i++)
  224. for(size_t j=0; j<colnum; j++)
  225. {
  226. a = value(i,j)+m.value(i,j);
  227. set(i,j,a);
  228. }
  229. checksym(); // 检查是否为对称阵
  230. return (*this);
  231. }
  232. matrix matrix::operator+(DOUBLE a) // 矩阵加常数,指每一元素加一固定的常数,产生
  233. // 新矩阵,原矩阵不变
  234. {
  235. matrix m(rownum, colnum);
  236. for(size_t i=0; i<rownum; i++)
  237. for(size_t j=0; j<colnum; j++)
  238. m.set(i,j,a+value(i,j));
  239. return m;
  240. }
  241. matrix& matrix::operator+=(DOUBLE a) // 矩阵自身加常数,自身内容改变
  242. {
  243. for(size_t i=0; i<rownum; i++)
  244. for(size_t j=0; j<colnum; j++)
  245. set(i,j,a+value(i,j));
  246. return (*this);
  247. }
  248. matrix operator-(DOUBLE a, matrix& m) { // 常数减矩阵,产生新的矩阵
  249. return (-m)+a;
  250. };
  251. matrix matrix::operator-(matrix& m) // 矩阵相减,产生新的矩阵
  252. {
  253. matrix mm(*this); // 产生一同自己同形的矩阵
  254. mm += (-m); // 加上相应的负矩阵
  255. return mm;
  256. }
  257. matrix& matrix::operator-=(matrix& m) // 矩阵相减,结果修改原矩阵
  258. {
  259. (*this) += (-m);
  260. return (*this);
  261. }
  262. matrix matrix::operator*(matrix& m) // 矩阵相乘,原矩阵内容不变,产生一新矩阵
  263. {
  264. if(colnum != m.rownum) // 必须满足相乘条件
  265. throw TMESSAGE("can not multiply!");
  266. matrix mm(rownum,m.colnum); // 计算并产生一合要求的矩阵放乘积
  267. DOUBLE a;
  268. for(size_t i=0; i<rownum; i++) // 计算乘积
  269. for(size_t j=0; j<m.colnum; j++){
  270. a = 0.0;
  271. for(size_t k=0; k<colnum; k++)
  272. a += value(i,k)*m.value(k,j);
  273. mm.set(i,j,a);
  274. }
  275. mm.checksym(); // 检查是否为对称阵
  276. return mm; // 返回乘积
  277. }
  278. matrix& matrix::operator*=(matrix& m) // 矩阵相乘,自己修改成积矩阵
  279. {
  280. (*this) = (*this)*m;
  281. return (*this);
  282. }
  283. matrix matrix::t()  // 矩阵转置,产生新的矩阵
  284. {
  285. matrix mm(*this);
  286. mm.trans();
  287. return mm;
  288. }
  289. int matrix::isnear(matrix& m, double e) // 检查二矩阵是否近似相等
  290. {
  291. if(rownum != m.rownum || colnum != m.colnum) return 0;
  292. for(size_t i=0; i< rownum; i++)
  293. for(size_t j=0; j< colnum; j++)
  294. if(fabs(value(i,j)-m.value(i,j)) > e) return 0;
  295. return 1;
  296. }
  297. int matrix::isnearunit(double e) // 检查矩阵是否近似为单位矩阵
  298. {
  299. if(rownum != colnum) return 0;
  300. return isnear(unit(rownum), e);
  301. }
  302. matrix matrix::row(size_t r) // 提取第r行行向量
  303. {
  304. matrix mm(1, colnum);
  305. for(int i=0; i< colnum; i++)
  306. mm.set(0, i, value(r,i));
  307. return mm;
  308. }
  309. matrix matrix::col(size_t c) // 提取第c列列向量
  310. {
  311. matrix mm(rownum, 1);
  312. for(int i=0; i< rownum; i++)
  313. mm.set(i, value(i, c));
  314. return mm;
  315. }
  316. void matrix::swapr(size_t r1, size_t r2, size_t k) // 交换矩阵r1和r2两行
  317. {
  318. DOUBLE a;
  319. for(size_t i=k; i<colnum; i++) {
  320. a = value(r1, i);
  321. set(r1, i, value(r2, i));
  322. set(r2, i, a);
  323. }
  324. }
  325. void matrix::swapc(size_t c1, size_t c2, size_t k) // 交换c1和c2两列
  326. {
  327. DOUBLE a;
  328. for(size_t i=k; i<colnum; i++) {
  329. a = value(i, c1);
  330. set(i, c1, value(i, c2));
  331. set(i, c2, a);
  332. }
  333. }
  334. DOUBLE matrix::maxabs(size_t &r, size_t &c, size_t k) // 求第k行和第k列后的主元及位置
  335. {
  336. DOUBLE a=0.0;
  337. for(size_t i=k;i<rownum;i++)
  338. for(size_t j=k;j<colnum;j++)
  339. if(a < fabs(value(i,j))) {
  340. r=i;c=j;a=fabs(value(i,j));
  341. }
  342. return a;
  343. }
  344. size_t matrix::zgsxy(matrix & m, int fn) // 进行主高斯消元运算,fn为参数,缺省为0
  345.  /* 本矩阵其实是常数阵,而矩阵m必须是方阵
  346. 运算过程其实是对本矩阵和m同时作行初等变换,
  347. 运算结果m的对角线相乘将是行列式,而本矩阵则变换成
  348. 自己的原矩阵被m的逆阵左乘,m的秩被返回,如果秩等于阶数
  349. 则本矩阵中的内容已经是唯一解
  350.  */
  351. {
  352. if(rownum != m.rownum || m.rownum != m.colnum) // 本矩阵行数必须与m相等
  353. // 且m必须是方阵
  354. throw TMESSAGE("can not divide!");
  355. lbuffer * bb = getnewlbuffer(rownum); // 产生一维数为行数的长整数缓存区
  356. lbuffer & b = (*bb); // 用引用的办法使下面的程序容易懂
  357. size_t is;
  358. DOUBLE a;
  359. size_t i,j,rank=0;
  360. for(size_t k=0; k<rownum; k++) { // 从第0行到第k行进行主高斯消元
  361. if(m.maxabs(is, i, k)==0) // 求m中第k级主元,主元所在的行,列存在is,i中
  362. break; // 如果主元为零,则m不可逆,运算失败
  363. rank = k+1; // rank存放当前的阶数
  364. b.retrieve(k) = i;  // 将长整数缓存区的第k个值设为i
  365. if(i != k)
  366. m.swapc(k, i); // 交换m中i,k两列
  367. if(is != k) {
  368. m.swapr(k, is, k); // 交换m中i,k两行,从k列以后交换
  369. swapr(k, is); // 交换本矩阵中i,k两行
  370. }
  371. a = m.value(k,k);  // 取出主元元素
  372. for (j=k+1;j<rownum;j++) // 本意是将m的第k行除以主元
  373. // 但只需把第k行的第k+1列以上除以主元即可
  374. // 这样还保留了主元作行列式运算用
  375. m.set(k,j,m.value(k,j)/a);
  376. for (j=0;j<colnum;j++) // 将本矩阵的第k行除以主元
  377. set(k,j,value(k,j)/a);
  378. // 上面两步相当于将m和本矩阵构成的增广矩阵第k行除以主元
  379. // 下面对增广矩阵作行基本初等变换使第k行的其余列均为零
  380. // 但0值无必要计算,因此从第k+1列开始计算
  381. for(j=k+1;j<rownum;j++) // j代表列,本矩阵的行数就是m的列数
  382. for(i=0;i<rownum;i++) //i代表行,依次对各行计算,k行除外
  383. if(i!=k)
  384. m.set(i,j,m.value(i,j)-m.value(i,k)*m.value(k,j));
  385. // 对本矩阵亦作同样的计算
  386. for(j=0;j<colnum;j++)
  387. for(i=0;i<rownum;i++)
  388. if(i!=k)
  389. set(i,j,value(i,j)-m.value(i,k)*value(k,j));
  390. } // 主高斯消元循环k结束
  391. if(fn == 1) {
  392. for(j=0; j<rank; j++)
  393. for(i=0; i<rownum; i++)
  394. if(i==j) m.set(i,i,1.0);
  395. else
  396. m.set(i,j,0.0);
  397. for(k = rank; k>0; k--)
  398. m.swapc(k-1,(size_t)b[k-1]);
  399. }
  400. for(k = rank; k>0; k--) // 将本矩阵中的各行按b中内容进行调节
  401. if(b[k-1] != k-1)
  402. swapr(k-1,(size_t)b[k-1]); // 行交换
  403. delete bb; // 释放长整数缓存
  404. return rank; // 返回mm的秩
  405. }
  406. matrix& matrix::operator/=(matrix m) // 利用重载的除法符号/=来解方程
  407. // 本矩阵设为d,则方程为mx=d,考虑解写成x=d/m的形式,
  408. // 而方程的解也存放在d中,则实际编程时写d/=m
  409. {
  410. if(zgsxy(m)!=rownum) // 如秩不等于m的阶数,则方程无解
  411. throw TMESSAGE("can not divide!");
  412. return *this;
  413. }
  414. matrix matrix::operator/(matrix m) // 左乘m的逆矩阵产生新矩阵
  415. {
  416. m.inv(); // m的逆矩阵
  417. return (*this)*m;
  418. }
  419. matrix& matrix::inv() // 用全选主元高斯-约当法求逆矩阵
  420. {
  421. if(rownum != colnum || rownum == 0)
  422. throw TMESSAGE("Can not calculate inverse");
  423. size_t i,j,k;
  424.  DOUBLE d,p;
  425. lbuffer * isp = getnewlbuffer(rownum); // 产生一维数为行数的长整数缓存区
  426. lbuffer * jsp = getnewlbuffer(rownum); // 产生一维数为行数的长整数缓存区
  427. lbuffer& is = *isp; // 使用引用使程序看起来方便
  428. lbuffer& js = *jsp;
  429. for(k=0; k<rownum; k++)
  430. {
  431. d = maxabs(i, j, k); // 全主元的位置和值
  432. is[k] = i;
  433. js[k] = j;
  434. if(d==0.0) {
  435. delete isp;
  436. delete jsp;
  437. throw TMESSAGE("can not inverse");
  438. }
  439.   if (is[k] != k) swapr(k,(size_t)is[k]);
  440.   if (js[k] != k) swapc(k,(size_t)js[k]);
  441. p = 1.0/value(k,k);
  442. set(k,k,p);
  443.   for (j=0; j<rownum; j++)
  444.  if (j!=k) set(k,j,value(k,j)*p);
  445.   for (i=0; i<rownum; i++)
  446.  if (i!=k)
  447. for (j=0; j<rownum; j++)
  448.   if (j!=k) set(i,j,value(i,j)-value(i,k)*value(k,j));
  449.   for (i=0; i<rownum; i++)
  450.  if (i!=k) set(i,k,-value(i,k)*p);
  451. } // end for k
  452.  for (k=rownum; k>0; k--)
  453. { if (js[k-1]!=k-1) swapr((size_t)js[k-1], k-1);
  454.   if (is[k-1]!=k-1) swapc((size_t)is[k-1], k-1);
  455. }
  456.   delete isp;
  457.   delete jsp;
  458. checksym(); // 检查是否为对称阵
  459.   return (*this);
  460. }
  461. matrix matrix::operator~() // 求逆矩阵,但产生新矩阵
  462. {
  463. matrix m(*this);
  464. m.inv();
  465. return m;
  466. }
  467. matrix operator/(DOUBLE a, matrix& m) // 求逆矩阵再乘常数
  468. {
  469. matrix mm(m);
  470. mm.inv();
  471. if(a != 1.0) mm*=a;
  472. return mm;
  473. }
  474. matrix& matrix::operator/=(DOUBLE a) // 所有元素乘a的倒数,自身改变
  475. {
  476. return operator*=(1/a);
  477. }
  478. matrix matrix::operator/(DOUBLE a) // 所有元素乘a的倒数,产生新的矩阵
  479. {
  480. matrix m(*this);
  481. m/=a;
  482. return m;
  483. }
  484. DOUBLE matrix::det(DOUBLE err) // 求行列式的值
  485. {
  486. if(rownum != colnum || rownum == 0)
  487. throw TMESSAGE("Can not calculate det");
  488. matrix m(*this);
  489. size_t rank;
  490. return m.detandrank(rank, err);
  491. }
  492. size_t matrix::rank(DOUBLE err) // 求矩阵的秩
  493. {
  494. if(rownum==0 || colnum==0)return 0;
  495. size_t k;
  496. k = rownum > colnum ? colnum : rownum;
  497. matrix m(k,k); // 产生k阶方阵
  498. for(size_t i=0; i<k; i++)
  499. for(size_t j=0; j<k; j++)
  500. m.set(i,j,value(i,j));
  501. size_t r;
  502. m.detandrank(r, err);
  503. return r;
  504. }
  505. DOUBLE matrix::detandrank(size_t & rank, DOUBLE err) // 求方阵的行列式和秩
  506. {
  507. if(rownum != colnum || rownum == 0)
  508. throw TMESSAGE("calculate det and rank error!");
  509. size_t i,j,k,is,js;
  510. double f,detv,q,d;
  511. f=1.0; detv=1.0;
  512. rank = 0;
  513.  for (k=0; k<rownum-1; k++)
  514. {
  515. q = maxabs(is, js, k);
  516. if(q<err) return 0.0; // 如主元太小,则行列式的值被认为是0
  517. rank++; // 秩增1
  518. if(is!=k) { f=-f; swapr(k,is,k); }
  519. if(js!=k) { f=-f; swapc(k,js,k); }
  520. q = value(k,k);
  521. detv *= q;
  522.   for (i=k+1; i<rownum; i++)
  523.  {
  524. d=value(i,k)/q;
  525. for (j=k+1; j<rownum; j++)
  526. set(i,j,value(i,j)-d*value(k,j));
  527.  }
  528. } // end loop k
  529.  q = value(rownum-1,rownum-1);
  530.  if(q != 0.0 ) rank++;
  531. return f*detv*q;
  532. }
  533. void matrix::checksym() // 检查和尝试调整矩阵到对称矩阵
  534. {
  535. issym = 0; // 先假设矩阵非对称
  536. if(rownum != colnum) return; // 行列不等当然不是对称矩阵
  537. DOUBLE a,b;
  538. for(size_t i=1; i<rownum; i++) // 从第二行开始检查
  539. for(size_t j=0; j<i; j++) // 从第一列到第i-1列
  540. {
  541. a = value(i,j);
  542. b = value(j,i);
  543. if( fabs(a-b) >= defaulterr ) return; // 发现不对称,返回
  544. if(a!=b)set(i,j,b); // 差别很小就进行微调
  545. }
  546. issym = 1; // 符合对称阵标准
  547. }
  548. void matrix::house(buffer & b, buffer & c)// 用豪斯荷尔德变换将对称阵变为对称三对
  549. // 角阵,b返回主对角线元素,c返回次对角线元素
  550. {
  551. if(!issym) throw TMESSAGE("not symatry");
  552. size_t i,j,k;
  553. DOUBLE h,f,g,h2,a;
  554.  for (i=rownum-1; i>0; i--)
  555. { h=0.0;
  556.   if (i>1)
  557.  for (k=0; k<i; k++)
  558. { a = value(i,k); h += a*a;}
  559.   if (h == 0.0)
  560.  { c[i] = 0.0;
  561. if (i==1) c[i] = value(i,i-1);
  562. b[i] = 0.0;
  563.  }
  564.   else
  565.  { c[i] = sqrt(h);
  566. a = value(i,i-1);
  567. if (a > 0.0) c[i] = -c[i];
  568. h -= a*c[i];
  569. set(i,i-1,a-c[i]);
  570. f=0.0;
  571. for (j=0; j<i; j++)
  572.   { set(j,i,value(i,j)/h);
  573.  g=0.0;
  574.  for (k=0; k<=j; k++)
  575. g += value(j,k)*value(i,k);
  576.  if(j<=i-2)
  577. for (k=j+1; k<i; k++)
  578. g += value(k,j)*value(i,k);
  579.  c[j] = g/h;
  580.  f += g*value(j,i);
  581.   }
  582. h2=f/(2*h);
  583. for (j=0; j<i; j++)
  584.   { f=value(i,j);
  585.  g=c[j] - h2*f;
  586.  c[j] = g;
  587.  for (k=0; k<=j; k++)
  588. set(j,k, value(j,k)-f*c[k]-g*value(i,k) );
  589.   }
  590. b[i] = h;
  591.  }
  592. }
  593.  for (i=0; i<=rownum-2; i++) c[i] = c[i+1];
  594.  c[rownum-1] = 0.0;
  595.  b[0] = 0.0;
  596.  for (i=0; i<rownum; i++)
  597. { if ((b[i]!=0.0)&&(i>=1))
  598.  for (j=0; j<i; j++)
  599. { g=0.0;
  600.   for (k=0; k<i; k++)
  601.  g=g+value(i,k)*value(k,j);
  602.   for (k=0; k<i; k++)
  603.  set(k,j,value(k,j)-g*value(k,i));
  604. }
  605.   b[i] = value(i,i);
  606.   set(i,i,1.0);
  607.   if (i>=1)
  608.  for (j=0; j<=i-1; j++)
  609. { set(i,j,0.0);
  610.   set(j,i,0.0); }
  611. }
  612.  return;
  613. }
  614. void matrix::trieigen(buffer& b, buffer& c, size_t l, DOUBLE eps)
  615. // 计算三对角阵的全部特征值与特征向量
  616. { size_t i,j,k,m,it;
  617. double d,f,h,g,p,r,e,s;
  618. c[rownum-1]=0.0; d=0.0; f=0.0;
  619. for (j=0; j<rownum; j++)
  620. { it=0;
  621.   h=eps*(fabs(b[j])+fabs(c[j]));
  622.   if (h>d) d=h;
  623.   m=j;
  624.   while ((m<rownum)&&(fabs(c[m])>d)) m+=1;
  625.   if (m!=j)
  626.  { do
  627.   { if (it==l) throw TMESSAGE("fial to calculate eigen value");
  628.  it += 1;
  629.  g=b[j];
  630.  p=(b[j+1]-g)/(2.0*c[j]);
  631.  r=sqrt(p*p+1.0);
  632.  if (p>=0.0) b[j]=c[j]/(p+r);
  633.  else b[j]=c[j]/(p-r);
  634.  h=g-b[j];
  635.  for (i=j+1; i<rownum; i++)
  636. b[i]-=h;
  637.  f=f+h; p=b[m]; e=1.0; s=0.0;
  638.  for (i=m-1; i>=j; i--)
  639. { g=e*c[i]; h=e*p;
  640.   if (fabs(p)>=fabs(c[i]))
  641.  { e=c[i]/p; r=sqrt(e*e+1.0);
  642. c[i+1]=s*p*r; s=e/r; e=1.0/r;
  643.  }
  644.   else
  645. { e=p/c[i]; r=sqrt(e*e+1.0);
  646. c[i+1]=s*c[i]*r;
  647. s=1.0/r; e=e/r;
  648.  }
  649.   p=e*b[i]-s*g;
  650.   b[i+1]=h+s*(e*g+s*b[i]);
  651.   for (k=0; k<rownum; k++)
  652.  {
  653. h=value(k,i+1);
  654. set(k,i+1, s*value(k,i)+e*h);;
  655. set(k,i,e*value(k,i)-s*h);
  656.  }
  657.   if(i==0) break;
  658. }
  659.  c[j]=s*p; b[j]=e*p;
  660.   }
  661. while (fabs(c[j])>d);
  662.  }
  663.   b[j]+=f;
  664. }
  665.  for (i=0; i<=rownum; i++)
  666. { k=i; p=b[i];
  667.   if (i+1<rownum)
  668.  { j=i+1;
  669. while ((j<rownum)&&(b[j]<=p))
  670.   { k=j; p=b[j]; j++;}
  671.  }
  672.   if (k!=i)
  673.  { b[k]=b[i]; b[i]=p;
  674. for (j=0; j<rownum; j++)
  675.   { p=value(j,i);
  676.  set(j,i,value(j,k));
  677.  set(j,k,p);
  678.   }
  679.  }
  680. }
  681. }
  682. matrix matrix::eigen(matrix & eigenvalue, DOUBLE eps, size_t l)
  683.  // 计算对称阵的全部特征向量和特征值
  684. // 返回按列排放的特征向量,而eigenvalue将返回一维矩阵,为所有特征值
  685. // 组成的列向量
  686. {
  687. if(!issym) throw TMESSAGE("it is not symetic matrix");
  688. eigenvalue = matrix(rownum); // 产生n行1列向量准备放置特征值
  689. matrix m(*this); // 复制自己产生一新矩阵
  690. if(rownum == 1) { // 如果只有1X1矩阵,则特征向量为1,特征值为value(0,0)
  691. m.set(0,0,1.0);
  692. eigenvalue.set(0,value(0,0));
  693. return m;
  694. }
  695. buffer * b, *c;
  696. b = getnewbuffer(rownum);
  697. c = getnewbuffer(rownum);
  698. m.house(*b,*c); // 转换成三对角阵
  699. m.trieigen(*b,*c,l,eps); // 算出特征向量和特征值
  700. for(size_t i=0; i<rownum; i++) // 复制b的内容到eigenvalue中
  701. eigenvalue.set(i,(*b)[i]);
  702. return m;
  703. }
  704. void matrix::hessenberg() // 将一般实矩阵约化为赫申伯格矩阵
  705. {
  706.  size_t i,j,k;
  707.  double d,t;
  708.  for (k=1; k<rownum-1; k++)
  709. { d=0.0;
  710.   for (j=k; j<rownum; j++)
  711.  { t=value(j,k-1);
  712. if (fabs(t)>fabs(d))
  713.   { d=t; i=j;}
  714.  }
  715.   if (fabs(d)!=0.0)
  716.  { if (i!=k)
  717.   { for (j=k-1; j<rownum; j++)
  718. {
  719.   t = value(i,j);
  720.   set(i,j,value(k,j));
  721.   set(k,j,t);
  722. }
  723.  for (j=0; j<rownum; j++)
  724. {
  725.   t = value(j,i);
  726.   set(j,i,value(j,k));
  727.   set(j,k,t);
  728. }
  729.   }
  730. for (i=k+1; i<rownum; i++)
  731.   {
  732.  t = value(i,k-1)/d;
  733.  set(i,k-1,0.0);
  734.  for (j=k; j<rownum; j++)
  735.   set(i,j,value(i,j)-t*value(k,j));
  736.  for (j=0; j<rownum; j++)
  737.   set(j,k,value(j,k)+t*value(j,i));
  738.   }
  739.  }
  740. }
  741. }
  742. void matrix::qreigen(matrix & u1, matrix & v1, size_t jt, DOUBLE eps)
  743.  // 求一般实矩阵的所有特征根
  744. // a和b均返回rownum行一列的列向量矩阵,返回所有特征根的实部和虚部
  745. {
  746. matrix a(*this);
  747. a.hessenberg(); // 先算出赫申伯格矩阵
  748. u1 = matrix(rownum);
  749. v1 = matrix(rownum);
  750. buffer * uu = getnewbuffer(rownum);
  751. buffer * vv = getnewbuffer(rownum);
  752. buffer &u = *uu;
  753. buffer &v = *vv;
  754.  size_t m,it,i,j,k,l;
  755.  size_t iir,iic,jjr,jjc,kkr,kkc,llr,llc;
  756.  DOUBLE b,c,w,g,xy,p,q,r,x,s,e,f,z,y;
  757.  it=0; m=rownum;
  758.  while (m!=0)
  759. { l=m-1;
  760.   while ( l>0 && (fabs(a.value(l,l-1))>eps*
  761. (fabs(a.value(l-1,l-1))+fabs(a.value(l,l))))) l--;
  762.   iir = m-1; iic = m-1;
  763.   jjr = m-1; jjc = m-2;
  764.   kkr = m-2; kkc = m-1;
  765.   llr = m-2; llc = m-2;
  766.   if (l==m-1)
  767.  { u[m-1]=a.value(m-1,m-1); v[m-1]=0.0;
  768. m--; it=0;
  769.  }
  770.   else if (l==m-2)
  771.  { b=-(a.value(iir,iic)+a.value(llr,llc));
  772. c=a.value(iir,iic)*a.value(llr,llc)-
  773. a.value(jjr,jjc)*a.value(kkr,kkc);
  774. w=b*b-4.0*c;
  775. y=sqrt(fabs(w));
  776. if (w>0.0)
  777.   { xy=1.0;
  778.  if (b<0.0) xy=-1.0;
  779.  u[m-1]=(-b-xy*y)/2.0;
  780.  u[m-2]=c/u[m-1];
  781.  v[m-1]=0.0; v[m-2]=0.0;
  782.   }
  783. else
  784.   { u[m-1]=-b/2.0; u[m-2]=u[m-1];
  785.  v[m-1]=y/2.0; v[m-2]=-v[m-1];
  786.   }
  787. m=m-2; it=0;
  788.  }
  789.   else
  790.  {
  791.  if (it>=jt) {
  792. delete uu;
  793. delete vv;
  794. throw TMESSAGE("fail to calculate eigenvalue");
  795.  }
  796. it++;
  797. for (j=l+2; j<m; j++)
  798. a.set(j,j-2,0.0);
  799. for (j=l+3; j<m; j++)
  800. a.set(j,j-3,0.0);
  801. for (k=l; k+1<m; k++)
  802.   { if (k!=l)
  803. { p=a.value(k,k-1); q=a.value(k+1,k-1);
  804.   r=0.0;
  805.   if (k!=m-2) r=a.value(k+2,k-1);
  806. }
  807.  else
  808. {
  809.   x=a.value(iir,iic)+a.value(llr,llc);
  810.   y=a.value(llr,llc)*a.value(iir,iic)-
  811. a.value(kkr,kkc)*a.value(jjr,jjc);
  812.   iir = l; iic = l;
  813.   jjr = l; jjc = l+1;
  814.   kkr = l+1; kkc = l;
  815.   llr = l+1; llc = l+1;
  816.   p=a.value(iir,iic)*(a.value(iir,iic)-x)
  817. +a.value(jjr,jjc)*a.value(kkr,kkc)+y;
  818.   q=a.value(kkr,kkc)*(a.value(iir,iic)+a.value(llr,llc)-x);
  819.   r=a.value(kkr,kkc)*a.value(l+2,l+1);
  820. }
  821.  if ((fabs(p)+fabs(q)+fabs(r))!=0.0)
  822. { xy=1.0;
  823.   if (p<0.0) xy=-1.0;
  824.   s=xy*sqrt(p*p+q*q+r*r);
  825.   if (k!=l) a.set(k,k-1,-s);
  826.   e=-q/s; f=-r/s; x=-p/s;
  827.   y=-x-f*r/(p+s);
  828.   g=e*r/(p+s);
  829.   z=-x-e*q/(p+s);
  830.   for (j=k; j<m; j++)
  831.  {
  832. iir = k; iic = j;
  833. jjr = k+1; jjc = j;
  834. p=x*a.value(iir,iic)+e*a.value(jjr,jjc);
  835. q=e*a.value(iir,iic)+y*a.value(jjr,jjc);
  836. r=f*a.value(iir,iic)+g*a.value(jjr,jjc);
  837. if (k!=m-2)
  838.   { kkr = k+2; kkc = j;
  839.  p=p+f*a.value(kkr,kkc);
  840.  q=q+g*a.value(kkr,kkc);
  841.  r=r+z*a.value(kkr,kkc);
  842.  a.set(kkr,kkc,r);
  843.   }
  844. a.set(jjr,jjc,q);
  845. a.set(iir,iic,p);
  846.  }
  847.   j=k+3;
  848.   if (j>=m-1) j=m-1;
  849.   for (i=l; i<=j; i++)
  850.  { iir = i; iic = k;
  851. jjr = i; jjc = k+1;
  852. p=x*a.value(iir,iic)+e*a.value(jjr,jjc);
  853. q=e*a.value(iir,iic)+y*a.value(jjr,jjc);
  854. r=f*a.value(iir,iic)+g*a.value(jjr,jjc);
  855. if (k!=m-2)
  856.   { kkr = i; kkc = k+2;
  857.  p=p+f*a.value(kkr,kkc);
  858.  q=q+g*a.value(kkr,kkc);
  859.  r=r+z*a.value(kkr,kkc);
  860.  a.set(kkr,kkc,r);
  861.   }
  862. a.set(jjr,jjc,q);
  863. a.set(iir,iic,p);
  864.  }
  865. }
  866.   }
  867.  }
  868. }
  869. for(i=0;i<rownum;i++) {
  870. u1.set(i,u[i]);
  871. v1.set(i,v[i]);
  872. }
  873. delete uu;
  874. delete vv;
  875. }
  876. DOUBLE gassrand(int rr) // 返回一零均值单位方差的正态分布随机数
  877. {
  878. static DOUBLE r=3.0; // 种子
  879. if(rr) r = rr;
  880. int i,m;
  881. DOUBLE s,w,v,t;
  882. s=65536.0; w=2053.0; v=13849.0;
  883. t=0.0;
  884. for (i=1; i<=12; i++)
  885. { r=r*w+v; m=(int)(r/s);
  886.   r-=m*s; t+=r/s;
  887. }
  888. t-=6.0;
  889. return(t);
  890. }
  891. gassvector::gassvector(matrix & r): //r必须是正定对称阵,为正态随机向量的协方差
  892. a(r)
  893. {
  894. if(r.rownum != r.colnum) throw TMESSAGE("must be a sqare matrix");
  895. if(!r.issym) throw TMESSAGE("must be a symetic matrix");
  896. matrix evalue;
  897. a = a.eigen(evalue);
  898. for(size_t i=0; i<a.colnum; i++) {
  899. DOUBLE e = sqrt(evalue(i));
  900. for(size_t j=0; j<a.rownum; j++)
  901. a.set(j,i,a.value(j,i)*e);
  902. }
  903. }
  904. matrix gassvector::operator()(matrix & r) // 返回给定协方差矩阵的正态随机向量
  905. {
  906. a = r;
  907. matrix evalue;
  908. a = a.eigen(evalue);
  909. size_t i;
  910. for(i=0; i<a.colnum; i++) {
  911. DOUBLE e = sqrt(evalue(i));
  912. for(size_t j=0; j<a.rownum; j++)
  913. a.set(j,i,a.value(j,i)*e);
  914. }
  915. matrix rr(a.rownum); // 产生列向量
  916. for(i=0; i<a.rownum; i++)
  917. rr.set(i,gassrand());
  918. return a*rr;
  919. }
  920. matrix gassvector::operator()() // 返回已设定的协方差矩阵的正态随机向量
  921. {
  922. matrix rr(a.rownum);
  923. for(size_t i=0; i<a.rownum; i++)
  924. rr.set(i,gassrand());
  925. return a*rr;
  926. }
  927. void gassvector::setdata(matrix & r) // 根据协方差矩阵设置增益矩阵
  928. {
  929. if(!r.issym) throw TMESSAGE("r must be symetic!");
  930. a = r;
  931. matrix evalue;
  932. a = a.eigen(evalue);
  933. for(size_t i=0; i<a.colnum; i++) {
  934.     if(evalue(i)<0.0) throw TMESSAGE("var matrix not positive!");
  935. DOUBLE e = sqrt(evalue(i));
  936. for(size_t j=0; j<a.rownum; j++)
  937. a.set(j,i,a.value(j,i)*e);
  938. }
  939. }
  940. int matrix::ispositive() // 判定矩阵是否对称非负定阵,如是返回1,否则返回0
  941. {
  942. if(!issym) return 0;
  943. matrix ev;
  944. eigen(ev);
  945. for(size_t i=0; i<rownum; i++)
  946. if(ev(i)<0) return 0;
  947. return 1;
  948. }
  949. matrix matrix::cholesky(matrix& dd) // 用乔里斯基分解法求对称正定阵的线性
  950. // 方程组ax=d返回方程组的解,本身为a,改变为分解阵u,d不变
  951. {
  952. if(!issym) throw TMESSAGE("not symetic!");
  953. if(dd.rownum != colnum) throw TMESSAGE("dd's rownum not right!");
  954. matrix md(dd);
  955. size_t i,j,k,u,v;
  956. if(value(0,0)<=0.0) throw TMESSAGE("not positive");
  957. set(0,0,sqrt(value(0,0))); //  a[0]=sqrt(a[0]);
  958. buffer& a = (*buf);
  959. buffer& d = (*(md.buf));
  960. size_t n = rownum;
  961. size_t m = dd.colnum;
  962. for (j=1; j<n; j++) a[j]=a[j]/a[0];
  963. for (i=1; i<n; i++)
  964. { u=i*n+i;
  965.   for (j=1; j<=i; j++)
  966.  { v=(j-1)*n+i;
  967. a[u]=a[u]-a[v]*a[v];
  968.  }
  969.   if (a[u]<=0.0) throw TMESSAGE("not positive");
  970.   a[u]=sqrt(a[u]);
  971.   if (i!=(n-1))
  972.  { for (j=i+1; j<n; j++)
  973.   { v=i*n+j;
  974.  for (k=1; k<=i; k++)
  975. a[v]=a[v]-a[(k-1)*n+i]*a[(k-1)*n+j];
  976.  a[v]=a[v]/a[u];
  977.   }
  978.  }
  979. }
  980. for (j=0; j<m; j++)
  981. { d[j]=d[j]/a[0];
  982.   for (i=1; i<=n-1; i++)
  983.  { u=i*n+i; v=i*m+j;
  984. for (k=1; k<=i; k++)
  985.   d[v]=d[v]-a[(k-1)*n+i]*d[(k-1)*m+j];
  986. d[v]=d[v]/a[u];
  987.  }
  988. }
  989. for (j=0; j<=m-1; j++)
  990. { u=(n-1)*m+j;
  991.   d[u]=d[u]/a[n*n-1];
  992.   for (k=n-1; k>=1; k--)
  993.  { u=(k-1)*m+j;
  994. for (i=k; i<=n-1; i++)
  995.   { v=(k-1)*n+i;
  996.  d[u]=d[u]-a[v]*d[i*m+j];
  997.   }
  998. v=(k-1)*n+k-1;
  999. d[u]=d[u]/a[v];
  1000.  }
  1001. }
  1002. if(n>1)
  1003. for(j=1; j<n; j++)
  1004. for(i=0; i<j; i++)
  1005. a[i+j*n]=0.0;
  1006. return md;
  1007. }
  1008. DOUBLE lineopt(matrix& aa,matrix& bb, matrix& cc, matrix & xx)
  1009.  // 线性规划最优点寻找程序,aa为mXn不等式约束条件左端系数矩阵,bb为不等式约束
  1010.  // 条件的右端项,为m维向量,cc为目标函数系数,n维向量,xx返回极小点,为n维向量
  1011. {
  1012. if(aa.rownum != bb.rownum || aa.colnum != cc.rownum ||
  1013. aa.colnum != xx.rownum) throw TMESSAGE("dimenstion not right!");
  1014. size_t n=aa.colnum, m=aa.rownum;
  1015. size_t i,mn,k,j;
  1016. matrix a(m,n+m);
  1017. for(i=0;i<m;i++) {
  1018. for(j=0;j<n;j++)
  1019. a.set(i,j,aa(i,j));
  1020. for(j=n;j<n+m;j++)
  1021. if(j-n == i) a.set(i,j,1.0);
  1022. else a.set(i,j,0.0);
  1023. }
  1024. matrix c(m+n);
  1025. c = 0.0;
  1026. for(i=0;i<m;i++)
  1027. c.set(i,cc(i));
  1028. lbuffer* jjs = getnewlbuffer(m);
  1029. lbuffer& js = (*jjs);
  1030. DOUBLE s,z,dd,y; //,*p,*d;
  1031. for (i=0; i<m; i++) js[i]=n+i;
  1032. matrix p(m,m);
  1033. matrix d;
  1034. mn=m+n; s=0.0;
  1035. matrix x(mn);
  1036. while (1)
  1037. { for (i=0; i<m; i++)
  1038.  for (j=0; j<m; j++)
  1039. p.set(i,j,a(i,(size_t)js[j]));
  1040.   p.inv();
  1041. d = p*a;
  1042. x = 0.0;
  1043.   for (i=0; i<m; i++)
  1044.  { s=0.0;
  1045. for (j=0; j<=m-1; j++)
  1046. s+=p(i,j)*bb(j);
  1047. x.set((size_t)js[i],s);
  1048.  }
  1049.   k=mn; dd=1.0e-35;
  1050.   for (j=0; j<mn; j++)
  1051.  { z=0.0;
  1052. for (i=0; i<m; i++)
  1053. z+=c((size_t)js[i])*d(i,j);
  1054. z-=c(j);
  1055. if (z>dd) { dd=z; k=j;}
  1056.  }
  1057.   if (k==mn)
  1058.  { s=0.0;
  1059. for (j=0; j<n; j++) {
  1060. xx.set(j,x(j));
  1061. s+=c(j)*x(j);
  1062. }
  1063. delete jjs;
  1064. return s;
  1065.  }
  1066.   j=m;
  1067.   dd=1.0e+20;
  1068.   for (i=0; i<=m-1; i++)
  1069.  if (d(i,k)>=1.0e-20)   // [i*mn+k]>=1.0e-20)
  1070. { y=x(size_t(js[i]))/d(i,k);
  1071.   if (y<dd) { dd=y; j=i;}
  1072. }
  1073.   if (j==m) { delete jjs;
  1074. throw TMESSAGE("lineopt failed!");
  1075. }
  1076.   js[j]=k;
  1077. }
  1078. }