PageRenderTime 65ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/encog-core-silverlight/encog-core-silverlight/Neural/Networks/Training/SVD/SVD.cs

http://encog-cs.googlecode.com/
C# | 375 lines | 302 code | 24 blank | 49 comment | 83 complexity | 79587c9386a64ed2c6d200cc65e92d8c MD5 | raw file
  1. // Encog(tm) Artificial Intelligence Framework v2.5
  2. // .Net Version
  3. // http://www.heatonresearch.com/encog/
  4. // http://code.google.com/p/encog-java/
  5. //
  6. // Copyright 2008-2010 by Heaton Research Inc.
  7. //
  8. // Released under the LGPL.
  9. //
  10. // This is free software; you can redistribute it and/or modify it
  11. // under the terms of the GNU Lesser General Public License as
  12. // published by the Free Software Foundation; either version 2.1 of
  13. // the License, or (at your option) any later version.
  14. //
  15. // This software is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. // Lesser General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU Lesser General Public
  21. // License along with this software; if not, write to the Free
  22. // Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  23. // 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  24. //
  25. // Encog and Heaton Research are Trademarks of Heaton Research, Inc.
  26. // For information on Heaton Research trademarks, visit:
  27. //
  28. // http://www.heatonresearch.com/copyright.html
  29. using System;
  30. using System.Collections.Generic;
  31. using System.Linq;
  32. using System.Text;
  33. using System.Diagnostics;
  34. namespace Encog.Neural.Networks.Training.SVD
  35. {
  36. /// <summary>
  37. /// Contains methods for computing singular value decompositions of matrices and solving them against multiple right hand sides
  38. ///
  39. // Contributed to Encog By M.Dean and M.Fletcher
  40. // University of Cambridge, Dept. of Physics, UK
  41. /// </summary>
  42. internal static class SVD
  43. {
  44. internal static void svdfit(double[][] x, double[][] y, double[][] a, out double chisq, Func<double[], double>[] funcs)
  45. {
  46. int i, j, k;
  47. double wmax, tmp, thresh, sum, TOL = 1e-13;
  48. //Allocated memory for svd matrices
  49. double[,] u = new double[x.Length, funcs.Length];
  50. double[,] v = new double[funcs.Length, funcs.Length];
  51. double[] w = new double[funcs.Length];
  52. //Fill input matrix with values based on fitting functions and input coordinates
  53. for (i = 0; i < x.Length; i++)
  54. {
  55. for (j = 0; j < funcs.Length; j++)
  56. u[i, j] = funcs[j](x[i]);
  57. }
  58. //Perform decomposition
  59. svdcmp(u, w, v);
  60. //Check for w values that are close to zero and replace them with zeros such that they are ignored in backsub
  61. wmax = 0;
  62. for (j = 0; j < funcs.Length; j++)
  63. if (w[j] > wmax) wmax = w[j];
  64. thresh = TOL * wmax;
  65. for (j = 0; j < funcs.Length; j++)
  66. if (w[j] < thresh) w[j] = 0;
  67. //Perform back substitution to get result
  68. svdbksb(u, w, v, y, a);
  69. //Calculate chi squared for the fit
  70. chisq = 0;
  71. for (k = 0; k < y[0].Length; k++)
  72. {
  73. for (i = 0; i < y.Length; i++)
  74. {
  75. sum = 0.0;
  76. for (j = 0; j < funcs.Length; j++) sum += a[j][k] * funcs[j](x[i]);
  77. tmp = (y[i][k] - sum);
  78. chisq += tmp * tmp;
  79. }
  80. }
  81. chisq = Math.Sqrt(chisq / (y.Length * y[0].Length));
  82. }
  83. internal static void svdbksb(double[,] u, double[] w, double[,] v, double[][] b, double[][] x)
  84. {
  85. int jj, j, i, m, n, k;
  86. double s;
  87. m = u.GetLength(0); n = u.GetLength(1);
  88. double[] temp = new double[n];
  89. for (k = 0; k < b[0].Length; k++)
  90. {
  91. for (j = 0; j < n; j++)
  92. {
  93. s = 0;
  94. if (w[j] != 0)
  95. {
  96. for (i = 0; i < m; i++)
  97. s += u[i, j] * b[i][k];
  98. s /= w[j];
  99. }
  100. temp[j] = s;
  101. }
  102. for (j = 0; j < n; j++)
  103. {
  104. s = 0;
  105. for (jj = 0; jj < n; jj++)
  106. s += v[j, jj] * temp[jj];
  107. x[j][k] = s;
  108. }
  109. }
  110. }
  111. /// <summary>
  112. /// Given a matrix a[1..m][1..n], this routine computes its singular value
  113. /// decomposition, A = U.W.VT. The matrix U replaces a on output. The diagonal
  114. /// matrix of singular values W is output as a vector w[1..n]. The matrix V (not
  115. /// the transpose VT) is output as v[1..n][1..n].
  116. /// </summary>
  117. /// <param name="a"></param>
  118. /// <param name="w"></param>
  119. /// <param name="v"></param>
  120. internal static void svdcmp(double[,] a, double[] w, double[,] v)
  121. {
  122. bool flag;
  123. int i, its, j, jj, k, l = 0, nm = 0;
  124. double anorm, c, f, g, h, s, scale, x, y, z;
  125. int m = a.GetLength(0);
  126. int n = a.GetLength(1);
  127. double[] rv1 = new double[n];
  128. g = scale = anorm = 0.0;
  129. for (i = 0; i < n; i++)
  130. {
  131. l = i + 2;
  132. rv1[i] = scale * g;
  133. g = s = scale = 0.0;
  134. if (i < m)
  135. {
  136. for (k = i; k < m; k++) scale += Math.Abs(a[k, i]);
  137. if (scale != 0.0)
  138. {
  139. for (k = i; k < m; k++)
  140. {
  141. a[k, i] /= scale;
  142. s += a[k, i] * a[k, i];
  143. }
  144. f = a[i, i];
  145. g = -SIGN(Math.Sqrt(s), f);
  146. h = f * g - s;
  147. a[i, i] = f - g;
  148. for (j = l - 1; j < n; j++)
  149. {
  150. for (s = 0.0, k = i; k < m; k++) s += a[k, i] * a[k, j];
  151. f = s / h;
  152. for (k = i; k < m; k++) a[k, j] += f * a[k, i];
  153. }
  154. for (k = i; k < m; k++) a[k, i] *= scale;
  155. }
  156. }
  157. w[i] = scale * g;
  158. g = s = scale = 0.0;
  159. if (i + 1 <= m && i + 1 != n)
  160. {
  161. for (k = l - 1; k < n; k++) scale += Math.Abs(a[i, k]);
  162. if (scale != 0.0)
  163. {
  164. for (k = l - 1; k < n; k++)
  165. {
  166. a[i, k] /= scale;
  167. s += a[i, k] * a[i, k];
  168. }
  169. f = a[i, l - 1];
  170. g = -SIGN(Math.Sqrt(s), f);
  171. h = f * g - s;
  172. a[i, l - 1] = f - g;
  173. for (k = l - 1; k < n; k++) rv1[k] = a[i, k] / h;
  174. for (j = l - 1; j < m; j++)
  175. {
  176. for (s = 0.0, k = l - 1; k < n; k++) s += a[j, k] * a[i, k];
  177. for (k = l - 1; k < n; k++) a[j, k] += s * rv1[k];
  178. }
  179. for (k = l - 1; k < n; k++) a[i, k] *= scale;
  180. }
  181. }
  182. anorm = MAX(anorm, (Math.Abs(w[i]) + Math.Abs(rv1[i])));
  183. }
  184. for (i = n - 1; i >= 0; i--)
  185. {
  186. if (i < n - 1)
  187. {
  188. if (g != 0.0)
  189. {
  190. for (j = l; j < n; j++)
  191. v[j, i] = (a[i, j] / a[i, l]) / g;
  192. for (j = l; j < n; j++)
  193. {
  194. for (s = 0.0, k = l; k < n; k++) s += a[i, k] * v[k, j];
  195. for (k = l; k < n; k++) v[k, j] += s * v[k, i];
  196. }
  197. }
  198. for (j = l; j < n; j++) v[i, j] = v[j, i] = 0.0;
  199. }
  200. v[i, i] = 1.0;
  201. g = rv1[i];
  202. l = i;
  203. }
  204. for (i = MIN(m, n) - 1; i >= 0; i--)
  205. {
  206. l = i + 1;
  207. g = w[i];
  208. for (j = l; j < n; j++) a[i, j] = 0.0;
  209. if (g != 0.0)
  210. {
  211. g = 1.0 / g;
  212. for (j = l; j < n; j++)
  213. {
  214. for (s = 0.0, k = l; k < m; k++) s += a[k, i] * a[k, j];
  215. f = (s / a[i, i]) * g;
  216. for (k = i; k < m; k++) a[k, j] += f * a[k, i];
  217. }
  218. for (j = i; j < m; j++) a[j, i] *= g;
  219. }
  220. else for (j = i; j < m; j++) a[j, i] = 0.0;
  221. ++a[i, i];
  222. }
  223. for (k = n - 1; k >= 0; k--)
  224. {
  225. for (its = 0; its < 30; its++)
  226. {
  227. flag = true;
  228. for (l = k; l >= 0; l--)
  229. {
  230. nm = l - 1;
  231. if (Math.Abs(rv1[l]) + anorm == anorm)
  232. {
  233. flag = false;
  234. break;
  235. }
  236. if (Math.Abs(w[nm]) + anorm == anorm) break;
  237. }
  238. if (flag)
  239. {
  240. c = 0.0;
  241. s = 1.0;
  242. for (i = l; i < k + 1; i++)
  243. {
  244. f = s * rv1[i];
  245. rv1[i] = c * rv1[i];
  246. if (Math.Abs(f) + anorm == anorm) break;
  247. g = w[i];
  248. h = pythag(f, g);
  249. w[i] = h;
  250. h = 1.0 / h;
  251. c = g * h;
  252. s = -f * h;
  253. for (j = 0; j < m; j++)
  254. {
  255. y = a[j, nm];
  256. z = a[j, i];
  257. a[j, nm] = y * c + z * s;
  258. a[j, i] = z * c - y * s;
  259. }
  260. }
  261. }
  262. z = w[k];
  263. if (l == k)
  264. {
  265. if (z < 0.0)
  266. {
  267. w[k] = -z;
  268. for (j = 0; j < n; j++) v[j, k] = -v[j, k];
  269. }
  270. break;
  271. }
  272. #if !SILVERLIGHT
  273. if (its == 29) Debug.Print("no convergence in 30 svdcmp iterations");
  274. #endif
  275. x = w[l];
  276. nm = k - 1;
  277. y = w[nm];
  278. g = rv1[nm];
  279. h = rv1[k];
  280. f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
  281. g = pythag(f, 1.0);
  282. f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
  283. c = s = 1.0;
  284. for (j = l; j <= nm; j++)
  285. {
  286. i = j + 1;
  287. g = rv1[i];
  288. y = w[i];
  289. h = s * g;
  290. g = c * g;
  291. z = pythag(f, h);
  292. rv1[j] = z;
  293. c = f / z;
  294. s = h / z;
  295. f = x * c + g * s;
  296. g = g * c - x * s;
  297. h = y * s;
  298. y *= c;
  299. for (jj = 0; jj < n; jj++)
  300. {
  301. x = v[jj, j];
  302. z = v[jj, i];
  303. v[jj, j] = x * c + z * s;
  304. v[jj, i] = z * c - x * s;
  305. }
  306. z = pythag(f, h);
  307. w[j] = z;
  308. if (z != 0)
  309. {
  310. z = 1.0 / z;
  311. c = f * z;
  312. s = h * z;
  313. }
  314. f = c * g + s * y;
  315. x = c * y - s * g;
  316. for (jj = 0; jj < m; jj++)
  317. {
  318. y = a[jj, j];
  319. z = a[jj, i];
  320. a[jj, j] = y * c + z * s;
  321. a[jj, i] = z * c - y * s;
  322. }
  323. }
  324. rv1[l] = 0.0;
  325. rv1[k] = f;
  326. w[k] = x;
  327. }
  328. }
  329. }
  330. private static int MIN(int m, int n)
  331. {
  332. return m < n ? m : n;
  333. }
  334. private static double MAX(double a, double b)
  335. {
  336. return (a > b) ? a : b;
  337. }
  338. private static double SIGN(double a, double b)
  339. {
  340. return ((b) >= 0.0 ? Math.Abs(a) : -Math.Abs(a));
  341. }
  342. private static double pythag(double a, double b)
  343. {
  344. double absa, absb;
  345. absa = Math.Abs(a);
  346. absb = Math.Abs(b);
  347. if (absa > absb) return absa * Math.Sqrt(1.0 + (absb / absa) * (absb / absa));
  348. else return (absb == 0.0 ? 0.0 : absb * Math.Sqrt(1.0 + (absa / absb) * (absa / absb)));
  349. }
  350. }
  351. }