Skip to main content

gammalooprs/numerator/
uninit.rs

1use 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                // TENSORLIB.write().unwrap().insert_explicit(
33                //     ExplicitKey::<Aind>::from_iter(
34                //         [Minkowski {}.new_rep(4)],
35                //         GS.emr_vec,
36                //         Some(vec![Atom::num(eid.0 as i64)]),
37                //     )
38                //     .map_structure(|s| {
39                //         let mut a = ParamTensor::param(DenseTensor::fill(s, Atom::new()).into()).into();
40                //         a.set_flat(
41                //             FlatIndex(0),
42                //             GS.emr_vec(eid, Minkowski {}.new_rep(4).to_symbolic([])),
43                //         )
44                //         a
45                //     }),
46                // );
47            }
48            if let HedgePair::Paired { source, sink } = p {
49                let source_n = graph.node_id(source);
50                if !seen[source_n] {
51                    seen.add(source_n);
52                    num *= graph[source_n].get_num();
53                }
54                let sink_n = graph.node_id(sink);
55                if !seen[sink_n] {
56                    seen.add(sink_n);
57                    num *= graph[sink_n].get_num();
58                }
59
60                num *= &e.data.num.value //.kill_color();
61            }
62        }
63
64        let notseen = !seen;
65
66        // From all the nodes not yet covered by paired edges, include those included in the subgraph, ignoring dummies
67        for node_id in notseen.included_iter() {
68            if graph
69                .iter_crown(node_id)
70                .all(|h| subgraph.includes(&h) || graph[graph[&h]].is_dummy)
71            {
72                num *= graph[node_id].get_num()
73            }
74        }
75
76        debug!( numerator = %num.to_bare_ordered_string(),"Numerator constructed",);
77
78        Numerator {
79            state: AppliedFeynmanRule {
80                expr: num,
81                state: Default::default(),
82            },
83        }
84    }
85    #[instrument(skip_all, fields(graph=%graph.name,debug_dot=%graph.debug_dot(),subgraph_dot=%graph.dot(subgraph)))]
86    #[allow(clippy::wrong_self_convention)]
87    pub(crate) fn fill_in_reduced<S: SubGraphLike + SubSetOps>(
88        self,
89        graph: &Graph,
90        subgraph: &S,
91        ignore: &S,
92    ) -> Numerator<AppliedFeynmanRule> {
93        let mut num = Atom::one();
94
95        let mut seen: SubSet<NodeIndex> = SubSet::empty(graph.n_nodes());
96
97        for (nid, _, _) in graph.underlying.iter_nodes_of(ignore) {
98            seen.add(nid);
99        }
100        let not_ignored = subgraph.subtract(ignore);
101
102        for (p, _eid, e) in graph.underlying.iter_edges_of(&not_ignored) {
103            if let HedgePair::Paired { source, sink } = p {
104                let source_n = graph.node_id(source);
105                if !seen[source_n] {
106                    seen.add(source_n);
107                    num *= graph[source_n].get_num();
108                }
109                let sink_n = graph.node_id(sink);
110                if !seen[sink_n] {
111                    seen.add(sink_n);
112                    num *= graph[sink_n].get_num();
113                }
114
115                num *= &e.data.num.value //.kill_color();
116            }
117        }
118
119        let notseen = !seen;
120
121        // From all the nodes not yet covered by paired edges, include those included in the subgraph, ignoring dummies
122        for node_id in notseen.included_iter() {
123            if graph
124                .iter_crown(node_id)
125                .all(|h| subgraph.includes(&h) || graph[graph[&h]].is_dummy)
126            {
127                num *= graph[node_id].get_num()
128            }
129        }
130
131        debug!( numerator = %num.to_bare_ordered_string(),"Numerator constructed",);
132
133        Numerator {
134            state: AppliedFeynmanRule {
135                expr: num,
136                state: Default::default(),
137            },
138        }
139    }
140}