Exemplo n.º 1
0
        private void ssor(ISparseRowAccessMatrix A, double[] xdata)
        {
            int n = A.RowCount;

            // M = (D+L) D^{-1} (D+L)^T

            // Solves (1/omega)*(D+L) y = b
            for (int i = 0; i < n; ++i)
            {
                // Do nothing if we get a divide by zero
                if (Math.Abs(diag[i]) == 0.0)
                {
                    continue;
                }

                IntDoubleVectorPair Arow = A.GetRow(i);
                double[]            Adat = Arow.data;
                int[] Aind = Arow.indices;

                double sum = 0;
                for (int j = 0; j < Aind.Length && Aind[j] < i; ++j)
                {
                    sum += Adat[j] * xdata[Aind[j]];
                }
                xdata[i] = (omega / diag[i]) * (xdata[i] - sum);
            }

            // Solves (omega/(2-omega))*D^{-1} z = y
            for (int i = 0; i < n; ++i)
            {
                // No need to do anything
                if (Math.Abs(diag[i]) == 0.0)
                {
                    continue;
                }

                xdata[i] = (2 - omega) / omega * diag[i] * xdata[i];
            }

            // Solves (1/omega)*(D+L)^T x = z
            for (int i = n - 1; i >= 0; --i)
            {
                // Do nothing if we get a divide by zero
                if (Math.Abs(diag[i]) == 0.0)
                {
                    continue;
                }

                IntDoubleVectorPair Arow = A.GetRow(i);
                double[]            Adat = Arow.data;
                int[] Aind = Arow.indices;

                double sum = 0;
                for (int j = diagInd[i] + 1; j < Aind.Length; ++j)
                {
                    sum += Adat[j] * xdata[Aind[j]];
                }
                xdata[i] = (omega / diag[i]) * (xdata[i] - sum);
            }
        }
