3 个不稳定版本
使用旧的 Rust 2015
0.1.0 | 2016年12月20日 |
---|---|
0.0.2 | 2015年6月29日 |
0.0.1 | 2015年6月28日 |
#1121 in 算法
78KB
1.5K SLoC
符号多项式
一个用于操作和评估符号整数多项式的 Rust 库。
模板类型参数
所有符号表达式都与三个模板类型相关联。
- I - 唯一标识单个符号变量的类型
- C - 每个单项式中的自由系数的类型
- P - 每个单项式中使用的幂的类型
概述
你可能会最常使用的类是 Polynomial<I, C, P>
,它代表任何符号多项式。创建单个变量(例如 a
、b
、c
...)的最简单方法是调用 variable(I id)
。这将是一个变量的唯一标识。从那里,你可以使用标准算术运算符与其他符号表达式以及常数一起使用。
如果你想要评估一个符号表达式,你可以调用它的 eval
方法,该方法需要你指定从唯一标识符到它们的赋值的映射。
你也可以使用自动推导来解决一组方程。
多项式和单项式的顺序基于从 I
上的顺序推导出的 分级逆字典序。注意,这需要为类型 I
实现比较运算符。
该库实现了 Display
,可以将任何表达式转换为可读的格式。此外,to_code
方法将幂表示为重复乘法,输出字符串看起来像代码片段。
一个缺点是所有运算符都定义为引用。
安装
只需在您的 Cargo.toml
文件中添加依赖项,然后导入包。
示例用法
以下是 examples
文件夹中找到的示例代码。
use std::collections::HashMap;
extern crate symbolic_polynomials;
use symbolic_polynomials::*;
type SymInt = Polynomial<String, i64, u8>;
pub fn main() {
// Create symbolic variables
let a: SymInt = variable("a".into());
let b: SymInt = variable("b".into());
let c: SymInt = variable("c".into());
// Build polynomials
// 5b + 2
let poly1 = &(&b * 5) + 2;
// ab
let poly2 = &a * &b;
// ab + ac + b + c
let poly3 = &(&b + &c) * &(&a + 1);
// a^2 - ab + 12
let poly4 = &(&(&a * &a) - &(&a * &b)) + 12;
// ac^2 + 3a + bc^2 + 3b + c^2 + 3
let poly5 = &(&(&a + &b) + 1) * &(&(&c * 2) + 3);
// floor(a^2, b^2)
let poly6 = floor(&(&b * &b), &(&a * &a));
// ceil(a^2, b^2)
let poly7 = ceil(&(&b * &b), &(&a * &a));
// min(ab + 12, ab + a)
let poly8 = min(&(&(&a * &b) + 12), &(&(&a * &b) + &a));
// max (ab + 12, ab + a)
let poly9 = max(&(&(&a * &b) + 12), &(&(&a * &b) + &a));
// max(floor(a^2, b) - 4, ceil(c, b) + 1)
let poly10 = max(&(&floor(&(&a *&a), &b) - 2), &(&ceil(&c, &b) + 1));
// Polynomial printing
println!("{}", (0..50).map(|_| "=").collect::<String>());
println!("Displaying polynomials");
println!("{}", poly1);
println!("{}", poly2);
println!("{}", poly3);
println!("{}", poly4);
println!("{}", poly5);
println!("{}", poly6);
println!("{}", poly7);
println!("{}", poly8);
println!("{}", poly9);
println!("{}", poly10);
println!("{}", (0..50).map(|_| "=").collect::<String>());
// Polynomial evaluation
let mut values = HashMap::<String, i64>::new();
values.insert("a".into(), 3);
values.insert("b".into(), 2);
values.insert("c".into(), 5);
println!("Evaluating for a = 3, b = 2, c = 5.");
println!("{} = {} [Expected 12]", poly1, poly1.eval(&values).unwrap());
println!("{} = {} [Expected 6]", poly2, poly2.eval(&values).unwrap());
println!("{} = {} [Expected 28]", poly3, poly3.eval(&values).unwrap());
println!("{} = {} [Expected 15]", poly4, poly4.eval(&values).unwrap());
println!("{} = {} [Expected 78]", poly5, poly5.eval(&values).unwrap());
println!("{} = {} [Expected 0]", poly6, poly6.eval(&values).unwrap());
println!("{} = {} [Expected 1]", poly7, poly7.eval(&values).unwrap());
println!("{} = {} [Expected 9]", poly8, poly8.eval(&values).unwrap());
println!("{} = {} [Expected 18]", poly9, poly9.eval(&values).unwrap());
println!("{} = {} [Expected 4]", poly10, poly10.eval(&values).unwrap());
println!("{}", (0..50).map(|_| "=").collect::<String>());
// Variable deduction
values.insert("a".into(), 5);
values.insert("b".into(), 3);
values.insert("c".into(), 8);
let implicit_values = vec![(poly1.clone(), poly1.eval(&values).unwrap()),
(poly2.clone(), poly2.eval(&values).unwrap()),
(poly3.clone(), poly3.eval(&values).unwrap())];
let deduced_values = deduce_values(&implicit_values).unwrap();
println!("Deduced values:");
println!("a = {} [Expected 5]", deduced_values["a"]);
println!("b = {} [Expected 3]", deduced_values["b"]);
println!("c = {} [Expected 8]", deduced_values["c"]);
println!("{}", (0..50).map(|_| "=").collect::<String>());
}
程序输出
==================================================
Displaying polynomials (string representation = code representation):
5b + 2 = 5 * b + 2
ab = a * b
ab + ac + b + c = a * b + a * c + b + c
a^2 - ab + 12 = a * a - a * b + 12
2ac + 3a + 2bc + 3b + 2c + 3 = 2 * a * c + 3 * a + 2 * b * c + 3 * b + 2 * c + 3
floor(b^2, a^2) = floor(b * b, a * a)
ceil(b^2, a^2) = ceil(b * b, a * a)
min(ab + 12, ab + a) = min(a * b + 12, a * b + a)
max(ab + 12, ab + a) = max(a * b + 12, a * b + a)
max(floor(a^2, b) - 2, ceil(c, b) + 1) = max(floor(a * a, b) - 2, ceil(c, b) + 1)
==================================================
Evaluating for a = 3, b = 2, c = 5.
5b + 2 = 12 [Expected 12]
ab = 6 [Expected 6]
ab + ac + b + c = 28 [Expected 28]
a^2 - ab + 12 = 15 [Expected 15]
2ac + 3a + 2bc + 3b + 2c + 3 = 78 [Expected 78]
floor(b^2, a^2) = 0 [Expected 0]
ceil(b^2, a^2) = 1 [Expected 1]
min(ab + 12, ab + a) = 9 [Expected 9]
max(ab + 12, ab + a) = 18 [Expected 18]
max(floor(a^2, b) - 2, ceil(c, b) + 1) = 4 [Expected 4]
==================================================
Deduced values:
a = 5 [Expected 5]
b = 3 [Expected 3]
c = 8 [Expected 8]
==================================================
您可以在 tests
文件夹中查看更多示例的测试。
限制
目前,用于解方程组的自动减法功能相当有限。主要原因是为了项目开发的目的,这已经足够了。一个更强大和完整的算法可能需要使用Grobner 基。
许可证
该项目受 Apache 2.0 许可证的约束。
贡献
如果您想以任何方式做出贡献,请提出一个问题或提交一个描述其功能的PR请求。
依赖项
~240KB