wip flat representation of polynomial over Z
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
25
Cargo.lock
generated
Normal file
25
Cargo.lock
generated
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "circuit-polynomial"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "circuit-polynomial"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
itertools = "0.14.0"
|
||||||
34
src/bin/flat.rs
Normal file
34
src/bin/flat.rs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
use circuit_polynomial::poly::flat;
|
||||||
|
use circuit_polynomial::poly::flat::Mono;
|
||||||
|
use circuit_polynomial::{var,poly::var::StaticVar};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let poly: flat::Poly<StaticVar> = [
|
||||||
|
(
|
||||||
|
2,
|
||||||
|
[
|
||||||
|
(var!("x", 1, 5), 5),
|
||||||
|
(var!("x", 1, 2), 5),
|
||||||
|
(var!("x", 2, 5), 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3,
|
||||||
|
[
|
||||||
|
(var!("x", 1, 9), 5),
|
||||||
|
(var!("x", 1, 2), 5),
|
||||||
|
(var!("x", 2, 5), 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let x=var!("x");
|
||||||
|
let y=var!("y");
|
||||||
|
let mono = 3*((&x^2)*(&y^4));
|
||||||
|
|
||||||
|
println!("{poly}");
|
||||||
|
|
||||||
|
let z=poly+mono;
|
||||||
|
println!("{z}");
|
||||||
|
}
|
||||||
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod poly;
|
||||||
181
src/poly/flat.rs
Normal file
181
src/poly/flat.rs
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
|
use std::ops::{Add, BitXor, Mul};
|
||||||
|
|
||||||
|
use super::var::{StaticVar, Var};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Poly<V: Var> {
|
||||||
|
mono: HashMap<Mono<V>, i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var> Default for Poly<V> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Poly {
|
||||||
|
mono: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var> Display for Poly<V> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
|
match self.mono.is_empty() {
|
||||||
|
true => write!(fmt, "∅"),
|
||||||
|
false => write!(
|
||||||
|
fmt,
|
||||||
|
"{}",
|
||||||
|
self.mono
|
||||||
|
.iter()
|
||||||
|
.map(|(m, c)| format!("{}{}", c, m))
|
||||||
|
.join(" + ")
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var, T: IntoIterator> From<T> for Poly<V>
|
||||||
|
where
|
||||||
|
Poly<V>: FromIterator<<T as IntoIterator>::Item>,
|
||||||
|
{
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
value.into_iter().collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var, U: Into<Mono<V>>> FromIterator<(i32, U)> for Poly<V> {
|
||||||
|
fn from_iter<T: IntoIterator<Item = (i32, U)>>(iter: T) -> Self {
|
||||||
|
Poly {
|
||||||
|
mono: iter.into_iter().map(|(c, m)| (m.into(), c)).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Mono<V: Var> {
|
||||||
|
pub term: Vec<(V, u32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var, T: IntoIterator> From<T> for Mono<V>
|
||||||
|
where
|
||||||
|
Mono<V>: FromIterator<<T as IntoIterator>::Item>,
|
||||||
|
{
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
value.into_iter().collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var, U: Into<V>> FromIterator<(U, u32)> for Mono<V> {
|
||||||
|
fn from_iter<T: IntoIterator<Item = (U, u32)>>(iter: T) -> Self {
|
||||||
|
let mut term = iter
|
||||||
|
.into_iter()
|
||||||
|
.map(|(t, pow)| (t.into(), pow))
|
||||||
|
.collect::<Vec<(V, u32)>>();
|
||||||
|
term.sort();
|
||||||
|
|
||||||
|
// Check duplicate variables
|
||||||
|
assert!((term[..])
|
||||||
|
.windows(2)
|
||||||
|
.all(|window| window[0].0 != window[1].0));
|
||||||
|
|
||||||
|
Mono { term }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var> Display for Mono<V> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
|
write!(
|
||||||
|
fmt,
|
||||||
|
"{}",
|
||||||
|
self.term
|
||||||
|
.iter()
|
||||||
|
.map(|(t, p)| match p {
|
||||||
|
1 => format!("{t}"),
|
||||||
|
_ => format!("{t}^{p}"),
|
||||||
|
})
|
||||||
|
.join("")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitXor<u32> for StaticVar {
|
||||||
|
type Output = Mono<StaticVar>;
|
||||||
|
|
||||||
|
fn bitxor(self, exp: u32) -> Self::Output {
|
||||||
|
[(self, exp)].into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BitXor<u32> for &'a StaticVar {
|
||||||
|
type Output = Mono<StaticVar>;
|
||||||
|
|
||||||
|
fn bitxor(self, exp: u32) -> Self::Output {
|
||||||
|
[(self.clone(), exp)].into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var> Mul for Mono<V> {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, other: Mono<V>) -> Self::Output {
|
||||||
|
let mut a_term = self.term.into_iter().peekable();
|
||||||
|
let mut b_term = other.term.into_iter().peekable();
|
||||||
|
|
||||||
|
let mut result: Vec<(V, u32)> = Default::default();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match (a_term.peek(), b_term.peek()) {
|
||||||
|
(Some((a_var, _)), Some((b_var, _))) => {
|
||||||
|
if a_var < b_var {
|
||||||
|
result.push(a_term.next().unwrap());
|
||||||
|
} else if a_var > b_var {
|
||||||
|
result.push(b_term.next().unwrap());
|
||||||
|
} else {
|
||||||
|
let (var, a_exp) = a_term.next().unwrap();
|
||||||
|
let (_, b_exp) = b_term.next().unwrap();
|
||||||
|
result.push((var, a_exp + b_exp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(a), None) => {
|
||||||
|
result.push(a.clone());
|
||||||
|
a_term.next();
|
||||||
|
}
|
||||||
|
(None, Some(b)) => {
|
||||||
|
result.push(b.clone());
|
||||||
|
b_term.next();
|
||||||
|
}
|
||||||
|
(None, None) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mono { term: result }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var> Mul<Mono<V>> for i32 {
|
||||||
|
type Output = Poly<V>;
|
||||||
|
|
||||||
|
fn mul(self, mono: Mono<V>) -> Self::Output {
|
||||||
|
let mut poly: HashMap<Mono<V>, i32> = Default::default();
|
||||||
|
|
||||||
|
poly.insert(mono, self);
|
||||||
|
|
||||||
|
Poly { mono: poly }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Var> Add for Poly<V> {
|
||||||
|
type Output = Poly<V>;
|
||||||
|
|
||||||
|
fn add(mut self, other: Poly<V>) -> Self::Output {
|
||||||
|
for (mono, coeff) in other.mono {
|
||||||
|
let entry = self.mono.entry(mono).or_insert(0);
|
||||||
|
*entry += coeff;
|
||||||
|
}
|
||||||
|
self.mono.retain(|_, &mut coeff| coeff != 0);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
2
src/poly/mod.rs
Normal file
2
src/poly/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod flat;
|
||||||
|
pub mod var;
|
||||||
63
src/poly/var.rs
Normal file
63
src/poly/var.rs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
pub struct StaticVar {
|
||||||
|
name: &'static str,
|
||||||
|
indices: Vec<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Var: PartialEq + Eq + PartialOrd + Ord + Clone + Hash + Debug + Display {}
|
||||||
|
|
||||||
|
impl Display for StaticVar {
|
||||||
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
|
let num_indices = self.indices.len();
|
||||||
|
match num_indices {
|
||||||
|
0 => write!(fmt, "{}", self.name),
|
||||||
|
_ => write!(fmt, "{}_{{{}}}", self.name, self.indices.iter().join(",")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Var for StaticVar {}
|
||||||
|
|
||||||
|
impl From<&'static str> for StaticVar {
|
||||||
|
fn from(name: &'static str) -> Self {
|
||||||
|
StaticVar {
|
||||||
|
name,
|
||||||
|
indices: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(&'static str, u32)> for StaticVar {
|
||||||
|
fn from(values: (&'static str, u32)) -> Self {
|
||||||
|
StaticVar {
|
||||||
|
name: values.0,
|
||||||
|
indices: vec![values.1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(&'static str, u32, u32)> for StaticVar {
|
||||||
|
fn from(values: (&'static str, u32, u32)) -> Self {
|
||||||
|
StaticVar {
|
||||||
|
name: values.0,
|
||||||
|
indices: vec![values.1, values.2],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! var {
|
||||||
|
($name:expr) => {
|
||||||
|
::circuit_polynomial::poly::var::StaticVar::from($name)
|
||||||
|
};
|
||||||
|
($name:expr, $idx1:expr) => {
|
||||||
|
::circuit_polynomial::poly::var::StaticVar::from(($name, $idx1))
|
||||||
|
};
|
||||||
|
($name:expr, $idx1:expr, $idx2:expr) => {
|
||||||
|
::circuit_polynomial::poly::var::StaticVar::from(($name, $idx1, $idx2))
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user