# Testing concrete implementations of the 'Solver' class. test_that("'Solver' implementations set correct constraints for monotone non-decreasing spline", { # Data. x <- 1:10 y <- c(-.5, .8, .6, 1, .3, 1, 1, 1, 1, .5) # Create spline basis. ispline <- Basis$new(x, df = 0, monotone = TRUE) n <- ncol(ispline$matrix) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(ispline, y, increasing = TRUE) # Constraints for 'QuadprogSolver'. b_vec <- rep(0, n) a_mat <- diag(1, n) a_mat[1, 1] <- 0 # Test constraints for 'QuadprogSolver'. expect_equal(qp$.__enclos_env__$private$.b_vec, b_vec) expect_equal(qp$.__enclos_env__$private$.a_mat, a_mat) }) test_that("'Solver' implementations set correct constraints for monotone non-increasing spline", { # Data. x <- 1:10 y <- c(-.5, .8, .6, 1, .3, 1, 1, 1, 1, .5) # Create spline basis. ispline <- Basis$new(x, df = 0, monotone = TRUE) n <- ncol(ispline$matrix) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(ispline, y, increasing = FALSE) # Constraints for 'QuadprogSolver'. b_vec <- rep(0, n) a_mat <- diag(-1, n) a_mat[1, 1] <- 0 # Test constraints for 'QuadprogSolver'. expect_equal(qp$.__enclos_env__$private$.b_vec, b_vec) expect_equal(qp$.__enclos_env__$private$.a_mat, a_mat) }) test_that("'Solver' implementations set correct constraints for non-monotone spline", { # Data. x <- 1:10 y <- c(-.5, .8, .6, 1, .3, 1, 1, 1, 1, .5) # Create basis. bspline <- Basis$new(x, df = 0, monotone = FALSE) n <- ncol(bspline$matrix) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(bspline, y) # Constraints for 'QuadprogSolver'. b_vec <- rep(0, n) a_mat <- diag(0, n) # Test constraints for 'QuadprogSolver'. expect_equal(qp$.__enclos_env__$private$.b_vec, b_vec) expect_equal(qp$.__enclos_env__$private$.a_mat, a_mat) }) test_that("'Solver' implementations give correct solution for monotone non-decreasing spline", { # Data. x <- 1:10 y <- c(-0.2, 0.3, 0.5, 0.7, 0.6, 1, 0.9, 1, 1, 1) # Create spline. ispline <- Basis$new(x, df = 0, monotone = TRUE) n <- ncol(ispline$matrix) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(ispline, y, increasing = TRUE) # Solve using own implementations. qp_impl_alpha <- qp$solve() # Solve using 'quadprog'. a_mat <- diag(1, n) a_mat[1, 1] <- 0 b_vec <- rep(0, n) qp_alpha <- solve_qp(ispline$matrix, y, a_mat, b_vec) # Each implementation should be equal with its counterpart. expect_equal(qp_impl_alpha, qp_alpha, tolerance = 1e-6) }) test_that("'Solver' implementations give correct solution for monotone non-increasing spline", { # Data. x <- 1:10 y <- rev(c(-0.2, 0.3, 0.5, 0.7, 0.6, 1, 0.9, 1, 1, 1)) # Create spline. ispline <- Basis$new(x, df = 0, monotone = TRUE) n <- ncol(ispline$matrix) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(ispline, y, increasing = FALSE) # Solve using own implementations. qp_impl_alpha <- qp$solve() # Solve using 'quadprog'. a_mat <- diag(-1, n) a_mat[1, 1] <- 0 b_vec <- rep(0, n) qp_alpha <- solve_qp(ispline$matrix, y, a_mat, b_vec) # Each implementation should be equal with its counterpart. expect_equal(qp_impl_alpha, qp_alpha, tolerance = 1e-6) }) test_that("'Solver' implementations give correct solution for non-monotone spline", { # Data. x <- 1:10 y <- c(-.5, .8, .6, 1, .3, 1, 1, 1, 1, .5) # Create spline. bspline <- Basis$new(x, df = 0, monotone = FALSE) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(bspline, y) # Solve using own implementations. qp_impl_alpha <- qp$solve() # Solve using 'lm'. lm_alpha <- as.numeric(lm.fit(bspline$matrix, y)$coefficients) # Test. expect_equal(qp_impl_alpha, lm_alpha, tolerance = 1e-6) }) test_that("'Solver' implementations gives correct solution for updated statistics", { # Data. x <- 1:10 y <- c(-0.2, 0.3, 0.5, 0.7, 0.6, 1, 0.9, 1, 1, 1) # Create spline. ispline <- Basis$new(x, df = 0, monotone = TRUE) n <- ncol(ispline$matrix) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(ispline, y, increasing = TRUE) # Solve first time with original data. qp$solve() # Create new data to update the solver. y_new <- sample(y, length(y), TRUE) # Update solvers and solve problem. qp_impl_alpha <- qp$solve_update(y_new) # Solve problem with new data using 'quadprog' helper. qp_alpha <- solve_qp(ispline$matrix, y_new, qp$.__enclos_env__$private$.a_mat, qp$.__enclos_env__$private$.b_vec) # The solver implementations should agree with their counterpart helpers. expect_equal(qp_impl_alpha, qp_alpha, tolerance = 1e-6) }) test_that("'Solver' implementations still give original solution after solving with updated data", { # Data. x <- 1:10 y <- c(-0.2, 0.3, 0.5, 0.7, 0.6, 1, 0.9, 1, 1, 1) # Create spline. ispline <- Basis$new(x, df = 0, monotone = TRUE) # Create solvers. qp <- QuadprogSolver$new() # Setup solvers. qp$setup(ispline, y, increasing = TRUE) # Solve first time with original data. qp_first_alpha <- qp$solve() # Create new data to update the solver. y_new <- sample(y, length(y), TRUE) # Solve with updated data. qp$solve_update(y_new) # Solve again and expect to recover the original solution. expect_equal(qp_first_alpha, qp$solve()) }) test_that("'Solver' base class throws errors for abstract methods", { # Create `Solver` base class. solver <- Solver$new() # Expect error because the methods are abstract. expect_error(solver$setup(NULL, NULL, NULL), .__ERRORS__$not_implemented) expect_error(solver$solve(), .__ERRORS__$not_implemented) expect_error(solver$solve_update(NULL), .__ERRORS__$not_implemented) })