Exemplo n.º 2
0
        public override void Setup(IMatrix A)
        {
            int n = A.RowCount;

            diag    = new double[n];
            diagInd = new int[n];

            // Get the diagonal and its indices
            if (A is ISparseRowAccessMatrix)
            {
                for (int i = 0; i < n; ++i)
                {
                    IntDoubleVectorPair Arow = ((ISparseRowAccessMatrix)A).GetRow(i);
                    int ind = Array.BinarySearch(Arow.indices, i);
                    if (ind < 0)
                    {
                        throw new ArgumentException("Diagonal not present");
                    }
                    diag[i]    = Arow.data[ind];
                    diagInd[i] = ind;
                }
            }
            else if (A is ISparseRowColumnAccessMatrix)
            {
                IntIntDoubleVectorTriple Amat = ((ISparseRowColumnAccessMatrix)A).Matrix;
                for (int i = 0; i < n; ++i)
                {
                    int ind = Arrays.binarySearch(Amat.major, i, Amat.minor[i], Amat.minor[i + 1]);
                    if (ind < 0)
                    {
                        throw new ArgumentException("Diagonal not present");
                    }
                    diag[i]    = Amat.data[ind];
                    diagInd[i] = ind;
                }
            }
            else if (A is IDenseRowColumnAccessMatrix)
            {
                IntDoubleVectorPair Amat = ((IDenseRowColumnAccessMatrix)A).Matrix;
                for (int i = 0; i < n; ++i)
                {
                    diagInd[i] = Amat.indices[i] + i;
                    diag[i]    = Amat.data[diagInd[i]];
                }
            }
            else if (A is IDenseRowAccessMatrix)
            {
                for (int i = 0; i < n; ++i)
                {
                    double[] Arow = ((IDenseRowAccessMatrix)A).GetRow(i);
                    diagInd[i] = i;
                    diag[i]    = Arow[i];
                }
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Exemplo n.º 3
0
        private void ssor(IDenseRowColumnAccessMatrix A, double[] xdata)
        {
            int n = A.RowCount;

            IntDoubleVectorPair Amat = A.Matrix;

            // M = (D+L) D^{-1} (D+L)^T

            // Solves (1/omega)*(D+L) y = b
            for (int i = 0; i < n; ++i)
            {
                // Do nothing if we get a divide by zero
                if (Math.Abs(diag[i]) == 0.0)
                {
                    continue;
                }

                double sum = 0;
                for (int j = Amat.indices[i], k = 0; j < diagInd[i]; ++j, ++k)
                {
                    sum += Amat.data[j] * xdata[k];
                }
                xdata[i] = (omega / diag[i]) * (xdata[i] - sum);
            }

            // Solves (omega/(2-omega))*D^{-1} z = y
            for (int i = 0; i < n; ++i)
            {
                // No need to do anything
                if (Math.Abs(diag[i]) == 0.0)
                {
                    continue;
                }

                xdata[i] = (2 - omega) / omega * diag[i] * xdata[i];
            }

            // Solves (1/omega)*(D+L)^T x = z
            for (int i = n - 1; i >= 0; --i)
            {
                // Do nothing if we get a divide by zero
                if (Math.Abs(diag[i]) == 0.0)
                {
                    continue;
                }

                double sum = 0;
                for (int j = diagInd[i] + 1, k = i + 1; j < n; ++j, ++k)
                {
                    sum += Amat.data[j] * xdata[k];
                }
                xdata[i] = (omega / diag[i]) * (xdata[i] - sum);
            }
        }
Exemplo n.º 4
0
        private void sor(IDenseRowColumnAccessMatrix A, double[] bdata, double[] xdata)
        {
            IntDoubleVectorPair Amat = A.Matrix;

            for (int i = 0; i < A.RowCount; ++i)
            {
                double newVal = 0, diagVal = 0.0;
                for (int j = Amat.indices[i], k = 0; j < Amat.indices[i + 1]; ++j, ++k)
                {
                    if (k != i)
                    {
                        newVal += Amat.data[j] * xdata[k];
                    }
                    else
                    {
                        diagVal = Amat.data[j];
                    }
                }
                newVal    = (bdata[i] - newVal) / diagVal;
                xdata[i] += omega * (newVal - xdata[i]);
            }
        }
Exemplo n.º 5
0
        private void sor(ISparseRowAccessMatrix A, double[] bdata, double[] xdata)
        {
            for (int i = 0; i < A.RowCount; ++i)
            {
                IntDoubleVectorPair Arow = A.GetRow(i);

                double newVal = 0, diagVal = 0.0;
                for (int j = 0; j < Arow.indices.Length; ++j)
                {
                    if (Arow.indices[j] != i)
                    {
                        newVal += Arow.data[j] * xdata[Arow.indices[j]];
                    }
                    else
                    {
                        diagVal = Arow.data[j];
                    }
                }
                newVal    = (bdata[i] - newVal) / diagVal;
                xdata[i] += omega * (newVal - xdata[i]);
            }
        }
        /// <summary> F is upper-triangular, and F<sup>T</sup> is solved for.</summary>
        /// <param name="data">Initially the right hand side. Overwritten with solution.</param>
        /// <param name="diagDiv">True if the diagonal will be divided with.</param>
        protected internal virtual void SolveUT(double[] data, bool diagDiv)
        {
            for (int i = 0; i < F.RowCount; ++i)
            {
                IntDoubleVectorPair cur = F.GetRow(i);
                int[]    curInd         = cur.indices;
                double[] curDat         = cur.data;

                // Solve at current position
                if (diagDiv)
                {
                    data[i] /= curDat[diagInd[i]];
                }
                double val = data[i];

                // Move over to right hand side
                for (int j = diagInd[i] + 1; j < curInd.Length; ++j)
                {
                    data[curInd[j]] -= curDat[j] * val;
                }
            }
        }
        /// <summary> F is upper-triangular, and it is solved for.</summary>
        /// <param name="data">Initially the right hand side. Overwritten with solution.</param>
        /// <param name="diagDiv">True if the diagonal will be divided with.</param>
        protected internal virtual void SolveU(double[] data, bool diagDiv)
        {
            for (int i = F.RowCount - 1; i >= 0; --i)
            {
                IntDoubleVectorPair cur = F.GetRow(i);
                int[]    curInd         = cur.indices;
                double[] curDat         = cur.data;

                double sum = 0;
                for (int j = diagInd[i] + 1; j < curInd.Length; ++j)
                {
                    sum += curDat[j] * data[curInd[j]];
                }

                data[i] -= sum;

                // Divide by diagonal. The factorization guarantees its existence
                if (diagDiv)
                {
                    data[i] /= curDat[diagInd[i]];
                }
            }
        }
        private void gaussSeidel(ISparseRowAccessMatrix A, double[] bdat, double[] xdat)
        {
            for (int i = 0; i < A.RowCount; ++i)
            {
                IntDoubleVectorPair Arow = A.GetRow(i);
                int[]    ArowInd         = Arow.indices;
                double[] ArowDat         = Arow.data;

                double newVal = 0, diagVal = 0.0;
                for (int j = 0; j < ArowInd.Length; ++j)
                {
                    if (ArowInd[j] != i)
                    {
                        newVal += ArowDat[j] * xdat[ArowInd[j]];
                    }
                    else
                    {
                        diagVal = ArowDat[j];
                    }
                }

                xdat[i] = (bdat[i] - newVal) / diagVal;
            }
        }
        /// <summary> F is lower-triangular, and it is solved for.</summary>
        /// <param name="data">Initially the right hand side. Overwritten with solution.</param>
        /// <param name="diagDiv">True if the diagonal will be divided with.</param>
        protected internal virtual void solveL(double[] data, bool diagDiv)
        {
            for (int i = 0; i < F.RowCount; ++i)
            {
                IntDoubleVectorPair cur = F.GetRow(i);
                int[]    curInd         = cur.indices;
                double[] curDat         = cur.data;

                double sum = 0;
                int    j   = 0;
                for (; curInd[j] < i; ++j)
                {
                    sum += curDat[j] * data[curInd[j]];
                }

                data[i] -= sum;

                // Divide by diagonal. The factorization guarantees its existence
                if (diagDiv)
                {
                    data[i] /= curDat[j];
                }
            }
        }
Exemplo n.º 10
0
        protected internal override void Factor()
        {
            double diagMod = initShift;
            int    n       = A.RowCount;

            diagInd = new int[n];
            double[] curRow = new double[n];

            //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"'
            while (true)
            {
                // Copy A into F, and ensure non-zero diagonal
                Blas.Default.AddDiagonal(diagMod, Blas.Default.Copy(A, F));

                // Clear cache of diagonal indices
                SupportClass.ArraySupport.Fill(diagInd, -1);
                GetDiagIndex(0);

                // Row-based Gaussian elimination
                for (int i = 1; i < n; ++i)
                {
                    // Get current row in dense format
                    IntDoubleVectorPair curRowI = F.GetRow(i);
                    curRow = Blas.Default.Scatter(curRowI, curRow);

                    // Check for empty row
                    if (curRowI.indices.Length == 0)
                    {
                        diagMod += shift;
                        //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"'
                        goto outer;
                    }

                    // Traverse all active rows
                    for (int j = 0; j < curRowI.indices.Length && curRowI.indices[j] < i; ++j)
                    {
                        IntDoubleVectorPair actRow = F.GetRow(curRowI.indices[j]);

                        // Check for missing or zero diagonal
                        int diag = GetDiagIndex(curRowI.indices[j], actRow.indices);
                        if (diag < 0 || actRow.data[diag] == 0)
                        {
                            diagMod += shift;
                            //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"'
                            goto outer;
                        }

                        // Get multiplier (to be stored in L)
                        double mult = (-curRow[curRowI.indices[j]]) / actRow.data[diag];
                        curRow[curRowI.indices[j]] = -mult;

                        // Reduce everything on the upper diagonal of current row
                        for (int k = diag + 1; k < actRow.indices.Length; ++k)
                        {
                            curRow[actRow.indices[k]] += mult * actRow.data[k];
                        }
                    }

                    // Put updated row back into the factor matrix
                    // We either keep or discard filled in values
                    if (fill)
                    {
                        F.SetRow(i, Blas.Default.Gather(curRow));
                    }
                    else
                    {
                        F.SetRow(i, Blas.Default.Gather(curRowI.indices, curRow));
                    }
                }

                // No errors during factorization
                break;
                //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"'

outer:
                ;
            }
        }
Exemplo n.º 11
0
        protected internal override void Factor()
        {
            double diagMod = initShift;
            int    n       = F.RowCount;

            this.diagInd = new int[n];
            double[] actRow = new double[n];

            //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"'
            while (true)
            {
                // Copy A into F, and ensure non-zero diagonal
                Blas.Default.AddDiagonal(diagMod, Blas.Default.Copy(A, F));

                // Extract the upper triangular part
                for (int i = 0; i < n; ++i)
                {
                    IntDoubleVectorPair curRow = F.GetRow(i);
                    int diagInd = Array.BinarySearch(curRow.indices, i);
                    if (diagInd < 0)
                    {
                        diagMod += shift;
                        //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"'
                        goto outer;
                    }
                    int[]    index = new int[curRow.indices.Length - diagInd];
                    double[] data  = new double[curRow.data.Length - diagInd];
                    Array.Copy(curRow.indices, diagInd, index, 0, index.Length);
                    Array.Copy(curRow.data, diagInd, data, 0, data.Length);
                    F.SetRow(i, new IntDoubleVectorPair(index, data));
                }

                // Factorize
                for (int i = 0; i < n; ++i)
                {
                    // Get current row
                    IntDoubleVectorPair curRow = F.GetRow(i);

                    // We must have positive entries on the diagonal
                    if (curRow.data.Length == 0 || curRow.data[0] <= 0.0)
                    {
                        diagMod += shift;
                        //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"'
                        goto outer;
                    }

                    // Divide by rooted diagonal
                    double diag = curRow.data[0] = Math.Sqrt(curRow.data[0]);
                    for (int j = 1; j < curRow.data.Length; ++j)
                    {
                        curRow.data[j] /= diag;
                    }
                    F.SetRow(i, curRow);

                    // Reduce submatrix using current row
                    for (int j = 1; j < curRow.indices.Length; ++j)
                    {
                        // Active row in dense format
                        IntDoubleVectorPair actRowI = F.GetRow(curRow.indices[j]);
                        actRow = Blas.Default.Scatter(actRowI, actRow);

                        // Reduce active row
                        double factor = curRow.data[j];
                        for (int k = j; k < curRow.data.Length; ++k)
                        {
                            actRow[curRow.indices[k]] -= factor * curRow.data[k];
                        }

                        // Put updated row back into the factor matrix
                        // We either keep or discard filled in values
                        if (fill)
                        {
                            F.SetRow(i, Blas.Default.Gather(actRow));
                        }
                        else
                        {
                            F.SetRow(i, Blas.Default.Gather(actRowI.indices, actRow));
                        }
                    }
                }

                // No errors during factorization
                break;
                //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"'

outer:
                ;
            }
        }
Exemplo n.º 12
0
        protected internal override void SolveI(IMatrix A, double[] eig, IVector[] x)
        {
            // Number of eigenvalues wanted and the maximum factorization size
            int n = eig.Length, m = A.RowCount;

            // Current factorization size, increment, and new size
            int nv = n, inc = 2, nvn = Math.Min(nv * inc, m);

            // These holds the matrix factorization
            IVector[] q = Factory.createVectors(x);
            for (int i = 0; i < nv; ++i)
            {
                q[i] = Blas.Default.Copy(x[i], q[i]);
            }
            double[] alpha = new double[nv], beta = new double[nv];

            // Work-vector
            IVector z = Factory.createVector(q[0]);

            // Initial factorization
            Lanczos(A, q, alpha, beta, z, 0);

            // Compute the eigenvalues, and estimate residuals
            double[] r   = new double[n];
            int[]    ind = new int[n];
            EigenvalueDecomposition evd = new EigenvalueDecomposition(alpha, beta);

            EstimateResidual(nv, beta, evd, r, ind);

            // Continue while not converged or until the factorization is complete
            // Increase the size of the factorization at each iteration
            for (iter.Reset(); !iter.Converged(r, eig, x) && nv < m;
                 iter.MoveNext(), nv = nvn, nvn = Math.Min(nv * inc, m))
            {
                // Allocate more memory for larger factorization
                IVector[] qn     = new IVector[nvn];
                double[]  alphan = new double[nvn], betan = new double[nvn];
                Expand(q, alpha, beta, qn, alphan, betan);
                q     = qn;
                alpha = alphan;
                beta  = betan;

                // Compute larger factorization, starting at previous offset
                Lanczos(A, q, alpha, beta, z, nv - 1);

                // Get eigenvalues and the residuals
                evd = new EigenvalueDecomposition(alpha, beta);
                EstimateResidual(nv, beta, evd, r, ind);

                Console.Error.WriteLine(nvn);
            }

            // Get the eigenvalues (only real)
            double[] eigLoc = evd.RealEigenvalues;
            for (int i = 0; i < eig.Length; ++i)
            {
                eig[i] = eigLoc[ind[i]];
            }

            // Compute the eigenvectors (x=q*V)
            IDenseAccessVector[] qa = new IDenseAccessVector[x.Length],
            xa = new IDenseAccessVector[x.Length];
            for (int i = 0; i < x.Length; ++i)
            {
                qa[i] = (IDenseAccessVector)q[ind[i]];
                xa[i] = (IDenseAccessVector)x[i];
            }
            //Prod(qa, evd.getV(), xa); TODO: clean this
            Prod(qa, evd.EigenVectors, xa);

            // Sort by the eigenvalues
            IntDoubleVectorPair[] s = new IntDoubleVectorPair[eig.Length];
            for (int i = 0; i < s.Length; ++i)
            {
                s[i] = new IntDoubleVectorPair(this, eig[i], i, xa[i]);
            }
            Array.Sort(s);

            // Extract and return
            for (int i = 0; i < s.Length; ++i)
            {
                eig[i] = s[i].d;
                x[i]   = s[i].v;
            }
            et.Eigenvalue(eig);
        }