二次乘积
ProductFunction 将两个线性多项式的乘积表示为二次中间表达式。
NOTE
普通中间表达式是 registerConstraints 不提交独立约束;展开后的多项式由目标函数或外层约束直接消费。
契约
- 输入:
left: LinearPolynomial<V>和right: LinearPolynomial<V>。 - 输出表达式:展开后的
QuadraticPolynomial<V>,即。 - 中间符号直接求值会把两个线性表达式求值后相乘;token 表中缺少符号时沿求值路径返回
null。 - 泛型值要求
V : RealNumber<V>, V : Ring<V>, V : NumberField<V>,并配合IntoValue<V>转换器。 - 即使输入表达式使部分项退化为线性,该符号仍属于二次中间符号。
定义与数学模型
对于
展开式为
中间符号的多项式就是该展开式;仅表示表达式不需要辅助
求解器数学模型
Kotlin
作为中间表达式使用时不创建辅助变量,也不独立提交约束;求解器直接在目标函数或其他约束中接收二次展开式
registerConstraints 不提交独立约束,也不创建
Rust
Rust 同样不创建辅助变量,直接把
当前 API
Kotlin
源码:Product.kt(ProductFunction)
import fuookami.ospf.kotlin.core.solver.value.IntoValue
import fuookami.ospf.kotlin.core.symbol.function.ProductFunction
import fuookami.ospf.kotlin.core.token.AutoTokenTable
import fuookami.ospf.kotlin.math.algebra.number.Flt64
import fuookami.ospf.kotlin.math.symbol.Quadratic
import fuookami.ospf.kotlin.math.symbol.Symbol
import fuookami.ospf.kotlin.math.symbol.monomial.LinearMonomial
import fuookami.ospf.kotlin.math.symbol.polynomial.LinearPolynomial
import fuookami.ospf.kotlin.core.variable.RealVar
val x = RealVar("x")
val y = RealVar("y")
val left = LinearPolynomial(
listOf(LinearMonomial(Flt64.one, x)), Flt64.two
)
val right = LinearPolynomial(
listOf(LinearMonomial(Flt64.one, y)), -Flt64.one
)
val product = ProductFunction(
left = left,
right = right,
converter = IntoValue.Identity,
name = "product"
)
val tokens = AutoTokenTable<Flt64>(Quadratic, false)
tokens.add(listOf(x, y))
val value = product.prepare(
mapOf<Symbol, Flt64>(x to Flt64.two, y to Flt64(5.0)),
tokens,
IntoValue.Identity
)
check(value == Flt64(16.0))
tokens.close()Rust
Rust 通过 ProductFunction<V> 提供相同的表达式级乘积。构造器为:
ProductFunction::new(id: u64, name: &str, left: Linear<V>, right: Linear<V>) -> ProductFunction<V>相关公开操作包括 left_polynomial、right_polynomial、prepare、FunctionSymbol::calculate_value 和 QuadraticIntermediateSymbol::to_quadratic_polynomial。Rust 实现不注册辅助 token,也不返回机理约束,与 Kotlin 的 registerConstraints 空操作契约一致。
use ospf_rust_core::symbol::flatten::{Linear, LinearMonomial};
use ospf_rust_core::symbol::function::ProductFunction;
use ospf_rust_core::symbol::QuadraticIntermediateSymbol;
let left = Linear::new(vec![LinearMonomial::new(1.0, 0)], 2.0);
let right = Linear::new(vec![LinearMonomial::new(1.0, 1)], -1.0);
let product = ProductFunction::new(7, "product", left, right);
let expanded = product.to_quadratic_polynomial();
assert_eq!(*expanded.constant(), -2.0);泛型边界是实现使用的 Rust 算术 trait(求值时还需要 Clone + Debug + Send + Sync + 'static、Add、Mul 和 Zero)。默认类型为 f64,也是最小示例的选择。
evaluate 与 solver 的差异
中间求值 API(prepare、带 token 表的 evaluate 和结果列表 evaluate)直接计算乘积。二次机制注册把展开后的多项式作为二次表达式使用。直接调用 registerConstraints 不会增加约束行,也不会创建自由的乘积结果变量。
边界、tolerance 与 Undefined
两个线性输入都必须可求值;token 值缺失时返回 null。该算术没有基于 tolerance 的分类,也没有 TruthValue.Undefined 状态。大系数或大乘积仍必须能由所选泛型数值和 solver 表示。
示例与测试
import fuookami.ospf.kotlin.core.solver.value.IntoValue
import fuookami.ospf.kotlin.core.symbol.function.ProductFunction
import fuookami.ospf.kotlin.core.token.AutoTokenTable
import fuookami.ospf.kotlin.math.algebra.number.Flt64
import fuookami.ospf.kotlin.math.symbol.Quadratic
import fuookami.ospf.kotlin.math.symbol.Symbol
import fuookami.ospf.kotlin.math.symbol.monomial.LinearMonomial
import fuookami.ospf.kotlin.math.symbol.polynomial.LinearPolynomial
import fuookami.ospf.kotlin.core.variable.RealVar
val x = RealVar("x")
val y = RealVar("y")
val left = LinearPolynomial(
listOf(LinearMonomial(Flt64.one, x)), Flt64.two
)
val right = LinearPolynomial(
listOf(LinearMonomial(Flt64.one, y)), -Flt64.one
)
val product = ProductFunction(
left = left,
right = right,
converter = IntoValue.Identity,
name = "product"
)
val tokens = AutoTokenTable<Flt64>(Quadratic, false)
tokens.add(listOf(x, y))
val value = product.prepare(
mapOf<Symbol, Flt64>(x to Flt64.two, y to Flt64(5.0)),
tokens,
IntoValue.Identity
)
check(value == Flt64(16.0))
tokens.close()use ospf_rust_core::symbol::FunctionSymbol;
use ospf_rust_core::symbol::flatten::{Linear, LinearMonomial};
use ospf_rust_core::symbol::function::ProductFunction;
use ospf_rust_core::token::{MutableTokenList, Token, VecTokenList};
use ospf_rust_core::variable::{ContinuousVariableItem, VariableId};
let x = ContinuousVariableItem::create(VariableId::standalone(0), "x");
let y = ContinuousVariableItem::create(VariableId::standalone(1), "y");
let mut tokens = VecTokenList::<f64>::new();
let tx = Token::from_generic(x, 0);
tx.set_result(2.0);
tokens.add_token(tx);
let ty = Token::from_generic(y, 1);
ty.set_result(5.0);
tokens.add_token(ty);
let product = ProductFunction::new(
8,
"product",
Linear::new(vec![LinearMonomial::new(1.0, 0)], 2.0),
Linear::new(vec![LinearMonomial::new(1.0, 1)], -1.0),
);
assert_eq!(product.calculate_value(&tokens, false), Some(16.0));Core 展开/注册:
ProductFunctionTest.ktKotlin 表达式级聚焦测试:
ProductFunctionDedicatedTest.ktRust 实现与单元测试:
product.rsRust 表达式级聚焦测试:
function_symbol_product.rs