| Title: | A Unified Contract and Auto-Selector for Efficient Optimisers |
|---|---|
| Description: | Provides a single typed problem contract over a curated portfolio of efficient optimisers, with an automatic per-instance selector that picks the best optimiser for a given problem and returns it in an 'stats::optim()'-compatible result object. The base solver runs with no suggested packages installed; each additional engine, and an optional mixture-valued mapper from 'proxymix', is loaded lazily only when used. |
| Authors: | Max Moldovan [aut, cre, cph] (ORCID: <https://orcid.org/0000-0001-9680-8474>) |
| Maintainer: | Max Moldovan <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-10-10 07:22:07 UTC |
| Source: | https://github.com/max578/optimix |
Returns the bare stats::optim()-shaped components of a result, for code
paths that expect exactly that list and nothing more.
as_optim(x, ...)as_optim(x, ...)
x |
An object to coerce. |
... |
Unused; for method consistency. |
A list with par, value, counts, convergence, and message.
Other results:
optimix(),
optimix_map()
res <- optimix(function(x) sum(x^2), c(-5, -5), c(5, 5), method = "base_optim") as_optim(res)res <- optimix(function(x) sum(x^2), c(-5, -5), c(5, 5), method = "base_optim") as_optim(res)
The federation's emit / adapt generic. The optimix_result method turns an
optimisation result into the shared orchestra_manifest contract:
inferential_target = "parameters", the optimum carried as a one-row
params table (the best parameter vector and its objective value), and the
engine provenance – which optimiser ran, why it was chosen, convergence,
the true evaluation count, and whether an uncertainty quantification is
available – in the typed summary and metadata. When the proxymix
mixture engine ran, metadata$solution_map carries the queryable mixture
over all optima, so a downstream consumer that needs a posterior over the
optimum (not just a point) can read it; a point engine sets
metadata$uncertainty_available = FALSE. The payload is integrity-hashed
so a consumer can verify it with verify_manifest().
as_orchestra_manifest(x, ...) ## S3 method for class 'optimix_result' as_orchestra_manifest(x, ..., run_id = NULL, seed = NA_integer_)as_orchestra_manifest(x, ...) ## S3 method for class 'optimix_result' as_orchestra_manifest(x, ..., run_id = NULL, seed = NA_integer_)
x |
An |
... |
Further arguments passed to methods. |
run_id |
Optional character run identifier; a content hash is derived when omitted, so two identical optima get the same identifier. |
seed |
Optional integer recorded for reproducibility. |
An orchestra_manifest S7 object.
Other orchestra manifest:
orchestra_manifest(),
verify_manifest()
res <- optimix(function(x) sum((x - 0.5)^2), c(-2, -2), c(2, 2), method = "base_optim") as_orchestra_manifest(res)res <- optimix(function(x) sum((x - 0.5)^2), c(-2, -2), c(2, 2), method = "base_optim") as_orchestra_manifest(res)
Reports every registered engine, whether its backend package is installed,
and the metadata method = "auto" uses to choose between them.
list_optimisers()list_optimisers()
A data frame, one row per engine, with columns name, package,
installed, global, noise_tolerant, and emits_map.
Other engines and registry:
optim_engine(),
register_optimiser()
list_optimisers()list_optimisers()
Marks the objective as deterministic, so repeated evaluations at the same
point return the same value. This is the default for optim_problem().
objective_deterministic()objective_deterministic()
An objective_spec with kind = "deterministic".
Other objective declarations:
objective_expensive(),
objective_noisy(),
objective_spec()
objective_deterministic()objective_deterministic()
Marks the objective as expensive to evaluate, so the selector prefers a surrogate-model (Bayesian-optimisation) engine that spends few evaluations.
objective_expensive()objective_expensive()
An objective_spec with kind = "expensive".
Other objective declarations:
objective_deterministic(),
objective_noisy(),
objective_spec()
objective_expensive()objective_expensive()
Marks the objective as stochastic, so the selector prefers a noise-tolerant optimiser.
objective_noisy(sd = NA_real_)objective_noisy(sd = NA_real_)
sd |
A single non-negative number, an optional estimate of the
observation-noise standard deviation. Use |
An objective_spec with kind = "noisy".
Other objective declarations:
objective_deterministic(),
objective_expensive(),
objective_spec()
objective_noisy(sd = 0.1)objective_noisy(sd = 0.1)
Describes the nature of the objective so the selector and the engines can
treat it appropriately. Construct one with objective_deterministic() or
objective_noisy() rather than calling the class directly.
objective_spec(kind = "deterministic", noise_sd = NA_real_)objective_spec(kind = "deterministic", noise_sd = NA_real_)
kind |
A single string: |
noise_sd |
A single number, an optional estimate of the observation
noise standard deviation, or |
An S7 object of class objective_spec.
Other objective declarations:
objective_deterministic(),
objective_expensive(),
objective_noisy()
objective_spec(kind = "noisy", noise_sd = 0.1)objective_spec(kind = "noisy", noise_sd = 0.1)
Abstract parent for the design spaces an optim_problem() can search. Each
concrete space declares the geometry an optimiser must respect. The
concrete spaces in this release are space_box() and
space_permutation().
opt_space()opt_space()
Not constructed directly; see space_box().
Other design spaces:
optim_problem(),
space_box(),
space_permutation()
Bundles the metadata that drives selection with the adapter that maps a
optim_problem to a backend optimiser and returns an
optimix_result. The accepts, global, noise_tolerant,
emits_map, and dimension fields are exactly what method = "auto" reads
when it chooses an engine, so registering an engine and teaching the selector
about it are one and the same act.
optim_engine( name = character(0), pkg = "base", accepts = "space_box", global = FALSE, uses_gradient = FALSE, noise_tolerant = FALSE, stochastic = FALSE, emits_map = FALSE, dim_min = 1, dim_max = Inf, available = function() NULL, run = function() NULL )optim_engine( name = character(0), pkg = "base", accepts = "space_box", global = FALSE, uses_gradient = FALSE, noise_tolerant = FALSE, stochastic = FALSE, emits_map = FALSE, dim_min = 1, dim_max = Inf, available = function() NULL, run = function() NULL )
name |
A single string naming the engine; this is the value passed to
|
pkg |
A single string naming the package the engine needs, or |
accepts |
A character vector of the design-space class names the engine
can search, such as |
global |
A single logical, |
uses_gradient |
A single logical, |
noise_tolerant |
A single logical, |
stochastic |
A single logical, |
emits_map |
A single logical, |
dim_min, dim_max
|
Single numbers bounding the problem dimensions the engine supports. |
available |
A function of no arguments returning a single logical: is the engine usable in the current session? |
run |
A function taking an optim_problem and returning an
|
An S7 object of class optim_engine.
Other engines and registry:
list_optimisers(),
register_optimiser()
optim_engine( name = "my_solver", pkg = "base", available = function() TRUE, run = function(problem) NULL )optim_engine( name = "my_solver", pkg = "base", available = function() TRUE, run = function(problem) NULL )
The typed contract that every optimix engine consumes. The easy facade
optimix() builds one of these from fn, lower, and upper; construct it
directly to set a noisy objective, a warm start, an evaluation budget, or a
seed.
fn |
The objective function. It takes a single numeric vector – a
point in the design space – and returns a single finite number to be
minimised (or maximised when |
space |
The design space to search, such as a |
objective |
An objective_spec describing the objective; defaults to
|
maximise |
A single logical. When |
max_evals |
A single number, the soft budget of objective evaluations,
or |
warm_start |
A numeric vector to start the search from, or a zero-length vector for none. When supplied it must match the space dimension. |
seed |
A single integer seed for reproducible stochastic search, or
|
delta_fn |
An optional incremental-scoring function with signature
|
An S7 object of class optim_problem.
Other design spaces:
opt_space(),
space_box(),
space_permutation()
optim_problem( fn = function(x) sum(x^2), space = space_box(lower = c(-5, -5), upper = c(5, 5)) )optim_problem( fn = function(x) sum(x^2), space = space_box(lower = c(-5, -5), upper = c(5, 5)) )
The single entry point. Pass a function with lower and upper bounds for
the easy path, or a prepared optim_problem() for full control. With
method = "auto" (the default) the best available optimiser is chosen for
the problem and recorded in the result's provenance.
optimix( fn, lower = NULL, upper = NULL, ..., method = "auto", maximise = FALSE, max_evals = NULL, goal = c("optimum", "map") ) minimise(fn, lower, upper, ...) maximise(fn, lower, upper, ...)optimix( fn, lower = NULL, upper = NULL, ..., method = "auto", maximise = FALSE, max_evals = NULL, goal = c("optimum", "map") ) minimise(fn, lower, upper, ...) maximise(fn, lower, upper, ...)
fn |
The objective function, taking a numeric vector and returning a
single finite number; or a prepared |
lower |
A numeric vector of lower bounds (easy path). |
upper |
A numeric vector of upper bounds (easy path). |
... |
Further arguments passed on to |
method |
The optimiser to use: |
maximise |
A single logical; maximise rather than minimise. Defaults to
|
max_evals |
A soft budget of objective evaluations, or |
goal |
What to return: |
An optimix_result: a list shaped like a stats::optim() result
(par, value, counts, convergence, message) with optimix extras
(provenance, map, diagnostics, problem). It has
print(), summary(), plot(), coef(), as.data.frame(), and
as_optim() methods. Results embed the problem, including the objective
closure and its environment, and are therefore session objects;
as_optim() gives the minimal durable form for storage.
Other results:
as_optim(),
optimix_map()
# Easy path: minimise a quadratic on a box. optimix(function(x) sum(x^2), lower = c(-5, -5), upper = c(5, 5), method = "base_optim") # Power path: a prepared problem. prob <- optim_problem( fn = function(x) sum((x - 1)^2), space = space_box(lower = c(-5, -5), upper = c(5, 5)) ) optimix(prob, method = "base_optim")# Easy path: minimise a quadratic on a box. optimix(function(x) sum(x^2), lower = c(-5, -5), upper = c(5, 5), method = "base_optim") # Power path: a prepared problem. prob <- optim_problem( fn = function(x) sum((x - 1)^2), space = space_box(lower = c(-5, -5), upper = c(5, 5)) ) optimix(prob, method = "base_optim")
Returns the distinct optima of fn over a box, rather than a single argmin.
Natively it runs a local search from many starts and clusters the results;
when a new-enough proxymix is installed it returns a calibrated
Gaussian-mixture map over the optima instead.
optimix_map( fn, lower, upper, ..., n_starts = NULL, tol = 0.05, max_evals = NULL )optimix_map( fn, lower, upper, ..., n_starts = NULL, tol = 0.05, max_evals = NULL )
fn |
The objective function: takes a numeric vector, returns a single finite number to be minimised. |
lower, upper
|
Numeric vectors of box bounds, of equal length. |
... |
Further arguments passed on to |
n_starts |
The number of local-search starts (native path); defaults to
|
tol |
The merge distance for clustering optima, as a fraction of the box
width. Defaults to |
max_evals |
The per-start local-search budget, or |
An optimix_map: a list with modes (a matrix, one optimum per
row, best first), values, n, source ("native" or "proxymix"),
and, on the proxymix path, map (the queryable mixture).
Other results:
as_optim(),
optimix()
# A double well with two optima at (+/-1, 0). optimix_map( function(x) (x[1]^2 - 1)^2 + x[2]^2, lower = c(-2, -2), upper = c(2, 2) )# A double well with two optima at (+/-1, 0). optimix_map( function(x) (x[1]^2 - 1)^2 + x[2]^2, lower = c(-2, -2), upper = c(2, 2) )
A versioned, hashed, provenance-complete S7 result object,
property-compatible with the federation's reference orchestra_manifest.
An optimix_result is adapted into one through as_orchestra_manifest():
the optimum rides in params (inferential_target = "parameters"), the
engine, convergence and uncertainty-availability ride in metadata and the
typed summary, and the payload is integrity-hashed so a tampered optimum
is detected downstream.
An S7 object of class orchestra_manifest.
as_orchestra_manifest(), verify_manifest()
Other orchestra manifest:
as_orchestra_manifest(),
verify_manifest()
# A minimal hand-built manifest; as_orchestra_manifest() fills these # slots (and a real payload hash) from an optimix result. m <- orchestra_manifest( emitter_package = "optimix", emitter_version = "0.0.0.9000", inferential_target = "parameters", run_id = "example-0001", method = "optimix:base_optim", params = data.frame(par1 = 0.5, value = 0.25), timestamp = Sys.time(), data_hash = "sha256:unhashed-example" ) m@run_id# A minimal hand-built manifest; as_orchestra_manifest() fills these # slots (and a real payload hash) from an optimix result. m <- orchestra_manifest( emitter_package = "optimix", emitter_version = "0.0.0.9000", inferential_target = "parameters", run_id = "example-0001", method = "optimix:base_optim", params = data.frame(par1 = 0.5, value = 0.25), timestamp = Sys.time(), data_hash = "sha256:unhashed-example" ) m@run_id
Adds an optim_engine to the registry so it can be selected by name or by
method = "auto". Registering an engine with the same name as an existing
one replaces it; replacing one of the built-in engines additionally emits a
warning, since it changes what method = "auto" can dispatch to.
register_optimiser(engine)register_optimiser(engine)
engine |
An optim_engine to register. |
The engine name, invisibly.
Other engines and registry:
list_optimisers(),
optim_engine()
engine <- optim_engine( name = "my_solver", pkg = "base", available = function() TRUE, run = function(problem) NULL ) register_optimiser(engine) "my_solver" %in% list_optimisers()$nameengine <- optim_engine( name = "my_solver", pkg = "base", available = function() TRUE, run = function(problem) NULL ) register_optimiser(engine) "my_solver" %in% list_optimisers()$name
A continuous, real-valued design space bounded below and above by vectors of
equal length. This is the design space the easy facade optimix()
constructs from its lower and upper arguments.
space_box(lower = integer(0), upper = integer(0))space_box(lower = integer(0), upper = integer(0))
lower |
A numeric vector of lower bounds, one per dimension. Every
element must be finite and not greater than its |
upper |
A numeric vector of upper bounds, the same length as |
An S7 object of class space_box.
Other design spaces:
opt_space(),
optim_problem(),
space_permutation()
space_box(lower = c(-5, -5), upper = c(5, 5))space_box(lower = c(-5, -5), upper = c(5, 5))
A combinatorial design space whose points are permutations of seq_len(n).
Use it for ordering and assignment problems via the powerful path:
optim_problem(fn, space = space_permutation(n)), where fn takes a
permutation (an integer vector).
space_permutation(n = integer(0))space_permutation(n = integer(0))
n |
A single integer of at least 2: the number of items to order. |
An S7 object of class space_permutation.
Other design spaces:
opt_space(),
optim_problem(),
space_box()
space_permutation(5)space_permutation(5)
Recomputes the payload hash from the object's own load-bearing slots and
compares it to the stored data_hash. A mismatch means the payload was
modified after emission. Matches the reference contract's
verify_manifest().
verify_manifest(m)verify_manifest(m)
m |
An |
A list with logical ok and a human-readable message.
Other orchestra manifest:
as_orchestra_manifest(),
orchestra_manifest()
res <- optimix(function(x) sum(x^2), c(-5, -5), c(5, 5), method = "base_optim") m <- as_orchestra_manifest(res) verify_manifest(m)res <- optimix(function(x) sum(x^2), c(-5, -5), c(5, 5), method = "base_optim") m <- as_orchestra_manifest(res) verify_manifest(m)