Skip to content

向下取整 ​

FloorFunction 表示线性多项式的向下取整:

y=⌊p⌋.

契约 ​

  • 输入:x: LinearPolynomial<V>。
  • 输出:IntVar(resultVar),通过 resultPolynomial 暴露。
  • 输入无法求值时,evaluate 返回 null;否则返回 floor(p)。
  • 没有除数 d:此 API 是 floor(p),不是 floor(p / d)。
  • bigM 作为兼容参数保留但未使用;当前编码不使用 Big-M。

数学定义 ​

对于有限实数输入,

⌊p⌋=k⟺k≤p<k+1.

solver 使用 epsilon = NONZERO_TOLERANCE 将严格上界表示为

p≥k,p≤k+1−ε,

并注册 resultVar = k。

适用域与边界 ​

数学函数接受任意有限实数,包括负值。严格上界通过容差实现,因此整数边界下方 epsilon 范围内的值可能在 solver 模型中受到影响;远离该范围的普通值不受影响。kVar 与 resultVar 都是整数变量。

当前 API ​

Kotlin ​

源码:Floor.kt(构造、求值与约束)

kotlin
FloorFunction(
    x: LinearPolynomial<V>,
    converter: IntoValue<V>,
    bigM: V? = null,
    name: String,
    displayName: String? = null
)

Rust ​

源码:floor.rs

Rust 接受平展后的 Linear<V>,并提供 FloorFunction::new(id, name, input)、FloorFunction::named(name, input) 与 FloorFunction::auto(input)。input_polynomial()、result_variable() 和 integer_variable() 暴露输入及辅助变量。结果变量是与辅助整数变量关联的 ContinuousVariableItem;Rust 没有调用方可传入的 big_m 或 tolerance 参数,机理层使用固定的 ROUNDING_EPSILON = 1e-10 边界。

rust
FloorFunction::new(id: u64, name: &str, input: Linear<V>) -> Self
FloorFunction::named(name: impl AsRef<str>, input: Linear<V>) -> Self
FloorFunction::auto(input: Linear<V>) -> Self

求解器数学模型 ​

令 k 为整数辅助变量、y 为结果变量。实际传给求解器的约束为

p−k≥0,p−k≤1−ε,y−k=0.

这里没有 Big-M 约束。Kotlin 的 k、y 都是整数变量;Rust 通过最后一条等式把连续结果变量连接到整数变量 k。

evaluate 与 solver 的差异 ​

evaluate 通过 IntoValue 转换输入并调用数值类型的 floor。solver 注册整数变量和带 epsilon 的不等式。差异仅限于严格边界的数值处理;bigM 不影响此函数。

当前最小示例 ​

kotlin
import fuookami.ospf.kotlin.core.solver.value.IntoValue
import fuookami.ospf.kotlin.core.symbol.function.FloorFunction
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 xPoly = LinearPolynomial(listOf(LinearMonomial(Flt64.one, x)), Flt64.zero)
val floor = FloorFunction(
    x = xPoly,
    converter = IntoValue.Identity,
    name = "floor"
)
val value = floor.evaluate(mapOf<Symbol, Flt64>(x to Flt64(1.8)))
check(value != null && (value eq Flt64.one))
rust
use ospf_rust_core::symbol::flatten::Linear;
use ospf_rust_core::symbol::function::FloorFunction;
use ospf_rust_core::symbol::FunctionSymbol;
use ospf_rust_core::token::VecTokenList;

let function = FloorFunction::named("floor", Linear::new(vec![], 1.8));
let value = <FloorFunction as FunctionSymbol>::calculate_value(
    &function,
    &VecTokenList::<f64>::new(),
    false,
);
assert_eq!(value, Some(1.0));

完整示例:FloorTest.kt

Core 验证:FunctionSymbolDiscreteGenericEvaluateTest.kt

Rust 实现与单元测试:floor.rs

相关页面 ​

  • ceiling:向上取整对应运算。
  • rounding:最近整数编码,半整数规则不同。
  • mod:使用缩放值的 floor,但要求正除数。