utils.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package pb
  2. import "sort"
  3. // ToBurndownSparseMatrix converts a rectangular integer matrix to the corresponding Protobuf object.
  4. // It is specific to hercules.BurndownAnalysis.
  5. func ToBurndownSparseMatrix(matrix [][]int64, name string) *BurndownSparseMatrix {
  6. if len(matrix) == 0 {
  7. panic("matrix may not be nil or empty")
  8. }
  9. r := BurndownSparseMatrix{
  10. Name: name,
  11. NumberOfRows: int32(len(matrix)),
  12. NumberOfColumns: int32(len(matrix[len(matrix)-1])),
  13. Rows: make([]*BurndownSparseMatrixRow, len(matrix)),
  14. }
  15. for i, status := range matrix {
  16. nnz := make([]uint32, 0, len(status))
  17. changed := false
  18. for j := range status {
  19. v := status[len(status)-1-j]
  20. if v < 0 {
  21. v = 0
  22. }
  23. if !changed {
  24. changed = v != 0
  25. }
  26. if changed {
  27. nnz = append(nnz, uint32(v))
  28. }
  29. }
  30. r.Rows[i] = &BurndownSparseMatrixRow{
  31. Columns: make([]uint32, len(nnz)),
  32. }
  33. for j := range nnz {
  34. r.Rows[i].Columns[j] = nnz[len(nnz)-1-j]
  35. }
  36. }
  37. return &r
  38. }
  39. // DenseToCompressedSparseRowMatrix takes an integer matrix and converts it to a Protobuf CSR.
  40. // CSR format: https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_.28CSR.2C_CRS_or_Yale_format.29
  41. func DenseToCompressedSparseRowMatrix(matrix [][]int64) *CompressedSparseRowMatrix {
  42. r := CompressedSparseRowMatrix{
  43. NumberOfRows: int32(len(matrix)),
  44. NumberOfColumns: int32(len(matrix[0])),
  45. Data: make([]int64, 0),
  46. Indices: make([]int32, 0),
  47. Indptr: make([]int64, 1),
  48. }
  49. r.Indptr[0] = 0
  50. for _, row := range matrix {
  51. nnz := 0
  52. for x, col := range row {
  53. if col != 0 {
  54. r.Data = append(r.Data, col)
  55. r.Indices = append(r.Indices, int32(x))
  56. nnz++
  57. }
  58. }
  59. r.Indptr = append(r.Indptr, r.Indptr[len(r.Indptr)-1]+int64(nnz))
  60. }
  61. return &r
  62. }
  63. // MapToCompressedSparseRowMatrix takes an integer matrix and converts it to a Protobuf CSR.
  64. // In contrast to DenseToCompressedSparseRowMatrix, a matrix here is already in DOK format.
  65. // CSR format: https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_.28CSR.2C_CRS_or_Yale_format.29
  66. func MapToCompressedSparseRowMatrix(matrix []map[int]int64) *CompressedSparseRowMatrix {
  67. r := CompressedSparseRowMatrix{
  68. NumberOfRows: int32(len(matrix)),
  69. NumberOfColumns: int32(len(matrix)),
  70. Data: make([]int64, 0),
  71. Indices: make([]int32, 0),
  72. Indptr: make([]int64, 1),
  73. }
  74. r.Indptr[0] = 0
  75. for _, row := range matrix {
  76. order := make([]int, len(row))
  77. i := 0
  78. for col := range row {
  79. order[i] = col
  80. i++
  81. }
  82. sort.Ints(order)
  83. for _, col := range order {
  84. val := row[col]
  85. r.Data = append(r.Data, val)
  86. r.Indices = append(r.Indices, int32(col))
  87. }
  88. r.Indptr = append(r.Indptr, r.Indptr[len(r.Indptr)-1]+int64(len(row)))
  89. }
  90. return &r
  91. }