# The Solver API

While `highs_solve()` is convenient for one-shot problems, the solver API gives fine-grained control for building models incrementally, modifying problems, and performing warm-starts.

## Creating a Solver

Build a model and create a solver from it:

    library(highs)

    model <- highs_model(
      L = c(2, 4, 3),
      lower = 0,
      A = matrix(c(3, 4, 2, 2, 1, 2, 1, 3, 2), nrow = 3, byrow = TRUE),
      rhs = c(60, 40, 80),
      maximum = TRUE
    )
    solver <- hi_new_solver(model)

## Solving and Retrieving Results

    hi_solver_run(solver)
    #> [1] 0
    hi_solver_status_message(solver)
    #> [1] "Optimal"
    sol <- hi_solver_get_solution(solver)
    sol$col_value
    #> [1]  0.000000  6.666667 16.666667

## Solver Information

After solving, retrieve detailed solver information:

    info <- hi_solver_info(solver)
    info$objective_function_value
    #> [1] 76.66667
    info$simplex_iteration_count
    #> [1] 2
    info$primal_solution_status
    #> [1] "Feasible"

## Modifying the Problem

Change objective coefficients, bounds, and constraints without rebuilding from scratch:

    # Change the objective coefficient for variable 1 (0-based indexing)
    hi_solver_set_objective(solver, index = 0L, coeff = 10.0)
    #> [1] 0

    # Change variable bounds
    hi_solver_set_variable_bounds(solver, index = 0L, lower = 1.0, upper = 20.0)
    #> [1] 0

    # Change constraint bounds
    hi_solver_set_constraint_bounds(solver, index = 0L, lower = -Inf, upper = 50.0)
    #> [1] 0

    # Re-solve
    hi_solver_run(solver)
    #> [1] 0
    hi_solver_get_solution(solver)$col_value
    #> [1] 16.66667  0.00000  0.00000

## Adding Variables and Constraints

Grow the model dynamically:

    solver <- hi_new_solver(model)

    # Add a new variable with bounds [0, 15]
    hi_solver_add_vars(solver, lower = 0, upper = 15)
    #> [1] 0
    cat("Columns after add:", hi_solver_get_num_col(solver), "\n")
    #> Columns after add: 4

    # Add a new constraint: x1 + x2 + x3 + x4 <= 100
    hi_solver_add_rows(solver,
      lhs = -Inf, rhs = 100,
      start = 0L,
      index = 0L:3L,
      value = rep(1.0, 4)
    )
    #> [1] 0
    cat("Rows after add:", hi_solver_get_num_row(solver), "\n")
    #> Rows after add: 4

## Querying Model Data

    solver <- hi_new_solver(model)
    hi_solver_get_lp_costs(solver)
    #> [1] 2 4 3
    hi_solver_get_num_col(solver)
    #> [1] 3
    hi_solver_get_num_row(solver)
    #> [1] 3

## The `highs_solver()` Wrapper

For an object-oriented style, use `highs_solver()` which returns an environment with methods:

    hw <- highs_solver(model)
    hw$solve()
    #> ERROR:   getOptionIndex: Option "pdlp_features_off" is unknown
    #> [1] 0
    hw$status_message()
    #> [1] "Optimal"
    hw$solution()$col_value
    #> [1]  0.000000  6.666667 16.666667
    hw$info()$objective_function_value
    #> [1] 76.66667

    # Modify and re-solve
    hw$L(1, 10.0)     # set cost of variable 1 to 10
    #> [1] 0
    hw$vbounds(1, 1, 20)  # set bounds of variable 1 to [1, 20]
    #> [1] 0
    hw$solve()
    #> ERROR:   getOptionIndex: Option "pdlp_features_off" is unknown
    #> [1] 0
    hw$solution()$col_value
    #> [1] 20  0  0

## Reading and Writing Models

    solver <- hi_new_solver(model)
    temp <- tempfile(fileext = ".mps")
    hi_solver_write_model(solver, temp)
    #> WARNING: Column names are not present, or contain duplicates: using names with prefix "c", beginning with suffix 0
    #>
    #> WARNING: Row    names are not present, or contain duplicates: using names with prefix "r", beginning with suffix 0
    #>
    #> Writing the model to /tmp/RtmpRAr2Nn/file53de732c74f61.mps
    #> [1] 1

    # Read into a fresh solver
    solver2 <- hi_new_solver(highs_model(L = 0))
    hi_solver_read_model(solver2, temp)
    #> [1] 0
    hi_solver_run(solver2)
    #> [1] 0
    hi_solver_get_solution(solver2)$col_value
    #> [1]  0.000000  6.666667 16.666667
    unlink(temp)

## Version and Timing

    solver <- hi_new_solver(model)
    hi_solver_version(solver)
    #> [1] "1.14.0"
    hi_solver_run(solver)
    #> [1] 0
    hi_solver_get_run_time(solver)
    #> [1] 0.000241518