Skip to main content

gammalooprs/uv/
mod.rs

1use std::{
2    collections::BTreeMap,
3    hash::Hash,
4    ops::{Mul, Neg},
5};
6
7use crate::{
8    GammaLoopContext, cff::CutCFFIndex, numerator::aind::Aind, utils::GS, uv::approx::Rooted,
9};
10use bincode_trait_derive::{Decode, Encode};
11use color_eyre::Result;
12use eyre::eyre;
13use itertools::{EitherOrBoth, Itertools};
14use spenso::{
15    network::parsing::ShadowedStructure,
16    structure::{
17        NamedStructure, ToSymbolic,
18        dimension::Dimension,
19        representation::{Minkowski, RepName},
20    },
21};
22use symbolica::atom::Atom;
23
24use linnet::half_edge::involution::HedgePair;
25
26// use vakint::{EvaluationOrder, LoopNormalizationFactor, Vakint, VakintSettings};
27
28pub(crate) fn spenso_lor(
29    tag: i32,
30    ind: impl Into<Aind>,
31    dim: impl Into<Dimension>,
32) -> ShadowedStructure<Aind> {
33    let mink = Minkowski {}.new_slot(dim, ind);
34    NamedStructure::from_iter([mink], GS.emr_mom, Some(vec![Atom::num(tag)])).structure
35}
36
37pub(crate) fn spenso_lor_atom(tag: i32, ind: impl Into<Aind>, dim: impl Into<Dimension>) -> Atom {
38    spenso_lor(tag, ind, dim).to_symbolic(None).unwrap()
39}
40
41#[derive(Clone, Debug, PartialEq, Eq, Hash)]
42pub struct IntegrandExpr {
43    integrands: BTreeMap<CutCFFIndex, Atom>,
44    // add_arg: Option<Atom>,
45}
46
47#[derive(Clone, Debug, PartialEq, Eq, Hash, Encode, Decode)]
48#[trait_decode(trait = GammaLoopContext)]
49pub struct Integrands(BTreeMap<CutCFFIndex, Atom>);
50
51impl Integrands {
52    pub fn map<F: FnMut(&Atom) -> Atom>(&self, mut f: F) -> Self {
53        Integrands(self.0.iter().map(|(k, v)| (*k, f(v))).collect())
54    }
55
56    pub fn fallible_map<F: FnMut(&Atom) -> Result<Atom>>(&self, mut f: F) -> Result<Self> {
57        self.0.iter().map(|(k, v)| Ok((*k, f(v)?))).collect()
58    }
59
60    pub fn iter(&self) -> impl Iterator<Item = (&CutCFFIndex, &Atom)> {
61        self.0.iter()
62    }
63
64    pub fn checked_zip(
65        &self,
66        other: &Integrands,
67        mut map: impl FnMut(&CutCFFIndex, &Atom, &Atom) -> Result<Atom>,
68    ) -> Result<Integrands> {
69        self.0
70            .iter()
71            .merge_join_by(&other.0, |(left_key, _), (right_key, _)| {
72                left_key.cmp(right_key)
73            })
74            .map(|pair| match pair {
75                EitherOrBoth::Both((key, left), (_, right)) => Ok((*key, map(key, left, right)?)),
76                EitherOrBoth::Left((key, _)) => {
77                    Err(eyre!("right integrands are missing key {key:?}"))
78                }
79                EitherOrBoth::Right((key, _)) => {
80                    Err(eyre!("left integrands are missing key {key:?}"))
81                }
82            })
83            .collect()
84    }
85
86    pub fn zip_mul(&self, other: &Integrands) -> Result<Integrands> {
87        self.checked_zip(other, |_, v1, v2| Ok(v1 * v2))
88    }
89    pub fn zip_add(&self, other: &Integrands) -> Result<Integrands> {
90        self.checked_zip(other, |_, v1, v2| Ok(v1 + v2))
91    }
92}
93
94impl FromIterator<(CutCFFIndex, Atom)> for Integrands {
95    fn from_iter<I: IntoIterator<Item = (CutCFFIndex, Atom)>>(iter: I) -> Self {
96        Integrands(BTreeMap::from_iter(iter))
97    }
98}
99
100impl Mul<Atom> for Integrands {
101    type Output = Self;
102
103    fn mul(self, rhs: Atom) -> Self::Output {
104        self.map(|a| a * &rhs)
105    }
106}
107
108impl Neg for Integrands {
109    type Output = Self;
110
111    fn neg(self) -> Self::Output {
112        self.map(|a| a.neg())
113    }
114}
115
116impl Mul<&Atom> for Integrands {
117    type Output = Self;
118
119    fn mul(self, rhs: &Atom) -> Self::Output {
120        self.map(|a| a * rhs)
121    }
122}
123
124impl Rooted for Integrands {
125    fn root() -> Self {
126        Integrands(BTreeMap::from([(
127            CutCFFIndex::new_all_none(),
128            Atom::num(1),
129        )]))
130    }
131}
132#[allow(dead_code)]
133pub(crate) fn is_not_paired(pair: &HedgePair) -> bool {
134    !pair.is_paired()
135}
136
137pub mod hedge_poset;
138mod marker;
139mod orchestrator;
140pub mod renormalization;
141pub use renormalization::{RenormalizationPart, RenormalizationStats};
142pub mod settings;
143pub use settings::{
144    ApproximationType, CTIdentifier, CTRenormalizationRule, RenormalizationPrescriptionSettings,
145    UVOrchestrator, UVgenerationSettings,
146};
147pub mod uv_graph;
148pub use uv_graph::UltravioletGraph;
149
150pub mod spinney;
151pub use spinney::Spinney;
152
153pub mod poset;
154pub use poset::Poset;
155
156pub mod wood;
157pub use wood::Wood;
158
159pub mod approx;
160pub use approx::ApproxOp;
161
162pub mod export;
163
164pub mod forest;
165pub use forest::Forest;
166
167pub mod profile;
168pub use profile::{UVProfile, UVProfileAnalysis, UVProfilePassFail};
169
170#[cfg(test)]
171mod tests;