HepLib
Loading...
Searching...
No Matches
Others.cpp
Go to the documentation of this file.
1
6#include "HEP.h"
7#include <cmath>
8
9namespace HepLib {
10
11 namespace {
12 int ep_ldegree(const ex & e) {
13 auto ee = exnormal(e);
14 auto nd = ee.numer_denom();
15 if(nd.op(0).is_polynomial(ep) && nd.op(1).is_polynomial(ep)) {
16 return nd.op(0).ldegree(ep) - nd.op(1).ldegree(ep);
17 }
18 cout << "numer or denom is NOT a polynormial of ep." << endl;
19 abort();
20 }
21
22
23 class Family {
24 public:
25 int pn;
26 lst intg;
27 Family(int pn_) : pn(pn_) { }
28 };
29
30 exmap _sp2x_(const ex & ips, const ex & eps) {
31 int ni = 0;
32 exmap sp2x;
33 for(auto ip : ips) {
34 for(auto ipx : ips) {
35 if(sp2x.find(ip*ipx)==sp2x.end()) {
36 auto xi = x(ni);
37 sp2x[ip*ipx] = xi;
38 sp2x[w*ip*ipx] = w*xi;
39 ni++;
40 }
41 }
42 for(auto ep : eps) {
43 auto xi = x(ni);
44 sp2x[ep*ip] = xi;
45 sp2x[w*ep*ip] = w*xi;
46 ni++;
47 }
48 }
49 return sp2x;
50 }
51
52 bool is_complete(const ex & props, const ex & ips, const ex & eps) {
53 auto sp2x = _sp2x_(ips, eps);
54 auto ps = subs(props, sp2x);
55 int n = ps.nops();
56 matrix mat(n,n);
57 for(int r=0; r<n; r++) {
58 auto xi = x(r);
59 for(int c=0; c<n; c++) {
60 mat(r,c) = ps.op(c).coeff(xi);
61 }
62 }
63 return mat.rank()==n;
64 }
65 bool is_complete(const ex & props, const exmap & sp2x) {
66 auto ps = subs(props, sp2x);
67 int n = ps.nops();
68 matrix mat(n,n);
69 for(int r=0; r<n; r++) {
70 auto xi = x(r);
71 for(int c=0; c<n; c++) {
72 mat(r,c) = ps.op(c).coeff(xi);
73 }
74 }
75 return mat.rank()==n;
76 }
77 }
78
79 bool Exp2AMFLOW::is_loop(const ex & e) {
80 for(auto ei : Internal) if(ei.is_equal(e)) return true;
81 return false;
82 }
83
84 void Exp2AMFLOW::Export(const ex & expr, const string & dir) {
85 static string wlo =
86R"EOF(
87If[Length[$ScriptCommandLine]<2, Print["Usage: wolframescript -f "<>ToString[$ScriptCommandLine[[1]]]<>" <n>"];Quit[]];
88current = DirectoryName@If[$FrontEnd===Null,$InputFileName,NotebookFileName[]];
89
90<<AMFlow`AMFlow`
91
92SetReductionOptions["IBPReducer"->"Kira"];
93ID = ToExpression[$ScriptCommandLine[[2]]];
94PropsInts=Get[FileNameJoin[{current,ToString[ID]<>".m"}]];
95
96AMFlowInfo["Family"] = Symbol["I"<>ToString[ID]];
97AMFlowInfo["Loop"] = <<Loop>>;
98AMFlowInfo["Leg"] = <<Leg>>;
99AMFlowInfo["Conservation"] = { };
100AMFlowInfo["Replacement"] = <<Replacement>>;
101AMFlowInfo["Propagator"] = PropsInts[[1]]/.<<M2M2>>;
102AMFlowInfo["Numeric"] = <<Numeric>>;
103AMFlowInfo["NThread"] = <<NThread>>;
104
105integrals = Map[(j[Symbol["I"<>ToString[ID]], Sequence@@#])&, PropsInts[[2]]];
106precision = <<Precision>>;
107epsorder = 2*Length@AMFlowInfo["Loop"]-PropsInts[[3]] + <<Order>>;
108sol = SolveIntegrals[integrals, precision, epsorder];
109Put[sol, FileNameJoin[{current, "sol"<>ToString[ID]<>".m"}]];
110
111Quit[];
112)EOF";
113
114 string sLoop = ex2str(Internal);
115 string_replace_all(sLoop, "==", "->");
116 string sLeg = ex2str(External);
117 string_replace_all(sLeg, "==", "->");
118 string sReplacement = ex2str(Replacement);
119 string_replace_all(sReplacement, "==", "->");
120 string sNumeric = ex2str(Numeric);
121 string_replace_all(sNumeric, "==", "->");
122 string sM2M2 = ex2str(M2M2);
123 string_replace_all(sM2M2, "==", "->");
124 string wl = wlo;
125 string_replace_all(wl, "<<Loop>>", sLoop);
126 string_replace_all(wl, "<<Leg>>", sLeg);
127 string_replace_all(wl, "<<Replacement>>", sReplacement);
128 string_replace_all(wl, "<<Numeric>>", sNumeric);
129 string_replace_all(wl, "<<NThread>>", to_string(NThread));
130 string_replace_all(wl, "<<M2M2>>", sM2M2);
131 string_replace_all(wl, "<<Order>>", ex2str(Order));
132 string_replace_all(wl, "<<Precision>>", ex2str(Precision));
133
134 system(("mkdir -p "+dir).c_str());
135 str2file(wl, dir+"/run.wl");
136
137 auto res = expr;
138
139 // handle (qi*pi)^-n
140 cout << "Replacing linear propagators ..." << endl;
141 sp2x = _sp2x_(Internal, External);
142 exset pq_fs;
143 find(res, F(w1,w2), pq_fs);
144 exmap pq_f2f;
145 for(auto f : pq_fs) {
146 lst ps = ex_to<lst>(f.op(0));
147 lst ns = ex_to<lst>(f.op(1));
148 lst ns_p; // problematic ns
149 for(int i=0; i<ps.nops(); i++) {
150 bool ok = false;
151 for(auto ip : Internal) {
152 if(ps.op(i).has(ip*ip)) {
153 ok = true;
154 break;
155 }
156 }
157 if(!ok) {
158 ex pi = ps.op(i);
159 if(!is_a<mul>(pi) || !pi.nops()==2) {
160 cout << "prop: " << pi << endl;
161 cout << "prop is NOT the form of a*b" << endl;
162 abort();
163 }
164
165 if(ns.op(i)==-1) {
166 ns_p.append(i);
167 } else if(ns.op(i)!=0) {
168 cout << f << endl;
169 cout << "n of qi.pi is NOT -1" << endl;
170 abort();
171 } else { // ns.op(i)==0
172 auto pa = pi.op(0), pb = pi.op(1);
173 ex pab = expand(pow(pa+pb,2)).subs(Replacement);
174 ps[i] = pab;
175 bool ic = is_complete(ps, sp2x);
176 if(!ic && is_loop(pa)) {
177 ps[i] = expand(pow(pa,2)).subs(Replacement);
178 ic = is_complete(ps, sp2x);
179 }
180 if(!ic && is_loop(pb)) {
181 ps[i] = expand(pow(pb,2)).subs(Replacement);
182 ic = is_complete(ps, sp2x);
183 }
184 if(!ic) {
185 cout << "1st: ic is NOT true!" << endl;
186 abort();
187 }
188 }
189 }
190 }
191 if(ns_p.nops()>1) {
192 cout << f << endl;
193 abort();
194 } else if(ns_p.nops()>0) {
195 auto idx = ex2int(ns_p.op(0));
196 ns[idx] = 0;
197 auto pidx = ps.op(idx);
198
199 ex pa = pidx.op(0);
200 ex pb = pidx.op(1);
201
202 ex pab = expand(pow(pa+pb,2)).subs(Replacement);
203 ps[idx] = pab;
204 bool ic = is_complete(ps, sp2x);
205 if(!ic && is_loop(pa)) {
206 ps[idx] = expand(pow(pa,2)).subs(Replacement);
207 ic = is_complete(ps, sp2x);
208 }
209 if(!ic && is_loop(pb)) {
210 ps[idx] = expand(pow(pb,2)).subs(Replacement);
211 ic = is_complete(ps, sp2x);
212 }
213 if(!ic) {
214 cout << "2nd: ic is NOT true!" << endl;
215 abort();
216 }
217
218 auto xps = subs(ps,sp2x);
219 auto xpidx = pidx.subs(sp2x);
220 for(auto ip : Internal) {
221 if(xps.has(ip)) {
222 cout << "xps still has ip" << endl;
223 cout << "xps: " << xps << endl;
224 abort();
225 }
226 if(xpidx.has(ip)) {
227 cout << "xpidx still has ip" << endl;
228 cout << "xpidx: " << xpidx << endl;
229 abort();
230 }
231 }
232
233 ex xeq = 0, eq = 0, fres = 0;
234 lst ys;
235 for(int ii=0; ii<ps.nops(); ii++) {
236 symbol yi;
237 xeq += yi*xps.op(ii);
238 eq += yi*ps.op(ii);
239 lst nn = ns;
240 nn[ii] = ns.op(ii)-1;
241 fres += yi*F(ps, nn);
242 ys.append(yi);
243 }
244 lst eqs;
245 for(int ii=0; ii<ps.nops(); ii++) {
246 auto xi = x(ii);
247 eqs.append(xeq.coeff(xi)==xpidx.coeff(xi));
248 }
249 auto sol = lsolve(eqs,ys);
250
251 if(sol.nops()<1 || sol.has(x(w))) {
252 cout << "wrong sol: " << sol << endl;
253 }
254
255 auto rem = pidx-eq.subs(sol);
256 fres = fres.subs(sol);
257 if(!is_zero(rem)) {
258 fres += rem * F(ps, ns);
259 }
260
261 pq_f2f[f] = fres;
262 ex chk = exnormal(F2ex(f-pq_f2f[f]));
263 if(chk!=0) {
264 cout << "Failed: chk=" << chk << endl;
265 }
266 } else if(!f.op(0).is_equal(ps)) {
267 pq_f2f[f] = F(ps, ns);
268 ex chk = exnormal(F2ex(f-pq_f2f[f]));
269 if(chk!=0) {
270 cout << "Failed: chk=" << chk << endl;
271 }
272 }
273 }
274
275 cout << "Collecting ..." << endl;
276
277 res = MapFunction([&](const ex & e, MapFunction &self)->ex{
278 if(e.match(F(w1, w2))) {
279 auto itr = pq_f2f.find(e);
280 if(itr==pq_f2f.end()) return e;
281 else return itr->second;
282 } else return e.map(self);
283 })(res);
284
285 res = collect_ex(res, F(w1,w2));
286
287 if(true) { // alos export CPP by calling Exp2AMF
288 Exp2AMF amf;
289 amf.Internal = Internal;
290 amf.External = External;
292 amf.Precision = Precision;
293 amf.Order = Order;
294 for(auto item : Numeric) amf.Replacement.append(item);
295 amf.Export(res, dir);
296 }
297
298 exset fs;
299 find(res, F(w1,w2), fs);
300 map<ex,Family,ex_is_less> p2f;
301 exmap f2f;
302 int pn = 0;
303 for(auto f : fs) {
304 auto itr = p2f.find(f.op(0));
305 if(itr == p2f.end()) {
306 itr = p2f.insert(make_pair(f.op(0), Family(pn))).first;
307 pn++;
308 }
309 itr->second.intg.append(f.op(1));
310 f2f[f] = F(itr->second.pn, f.op(1));
311 }
312
313 res = MapFunction([&](const ex & e, MapFunction &self)->ex{
314 if(e.match(F(w1, w2))) {
315 auto itr = f2f.find(e);
316 if(itr==f2f.end()) {
317 cout << "F Not Found" << endl;
318 abort();
319 }
320 return itr->second;
321 } else return e.map(self);
322 })(res);
323
324 cout << "Exporting res.txt ..." << endl;
325 ex2file(res.subs(Numeric), dir+"/res.txt");
326
327 string sres =
328R"EOF(
329current = If[$FrontEnd===Null,$InputFileName,NotebookFileName[]]//DirectoryName;
330<<HepLib`
331Module[{sols, res},
332sols = Flatten@Table[Import[FileNameJoin[{current,"sol"<>ToString[i]<>".m"}]], {i,0,<<NN>>}];
333res = C2M@Import[FileNameJoin[{current, "res.txt"}]];
334res = res/.{F[p_, n_] :> j[Symbol["I"<>ToString[p]], Sequence@@n]} /. Dispatch@sols;
335res
336]
337)EOF";
338
339 string_replace_all(sres, "<<NN>>", to_string(pn-1));
340 str2file(sres, dir+"/res.m");
341
342 int tot = p2f.size(), cur = 0;
343 for(auto kv : p2f) {
344 cur++;
345 cout << "[ " << cur << " / " << tot << "] pn = " << kv.second.pn << endl;
346 cout << kv.first << endl;
347 cout << kv.second.intg << endl;
348 cout << endl;
349
350 lst prop = ex_to<lst>(kv.first);
351 auto & f = kv.second;
352 for(int i=0; i<prop.nops(); i++) {
353 bool ok = false;
354 for(auto ip : Internal) {
355 if(prop.op(i).has(ip*ip)) {
356 ok = true;
357 break;
358 }
359 }
360 if(!ok) {
361 cout << "Propagators: " << prop.op(i) << " @ pos: " << i << endl;
362 cout << "Integrals: " << f.intg << endl;
363 abort();
364 }
365 }
366
367 GiNaC_Parallel_Verb["Exp2AMFLOW"] = 0;
368 auto order_vec = GiNaC_Parallel(f.intg.nops(), [&](int idx)->ex{
369 auto ns = f.intg.op(idx);
370 ex cc = res.coeff(F(f.pn, ns)).subs(Numeric);
371 cc = cc.subs(d==4-2*ep);
372 auto ldeg = ep_ldegree(cc);
373 return ldeg;
374 }, "Exp2AMFLOW");
375
376 int order = 0;
377 for(auto ldeg : order_vec) {
378 if(order>ldeg) order = ex2int(ldeg);
379 }
380
381 ex2file(lst{ prop, f.intg, order }, dir+"/"+to_string(f.pn)+".m");
382 }
383
384
385
386 }
387
388 void Exp2AMF::Export(const ex & expr, const string & dir) {
389 static string cpp =
390R"EOF(
391#include "HepLib.h"
392
393using namespace HepLib;
394
395int main(int argc, char ** argv) {
396
397 Verbose = 100;
398 lst Replacement = str2lst("<<Replacement>>");
399
400 string n = "res";
401 if(argc>1) n = string(argv[1]);
402 map<string,ex> data;
403 garRead("data.gar", data);
404 int tot = ex2int(data["total"]);
405
406 if(n=="res") {
407 ex res = data["res"];
408 lst rules;
409 for(int i=0; i<tot; i++) {
410 ex ri = file2ex(to_string(i)+".out");
411 for(auto item : ri) rules.append(item);
412 }
413 res = res.subs(rules).subs(Replacement).subs(d==4-2*ep);
414 res = series_ex(res,ep,ex2int(data["Order"]));
415 res = collect_ex(res, lst{ ep });
416 res = chop(res, str2ex("1E-15"));
417 cout << endl << res << endl << endl;
418 return 0;
419 }
420 int pn = stoi(n);
421 if(pn+1>tot || pn<0) return 0;
422
423 Fit amf;
424 //amf.Mode = Fit::Modes::All;
425
426 amf.Replacement = Replacement;
427 amf.Internal = ex_to<lst>(data["Internal"]);
428 amf.External = ex_to<lst>(data["External"]);
429
430 amf.Propagator = ex_to<lst>(data[n].op(0));
431 amf.Integral = ex_to<lst>(data[n].op(1));
432
433 int tot_order = 2*amf.Internal.nops() + ex2int(data["Order"]) - ex2int(data[n].op(2));
434 amf.Parallel(ex2int(data["Precision"]), tot_order);
435
436 lst rules;
437 for(int i=0; i<amf.Integral.nops(); i++) {
438 rules.append(F(pn, amf.Integral.op(i)) == amf.NIntegral.op(i));
439 }
440
441 ex2file(rules, n+".out");
442
443 return 0;
444
445}
446)EOF";
447
448 string w_cpp = cpp;
449 system(("mkdir -p "+dir).c_str());
450 string_replace_all(w_cpp, "<<Replacement>>", ex2str(Replacement));
451 str2file(w_cpp, dir+"/AMF.cpp");
452
453 map<string, ex> data_export;
454
455 data_export["Internal"] = Internal;
456 data_export["External"] = External;
457 data_export["Replacement"] = Replacement;
458 data_export["Order"] = Order;
459 data_export["Precision"] = Precision;
460
461 auto res = expr;
462 res = collect_ex(res, F(w1,w2));
463
464 exset fs;
465 find(res, F(w1,w2), fs);
466 map<ex,Family,ex_is_less> p2f;
467 exmap f2f;
468 int pn = 0;
469 for(auto f : fs) {
470 auto itr = p2f.find(f.op(0));
471 if(itr == p2f.end()) {
472 itr = p2f.insert(make_pair(f.op(0), Family(pn))).first;
473 pn++;
474 }
475 itr->second.intg.append(f.op(1));
476 f2f[f] = F(itr->second.pn, f.op(1));
477 }
478
479 res = MapFunction([&](const ex & e, MapFunction &self)->ex{
480 if(e.match(F(w1, w2))) {
481 auto itr = f2f.find(e);
482 if(itr==f2f.end()) {
483 cout << "F Not Found" << endl;
484 abort();
485 }
486 return itr->second;
487 } else return e.map(self);
488 })(res);
489 data_export["res"] = res;
490
491 int tot = p2f.size();
492 for(auto kv : p2f) {
493 lst prop = ex_to<lst>(kv.first);
494 auto & f = kv.second;
495
496 GiNaC_Parallel_Verb["Exp2AMF"] = 0;
497 auto order_vec = GiNaC_Parallel(f.intg.nops(), [&](int idx)->ex{
498 auto ns = f.intg.op(idx);
499 ex cc = res.coeff(F(f.pn, ns)).subs(Replacement);
500 cc = cc.subs(d==4-2*ep);
501 auto ldeg = ep_ldegree(cc);
502 return ldeg;
503 }, "Exp2AMF");
504
505 int order = 0;
506 for(auto ldeg : order_vec) {
507 if(order>ldeg) order = ex2int(ldeg);
508 }
509
510 data_export[to_string(f.pn)] = lst{ prop, f.intg, order };
511 }
512 data_export["total"] = tot;
513
514 garWrite(dir+"/data.gar", data_export);
515
516 str2file("heplib++ -o AMF AMF.cpp\nseq 0 "+to_string(tot-1)+" | parallel -j 4 ./AMF {}\n./AMF res\n", dir+"/run.sh");
517
518 }
519
520}
HEP header file.
int pn
Definition Others.cpp:25
lst intg
Definition Others.cpp:26
void Export(const ex &expr, const string &dir)
Definition Others.cpp:84
lst Replacement
Definition HEP.h:670
lst Internal
Definition HEP.h:668
int Precision
Definition HEP.h:671
void Export(const ex &expr, const string &dir)
Definition Others.cpp:353
lst External
Definition HEP.h:669
class to wrap map_function of GiNaC
Definition BASIC.h:676
HepLib namespace.
Definition BASIC.cpp:17
void ex2file(const ex &expr, string filename)
export expression file
Definition BASIC.cpp:846
const Symbol ep
ex collect_ex(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica
Definition BASIC.cpp:1203
const Symbol eps
ex F2ex(const ex &expr_in)
convert F(ps, ns) to normal ex, ns is like FIRE convention
Definition ApartIBP.cpp:87
ex w
Definition Init.cpp:93
map< string, int > GiNaC_Parallel_Verb
Definition Init.cpp:149
ex exnormal(const ex &expr, int opt)
normalize a expression
Definition BASIC.cpp:1917
void string_replace_all(string &str, const string &from, const string &to)
void garWrite(const string &garfn, const map< string, ex > &resMap)
garWrite to write the string-key map to the archive
Definition BASIC.cpp:640
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
Definition BASIC.cpp:716
void str2file(const string &ostr, string filename)
export string to a file
Definition BASIC.cpp:788
ex w1
Definition BASIC.h:500
exvector GiNaC_Parallel(int ntotal, std::function< ex(int)> f, const string &key)
GiNaC Parallel Evaluation using fork.
Definition BASIC.cpp:259
ex w2
Definition BASIC.h:500
int ex2int(ex num)
ex to integer
Definition BASIC.cpp:894
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51