use std::ops::{Deref, DerefMut}; use crate::poly::var::Var; use crate::poly::flat::Poly; use crate::poly::ideal::{Generators, GroebnerBasis, Ideal}; use super::dag::{Dag,NodeId}; use super::traits::{Circuit,Node}; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum QNode { Leaf(V), Sum(NodeId, NodeId), Prod(NodeId, NodeId), DivStep(NodeId, NodeId) } impl Node for QNode{ fn children(&self) -> impl Iterator { match self { Self::Leaf(_) => [None, None], Self::Sum(l, r) | Self::Prod(l, r) | Self::DivStep(l,r) => [Some(*l), Some(*r)], } .into_iter() .flatten() } } #[derive(Clone, Debug)] pub struct QuotientCircuit { basis: Ideal, dag: Dag>, } impl From> for QuotientCircuit { fn from(basis: Ideal) -> Self { Self { basis, dag: Default::default(), } } } impl FromIterator> for QuotientCircuit { fn from_iter>>(iter: T) -> Self { let ideal: Ideal = iter.into_iter().collect(); Self { basis: ideal.groebner_basis(), dag: Default::default(), } } } impl Deref for QuotientCircuit{ type Target = Dag>; fn deref(&self)->&Self::Target{ &self.dag } } impl DerefMut for QuotientCircuit{ fn deref_mut(&mut self)->&mut Self::Target{ &mut self.dag } } impl Circuit for QuotientCircuit{ type Node=QNode; type Var=V; fn leaf(&mut self, variable:V)->NodeId{ self.node(Self::Node::Leaf(variable)) } fn add(&mut self, left: NodeId, right: NodeId) -> NodeId { let (l, r) = if left <= right { (left, right) } else { (right, left) }; self.node(Self::Node::Sum(l, r)) } fn mul(&mut self, left: NodeId, right: NodeId) -> NodeId { let (l, r) = if left <= right { (left, right) } else { (right, left) }; self.node(Self::Node::Prod(l, r)) } }