Base Apply and Elementwise Function CVXR

241 views Asked by At

Is there a way to use base::apply and a CVXR elementwise function to apply an elementwise function to every column of a matrix? Assuming the length of the vector matches the number of rows of the matrix, I'd like to be able to make my objective function the following:

new_matrix <- apply(constant_matrix, 2, function(x) x * variable_vector)
objective <- sum_entries( max_entries( as.matrix(new_matrix), axis = 2 ) )

I get the following error when solving the problem: Error in min(constant) : invalid 'type' (list) of argument

(In case my code is unclear, my goal is to multiply a variable vector by every column of a constant matrix, then get the max of each of those scaled columns, and then sum all of those maxes.)

Thanks!

1

There are 1 answers

2
Balasubramanian Narasimhan On

Below I work out an example using base::apply and element-wise multiplication with CVXR along with the output. For a more involved example, see the Pliable Lasso.

library(CVXR)
library(magrittr)

constant_matrix <- base::matrix(1:20, nrow = 4)
variable_vector <- CVXR::Variable(4, pos = TRUE)

constant_matrix %>%
    base::apply(MARGIN = 2, FUN = function(x) CVXR::multiply(lh_exp = x, rh_exp = variable_vector)) %>%
    base::lapply(max) ->
    column_max_list

objective <- base::Reduce(f = '+', x = column_max_list)
prob <- CVXR::Problem(CVXR::Minimize(objective), constraints = list(variable_vector >= 2))

result  <- CVXR::solve(prob, verbose = TRUE)
result$value
result$getValue(variable_vector)

Here is the output:

-----------------------------------------------------------------
           OSQP v0.6.0  -  Operator Splitting QP Solver
              (c) Bartolomeo Stellato,  Goran Banjac
        University of Oxford  -  Stanford University 2019
-----------------------------------------------------------------
problem:  variables n = 9, constraints m = 28
          nnz(P) + nnz(A) = 48
settings: linear system solver = qdldl,
          eps_abs = 1.0e-05, eps_rel = 1.0e-05,
          eps_prim_inf = 1.0e-04, eps_dual_inf = 1.0e-04,
          rho = 1.00e-01 (adaptive),
          sigma = 1.00e-06, alpha = 1.60, max_iter = 10000
          check_termination: on (interval 25),
          scaling: on, scaled_termination: off
          warm start: on, polish: on, time_limit: off

iter   objective    pri res    dua res    rho        time
   1  -1.0811e+02   1.94e+01   1.56e+01   1.00e-01   6.07e-05s
 200   1.1999e+02   3.92e-04   4.69e-04   1.00e-01   2.31e-04s
 300   1.2000e+02   1.46e-05   2.92e-06   1.00e-01   2.86e-04s

status:               solved
solution polish:      unsuccessful
number of iterations: 300
optimal objective:    120.0005
run time:             3.11e-04s
optimal rho estimate: 3.06e-01

> result$value
[1] 120.0005
> result$getValue(variable_vector)
         [,1]
[1,] 2.248055
[2,] 2.149815
[3,] 2.057720
[4,] 2.000007
`