绝对值
AbsFunction 表示线性多项式的绝对值:
本页以 ospf-kotlin-core 中的当前实现作为唯一契约。
契约
- 输入:一个
LinearPolynomial<V>,名称为polynomial。 - 输出:非负
URealVar,通过resultPolynomial暴露。 - 当输入多项式无法由给定符号值求出时,
evaluate返回null;否则返回|p|。 V必须同时实现RealNumber<V>与NumberField<V>,常量和求值必须使用同一个IntoValue<V>转换器。
数学定义
对于求值后的输入值
求解器模型将其分解为非负部分:
并使用二进制选择变量
适用域与边界
数学函数接受任意有限实数。求解器编码需要可用的 Big-M 界。省略 bigM 时,实现会从 polynomial 的有限范围按侧推导(正部取其上界,负部取其下界的相反数);无法推导时退回库默认值(当前为 bigM。结果变量非负,但输入多项式可以为负。
当前 API
Kotlin
主要构造器/工厂为:
AbsFunction(
polynomial: LinearPolynomial<V>,
converter: IntoValue<V>,
bigM: V? = null,
name: String,
displayName: String? = null
)公开的辅助/结果变量为 resultVar、posVar、negVar 和 signVar;helperVariables 会注册这四个变量。resultPolynomial 是仅含 resultVar 的单项线性多项式。
Rust
源码:abs.rs
Rust 实现接收平展后的 Linear<V>,提供 AbsFunction::new(id, name, input)、AbsFunction::named(name, input) 和 AbsFunction::auto(input)。可通过 result_variable() 与 side_variable() 获取结果变量和符号辅助变量。注册变量有范围时会推导 Big-M,否则使用核心层回退值;Rust 构造器没有显式 big_m 参数。
AbsFunction::new(id: u64, name: &str, input: Linear<V>) -> Self
AbsFunction::named(name: impl AsRef<str>, input: Linear<V>) -> Self
AbsFunction::auto(input: Linear<V>) -> Self求解器数学模型
令
Kotlin 注册全部四个辅助变量。Rust 只注册一个结果变量和一个二值侧变量,并以
evaluate 与 solver 的差异
evaluate 直接求值 polynomial 并根据符号取值。求解器使用二进制分解,因此还依赖 bigM 足够大。在有效有限输入上两者表示同一个绝对值;但 Big-M 过小会使求解器模型不可行或排除正确值,而 evaluate 仍可能成功。
当前最小示例
import fuookami.ospf.kotlin.core.solver.value.IntoValue
import fuookami.ospf.kotlin.core.symbol.function.AbsFunction
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(
monomials = listOf(LinearMonomial(Flt64.one, x)),
constant = Flt64.zero
)
val abs = AbsFunction(
polynomial = xPoly,
converter = IntoValue.Identity,
name = "abs"
)
val value = abs.evaluate(mapOf<Symbol, Flt64>(x to Flt64(-3.0)))
check(value != null && (value eq Flt64(3.0)))use ospf_rust_core::symbol::flatten::{Linear, LinearMonomial};
use ospf_rust_core::symbol::function::AbsFunction;
use ospf_rust_core::symbol::FunctionSymbol;
use ospf_rust_core::token::{MutableTokenList, Token, VecTokenList};
use ospf_rust_core::variable::{ContinuousVariableItem, VariableId};
let x = ContinuousVariableItem::create(VariableId::standalone(1), "x");
let token = Token::from_generic(x, 0);
token.set_result(-3.0);
let mut tokens = VecTokenList::new();
tokens.add_token(token);
let input = Linear::new(vec![LinearMonomial::new(1.0, 0)], 0.0);
let abs = AbsFunction::named("abs", input);
let value = <AbsFunction as FunctionSymbol>::calculate_value(&abs, &tokens, false);
assert_eq!(value, Some(3.0));Rust 求值/注册覆盖:p0_evaluation_tests.rs
完整示例:AbsTest.kt
Core 验证:FunctionSymbolGenericRegistrationTest.kt