HepLib
TIR.cpp
Go to the documentation of this file.
1 
6 #include "HEP.h"
7 #include <cmath>
8 
9 namespace HepLib {
10 
11  namespace {
12 
13  lst combs(const lst & items, int n) {
14  lst ret;
15  if(n<1 || items.nops()<1) return lst{ret};
16  if(n==1) {
17  for(auto it : items) ret.append(lst{it});
18  return ret;
19  }
20  if(items.nops()==1) {
21  lst comb;
22  for(int i=0; i<n; i++) comb.append(items.op(0));
23  ret.append(comb);
24  return ret;
25  }
26  auto its = items;
27  ex first = its.op(0);
28  its.remove_first();
29  //for(int i=0; i<=n; i++) {
30  for(int i=n; i>=0; i--) {
31  auto rets = combs(its, n-i);
32  for(auto it : rets) {
33  lst item = ex_to<lst>(it);
34  for(int j=0; j<i; j++) item.append(first);
35  ret.append(item);
36  }
37  }
38  return ret;
39  }
40 
41  }
42 
43  ex UnContract(const ex expr, const lst &loop_ps, const lst &ext_ps) {
44  // handle Eps/DGamma/Pair and related power
45  int lproj = 0;
46  return MapFunction([&lproj,loop_ps,ext_ps](const ex &e, MapFunction &self)->ex {
47  string prefix = "dmi";
48  int mode = 0;
49  if(ext_ps.nops()>0) mode = 1;
50  if(!Eps::has(e) && !DGamma::has(e) && (mode==0 || !Pair::has(e))) return e;
51  else if(mode==1 && is_a<Pair>(e) && has_any(e,loop_ps) && has_any(e,ext_ps)) {
52  Index idx(prefix+to_string(++lproj));
53  auto p = ex_to<Pair>(e);
54  return SP(p.op(0), idx) * SP(p.op(1), idx);
55  } else if(is_a<Eps>(e)) {
56  auto pis0 = ex_to<Eps>(e).pis;
57  ex pis[4];
58  ex cc = 1;
59  for(int i=0; i<4; i++) {
60  pis[i] = pis0[i];
61  if(is_equal_any(pis[i],loop_ps)) {
62  Index idx(prefix+to_string(++lproj));
63  cc *= SP(pis[i], idx);
64  pis[i] = idx;
65  } else if(has_any(pis[i],loop_ps)) throw Error("UnContract: Eps still has loops.");
66  }
67  return LC(pis[0], pis[1], pis[2], pis[3]) * cc;
68  } else if(is_a<DGamma>(e)) {
69  Index idx(prefix+to_string(++lproj));
70  auto g = ex_to<DGamma>(e);
71  if(!is_equal_any(g.pi,loop_ps)) throw Error("UnContract: g.pi is NOT a loop.");
72  return DGamma(idx, g.rl) * SP(g.pi, idx);
73  } else if (e.match(TR(w))) {
74  auto ret = self(e.op(0));
75  auto cvs = collect_lst(ret, loop_ps);
76  ret = 0;
77  for(auto const & cv : cvs) {
78  if(DGamma::has(cv.op(1))) throw Error("UnContract: Not working for TIR.");
79  ret += TR(cv.op(0)) * cv.op(1);
80  }
81  return ret;
82  } else if(is_a<add>(e)) {
83  int lpj = lproj;
84  int lpj_max = -100;
85  ex ret = 0;
86  for(auto item : e) {
87  lproj = lpj;
88  ret += self(item);
89  if(lpj_max<lproj) lpj_max = lproj;
90  }
91  lproj = lpj_max;
92  return ret;
93  } else if(is_a<power>(e)) {
94  if(!e.op(1).info(info_flags::posint)) return e; // no need to handle negative powers
95  ex ret = 1;
96  int pn = ex_to<numeric>(e.op(1)).to_int();
97  for(int i=0; i<pn; i++) {
98  ret *= self(e.op(0));
99  }
100  return ret;
101  } else return e.map(self);
102  })(expr);
103  }
104 
112  ex TIR(const ex &expr_in, const lst &loop_ps, const lst &ext_ps) {
113  for(auto pi : loop_ps) {
114  if(!is_a<Vector>(pi)) throw Error("TIR invalid 2nd argument");
115  }
116  for(auto pi : ext_ps) {
117  if(!is_a<Vector>(pi)) throw Error("TIR invalid 3rd argument");
118  }
119 
120  Fermat &fermat = Fermat::get();
121  int &v_max = fermat.vmax;
122  static exmap cache_map;
123 
124  auto expr = UnContract(expr_in, loop_ps); // UnContract
125  auto cvs = collect_lst(expr, [&loop_ps](const ex & e)->bool{
126  if(!Index::hasv(e)) return false;
127  for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
128  auto item = *i;
129  if(is_a<Pair>(item) && is_a<Index>(item.op(1)) && loop_ps.has(item.op(0))) return true;
130  }
131  return false;
132  });
133 
134  expr = 0;
135  for(auto cv : cvs) {
136  auto const & cc = cv.op(0);
137  auto const & vv = cv.op(1);
138  if(vv.is_equal(1)) {
139  expr += cc * vv;
140  continue;
141  }
142 
143  ex map_key = lst{vv, ext_ps};
144  if(using_cache) {
145  auto itr = cache_map.find(map_key);
146  if(itr!=cache_map.end()) {
147  expr += cc * itr->second;
148  continue;
149  }
150  }
151  lst vis, lps;
152  map<ex,int,ex_is_less> pc;
153  if(is_a<mul>(vv)) {
154  for(auto item : vv) {
155  vis.append(item);
156  lps.append(item.op(0));
157  pc[item.op(0)]++;
158  }
159  } else {
160  vis.append(vv);
161  lps.append(vv.op(0));
162  }
163  lps.sort();
164  lps.unique();
165 
166  ex res;
167  auto visn = vis.nops();
168  if(lps.nops()<2) {
169  ex eqL=1;
170  lst is, bis;
171  for(auto vi : vis) {
172  eqL *= vi;
173  is.append(vi.op(1));
174  }
175 
176  //for(int er=((visn%2==0)?0:1); er<=visn; er+=2) {
177  for(int er=visn; er>=((visn%2==0)?0:1); er-=2) {
178  auto ep_comb = combs(ext_ps, er);
179  for(auto item : ep_comb) {
180  ex bi=1;
181  for(int j=0; j<er; j++) bi *= SP(item.op(j), is.op(j));
182  for(int j=er; j<visn; j=j+2) bi *= SP(is.op(j), is.op(j+1));
183  bi = bi.symmetrize(is);
184  bis.append(bi);
185  }}
186 
187  int n = bis.nops();
188  lst mat;
189  for(auto bi : bis) {
190  for(auto bj : bis) mat.append(bi*bj);
191  }
192  for(auto bj : bis) mat.append(eqL*bj);
193 
194  // we need to remap the dummy index, to avoid SP_map set the index object to 0
195  if(true) {
196  lst isu = is;
197  isu.sort();
198  isu.unique();
199  exmap i2u, u2i;
200  int c=0;
201  for(auto item : isu) {
202  auto ii = Index("TIR"+to_string(c++));
203  i2u[item] = ii;
204  u2i[ii] = item;
205  }
206  mat = ex_to<lst>(subs(mat,i2u));
207  mat = ex_to<lst>(form(mat).subs(u2i));
208  }
209 
210  lst rep_vs;
211  ex tree = mat;
212  for(const_preorder_iterator i = tree.preorder_begin(); i != tree.preorder_end(); ++i) {
213  auto e = (*i);
214  if(is_a<symbol>(e) || is_a<Pair>(e) || is_a<Eps>(e)) {
215  rep_vs.append(e);
216  }
217  }
218  rep_vs.sort();
219  rep_vs.unique();
220  sort_lst(rep_vs);
221 
222  exmap v2f;
223  symtab st;
224  int fvi = 0;
225  for(auto vi : rep_vs) {
226  auto name = "v" + to_string(fvi);
227  v2f[vi] = Symbol(name);
228  st[name] = vi;
229  fvi++;
230  }
231 
232  stringstream ss;
233  if(fvi>111) {
234  cout << rep_vs << endl;
235  throw Error("Fermat: Too many variables.");
236  }
237  if(fvi>v_max) {
238  for(int i=v_max; i<fvi; i++) ss << "&(J=v" << i << ");" << endl;
239  fermat.Execute(ss.str());
240  ss.clear();
241  ss.str("");
242  v_max = fvi;
243  }
244 
245  ss << "Array m[" << n << "," << n+1 << "];" << endl;
246  fermat.Execute(ss.str());
247  ss.clear();
248  ss.str("");
249 
250  ss << "[m]:=[(";
251  for(auto item : mat) {
252  ss << item.subs(v2f) << ",";
253  }
254  ss << ")];" << endl;
255  ss << "Redrowech([m]);" << endl;
256  auto tmp = ss.str();
257 
258  string_replace_all(tmp,",)]",")]");
259  fermat.Execute(tmp);
260  ss.clear();
261  ss.str("");
262 
263  ss << "&(U=1);" << endl; // ugly printing, the whitespace matters
264  ss << "![m" << endl;
265  auto ostr = fermat.Execute(ss.str());
266  ss.clear();
267  ss.str("");
268 
269  ss << "&(U=0);" << endl; // disable ugly printing
270  ss << "@([m]);" << endl;
271  ss << "&_G;" << endl;
272  fermat.Execute(ss.str());
273  ss.clear();
274  ss.str("");
275 
276  // make sure last char is 0
277  if(ostr[ostr.length()-1]!='0') throw Error("TIR: last char is NOT 0.");
278  ostr = ostr.substr(0, ostr.length()-1);
279  string_trim(ostr);
280 
281  ostr.erase(0, ostr.find(":=")+2);
282  string_replace_all(ostr, "[", "{");
283  string_replace_all(ostr, "]", "}");
284  Parser fp(st);
285  auto mat2 = fp.Read(ostr);
286 
287  res = 0;
288  for(int i=0; i<n; i++) {
289  if(is_zero(mat2.op(i).op(i)) && !is_zero(mat2.op(i).op(n))) {
290  cout << cv << endl;
291  cout << mat << " :> " << mat2 << endl;
292  throw Error("No Solution in TIR.");
293  }
294  res += bis.op(i) * mat2.op(i).op(n);
295  }
296  res = res.subs(SP_map);
297  } else {
298  int cmin=10000, cmax=-1;
299  ex pmin, pmax;
300  for(auto lpi : lps) {
301  auto cc = pc[lpi];
302  if(cc<cmin) { cmin = cc; pmin = lpi; }
303  if(cc>cmax) { cmax = cc; pmax = lpi; }
304  }
305 
306  auto lp0 = pmin;
307  auto ext_ps2 = ext_ps;
308  for(auto lpi : lps) if(!is_zero(lpi-lp0)) ext_ps2.append(lpi);
309  res = TIR(vv, lst{ lp0 }, ext_ps2);
310  res = TIR(res, loop_ps, ext_ps);
311  }
312 
313  res = exnormal(res);
314  if(using_cache) cache_map.insert({map_key,res});
315  expr += cc * res;
316  }
317 
318  return expr;
319  }
320 
321 }
322 
HEP header file.
class for Dirac Gamma object
Definition: HEP.h:437
static bool has(const ex &e)
static bool has(const ex &e)
class used to wrap error message
Definition: BASIC.h:242
interface to communicate with Fermat program
Definition: BASIC.h:797
static Fermat & get()
Definition: Fermat.cpp:7
string Execute(string)
Definition: Process.cpp:102
class for index object
Definition: HEP.h:104
static bool hasv(const ex &e)
Definition: Basic.cpp:234
class to wrap map_function of GiNaC
Definition: BASIC.h:632
static bool has(const ex &e)
class to parse for string or file, helpful with Symbol class
Definition: BASIC.h:645
ex Read(const string &instr, bool s2S=true)
Definition: Functions.cpp:111
class extended to GiNaC symbol class, represent a positive symbol
Definition: BASIC.h:113
HepLib namespace.
Definition: BASIC.cpp:17
bool is_equal_any(ex expr, lst ps)
Definition: BASIC.h:64
exmap SP_map
Definition: Init.cpp:179
bool using_cache
Definition: Init.cpp:153
bool has_any(ex expr, lst ps)
Definition: BASIC.h:55
ex w
Definition: Init.cpp:90
ex exnormal(const ex &expr, int opt)
normalize a expression
Definition: BASIC.cpp:1906
lst collect_lst(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica, reture the lst { {c1,v1}, {c2,v2}, ... }
Definition: BASIC.cpp:1222
void sort_lst(lst &ilst, bool less=true)
sort the list in less order, or the reverse
Definition: Sort.cpp:79
void string_replace_all(string &str, const string &from, const string &to)
Definition: Functions.cpp:148
ex UnContract(const ex expr, const lst &loop_ps, const lst &ext_ps=lst{})
Definition: TIR.cpp:43
ex LC(ex pi1, ex pi2, ex pi3, ex pi4)
function similar to LCD in FeynCalc
Definition: Eps.cpp:179
void string_trim(string &str)
Definition: Functions.cpp:156
ex form(const ex &iexpr, int verb)
evalulate expr in form program, see also the form_trace_mode and form_expand_mode
Definition: Form.cpp:563
ex TIR(const ex &expr_in, const lst &loop_ps, const lst &ext_ps)
Tensor Index Reduction, note that we only handle numerator.
Definition: TIR.cpp:112
ex SP(const ex &a, bool use_map=false)
Definition: Pair.cpp:166
ex subs(const ex &e, init_list sl)
Definition: BASIC.h:51