public FFT2d(MathNet.Numerics.LinearAlgebra.Double.DenseMatrix dmReal, MathNet.Numerics.LinearAlgebra.Double.DenseMatrix dmImag) { dmInput = null; dmComplexInput = MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix.Create(dmReal.RowCount, dmReal.ColumnCount, new Func <int, int, Complex>((row, column) => { return(new Complex(dmReal[row, column], dmImag[row, column])); })); }
public FFT2d(MathNet.Numerics.LinearAlgebra.Double.DenseMatrix dm2Process) { dmInput = (MathNet.Numerics.LinearAlgebra.Double.DenseMatrix)dm2Process.Clone(); dmComplexInput = new MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix(dmInput.RowCount, dmInput.ColumnCount); dmComplexInput.MapIndexedInplace(new Func <int, int, Complex, Complex>( (row, column, val) => { return(new Complex(dmInput[row, column], 0.0d)); })); }
public void CanCheckRankOfSquareSingular(int order) { var matrixA = new DenseMatrix(order, order); matrixA[0, 0] = 1; matrixA[order - 1, order - 1] = 1; for (var i = 1; i < order - 1; i++) { matrixA[i, i - 1] = 1; matrixA[i, i + 1] = 1; matrixA[i - 1, i] = 1; matrixA[i + 1, i] = 1; } var factorSvd = matrixA.Svd(); Assert.AreEqual(factorSvd.Determinant, Complex.Zero); Assert.AreEqual(factorSvd.Rank, order - 1); }
public void CanCheckRankOfSquareSingular([Values(10, 50, 100)] int order) { var A = new DenseMatrix(order, order); A[0, 0] = 1; A[order - 1, order - 1] = 1; for (var i = 1; i < order - 1; i++) { A[i, i - 1] = 1; A[i, i + 1] = 1; A[i - 1, i] = 1; A[i + 1, i] = 1; } var factorEvd = A.Evd(); Assert.AreEqual(factorEvd.Determinant, Complex.Zero); Assert.AreEqual(factorEvd.Rank, order - 1); }
public void CalculateYBus() { Y_Bus = new DenseMatrix(buses.Count, buses.Count); foreach (Branch branch in branches) { int fromBus = Convert.ToInt32(branch.FromBus) - 1; int toBus = Convert.ToInt32(branch.ToBus) - 1; Complex impedance = new Complex(branch.Resistance,branch.Reactance); Complex admittance = 1/impedance; if (branch.Ratio != 0) { double t = 1 / branch.Ratio; Y_Bus[fromBus, toBus] = -1 * t * admittance + Y_Bus[fromBus, toBus]; Y_Bus[toBus, fromBus] = -1 * t * admittance + Y_Bus[toBus, fromBus]; Y_Bus[fromBus, fromBus] = Y_Bus[fromBus, fromBus] + t * t * admittance; Y_Bus[toBus, toBus] = Y_Bus[toBus, toBus] + admittance; } else { Complex shuntsusceptance = new Complex(0,0.5*branch.Susceptance); Y_Bus[fromBus, fromBus] = Y_Bus[fromBus, fromBus] + admittance + shuntsusceptance; Y_Bus[toBus, toBus] = Y_Bus[toBus, toBus] + admittance + shuntsusceptance; Y_Bus[fromBus, toBus] = Y_Bus[fromBus, toBus] - admittance; Y_Bus[toBus, fromBus] = Y_Bus[toBus, fromBus] - admittance; } } foreach (Bus bus in buses) { if (bus.ShuntSusceptance != 0) { Complex busshuntsusceptance = new Complex(0,bus.ShuntSusceptance); for (int i = 0; i < Y_Bus.ColumnCount; i++) { if (i==(Convert.ToInt32(bus.ID)-1)) { Y_Bus[i, i] = Y_Bus[i, i] + busshuntsusceptance; } } } } //Console.WriteLine(Y_Bus); }
public void FFT2dInverse() { dmResultComplex = new MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix(dmComplexInput.RowCount, dmComplexInput.ColumnCount, new Complex[] { new Complex(0.0d, 0.0d) }); IEnumerable <Tuple <int, Vector <Complex> > > columnEnumerator = dmComplexInput.EnumerateColumnsIndexed(); foreach (Tuple <int, Vector <Complex> > theColumnTuple in columnEnumerator) { Vector <Complex> theVector = theColumnTuple.Item2; Complex[] theVectorArray = theVector.ToArray(); Fourier.Inverse(theVectorArray); Vector <Complex> theVectorSpectrum = new MathNet.Numerics.LinearAlgebra.Complex.DenseVector(theVectorArray); dmResultComplex.SetColumn(theColumnTuple.Item1, theVectorSpectrum); } IEnumerable <Tuple <int, Vector <Complex> > > rowEnumerator = dmResultComplex.EnumerateRowsIndexed(); foreach (Tuple <int, Vector <Complex> > theRowTuple in rowEnumerator) { Vector <Complex> theVector = theRowTuple.Item2; Complex[] theVectorArray = theVector.ToArray(); Fourier.Inverse(theVectorArray); Vector <Complex> theVectorSpectrum = new MathNet.Numerics.LinearAlgebra.Complex.DenseVector(theVectorArray); dmResultComplex.SetRow(theRowTuple.Item1, theVectorSpectrum); } dmOutputReal = MathNet.Numerics.LinearAlgebra.Double.DenseMatrix.Create(dmResultComplex.RowCount, dmResultComplex.ColumnCount, new Func <int, int, double>( (row, column) => { return(dmResultComplex[row, column].Real); })); dmOutputImaginary = MathNet.Numerics.LinearAlgebra.Double.DenseMatrix.Create(dmResultComplex.RowCount, dmResultComplex.ColumnCount, new Func <int, int, double>( (row, column) => { return(dmResultComplex[row, column].Imaginary); })); }
public void CanAddSparseMatricesBothWays() { var m1 = new SparseMatrix(1, 3); var m2 = SparseMatrix.OfArray(new Complex[,] {{0, 1, 1}}); var sum1 = m1 + m2; var sum2 = m2 + m1; Assert.IsTrue(sum1.Equals(m2)); Assert.IsTrue(sum1.Equals(sum2)); var sparseResult = new SparseMatrix(1, 3); sparseResult.Add(m2, sparseResult); Assert.IsTrue(sparseResult.Equals(sum1)); sparseResult = SparseMatrix.OfArray(new Complex[,] {{0, 1, 1}}); sparseResult.Add(m1, sparseResult); Assert.IsTrue(sparseResult.Equals(sum1)); sparseResult = SparseMatrix.OfArray(new Complex[,] {{0, 1, 1}}); m1.Add(sparseResult, sparseResult); Assert.IsTrue(sparseResult.Equals(sum1)); sparseResult = SparseMatrix.OfArray(new Complex[,] {{0, 1, 1}}); sparseResult.Add(sparseResult, sparseResult); Assert.IsTrue(sparseResult.Equals(2*sum1)); var denseResult = new DenseMatrix(1, 3); denseResult.Add(m2, denseResult); Assert.IsTrue(denseResult.Equals(sum1)); denseResult = DenseMatrix.OfArray(new Complex[,] {{0, 1, 1}}); denseResult.Add(m1, denseResult); Assert.IsTrue(denseResult.Equals(sum1)); var m3 = DenseMatrix.OfArray(new Complex[,] {{0, 1, 1}}); var sum3 = m1 + m3; var sum4 = m3 + m1; Assert.IsTrue(sum3.Equals(m3)); Assert.IsTrue(sum3.Equals(sum4)); }
public void CanSolveForRandomMatrixWhenResultMatrixGiven(int row, int column) { var matrixA = MatrixLoader.GenerateRandomDenseMatrix(row, column); var matrixACopy = matrixA.Clone(); var factorSvd = matrixA.Svd(); var matrixB = MatrixLoader.GenerateRandomDenseMatrix(row, column); var matrixBCopy = matrixB.Clone(); var matrixX = new DenseMatrix(column, column); factorSvd.Solve(matrixB, matrixX); // The solution X row dimension is equal to the column dimension of A Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); // The solution X has the same number of columns as B Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); var matrixBReconstruct = matrixA*matrixX; // Check the reconstruction. for (var i = 0; i < matrixB.RowCount; i++) { for (var j = 0; j < matrixB.ColumnCount; j++) { AssertHelpers.AlmostEqual(matrixB[i, j], matrixBReconstruct[i, j], 9); } } // Make sure A didn't change. for (var i = 0; i < matrixA.RowCount; i++) { for (var j = 0; j < matrixA.ColumnCount; j++) { Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]); } } // Make sure B didn't change. for (var i = 0; i < matrixB.RowCount; i++) { for (var j = 0; j < matrixB.ColumnCount; j++) { Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]); } } }
public void CholeskyFailsWithNonSquareMatrix() { var matrix = new DenseMatrix(3, 2); Assert.That(() => matrix.Cholesky(), Throws.ArgumentException); }
/// <summary> /// Returns the conjugate transpose of this matrix. /// </summary> /// <returns>The conjugate transpose of this matrix.</returns> public override Matrix<Complex> ConjugateTranspose() { var ret = new DenseMatrix(_columnCount, _rowCount); for (var j = 0; j < _columnCount; j++) { var index = j * _rowCount; for (var i = 0; i < _rowCount; i++) { ret._values[(i * _columnCount) + j] = _values[index + i].Conjugate(); } } return ret; }
/// <summary> /// Create a new dense matrix with the diagonal as a copy of the given vector. /// This new matrix will be independent from the vector. /// A new memory block will be allocated for storing the matrix. /// </summary> public static DenseMatrix OfDiagonalVector(int rows, int columns, Vector<Complex> diagonal) { var m = new DenseMatrix(rows, columns); m.SetDiagonal(diagonal); return m; }
/// <summary> /// Create a new dense matrix with the diagonal as a copy of the given array. /// This new matrix will be independent from the array. /// A new memory block will be allocated for storing the matrix. /// </summary> public static DenseMatrix OfDiagonalArray(int rows, int columns, Complex[] diagonal) { var m = new DenseMatrix(rows, columns); m.SetDiagonal(diagonal); return m; }
public void CanComputeQRFactorWideMatrix() { var matrix = _matrices["Wide2x3"]; var r = new Complex[matrix.RowCount*matrix.ColumnCount]; Array.Copy(matrix.Values, r, r.Length); var tau = new Complex[3]; var q = new Complex[matrix.RowCount*matrix.RowCount]; Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau); var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle(); var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q); var a = mq*mr; for (var row = 0; row < matrix.RowCount; row++) { for (var col = 0; col < matrix.ColumnCount; col++) { AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14); } } }
public void CanSolveUsingCholesky() { var matrix = new DenseMatrix(3, 3, new Complex[] {1, 1, 1, 1, 2, 3, 1, 3, 6}); var a = new Complex[] {1, 1, 1, 1, 2, 3, 1, 3, 6}; var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0}; Control.LinearAlgebraProvider.CholeskySolve(a, 3, b, 2); AssertHelpers.AlmostEqualRelative(b[0], 0, 14); AssertHelpers.AlmostEqualRelative(b[1], 1, 14); AssertHelpers.AlmostEqualRelative(b[2], 0, 14); AssertHelpers.AlmostEqualRelative(b[3], 3, 14); AssertHelpers.AlmostEqualRelative(b[4], 1, 14); AssertHelpers.AlmostEqualRelative(b[5], 0, 14); NotModified(3, 3, a, matrix); }
public void CanMultiplyTallAndWideMatricesWithUpdate() { var x = _matrices["Tall3x2"]; var y = _matrices["Wide2x3"]; var c = new DenseMatrix(x.RowCount, y.ColumnCount); Control.LinearAlgebraProvider.MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 2.2, x.Values, x.RowCount, x.ColumnCount, y.Values, y.RowCount, y.ColumnCount, 1.0, c.Values); for (var i = 0; i < c.RowCount; i++) { for (var j = 0; j < c.ColumnCount; j++) { AssertHelpers.AlmostEqualRelative(2.2*x.Row(i)*y.Column(j), c[i, j], 14); } } }
/// <summary> /// 平行ビームの電子回折計算 /// </summary> /// <param name="maxNumOfBloch"></param> /// <param name="voltage"></param> /// <param name="rotation"></param> /// <param name="thickness"></param> /// <returns></returns> public Beam[] GetDifractedBeamAmpriltudes(int maxNumOfBloch, double voltage, Matrix3D rotation, double thickness) { var useEigen = !MathNet.Numerics.Control.TryUseNativeMKL(); if (AccVoltage != voltage) { uDictionary = new Dictionary <int, (Complex, Complex)>(); } //波数を計算 var k_vac = UniversalConstants.Convert.EnergyToElectronWaveNumber(voltage); //U0を計算 var u0 = getU(voltage, (0, 0, 0), 0).Real.Real; var vecK0 = getVecK0(k_vac, u0); if (MaxNumOfBloch != maxNumOfBloch || AccVoltage != voltage || EigenValues == null || EigenVectors == null || !rotation.Equals(BaseRotation)) { MaxNumOfBloch = maxNumOfBloch; AccVoltage = voltage; BaseRotation = new Matrix3D(rotation); Thickness = thickness; //計算対象のg-Vectorsを決める。 Beams = Find_gVectors(BaseRotation, vecK0); if (Beams == null || Beams.Length == 0) { return(new Beam[0]); } var potentialMatrix = getEigenProblemMatrix(Beams); //A行列に関する固有値、固有ベクトルを取得 if (useEigen) { (EigenValues, EigenVectors) = NativeWrapper.EigenSolver(potentialMatrix); } else { var evd = DMat.OfArray(potentialMatrix).Evd(Symmetricity.Asymmetric); EigenValues = evd.EigenValues.AsArray(); EigenVectors = (DMat)evd.EigenVectors; } //(EigenVectors, EigenValues) = RefineEigenProblem(DMat.OfArray(potentialMatrix), (DMat)evd.EigenVectors, evd.EigenValues.ToArray()); } int len = EigenValues.Count(); var psi0 = DVec.OfArray(new Complex[len]);//入射面での波動関数を定義 psi0[0] = 1; var alpha = EigenVectors.Inverse() * psi0;//アルファベクトルを求める //ガンマの対称行列×アルファを作成 var gamma_alpha = new DVec(Enumerable.Range(0, len).Select(n => Exp(TwoPiI * EigenValues[n] * thickness) * alpha[n]).ToArray()); //出射面での境界条件を考慮した位相にするため、以下の1行を追加 (20190827) var p = new DiagonalMatrix(len, len, Beams.Select(b => Exp(PiI * (b.P - 2 * k_vac * Surface.Z) * thickness)).ToArray()); //var p = new DiagonalMatrix(len, len, Beams.Select(b => new Complex(1, 0)).ToArray()); //深さZにおけるψを求める var psi_atZ = p * EigenVectors * gamma_alpha; for (int i = 0; i < Beams.Length && i < len; i++) { Beams[i].Psi = psi_atZ[i]; } return(Beams); }
private void cbed_DoWork(object sender, DoWorkEventArgs e) { //波数を計算 var kvac = UniversalConstants.Convert.EnergyToElectronWaveNumber(AccVoltage); //U0を計算 var u0 = getU(AccVoltage, (0, 0, 0), 0).Real.Real; //k0ベクトルを計算 var vecK0 = getVecK0(kvac, u0); //計算対象のg-Vectorsを決める。indexが小さく、かつsg(励起誤差)の小さいg-vectorを抽出する Beams = Find_gVectors(BaseRotation, vecK0); //入射面での波動関数を定義 var psi0 = DVec.OfArray(Enumerable.Range(0, Beams.Length).ToList().Select(g => g == 0 ? One : 0).ToArray()); //ポテンシャルマトリックスを取得 uDictionary = new Dictionary <int, (Complex, Complex)>(); var factorMatrix = getPotentialMatrix(Beams); //有効なRotationだけを選択 var beamRotationsValid = new List <Matrix3D>(); for (int i = 0; i < BeamRotations.Length; i++) { if (BeamRotations[i] != null) { beamRotationsValid.Add(BeamRotations[i]); } } RotationArrayValidLength = beamRotationsValid.Count; //rotationsValidに対応するdiskValidを定義 var diskValid = new List <Complex[][]>(); //進捗状況報告用の各種定数を初期化 int count = 0, total = beamRotationsValid.Count; var sw = new Stopwatch(); var bLen = Beams.Length; //ローカル関数. RotationsValid(の一部)を対象にdisks[t][g]を計算し、diskValidに追加し、最後にかかった時間を返す long func(Solver solver, int thread, bool speedTest = true) { if (solver == Solver.MKL) { MathNet.Numerics.Control.TryUseNativeMKL(); } else if (solver == Solver.Managed) { MathNet.Numerics.Control.UseManaged(); } var reportString = (solver == Solver.MKL ? "MKL" : "EIG") + thread.ToString(); var beamRotationsP = beamRotationsValid.AsParallel().WithDegreeOfParallelism(thread); if (speedTest)//スピードテストのとき { var n = Math.Min(bLen < 64 ? 512 : bLen < 128 ? 256 : bLen < 256 ? 128 : bLen < 512 ? 64 : 32, beamRotationsValid.Count); if (n == 0) { return(0); } beamRotationsP = beamRotationsValid.Take(n).ToArray().AsParallel().WithDegreeOfParallelism(thread); beamRotationsValid.RemoveRange(0, n); } sw.Restart(); //disks[t][g]を計算. var disk = beamRotationsP.Select(beamRotation => { if (bwCBED.CancellationPending) { return(null); } var rotZ = beamRotation * zNorm; var coeff = 1.0 / rotZ.Z; // = 1/cosTau var vecK0 = getVecK0(kvac, u0, beamRotation); var beams = reset_gVectors(Beams, BaseRotation, vecK0); //BeamsのPやQをリセット var potentialMatrix = getEigenProblemMatrix(beams, factorMatrix); //ポテンシャル行列をセット Complex[][] result; //ポテンシャル行列の固有値、固有ベクトルを取得し、resultに格納 if (solver == Solver.Eigen) { result = NativeWrapper.CBEDSolver(potentialMatrix, psi0.ToArray(), Thicknesses, coeff); } else { var evd = DMat.OfArray(potentialMatrix).Evd(Symmetricity.Unknown); var alpha = evd.EigenVectors.Inverse() * psi0; result = Thicknesses.Select(t => { //ガンマの対称行列×アルファを作成 var gammmaAlpha = DVec.OfArray(evd.EigenValues.Select((ev, i) => Exp(TwoPiI * ev * t * coeff) * alpha[i]).ToArray()); //深さtにおけるψを求める return((evd.EigenVectors * gammmaAlpha).ToArray()); }).ToArray(); } bwCBED.ReportProgress(Interlocked.Increment(ref count), reportString); //進捗状況を報告 return(result); }).ToArray(); diskValid.AddRange(disk); //diskをdiskValidに加える return(sw.ElapsedTicks); //経過時間を返す } //ここからチューニング&本番 if ((Solver)((object[])e.Argument)[0] == Solver.Auto) { if (EigenEnabled && bLen < 512 && func(Solver.Eigen, Environment.ProcessorCount) < func(Solver.MKL, 8))//eigenの方が早い場合 { func(Solver.Eigen, Environment.ProcessorCount, false); } else if (Environment.ProcessorCount <= 4)//MKLでコア数が4以下の場合 { func(Solver.MKL, Environment.ProcessorCount, false); } else//コア数4,6,8,10,12,14,16を試して最速のもので { var list = new SortedList <long, int>(); foreach (var t in new[] { 4, 6, 8, 10, 12, 14, 16 }) { if (t <= Environment.ProcessorCount) { list.Add(func(Solver.MKL, t), t); } } func(Solver.MKL, list.Values[0], false); } } else { func((Solver)((object[])e.Argument)[0], (int)((object[])e.Argument)[1], false); } //無効なRotationも考慮してdisk[RotationIndex][Z_index][G_index]を構築 var disk = new List <Complex[][]>(); for (int i = 0, j = 0; i < BeamRotations.Length; i++) { disk.Add(BeamRotations[i] != null ? diskValid[j++] : null); } //diskをコンパイルする Disks = new CBED_Disk[Thicknesses.Length][]; Parallel.For(0, Thicknesses.Length, t => { Disks[t] = new CBED_Disk[Beams.Length]; for (int g = 0; g < Beams.Length; g++) { var intensity = new double[BeamRotations.Length]; for (int r = 0; r < BeamRotations.Length; r++) { if (disk[r] != null) { intensity[r] = disk[r][t][g].Magnitude2(); } } Disks[t][g] = new CBED_Disk(new[] { Beams[g].H, Beams[g].K, Beams[g].L }, Beams[g].Vec, Thicknesses[t], intensity); } }); if (bwCBED.CancellationPending) { e.Cancel = true; } }
public FFT2d(MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix dm2Process) { dmInput = null; dmComplexInput = (MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix)dm2Process.Clone(); }
public void CanSolveForRandomMatrixAndSymmetricMatrixWhenResultMatrixGiven([Values(1, 2, 5, 10, 50, 100)] int order) { var A = Matrix<Complex>.Build.RandomPositiveDefinite(order, 1); MatrixHelpers.ForceHermitian(A); var ACopy = A.Clone(); var evd = A.Evd(Symmetricity.Hermitian); var B = Matrix<Complex>.Build.Random(order, order, 2); var BCopy = B.Clone(); var X = new DenseMatrix(order, order); evd.Solve(B, X); // The solution X row dimension is equal to the column dimension of A Assert.AreEqual(A.ColumnCount, X.RowCount); // The solution X has the same number of columns as B Assert.AreEqual(B.ColumnCount, X.ColumnCount); var BReconstruct = A * X; // Check the reconstruction. AssertHelpers.AlmostEqual(B, BReconstruct, 9); // Make sure A/B didn't change. AssertHelpers.AlmostEqual(ACopy, A, 14); AssertHelpers.AlmostEqual(BCopy, B, 14); }
public void CanComputeThinQRFactorTallMatrix() { var matrix = _matrices["Tall3x2"]; var r = new Complex[matrix.ColumnCount*matrix.ColumnCount]; var tau = new Complex[3]; var q = new Complex[matrix.RowCount*matrix.ColumnCount]; Array.Copy(matrix.Values, q, q.Length); Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau); var mq = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, q); var mr = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, r); var a = mq*mr; for (var row = 0; row < matrix.RowCount; row++) { for (var col = 0; col < matrix.ColumnCount; col++) { AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14); } } }
/// <summary> /// Create a new dense matrix with the diagonal as a copy of the given array. /// This new matrix will be independent from the array. /// A new memory block will be allocated for storing the matrix. /// </summary> public static DenseMatrix OfDiagonalArray(Complex[] diagonal) { var m = new DenseMatrix(diagonal.Length, diagonal.Length); m.SetDiagonal(diagonal); return m; }
public void CanSolveUsingThinQRSquareMatrixOnFactoredMatrix() { var matrix = _matrices["Square3x3"]; var a = new Complex[matrix.RowCount*matrix.ColumnCount]; Array.Copy(matrix.Values, a, a.Length); var tau = new Complex[matrix.ColumnCount]; var r = new Complex[matrix.ColumnCount*matrix.ColumnCount]; Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau); var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0}; var x = new Complex[matrix.ColumnCount*2]; Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, QRMethod.Thin); var mx = new DenseMatrix(matrix.ColumnCount, 2, x); var mb = matrix*mx; AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13); AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13); AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13); AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13); AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13); AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13); }
/// <summary> /// Create a new dense matrix with the diagonal as a copy of the given vector. /// This new matrix will be independent from the vector. /// A new memory block will be allocated for storing the matrix. /// </summary> public static DenseMatrix OfDiagonalVector(Vector<Complex> diagonal) { var m = new DenseMatrix(diagonal.Count, diagonal.Count); m.SetDiagonal(diagonal); return m; }
public void CanSolveUsingThinQRTallMatrixOnFactoredMatrix() { var matrix = _matrices["Tall3x2"]; var a = new Complex[matrix.RowCount*matrix.ColumnCount]; Array.Copy(matrix.Values, a, a.Length); var tau = new Complex[matrix.ColumnCount]; var r = new Complex[matrix.ColumnCount*matrix.ColumnCount]; Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau); var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0}; var x = new Complex[matrix.ColumnCount*2]; Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, QRMethod.Thin); var mb = new DenseMatrix(matrix.RowCount, 2, b); var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb; AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13); AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13); AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13); AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13); }
/// <summary> /// Initializes a square <see cref="DenseMatrix"/> with all zero's except for ones on the diagonal. /// </summary> /// <param name="order">the size of the square matrix.</param> /// <returns>A dense identity matrix.</returns> /// <exception cref="ArgumentException"> /// If <paramref name="order"/> is less than one. /// </exception> public static DenseMatrix Identity(int order) { var m = new DenseMatrix(order); for (var i = 0; i < order; i++) { m._values[(i * order) + i] = 1.0; } return m; }
public void CanComputeSVDFactorizationOfWideMatrix() { var matrix = _matrices["Wide2x3"]; var a = new Complex[matrix.RowCount*matrix.ColumnCount]; Array.Copy(matrix.Values, a, a.Length); var s = new Complex[matrix.RowCount]; var u = new Complex[matrix.RowCount*matrix.RowCount]; var vt = new Complex[matrix.ColumnCount*matrix.ColumnCount]; Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt); var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount); for (var index = 0; index < s.Length; index++) { w[index, index] = s[index]; } var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u); var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt); var result = mU*w*mV; AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 14); AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 14); AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 14); AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 14); AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 14); AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 14); }
public void CanSolveForRandomMatrixWhenResultMatrixGiven(int row, int col) { var matrixA = Matrix<Complex>.Build.RandomPositiveDefinite(row, 1); var matrixACopy = matrixA.Clone(); var chol = matrixA.Cholesky(); var matrixB = Matrix<Complex>.Build.Random(row, col, 1); var matrixBCopy = matrixB.Clone(); var matrixX = new DenseMatrix(row, col); chol.Solve(matrixB, matrixX); Assert.AreEqual(matrixB.RowCount, matrixX.RowCount); Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); var matrixBReconstruct = matrixA * matrixX; // Check the reconstruction. for (var i = 0; i < matrixB.RowCount; i++) { for (var j = 0; j < matrixB.ColumnCount; j++) { AssertHelpers.AlmostEqual(matrixB[i, j], matrixBReconstruct[i, j], 10); } } // Make sure A didn't change. for (var i = 0; i < matrixA.RowCount; i++) { for (var j = 0; j < matrixA.ColumnCount; j++) { Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]); } } // Make sure B didn't change. for (var i = 0; i < matrixB.RowCount; i++) { for (var j = 0; j < matrixB.ColumnCount; j++) { Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]); } } }
public void CanSolveUsingSVDSquareMatrix() { var matrix = _matrices["Square3x3"]; var a = new Complex[matrix.RowCount*matrix.ColumnCount]; Array.Copy(matrix.Values, a, a.Length); var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0}; var x = new Complex[matrix.ColumnCount*2]; Control.LinearAlgebraProvider.SvdSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x); NotModified(3, 3, a, matrix); var mx = new DenseMatrix(matrix.ColumnCount, 2, x); var mb = matrix*mx; AssertHelpers.AlmostEqual(mb[0, 0], b[0], 13); AssertHelpers.AlmostEqual(mb[1, 0], b[1], 13); AssertHelpers.AlmostEqual(mb[2, 0], b[2], 13); AssertHelpers.AlmostEqual(mb[0, 1], b[3], 13); AssertHelpers.AlmostEqual(mb[1, 1], b[4], 13); AssertHelpers.AlmostEqual(mb[2, 1], b[5], 13); }
public void MatrixFrom1DArrayIsReference() { var data = new[] {new Complex(1.0, 1), new Complex(1.0, 1), new Complex(1.0, 1), new Complex(1.0, 1), new Complex(1.0, 1), new Complex(1.0, 1), new Complex(2.0, 1), new Complex(2.0, 1), new Complex(2.0, 1)}; var matrix = new DenseMatrix(3, 3, data); matrix[0, 0] = new Complex(10.0, 1); Assert.AreEqual(new Complex(10.0, 1), data[0]); }
public void CanSolveForRandomMatrixWhenResultMatrixGivenUsingThinQR(int order) { var matrixA = Matrix<Complex>.Build.Random(order, order, 1); var matrixACopy = matrixA.Clone(); var factorQR = matrixA.QR(QRMethod.Thin); var matrixB = Matrix<Complex>.Build.Random(order, order, 1); var matrixBCopy = matrixB.Clone(); var matrixX = new DenseMatrix(order, order); factorQR.Solve(matrixB, matrixX); // The solution X row dimension is equal to the column dimension of A Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); // The solution X has the same number of columns as B Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); var matrixBReconstruct = matrixA * matrixX; // Check the reconstruction. for (var i = 0; i < matrixB.RowCount; i++) { for (var j = 0; j < matrixB.ColumnCount; j++) { AssertHelpers.AlmostEqual(matrixB[i, j], matrixBReconstruct[i, j], 10); } } // Make sure A didn't change. for (var i = 0; i < matrixA.RowCount; i++) { for (var j = 0; j < matrixA.ColumnCount; j++) { Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]); } } // Make sure B didn't change. for (var i = 0; i < matrixB.RowCount; i++) { for (var j = 0; j < matrixB.ColumnCount; j++) { Assert.AreEqual(matrixBCopy[i, j], matrixB[i, j]); } } }
/// <summary> /// Subtracts another matrix from this matrix. /// </summary> /// <param name="other">The matrix to subtract.</param> /// <returns>The result of the subtraction.</returns> /// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception> public override Matrix<Complex> Subtract(Matrix<Complex> other) { if (other == null) { throw new ArgumentNullException("other"); } if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, other, "other"); } Matrix<Complex> result; if (other is DiagonalMatrix) { result = new DenseMatrix(RowCount, ColumnCount); } else { result = new DiagonalMatrix(RowCount, ColumnCount); } Subtract(other, result); return result; }
/// <summary> /// Create a matrix based on this vector in row form (one single row). /// </summary> /// <returns>This vector as a row matrix.</returns> public override Matrix<Complex> ToRowMatrix() { var matrix = new DenseMatrix(1, _length); for (var i = 0; i < _values.Length; i++) { matrix.At(0, i, _values[i]); } return matrix; }
/// <summary> /// Create a matrix based on this vector in column form (one single column). /// </summary> /// <returns>This vector as a column matrix.</returns> public override Matrix<Complex> ToColumnMatrix() { var matrix = new DenseMatrix(_length, 1); for (var i = 0; i < _values.Length; i++) { matrix.At(i, 0, _values[i]); } return matrix; }
/// <summary> /// Adds another matrix to this matrix. /// </summary> /// <param name="other">The matrix to add to this matrix.</param> /// <returns>The result of the addition.</returns> /// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception> public override Matrix<Complex> Add(Matrix<Complex> other) { if (other == null) { throw new ArgumentNullException("other"); } if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw new ArgumentOutOfRangeException("other", Resources.ArgumentMatrixDimensions); } Matrix<Complex> result; if (other is DiagonalMatrix) { result = new DenseMatrix(RowCount, ColumnCount); } else { result = new DiagonalMatrix(RowCount, ColumnCount); } Add(other, result); return result; }
/// <summary> /// Outer product of two vectors /// </summary> /// <param name="u">First vector</param> /// <param name="v">Second vector</param> /// <returns>Matrix M[i,j] = u[i]*v[j] </returns> /// <exception cref="ArgumentNullException">If the u vector is <see langword="null" />.</exception> /// <exception cref="ArgumentNullException">If the v vector is <see langword="null" />.</exception> public static DenseMatrix OuterProduct(DenseVector u, DenseVector v) { if (u == null) { throw new ArgumentNullException("u"); } if (v == null) { throw new ArgumentNullException("v"); } var matrix = new DenseMatrix(u.Count, v.Count); CommonParallel.For( 0, u.Count, i => { for (var j = 0; j < v.Count; j++) { matrix.At(i, j, u._values[i] * v._values[j]); } }); return matrix; }
/// <summary> /// Returns the transpose of this matrix. /// </summary> /// <returns>The transpose of this matrix.</returns> public override Matrix<Complex> Transpose() { var ret = new DenseMatrix(ColumnCount, RowCount); for (var j = 0; j < ColumnCount; j++) { var index = j * RowCount; for (var i = 0; i < RowCount; i++) { ret.Data[(i * ColumnCount) + j] = Data[index + i]; } } return ret; }