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(FlatIndex(0), GS.emr_vec())
41                //         a
42                //     }),
43                // );
44            }
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 //.kill_color();
58            }
59        }
60
61        let notseen = !seen;
62
63        // From all the nodes not yet covered by paired edges, include those included in the subgraph, ignoring dummies
64        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(&not_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 //.kill_color();
113            }
114        }
115
116        let notseen = !seen;
117
118        // From all the nodes not yet covered by paired edges, include those included in the subgraph, ignoring dummies
119        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}