1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
//! The crate provides manipulation, calculation and evaluation of integer polynomials. //! //! The central struct of the crate is `Polynomial<I, C, P>`. The three generic arguments //! specify the types of three internal parts: //! //! `I: Id` - the type which uniquely identifies a single variable variable, e.g. if we have a^x , //! then `a: Id`. Note that this does not mean that it is an `Integer`, but rather it is a type //! which can uniquely defined variables. For instance one can use a `String` by naming each //! variable. Importantly, the ordering of `I` defines the total ordering of the monomials //! which is used to define the ordering of the polynomials as well - //! [Wikipedia](https://en.wikipedia.org/wiki/Gr%C3%B6bner_basis#Monomial_ordering). //! //! `C: Coefficient` - the variable `Integer` type of the internal coefficients for each monomial. //! The `Polynomial<C, I, P>` will have implemented standard operators for interacting with type `C`. //! Whenever you evaluate a polynomial, the output would be of this type. //! //! `P: Power` - the `Integer` type of the power values of each monomial, e.g. if we have a^x , //! then `x: Power`. Note that it is required that `P` is an `Unsigned` type. //! //! The choice of `C` and `P` should depend on the problem you are using the library for. If you //! do not expect too high power values setting `P` to `u8` or `u16` should suffice. //! In all of the tests `Polynomial<String, i64, u8>` is used. //! //! # 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!("{}", (0..50).map(|_| "=").collect::<String>()); //! println!("Displaying polynomials (string representation = code representation):"); //! println!("{} = {}", poly1, poly1.to_code(&|x: String| x)); //! println!("{} = {}", poly2, poly2.to_code(&|x: String| x)); //! println!("{} = {}", poly3, poly3.to_code(&|x: String| x)); //! println!("{} = {}", poly4, poly4.to_code(&|x: String| x)); //! println!("{} = {}", poly5, poly5.to_code(&|x: String| x)); //! println!("{} = {}", poly6, poly6.to_code(&|x: String| x)); //! println!("{} = {}", poly7, poly7.to_code(&|x: String| x)); //! println!("{} = {}", poly8, poly8.to_code(&|x: String| x)); //! println!("{} = {}", poly9, poly9.to_code(&|x: String| x)); //! println!("{} = {}", poly10, poly10.to_code(&|x: String| x)); //! 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>()); //! } //! //! ``` //! The polynomials are used in `Metadiff` for modeling the shapes of tensors. //! A small example of how this can be achieved is shown //! [here](https://gist.github.com/botev/bac770e32f7df341ce18562f5333e5e5). extern crate num; mod traits; mod functions; mod monomial; mod polynomial; mod composite; mod integer_impl; pub use traits::*; pub use monomial::*; pub use polynomial::*; pub use composite::*; pub use functions::*; pub use integer_impl::*;