Skip to content

Minimum ​

MinFunction represents the minimum of one or more linear polynomials:

y=min(p1,p2,…,pn).

Contract ​

  • Input: a non-empty List<LinearPolynomial<V>> (n >= 1).
  • Output: resultVar, a signed RealVar, exposed as resultPolynomial.
  • evaluate evaluates every input and returns their minimum; a missing symbol value makes it return null.
  • V must implement RealNumber<V> and NumberField<V>; pass the matching IntoValue<V> converter.

Mathematical definition ​

The implementation uses binary selectorVars si and the symmetric exact selector model:

y≤pi(i=1,…,n),y−pi−Misi≥−Mi,∑i=1nsi=1.

With the selector for one candidate equal to zero, that candidate is forced to equal the result; the remaining inequalities force the result to be no greater than every candidate.

Domain and boundaries ​

The solver result is a signed RealVar; when every candidate has finite bounds, the result range is tightened to the candidate bounds, so a negative minimum is representable. Inferred Big-M values require finite candidate bounds; otherwise the current fallback is 106, and an explicit bigM must cover all candidate gaps. When bounds are inferred, each candidate's Big-M is that candidate's upper bound minus the lowest candidate lower bound.

Current API ​

Kotlin ​

MinFunction is declared in the same source file as MaxFunction (there is no separate implementation file): Max.kt (MinFunction)

kotlin
MinFunction(
    polynomials: List<LinearPolynomial<V>>,
    bigM: V? = null,
    converter: IntoValue<V>,
    name: String = "min",
    displayName: String? = null
)

The companion factory also provides fromSymbols for LinearIntermediateSymbol<V> candidates.

Rust ​

Rust exposes MinFunction over flatten::Linear<V>:

rust
MinFunction::new(id: u64, name: &str, polynomials: Vec<Linear<V>>, exact: bool) -> MinFunction<V>

exact = true creates one binary selector per candidate and registers the exact selector model. exact = false keeps only the inequality envelope; unlike Kotlin, Rust has no bigM or converter argument on this constructor. The result is exposed by result_variable().

Solver mathematical model ​

With result y, candidates pi, and selectors si∈{0,1}, Kotlin and Rust exact = true pass

y−pi≤0(1≤i≤n),y−pi−Misi≥−Mi(1≤i≤n),∑i=1nsi=1.

Here the selected candidate has si=0. Rust exact = false keeps only y−pi≤0; equality with the minimum then requires maximization or another lower bound. Kotlin always registers the exact selector form.

evaluate versus solver ​

evaluate directly folds the candidate values and does not apply the solver result-range tightening. Solver registration tightens the result range to the candidate bounds and relies on valid Big-M values; an undersized Big-M can exclude the true minimum.

Examples and tests ​

kotlin
import fuookami.ospf.kotlin.core.solver.value.IntoValue
import fuookami.ospf.kotlin.core.symbol.function.MinFunction
import fuookami.ospf.kotlin.core.variable.RealVar
import fuookami.ospf.kotlin.math.algebra.number.Flt64
import fuookami.ospf.kotlin.math.symbol.Symbol
import fuookami.ospf.kotlin.math.symbol.inequality.eq
import fuookami.ospf.kotlin.math.symbol.monomial.LinearMonomial
import fuookami.ospf.kotlin.math.symbol.polynomial.LinearPolynomial

val x = RealVar("x")
val y = RealVar("y")
val xPoly = LinearPolynomial(listOf(LinearMonomial(Flt64.one, x)), Flt64.zero)
val yPoly = LinearPolynomial(listOf(LinearMonomial(Flt64.one, y)), Flt64.zero)
val min = MinFunction(
    polynomials = listOf(xPoly, yPoly),
    bigM = Flt64(10.0),
    converter = IntoValue.Identity,
    name = "min"
)
val value = min.evaluate(mapOf<Symbol, Flt64>(x to Flt64.two, y to Flt64(5.0)))
check(value != null && (value eq Flt64.two))
rust
use ospf_rust_core::symbol::flatten::{Linear, LinearMonomial};
use ospf_rust_core::symbol::function::MinFunction;

let x = Linear::new(vec![LinearMonomial::new(1.0, 0)], 0.0);
let y = Linear::new(vec![LinearMonomial::new(1.0, 1)], 0.0);
let min = MinFunction::new(1, "min", vec![x, y], true);
assert!(min.exact());
let _result = min.result_variable();

Complete example: MinTest.kt

Core validation: MaxAndMaskingFunctionGenericEvaluateTest.kt

Rust source and cross-language regression coverage: max.rs and gurobi_linear_function_kotlin_parity.rs.

MinMaxFunction and MaxMinFunction ​

MinMax(p1,…,pn)=maxipi,MaxMin(p1,…,pn)=minipi.

Despite their names, MinMaxFunction computes the maximum by delegating every evaluation, helper-variable, and constraint operation to an inner MaxFunction. MaxMinFunction computes the minimum by delegating to an inner MinFunction. The names describe the optimization interpretation, not a different aggregation algorithm. Both wrappers accept the same polynomials, optional bigM, converter, name, and optional displayName parameters. Their fromSymbols factories accept List<LinearIntermediateSymbol<V>> and return a LinearFunctionSymbolAdapter; the adapter is only a bridge to the intermediate-symbol API.

Source: MinMax.kt (MinMaxFunction and MaxMinFunction)

kotlin
val minMax = MinMaxFunction(
    polynomials = listOf(xPoly, yPoly),
    bigM = Flt64(10.0),
    converter = IntoValue.Identity,
    name = "min_max"
)
val maxMin = MaxMinFunction(
    polynomials = listOf(xPoly, yPoly),
    bigM = Flt64(10.0),
    converter = IntoValue.Identity,
    name = "max_min"
)
  • max: the corresponding maximum operator.
  • masking: binary selection of one polynomial versus zero.