3 个不稳定版本

使用旧的 Rust 2015

0.1.0 2016年12月20日
0.0.2 2015年6月29日
0.0.1 2015年6月28日

#1121 in 算法

Apache-2.0

78KB
1.5K SLoC

符号多项式

Build Status Documentation License

一个用于操作和评估符号整数多项式的 Rust 库。

模板类型参数

所有符号表达式都与三个模板类型相关联。

  1. I - 唯一标识单个符号变量的类型
  2. C - 每个单项式中的自由系数的类型
  3. P - 每个单项式中使用的幂的类型

概述

你可能会最常使用的类是 Polynomial<I, C, P>,它代表任何符号多项式。创建单个变量(例如 abc ...)的最简单方法是调用 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