MyNixOS website logo
Description

'HiGHS' Optimization Solver.

R interface to 'HiGHS', an optimization solver for solving mixed integer optimization problems with quadratic or linear objective and linear constraints.

R HIGHS Interface

Florian Schwendinger Updated: 2023-01-21

CRANstatus 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 Basic usage

library("highs")

args(highs_solve)
#> function (Q = NULL, L, lower, upper, A, lhs, rhs, types, maximum = FALSE, 
#>     offset = 0, control = list(), dry_run = FALSE) 
#> NULL

2.1 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 2
#>   ..$ ipm_iteration_count       : int 0
#>   ..$ 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.2 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] 2e+00 -1e+07
#>  $ objective_value: num -1e+07
#>  $ 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] 2e+00 -1e+07
#>   ..$ col_dual   : num [1:2] 0 0
#>   ..$ row_value  : num 2
#>   ..$ row_dual   : num 0
#>  $ info           :List of 18
#>   ..$ valid                     : logi TRUE
#>   ..$ mip_node_count            : num -1
#>   ..$ simplex_iteration_count   : int 0
#>   ..$ ipm_iteration_count       : int 0
#>   ..$ qp_iteration_count        : int 5
#>   ..$ crossover_iteration_count : int 0
#>   ..$ primal_solution_status    : chr "Feasible"
#>   ..$ dual_solution_status      : chr "Feasible"
#>   ..$ basis_validity            : int 0
#>   ..$ objective_function_value  : num -1e+07
#>   ..$ 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

3 Additional information

3.1 Sparse matrices

The HiGHsC++ 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)
optiontypecategory
allow_unbounded_or_infeasiblebooladvanced
allowed_cost_scale_factorintegeradvanced
allowed_matrix_scale_factorintegeradvanced
cost_scale_factorintegeradvanced
dual_simplex_cost_perturbation_multiplierdoubleadvanced
dual_simplex_pivot_growth_tolerancedoubleadvanced
dual_steepest_edge_weight_error_tolerancedoubleadvanced
dual_steepest_edge_weight_log_error_thresholddoubleadvanced
factor_pivot_thresholddoubleadvanced
factor_pivot_tolerancedoubleadvanced
keep_n_rowsintegeradvanced
less_infeasible_DSE_checkbooladvanced
less_infeasible_DSE_choose_rowbooladvanced
log_dev_levelintegeradvanced
lp_presolve_requires_basis_postsolvebooladvanced
max_dual_simplex_cleanup_levelintegeradvanced
max_dual_simplex_phase1_cleanup_levelintegeradvanced
mps_parser_type_freebooladvanced
no_unnecessary_rebuild_refactorbooladvanced
presolve_pivot_thresholddoubleadvanced
presolve_rule_loggingbooladvanced
presolve_rule_offintegeradvanced
presolve_substitution_maxfillinintegeradvanced
primal_simplex_bound_perturbation_multiplierdoubleadvanced
rebuild_refactor_solution_error_tolerancedoubleadvanced
run_crossoverbooladvanced
simplex_dualise_strategyintegeradvanced
simplex_initial_condition_checkbooladvanced
simplex_initial_condition_tolerancedoubleadvanced
simplex_permute_strategyintegeradvanced
simplex_price_strategyintegeradvanced
simplex_unscaled_solution_strategyintegeradvanced
start_crossover_tolerancedoubleadvanced
use_implied_bounds_from_presolvebooladvanced
use_original_HFactor_logicbooladvanced
dual_feasibility_tolerancedoublefile
glpsol_cost_row_locationintegerfile
highs_analysis_levelintegerfile
highs_debug_levelintegerfile
infinite_bounddoublefile
infinite_costdoublefile
ipm_iteration_limitintegerfile
ipm_optimality_tolerancedoublefile
large_matrix_valuedoublefile
log_filestringfile
objective_bounddoublefile
objective_targetdoublefile
primal_feasibility_tolerancedoublefile
random_seedintegerfile
simplex_crash_strategyintegerfile
simplex_dual_edge_weight_strategyintegerfile
simplex_iteration_limitintegerfile
simplex_max_concurrencyintegerfile
simplex_min_concurrencyintegerfile
simplex_primal_edge_weight_strategyintegerfile
simplex_scale_strategyintegerfile
simplex_strategyintegerfile
simplex_update_limitintegerfile
small_matrix_valuedoublefile
solution_filestringfile
threadsintegerfile
write_model_filestringfile
write_model_to_fileboolfile
write_solution_styleintegerfile
write_solution_to_fileboolfile
icrashboolicrash
icrash_approx_iterintegericrash
icrash_breakpointsboolicrash
icrash_dualizeboolicrash
icrash_exactboolicrash
icrash_iterationsintegericrash
icrash_starting_weightdoubleicrash
icrash_strategystringicrash
log_to_consoleboollogging
output_flagboollogging
mip_abs_gapdoublemip
mip_detect_symmetryboolmip
mip_feasibility_tolerancedoublemip
mip_heuristic_effortdoublemip
mip_lp_age_limitintegermip
mip_max_improving_solsintegermip
mip_max_leavesintegermip
mip_max_nodesintegermip
mip_max_stall_nodesintegermip
mip_min_cliquetable_entries_for_parallelismintegermip
mip_pool_age_limitintegermip
mip_pool_soft_limitintegermip
mip_pscost_minreliableintegermip
mip_rel_gapdoublemip
mip_report_levelintegermip
parallelstringrun-time
presolvestringrun-time
rangingstringrun-time
solverstringrun-time
time_limitdoublerun-time

for additional information see the HiGHS homepage.

5 Status codes

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

enumeratorstatusmessage
kNotset0"Not Set"
kLoadError1"Load error"
kModelError2"Model error"
kPresolveError3"Presolve error"
kSolveError4"Solve error"
kPostsolveError5"Postsolve error"
kModelEmpty6"Empty"
kOptimal7"Optimal"
kInfeasible8"Infeasible"
kUnboundedOrInfeasible9"Primal infeasible or unbounded"
kUnbounded10"Unbounded"
kObjectiveBound11"Bound on objective reached"
kObjectiveTarget12"Target for objective reached"
kTimeLimit13"Time limit reached"
kIterationLimit14"Iteration limit reached"
kUnknown15"Unknown"
kMin0"Not Set"
kMax15"Unknown"
Metadata

Version

0.1-10

License

Unknown

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows