README.md

R HIGHS Interface

Florian Schwendinger Updated: 2025-04-20

CRAN
status Licence

This repository contains an R interface to the HiGHS solver. The HiGHS solver, is a high-performance open-source solver for solving linear programming (LP), mixed-integer programming (MIP) and quadratic programming (QP) optimization problems.

1 Installation

The package can be installed from CRAN

install.packages("highs")

or GitLab.

remotes::install_gitlab("roigrp/solver/highs")

1.0.1 Using a preinstalled HiGHS library

It is possible to use a precompile HiGHS library by providing the system variable R_HIGHS_LIB_DIR. For example I used

mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/Z/bin/highslib -DCMAKE_POSITION_INDEPENDENT_CODE:bool=ON -DSHARED:bool=OFF -DBUILD_TESTING:bool=OFF
make install

to install the HiGHS library to /Z/bin/highslib

Sys.setenv(R_HIGHS_LIB_DIR = "/Z/bin/highslib")
install.packages("highs")
# or 
# remotes::install_gitlab("roigrp/solver/highs")

2 Package

The highs package provides an API similar to Rglpk and a low level API to the HiGHS solver. For most users using highs_solve as shown below should be the best choice.

The package functions can be grouped into the following categories:

  1. The main function highs_solve.
  2. Object style wrappers for the model and the solver highs_model and highs_solver.
  3. Function highs_control to construct the control object for highs_solveand highs_solver.
  4. Low-level API wrapper functions to create and modify models hi_new_model and other functions starting with hi_model_.
  5. Low-level API wrapper functions to create and modify solvers hi_new_solver and other functions starting with hi_solver_.
  6. Functions to create example models example_model and solvers example_solver for the documentation examples.
  7. Function highs_available_solver_options to get the available solver options.
  8. Function highs_write_model to write the model to a file.
library("highs")

2.1 Examples

The the example models and solvers are included to have small examples available for the manual.

writeLines(ls("package:highs", pattern = "^example"))
#> example_model
#> example_solver

2.2 Low level model functions

The low-level model functions allow to create and modify models. More details and examples can be found in the manual.

writeLines(ls("package:highs", pattern = "^hi(|_new)_model"))
#> hi_model_get_ncons
#> hi_model_get_nvars
#> hi_model_set_constraint_matrix
#> hi_model_set_hessian
#> hi_model_set_lhs
#> hi_model_set_lower
#> hi_model_set_ncol
#> hi_model_set_nrow
#> hi_model_set_objective
#> hi_model_set_offset
#> hi_model_set_rhs
#> hi_model_set_sense
#> hi_model_set_upper
#> hi_model_set_vartype
#> hi_new_model

2.3 Low level solver functions

The low-level solver functions allow to create and modify solvers. More details and examples can be found in the manual.

writeLines(ls("package:highs", pattern = "^hi(|_new)_solver"))
#> hi_new_solver
#> hi_solver_add_cols
#> hi_solver_add_rows
#> hi_solver_add_vars
#> hi_solver_change_constraint_bounds
#> hi_solver_change_variable_bounds
#> hi_solver_clear
#> hi_solver_clear_model
#> hi_solver_clear_solver
#> hi_solver_get_bool_option
#> hi_solver_get_constraint_bounds
#> hi_solver_get_constraint_matrix
#> hi_solver_get_dbl_option
#> hi_solver_get_int_option
#> hi_solver_get_lp_costs
#> hi_solver_get_model
#> hi_solver_get_num_col
#> hi_solver_get_num_row
#> hi_solver_get_option
#> hi_solver_get_options
#> hi_solver_get_sense
#> hi_solver_get_str_option
#> hi_solver_get_variable_bounds
#> hi_solver_get_vartype
#> hi_solver_infinity
#> hi_solver_info
#> hi_solver_run
#> hi_solver_set_coeff
#> hi_solver_set_constraint_bounds
#> hi_solver_set_integrality
#> hi_solver_set_objective
#> hi_solver_set_offset
#> hi_solver_set_option
#> hi_solver_set_options
#> hi_solver_set_sense
#> hi_solver_set_variable_bounds
#> hi_solver_solution
#> hi_solver_status
#> hi_solver_status_message
#> hi_solver_write_basis
#> hi_solver_write_model

2.4 High level functions

The high level functions allow to work with models and solvers. More details and examples can be found in the manual.

