In-Step Range
InStepRangeFunction returns the greatest grid point not exceeding the upper expression:
It is a numeric stepping function, not a Boolean membership test. step must be finite and strictly positive, and the implementation rejects ub < lb when the value is evaluated or constrained.
Solver mathematical model
Let
The quotient is divided by step before flooring; therefore a range from 1 to 10 with step 3 returns 10, while a range from 1 to 9 returns 7.
Kotlin API
val stepped = InStepRangeFunction(
lb = lower,
ub = upper,
step = Flt64(3.0),
converter = IntoValue.Identity,
name = "stepped"
)Rust API
Rust now exposes the same numeric function:
let stepped = InStepRangeFunction::new(
1, "stepped", lower, upper, 3.0_f64,
);The former grid-membership function is explicitly named InStepRangeIndicatorFunction; use it when the required result is a binary “is this value one of the grid points?” flag.
Kotlin/Rust example
val stepped = InStepRangeFunction(
lb = LinearPolynomial(emptyList(), Flt64(1.0)),
ub = LinearPolynomial(emptyList(), Flt64(10.0)),
step = Flt64(3.0),
converter = IntoValue.Identity,
name = "stepped"
)
check(stepped.evaluate(emptyMap()) == Flt64(10.0))let stepped = InStepRangeFunction::new(1, "stepped", lower, upper, 3.0_f64);
assert_eq!(stepped.calculate_value(&tokens, false), Some(10.0));Tests and references
- Kotlin numeric focused test:
InStepRangeFunctionDedicatedTest.kt - Kotlin membership focused test:
InStepRangeIndicatorFunctionDedicatedTest.kt - Kotlin implementation:
InStepRange.kt - Rust numeric implementation:
in_step_range.rs - Rust numeric focused test:
function_symbol_in_step_range.rs - Rust membership focused test:
function_symbol_in_step_range_indicator.rs
The focused tests assert the numeric function's two Floor helpers and four registered rows, and the indicator's seven helpers and sixteen point/OR rows; they also cover grid boundaries, missing input, and invalid step/Big-M values.
The endpoint function has no unused Big-M parameter because FloorFunction does not use one. InStepRangeIndicatorFunction is available in both Kotlin and Rust for membership tests and uses the shared 1e-10 boundary epsilon. Kotlin accepts an optional bigM constructor argument; Rust uses InStepRangeIndicatorFunction::with_big_m when an explicit positive finite value is required, and new otherwise follows the token-derived/default policy.