You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mrq.cc 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: mrq.cc
  6. Purpose: mrqmin and mrqcof algorithms
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. namespace ABACUS {
  11. void mrqmin (Vect_DP& x, Vect_DP& y, Vect_DP& sig, Vect_DP& a,
  12. Vect<bool>& ia, SQMat_DP& covar, SQMat_DP& alpha, DP& chisq,
  13. void funcs(const DP, Vect_DP&, DP&, Vect_DP&), DP& alambda)
  14. {
  15. // Levenberg-Marquardt method. See NRC++ p.691.
  16. static int mfit;
  17. static DP ochisq;
  18. int j, k, l;
  19. int ma = a.size();
  20. static SQMat_DP oneda (ma);
  21. static Vect_DP atry(ma);
  22. static Vect_DP beta(ma);
  23. static Vect_DP da(ma);
  24. if (alambda < 0.0) {
  25. mfit = 0;
  26. for (j = 0; j < ma; j++)
  27. if (ia[j]) mfit++;
  28. alambda = 0.001;
  29. mrqcof (x, y, sig, a, ia, alpha, beta, chisq, funcs);
  30. ochisq = chisq;
  31. for (j = 0; j < ma; j++) atry[j] = a[j];
  32. }
  33. SQMat_DP temp (mfit);
  34. for (j = 0; j < mfit; j++) {
  35. for (k = 0; k < mfit; k++) covar[j][k] = alpha[j][k];
  36. covar[j][j] = alpha[j][j] * (1.0 + alambda);
  37. for (k = 0; k < mfit; k++) temp[j][k] = covar[j][k];
  38. oneda[j][0] = beta[j];
  39. }
  40. gaussj (temp, oneda);
  41. for (j = 0; j < mfit; j++) {
  42. for (k = 0; k < mfit; k++) covar[j][k] = temp[j][k];
  43. da[j] = oneda[j][0];
  44. }
  45. if (alambda == 0.0) {
  46. covsrt (covar, ia, mfit);
  47. covsrt (alpha, ia, mfit);
  48. return;
  49. }
  50. for (j = 0, l = 0; l < ma; l++)
  51. if (ia[l]) atry[l] = a[l] + da[j++];
  52. mrqcof (x, y, sig, atry, ia, covar, da, chisq, funcs);
  53. if (chisq < ochisq) {
  54. alambda *= 0.1;
  55. ochisq = chisq;
  56. for (j = 0; j < mfit; j++) {
  57. for (k = 0; k < mfit; k++) alpha[j][k] = covar[j][k];
  58. beta[j] = da[j];
  59. }
  60. for (l = 0; l < ma; l++) a[l] = atry[l];
  61. } else {
  62. alambda *= 10.0;
  63. chisq = ochisq;
  64. }
  65. }
  66. void mrqcof (Vect_DP& x, Vect_DP& y, Vect_DP& sig, Vect_DP& a,
  67. Vect<bool>& ia, SQMat_DP& alpha, Vect_DP& beta, DP& chisq,
  68. void funcs (const DP, Vect_DP&, DP&, Vect_DP&))
  69. {
  70. int i, j, k, l, m, mfit = 0;
  71. DP ymod, wt, sig2i, dy;
  72. int ndata = x.size();
  73. int ma = a.size();
  74. Vect_DP dyda (ma);
  75. for (j = 0; j < ma; j++)
  76. if (ia[j]) mfit++;
  77. for (j = 0; j < mfit; j++) {
  78. for (k = 0; k <= j; k++) alpha[j][k] = 0.0;
  79. beta[j] = 0.0;
  80. }
  81. chisq = 0.0;
  82. for (i = 0; i < ndata; i++) {
  83. funcs (x[i], a, ymod, dyda);
  84. sig2i = 1.0/(sig[i] * sig[i]);
  85. dy = y[i] - ymod;
  86. for (j = 0, l = 0; l < ma; l++) {
  87. if (ia[l]) {
  88. wt = dyda[l] * sig2i;
  89. for (k = 0, m = 0; m < l+1; m++)
  90. if (ia[m]) alpha[j][k++] += wt * dyda[m];
  91. beta[j++] += dy * wt;
  92. }
  93. }
  94. chisq += dy * dy * sig2i;
  95. }
  96. for (j = 1; j < mfit; j++)
  97. for (k = 0; k < j; k++) alpha[k][j] = alpha[j][k];
  98. }
  99. }