args(highs_model)
#> function (Q = NULL, L, lower, upper, A = NULL, lhs = NULL, rhs = NULL, 
#>     types = rep.int(1L, length(L)), maximum = FALSE, offset = 0) 
#> NULL
args(highs_solver)
#> function (model, control = highs_control()) 
#> NULL
args(highs_control)
#> function (threads = 1L, time_limit = Inf, log_to_console = FALSE, 
#>     ...) 
#> NULL
args(highs_write_model)
#> function (model, file) 
#> NULL

2.5 Main function

The main function highs_solve.

library("highs")

args(highs_solve)
#> function (Q = NULL, L, lower, upper, A = NULL, lhs = NULL, rhs = NULL, 
#>     types = rep.int(1L, length(L)), maximum = FALSE, offset = 0, 
#>     control = highs_control()) 
#> NULL

2.6 LP

# Minimize
#  x_0 +  x_1 + 3
# Subject to
#                 x_1 <= 7
#  5 <=   x_0 + 2 x_1 <= 15
#  6 <= 3 x_0 + 2 x_1
#  0 <=   x_0         <= 4
#  1 <=           x_1
A <- rbind(c(0, 1), c(1, 2), c(3, 2))
s <- highs_solve(L = c(1.0, 1), lower = c(0, 1), upper = c(4, Inf),
                 A = A, lhs = c(-Inf, 5, 6), rhs = c(7, 15, Inf),
                 offset = 3)
str(s)
#> List of 6
#>  $ primal_solution: num [1:2] 0.5 2.25
#>  $ objective_value: num 5.75
#>  $ status         : int 7
#>  $ status_message : chr "Optimal"
#>  $ solver_msg     :List of 6
#>   ..$ value_valid: logi TRUE
#>   ..$ dual_valid : logi TRUE
#>   ..$ col_value  : num [1:2] 0.5 2.25
#>   ..$ col_dual   : num [1:2] 0 0
#>   ..$ row_value  : num [1:3] 2.25 5 6
#>   ..$ row_dual   : num [1:3] 0 0.25 0.25
#>  $ info           :List of 18
#>   ..$ valid                     : logi TRUE
#>   ..$ mip_node_count            : num -1
#>   ..$ simplex_iteration_count   : int 0
#>   ..$ ipm_iteration_count       : int 5
#>   ..$ qp_iteration_count        : int 0
#>   ..$ crossover_iteration_count : int 0
#>   ..$ primal_solution_status    : chr "Feasible"
#>   ..$ dual_solution_status      : chr "Feasible"
#>   ..$ basis_validity            : int 1
#>   ..$ objective_function_value  : num 5.75
#>   ..$ mip_dual_bound            : num 0
#>   ..$ mip_gap                   : num Inf
#>   ..$ num_primal_infeasibilities: int 0
#>   ..$ max_primal_infeasibility  : num 0
#>   ..$ sum_primal_infeasibilities: num 0
#>   ..$ num_dual_infeasibilities  : int 0
#>   ..$ max_dual_infeasibility    : num 0
#>   ..$ sum_dual_infeasibilities  : num 0

2.7 QP

# Minimize
#  0.5 x^2 - 2 x + y
# Subject to
#  x <= 3
zero <- .Machine$double.eps * 100
Q <- rbind(c(1, 0), c(0, zero))
L <- c(-2, 1)
A <- t(c(1, 0))

cntrl <- list(log_dev_level = 0L)
s <- highs_solve(Q = Q, L = L, A = A, lhs = 0, rhs = 3, control = cntrl)
str(s)
#> List of 6
#>  $ primal_solution: num [1:2] 3 0
#>  $ objective_value: num -6
#>  $ status         : int 10
#>  $ status_message : chr "Unbounded"
#>  $ solver_msg     :List of 6
#>   ..$ value_valid: logi TRUE
#>   ..$ dual_valid : logi TRUE
#>   ..$ col_value  : num [1:2] 3 0
#>   ..$ col_dual   : num [1:2] 0 1
#>   ..$ row_value  : num 3
#>   ..$ row_dual   : num -2
#>  $ info           :List of 18
#>   ..$ valid                     : logi TRUE
#>   ..$ mip_node_count            : num -1
#>   ..$ simplex_iteration_count   : int 1
#>   ..$ ipm_iteration_count       : int 0
#>   ..$ qp_iteration_count        : int 0
#>   ..$ crossover_iteration_count : int 0
#>   ..$ primal_solution_status    : chr "Feasible"
#>   ..$ dual_solution_status      : chr "Infeasible"
#>   ..$ basis_validity            : int 1
#>   ..$ objective_function_value  : num -6
#>   ..$ mip_dual_bound            : num 0
#>   ..$ mip_gap                   : num Inf
#>   ..$ num_primal_infeasibilities: int 0
#>   ..$ max_primal_infeasibility  : num 0
#>   ..$ sum_primal_infeasibilities: num 0
#>   ..$ num_dual_infeasibilities  : int 1
#>   ..$ max_dual_infeasibility    : num 1
#>   ..$ sum_dual_infeasibilities  : num 1

