Inheritance: System.Matrix
Beispiel #1
0
 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]));
     }));
 }
Beispiel #2
0
 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));
     }));
 }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
 }
Beispiel #6
0
        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));
        }
Beispiel #8
0
        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);
 }
Beispiel #10
0
        /// <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;
        }
Beispiel #11
0
 /// <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;
 }
Beispiel #12
0
 /// <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);
                }
            }
        }
Beispiel #16
0
        /// <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);
        }
Beispiel #17
0
        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;
            }
        }
Beispiel #18
0
 public FFT2d(MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix dm2Process)
 {
     dmInput        = null;
     dmComplexInput = (MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix)dm2Process.Clone();
 }
Beispiel #19
0
        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);
                }
            }
        }
Beispiel #21
0
 /// <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);
        }
Beispiel #23
0
 /// <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);
        }
Beispiel #25
0
        /// <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]);
 }
Beispiel #30
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;
        }