context("test-g01-problem") TOL <- 1e-6 a <- Variable(name = "a") b <- Variable(name = "b") c <- Variable(name = "c") x <- Variable(2, name = "x") y <- Variable(3, name = "y") z <- Variable(2, name = "z") A <- Variable(2, 2, name = "A") B <- Variable(2, 2, name = "B") C <- Variable(3, 2, name = "C") ConicSolver <- CVXR:::ConicSolver INSTALLED_SOLVERS <- installed_solvers() SCS.dims_to_solver_dict <- CVXR:::SCS.dims_to_solver_dict ECOS.dims_to_solver_dict <- CVXR:::ECOS.dims_to_solver_dict .p_norm <- CVXR:::.p_norm test_that("test the variables method", { skip_on_cran() p <- Problem(Minimize(a), list(a <= x, b <= A + 2)) vars_ <- variables(p) ref <- list(a, x, b, A) mapply(function(v, r) { expect_equal(v, r) }, vars_, ref) }) test_that("test the parameters method", { skip_on_cran() p1 <- Parameter() p2 <- Parameter(3, nonpos = TRUE) p3 <- Parameter(4, 4, nonneg = TRUE) p <- Problem(Minimize(p1), list(a + p1 <= p2, b <= p3 + p3 + 2)) params <- parameters(p) ref <- c(p1, p2, p3) mapply(function(p, r) { expect_equal(p, r) }, params, ref) }) test_that("test the constants method", { skip_on_cran() c1 <- matrix(stats::rnorm(2), nrow = 1, ncol = 2) c2 <- matrix(stats::rnorm(2), nrow = 2, ncol = 1) p <- Problem(Minimize(c1 %*% x), list(x >= c2)) constants_ <- constants(p) ref <- list(c1, c2) expect_equal(length(constants_), length(ref)) mapply(function(c, r) { expect_equal(dim(c), dim(r)) expect_true(all(value(c) == r)) }, constants_, ref) # Single scalar constants p <- Problem(Minimize(a), list(x >= 1)) constants_ <- constants(p) ref <- list(matrix(1)) expect_equal(length(ref), length(constants_)) mapply(function(c, r) { expect_equal(dim(c), dim(r)) expect_true(all(value(c) == r)) }, constants_, ref) }) test_that("Test the size_metrics method", { skip_on_cran() p1 <- Parameter() p2 <- Parameter(3, nonpos = TRUE) p3 <- Parameter(4, 4, nonneg = TRUE) c1 <- matrix(stats::rnorm(2), nrow = 2, ncol = 1) c2 <- matrix(stats::rnorm(2), nrow = 1, ncol = 2) constants <- c(2, as.numeric(c2 %*% c1)) p <- Problem(Minimize(p1), list(a + p1 <= p2, b <= p3 + p3 + constants[1], c == constants[2])) # num_scalar variables n_variables <- size_metrics(p)@num_scalar_variables ref <- size(a) + size(b) + size(c) expect_equal(n_variables, ref) # num_scalar_data n_data <- size_metrics(p)@num_scalar_data ref <- size(p1) + size(p2) + size(p3) + length(constants) # 2 and c2 %*% c1 are both single scalar constants expect_equal(n_data, ref) # num_scalar_eq_constr n_eq_constr <- size_metrics(p)@num_scalar_eq_constr ref <- prod(dim(c2 %*% c1)) expect_equal(n_eq_constr, ref) # num_scalar_leq_constr n_leq_constr <- size_metrics(p)@num_scalar_leq_constr ref <- size(p3) + size(p2) expect_equal(n_leq_constr, ref) # max_data_dimension max_data_dim <- size_metrics(p)@max_data_dimension ref <- max(dim(p3)) expect_equal(max_data_dim, ref) }) test_that("Test the solver_stats method", { skip_on_cran() prob <- Problem(Minimize(p_norm(x)), list(x == 0)) result <- solve(prob, solver = "ECOS") expect_true(result$solve_time > 0) expect_true(result$setup_time > 0) expect_true(result$num_iters > 0) }) test_that("Test the get_problem_data method", { skip_on_cran() data <- get_problem_data(Problem(Minimize(exp(a) + 2)), "SCS")[[1]] dims <- data[[ConicSolver()@dims]] expect_equal(dims@exp, 1) expect_equal(length(data[["c"]]), 2) expect_equal(dim(data[["A"]]), c(3,2)) data <- get_problem_data(Problem(Minimize(p_norm(x) + 3)), "ECOS")[[1]] dims <- data[[ConicSolver()@dims]] expect_equal(dims@soc, list(3)) expect_equal(length(data[["c"]]), 3) expect_equal(dim(data[["A"]]), c(0,0)) expect_equal(dim(data[["G"]]), c(3,3)) if("CVXOPT" %in% INSTALLED_SOLVERS) { data <- get_problem_data(Problem(Minimize(p_norm(x) + 3)), "CVXOPT")[[1]] dims <- data[["dims"]] expect_equal(dims@soc, list(3)) # TODO: We cannot test whether the coefficients or offsets were correctly parsed until we update the CVXOPT interface. } }) test_that("Test unpack results method", { skip_on_cran() prob <- Problem(Minimize(exp(a)), list(a == 0)) tmp <- get_problem_data(prob, solver = "SCS") args <- tmp[[1]] chain <- tmp[[2]] inv <- tmp[[3]] data <- list(c = args[["c"]], A = args[["A"]], b = args[["b"]]) cones <- SCS.dims_to_solver_dict(args[[ConicSolver()@dims]]) solution <- scs::scs(A = data$A, b = data$b, obj = data$c, cone = cones) prob <- Problem(Minimize(exp(a)), list(a == 0)) result <- unpack_results(prob, solution, chain, inv) expect_equal(result$getValue(a), 0, tolerance = 1e-3) expect_equal(result$value, 1, tolerance = 1e-3) expect_equal(result$status, "optimal") prob <- Problem(Minimize(p_norm(x)), list(x == 0)) tmp <- get_problem_data(prob, solver = "ECOS") args <- tmp[[1]] chain <- tmp[[2]] inv <- tmp[[3]] cones <- ECOS.dims_to_solver_dict(args[[ConicSolver()@dims]]) solution <- ECOSolveR::ECOS_csolve(args[["c"]], args[["G"]], args[["h"]], cones, args[["A"]], args[["b"]]) prob <- Problem(Minimize(p_norm(x)), list(x == 0)) result <- unpack_results(prob, solution, chain, inv) expect_equal(result$getValue(x), matrix(c(0,0))) expect_equal(result$value, 0) expect_equal(result$status, "optimal") }) # test_that("Test silencing and enabling solver messages", { # }) # test_that("Test registering other solve methods", { # Problem.register_solve("test", function(self) { 1 }) # p <- Problem(Minimize(1)) # result <- solve(p, method = "test") # expect_equal(result$value, 1) # # test <- function(self, a, b = 2) { c(a, b) } # Problem.register_solve("test", test) # p <- Problem(Minimize(0)) # result <- solve(p, 1, b = 3, method = "test") # expect_equal(result$value, c(1,3)) # result <- solve(p, 1, method = "test") # expect_equal(result$value, c(1,2)) # result <- solve(p, 1, method = "test", b = 4) # expect_equal(result$value, c(1,4)) # }) # TODO: Adapt this test to the reduction infrastructure. # test_that("Test that variables and constraints keep a consistent order", { # num_solves <- 4 # vars_lists <- list() # ineqs_lists <- list() # var_ids_order_created <- list() # for(k in 1:num_solves) { # sum <- 0 # constraints <- list() # var_ids <- c() # for(i in 1:100) { # var <- Variable(name = as.character(i)) # var_ids <- c(var_ids, var@id) # sum <- sum + var # constraints <- c(constraints, list(var >= i)) # } # var_ids_order_created <- c(var_ids_order_created, list(var_ids)) # obj <- Minimize(sum) # p <- Problem(obj, constraints) # canon <- canonicalize(p) # objective <- canon[[1]] # constraints <- canon[[2]] # sym_data <- SymData(objective, constraints, ECOS()) # # # Sort by offset # offsets <- sym_data@.var_offsets # vars_ <- as.numeric(names(sort(offsets, decreasing = FALSE))) # vars_lists <- c(vars_lists, list(vars_)) # ineqs_lists <- c(ineqs_lists, list(sym_data@.constr_map[[LEQ_MAP]])) # } # # # Verify order of variables is consistent # for(i in 1:num_solves) # expect_equal(var_ids_order_created[[i]], vars_lists[[i]]) # # for(i in 1:num_solves) { # idx <- 1 # for(constr in ineqs_lists[[i]]) { # var_tmp <- get_expr_vars(constr$expr)[[1]] # var_id <- as.numeric(var_tmp[[1]]) # expect_equal(var_ids_order_created[[i]][idx], var_id) # idx <- idx + 1 # } # } # }) # TODO: Adapt this test to the reduction infrastructure. # test_that("Test removing duplicate constraints objects", { # eq <- (x == 2) # le <- (x <= 2) # obj <- 0 # # test <- function(self) { # canon <- canonicalize(self) # objective <- canon[[1]] # constraints <- canon[[2]] # sym_data <- SymData(objective, constraints) # list(length(sym_data@constr_map[EQ_MAP]), length(sym_data@constr_map[LEQ_MAP])) # } # # Problem.register_solve("test", test) # # p <- Problem(Minimize(obj), list(eq, eq, le, le)) # # result <- solve(p, method = "test") # # expect_equal(result$value, c(1,1)) # # # Internal constraints # X <- Semidef(2) # obj <- sum_entries(X + X) # p <- Problem(Minimize(obj)) # # result <- solve(p, method = "test") # # expect_equal(result$value, c(0,1)) # # # Duplicates from non-linear constraints # # exp <- norm(x, "2") # # prob <- Problem(Minimize(0), list(exp <= 1, exp <= 2)) # # result <- solve(prob, method = "test") # # expect_equal(result$value, c(0,4)) # }) test_that("test the is_dcp method", { skip_on_cran() p <- Problem(Minimize(norm_inf(a))) expect_true(is_dcp(p)) p <- Problem(Maximize(norm_inf(a))) expect_false(is_dcp(p)) expect_error(solve(p)) }) test_that("test the is_qp method", { skip_on_cran() A <- matrix(rnorm(4*3), nrow = 4, ncol = 3) b <- matrix(rnorm(4), nrow = 4) Aeq <- matrix(rnorm(2*3), nrow = 2, ncol = 3) beq <- matrix(rnorm(2), nrow = 2, ncol = 1) Fmat <- matrix(rnorm(2*3), nrow = 2, ncol = 3) g <- matrix(rnorm(2), nrow = 2, ncol = 1) obj <- sum_squares(A %*% y - b) qpwa_obj <- 3*sum_squares(-abs(A %*% y)) + quad_over_lin(max_elemwise(abs(A %*% y), rep(3, 4)), 2) not_qpwa_obj <- 3*sum_squares(abs(A %*% y)) + quad_over_lin(min_elemwise(abs(A %*% y), rep(3, 4)), 2) p <- Problem(Minimize(obj), list()) expect_true(is_qp(p)) p <- Problem(Minimize(qpwa_obj), list()) expect_true(is_qp(p)) p <- Problem(Minimize(not_qpwa_obj), list()) expect_false(is_qp(p)) p <- Problem(Minimize(obj), list(Aeq %*% y == beq, Fmat %*% y <= g)) expect_true(is_qp(p)) p <- Problem(Minimize(obj), list(max_elemwise(1, 3*y) <= 200, abs(2*y) <= 100, p_norm(2*y, 1) <= 1000, Aeq %*% y == beq)) expect_true(is_qp(p)) p <- Problem(Minimize(qpwa_obj), list(max_elemwise(1, 3*y) <= 200, abs(2*y) <= 100, p_norm(2*y, 1) <= 1000, Aeq %*% y == beq)) expect_true(is_qp(p)) p <- Problem(Minimize(obj), list(max_elemwise(1, 3*y^2) <= 200)) expect_false(is_qp(p)) p <- Problem(Minimize(qpwa_obj), list(max_elemwise(1, 3*y^2) <= 200)) expect_false(is_qp(p)) }) test_that("test problems involving variables with the same name", { skip_on_cran() var <- Variable(name = "a") p <- Problem(Maximize(a + var), list(var == 2 + a, var <= 3)) result <- solve(p) expect_equal(result$value, 4.0, tolerance = TOL) expect_equal(result$getValue(a), 1, tolerance = TOL) expect_equal(result$getValue(var), 3, tolerance = TOL) }) test_that("test adding problems", { skip_on_cran() prob1 <- Problem(Minimize(a), list(a >= b)) prob2 <- Problem(Minimize(2*b), list(a >= 1, b >= 2)) prob_minimize <- prob1 + prob2 expect_equal(length(prob_minimize@constraints), 3) result <- solve(prob_minimize) expect_equal(result$value, 6, tolerance = TOL) prob3 <- Problem(Maximize(a), list(b <= 1)) prob4 <- Problem(Maximize(2*b), list(a <= 2)) prob_maximize <- prob3 + prob4 expect_equal(length(prob_maximize@constraints), 2) result <- solve(prob_maximize) expect_equal(result$value, 4, tolerance = TOL) # Test using the sum function prob5 <- Problem(Minimize(3*a)) prob_sum <- Reduce("+", list(prob1, prob2, prob5)) expect_equal(length(prob_sum@constraints), 3) result <- solve(prob_sum) expect_equal(result$value, 12, tolerance = TOL) prob_sum <- Reduce("+", list(prob1)) expect_equal(length(prob_sum@constraints), 1) # Test Minimize + Maximize expect_error(prob_bad_sum <- prob1 + prob3, "Problem does not follow DCP rules") }) test_that("test problem multiplication by scalar", { skip_on_cran() prob1 <- Problem(Minimize(a^2), list(a >= 2)) answer <- solve(prob1)$value factors <- c(0, 1, 2.3, -4.321) for(f in factors) { expect_equal(solve(f * prob1)$value, f * answer, tolerance = TOL) expect_equal(solve(prob1 * f)$value, f * answer, tolerance = TOL) } }) test_that("test problem linear combinations", { skip_on_cran() prob1 <- Problem(Minimize(a), list(a >= b)) prob2 <- Problem(Minimize(2*b), list(a >= 1, b >= 2)) prob3 <- Problem(Maximize(-(b + a)^2), list(b >= 3)) # Simple addition and multiplication. combo1 <- prob1 + 2 * prob2 combo1_ref <- Problem(Minimize(a + 4*b), list(a >= b, a >= 1, b >= 2)) expect_equal(solve(combo1)$value, solve(combo1_ref)$value) # Division and subtraction. combo2 <- prob1 - prob3/2 combo2_ref <- Problem(Minimize(a + (b + a)^2/2), list(b >= 3, a >= b)) expect_equal(solve(combo2)$value, solve(combo2_ref)$value) # Multiplication with 0 (prob2's constraints should still hold). combo3 <- prob1 + 0*prob2 - 3*prob3 combo3_ref <- Problem(Minimize(a + 3*(b + a)^2), list(a >= b, a >= 1, b >= 3)) expect_equal(solve(combo3)$value, solve(combo3_ref)$value, tolerance = TOL) }) # test_that("test solving problems in parallel", { # p <- Parameter() # problem <- Problem(Minimize(a^2 + b^2 + p), list(b >= 2, a >= 1)) # value(p) <- 1 # # # Ensure that parallel solver still works after repeated calls # for(i in 1:2) { # result <- solve(problem, parallel = TRUE) # expect_equal(result$value, 6.0, tolerance = TOL) # expect_equal(result$status, "optimal") # expect_equal(result$getValue(a), 1, tolerance = TOL) # expect_equal(result$getValue(b), 2, tolerance = TOL) # } # # # The constant p should not be a separate problem, but rather added to the first separable problem # expect_true(length(problem@.separable_problems) == 2) # # # Ensure that parallel solver works with options # result <- solve(problem, parallel = TRUE, verbose = TRUE, warm_start = TRUE) # expect_equal(result$value, 6.0, tolerance = TOL) # expect_equal(result$status, "optimal") # expect_equal(result$getValue(a), 1, tolerance = TOL) # expect_equal(result$getValue(b), 2, tolerance = TOL) # # # Ensure that parallel solver works when problem changes # objective <- Minimize(a^2 + b^2) # problem <- Problem(objective, problem@constraints) # result <- solve(problem, parallel = TRUE) # expect_equal(result$value, 5.0, tolerance = TOL) # expect_equal(result$status, "optimal") # expect_equal(result$getValue(a), 1, tolerance = TOL) # expect_equal(result$getValue(b), 2, tolerance = TOL) # }) test_that("Test scalar LP problems", { skip_on_cran() p <- Problem(Minimize(3*a), list(a >= 2)) result <- solve(p) expect_equal(result$value, 6, tolerance = TOL) expect_equal(result$getValue(a), 2, tolerance = TOL) p <- Problem(Maximize(3*a - b), list(a <= 2, b == a, b <= 5)) result <- solve(p) expect_equal(result$value, 4.0, tolerance = TOL) expect_equal(result$getValue(a), 2, tolerance = TOL) expect_equal(result$getValue(b), 2, tolerance = TOL) # With a constant in the objective p <- Problem(Minimize(3*a - b + 100), list(a >= 2, b + 5*c - 2 == a, b <= 5 + c)) result <- solve(p) expect_equal(result$value, 101+1.0/6, tolerance = TOL) expect_equal(result$getValue(a), 2, tolerance = TOL) expect_equal(result$getValue(b), 5-1.0/6, tolerance = TOL) expect_equal(result$getValue(c), -1.0/6, tolerance = TOL) # Test status and value exp <- Maximize(a) p <- Problem(exp, list(a <= 2)) result <- solve(p, solver = "ECOS") # expect_equal(result$value, value(p)) expect_equal(result$status, "optimal") expect_false(is.na(result$getValue(a))) expect_false(is.na(result$getDualValue(p@constraints[[1]]))) # Unbounded problems p <- Problem(Maximize(a), list(a >= 2)) result <- solve(p, solver = "ECOS") expect_equal(result$value, Inf) expect_true(is.na(result$getValue(a))) expect_true(is.na(result$getDualValue(p@constraints[[1]]))) if("CVXOPT" %in% INSTALLED_SOLVERS) { p <- Problem(Minimize(-a), list(a >= 2)) result <- solve(p, solver = "CVXOPT") # expect_equal(result$value, value(p)) expect_equal(result$status, "unbounded") expect_equal(result$value, -Inf) } # Infeasible problems p <- Problem(Maximize(a), list(a >= 2, a <= 1)) # a <- save_value(a, 2) # p@constraints[[1]] <- save_value(p@constraints[[1]], 2) result <- solve(p, solver = "ECOS") # expect_equal(result$value, value(p)) expect_equal(result$status, "infeasible") expect_equal(result$value, -Inf) expect_true(is.na(result$getValue(a))) expect_true(is.na(result$getDualValue(p@constraints[[1]]))) p <- Problem(Minimize(-a), list(a >= 2, a <= 1)) result <- solve(p, solver = "ECOS") # expect_equal(result$value, value(p)) expect_equal(result$status, "infeasible") expect_equal(result$value, Inf) }) test_that("Test vector LP problems", { skip_on_cran() c <- Constant(matrix(c(1, 2), nrow = 2, ncol = 1))@value p <- Problem(Minimize(t(c) %*% x), list(x >= c)) result <- solve(p) expect_equal(result$value, 5, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(1, 2)), tolerance = TOL) A <- Constant(rbind(c(3, 5), c(1, 2)))@value I <- Constant(rbind(c(1, 0), c(0, 1))) p <- Problem(Minimize(t(c) %*% x + a), list(A %*% x >= c(-1, 1), 4*I %*% z == x, z >= c(2,2), a >= 2)) result <- solve(p) expect_equal(result$value, 26, tolerance = 1e-3) obj <- result$getValue(t(c) %*% x + a) expect_equal(obj, result$value, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(8,8)), tolerance = 1e-3) expect_equal(result$getValue(z), matrix(c(2,2)), tolerance = 1e-3) }) test_that("Test ECOS with no inequality constraints", { skip_on_cran() Tmat <- value(Constant(matrix(1, nrow = 2, ncol = 2))) p <- Problem(Minimize(1), list(A == Tmat)) result <- solve(p, solver = "ECOS") expect_equal(result$value, 1, tolerance = TOL) expect_equal(result$getValue(A), Tmat, tolerance = TOL) }) test_that("Test matrix LP problems", { skip_on_cran() Tmat <- value(Constant(matrix(1, nrow = 2, ncol = 2))) p <- Problem(Minimize(1), list(A == Tmat)) result <- solve(p) expect_equal(result$value, 1, tolerance = TOL) expect_equal(result$getValue(A), Tmat, tolerance = TOL) Tmat <- value(Constant(matrix(1, nrow = 2, ncol = 3)*2)) p <- Problem(Minimize(1), list(A >= Tmat %*% C, A == B, C == t(Tmat))) result <- solve(p) expect_equal(result$value, 1, tolerance = TOL) expect_equal(result$getValue(A), result$getValue(B), tolerance = TOL) expect_equal(result$getValue(C), t(Tmat), tolerance = TOL) expect_true(all(result$getValue(A) >= Tmat %*% result$getValue(C))) # Test variables are dense expect_true(is(result$getValue(A), "matrix")) }) test_that("Test variable promotion", { skip_on_cran() p <- Problem(Minimize(a), list(x <= a, x == c(1, 2))) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) expect_equal(result$getValue(a), 2, tolerance = TOL) p <- Problem(Minimize(a), list(A <= a, A == rbind(c(1,2), c(3,4)))) result <- solve(p) expect_equal(result$value, 4, tolerance = TOL) expect_equal(result$getValue(a), 4, tolerance = TOL) # Promotion must happen before multiplication p <- Problem(Minimize(matrix(1, nrow = 1, ncol = 2) %*% (x + a + 1)), list(a + x >= c(1, 2))) result <- solve(p) expect_equal(result$value, 5, tolerance = TOL) }) test_that("Test parameter promotion", { skip_on_cran() a <- Parameter() value(a) <- 2 exp <- cbind(c(1,2), c(3,4))*a expect_false(any(value(exp) - 2*cbind(c(1,2), c(3,4)) != 0)) }) test_that("test problems with parameters", { skip_on_cran() p1 <- Parameter() p2 <- Parameter(3, nonpos = TRUE) p3 <- Parameter(4, 4, nonneg = TRUE) p <- Problem(Maximize(p1*a), list(a + p1 <= p2, b <= p3 + p3 + 2)) value(p1) <- 2 value(p2) <- -matrix(1, nrow = 3, ncol = 1) value(p3) <- matrix(1, nrow = 4, ncol = 4) ##p <- Problem(Maximize(p1*a), list(a + p1 <= p2, b <= p3 + p3 + 2)) result <- solve(p) expect_equal(result$value, -6, tolerance = TOL) value(p1) <- NA_real_ p <- Problem(Maximize(p1*a), list(a + p1 <= p2, b <= p3 + p3 + 2)) expect_error(solve(p)) }) test_that("test problems with norm_inf", { skip_on_cran() # Constant argument p <- Problem(Minimize(norm_inf(-2))) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) # Scalar arguments p <- Problem(Minimize(norm_inf(a)), list(a >= 2)) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) expect_equal(result$getValue(a), 2, tolerance = TOL) p <- Problem(Minimize(3*norm_inf(a + 2*b) + c), list(a >= 2, b <= -1, c == 3)) result <- solve(p) expect_equal(result$value, 3, tolerance = TOL) expect_equal(result$getValue(a + 2*b), 0, tolerance = TOL) expect_equal(result$getValue(c), 3, tolerance = TOL) # Maximize p <- Problem(Maximize(-norm_inf(a)), list(a <= -2)) result <- solve(p) expect_equal(result$value, -2, tolerance = TOL) expect_equal(result$getValue(a), -2, tolerance = TOL) # Vector arguments p <- Problem(Minimize(norm_inf(x - z) + 5), list(x >= c(2,3), z <= c(-1,-4))) result <- solve(p, solver = "ECOS") expect_equal(result$value, 12, tolerance = TOL) expect_equal(result$getValue(x[2] - z[2]), 7, tolerance = TOL) }) test_that("Test problems with norm1", { skip_on_cran() # Constant argument p <- Problem(Minimize(norm1(-2))) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) # Scalar arguments p <- Problem(Minimize(norm1(a)), list(a <= -2)) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) expect_equal(result$getValue(a), -2, tolerance = TOL) # Maximize p <- Problem(Maximize(-norm1(a)), list(a <= -2)) result <- solve(p) expect_equal(result$value, -2, tolerance = TOL) expect_equal(result$getValue(a), -2, tolerance = TOL) # Vector arguments p <- Problem(Minimize(norm1(x - z) + 5), list(x >= c(2,3), z <= c(-1,-4))) result <- solve(p) expect_equal(result$value, 15, tolerance = TOL) expect_equal(result$getValue(x[2] - z[2]), 7, tolerance = TOL) }) test_that("Test problems with norm2", { skip_on_cran() # Constant argument p <- Problem(Minimize(norm2(-2))) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) # Scalar arguments p <- Problem(Minimize(norm2(a)), list(a <= -2)) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) expect_equal(result$getValue(a), -2, tolerance = TOL) # Maximize p <- Problem(Maximize(-norm2(a)), list(a <= -2)) result <- solve(p) expect_equal(result$value, -2, tolerance = TOL) expect_equal(result$getValue(a), -2, tolerance = TOL) # Vector arguments p <- Problem(Minimize(norm2(x - z) + 5), list(x >= c(2,3), z <= c(-1,-4))) result <- solve(p) expect_equal(result$value, 12.61577, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(2,3)), tolerance = TOL) expect_equal(result$getValue(z), matrix(c(-1,-4)), tolerance = TOL) # Row arguments p <- Problem(Minimize(norm2(t(x - z)) + 5), list(x >= c(2,3), z <= c(-1,-4))) result <- solve(p) expect_equal(result$value, 12.61577, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(2,3)), tolerance = TOL) expect_equal(result$getValue(z), matrix(c(-1,-4)), tolerance = TOL) }) test_that("Test problems with abs", { skip_on_cran() p <- Problem(Minimize(sum_entries(abs(A))), list(-2 >= A)) result <- solve(p) expect_equal(result$value, 8, tolerance = TOL) expect_equal(result$getValue(A), matrix(rep(-2, 4), nrow = 2, ncol = 2), tolerance = TOL) }) test_that("Test problems with quad_form", { skip_on_cran() expect_error(solve(Problem(Minimize(quad_form(x, A)))), "At least one argument to QuadForm must be constant.") expect_error(solve(Problem(Minimize(quad_form(1, A)))), "Invalid dimensions for arguments.") expect_error(solve(Problem(Minimize(quad_form(x, rbind(c(-1,0), c(0,9))))))) # Error: Problem does not follow DCP rules P <- rbind(c(4,0), c(0,9)) p <- Problem(Minimize(quad_form(x, P)), list(x >= 1)) result <- solve(p) expect_equal(result$value, 13, tolerance = 1e-3) c <- c(1,2) p <- Problem(Minimize(quad_form(c, A)), list(A >= 1)) result <- solve(p) expect_equal(result$value, 9, tolerance = TOL) c <- c(1,2) P <- rbind(c(4,0), c(0,9)) p <- Problem(Minimize(quad_form(c, P))) result <- solve(p) expect_equal(result$value, 40) }) test_that("Test combining atoms", { skip_on_cran() p <- Problem(Minimize(norm2(5 + p_norm(z,1) + p_norm(x,1) + norm_inf(x - z))), list(x >= c(2,3), z <= c(-1,-4), p_norm(x + z,2) <= 2)) result <- solve(p) expect_equal(result$value, 22, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(2,3)), tolerance = TOL) expect_equal(result$getValue(z), matrix(c(-1,-4)), tolerance = TOL) }) test_that("Test multiplying by constant atoms", { skip_on_cran() p <- Problem(Minimize(norm2(c(3,4)) * a), list(a >= 2)) result <- solve(p) expect_equal(result$value, 10, tolerance = TOL) expect_equal(result$getValue(a), 2, tolerance = TOL) }) test_that("Test recovery of dual variables", { skip_on_cran() for(solver in c("ECOS", "SCS", "CVXOPT")) { if(solver %in% INSTALLED_SOLVERS) { if(solver == "SCS") acc <- 1e-1 else acc <- 1e-5 p <- Problem(Minimize(p_norm(x + z, 1)), list(x >= c(2,3), cbind(c(1,2), c(3,4)) %*% z == c(-1,-4), p_norm(x + z, 2) <= 100)) result <- solve(p, solver = solver) expect_equal(result$value, 4, tolerance = acc) expect_equal(result$getValue(x), matrix(c(4,3)), tolerance = acc) expect_equal(result$getValue(z), matrix(c(-4,1)), tolerance = acc) # Dual values expect_equal(result$getDualValue(p@constraints[[1]]), matrix(c(0,1)), tolerance = acc) expect_equal(result$getDualValue(p@constraints[[2]]), matrix(c(-1,0.5)), tolerance = acc) expect_equal(result$getDualValue(p@constraints[[3]]), 0, tolerance = acc) Tmat <- matrix(1, nrow = 2, ncol = 3) * 2 c <- matrix(c(3,4), nrow = 1, ncol = 2) p <- Problem(Minimize(1), list(A >= Tmat %*% C, A == B, C == t(Tmat))) result <- solve(p, solver = solver) # Dual values expect_equal(result$getDualValue(p@constraints[[1]]), matrix(0, nrow = 2, ncol = 2), tolerance = acc) expect_equal(result$getDualValue(p@constraints[[2]]), matrix(0, nrow = 2, ncol = 2), tolerance = acc) expect_equal(result$getDualValue(p@constraints[[3]]), matrix(0, nrow = 3, ncol = 2), tolerance = acc) } } }) test_that("Test problems with indexing", { skip_on_cran() # Vector variables p <- Problem(Maximize(x[1,1]), list(x[1,1] <= 2, x[2,1] == 3)) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(2,3))) n <- 10 Aloc <- matrix(0:(n^2-1), nrow = n, ncol = n) xloc <- Variable(n,n) p <- Problem(Minimize(sum_entries(xloc)), list(xloc == Aloc)) result <- solve(p) answer <- n*n*(n*n+1)/2 - n*n expect_equal(result$value, answer) # Matrix variables obj <- A[1,1] + A[1,2] + A[2,2] + A[2,1] p <- Problem(Maximize(obj), list(A <= rbind(c(1,-2), c(-3,4)))) result <- solve(p) expect_equal(result$value, 0, tolerance = TOL) expect_equal(result$getValue(A), rbind(c(1,-2), c(-3,4))) # Indexing arithmetic expressions exp <- cbind(c(1,2), c(3,4)) %*% z + x p <- Problem(Minimize(exp[2,1]), list(x == z, z == c(1,2))) result <- solve(p) expect_equal(result$value, 12, tolerance = TOL) expect_equal(result$getValue(x), result$getValue(z), tolerance = TOL) }) test_that("Test problems with slicing", { skip_on_cran() p <- Problem(Maximize(sum_entries(C)), list(C[2:3,] <= 2, C[1,] == 1)) result <- solve(p) expect_equal(result$value, 10, tolerance = TOL) expect_equal(result$getValue(C), cbind(c(1,2,2), c(1,2,2))) p <- Problem(Maximize(sum_entries(C[seq(1,3,2),2])), list(C[2:3,] <= 2, C[1,] == 1)) result <- solve(p) expect_equal(result$value, 3, tolerance = TOL) expect_equal(result$getValue(C[seq(1,3,2),2]), matrix(c(1,2))) p <- Problem(Maximize(sum_entries((C[1:2,] + A)[,1:2])), list(C[2:3,] <= 2, C[1,] == 1, (A + B)[,1] == 3, (A + B)[,2] == 2, B == 1)) result <- solve(p) expect_equal(result$value, 12, tolerance = TOL) expect_equal(result$getValue(C[1:2,]), cbind(c(1,2), c(1,2)), tolerance = TOL) expect_equal(result$getValue(A), cbind(c(2,2),c(1,1)), tolerance = TOL) p <- Problem(Maximize(matrix(c(3,4), nrow = 1, ncol = 2) %*% (C[1:2,] + A)[,1]), list(C[2:3,] <= 2, C[1,] == 1, matrix(c(1,2), nrow = 1, ncol = 2) %*% (A + B)[,1] == 3, (A + B)[,2] == 2, B == 1, 3*A[,1] <= 3)) result <- solve(p) expect_equal(result$value, 12, tolerance = TOL) expect_equal(result$getValue(C[1:2,1]), matrix(c(1,2)), tolerance = TOL) expect_equal(result$getValue(A), cbind(c(1,-0.5), c(1,1)), tolerance = TOL) p <- Problem(Minimize(norm2((C[1:2,] + A)[,1])), list(C[2:3,] <= 2, C[1,] == 1, (A + B)[,1] == 3, (A + B)[,2] == 2, B == 1)) result <- solve(p) expect_equal(result$value, 3, tolerance = TOL) expect_equal(result$getValue(C[1:2,1]), matrix(c(1,-2)), tolerance = 1e-4) expect_equal(result$getValue(A), cbind(c(2,2), c(1,1)), tolerance = TOL) # Transpose of slice p <- Problem(Maximize(sum_entries(C)), list(t(C[2:3,]) <= 2, t(C[1,]) == 1)) result <- solve(p) expect_equal(result$value, 10, tolerance = TOL) expect_equal(result$getValue(C), cbind(c(1,2,2), c(1,2,2))) }) test_that("Test the vstack function", { skip_on_cran() c <- matrix(1, nrow = 1, ncol = 5) p <- Problem(Minimize(c %*% vstack(x, y)), list(x == c(1,2), y == c(3,4,5))) result <- solve(p) expect_equal(result$value, 15, tolerance = TOL) c <- matrix(1, nrow = 1, ncol = 4) p <- Problem(Minimize(c %*% vstack(x, x)), list(x == c(1,2))) result <- solve(p) expect_equal(result$value, 6, tolerance = TOL) c <- matrix(1, nrow = 2, ncol = 2) p <- Problem(Minimize(sum_entries(vstack(A, C))), list(A >= 2*c, C == -2)) result <- solve(p) expect_equal(result$value, -4, tolerance = TOL) c <- matrix(1, nrow = 1, ncol = 2) p <- Problem(Minimize(sum_entries(vstack(c %*% A, c %*% B))), list(A >= 2, B == -2)) result <- solve(p) expect_equal(result$value, 0, tolerance = TOL) c <- matrix(c(1,-1), nrow = 2, ncol = 1) p <- Problem(Minimize(t(c) %*% vstack(a^2, sqrt(b))), list(a == 2, b == 16)) expect_error(solve(p)) }) test_that("Test the hstack function", { skip_on_cran() c <- matrix(1, nrow = 1, ncol = 5) p <- Problem(Minimize(c %*% t(hstack(t(x), t(y)))), list(x == c(1,2), y == c(3,4,5))) result <- solve(p) expect_equal(result$value, 15, tolerance = TOL) c <- matrix(1, nrow = 1, ncol = 4) p <- Problem(Minimize(c %*% t(hstack(t(x), t(x)))), list(x == c(1,2))) result <- solve(p) expect_equal(result$value, 6, tolerance = TOL) c <- matrix(1, nrow = 2, ncol = 2) p <- Problem(Minimize(sum_entries(hstack(t(A), t(C)))), list(A >= 2*c, C == -2)) result <- solve(p) expect_equal(result$value, -4, tolerance = TOL) D <- Variable(3,3) expr <- hstack(C, D) p <- Problem(Minimize(expr[1,2] + sum_entries(hstack(expr, expr))), list(C >= 0, D >= 0, D[1,1] == 2, C[1,2] == 3)) result <- solve(p) expect_equal(result$value, 13, tolerance = TOL) c <- matrix(c(1,-1), nrow = 2, ncol = 1) p <- Problem(Minimize(t(c) %*% t(hstack(t(a^2), t(sqrt(b))))), list(a == 2, b == 16)) expect_error(solve(p)) }) test_that("Test using a CVXR expression as an objective", { skip_on_cran() expect_error(Problem(x+2)) }) test_that("Test variable transpose", { skip_on_cran() p <- Problem(Minimize(sum_entries(x)), list(t(x) >= matrix(c(1,2), nrow = 1, ncol = 2))) result <- solve(p) expect_equal(result$value, 3, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(1,2))) p <- Problem(Minimize(sum_entries(C)), list(matrix(c(1,1), nrow = 1, ncol = 2) %*% t(C) >= matrix(0:2, nrow = 1, ncol = 3))) result <- solve(p) value <- result$getValue(C) constraints <- lapply(1:3, function(i) { 1*C[i,1] + 1*C[i,2] >= (i-1) }) p <- Problem(Minimize(sum_entries(C)), constraints) result2 <- solve(p) expect_equal(result$value, result2$value) expect_equal(result$getValue(C), value) p <- Problem(Minimize(A[1,2] - t(A)[2,1]), list(A == cbind(c(1,2), c(3,4)))) result <- solve(p) expect_equal(result$value, 0, tolerance = TOL) exp <- t(-x) p <- Problem(Minimize(sum_entries(x)), list(t(-x) <= 1)) result <- solve(p) expect_equal(result$value, -2, tolerance = TOL) c <- matrix(c(1,-1), nrow = 2, ncol = 1) p <- Problem(Minimize(max_elemwise(t(c), 2, 2 + t(c))[2])) result <- solve(p) expect_equal(result$value, 2, tolerance = TOL) c <- cbind(c(1,-1,2), c(1,-1,2)) p <- Problem(Minimize(sum_entries(t(max_elemwise(c, 2, 2+c))[,1]))) result <- solve(p) expect_equal(result$value, 6, tolerance = TOL) c <- cbind(c(1,-1,2), c(1,-1,2)) p <- Problem(Minimize(sum_entries(t(t(c)^2)[,1]))) result <- solve(p) expect_equal(result$value, 6, tolerance = TOL) # Slice of transpose p <- Problem(Maximize(sum_entries(C)), list(t(C)[,2:3] <= 2, t(C)[,1] == 1)) result <- solve(p) expect_equal(result$value, 10, tolerance = TOL) expect_equal(result$getValue(C), cbind(c(1,2,2), c(1,2,2))) }) test_that("Test multiplication on the left by a non-constant", { skip_on_cran() c <- matrix(c(1,2), nrow = 2, ncol = 1) p <- Problem(Minimize(t(c) %*% A %*% c), list(A >= 2)) result <- solve(p) expect_equal(result$value, 18, tolerance = TOL) p <- Problem(Minimize(a*2), list(a >= 2)) result <- solve(p) expect_equal(result$value, 4, tolerance = TOL) p <- Problem(Minimize(t(x) %*% c), list(x >= 2)) result <- solve(p) expect_equal(result$value, 6, tolerance = TOL) p <- Problem(Minimize((t(x) + t(z)) %*% c), list(x >= 2, z >= 1)) result <- solve(p) expect_equal(result$value, 9, tolerance = TOL) }) test_that("Test redundant constraints", { skip_on_cran() obj <- Minimize(sum_entries(x)) constraints <- list(x == 2, x == 2, t(x) == 2, x[1] == 2) p <- Problem(obj, constraints) result <- solve(p, solver = "ECOS") expect_equal(result$value, 4, tolerance = TOL) obj <- Minimize(sum_entries(x^2)) constraints <- list(x == x) p <- Problem(obj, constraints) result <- solve(p, solver = "ECOS") expect_equal(result$value, 0, tolerance = TOL) }) test_that("Test that symmetry is enforced", { skip_on_cran() p <- Problem(Minimize(lambda_max(A)), list(A >= 2)) result <- solve(p) expect_equal(result$getValue(A), t(result$getValue(A)), tolerance = 1e-3) p <- Problem(Minimize(lambda_max(A)), list(A == cbind(c(1,2), c(3,4)))) result <- solve(p) expect_equal(result$status, "infeasible") }) test_that("Test SDP", { skip_on_cran() # Ensure SDP constraints enforce transpose obj <- Maximize(A[2,1] - A[1,2]) p <- Problem(obj, list(lambda_max(A) <= 100, A[1,1] == 2, A[2,2] == 2, A[2,1] == 2)) result <- solve(p) expect_equal(result$value, 0, tolerance = 1e-3) }) test_that("Test getting values for expressions", { skip_on_cran() diff_exp <- x - z inf_exp <- norm_inf(diff_exp) sum_entries_exp <- 5 + p_norm(z,1) + p_norm(x,1) + inf_exp constr_exp <- norm2(x + z) obj <- norm2(sum_entries_exp) p <- Problem(Minimize(obj), list(x >= c(2,3), z <= c(-1,-4), constr_exp <= 2)) result <- solve(p) expect_equal(result$value, 22, tolerance = TOL) expect_equal(result$getValue(x), matrix(c(2,3)), tolerance = TOL) expect_equal(result$getValue(z), matrix(c(-1,-4)), tolerance = TOL) # Expression values xs <- result$getValue(x) zs <- result$getValue(z) expect_equal(result$getValue(diff_exp), xs - zs, tolerance = TOL) expect_equal(result$getValue(inf_exp), norm(xs - zs, "I")) expect_equal(result$getValue(sum_entries_exp), 5 + norm(zs, "1") + norm(xs, "1") + norm(xs - zs, "I")) expect_equal(result$getValue(constr_exp), base::norm(xs + zs, "2")) expect_equal(result$getValue(obj), result$value) }) test_that("Test multiplication by zero", { skip_on_cran() exp <- 0*a expect_equal(value(exp), matrix(0)) obj <- Minimize(exp) p <- Problem(obj) result <- solve(p) expect_equal(result$value, 0, tolerance = TOL) expect_false(is.na(result$getValue(a))) }) test_that("Tests a problem with division", { skip_on_cran() obj <- Minimize(norm_inf(A/5)) p <- Problem(obj, list(A >= 5)) result <- solve(p) expect_equal(result$value, 1, tolerance = TOL) }) test_that("Tests problems with multiply", { skip_on_cran() c <- cbind(c(1,-1), c(2,-2)) expr <- multiply(c, A) obj <- Minimize(norm_inf(expr)) p <- Problem(obj, list(A == 5)) result <- solve(p) expect_equal(result$value, 10, tolerance = TOL) expect_equal(result$getValue(expr), cbind(c(5,-5), c(10,-10)), tolerance = TOL) # Test with a sparse matrix c <- Matrix::sparseMatrix(i = c(1,2), j = c(1,1), x = c(1,2)) expr <- multiply(c, x) obj <- Minimize(norm_inf(expr)) p <- Problem(obj, list(x == 5)) result <- solve(p) expect_equal(result$value, 10, tolerance = TOL) expect_equivalent(as.matrix(result$getValue(expr)), matrix(c(5,10))) # Test promotion c <- cbind(c(1,-1), c(2,-2)) expr <- multiply(c, a) obj <- Minimize(norm_inf(expr)) p <- Problem(obj, list(a == 5)) result <- solve(p) expect_equal(result$value, 10, tolerance = TOL) expect_equivalent(as.matrix(result$getValue(expr)), cbind(c(5,-5), c(10,-10))) }) test_that("Tests that errors occur when you use an invalid solver", { skip_on_cran() expect_error(solve(Problem(Minimize(Bool())), solver = "ECOS")) expect_error(solve(Problem(Minimize(lambda_max(a))), solver = "ECOS")) expect_error(solve(Problem(Minimize(a)), solver = "SCS")) }) test_that("Tests problems with reshape_expr", { skip_on_cran() # Test on scalars expect_equal(value(reshape_expr(1,c(1,1))), matrix(1)) # Test vector to matrix x <- Variable(4) mat <- cbind(c(1,-1), c(2,-2)) vec <- matrix(1:4) vec_mat <- cbind(c(1,2), c(3,4)) expr <- reshape_expr(x,c(2,2)) obj <- Minimize(sum_entries(mat %*% expr)) prob <- Problem(obj, list(x == vec)) result <- solve(prob) expect_equal(result$value, sum(mat %*% vec_mat)) # Test on matrix to vector c <- 1:4 expr <- reshape_expr(A,c(4,1)) obj <- Minimize(t(expr) %*% c) constraints <- list(A == cbind(c(-1,-2), c(3,4))) prob <- Problem(obj, constraints) result <- solve(prob) expect_equal(result$value, 20, tolerance = TOL) expect_equal(result$getValue(expr), matrix(c(-1,-2,3,4))) expect_equal(result$getValue(reshape_expr(expr,c(2,2))), cbind(c(-1,-2), c(3,4))) # Test matrix to matrix expr <- reshape_expr(C,c(2,3)) mat <- rbind(c(1,-1), c(2,-2)) C_mat <- rbind(c(1,4), c(2,5), c(3,6)) obj <- Minimize(sum_entries(mat %*% expr)) prob <- Problem(obj, list(C == C_mat)) result <- solve(prob) reshaped = matrix(C_mat, nrow = 2, ncol = 3, byrow = FALSE) expect_equal(result$value, sum(mat %*% reshaped), tolerance = TOL) expect_equal(result$getValue(expr), reshaped, tolerance = TOL) # Test promoted expressions c <- cbind(c(1,-1), c(2,-2)) expr <- reshape_expr(c * a,c(1,4)) obj <- Minimize(expr %*% (1:4)) prob <- Problem(obj, list(a == 2)) result <- solve(prob) expect_equal(result$value, -6, tolerance = TOL) expect_equal(result$getValue(expr), 2*matrix(c, nrow = 1), tolerance = TOL) expr <- reshape_expr(c * a,c(4,1)) obj <- Minimize(t(expr) %*% (1:4)) prob <- Problem(obj, list(a == 2)) result <- solve(prob) expect_equal(result$value, -6, tolerance = TOL) expect_equal(result$getValue(expr), 2*matrix(c, ncol = 1), tolerance = TOL) }) test_that("Tests problems with vec", { skip_on_cran() c <- 1:4 expr <- vec(A) obj <- Minimize(t(expr) %*% c) constraints <- list(A == cbind(c(-1,-2), c(3,4))) prob <- Problem(obj, constraints) result <- solve(prob) expect_equal(result$value, 20, tolerance = TOL) expect_equal(result$getValue(expr), matrix(c(-1,-2,3,4))) }) test_that("Test a problem with diag", { skip_on_cran() C <- Variable(3,3) obj <- Maximize(C[1,3]) constraints <- list(diag(C) == 1, C[1,2] == 0.6, C[2,3] == -0.3, C == Variable(3, 3, PSD = TRUE)) prob <- Problem(obj, constraints) result <- solve(prob) expect_equal(result$value, 0.583151, tolerance = 1e-2) }) # test_that("Test presolve parameters", { # # Test with parameters # gamma <- Parameter(nonneg = TRUE) # x <- Variable() # obj <- Minimize(x) # value(gamma) <- 0 # prob <- Problem(obj, list(gamma == 1, x >= 0)) # result <- solve(prob, solver = "SCS") # expect_equal(result$status, "infeasible") # # value(gamma) <- 1 # prob <- Problem(obj, list(gamma == 1, x >= 0)) # result <- solve(prob, solver = "SCS") # expect_equal(result$status, "optimal") # }) # test_that("Test that expressions with parameters are updated properly", { # x <- Variable() # y <- Variable() # x0 <- Parameter() # # # Initial guess for x # value(x0) <- 2 # # # Make the constraints x^2 - y == 0 # xSquared <- x0*x0 + 2*x0*(x-x0) # g <- xSquared - y # # # Set up the problem # obj <- abs(x - 1) # prob <- Problem(Minimize(obj), list(g == 0)) # result <- solve(prob) # # value(x0) <- 1 # xSquared <- x0*x0 + 2*x0*(x-x0) # g <- xSquared - y # prob <- Problem(Minimize(obj), list(g == 0)) # result <- solve(prob) # # expect_equal(result$getValue(g), 0, tolerance = TOL) # # # Test multiplication # prob <- Problem(Minimize(x0*x), list(x == 1)) # value(x0) <- 2 # result <- solve(prob) # x0@value <- 1 # result <- solve(prob) # expect_equal(result$value, 1, tolerance = TOL) # }) test_that("Test interaction of caching with changing constraints", { skip_on_cran() prob <- Problem(Minimize(a), list(a == 2, a >= 1)) result <- solve(prob) expect_equal(result$value, 2, tolerance = TOL) prob@constraints[[1]] = (a == 1) result <- solve(prob) expect_equal(result$value, 1, tolerance = TOL) }) test_that("Test positive definite constraints", { skip_on_cran() C <- Variable(3,3) obj <- Maximize(C[1,3]) constraints <- list(diag(C) == 1, C[1,2] == 0.6, C[2,3] == -0.3, C == t(C), C %>>% 0) prob <- Problem(obj, constraints) result <- solve(prob) expect_equal(result$value, 0.583151, tolerance = 1e-2) C <- Variable(2,2) obj <- Maximize(C[1,2]) constraints <- list(C == 1, C %>>% rbind(c(2,0), c(0,2))) prob <- Problem(obj, constraints) result <- solve(prob) expect_equal(result$status, "infeasible") C <- Variable(2, 2, symmetric = TRUE) obj <- Minimize(C[1,1]) constraints <- list(C %<<% cbind(c(2,0), c(0,2))) prob <- Problem(obj, constraints) result <- solve(prob) expect_equal(result$status, "unbounded") }) test_that("Test the duals of PSD constraints", { skip_on_cran() # Test dual values with SCS C <- Variable(2, 2, symmetric = TRUE, name = "C") obj <- Maximize(C[1,1]) constraints <- list(C %<<% cbind(c(2,0), c(0,2))) prob <- Problem(obj, constraints) result <- solve(prob, solver = "SCS") expect_equal(result$value, 2, tolerance = 1e-4) psd_constr_dual <- result$getDualValue(constraints[[1]]) C <- Variable(2, 2, symmetric = TRUE, name = "C") X <- Variable(2, 2, PSD = TRUE) obj <- Maximize(C[1,1]) constraints <- list(X == cbind(c(2,0), c(0,2)) - C) prob <- Problem(obj, constraints) result <- solve(prob, solver = "SCS") expect_equal(result$getDualValue(constraints[[1]]), psd_constr_dual, tolerance = 1e-3) # Test dual values with SCS that have off-diagonal entries C <- Variable(2, 2, symmetric = TRUE) obj <- Maximize(C[1,2] + C[2,1]) constraints <- list(C %<<% cbind(c(2,0), c(0,2)), C >= 0) prob <- Problem(obj, constraints) result <- solve(prob, solver = "SCS") expect_equal(result$value, 4, tolerance = 1e-3) psd_constr_dual <- result$getDualValue(constraints[[1]]) C <- Variable(2, 2, symmetric = TRUE) X <- Variable(2, 2, PSD = TRUE) obj <- Maximize(C[1,2] + C[2,1]) constraints <- list(X == cbind(c(2,0), c(0,2)) - C, C >= 0) prob <- Problem(obj, constraints) result <- solve(prob, solver = "SCS") expect_equal(result$getDualValue(constraints[[1]]), psd_constr_dual, tolerance = 1e-3) }) test_that("Test geo_mean function", { skip_on_cran() x <- Variable(2) cost <- geo_mean(x) prob <- Problem(Maximize(cost), list(x <= 1)) result <- solve(prob) expect_equal(result$value, 1, tolerance = TOL) prob <- Problem(Maximize(cost), list(sum(x) <= 1)) result <- solve(prob) expect_equal(result$getValue(x), matrix(c(0.5,0.5)), tolerance = TOL) x <- Variable(3,3) expect_error(geo_mean(x)) x <- Variable(3,1) g <- geo_mean(x) ##expect_equal(g@w, gmp::as.bigq(1,3)*3, tolerance = TOL) x <- Variable(1,5) g <- geo_mean(x) ##expect_equal(g@w, gmp::as.bigq(1,5)*5, tolerance = TOL) ## Check that we get the right answer for max geo_mean(x) s.t. sum(x) <= 1 p <- c(0.07, 0.12, 0.23, 0.19, 0.39) short_geo_mean <- function(x, p) { p <- as.numeric(p)/sum(p) x <- as.numeric(x) prod(x^p) } x <- Variable(5) prob <- Problem(Maximize(geo_mean(x, p)), list(sum(x) <= 1)) result <- solve(prob) x <- as.numeric(result$getValue(x)) x_true <- p/sum(p) expect_equal(result$value, result$getValue(geo_mean(x, p)), tolerance = TOL) expect_equal(result$value, short_geo_mean(x, p), tolerance = TOL) expect_equal(x, x_true, tolerance = 1e-3) ## Check that we get the right answer for max geo_mean(x) s.t. p_norm(x) <= 1 x <- Variable(5) prob <- Problem(Maximize(geo_mean(x, p)), list(p_norm(x) <= 1)) result <- solve(prob) x <- as.numeric(result$getValue(x)) x_true <- sqrt(p/sum(p)) expect_equal(result$value, result$getValue(geo_mean(x, p)), tolerance = 1e-3) expect_equal(result$value, short_geo_mean(x, p), tolerance = 1e-3) expect_equal(x, x_true, tolerance = 1e-3) ## The following 3 tests check vstack and hstack input to geo_mean ## The following 3 formulations should be equivalent n <- 5 x_true <- rep(1,n) x <- Variable(n) result <- solve(Problem(Maximize(geo_mean(x)), list(x <= 1))) xval <- as.numeric(result$getValue(x)) expect_equal(xval, x_true, tolerance = 1e-3) ##args <- list() ##for(i in 1:n) ## args <- c(args, x[i]) args <- lapply(seq_len(n), function(ind) x[ind]) y <- do.call(vstack, args) result <- solve(Problem(Maximize(geo_mean(y)), list(x <= 1))) xval <- as.numeric(result$getValue(x)) expect_equal(xval, x_true, tolerance = 1e-3) y <- do.call(hstack, args) result <- solve(Problem(Maximize(geo_mean(y)), list(x <= 1))) xval <- as.numeric(result$getValue(x)) expect_equal(xval, x_true, tolerance = 1e-3) }) test_that("Test p_norm function", { skip_on_cran() x <- Variable(3, name = "x") avec <- c(1.0, 2, 3) ## TODO: Add -1, 0.5, 0.3, -2.3 and testing positivity constraints for(p in c(1, 1.6, 1.3, 2, 1.99, 3, 3.7, Inf)) { prob <- Problem(Minimize(p_norm(x, p = p)), list(t(x) %*% avec >= 1)) result <- solve(prob) # Formula is true for any a >= 0 with p > 1 if(p == Inf) x_true <- rep(1, length(avec))/sum(avec) else if(p == 1) { # Only works for the particular a = c(1,2,3) x_true <- c(0,0,1.0/3) } else x_true <- avec^(1.0/(p-1)) / as.numeric(avec %*% (avec^(1.0/(p-1)))) x_alg <- as.vector(result$getValue(x)) expect_equal(x_alg, x_true, tolerance = 1e-3) expect_equal(result$value, .p_norm(x_alg, p), tolerance = TOL) expect_equal(.p_norm(x_alg, p), result$getValue(p_norm(x_alg, p))) } }) test_that("Test p_norm concave", { skip_on_cran() x <- Variable(3, name = "x") # Test positivity constraints a <- c(-1.0, 2, 3) for(p in c(-1, 0.5, 0.3, -2.3)) { prob <- Problem(Minimize(sum_entries(abs(x-a))), list(p_norm(x,p) >= 0)) result <- solve(prob) expect_equal(result$value, 1, tolerance = TOL) } a <- c(1.0, 2, 3) for(p in c(-1, 0.5, 0.3, -2.3)) { prob <- Problem(Minimize(sum_entries(abs(x-a))), list(p_norm(x,p) >= 0)) result <- solve(prob) expect_equal(result$value, 0, tolerance = TOL) } }) test_that("Test power function", { skip_on_cran() x <- Variable() prob <- Problem(Minimize(power(x, 1.7) + power(x, -2.3) - power(x, 0.45))) result <- solve(prob) xs <- result$getValue(x) expect_true(abs(1.7*xs^0.7 - 2.3*xs^-3.3 - 0.45*xs^-0.55) <= 1e-3) }) test_that("Test a problem with multiply by a scalar", { skip_on_cran() Tnum <- 10 Jnum <- 20 rvec <- matrix(stats::rnorm(Tnum*Jnum), nrow = Tnum, ncol = Jnum) dy <- matrix(stats::rnorm(2*Tnum), nrow = 2*Tnum, ncol = 1) theta <- Variable(Jnum) delta <- 1e-3 loglambda <- rvec %*% theta # rvec: TxJ regressor matrix, theta: (Jx1) cvx variable a <- multiply(dy[1:Tnum], loglambda) # size (Tx1) b1 <- exp(loglambda) b2 <- multiply(delta, b1) cost <- -a + b1 cost <- -a + b2 # size (Tx1) prob <- Problem(Minimize(sum_entries(cost))) result <- solve(prob, solver = "SCS") obj <- Minimize(sum_entries(multiply(2, x))) prob <- Problem(obj, list(x == 2)) result <- solve(prob) expect_equal(result$value, 8, tolerance = TOL) })