3 Additional information

3.1 Sparse matrices

The HiGHs C++ library internally supports the matrix formats csc (compressed sparse column matrix) and csr (compressed Sparse Row array). The highs package currently supports the following matrix classes:

  1. "matrix" dense matrices,
  2. "dgCMatrix" compressed sparse column matrix from the Matrix package,
  3. "dgRMatrix" compressed sparse row matrix from the Matrix package,
  4. "matrix.csc" compressed sparse column matrix from the SparseM package,
  5. "matrix.csr" compressed sparse row matrix from the SparseM package,
  6. "simple_triplet_matrix" coordinate format from the slam package.

If the constraint matrix A is provided as dgCMatrix, dgRMatrix, matrix.csc or matrix.csr the underlying data is directly passed to HiGHs otherwise it is first transformed into the csc format an afterwards passed to HiGHs

library("Matrix")

A <- rbind(c(0, 1), c(1, 2), c(3, 2))
csc <- as(A, "CsparseMatrix")  # dgCMatrix
s0 <- highs_solve(L = c(1.0, 1), lower = c(0, 1), upper = c(4, Inf),
                  A = csc, lhs = c(-Inf, 5, 6), rhs = c(7, 15, Inf),
                  offset = 3)

csr <- as(A, "RsparseMatrix")  # dgRMatrix
s1 <- highs_solve(L = c(1.0, 1), lower = c(0, 1), upper = c(4, Inf),
                  A = csr, lhs = c(-Inf, 5, 6), rhs = c(7, 15, Inf),
                  offset = 3)

library("SparseM")

csc <- as.matrix.csc(A)
s2 <- highs_solve(L = c(1.0, 1), lower = c(0, 1), upper = c(4, Inf),
                  A = csc, lhs = c(-Inf, 5, 6), rhs = c(7, 15, Inf),
                  offset = 3)

csr <- as.matrix.csr(A)
s3 <- highs_solve(L = c(1.0, 1), lower = c(0, 1), upper = c(4, Inf),
                  A = csr, lhs = c(-Inf, 5, 6), rhs = c(7, 15, Inf),
                  offset = 3)

library("slam")
stm <- as.simple_triplet_matrix(A)
s4 <- highs_solve(L = c(1.0, 1), lower = c(0, 1), upper = c(4, Inf),
                  A = stm, lhs = c(-Inf, 5, 6), rhs = c(7, 15, Inf),
                  offset = 3)

4 Options

The function highs_available_solver_options lists the available solver options

d <- highs_available_solver_options()
d[["option"]] <- sprintf("`%s`", d[["option"]])
knitr::kable(d, row.names = FALSE)

