public void SolveTest() { double[,] value = { { 2, -1, 0 }, { -1, 2, -1 }, { 0, -1, 2 } }; double[] b = { 1, 2, 3 }; double[] expected = { 2.5000, 4.0000, 3.5000 }; QrDecomposition target = new QrDecomposition(value); double[] actual = target.Solve(b); Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.0000000000001)); }
private double[,] SolveMatrix(Dictionary <Joint, Joint> matching) { double[,] matrix = new double[3 * matching.Count, 12]; double[] rightSide = new double[3 * matching.Count]; int i = 0; foreach (Joint key in matching.Keys) { for (int k = 0; k < 3; k++) { matrix[3 * i + k, 4 * k] = key.Position.X; matrix[3 * i + k, 4 * k + 1] = key.Position.Y; matrix[3 * i + k, 4 * k + 2] = key.Position.Z; matrix[3 * i + k, 4 * k + 3] = 1; } rightSide[3 * i] = matching[key].Position.X; rightSide[3 * i + 1] = matching[key].Position.Y; rightSide[3 * i + 2] = matching[key].Position.Z; i++; } QrDecomposition decomposition = new QrDecomposition(matrix); double[] coefficientsVector = decomposition.Solve(rightSide); double[,] coefficients = new double[4, 4]; for (int j = 0; j < coefficients.GetLength(0) - 1; j++) { for (int k = 0; k < coefficients.GetLength(1); k++) { coefficients[j, k] = coefficientsVector[j * coefficients.GetLength(1) + k]; } } for (int k = 0; k < coefficients.GetLength(1); k++) { coefficients[3, k] = (k == 3) ? 1 : 0; } return(coefficients); }
public void QrDecompositionCachingTest() { double[,] value = { { 2, -1, 0 }, { -1, 2, -1 }, { 0, -1, 2 } }; var target = new QrDecomposition(value); // Decomposition Identity var Q1 = target.OrthogonalFactor; var Q2 = target.OrthogonalFactor; var utf1 = target.UpperTriangularFactor; var utf2 = target.UpperTriangularFactor; Assert.AreSame(Q1, Q2); Assert.AreSame(utf1, utf2); }
public void InverseTestNaN() { int n = 5; var I = Matrix.Identity(n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { double[,] value = Matrix.Magic(n); value[i, j] = double.NaN; var target = new QrDecomposition(value); var solution = target.Solve(I); var inverse = target.Inverse(); Assert.IsTrue(Matrix.IsEqual(solution, inverse)); } } }
public void InverseTest1() { double[][] value = { new double[] { 41.9, 29.1, 1 }, new double[] { 43.4, 29.3, 1 }, new double[] { 43.9, 29.5, 0 }, new double[] { 44.5, 29.7, 0 }, new double[] { 47.3, 29.9, 0 }, new double[] { 47.5, 30.3, 0 }, new double[] { 47.9, 30.5, 0 }, new double[] { 50.2, 30.7, 0 }, new double[] { 52.8, 30.8, 0 }, new double[] { 53.2, 30.9, 0 }, new double[] { 56.7, 31.5, 0 }, new double[] { 57.0, 31.7, 0 }, new double[] { 63.5, 31.9, 0 }, new double[] { 65.3, 32.0, 0 }, new double[] { 71.1, 32.1, 0 }, new double[] { 77.0, 32.5, 0 }, new double[] { 77.8, 32.9, 0 } }; double[][] expected = new JaggedSingularValueDecomposition(value, computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: true).Inverse(); var target = new JaggedQrDecomposition(value); double[][] actual = target.Inverse(); Assert.IsTrue(Matrix.IsEqual(expected, actual, atol: 1e-4)); var targetMat = new QrDecomposition(value.ToMatrix()); double[][] actualMat = target.Inverse(); Assert.IsTrue(Matrix.IsEqual(expected, actualMat, atol: 1e-4)); }
public static void m1() { double[][] dataA = new double[][] { new double[] { 8.1, 2.3, -1.5 }, new double[] { 0.5, -6.23, 0.87 }, new double[] { 2.5, 1.5, 10.2 }, }; double[][] dataB = new double[][] { new double[] { 6.1 }, new double[] { 2.3 }, new double[] { 1.8 }, }; Matrix A = new Matrix(dataA); Matrix b = new Matrix(dataB); // 通过LU上下三角分解法 求解线性方程组 Ax = b QrDecomposition d = new QrDecomposition(A); Matrix x = d.Solve(b); }
static void Main(string[] args) { #region 1. Declaring matrices // 1.1 Using standard .NET declaration double[,] A = { { 1, 2, 3 }, { 6, 2, 0 }, { 0, 0, 1 } }; double[,] B = { { 2, 0, 0 }, { 0, 2, 0 }, { 0, 0, 2 } }; { // 1.2 Using Accord extension methods double[,] Bi = Matrix.Identity(3).Multiply(2); double[,] Bj = Matrix.Diagonal(3, 2.0); // both are equal to B // 1.2 Using Accord extension methods with implicit typing var I = Matrix.Identity(3); } #endregion #region 2. Matrix Operations { // 2.1 Addition var C = A.Add(B); // 2.2 Subtraction var D = A.Subtract(B); // 2.3 Multiplication { // 2.3.1 By a scalar var halfM = A.Multiply(0.5); // 2.3.2 By a vector double[] m = A.Multiply(new double[] { 1, 2, 3 }); // 2.3.3 By a matrix var M = A.Multiply(B); // 2.4 Transposing var At = A.Transpose(); } } // 2.5 Elementwise operations // 2.5.1 Elementwise multiplication A.ElementwiseMultiply(B); // A.*B // 2.5.1 Elementwise division A.ElementwiseDivide(B); // A./B #endregion #region 3. Matrix characteristics { // 3.1 Calculating the determinant double det = A.Determinant(); // 3.2 Calculating the trace double tr = A.Trace(); // 3.3 Computing the sum vector { double[] sumVector = A.Sum(); // 3.3.1 Computing the total sum of elements double sum = sumVector.Sum(); // 3.3.2 Computing the sum along the rows sumVector = A.Sum(0); // Equivalent to Octave's sum(A, 1) // 3.3.2 Computing the sum along the columns sumVector = A.Sum(1); // Equivalent to Octave's sum(A, 2) } } #endregion #region 4. Linear Algebra { // 4.1 Computing the inverse var invA = A.Inverse(); // 4.2 Computing the pseudo-inverse var pinvA = A.PseudoInverse(); // 4.3 Solving a linear system (Ax = B) var x = A.Solve(B); } #endregion #region 5. Special operators { // 5.1 Finding the indices of elements double[] v = { 5, 2, 2, 7, 1, 0 }; int[] idx = v.Find(e => e > 2); // finding the index of every element in v higher than 2. // 5.2 Selecting elements by index double[] u = v.Submatrix(idx); // u is { 5, 7 } // 5.3 Converting between different matrix representations double[][] jaggedA = A.ToArray(); // from multidimensional to jagged array // 5.4 Extracting a column or row from the matrix double[] a = A.GetColumn(0); // retrieves the first column double[] b = B.GetRow(1); // retrieves the second row // 5.5 Taking the absolute of a matrix var absA = A.Abs(); // 5.6 Applying some function to every element var newv = v.Apply(e => e + 1); } #endregion #region 7. Vector operations { double[] u = { 1, 2, 3 }; double[] v = { 4, 5, 6 }; var w1 = u.InnerProduct(v); var w2 = u.OuterProduct(v); var w3 = u.CartesianProduct(v); double[] m = { 1, 2, 3, 4 }; double[,] M = Matrix.Reshape(m, 2, 2); } #endregion #region Decompositions { // Singular value decomposition { SingularValueDecomposition svd = new SingularValueDecomposition(A); var U = svd.LeftSingularVectors; var S = svd.Diagonal; var V = svd.RightSingularVectors; } // or (please see documentation for details) { SingularValueDecomposition svd = new SingularValueDecomposition(A.Transpose()); var U = svd.RightSingularVectors; var S = svd.Diagonal; var V = svd.LeftSingularVectors; } // Eigenvalue decomposition { EigenvalueDecomposition eig = new EigenvalueDecomposition(A); var V = eig.Eigenvectors; var D = eig.DiagonalMatrix; } // QR decomposition { QrDecomposition qr = new QrDecomposition(A); var Q = qr.OrthogonalFactor; var R = qr.UpperTriangularFactor; } // Cholesky decomposition { CholeskyDecomposition chol = new CholeskyDecomposition(A); var R = chol.LeftTriangularFactor; } // LU decomposition { LuDecomposition lu = new LuDecomposition(A); var L = lu.LowerTriangularFactor; var U = lu.UpperTriangularFactor; } } #endregion }
private double regress(double[][] inputs, double[] outputs, out double[,] designMatrix, bool robust) { if (inputs.Length != outputs.Length) { throw new ArgumentException("Number of input and output samples does not match", "outputs"); } int parameters = Inputs; int rows = inputs.Length; // number of instance points int cols = Inputs; // dimension of each point for (int i = 0; i < inputs.Length; i++) { if (inputs[i].Length != parameters) { throw new DimensionMismatchException("inputs", String.Format( "Input vectors should have length {0}. The row at index {1} of the" + " inputs matrix has length {2}.", parameters, i, inputs[i].Length)); } } ISolverMatrixDecomposition <double> solver; // Create the problem's design matrix. If we // have to add an intercept term, add a new // extra column at the end and fill with 1s. if (!addIntercept) { // Just copy values over designMatrix = new double[rows, cols]; for (int i = 0; i < inputs.Length; i++) { for (int j = 0; j < inputs[i].Length; j++) { designMatrix[i, j] = inputs[i][j]; } } } else { // Add an intercept term designMatrix = new double[rows, cols + 1]; for (int i = 0; i < inputs.Length; i++) { for (int j = 0; j < inputs[i].Length; j++) { designMatrix[i, j] = inputs[i][j]; } designMatrix[i, cols] = 1; } } // Check if we have an overdetermined or underdetermined // system to select an appropriate matrix solver method. if (robust || cols >= rows) { // We have more variables than equations, an // underdetermined system. Solve using a SVD: solver = new SingularValueDecomposition(designMatrix, computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: true); } else { // We have more equations than variables, an // overdetermined system. Solve using the QR: solver = new QrDecomposition(designMatrix); } // Solve V*C = B to find C (the coefficients) coefficients = solver.Solve(outputs); // Calculate Sum-Of-Squares error double error = 0.0; double e; for (int i = 0; i < outputs.Length; i++) { e = outputs[i] - Compute(inputs[i]); error += e * e; } return(error); }
public void SolveTest3() { double[][] value = { new double[] { 41.9, 29.1, 1 }, new double[] { 43.4, 29.3, 1 }, new double[] { 43.9, 29.5, 0 }, new double[] { 44.5, 29.7, 0 }, new double[] { 47.3, 29.9, 0 }, new double[] { 47.5, 30.3, 0 }, new double[] { 47.9, 30.5, 0 }, new double[] { 50.2, 30.7, 0 }, new double[] { 52.8, 30.8, 0 }, new double[] { 53.2, 30.9, 0 }, new double[] { 56.7, 31.5, 0 }, new double[] { 57.0, 31.7, 0 }, new double[] { 63.5, 31.9, 0 }, new double[] { 65.3, 32.0, 0 }, new double[] { 71.1, 32.1, 0 }, new double[] { 77.0, 32.5, 0 }, new double[] { 77.8, 32.9, 0 } }; double[][] b = { new double[] { 251.3 }, new double[] { 251.3 }, new double[] { 248.3 }, new double[] { 267.5 }, new double[] { 273.0 }, new double[] { 276.5 }, new double[] { 270.3 }, new double[] { 274.9 }, new double[] { 285.0 }, new double[] { 290.0 }, new double[] { 297.0 }, new double[] { 302.5 }, new double[] { 304.5 }, new double[] { 309.3 }, new double[] { 321.7 }, new double[] { 330.7 }, new double[] { 349.0 } }; double[][] expected = { new double[] { 1.7315235669547167 }, new double[] { 6.25142110500275 }, new double[] { -5.0909763966987178 }, }; var target = new JaggedQrDecomposition(value); double[][] actual = target.Solve(b); Assert.IsTrue(Matrix.IsEqual(expected, actual, atol: 1e-4)); var reconstruct = value.Dot(expected); Assert.IsTrue(Matrix.IsEqual(reconstruct, b, rtol: 1e-1)); double[] b2 = b.GetColumn(0); double[] expected2 = expected.GetColumn(0); var target2 = new JaggedQrDecomposition(value); double[] actual2 = target2.Solve(b2); Assert.IsTrue(Matrix.IsEqual(expected2, actual2, atol: 1e-4)); var targetMat = new QrDecomposition(value.ToMatrix()); double[,] actualMat = targetMat.Solve(b.ToMatrix()); Assert.IsTrue(Matrix.IsEqual(expected, actualMat, atol: 1e-4)); var reconstructMat = value.ToMatrix().Dot(expected); Assert.IsTrue(Matrix.IsEqual(reconstruct, b, rtol: 1e-1)); var targetMat2 = new QrDecomposition(value.ToMatrix()); Assert.IsTrue(Matrix.IsEqual(target2.Diagonal, targetMat2.Diagonal, atol: 1e-4)); Assert.IsTrue(Matrix.IsEqual(target2.OrthogonalFactor, targetMat2.OrthogonalFactor, atol: 1e-4)); Assert.IsTrue(Matrix.IsEqual(target2.UpperTriangularFactor, targetMat2.UpperTriangularFactor, atol: 1e-4)); double[] actualMat2 = targetMat2.Solve(b2); Assert.IsTrue(Matrix.IsEqual(expected2, actualMat2, atol: 1e-4)); }
public List <Complex> GetAnswer() { var Ak = new matrix(matrix); var eigenvalues = new List <Complex>(); for (int i = 0; i < dim; i++) { eigenvalues.Add(Ak[i, i]); } var numberOfIterations = 0; while (true) { var qrDecomposition = new QrDecomposition(Ak); Ak = qrDecomposition.R * qrDecomposition.Q; var nextEigenvalues = new List <Complex>(); for (int i = 0; i < dim; i++) { if (Ak.GetColumn(i).Skip(i + 1).ToList().Rate2() < MatrixConstants.Lab5Eps) { nextEigenvalues.Add(new Complex(Ak[i, i], 0)); } else if (Ak.GetColumn(i).Skip(i + 2).ToList().Rate2() < MatrixConstants.Lab5Eps) { var roots = SolveQuadratic(Ak[i, i], Ak[i + 1, i + 1], Ak[i, i + 1], Ak[i + 1, i]); nextEigenvalues.AddRange(roots); i++; } else { nextEigenvalues.Clear(); break; } } numberOfIterations++; if (nextEigenvalues.Count == dim) { var isRootsFound = true; for (int i = 0; i < dim; i++) { if (Abs(eigenvalues[i].Real - nextEigenvalues[i].Real) > MatrixConstants.Lab5Eps) { isRootsFound = false; break; } } if (isRootsFound) { break; } eigenvalues = new List <Complex>(nextEigenvalues); } } Console.WriteLine("Number of iterations: {0}", numberOfIterations); return(eigenvalues); }
public static void Run(int pllproc) { double[] @params = new double[6]; double maxgrad = 0; double stpthrsh = 0; double maxeigen; double mineigen; double wr = 0; double[] alpha = { 0.50, 1.00 }; double rfMax = 2.75; int td = 0; int[] prtls = { -1, -1, -1, -1 }; int iterint = 1; long sn = (long)Math.Pow(10.0, 7); int prec = (int)Math.Pow(10.0, 4); string type = ""; string alg = ""; const string rootdir = Config.ConfigsRootDir; // Read setup details from control file. try { var getParams = File.ReadAllText(Path.Combine(rootdir, Config.ControlFile)); var s = getParams.Split(new[] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); @params = s.Take(6).Select(i => double.Parse(i, CultureInfo.InvariantCulture)).ToArray(); td = int.Parse(s[6]); wr = double.Parse(s[7]); stpthrsh = double.Parse(s[8]); alg = s[9]; type = s[10]; if (type.Equals("sim")) { sn = int.Parse(s[11]); alpha[0] = double.Parse(s[12]); alpha[1] = double.Parse(s[13]); } else if (type.Equals("dp")) { prec = int.Parse(s[11]); rfMax = double.Parse(s[12]); } } catch (Exception ex) { Trace.Write("ERROR: Could not read file: "); Trace.WriteLine(Path.Combine(rootdir, Config.ControlFile) + $". {ex.Message}"); Trace.WriteLine("EXITING...main()..."); Console.Read(); Environment.Exit(1); } // Read initial glide-path from file. var gp = new double[td]; var gpPath = Path.Combine(rootdir, Config.InitGladepathFile); try { gp = File.ReadAllLines(gpPath).Select(double.Parse) .Take(td).ToArray(); } catch (Exception ex) { Trace.Write("ERROR: Could not read file: "); Trace.WriteLine(gpPath + ". Error: " + ex.Message); Trace.WriteLine("EXITING...main()..."); Console.Read(); Environment.Exit(1); } if (gp.Length != td) { Trace.Write("ERROR: File: "); Trace.Write(gpPath); Trace.Write(" needs "); Trace.Write(td); Trace.WriteLine(" initial asset allocations, but has fewer."); Trace.WriteLine("EXITING...main()..."); Console.Read(); Environment.Exit(1); } // Display optimization algorithm. Trace.Write(@"===> Optimization algorithm: "); if (alg == "nr") { Trace.WriteLine(@"Newton's Method"); } else if (alg == "ga") { Trace.WriteLine(@"Gradient Ascent"); } // Display estimation method. Trace.WriteLine(""); Trace.Write(@"===> Estimation method: "); if (type == "sim") { Trace.WriteLine(@"Simulation"); } else if (type == "dp") { Trace.WriteLine(@"Dynamic Program"); pllproc = 4 * pllproc; } // Declare variables that depend on data read from the control file for sizing. double[,] hess; double[] ngrdnt = new double[td]; EigenvalueDecomposition hevals; var grad = new double[td]; // Take some steps (1 full iteration but no more than 50 steps) in the direction of steepest ascent. This can move us off // the boundary region where computations may be unstable (infinite), especially when constructing the Hessian for Newton's method. // Also, this initial stepping usually makes improvements very quickly before proceeding with the optimization routine. double probnr = GetPNR.Run(type, @params, gp, td, wr, 4 * sn, (int)(rfMax * prec), prec, prtls, pllproc); Trace.WriteLine(""); Trace.WriteLine("Initial Glide-Path (w/Success Probability):"); WrtAry.Run(probnr, gp, "GP", td); for (int s = 1; s <= 2; ++s) { maxgrad = BldGrad.Run(type, @params, gp, td, wr, sn, (int)(rfMax * prec), prec, probnr, 4 * sn, alpha[1], pllproc, grad); if (maxgrad <= stpthrsh) { Trace.Write("The glide-path supplied satisfies the EPSILON convergence criteria: "); Trace.WriteLine($"{maxgrad:F15} vs. {stpthrsh:F15}"); s = s + 1; } else if (s != 2) { probnr = Climb.Run(type, @params, gp, td, wr, 2 * sn, (int)(rfMax * prec), prec, pllproc, maxgrad, probnr, 4 * sn, grad, alpha[0], 50); Trace.WriteLine(""); Trace.WriteLine("New (Post Initial Climb) Glide-Path (w/Success Probability):"); WrtAry.Run(probnr, gp, "GP", td); } else if (maxgrad <= stpthrsh) { Trace.Write("The glide-path supplied satisfies the EPSILON convergence criteria after intial climb without iterating: "); Trace.WriteLine($"{maxgrad:F15} vs. {stpthrsh:F15}"); } } // Negate the gradient if using NR method. if (alg == "nr") { for (int y = 0; y < td; ++y) { ngrdnt[y] = -1.00 * grad[y]; } } // If convergence is not achieved after initial climb then launch into full iteration mode. while (maxgrad > stpthrsh) { Trace.WriteLine(""); Trace.WriteLine("========================="); Trace.WriteLine($"Start Iteration #{iterint}"); Trace.WriteLine("========================="); if (alg == "nr") { // Record the probability before iterating. double strtpnr = probnr; // Build the Hessian matrix for this glide-path and derive its eigenvalues. (Display the largest & smallest value.) // This is required when method=nr. When either procedure ends with convergence we recompute the Hessian matrix to // ensure we are at a local/global maximum (done below after convergence). hess = DrvHess.Run(type, @params, gp, td, wr, sn, (int)(rfMax * prec), prec, pllproc, grad, probnr); //hevals.compute(hess, false); hevals = new EigenvalueDecomposition(hess); var reals = hevals.RealEigenvalues; maxeigen = reals.Max(); mineigen = reals.Min(); // Display the smallest/largest eigenvalues. Trace.WriteLine(""); Trace.Write("Min Hessian eigenvalue for this iteration (>=0.00 --> convex region): "); Trace.WriteLine(mineigen); Trace.WriteLine(""); Trace.Write("Max Hessian eigenvalue for this iteration (<=0.00 --> concave region): "); Trace.WriteLine(maxeigen); // Update the glidepath and recompute the probability using the new glidepath. //sol = hess.colPivHouseholderQr().solve(ngrdnt); var qr = new QrDecomposition(hess); var sol = qr.Solve(ngrdnt); for (int y = 0; y < td; ++y) { gp[y] += sol[y]; } probnr = GetPNR.Run(type, @params, gp, td, wr, 4 * sn, (int)(rfMax * prec), prec, prtls, pllproc); // If success probability has worsened alert the user. if (probnr < strtpnr) { Trace.WriteLine(""); Trace.WriteLine("NOTE: The success probability has worsened during the last iteration. This could happen for different reasons:"); Trace.WriteLine(" 1.) The difference in probabilities is beyond the system's ability to measure accurately (i.e., beyond 15 significant digits)."); Trace.WriteLine(" 2.) The difference is due to estimation/approximation error."); Trace.WriteLine(" 3.) You may be operating along the boundary region. In general the procedure is not well defined on the boundaries. (Try gradient ascent.)"); } } else if (alg == "ga") { // Update the glide-path and recompute the probability using the new glide-path. probnr = Climb.Run(type, @params, gp, td, wr, 2 * sn, (int)(rfMax * prec), prec, pllproc, maxgrad, probnr, 4 * sn, grad, alpha[0]); } // Display the new glide-path. Trace.WriteLine(""); Trace.Write("New Glide-Path:"); WrtAry.Run(probnr, gp, "GP", td); // Rebuild the gradient and negate it when using NR. maxgrad = BldGrad.Run(type, @params, gp, td, wr, 1 * sn, (int)(rfMax * prec), prec, probnr, 4 * sn, alpha[1], pllproc, grad); if (alg == "nr") { for (int y = 0; y < td; ++y) { ngrdnt[y] = -1.00 * grad[y]; } } // Report the convergence status. Trace.WriteLine(""); Trace.WriteLine($"EPSILON Convergence Criteria: {maxgrad:F15} vs. {stpthrsh:F15}"); if (maxgrad <= stpthrsh) { Trace.WriteLine(""); Trace.WriteLine("==========> EPSILON Convergence criteria satisfied. <=========="); } Trace.WriteLine(""); Trace.WriteLine(new String('=', 25)); Trace.Write("End Iteration #"); Trace.WriteLine(iterint); Trace.WriteLine(new String('=', 25)); iterint++; } // Build Hessian and confirm we are at a maximum, not a saddle-point or plateau for example. Trace.WriteLine(""); Trace.WriteLine("Convergence Achieved: Final step is to confirm we are at a local/global maximum. Hessian is being built."); hess = DrvHess.Run(type, @params, gp, td, wr, sn, (int)(rfMax * prec), prec, pllproc, grad, probnr); hevals = new EigenvalueDecomposition(hess); var r = hevals.RealEigenvalues; maxeigen = r.Max(); mineigen = r.Min(); // Display the smallest/largest eigenvalues. Trace.WriteLine(""); Trace.Write("Min Hessian eigenvalue at solution [>=0.00 --> convex region --> (local/global) minimum]: "); Trace.WriteLine(mineigen); Trace.WriteLine(""); Trace.Write("Max Hessian eigenvalue at solution [<=0.00 --> concave region --> (local/global) maximum]: "); Trace.WriteLine(maxeigen); // Write final GP to the output file. Trace.WriteLine(""); if (maxeigen <= 0 || mineigen >= 0) { Trace.Write("(Local/Global) Optimal "); } Trace.WriteLine("Glide-Path:"); WrtAry.Run(probnr, gp, "GP", td, Path.Combine(rootdir, Config.Outfile)); Trace.WriteLine(""); }
public QrDecompositionWrapper(QrDecomposition qr) { _qr = qr; }