Skip to contents

The matrix route (model_to_lp(), solve_highs()) needs nothing beyond the ‘highs’ R package. The code-generation routes run external toolchains, and multimod has to find three executables:

Route Executable Looked up by
MathProg, solve_gmpl() glpsol get_multimod_glpsol()
JuMP, solve_jump() julia get_multimod_julia()
Pyomo, solve_pyomo() python get_multimod_python()

Each lookup checks, in this order, and stops at the first hit:

  1. an R option, set with set_multimod_python(), set_multimod_julia(), set_multimod_glpsol() (or the corresponding options, such as options(multimod.python_path = ...));
  2. an environment variable: MULTIMOD_PYTHON, MULTIMOD_JULIA, MULTIMOD_GLPSOL;
  3. a YAML configuration file, project-level .multimod.yml first, then the user-level file under tools::R_user_dir("multimod", "config");
  4. automatic detection: for Python the conda environment named multimod through reticulate; for glpsol the ‘glpsol’ R package, then the conda environment, then the PATH; for Julia the PATH.

multimod_config_show() prints what each lookup currently resolves to and where the value comes from.

Setting a path

For the current session:

set_multimod_python("C:/Users/me/.conda/envs/multimod/python.exe")
set_multimod_julia("C:/Julia-1.11/bin/julia.exe")
set_multimod_glpsol("C:/glpk/bin/glpsol.exe")

get_multimod_julia()

To make it permanent for one user, put the options in ~/.Rprofile (usethis::edit_r_profile() opens it):

options(
  multimod.python_path = "C:/Users/me/.conda/envs/multimod/python.exe",
  multimod.julia_path  = "C:/Julia-1.11/bin/julia.exe",
  multimod.glpsol_path = "C:/glpk/bin/glpsol.exe"
)

Environment variables suit CI and containers. In a shell:

export MULTIMOD_PYTHON=/usr/bin/python3
export MULTIMOD_JULIA=/usr/local/bin/julia
export MULTIMOD_GLPSOL=/usr/bin/glpsol

A YAML file suits a project shared by several people:

multimod_config_write(
  config = list(
    python = list(path = "C:/Users/me/.conda/envs/multimod/python.exe",
                  env_name = "multimod"),
    julia  = list(path = "C:/Julia-1.11/bin/julia.exe"),
    glpsol = list(path = "C:/glpk/bin/glpsol.exe")
  ),
  global = FALSE   # .multimod.yml in the working directory; TRUE = user level
)
multimod_config_path()        # where the project file is
multimod_config_read()

The file is plain YAML and can be edited by hand:

python:
  path: "C:/Users/me/.conda/envs/multimod/python.exe"
  env_name: "multimod"
julia:
  path: "C:/Julia-1.11/bin/julia.exe"
glpsol:
  path: "C:/glpk/bin/glpsol.exe"

Add .multimod.yml to .gitignore when the paths are user-specific.

To go back to automatic detection, clear the option:

GLPK

The ‘glpsol’ R package ships the glpsol executable, which multimod finds automatically:

A system GLPK works as well: brew install glpk on macOS, apt-get install glpk-utils on Debian and Ubuntu, winglpk or MSYS2 on Windows. The conda environment that mm_setup_python() creates also holds a copy. Check what will be used:

Julia

Install Julia from julialang.org and make sure the executable resolves:

get_multimod_julia()
system2(get_multimod_julia(), c("-e", "println(VERSION)"))

The generated model.jl needs the packages JuMP, HiGHS, Arrow, DataFrames and CSV. It installs any that are missing on its first run, which takes a few minutes; to do it beforehand:

using Pkg
Pkg.add(["JuMP", "HiGHS", "Arrow", "DataFrames", "CSV"])

Python

mm_setup_python() creates a conda environment named multimod with Python 3.14, installs pyomo, highspy, pyarrow and pandas with pip and GLPK with conda, and activates it through reticulate. Miniconda is installed first if there is none.

mm_check_python() reports the interpreter that will be used, its version and the packages that fail to import. solve_pyomo() uses the configured interpreter as it is; solve_pyomo(ensure_env = TRUE) checks it first and runs mm_setup_python() when it is not usable.

To use an existing interpreter instead, point to it and check it carries the packages a route needs:

set_multimod_python("/path/to/python")
mm_check_python(packages = c("pyomo", "highspy", "pyarrow"))

When a tool is not found

  • multimod_config_show() says which source each path comes from. A stale option or environment variable wins over everything below it.
  • Sys.which("julia") and Sys.which("glpsol") show what the PATH resolves. On Windows the conda environment’s bin directory is not on the PATH; multimod looks inside it for glpsol, but a shell will not.
  • mm_check_python() reports whether the interpreter solve_pyomo() will use carries the needed packages.