eigs.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createEigs = void 0;
  6. var _factory = require("../../utils/factory.js");
  7. var _string = require("../../utils/string.js");
  8. var _complexEigs = require("./eigs/complexEigs.js");
  9. var _realSymetric = require("./eigs/realSymetric.js");
  10. var _is = require("../../utils/is.js");
  11. var name = 'eigs';
  12. // The absolute state of math.js's dependency system:
  13. var dependencies = ['config', 'typed', 'matrix', 'addScalar', 'equal', 'subtract', 'abs', 'atan', 'cos', 'sin', 'multiplyScalar', 'divideScalar', 'inv', 'bignumber', 'multiply', 'add', 'larger', 'column', 'flatten', 'number', 'complex', 'sqrt', 'diag', 'qr', 'usolve', 'usolveAll', 'im', 're', 'smaller', 'matrixFromColumns', 'dot'];
  14. var createEigs = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  15. var config = _ref.config,
  16. typed = _ref.typed,
  17. matrix = _ref.matrix,
  18. addScalar = _ref.addScalar,
  19. subtract = _ref.subtract,
  20. equal = _ref.equal,
  21. abs = _ref.abs,
  22. atan = _ref.atan,
  23. cos = _ref.cos,
  24. sin = _ref.sin,
  25. multiplyScalar = _ref.multiplyScalar,
  26. divideScalar = _ref.divideScalar,
  27. inv = _ref.inv,
  28. bignumber = _ref.bignumber,
  29. multiply = _ref.multiply,
  30. add = _ref.add,
  31. larger = _ref.larger,
  32. column = _ref.column,
  33. flatten = _ref.flatten,
  34. number = _ref.number,
  35. complex = _ref.complex,
  36. sqrt = _ref.sqrt,
  37. diag = _ref.diag,
  38. qr = _ref.qr,
  39. usolve = _ref.usolve,
  40. usolveAll = _ref.usolveAll,
  41. im = _ref.im,
  42. re = _ref.re,
  43. smaller = _ref.smaller,
  44. matrixFromColumns = _ref.matrixFromColumns,
  45. dot = _ref.dot;
  46. var doRealSymetric = (0, _realSymetric.createRealSymmetric)({
  47. config: config,
  48. addScalar: addScalar,
  49. subtract: subtract,
  50. column: column,
  51. flatten: flatten,
  52. equal: equal,
  53. abs: abs,
  54. atan: atan,
  55. cos: cos,
  56. sin: sin,
  57. multiplyScalar: multiplyScalar,
  58. inv: inv,
  59. bignumber: bignumber,
  60. complex: complex,
  61. multiply: multiply,
  62. add: add
  63. });
  64. var doComplexEigs = (0, _complexEigs.createComplexEigs)({
  65. config: config,
  66. addScalar: addScalar,
  67. subtract: subtract,
  68. multiply: multiply,
  69. multiplyScalar: multiplyScalar,
  70. flatten: flatten,
  71. divideScalar: divideScalar,
  72. sqrt: sqrt,
  73. abs: abs,
  74. bignumber: bignumber,
  75. diag: diag,
  76. qr: qr,
  77. inv: inv,
  78. usolve: usolve,
  79. usolveAll: usolveAll,
  80. equal: equal,
  81. complex: complex,
  82. larger: larger,
  83. smaller: smaller,
  84. matrixFromColumns: matrixFromColumns,
  85. dot: dot
  86. });
  87. /**
  88. * Compute eigenvalues and eigenvectors of a matrix. The eigenvalues are sorted by their absolute value, ascending.
  89. * An eigenvalue with multiplicity k will be listed k times. The eigenvectors are returned as columns of a matrix –
  90. * the eigenvector that belongs to the j-th eigenvalue in the list (eg. `values[j]`) is the j-th column (eg. `column(vectors, j)`).
  91. * If the algorithm fails to converge, it will throw an error – in that case, however, you may still find useful information
  92. * in `err.values` and `err.vectors`.
  93. *
  94. * Syntax:
  95. *
  96. * math.eigs(x, [prec])
  97. *
  98. * Examples:
  99. *
  100. * const { eigs, multiply, column, transpose } = math
  101. * const H = [[5, 2.3], [2.3, 1]]
  102. * const ans = eigs(H) // returns {values: [E1,E2...sorted], vectors: [v1,v2.... corresponding vectors as columns]}
  103. * const E = ans.values
  104. * const U = ans.vectors
  105. * multiply(H, column(U, 0)) // returns multiply(E[0], column(U, 0))
  106. * const UTxHxU = multiply(transpose(U), H, U) // diagonalizes H
  107. * E[0] == UTxHxU[0][0] // returns true
  108. *
  109. * See also:
  110. *
  111. * inv
  112. *
  113. * @param {Array | Matrix} x Matrix to be diagonalized
  114. *
  115. * @param {number | BigNumber} [prec] Precision, default value: 1e-15
  116. * @return {{values: Array|Matrix, vectors: Array|Matrix}} Object containing an array of eigenvalues and a matrix with eigenvectors as columns.
  117. *
  118. */
  119. return typed('eigs', {
  120. Array: function Array(x) {
  121. var mat = matrix(x);
  122. return computeValuesAndVectors(mat);
  123. },
  124. 'Array, number|BigNumber': function ArrayNumberBigNumber(x, prec) {
  125. var mat = matrix(x);
  126. return computeValuesAndVectors(mat, prec);
  127. },
  128. Matrix: function Matrix(mat) {
  129. var _computeValuesAndVect = computeValuesAndVectors(mat),
  130. values = _computeValuesAndVect.values,
  131. vectors = _computeValuesAndVect.vectors;
  132. return {
  133. values: matrix(values),
  134. vectors: matrix(vectors)
  135. };
  136. },
  137. 'Matrix, number|BigNumber': function MatrixNumberBigNumber(mat, prec) {
  138. var _computeValuesAndVect2 = computeValuesAndVectors(mat, prec),
  139. values = _computeValuesAndVect2.values,
  140. vectors = _computeValuesAndVect2.vectors;
  141. return {
  142. values: matrix(values),
  143. vectors: matrix(vectors)
  144. };
  145. }
  146. });
  147. function computeValuesAndVectors(mat, prec) {
  148. if (prec === undefined) {
  149. prec = config.epsilon;
  150. }
  151. var size = mat.size();
  152. if (size.length !== 2 || size[0] !== size[1]) {
  153. throw new RangeError('Matrix must be square (size: ' + (0, _string.format)(size) + ')');
  154. }
  155. var arr = mat.toArray();
  156. var N = size[0];
  157. if (isReal(arr, N, prec)) {
  158. coerceReal(arr, N);
  159. if (isSymmetric(arr, N, prec)) {
  160. var _type = coerceTypes(mat, arr, N);
  161. return doRealSymetric(arr, N, prec, _type);
  162. }
  163. }
  164. var type = coerceTypes(mat, arr, N);
  165. return doComplexEigs(arr, N, prec, type);
  166. }
  167. /** @return {boolean} */
  168. function isSymmetric(arr, N, prec) {
  169. for (var i = 0; i < N; i++) {
  170. for (var j = i; j < N; j++) {
  171. // TODO proper comparison of bignum and frac
  172. if (larger(bignumber(abs(subtract(arr[i][j], arr[j][i]))), prec)) {
  173. return false;
  174. }
  175. }
  176. }
  177. return true;
  178. }
  179. /** @return {boolean} */
  180. function isReal(arr, N, prec) {
  181. for (var i = 0; i < N; i++) {
  182. for (var j = 0; j < N; j++) {
  183. // TODO proper comparison of bignum and frac
  184. if (larger(bignumber(abs(im(arr[i][j]))), prec)) {
  185. return false;
  186. }
  187. }
  188. }
  189. return true;
  190. }
  191. function coerceReal(arr, N) {
  192. for (var i = 0; i < N; i++) {
  193. for (var j = 0; j < N; j++) {
  194. arr[i][j] = re(arr[i][j]);
  195. }
  196. }
  197. }
  198. /** @return {'number' | 'BigNumber' | 'Complex'} */
  199. function coerceTypes(mat, arr, N) {
  200. /** @type {string} */
  201. var type = mat.datatype();
  202. if (type === 'number' || type === 'BigNumber' || type === 'Complex') {
  203. return type;
  204. }
  205. var hasNumber = false;
  206. var hasBig = false;
  207. var hasComplex = false;
  208. for (var i = 0; i < N; i++) {
  209. for (var j = 0; j < N; j++) {
  210. var el = arr[i][j];
  211. if ((0, _is.isNumber)(el) || (0, _is.isFraction)(el)) {
  212. hasNumber = true;
  213. } else if ((0, _is.isBigNumber)(el)) {
  214. hasBig = true;
  215. } else if ((0, _is.isComplex)(el)) {
  216. hasComplex = true;
  217. } else {
  218. throw TypeError('Unsupported type in Matrix: ' + (0, _is.typeOf)(el));
  219. }
  220. }
  221. }
  222. if (hasBig && hasComplex) {
  223. console.warn('Complex BigNumbers not supported, this operation will lose precission.');
  224. }
  225. if (hasComplex) {
  226. for (var _i = 0; _i < N; _i++) {
  227. for (var _j = 0; _j < N; _j++) {
  228. arr[_i][_j] = complex(arr[_i][_j]);
  229. }
  230. }
  231. return 'Complex';
  232. }
  233. if (hasBig) {
  234. for (var _i2 = 0; _i2 < N; _i2++) {
  235. for (var _j2 = 0; _j2 < N; _j2++) {
  236. arr[_i2][_j2] = bignumber(arr[_i2][_j2]);
  237. }
  238. }
  239. return 'BigNumber';
  240. }
  241. if (hasNumber) {
  242. for (var _i3 = 0; _i3 < N; _i3++) {
  243. for (var _j3 = 0; _j3 < N; _j3++) {
  244. arr[_i3][_j3] = number(arr[_i3][_j3]);
  245. }
  246. }
  247. return 'number';
  248. } else {
  249. throw TypeError('Matrix contains unsupported types only.');
  250. }
  251. }
  252. });
  253. exports.createEigs = createEigs;