Esempio n. 1
0
 public virtual DoubleMatrix1D Assign(Cern.Jet.Math.Mult mult)
 {
     for (int i = Size; --i >= 0;)
     {
         this[i] = mult.Apply(this[i]);
     }
     return(this);
 }
        public void Solve(DoubleMatrix2D B)
        {
            int CUT_OFF = 10;
            //algebra.property().checkRectangular(LU);
            int m = M;
            int n = N;

            if (B.Rows != m)
            {
                throw new ArgumentException("Matrix row dimensions must agree.");
            }
            if (!this.IsNonsingular)
            {
                throw new ArgumentException("Matrix is singular.");
            }


            // right hand side with pivoting
            // Matrix Xmat = B.getMatrix(piv,0,nx-1);
            if (this.work1 == null || this.work1.Length < m)
            {
                this.work1 = new int[m];
            }
            //if (this.work2 == null || this.work2.Length < m) this.work2 = new int[m];
            Algebra.PermuteRows(B, this.piv, this.work1);

            if (m * n == 0)
            {
                return;             // nothing to do
            }
            int nx = B.Columns;

            //precompute and cache some views to avoid regenerating them time and again
            DoubleMatrix1D[] Brows = new DoubleMatrix1D[n];
            for (int k = 0; k < n; k++)
            {
                Brows[k] = B.ViewRow(k);
            }

            // transformations
            Cern.Jet.Math.Mult     div       = Cern.Jet.Math.Mult.Div(0);
            Cern.Jet.Math.PlusMult minusMult = Cern.Jet.Math.PlusMult.MinusMult(0);

            IntArrayList   nonZeroIndexes = new IntArrayList();                              // sparsity
            DoubleMatrix1D Browk          = Cern.Colt.Matrix.DoubleFactory1D.Dense.Make(nx); // blocked row k

            // Solve L*Y = B(piv,:)
            for (int k = 0; k < n; k++)
            {
                // blocking (make copy of k-th row to localize references)
                Browk.Assign(Brows[k]);

                // sparsity detection
                int maxCardinality = nx / CUT_OFF; // == heuristic depending on speedup
                Browk.GetNonZeros(nonZeroIndexes, null, maxCardinality);
                int     cardinality = nonZeroIndexes.Count;
                Boolean sparse      = (cardinality < maxCardinality);

                for (int i = k + 1; i < n; i++)
                {
                    //for (int j = 0; j < nx; j++) B[i][j] -= B[k][j]*LU[i][k];
                    //for (int j = 0; j < nx; j++) B.set(i,j, B.Get(i,j) - B.Get(k,j)*LU.Get(i,k));

                    minusMult.Multiplicator = -LU[i, k];
                    if (minusMult.Multiplicator != 0)
                    {
                        if (sparse)
                        {
                            Brows[i].Assign(Browk, minusMult, nonZeroIndexes);
                        }
                        else
                        {
                            Brows[i].Assign(Browk, minusMult);
                        }
                    }
                }
            }

            // Solve U*B = Y;
            for (int k = n - 1; k >= 0; k--)
            {
                // for (int j = 0; j < nx; j++) B[k][j] /= LU[k][k];
                // for (int j = 0; j < nx; j++) B.set(k,j, B.Get(k,j) / LU.Get(k,k));
                div.Multiplicator = 1 / LU[k, k];
                Brows[k].Assign(div);

                // blocking
                if (Browk == null)
                {
                    Browk = Cern.Colt.Matrix.DoubleFactory1D.Dense.Make(B.Columns);
                }
                Browk.Assign(Brows[k]);

                // sparsity detection
                int maxCardinality = nx / CUT_OFF; // == heuristic depending on speedup
                Browk.GetNonZeros(nonZeroIndexes, null, maxCardinality);
                int     cardinality = nonZeroIndexes.Count;
                Boolean sparse      = (cardinality < maxCardinality);

                //Browk.GetNonZeros(nonZeroIndexes,null);
                //Boolean sparse = nonZeroIndexes.Count < nx/10;

                for (int i = 0; i < k; i++)
                {
                    // for (int j = 0; j < nx; j++) B[i][j] -= B[k][j]*LU[i][k];
                    // for (int j = 0; j < nx; j++) B.set(i,j, B.Get(i,j) - B.Get(k,j)*LU.Get(i,k));

                    minusMult.Multiplicator = -LU[i, k];
                    if (minusMult.Multiplicator != 0)
                    {
                        if (sparse)
                        {
                            Brows[i].Assign(Browk, minusMult, nonZeroIndexes);
                        }
                        else
                        {
                            Brows[i].Assign(Browk, minusMult);
                        }
                    }
                }
            }
        }
        public void Decompose(DoubleMatrix2D A)
        {
            int CUT_OFF = 10;

            // setup
            LU = A;
            int m = A.Rows;
            int n = A.Columns;

            // setup pivot vector
            if (this.piv == null || this.piv.Length != m)
            {
                this.piv = new int[m];
            }
            for (int i = m; --i >= 0;)
            {
                piv[i] = i;
            }
            pivsign = 1;

            if (m * n == 0)
            {
                LU = LU;
                return; // nothing to do
            }

            //precompute and cache some views to avoid regenerating them time and again
            DoubleMatrix1D[] LUrows = new DoubleMatrix1D[m];
            for (int i = 0; i < m; i++)
            {
                LUrows[i] = LU.ViewRow(i);
            }

            IntArrayList   nonZeroIndexes = new IntArrayList();      // sparsity
            DoubleMatrix1D LUcolj         = LU.ViewColumn(0).Like(); // blocked column j

            Cern.Jet.Math.Mult multFunction = Cern.Jet.Math.Mult.CreateInstance(0);

            // Outer loop.
            for (int j = 0; j < n; j++)
            {
                // blocking (make copy of j-th column to localize references)
                LUcolj.Assign(LU.ViewColumn(j));

                // sparsity detection
                int maxCardinality = m / CUT_OFF; // == heuristic depending on speedup
                LUcolj.GetNonZeros(nonZeroIndexes, null, maxCardinality);
                int     cardinality = nonZeroIndexes.Count;
                Boolean sparse      = (cardinality < maxCardinality);

                // Apply previous transformations.
                for (int i = 0; i < m; i++)
                {
                    int    kmax = System.Math.Min(i, j);
                    double s;
                    if (sparse)
                    {
                        s = LUrows[i].ZDotProduct(LUcolj, 0, kmax, nonZeroIndexes);
                    }
                    else
                    {
                        s = LUrows[i].ZDotProduct(LUcolj, 0, kmax);
                    }
                    double before = LUcolj[i];
                    double after  = before - s;
                    LUcolj[i] = after; // LUcolj is a copy
                    LU[i, j]  = after; // this is the original
                    if (sparse)
                    {
                        if (before == 0 && after != 0)
                        { // nasty bug fixed!
                            int pos = nonZeroIndexes.BinarySearch(i);
                            pos = -pos - 1;
                            nonZeroIndexes.Insert(pos, i);
                        }
                        if (before != 0 && after == 0)
                        {
                            nonZeroIndexes.Remove(nonZeroIndexes.BinarySearch(i));
                        }
                    }
                }

                // Find pivot and exchange if necessary.
                int p = j;
                if (p < m)
                {
                    double max = System.Math.Abs(LUcolj[p]);
                    for (int i = j + 1; i < m; i++)
                    {
                        double v = System.Math.Abs(LUcolj[i]);
                        if (v > max)
                        {
                            p   = i;
                            max = v;
                        }
                    }
                }
                if (p != j)
                {
                    LUrows[p].Swap(LUrows[j]);
                    int k = piv[p]; piv[p] = piv[j]; piv[j] = k;
                    pivsign = -pivsign;
                }

                // Compute multipliers.
                double jj;
                if (j < m && (jj = LU[j, j]) != 0.0)
                {
                    multFunction.Multiplicator = 1 / jj;
                    LU.ViewColumn(j).ViewPart(j + 1, m - (j + 1)).Assign(multFunction);
                }
            }
            LU = LU;
        }