gammalooprs/uv/
spinney.rs1use std::hash::{Hash, Hasher};
2
3use gammaloop_tracing_filter::LogMessage;
4use linnet::half_edge::{
5 HedgeGraph,
6 subgraph::{Inclusion, InternalSubGraph, SuBitGraph, SubSetLike},
7};
8use tracing::debug;
9
10use crate::{
11 graph::{LMBext, LoopMomentumBasis, cuts::CutSet},
12 uv::{ApproximationType, UltravioletGraph},
13};
14
15#[derive(Clone, Debug, Eq)]
16pub struct Spinney {
17 pub subgraph: InternalSubGraph,
18 components: Vec<SuBitGraph>,
19 pub dod: i32,
20 pub lmb: LoopMomentumBasis,
21 pub renormalization_scheme: ApproximationType,
22 max_comp_loop_count: usize,
23}
24
25impl LogMessage for Spinney {
26 fn log_display(&self) -> String {
27 format!(
28 "Spinney {{ dod: {}, components: {}, max_comp_loop_count: {},subgraph: {} }}",
29 self.dod,
30 self.components.len(),
31 self.max_comp_loop_count,
32 self.subgraph.string_label(),
33 )
34 }
35}
36
37impl Spinney {
38 pub fn compatible_with(&self, cut: &CutSet) -> bool {
39 !self.subgraph.filter.intersects(&cut.union)
40 }
41
42 pub fn empty<E, V, H, G: AsRef<HedgeGraph<E, V, H>> + LMBext + ?Sized>(g: &G) -> Self {
43 Self {
44 subgraph: InternalSubGraph::empty(g.as_ref().n_hedges()),
45 components: vec![],
46 dod: 0,
47 lmb: g.empty_lmb(),
48 renormalization_scheme: ApproximationType::MUV,
49 max_comp_loop_count: 0,
50 }
51 }
52
53 pub fn new<E, V, H, G: UltravioletGraph + AsRef<HedgeGraph<E, V, H>> + ?Sized>(
54 subgraph: InternalSubGraph,
55 g: &G,
56 lmb: &LoopMomentumBasis,
57 ) -> Option<Self> {
58 let dod = g.compute_dod(&subgraph);
59 Self::with_scheme(subgraph, g, lmb, ApproximationType::MUV, dod)
60 }
61
62 pub fn with_scheme<E, V, H, G: UltravioletGraph + AsRef<HedgeGraph<E, V, H>> + ?Sized>(
63 subgraph: InternalSubGraph,
64 g: &G,
65 lmb: &LoopMomentumBasis,
66 renormalization_scheme: ApproximationType,
67 dod: i32,
68 ) -> Option<Self> {
69 let components = g.as_ref().connected_components(&subgraph);
70 let max_comp_loop_count = components
71 .iter()
72 .map(|component| g.as_ref().cyclotomatic_number(component))
73 .max()
74 .unwrap_or(0);
75 let lmb = g
76 .try_compatible_sub_lmb(&subgraph, g.dummy_less_full_crown(&subgraph), lmb)
77 .ok()?;
78
79 if dod < 0 {
80 return None;
81 }
82
83 debug!(
84 dod = %dod,
85 graph = %g.dot_lmb_of(&subgraph,&lmb),
86 renormalization_scheme = %renormalization_scheme,
87 string_label =%subgraph.string_label(),
88 "Constucted spinney with scheme: {:?}",
89 renormalization_scheme
90 );
91
92 Some(Self {
93 components,
94 dod,
95 lmb,
96 subgraph,
97 renormalization_scheme,
98 max_comp_loop_count,
99 })
100 }
101
102 pub fn filter(&self) -> &SuBitGraph {
103 &self.subgraph.filter
104 }
105
106 pub fn max_comp_loop_count(&self) -> usize {
107 self.max_comp_loop_count
108 }
109
110 pub fn n_components(&self) -> usize {
111 self.components.len()
112 }
113}
114
115impl Hash for Spinney {
116 fn hash<H: Hasher>(&self, state: &mut H) {
117 self.subgraph.hash(state);
118 }
119}
120
121impl PartialEq for Spinney {
122 fn eq(&self, other: &Self) -> bool {
123 self.subgraph == other.subgraph
124 }
125}
126
127impl PartialOrd for Spinney {
128 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
129 if self.subgraph == other.subgraph {
130 Some(std::cmp::Ordering::Equal)
131 } else if self.subgraph.includes(&other.subgraph) {
132 Some(std::cmp::Ordering::Greater)
133 } else if other.subgraph.includes(&self.subgraph) {
134 Some(std::cmp::Ordering::Less)
135 } else {
136 None
137 }
138 }
139}