% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/set_solver.R
\name{set_solver}
\alias{set_solver}
\title{Configure solver settings}
\usage{
set_solver(
  x,
  solver = c("auto", "gurobi", "cplex", "cbc", "symphony"),
  gap_limit = NULL,
  time_limit = NULL,
  solution_limit = NULL,
  cores = NULL,
  verbose = FALSE,
  log_file = NULL,
  write_log = NULL,
  solver_params = list(),
  ...
)
}
\arguments{
\item{x}{A \code{Problem} object.}

\item{solver}{Character string indicating the solver backend to use. Must be
one of \code{"auto"}, \code{"gurobi"}, \code{"cplex"},
\code{"cbc"}, or \code{"symphony"}.}

\item{gap_limit}{Optional numeric value in \eqn{[0,1]} giving the relative
optimality gap for mixed-integer optimization. If \code{NULL}, the
previously stored value is kept unchanged.}

\item{time_limit}{Optional non-negative numeric value giving the maximum
solving time in seconds. If \code{NULL}, the previously stored value is
kept unchanged.}

\item{solution_limit}{Optional logical flag controlling backend-specific
early stopping after feasible solution discovery. If \code{NULL}, the
previously stored value is kept unchanged.}

\item{cores}{Optional positive integer giving the number of CPU cores to use.
If \code{NULL}, the previously stored value is kept unchanged.}

\item{verbose}{Optional logical flag indicating whether the solver should
print log output. If \code{NULL}, the previously stored value is kept
unchanged.}

\item{log_file}{Optional character string giving the name of the
solver log file. If \code{NULL}, the previously stored value is kept
unchanged.}

\item{write_log}{Optional logical flag indicating whether solver output
should be written to a file. If \code{NULL}, the previously stored value is
kept unchanged.}

\item{solver_params}{Named list of solver-specific parameters. These are
merged with previously stored backend-specific parameters rather than
replacing them completely.}

\item{...}{Additional named solver-specific parameters. These are merged into
\code{solver_params}. For example, \code{MIPFocus = 1} for Gurobi.}
}
\value{
An updated \code{Problem} object with modified solver settings stored
in \code{x$data$solve_args}.
}
\description{
Store solver configuration inside a \code{Problem} object so that
\code{\link{solve}} can later run using the stored backend and runtime
options.

This function does not build or solve the optimization model. It only updates
the solver configuration stored in \code{x$data$solve_args}.
}
\details{
\strong{Purpose}

The \code{multiscape} workflow separates problem specification from solver
configuration. Problem data, actions, effects, targets, objectives, and
methods are stored in the \code{Problem} object, and solver settings are
stored separately in \code{x$data$solve_args}.

This function allows solver options to be configured once and reused later
through \code{\link{solve}(x)} without repeating the same arguments each time.

\strong{Stored fields}

The solver configuration is stored in \code{x$data$solve_args}. Typical
entries include:
\itemize{
\item \code{solver},
\item \code{gap_limit},
\item \code{time_limit},
\item \code{solution_limit},
\item \code{cores},
\item \code{verbose},
\item \code{write_log},
\item \code{log_file},
\item \code{solver_params}.
}

\strong{Incremental update semantics}

This function updates solver settings incrementally.

If an argument is supplied as \code{NULL}, the previously stored value is
kept unchanged. Therefore, repeated calls can be used to modify only selected
components of the solver configuration.

For example, a user may first configure the solver backend and time limit,
and later update only the optimality gap or only a backend-specific
parameter.

\strong{Gap limit}

The argument \code{gap_limit} is interpreted as a relative optimality gap for
mixed-integer optimization. It must lie in \eqn{[0,1]}.

If the solver stops with incumbent value \eqn{z^{\mathrm{inc}}} and best
bound \eqn{z^{\mathrm{bd}}}, then the exact stopping rule depends on the
solver backend, but conceptually \code{gap_limit} controls the maximum
accepted relative difference between the incumbent and the bound.

\strong{Time limit}

The argument \code{time_limit} is interpreted as a maximum wall-clock time in
seconds allowed for the solver.

\strong{Solution limit}

The argument \code{solution_limit} is stored as a logical flag. Its exact
meaning depends on the backend-specific solving layer, but conceptually it
requests early termination after finding a feasible solution according to the
behaviour supported by the chosen solver.

\strong{Cores}

The argument \code{cores} specifies the number of CPU cores to use. If the
requested number exceeds the number of detected cores, it is capped to the
detected maximum with a warning.

\strong{Verbose output and log files}

The arguments \code{verbose}, \code{write_log}, and \code{log_file}
control how solver logging is handled. These options are stored and later
interpreted by the solving layer for the selected backend.

\strong{Solver-specific parameters}

Additional backend-specific parameters can be passed in two ways:
\itemize{
\item through the named list \code{solver_params},
\item through additional named arguments in \code{...}.
}

These two sources are merged, and the result is then merged with any
previously stored \code{solver_params}. Existing parameters are therefore
preserved unless explicitly overwritten.

This is particularly useful for backend-specific controls such as node
selection, emphasis parameters, tolerances, or heuristics.

\strong{Supported backends}

The \code{solver} argument selects the backend to be used later by
\code{\link{solve}}. Supported values are:
\itemize{
\item \code{"auto"}: let the solving layer choose an available backend,
\item \code{"gurobi"},
\item \code{"cplex"},
\item \code{"cbc"},
\item \code{"symphony"}.
}

This function only stores the requested backend. Availability of the backend
is checked later when solving.
}
\examples{
pu_tbl <- data.frame(
  id = 1:4,
  cost = c(1, 2, 3, 4)
)

feat_tbl <- data.frame(
  id = 1:2,
  name = c("feature_1", "feature_2")
)

dist_feat_tbl <- data.frame(
  pu = c(1, 1, 2, 3, 4),
  feature = c(1, 2, 2, 1, 2),
  amount = c(5, 2, 3, 4, 1)
)

x <- create_problem(
  pu = pu_tbl,
  features = feat_tbl,
  dist_features = dist_feat_tbl,
  cost = "cost"
)

x1 <- set_solver(
  x,
  solver = "cbc",
  gap_limit = 0.01,
  time_limit = 300,
  cores = 2,
  verbose = TRUE
)

x1$data$solve_args

# Update only selected settings
x2 <- set_solver(
  x1,
  gap_limit = 0.05,
  solver_params = list(randomSeed = 123)
)

x2$data$solve_args

}
\seealso{
\code{\link{solve}},
\code{\link{set_solver_gurobi}},
\code{\link{set_solver_cplex}},
\code{\link{set_solver_cbc}},
\code{\link{set_solver_symphony}}
}
