diff --git a/zixy/src/fermion/operator/mod.rs b/zixy/src/fermion/operator/mod.rs index 68b4627..0e24fd5 100644 --- a/zixy/src/fermion/operator/mod.rs +++ b/zixy/src/fermion/operator/mod.rs @@ -5,3 +5,6 @@ pub mod cmpnt_list; pub mod cre_or_ann; pub mod products; pub mod springs; +pub mod term; +pub mod term_set; +pub mod terms; diff --git a/zixy/src/fermion/operator/term.rs b/zixy/src/fermion/operator/term.rs new file mode 100644 index 0000000..86d3a8b --- /dev/null +++ b/zixy/src/fermion/operator/term.rs @@ -0,0 +1,52 @@ +//! Single-term fermion utilities. + +use std::fmt::Display; + +use crate::container::coeffs::traits::NumRepr; +use crate::container::traits::proj::Borrow; +use crate::container::word_iters::terms; +use crate::container::word_iters::terms::AsViewMut; +use crate::fermion::mode::Modes; +use crate::fermion::operator::cmpnt_list::CmpntList; +use crate::fermion::operator::terms::Terms; +use crate::fermion::traits::ModesBased; + +/// A single fermion operator with a generically-typed coefficient. +pub type Term = terms::Term; + +impl Term { + /// Create a single fermion term with unit coefficient on the given mode space. + pub fn new(modes: Modes) -> Self { + let mut terms = Terms::::new(modes); + terms.push_clear(); + Self { + word_iters: terms.word_iters, + coeffs: terms.coeffs, + } + } +} + +impl Display for Term { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.borrow()) + } +} + +impl ModesBased for Term { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::container::coeffs::unity::Unity; + use crate::container::traits::Elements; + + #[test] + fn test_new_has_one_term() { + let term = Term::::new(Modes::from_count(4)); + assert_eq!(term.coeffs.len(), 1); + } +} diff --git a/zixy/src/fermion/operator/term_set.rs b/zixy/src/fermion/operator/term_set.rs new file mode 100644 index 0000000..c210fbd --- /dev/null +++ b/zixy/src/fermion/operator/term_set.rs @@ -0,0 +1,68 @@ +//! Stores fermion terms with the help of a `Map` to ensure each string appears at most once. + +use crate::container::coeffs::traits::NumRepr; +use crate::container::map::Map; +use crate::container::word_iters; +use crate::fermion::mode::Modes; +use crate::fermion::operator::cmpnt_list::CmpntList; +use crate::fermion::operator::terms::Terms; +use crate::fermion::traits::ModesBased; + +pub type TermSet = word_iters::term_set::TermSet; +pub type View<'a, C /*: NumRepr*/> = word_iters::term_set::View<'a, CmpntList, C>; +pub type ViewMut<'a, C /*: NumRepr*/> = word_iters::term_set::ViewMut<'a, CmpntList, C>; + +/// Trait for structs that immutably view a [`TermSet`]. +pub trait AsView: word_iters::term_set::AsView {} + +/// Trait for structs that mutably view a [`TermSet`]. +pub trait AsViewMut: word_iters::term_set::AsViewMut {} + +impl AsView for TermSet {} +impl<'a, C: NumRepr> AsView for View<'a, C> {} +impl<'a, C: NumRepr> AsView for ViewMut<'a, C> {} + +impl AsViewMut for TermSet {} +impl<'a, C: NumRepr> AsViewMut for ViewMut<'a, C> {} + +impl TermSet { + /// Create a new instance. + pub fn new(modes: Modes) -> Self { + Self { + terms: Terms::new(modes), + map: Map::default(), + } + } +} + +impl ModesBased for TermSet { + fn modes(&self) -> &Modes { + self.terms.word_iters.modes() + } +} + +impl<'a, C: NumRepr> ModesBased for View<'a, C> { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +impl<'a, C: NumRepr> ModesBased for ViewMut<'a, C> { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::container::coeffs::unity::Unity; + use crate::container::traits::Elements; + + #[test] + fn test_empty() { + let set = TermSet::::new(Modes::from_count(4)); + assert_eq!(set.len(), 0); + assert!(set.is_empty()); + } +} diff --git a/zixy/src/fermion/operator/terms.rs b/zixy/src/fermion/operator/terms.rs new file mode 100644 index 0000000..928de79 --- /dev/null +++ b/zixy/src/fermion/operator/terms.rs @@ -0,0 +1,79 @@ +//! Extends fermion `CmpntList` fermion with associated coefficients. + +use crate::container::coeffs::traits::NumRepr; +use crate::container::word_iters::terms; +use crate::fermion::mode::Modes; +use crate::fermion::operator::cmpnt_list::CmpntList; +use crate::fermion::traits::ModesBased; + +/// A Fermion `CmpntList` paired with one coefficient per componenet, plus +// immutable and mutable views into one. +pub type Terms = terms::Terms; +pub type View<'a, C /*: NumRepr*/> = terms::View<'a, CmpntList, C>; +pub type ViewMut<'a, C /*: NumRepr*/> = terms::ViewMut<'a, CmpntList, C>; + +//Borrowed handles to a single fermion term inside a `Terms` container. +pub type TermRef<'a, C /*: NumRepr*/> = terms::TermRef<'a, CmpntList, C>; +pub type TermMutRef<'a, C /*: NumRepr*/> = terms::TermMutRef<'a, CmpntList, C>; + +/// Trait for structs that immutably view a fermion [`Terms`]. +/// Currently unused, but may be useful for future extensions. +pub trait AsView: terms::AsView {} +pub trait AsViewMut: terms::AsViewMut {} + +impl AsView for Terms {} +impl<'a, C: NumRepr> AsView for View<'a, C> {} + +impl AsViewMut for Terms {} +impl<'a, C: NumRepr> AsViewMut for ViewMut<'a, C> {} + +impl Terms { + /// Create a new (empty) list of fermion terms on the given mode space. + pub fn new(modes: Modes) -> Self { + use crate::container::traits::EmptyFrom; + Self::empty_from(&CmpntList::new(modes)) + } +} + +impl ModesBased for Terms { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +impl<'a, C: NumRepr> ModesBased for View<'a, C> { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +impl<'a, C: NumRepr> ModesBased for ViewMut<'a, C> { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +impl<'a, C: NumRepr> ModesBased for TermRef<'a, C> { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +impl<'a, C: NumRepr> ModesBased for TermMutRef<'a, C> { + fn modes(&self) -> &Modes { + self.word_iters.modes() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::container::coeffs::unity::Unity; + use crate::container::traits::Elements; + + #[test] + fn test_empty() { + let list = Terms::::new(Modes::from_count(3)); + assert!(list.is_empty()); + } +}