Beispiel #1
0
        /// <summary>
        /// Adds the specified sparse rows regarding defined multipliers.
        /// </summary>
        /// <param name="a1">The a1.</param>
        /// <param name="a2">The a2.</param>
        /// <param name="a1Coef">The a1 coef.</param>
        /// <param name="a2Coef">The a2 coef.</param>
        /// <returns> a1 * a1Coef + a2 * a2Coef</returns>
        public static SparseRow Add(SparseRow a1, SparseRow a2, double a1Coef, double a2Coef)
        {
            var buf = new SparseRow(a2.Size + a1.Size);

            //based on https://stackoverflow.com/a/12993675/1106889
            //result = a1 * a1Coef + a2 * a2Coef;

            var c1 = 0;
            var c2 = 0;

            var i1s = a1.Indexes;
            var v1s = a1.Values;
            var l1  = a1.Size;

            var i2s = a2.Indexes;
            var v2s = a2.Values;
            var l2  = a2.Size;


            while (c1 < l1 && c2 < l2)
            {
                var i1 = i1s[c1];
                var i2 = i2s[c2];

                var v1 = v1s[c1];
                var v2 = v2s[c2];

                if (i1 > i2)
                {
                    buf.Add(i2 /*or i1*/, v2 * a2Coef);
                    c2++;
                }
                else if (i1 < i2)
                {
                    buf.Add(i1, v1 * a1Coef);
                    c1++;
                }
                else
                {//common
                    var newValue = v1 * a1Coef + v2 * a2Coef;

                    buf.Add(i1, newValue);

                    c1++;
                    c2++;
                }
            }

            return(buf);
        }
            public static SparseRow From(int[] columns, double[] values)
            {
                Array.Sort(columns, values);
                Array.Sort(columns);

                var buf = new SparseRow();

                buf.Columns    = new List <int>(columns);
                buf.Values     = new List <double>(values);
                buf.NextMember = new List <int>(Enumerable.Range(0, columns.Length).Select(i => i + 1));
                buf.NextMember[buf.NextMember.Count - 1] = -1;
                buf.Head = 0;

                return(buf);
            }
            /// <summary>
            /// Adds the addition into the target
            /// </summary>
            /// <param name="target"></param>
            /// <param name="addition"></param>
            /// <param name="factor"></param>
            public static void Add(SparseRow target, SparseRow addition, double factor)
            {
                var it = target.Head;
                var ia = addition.Head;

                while (true)
                {
                    var c1 = target.Columns[it];
                    var c2 = addition.Columns[ia];

                    while (c2 < c1)
                    {
                    }


                    it = target.NextMember[it];
                }

                throw new NotImplementedException();
            }
