예제 #1
0
 public static IEnumerable <int> GetColWeights(IBitMatrix matrix)
 {
     for (int col = 0; col < matrix.Cols; col++)
     {
         yield return(matrix.GetColWeight(col));
     }
 }
        private IBitMatrix CompactMatrix()
        {
            var deletedRows = new bool[matrix.Rows];
            var deletedCols = new bool[matrix.Cols];

            ancestors = new Ancestor[matrix.Cols];
            for (int i = 0; i < matrix.Cols; i++)
            {
                ancestors[i] = new Ancestor {
                    Column = i
                }
            }
            ;
            if (diagnostics)
            {
                Console.WriteLine("initial density = {0:F3}/col", (double)matrix.GetRowWeights().Sum() / matrix.Rows);
            }

            int surplusCols = 0;
            int pass        = 1;

            while (true)
            {
                int deleted = 0;
                for (int n = matrix.Rows - 1; n >= 0; n--)
                {
                    if (deletedRows[n])
                    {
                        continue;
                    }
                    var weight = matrix.GetRowWeight(n);

                    // Delete entirely empty rows.
                    if (weight == 0)
                    {
                        deletedRows[n] = true;
                        ++surplusCols;
                        ++deleted;
                        continue;
                    }

                    // Delete rows with a single non-zero entry.
                    if (weight == 1)
                    {
                        var col = matrix.GetNonZeroCols(n).First();
                        deletedRows[n] = true;
                        MergeColumns(col);
                        deletedCols[col] = true;
                        ++deleted;
                        continue;
                    }

                    // Use surplus rows to bring weight down to merge limit.
                    int limit = Math.Min(pass, mergeLimit);
                    if (weight > limit && surplusCols > 0 && weight - surplusCols <= limit)
                    {
                        while (weight > limit)
                        {
                            var col = matrix.GetNonZeroCols(n)
                                      .OrderByDescending(index => matrix.GetColWeight(index))
                                      .First();
                            MergeColumns(col);
                            deletedCols[col] = true;
                            ++deleted;
                            --surplusCols;
                            --weight;
                        }
                    }

                    // Merge low weight rows.
                    if (weight <= limit)
                    {
                        var cols = matrix.GetNonZeroCols(n)
                                   .OrderByDescending(index => matrix.GetColWeight(index))
                                   .ToArray();
                        Debug.Assert(cols.Length == weight);
                        var srcCol = cols[0];
                        MergeColumns(cols);
                        for (var ancestor = ancestors[srcCol]; ancestor != null; ancestor = ancestor.Next)
                        {
                            for (int j = 1; j < weight; j++)
                            {
                                ancestors[cols[j]] = new Ancestor {
                                    Column = ancestor.Column, Next = ancestors[cols[j]]
                                }
                            }
                            ;
                        }
                        deletedRows[n]      = true;
                        ancestors[srcCol]   = null;
                        deletedCols[srcCol] = true;
                        ++deleted;
                        continue;
                    }
                }

                if (diagnostics)
                {
                    Console.WriteLine("pass {0}: deleted {1} rows", pass, deleted);
                }
                if (deleted == 0)
                {
                    break;
                }
                ++pass;
            }

            // Compute mapping between original matrix and compact matrix.
            ancestors = deletedCols
                        .Select((deleted, index) => deleted ? null : ancestors[index])
                        .Where(ancestor => ancestor != null)
                        .ToArray();
            var rowMap = deletedRows
                         .Select((deleted, index) => deleted ? -1 : index)
                         .Where(index => index != -1)
                         .ToArray();
            var colMap = deletedCols
                         .Select((deleted, index) => deleted ? -1 : index)
                         .Where(index => index != -1)
                         .ToArray();

            // Permute columns to sort by increasing column weight.
            var order = Enumerable.Range(0, colMap.Length)
                        .OrderBy(index => matrix.GetColWeight(colMap[index]))
                        .ToArray();

            ancestors = Enumerable.Range(0, colMap.Length)
                        .Select(index => ancestors[order[index]])
                        .ToArray();
            colMap = Enumerable.Range(0, colMap.Length)
                     .Select(index => colMap[order[index]])
                     .ToArray();

            // Create compact matrix.
            var revColMap = new int[matrix.Cols];

            for (int i = 0; i < colMap.Length; i++)
            {
                revColMap[colMap[i]] = i;
            }
            var compactMatrix = (IBitMatrix)Activator.CreateInstance(typeof(TMatrix), rowMap.Length, colMap.Length);

            for (int i = 0; i < rowMap.Length; i++)
            {
                int row = rowMap[i];
                foreach (var col in matrix.GetNonZeroCols(row))
                {
                    compactMatrix[i, revColMap[col]] = true;
                }
            }

            if (diagnostics)
            {
                Console.WriteLine("completed compaction in {0} passes", pass);
                Console.WriteLine("final density = {0:F3}/col", (double)matrix.GetRowWeights().Sum() / compactMatrix.Rows);
            }

            return(compactMatrix);
        }
예제 #3
0
 public static IEnumerable<int> GetColWeights(IBitMatrix matrix)
 {
     for (int col = 0; col < matrix.Cols; col++)
         yield return matrix.GetColWeight(col);
 }