utils.go 2.7 KB

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