Beispiel #4
0
        public CCS CalculateRref(CCS a)
        {
            var sys = SparseEqSystem.Generate((CSparse.Double.CompressedColumnStorage)a);

            var dns = a.ToDenseMatrix();

            sys.RowsPool = new SortedSet <SparseRow>();

            var eqs = sys.Equations;

            for (var i = 0; i < sys.Equations.Length; i++)
            {
                sys.Equations[i].Tag = i;
            }

            var lastColIndex = a.ColumnCount - 1;

            //should have n columns with one nonzero

            //var colPivotHistory = new HashSet<int>();
            //var rowPivotHistory = new HashSet<int>();
            var dependentRows = new bool[sys.RowCount];// HashSet<int>();
            var leadingMember = new bool[sys.RowCount];


            //var pivotedYet = new bool[a.RowCount];

            for (var i = 0; i < sys.Equations.Length; i++)
            {
                foreach (var tuple in sys.Equations[i].EnumerateIndexed())
                {
                    if (sys.ColumnNonzeros[tuple.Item1] == 1)
                    {
                        leadingMember[i] = true;
                    }
                }
            }


            var maxItter = Math.Max(a.ColumnCount, a.RowCount);

            var itter = 0;

            while (itter++ < maxItter)
            {
                //find count
                var oneNnzCols = sys.ColumnNonzeros.Count(i => i == 1);

                var eqNeeded = Math.Min(a.ColumnCount - 1, a.RowCount - dependentRows.Count(i => i == true));


                if (oneNnzCols == eqNeeded)
                {
                    break;
                }

                //select pivot
                //minimum row nnz x col nnz
                //select row strategy: row with minimum nnz, where nnz is nonzero count except last column (right side) and nnz > 1


                var minRowNnz      = int.MaxValue; // sys.RowNonzeros.Where(i => i > 1).Min();
                var minRowNnzIndex = -1;           // sys.RowNonzeros.FirstIndexOf(minRowNnz);

                {
                    for (var j = 0; j < sys.RowCount; j++)
                    {
                        if (leadingMember[j])
                        {
                            continue;
                        }

                        if (dependentRows[j])
                        {
                            continue;
                        }


                        //if (sys.RowNonzeros[j] <= 1)
                        //    continue;

                        if (sys.RowNonzeros[j] < minRowNnz)
                        {
                            minRowNnzIndex = j;
                            minRowNnz      = sys.RowNonzeros[j];
                        }
                    }
                }

                if (minRowNnzIndex == -1)
                {
                    throw new Exception();
                }


                //var minColNnz = sys.ColumnNonzeros.Where(i => i > 1).Min();
                var minColNnz      = int.MaxValue;// sys.ColumnNonzeros.Where(i => i > 1).Min();
                var minColNnzIndex = -1;


                {
                    for (var jj = 0; jj < sys.Equations[minRowNnzIndex].Size; jj++)
                    {
                        var j = sys.Equations[minRowNnzIndex].Indexes[jj];

                        //if (colPivotHistory.Contains(j))
                        //    continue;

                        if (sys.ColumnNonzeros[j] <= 1)
                        {
                            continue;
                        }

                        if (sys.ColumnNonzeros[j] < minColNnz)
                        {
                            minColNnzIndex = j;
                            minColNnz      = sys.ColumnNonzeros[j];
                        }
                    }
                }

                //var minColNnzIndex = sys.ColumnNonzeros.FirstIndexOf(minColNnz);



                if (minColNnzIndex == -1)
                {
                    //var t = sys.ToCcs().ToDenseMatrix();

                    throw new Exception();
                }

                var col = minColNnzIndex;


                var c1 = sys.Equations.Where(i => i.ContainsIndex(col) && !leadingMember[i.Tag]);

                var rw =
                    c1.MinBy(j => j.Size, null);
                //sys.Equations[minRowNnzIndex];

                if (dependentRows[sys.Equations.IndexOfReference(rw)])
                {
                    throw new Exception();
                }

                Console.WriteLine("Pivot: {0},{1}", sys.Equations.IndexOfReference(rw), col);

                //Console.ReadKey();
                // eqs.Equations.Where(i => i.Size > 1).MinBy(new SparseRowLengthComparer());

                var eliminator = rw;// sys.Equations[rw];

                //eliminate all rows with pivot
                for (var i = 0; i < sys.Equations.Length; i++)
                {
                    var canditate = eqs[i];

                    if (canditate.ContainsIndex(col) && !ReferenceEquals(eliminator, canditate))
                    {
                        var oldOne = eqs[i];//to be removed

                        foreach (var enm in oldOne.EnumerateIndexed())
                        {
                            sys.ColumnNonzeros[enm.Item1]--;
                        }

                        var newOne = SparseRow.Eliminate(eliminator, oldOne, col);

                        if (newOne.CalcNnz(lastColIndex) == 0 && newOne.GetRightSideValue(lastColIndex) != 0)
                        {
                            throw new Exception("Inconsistent system");
                        }

                        if (newOne.CalcNnz(lastColIndex) == 0 && newOne.GetRightSideValue(lastColIndex) == 0)
                        {
                            //fully zero equation
                            dependentRows[i] = true;// newOne.Tag);
                        }



                        newOne.Tag = oldOne.Tag;

                        foreach (var enm in newOne.EnumerateIndexed())
                        {
                            sys.ColumnNonzeros[enm.Item1]++;

                            if (sys.ColumnNonzeros[enm.Item1] == 1)
                            {
                                leadingMember[i] = true;
                            }
                        }


                        if (sys.ColumnNonzeros.Contains(0))
                        {
                            Guid.NewGuid();
                        }

                        eqs[i] = newOne;

                        sys.RowNonzeros[i] = newOne.CalcNnz(lastColIndex);
                    }
                }

                leadingMember[sys.Equations.IndexOfReference(rw)] = true;

                Console.WriteLine("elimination done for all eqs, Col[{0}] : {1} nnzs", col, sys.ColumnNonzeros[col]);

                if (sys.ColumnNonzeros[col] != 1)
                {
                    Guid.NewGuid();
                }
            }

            SparseEqSystem newSys;// = new SparseEqSystem();

            {
                ////////start final check

                var tol = 1e-9;

                var dependentEquationCount   = sys.Equations.Count(i => i.CalcNnz(lastColIndex) == 0 && i.GetRightSideValue(lastColIndex).FEquals(0, tol));
                var incosistentEquationCount = sys.Equations.Count(i => i.CalcNnz(lastColIndex) == 0 && !i.GetRightSideValue(lastColIndex).FEquals(0, tol));
                var NnzMemberInCol           = new int[sys.ColumnCount - 1];

                foreach (var eq in sys.Equations)
                {
                    foreach (var idx in eq.EnumerateIndexed())
                    {
                        if (idx.Item1 != lastColIndex)
                        {
                            if (!idx.Item2.FEquals(0, tol))
                            {
                                NnzMemberInCol[idx.Item1]++;
                            }
                        }
                    }
                }

                var leadingMembers = NnzMemberInCol.Count(i => i == 1);

                if (leadingMembers != Math.Min(sys.ColumnCount - 1, sys.RowCount - dependentEquationCount))
                {
                    throw new Exception();
                }

                if (incosistentEquationCount != 0)
                {
                    throw new Exception();
                }

                var allExceptDependentEqs = sys.Equations.Where(i => !(i.CalcNnz(lastColIndex) == 0 && i.GetRightSideValue(lastColIndex).FEquals(0, tol))).ToArray();

                newSys = SparseEqSystem.Generate(allExceptDependentEqs, a.ColumnCount);
            }

            return(newSys.ToCcs());
        }
