Exemplo n.º 1
0
        public RowBasedMatrix IncompleteCholesky(double droptol)
        {
            // suppose this matrix is symmetric, square and sorted

            int            n    = this.RowSize;
            int            nAdd = 0;
            RowBasedMatrix L    = new RowBasedMatrix(n);


            for (int i = 0; i < n; i++)
            {
                List <Element> r    = rows[i];
                List <Element> rr1  = L.rows[i];
                double         drop = 0;
                double         norm = 0;
                foreach (Element e in r)
                {
                    norm += e.value * e.value;
                }
                norm = Math.Sqrt(norm) * droptol;

                int k = 0;
                for (int j = 0; j < i; j++)
                {
                    double sum = 0;
                    if (k < r.Count && r[k].colIndex == j)
                    {
                        sum = r[k++].value;
                    }

                    int            c1 = 0, c2 = 0;
                    List <Element> rr2 = L.rows[j];
                    while (c1 < rr1.Count && c2 < rr2.Count)
                    {
                        Element e1 = rr1[c1];
                        Element e2 = rr2[c2];
                        if (e1.colIndex >= j)
                        {
                            break;
                        }
                        if (e2.colIndex >= j)
                        {
                            break;
                        }

                        if (e1.colIndex > e2.colIndex)
                        {
                            c2++;
                        }
                        else if (e1.colIndex < e2.colIndex)
                        {
                            c1++;
                        }
                        else
                        {
                            sum -= e1.value * e2.value;
                            c1++;
                            c2++;
                        }
                    }
                    while (rr2[c2].colIndex < j)
                    {
                        c2++;
                    }
                    sum /= rr2[c2].value;
                    if (Math.Abs(sum) > norm)
                    {
                        rr1.Add(new Element(j, sum)); nAdd++;
                    }
                    else
                    {
                        drop += sum;
                    }
                }

                if (r[k].colIndex != i)
                {
                    throw new Exception();
                }

                double diag = r[k].value;                // + drop;
                for (int c = 0; c < rr1.Count && rr1[c].colIndex < i; c++)
                {
                    diag -= rr1[c].value * rr1[c].value;
                }
                if (diag > 0.0)
                {
                    rr1.Add(new Element(i, Math.Sqrt(diag)));
                }
                else
                {
                    throw new Exception();
                }
            }
            OutputText("drops:" + nAdd.ToString());

            return(L);
        }
Exemplo n.º 2
0
        public void CG_SolveATA(double[] x, double[] b, int maxIter, double eps, int recompute, RowBasedMatrix inv)
        {
            int n    = x.Length;
            int iter = 0;

            double[] r = new double[n];
            double[] d = new double[n];
            double[] q = new double[n];
            double[] s = new double[n];
            double[] t = new double[n];
            double   errNew = 0, errold = 0;

            for (int i = 0; i < n; i++)
            {
                r[i] = b[i];
            }
            for (int i = 0; i < RowSize; i++)
            {
                double sum = 0;
                foreach (Element e in rows[i])
                {
                    sum += e.value * x[e.colIndex];
                }
                foreach (Element e in rows[i])
                {
                    r[e.colIndex] -= e.value * sum;
                }
            }
            inv.Cholesky_Solve(d, r);
            for (int i = 0; i < n; i++)
            {
                errNew += r[i] * d[i];
            }
            double tolerance = eps * errNew;

            OutputText("0:" + errNew.ToString());

            while (iter < maxIter && errNew > tolerance)
            {
                iter++;

                double dAd = 0;

                for (int i = 0; i < n; i++)
                {
                    q[i] = 0;
                }
                for (int i = 0; i < RowSize; i++)
                {
                    double sum = 0;
                    foreach (Element e in rows[i])
                    {
                        sum += e.value * d[e.colIndex];
                    }
                    foreach (Element e in rows[i])
                    {
                        q[e.colIndex] += e.value * sum;
                    }
                }
                for (int i = 0; i < n; i++)
                {
                    dAd += d[i] * q[i];
                }

                double alpha = errNew / dAd;

                for (int i = 0; i < n; i++)
                {
                    x[i] += alpha * d[i];
                }

                if (iter % recompute == 0)
                {
                    for (int i = 0; i < n; i++)
                    {
                        r[i] = b[i];
                    }
                    for (int i = 0; i < RowSize; i++)
                    {
                        double sum = 0;
                        foreach (Element e in rows[i])
                        {
                            sum += e.value * x[e.colIndex];
                        }
                        foreach (Element e in rows[i])
                        {
                            r[e.colIndex] -= e.value * sum;
                        }
                    }
                    OutputText(iter + ":" + errNew.ToString());
                }
                else
                {
                    for (int i = 0; i < n; i++)
                    {
                        r[i] -= alpha * q[i];
                    }
                }

                inv.Cholesky_Solve(s, r);
                errold = errNew;
                errNew = 0;
                for (int i = 0; i < n; i++)
                {
                    errNew += r[i] * s[i];
                }

                double beta = errNew / errold;

                for (int i = 0; i < n; i++)
                {
                    d[i] = s[i] + beta * d[i];
                }
            }

            double err = 0;

            for (int i = 0; i < n; i++)
            {
                err += r[i] * r[i];
            }
            OutputText(iter + ":" + err.ToString());
        }
Exemplo n.º 3
0
        public RowBasedMatrix IncompleteCholesky()
        {
            // suppose this matrix is symmetric, square and sorted

            int            n = this.RowSize;
            RowBasedMatrix L = new RowBasedMatrix(n);


            for (int i = 0; i < n; i++)
            {
                List <Element> r   = rows[i];
                List <Element> rr1 = L.rows[i];
                for (int j = 0; j < r.Count; j++)
                {
                    Element e = r[j];

                    if (e.colIndex == i)
                    {
                        double sum = e.value;
                        for (int c = 0; c < rr1.Count && rr1[c].colIndex < i; c++)
                        {
                            sum -= rr1[c].value * rr1[c].value;
                        }
                        if (sum > 0.0)
                        {
                            rr1.Add(new Element(i, Math.Sqrt(sum)));
                        }
                        else
                        {
                            rr1.Add(new Element(i, 10e-12));
                        }
                    }

                    else if (e.colIndex < i)
                    {
                        List <Element> rr2 = L.rows[e.colIndex];
                        double         sum = e.value;
                        int            c1 = 0, c2 = 0;
                        while (c1 < rr1.Count && c2 < rr2.Count)
                        {
                            Element e1 = rr1[c1];
                            Element e2 = rr2[c2];
                            if (e1.colIndex >= e.colIndex)
                            {
                                break;
                            }
                            if (e2.colIndex >= e.colIndex)
                            {
                                break;
                            }

                            if (e1.colIndex > e2.colIndex)
                            {
                                c2++;
                            }
                            else if (e1.colIndex < e2.colIndex)
                            {
                                c1++;
                            }
                            else
                            {
                                sum -= e1.value * e2.value;
                                c1++;
                                c2++;
                            }
                        }
                        while (rr2[c2].colIndex < e.colIndex)
                        {
                            c2++;
                        }
                        rr1.Add(new Element(e.colIndex, sum / rr2[c2].value));
                    }
                }
            }

            return(L);
        }