| option | type | |:------------------------------------------------|:--------| | presolve | string | | solver | string | | parallel | string | | run_crossover | string | | time_limit | double | | read_solution_file | string | | read_basis_file | string | | write_model_file | string | | solution_file | string | | write_basis_file | string | | random_seed | integer | | ranging | string | | infinite_cost | double | | infinite_bound | double | | small_matrix_value | double | | large_matrix_value | double | | primal_feasibility_tolerance | double | | dual_feasibility_tolerance | double | | ipm_optimality_tolerance | double | | primal_residual_tolerance | double | | dual_residual_tolerance | double | | objective_bound | double | | objective_target | double | | threads | integer | | user_bound_scale | integer | | user_cost_scale | integer | | highs_debug_level | integer | | highs_analysis_level | integer | | simplex_strategy | integer | | simplex_scale_strategy | integer | | simplex_crash_strategy | integer | | simplex_dual_edge_weight_strategy | integer | | simplex_primal_edge_weight_strategy | integer | | simplex_iteration_limit | integer | | simplex_update_limit | integer | | simplex_min_concurrency | integer | | simplex_max_concurrency | integer | | log_file | string | | write_model_to_file | bool | | write_presolved_model_to_file | bool | | write_solution_to_file | bool | | write_solution_style | integer | | glpsol_cost_row_location | integer | | write_presolved_model_file | string | | output_flag | bool | | log_to_console | bool | | timeless_log | bool | | ipm_iteration_limit | integer | | pdlp_native_termination | bool | | pdlp_scaling | bool | | pdlp_iteration_limit | integer | | pdlp_e_restart_method | integer | | pdlp_d_gap_tol | double | | qp_iteration_limit | integer | | qp_nullspace_limit | integer | | iis_strategy | integer | | blend_multi_objectives | bool | | log_dev_level | integer | | log_githash | bool | | solve_relaxation | bool | | allow_unbounded_or_infeasible | bool | | use_implied_bounds_from_presolve | bool | | lp_presolve_requires_basis_postsolve | bool | | mps_parser_type_free | bool | | use_warm_start | bool | | keep_n_rows | integer | | cost_scale_factor | integer | | allowed_matrix_scale_factor | integer | | allowed_cost_scale_factor | integer | | ipx_dualize_strategy | integer | | simplex_dualize_strategy | integer | | simplex_permute_strategy | integer | | max_dual_simplex_cleanup_level | integer | | max_dual_simplex_phase1_cleanup_level | integer | | simplex_price_strategy | integer | | simplex_unscaled_solution_strategy | integer | | presolve_reduction_limit | integer | | restart_presolve_reduction_limit | integer | | presolve_substitution_maxfillin | integer | | presolve_rule_off | integer | | presolve_rule_logging | bool | | presolve_remove_slacks | bool | | simplex_initial_condition_check | bool | | no_unnecessary_rebuild_refactor | bool | | simplex_initial_condition_tolerance | double | | rebuild_refactor_solution_error_tolerance | double | | dual_steepest_edge_weight_error_tolerance | double | | dual_steepest_edge_weight_log_error_threshold | double | | dual_simplex_cost_perturbation_multiplier | double | | primal_simplex_bound_perturbation_multiplier | double | | dual_simplex_pivot_growth_tolerance | double | | presolve_pivot_threshold | double | | factor_pivot_threshold | double | | factor_pivot_tolerance | double | | start_crossover_tolerance | double | | less_infeasible_DSE_check | bool | | less_infeasible_DSE_choose_row | bool | | use_original_HFactor_logic | bool | | run_centring | bool | | max_centring_steps | integer | | centring_ratio_tolerance | double | | icrash | bool | | icrash_dualize | bool | | icrash_strategy | string | | icrash_starting_weight | double | | icrash_iterations | integer | | icrash_approx_iter | integer | | icrash_exact | bool | | icrash_breakpoints | bool | | mip_detect_symmetry | bool | | mip_allow_restart | bool | | mip_max_nodes | integer | | mip_max_stall_nodes | integer | | mip_max_start_nodes | integer | | mip_max_leaves | integer | | mip_max_improving_sols | integer | | mip_lp_age_limit | integer | | mip_pool_age_limit | integer | | mip_pool_soft_limit | integer | | mip_pscost_minreliable | integer | | mip_min_cliquetable_entries_for_parallelism | integer | | mip_report_level | integer | | mip_feasibility_tolerance | double | | mip_rel_gap | double | | mip_abs_gap | double | | mip_heuristic_effort | double | | mip_min_logging_interval | double | | mip_heuristic_run_rins | bool | | mip_heuristic_run_rens | bool | | mip_heuristic_run_root_reduced_cost | bool | | mip_heuristic_run_zi_round | bool | | mip_heuristic_run_shifting | bool | | mip_improving_solution_save | bool | | mip_improving_solution_report_sparse | bool | | mip_improving_solution_file | string | | mip_root_presolve_only | bool | | mip_lifting_for_probing | integer |

for additional information see the HiGHS homepage.

5 Status codes

HiGHS currently has the following status codes defined in HConst.h".

| enumerator | status | message | |:-------------------------|-------:|:-----------------------------------| | kNotset | 0 | "Not Set" | | kLoadError | 1 | "Load error" | | kModelError | 2 | "Model error" | | kPresolveError | 3 | "Presolve error" | | kSolveError | 4 | "Solve error" | | kPostsolveError | 5 | "Postsolve error" | | kModelEmpty | 6 | "Empty" | | kOptimal | 7 | "Optimal" | | kInfeasible | 8 | "Infeasible" | | kUnboundedOrInfeasible | 9 | "Primal infeasible or unbounded" | | kUnbounded | 10 | "Unbounded" | | kObjectiveBound | 11 | "Bound on objective reached" | | kObjectiveTarget | 12 | "Target for objective reached" | | kTimeLimit | 13 | "Time limit reached" | | kIterationLimit | 14 | "Iteration limit reached" | | kUnknown | 15 | "Unknown" | | kMin | 0 | "Not Set" | | kMax | 15 | "Unknown" |



Try the highs package in your browser

Any scripts or data that you put into this service are public.

highs documentation built on June 8, 2025, 10:36 a.m.