Beispiel #5
0
        /// <summary>
        /// Eliminates the specified index of <see cref="eliminated"/> row by adding appropriated multiply of <see cref="eliminator"/> to it.
        /// </summary>
        /// <param name="eliminator">The eliminator row.</param>
        /// <param name="eliminated">The eliminated row.</param>
        /// <param name="eliminateIndex">The index of eliminated member.</param>
        /// <returns>Eliminated version of <see cref="eliminated"/></returns>
        public static SparseRow Eliminate(SparseRow eliminator, SparseRow eliminated, int eliminateIndex, double epsilon = 0)
        {
            var buf = new SparseRow(eliminated.Size + eliminator.Size);

            //based on https://stackoverflow.com/a/12993675/1106889
            //result = eliminator * coef + eliminated

            double coef;

            {
                var t1 = Array.BinarySearch(eliminator.Indexes, 0, eliminator.Size, eliminateIndex);
                var t2 = Array.BinarySearch(eliminated.Indexes, 0, eliminated.Size, eliminateIndex);

                if (t1 < 0 || t2 < 0)
                {
                    throw new Exception();
                }

                coef = -eliminated.Values[t2] / eliminator.Values[t1];
            }

            var c1 = 0;
            var c2 = 0;

            var i1s = eliminator.Indexes;
            var v1s = eliminator.Values;
            var l1  = eliminator.Size;

            var i2s = eliminated.Indexes;
            var v2s = eliminated.Values;
            var l2  = eliminated.Size;


            while (c1 < l1 && c2 < l2)
            {
                var i1 = i1s[c1];
                var i2 = i2s[c2];

                var v1 = v1s[c1];
                var v2 = v2s[c2];

                if (i1 > i2)
                {
                    buf.Add(i2 /*or i1*/, v2);
                    c2++;
                }
                else if (i1 < i2)
                {
                    buf.Add(i1, v1 * coef);
                    c1++;
                }
                else
                {//common
                    if (i1 != i2)
                    {
                        throw new Exception();
                    }

                    var newValue = v1 * coef + v2;

                    if (i1 == eliminateIndex || Math.Abs(newValue) < epsilon)
                    {
                        //this is eliminated item, newValue should be zero and nothing to add
                        if (Math.Abs(newValue) > 1e-6)
                        {
                            throw new Exception("wrong result");
                        }
                    }
                    else
                    {
                        buf.Add(i1, newValue);
                    }

                    c1++;
                    c2++;
                }
            }


            //tail
            {
                for (; c1 < l1; c1++)
                {
                    var i1 = i1s[c1];
                    var v1 = v1s[c1];

                    buf.Add(i1, v1 * coef);
                }

                for (; c2 < l2; c2++)
                {
                    var i2 = i2s[c2];
                    var v2 = v2s[c2];

                    buf.Add(i2, v2);
                }
            }



            return(buf);
        }