# HiGHS.jl

[![Build Status](https://github.com/jump-dev/HiGHS.jl/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/jump-dev/HiGHS.jl/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/jump-dev/HiGHS.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/jump-dev/HiGHS.jl)

[HiGHS.jl](https://github.com/jump-dev/HiGHS.jl) is a wrapper for the
[HiGHS](https://highs.dev) solver.

It has two components:

 - a thin wrapper around the complete C API
 - an interface to [MathOptInterface](https://github.com/jump-dev/MathOptInterface.jl)

## Affiliation

This wrapper is maintained by the JuMP community and is not an official project
of the HiGHS developers.

## Getting help

If you need help, please ask a question on the [JuMP community forum](https://jump.dev/forum).

If you have a reproducible example of a bug, please [open a GitHub issue](https://github.com/jump-dev/HiGHS.jl/issues/new).

## License

`HiGHS.jl` is licensed under the [MIT License](https://github.com/jump-dev/HiGHS.jl/blob/master/LICENSE.md).

The underlying solver, [ERGO-Code/HiGHS](https://github.com/ERGO-Code/HiGHS), is
licensed under the [MIT license](https://github.com/ERGO-Code/HiGHS/blob/master/LICENSE).

## Citation

If you use HiGHS in an academic context, please cite the following article:

Huangfu, Q., & Hall, J.A.J. (2018). Parallelizing the dual revised simplex
method. _Mathematical Programming Computation_, 10(1), 119-142.
DOI: [10.1007/s12532-017-0130-5](https://doi.org/10.1007/s12532-017-0130-5)

## Installation

Install HiGHS as follows:
```julia
import Pkg
Pkg.add("HiGHS")
```

In addition to installing the HiGHS.jl package, this will also download and
install the HiGHS binaries. You do not need to install HiGHS separately.

To use a custom binary, read the [Custom solver binaries](https://jump.dev/JuMP.jl/stable/developers/custom_solver_binaries/)
section of the JuMP documentation.

## Use with JuMP

To use HiGHS with JuMP, use `HiGHS.Optimizer`:

```julia
using JuMP, HiGHS
model = Model(HiGHS.Optimizer)
# Set options as needed, for example:
set_attribute(model, "presolve", "on")
set_attribute(model, "time_limit", 60.0)
```

## MathOptInterface API

The HiGHS optimizer supports the following constraints and attributes.

List of supported objective functions:

 * [`MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}`](@ref)
 * [`MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{Float64}}`](@ref)

List of supported variable types:

 * [`MOI.Reals`](@ref)

List of supported constraint types:

 * [`MOI.ScalarAffineFunction{Float64}`](@ref) in [`MOI.EqualTo{Float64}`](@ref)
 * [`MOI.ScalarAffineFunction{Float64}`](@ref) in [`MOI.GreaterThan{Float64}`](@ref)
 * [`MOI.ScalarAffineFunction{Float64}`](@ref) in [`MOI.Interval{Float64}`](@ref)
 * [`MOI.ScalarAffineFunction{Float64}`](@ref) in [`MOI.LessThan{Float64}`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.EqualTo{Float64}`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.GreaterThan{Float64}`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.Integer`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.Interval{Float64}`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.LessThan{Float64}`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.Semicontinuous{Float64}`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.Semiinteger{Float64}`](@ref)
 * [`MOI.VariableIndex`](@ref) in [`MOI.ZeroOne`](@ref)

List of supported model attributes:

 * [`MOI.Name()`](@ref)
 * [`MOI.ObjectiveSense()`](@ref)

## Options

See the [HiGHS documentation](https://ergo-code.github.io/HiGHS/dev/options/definitions/)
for a full list of the available options.

### Infeasibility certificates

By default, HiGHS.jl will attempt to compute an infeasibility certificate when
the primal or dual is infeasible. If you do not require the certificate, set
the `HiGHS.ComputeInfeasibilityCertificate` attribute to `false`:

```julia
using JuMP, HiGHS
model = Model(HiGHS.Optimizer)
set_attribute(model, HiGHS.ComputeInfeasibilityCertificate(), false)
```

## C API

The C API can be accessed via `HiGHS.Highs_xxx` functions, where the names and
arguments are identical to the C API.

## Threads

HiGHS uses a global scheduler that is shared between threads.

Before changing the number of threads using `MOI.Threads()`, you must call
`Highs_resetGlobalScheduler(1)`:
```julia
using JuMP, HiGHS
model = Model(HiGHS.Optimizer)
Highs_resetGlobalScheduler(1)
set_attribute(model, MOI.NumberOfThreads(), 1)
```

If modifying the number of HiGHS threads across different Julia threads, be sure
to read the docstring of `Highs_resetGlobalScheduler`. In particular, resetting
the scheduler is not thread-safe.

## HiPO

HiGHS v1.13 and later are compiled with [`libblastrampoline`](https://github.com/JuliaLinearAlgebra/libblastrampoline)
(LBT), a library that can change between BLAS backends at runtime.

The default BLAS backend is [OpenBLAS](https://github.com/OpenMathLib/OpenBLAS),
and we rely on the Julia artifact `OpenBLAS32_jll.jl` if no backend is loaded
before `using HiGHS`.

Using LBT, we can also switch dynamically to other BLAS backends such as Intel
MKL and Apple Accelerate. Because HiPO heavily relies on BLAS routines, using an
optimized backend for a particular platform can improve the performance.

### MKL

If you have [MKL.jl](https://github.com/JuliaLinearAlgebra/MKL.jl) installed,
switch to MKL by adding `using MKL` to your code:

```julia
using MKL
using JuMP, HiGHS
model = Model(HiGHS.Optimizer)
set_attribute(model, "solver", "hipo")
```

### AppleAccelerate

If you are using macOS, and you have [AppleAccelerate.jl](https://github.com/JuliaLinearAlgebra/AppleAccelerate.jl)
installed, switch to accelerate by adding `using AppleAccelerate` to your code:

```julia
using AppleAccelerate
using JuMP, HiGHS
model = Model(HiGHS.Optimizer)
set_attribute(model, "solver", "hipo")
```
