gammalooprs/numerator/
uninit.rs1use std::sync::atomic::AtomicUsize;
2
3use linnet::half_edge::subgraph::subset::SubSet;
4use linnet::half_edge::subgraph::{ModifySubSet, SubGraphLike, SubSetLike, SubSetOps};
5use linnet::half_edge::{NodeIndex, involution::HedgePair};
6use symbolica::atom::Atom;
7use symbolica_utils::AtomPrintExt;
8use tracing::debug;
9use tracing::instrument;
10
11use crate::graph::Graph;
12
13use super::{AppliedFeynmanRule, Numerator, UnInit};
14
15static MAXEDGECOUNTER: AtomicUsize = AtomicUsize::new(0);
16
17impl Numerator<UnInit> {
18 #[instrument(skip_all, fields(graph=%graph.name,debug_dot=%graph.debug_dot(),subgraph_dot=%graph.dot(subgraph)))]
19 #[allow(clippy::wrong_self_convention)]
20 pub(crate) fn from_new_graph<S: SubGraphLike>(
21 self,
22 graph: &Graph,
23 subgraph: &S,
24 ) -> Numerator<AppliedFeynmanRule> {
25 let mut num = Atom::one();
26
27 let mut seen: SubSet<NodeIndex> = SubSet::empty(graph.n_nodes());
28
29 for (p, eid, e) in graph.underlying.iter_edges_of(subgraph) {
30 let i = MAXEDGECOUNTER.fetch_max(eid.0, std::sync::atomic::Ordering::Relaxed);
31 if i == eid.0 {
32 }
45 if let HedgePair::Paired { source, sink } = p {
46 let source_n = graph.node_id(source);
47 if !seen[source_n] {
48 seen.add(source_n);
49 num *= graph[source_n].get_num();
50 }
51 let sink_n = graph.node_id(sink);
52 if !seen[sink_n] {
53 seen.add(sink_n);
54 num *= graph[sink_n].get_num();
55 }
56
57 num *= &e.data.num.value }
59 }
60
61 let notseen = !seen;
62
63 for node_id in notseen.included_iter() {
65 if graph
66 .iter_crown(node_id)
67 .all(|h| subgraph.includes(&h) || graph[graph[&h]].is_dummy)
68 {
69 num *= graph[node_id].get_num()
70 }
71 }
72
73 debug!( numerator = %num.to_bare_ordered_string(),"Numerator constructed",);
74
75 Numerator {
76 state: AppliedFeynmanRule {
77 expr: num,
78 state: Default::default(),
79 },
80 }
81 }
82 #[instrument(skip_all, fields(graph=%graph.name,debug_dot=%graph.debug_dot(),subgraph_dot=%graph.dot(subgraph)))]
83 #[allow(clippy::wrong_self_convention)]
84 pub(crate) fn fill_in_reduced<S: SubGraphLike + SubSetOps>(
85 self,
86 graph: &Graph,
87 subgraph: &S,
88 ignore: &S,
89 ) -> Numerator<AppliedFeynmanRule> {
90 let mut num = Atom::one();
91
92 let mut seen: SubSet<NodeIndex> = SubSet::empty(graph.n_nodes());
93
94 for (nid, _, _) in graph.underlying.iter_nodes_of(ignore) {
95 seen.add(nid);
96 }
97 let not_ignored = subgraph.subtract(ignore);
98
99 for (p, _eid, e) in graph.underlying.iter_edges_of(¬_ignored) {
100 if let HedgePair::Paired { source, sink } = p {
101 let source_n = graph.node_id(source);
102 if !seen[source_n] {
103 seen.add(source_n);
104 num *= graph[source_n].get_num();
105 }
106 let sink_n = graph.node_id(sink);
107 if !seen[sink_n] {
108 seen.add(sink_n);
109 num *= graph[sink_n].get_num();
110 }
111
112 num *= &e.data.num.value }
114 }
115
116 let notseen = !seen;
117
118 for node_id in notseen.included_iter() {
120 if graph
121 .iter_crown(node_id)
122 .all(|h| subgraph.includes(&h) || graph[graph[&h]].is_dummy)
123 {
124 num *= graph[node_id].get_num()
125 }
126 }
127
128 debug!( numerator = %num.to_bare_ordered_string(),"Numerator constructed",);
129
130 Numerator {
131 state: AppliedFeynmanRule {
132 expr: num,
133 state: Default::default(),
134 },
135 }
136 }
137}