Skip to contents

Modifies as little as possible the entries of a matrix in order to make them non-negative, keeping row and column totals unchanged.

Usage

make_non_negative(Y, allowSlack = FALSE)

Arguments

Y

Matrix to be positivized.

allowSlack

Can colSums and rowSums be modified?

Value

A non-negative matrix, except if it is impossible to balance the matrix.

Examples

Y <- c(1,2,-1,1,
       2,2,3,1,
       1,1,-2,3) |>
       matrix(nrow = 3)
X <- make_non_negative(Y)
Y
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    1    3    1
#> [2,]    2    2    1   -2
#> [3,]   -1    2    1    3
X |> round(2)
#>      [,1] [,2] [,3] [,4]
#> [1,] 0.97 1.43 3.43 0.17
#> [2,] 1.03 1.49 0.49 0.00
#> [3,] 0.00 2.09 1.09 1.83
rowSums(Y)
#> [1] 6 3 5
rowSums(X)
#> [1] 6 3 5
colSums(Y)
#> [1] 2 5 5 2
colSums(X)
#> [1] 2 5 5 2
set.seed(2)
Y <- rnorm(3*5) |> matrix(3,5) |> round(3)
Y
#>        [,1]   [,2]   [,3]   [,4]   [,5]
#> [1,] -0.897 -1.130  0.708 -0.139 -0.393
#> [2,]  0.185 -0.080 -0.240  0.418 -1.040
#> [3,]  1.588  0.132  1.984  0.982  1.782
tryCatch(make_non_negative(Y), error = function(e) {
  print(e)
})
#> <simpleError in make_non_negative(Y): Optimal solution not found. Solution status: infeasible>
make_non_negative(Y, allowSlack = TRUE) |> round()
#>      [,1] [,2] [,3] [,4] [,5]
#> [1,]    0    0    0    0    0
#> [2,]    0    0    0    0    0
#> [3,]    1    0    2    1    1