HepLib
Loading...
Searching...
No Matches
IBP.cpp
Go to the documentation of this file.
1
6#include "IBP.h"
7#include "exFlint.h"
8#include <cmath>
9
10namespace HepLib {
11
12 namespace {
13 ex_is_less less;
14 }
15
16 static void a_print(const ex & ex_in, const print_context & c) {
17 c.s << "a[" << ex_in << "]";
18 }
19
20 REGISTER_FUNCTION(a, do_not_evalf_params().print_func<print_dflt>(a_print))
21
22 void IBP::Reduce() {
23 Export();
24 Run();
25 Import();
26 }
27
28 void IBP::garExport(string garfn) {
29 archive ar;
30 ar.archive_ex(Internal, "Internal");
31 ar.archive_ex(External, "External");
32 ar.archive_ex(Replacement, "Replacement");
33 ar.archive_ex(Propagator, "Propagator");
34 ar.archive_ex(Cut, "Cut");
35 ar.archive_ex(DSP, "DSP");
36 ar.archive_ex(ISP, "ISP");
37 ar.archive_ex(SECTOR, "SECTOR");
38
39 ar.archive_ex(Shift.size(), "NShift");
40 int i = 0;
41 for(auto kv : Shift) {
42 ar.archive_ex(kv.first, ("ShiftK-"+to_string(i)).c_str());
43 ar.archive_ex(kv.second, ("ShiftV-"+to_string(i)).c_str());
44 i++;
45 }
46
47 ar.archive_ex(reCut, "reCut"); // bool
48 ar.archive_ex(ProblemNumber, "ProblemNumber"); // int
49 ar.archive_ex(Symbol(WorkingDir), "WorkingDir"); // string
50 ar.archive_ex(PIntegral, "PIntegral");
51 ar.archive_ex(MIntegral, "MIntegral");
52 ar.archive_ex(Rules, "Rules");
53 ar.archive_ex(IsAlwaysZero, "IsAlwaysZero"); // bool
54
55 ofstream out(garfn);
56 out << ar;
57 out.close();
58 }
59
60 ex IBP::TO() {
61 lst shift;
62 for(auto kv : Shift) shift.append(lst{kv.first, kv.second});
63
64 return lst{ Internal, External, Replacement, Propagator, Cut, DSP, ISP, SECTOR, shift, reCut, ProblemNumber, Symbol(WorkingDir), PIntegral, MIntegral, Rules, IsAlwaysZero };
65 }
66
67 void IBP::garImport(string garfn) {
68 archive ar;
69 ifstream in(garfn);
70 in >> ar;
71 in.close();
72
73 Internal = ex_to<lst>(ar.unarchive_ex("Internal"));
74 External = ex_to<lst>(ar.unarchive_ex("External"));
75 Replacement = ex_to<lst>(ar.unarchive_ex("Replacement"));
76 Propagator = ex_to<lst>(ar.unarchive_ex("Propagator"));
77 Cut = ex_to<lst>(ar.unarchive_ex("Cut"));
78 DSP = ex_to<lst>(ar.unarchive_ex("DSP"));
79 ISP = ex_to<lst>(ar.unarchive_ex("ISP"));
80 SECTOR = ex_to<lst>(ar.unarchive_ex("SECTOR"));
81
82 int n = ex_to<numeric>(ar.unarchive_ex("NShift")).to_int();
83 for(int i=0; i<n; i++) {
84 int key = ex_to<numeric>(ar.unarchive_ex(("ShiftK-"+to_string(i)).c_str())).to_int();
85 ex val = ar.unarchive_ex(("ShiftV-"+to_string(i)).c_str());
86 Shift[key] = val;
87 }
88
89 reCut = !(ar.unarchive_ex("reCut").is_zero()); // bool
90 ProblemNumber = ex_to<numeric>(ar.unarchive_ex("ProblemNumber")).to_int(); // int
91 WorkingDir = ex_to<Symbol>(ar.unarchive_ex("WorkingDir")).get_name();
92 PIntegral = ex_to<lst>(ar.unarchive_ex("PIntegral"));
93 MIntegral = ex_to<lst>(ar.unarchive_ex("MIntegral"));
94 Rules = ex_to<lst>(ar.unarchive_ex("Rules"));
95 IsAlwaysZero = !(ar.unarchive_ex("IsAlwaysZero").is_zero()); // bool
96 }
97
98 void IBP::FROM(ex s) {
99 int i = 0;
100 Internal = ex_to<lst>(s.op(i++));
101 External = ex_to<lst>(s.op(i++));
102 Replacement = ex_to<lst>(s.op(i++));
103 Propagator = ex_to<lst>(s.op(i++));
104 Cut = ex_to<lst>(s.op(i++));
105 DSP = ex_to<lst>(s.op(i++));
106 ISP = ex_to<lst>(s.op(i++));
107 if(s.nops()>15) SECTOR = ex_to<lst>(s.op(i++)); // if to work with old version
108 lst shift = ex_to<lst>(s.op(i++));
109 reCut = s.op(i++).is_equal(1);
110 ProblemNumber = ex_to<numeric>(s.op(i++)).to_int();
111 WorkingDir = ex_to<Symbol>(s.op(i++)).get_name();
112 PIntegral = ex_to<lst>(s.op(i++));
113 MIntegral = ex_to<lst>(s.op(i++));
114 Rules = ex_to<lst>(s.op(i++));
115 IsAlwaysZero = s.op(i++).is_equal(1);
116 for(auto item : shift) Shift[ex_to<numeric>(item.op(0)).to_int()] = item.op(1);
117 }
118
119 void IBP::ReShare(const vector<IBP*> & fs) {
120 string garfn = to_string(getpid())+".ReShare.gar";
121 if(true) {
122 archive ar;
123 for(int i=0; i<fs.size(); i++) {
124 string si = to_string(i);
125 ar.archive_ex(fs[i]->Internal, (si+"-1").c_str());
126 ar.archive_ex(fs[i]->External, (si+"-2").c_str());
127 ar.archive_ex(fs[i]->Replacement, (si+"-3").c_str());
128 ar.archive_ex(fs[i]->Propagator, (si+"-4").c_str());
129 ar.archive_ex(fs[i]->DSP, (si+"-5").c_str());
130 ar.archive_ex(fs[i]->ISP, (si+"-6").c_str());
131 ar.archive_ex(fs[i]->SECTOR,(si+"-7").c_str());
132 ar.archive_ex(fs[i]->PIntegral, (si+"-8").c_str());
133 ar.archive_ex(fs[i]->MIntegral, (si+"-9").c_str());
134 ar.archive_ex(fs[i]->Rules, (si+"-10").c_str());
135 }
136 ofstream out(garfn);
137 out << ar;
138 out.close();
139 }
140 if(true) {
141 archive ar;
142 ifstream in(garfn);
143 in >> ar;
144 in.close();
145
146 map<string, ex> dict;
147 for(int i=0; i<ar.num_expressions(); i++) {
148 string name;
149 ex res = ar.unarchive_ex(name, i);
150 dict[name] = res;
151 }
152
153 for(int i=0; i<fs.size(); i++) {
154 string si = to_string(i);
155 fs[i]->Internal = ex_to<lst>(dict[si+"-1"]);
156 fs[i]->External = ex_to<lst>(dict[si+"-2"]);
157 fs[i]->Replacement = ex_to<lst>(dict[si+"-3"]);
158 fs[i]->Propagator = ex_to<lst>(dict[si+"-4"]);
159 fs[i]->DSP = ex_to<lst>(dict[si+"-5"]);
160 fs[i]->ISP = ex_to<lst>(dict[si+"-6"]);
161 fs[i]->SECTOR = ex_to<lst>(dict[si+"-7"]);
162 fs[i]->PIntegral = ex_to<lst>(dict[si+"-8"]);
163 fs[i]->MIntegral = ex_to<lst>(dict[si+"-9"]);
164 fs[i]->Rules = ex_to<lst>(dict[si+"-10"]);
165 }
166 }
167 }
168
169 pair<exmap,lst> IBP::FindRules(bool is_mi) {
170 if(!has_w(Replacement)) {
171 lst repl;
172 for(auto item : Replacement) {
173 repl.append(item);
174 repl.append(w*item.op(0) == w*item.op(1));
175 }
176 Replacement = repl;
177 }
178 vector<IBP*> ibps;
179 ibps.push_back(this);
180 auto rs_mis = HepLib::FindRules(ibps, is_mi);
181 if(is_mi && rs_mis.first.size()>0) {
182 auto nr = Rules.nops();
183 for(int i=0; i<nr; i++) {
184 auto ri = Rules.op(i);
185 Rules.let_op(i) = (ri.op(0) == ri.op(1).subs(rs_mis.first, nopat));
186 }
187 for(auto mi : MIntegral) {
188 auto mi2 = mi.subs(rs_mis.first, nopat);
189 if(mi==mi2) continue;
190 Rules.append(mi==mi2);
191 }
192 MIntegral = rs_mis.second;
193 sort_lst(MIntegral);
194 }
195 return rs_mis;
196 }
197
204 exmap SortPermutation(const ex & in_expr, const lst & xs) {
205 auto expr = in_expr;
206 bool isPoly = true;
207 exmap xmap; // note that we need xmap.size == xs.nops()
208
209 map<ex,vector<int>,ex_is_less> pgrp;
210 if(!expr.is_polynomial(xs)) {
211 if(Verbose>2) cout << "SortPermutation: NOT a polynomials, try ALL permutations!" << endl;
212 expr = expr.numer_denom();
213 if(true || !expr.op(0).is_polynomial(xs) || !expr.op(1).is_polynomial(xs)) {
214 isPoly = false;
215 for(int i=0; i<xs.nops(); i++) {
216 pgrp[-1].push_back(i); // all permuations
217 xmap[xs.op(i)] = xs.op(i);
218 }
219 } else {
220 expr = expr.op(0) * expr.op(1);
221 }
222 }
223
224 if(isPoly) { // only for polynomials
225 auto cv_lst = collect_lst(expr, xs);
226 exvector cvs;
227 for(auto item : cv_lst) cvs.push_back(item);
228 sort_vec(cvs); // first sort by coefficient
229
230 int nxi = xs.nops();
231 bool first = true;
232 lst xkey[nxi];
233 lst subkey[nxi];
234 ex clast;
235 for(auto cv : cvs) {
236 ex cc = cv.op(0);
237 ex vv = cv.op(1);
238 if(is_zero(cc)) continue;
239 if(!first && !is_zero(cc-clast)) { // equal coefficient to the same key
240 for(int i=0; i<nxi; i++) {
241 sort_lst(subkey[i]);
242 for(auto item : subkey[i]) xkey[i].append(item);
243 subkey[i].remove_all();
244 }
245 }
246 first = false;
247 clast = cc;
248 for(int i=0; i<nxi; i++) subkey[i].append(vv.degree(xs.op(i)));
249 }
250
251 for(int i=0; i<nxi; i++) { // add last subkey
252 sort_lst(subkey[i]); // need sort due to equal coefficient
253 for(auto item : subkey[i]) xkey[i].append(item);
254 subkey[i].remove_all();
255 }
256
257 exvector key_xi;
258 for(int i=0; i<nxi; i++) key_xi.push_back(lst{xkey[i], xs.op(i)});
259 sort_vec(key_xi); // first sort by key
260
261 for(int i=0; i<nxi; i++) {
262 auto xi = key_xi[i].op(1);
263 auto xki = key_xi[i].op(0);
264 xmap[xi] = xs.op(i); // initial x-replacement
265 pgrp[xki].push_back(i);
266 }
267 expr = expr.subs(xmap, nopat); // need to update expr before permutations
268 expr = collect_ex(expr, xs); // need collect here
269 }
270
271 // pgrp - needs to permuation explicitly
272 ex expr_min = expr;
273 exmap xmap_min;
274 long long npt = 1;
275 for(auto pi : pgrp) {
276 int nvi = pi.second.size();
277 for(int i=1; i<=nvi; i++) npt *= i; // nvi!
278 }
279 for(long long np=0; np<npt; np++) {
280 long long npc = np;
281 exmap xmap_tmp;
282 for(auto pi : pgrp) {
283 auto vi = pi.second;
284 int nvi = vi.size();
285 if(nvi<2) continue;
286 long long npti = 1;
287 for(int i=1; i<=nvi; i++) npti *= i; // nvi!
288 int ck = npc % npti; // kth permutation
289 npc = npc / npti;
290
291 // https://stackoverflow.com/questions/1995328/are-there-any-better-methods-to-do-permutation-of-string
292 auto vip = vi;
293 int k = ck;
294 for(int j=1; j<nvi; ++j) { // startoverflow: j starts from 1
295 std::swap(vip[k%(j+1)], vip[j]);
296 k=k/(j+1);
297 }
298
299 for(int j=0; j<nvi; j++) xmap_tmp[xs.op(vi[j])] = xs.op(vip[j]);
300 }
301 ex expr_tmp = expr.subs(xmap_tmp,nopat);
302 if(ex_less(expr_tmp, expr_min)) {
303 expr_min = expr_tmp;
304 xmap_min = xmap_tmp;
305 }
306 }
307
308 for(auto & kv : xmap) kv.second = kv.second.subs(xmap_min,nopat);
309 return xmap;
310 }
311
318 lst LoopUF(const IBP & ibp, const ex & idx) {
319
320 auto props = ibp.Propagator;
321
322 // handle sign
323 ex sign = 1;
324 for(int i=0; i<props.nops(); i++) {
325 auto ipr = expand_ex(props.op(i), ibp.Internal);
326
327 if(ipr.has(iEpsilon)) {
328 auto cc = ipr.coeff(iEpsilon);
329 if(is_a<numeric>(cc)) {
330 if(cc<0) { // using +iEpsilon
331 sign *= pow(-1, idx.op(i));
332 props.let_op(i) = ex(0)-props.op(i);
333 }
334 props.let_op(i) = props.op(i).subs(iEpsilon==0,nopat);
335 goto sign_done;
336 } else {
337 cout << endl << ipr << endl;
338 throw Error("LoopUF: sign of iEpsilon NOT determined.");
339 }
340 }
341
342 for(auto lp : ibp.Internal) {
343 if(ipr.degree(lp)==2) {
344 auto cc = ipr.coeff(lp,2);
345 if(is_a<numeric>(cc)) {
346 if(cc<0) { // using +l^2
347 sign *= pow(-1, idx.op(i));
348 props.let_op(i) = ex(0)-props.op(i);
349 }
350 goto sign_done;
351 }
352 }
353 }
354
355 sign_done: ;
356 }
357
358 ex ut, ft, uf;
359 lst key;
360 lst xs;
361 exmap x2ax;
362 int nxi=0;
363 int nps = props.nops();
364 ft = 0;
365 for(int i=0; i<nps; i++) {
366 if(is_zero(idx.op(i))) {
367 key.append(0);
368 continue;
369 }
370 key.append(1);
371 if(!is_zero(idx.op(i)-1)) x2ax[x(nxi)] = a(idx.op(i)) * x(nxi);
372 xs.append(x(nxi));
373 ft -= x(nxi) * props.op(i); // only used when no cache item
374 nxi++;
375 }
376
377 static map<ex,exmap,ex_is_less> cache_by_prop;
378 if(using_cache && cache_limit>0 && cache_by_prop.size() > cache_limit/10) cache_by_prop.clear();
379 exmap & cache = cache_by_prop[lst{props,ibp.Internal}];
380 if(!using_cache || cache.find(key)==cache.end()) { // no cache item
381 ut = 1;
382 ft = expand_ex(ft);
383 ft = subs(ft, ibp.Replacement);
384 for(int i=0; i<ibp.Internal.nops(); i++) {
385 auto t2 = ft.coeff(ibp.Internal.op(i),2);
386 auto t1 = ft.coeff(ibp.Internal.op(i),1);
387 auto t0 = ft.subs(ibp.Internal.op(i)==0,nopat);
388 ut *= t2;
389 if(is_zero(t2)) return lst{0,0,1};
390 ft = normal_flint(t0-t1*t1/(4*t2));
391 //ft = expand_ex(ft);
392 ft = subs(ft, ibp.Replacement);
393 }
394 ft = normal_flint(ut*ft);
395 ft = normal_flint(subs(ft, ibp.Replacement));
396 ut = normal_flint(subs(ut, ibp.Replacement));
397 uf = normal_flint(ut+ft); // ut*ft, replay with ut+ft
398
399 if(using_cache) cache[key] = lst{ut,ft,uf};
400 } else {
401 auto cc = cache[key];
402 ut = cc.op(0);
403 ft = cc.op(1);
404 uf = cc.op(2);
405 }
406
407 ut = ut.subs(x2ax,nopat);
408 ft = ft.subs(x2ax,nopat);
409 uf = uf.subs(x2ax,nopat);
410
411 uf = uf.subs(MapPreSP);
412 auto xmap = SortPermutation(uf,xs);
413 ut = (ut.subs(xmap,nopat));
414 ft = (ft.subs(xmap,nopat));
415 return lst{ut, ft, sign};
416 }
417
428 lst UF(const ex & props, const ex & ns, const ex & loops, const ex & tloops, const ex & lsubs, const ex & tsubs) {
429 auto ps = props;
430
431 // handle sign
432 ex sign = 1;
433 for(int i=0; i<ps.nops(); i++) {
434 auto ipr = expand_ex(ps.op(i), loops);
435
436 if(ipr.has(iEpsilon)) {
437 auto cc = ipr.coeff(iEpsilon);
438 if(is_a<numeric>(cc)) {
439 if(cc<0) { // using +iEpsilon
440 sign *= pow(-1, ns.op(i));
441 ps.let_op(i) = ex(0)-ps.op(i);
442 }
443 ps.let_op(i) = ps.op(i).subs(iEpsilon==0,nopat);
444 goto sign_done;
445 } else throw Error("UF: sign of iEpsilon NOT determined.");
446 }
447
448 for(auto lp : loops) {
449 if(ipr.degree(lp)==2) {
450 auto cc = ipr.coeff(lp,2);
451 if(is_a<numeric>(cc)) {
452 if(cc<0) { // using +l^2
453 sign *= pow(-1, ns.op(i));
454 ps.let_op(i) = ex(0)-ps.op(i);
455 }
456 goto sign_done;
457 }
458 }
459 }
460
461 ipr = expand(ipr).subs(lsubs).subs(tsubs);
462 for(auto lp : tloops) {
463 if(ipr.degree(lp)==2) {
464 auto cc = ipr.coeff(lp,2);
465 if(is_a<numeric>(cc)) {
466 if(cc<0) { // using +l^2
467 sign *= pow(-1, ns.op(i));
468 ps.let_op(i) = ex(0)-ps.op(i);
469 }
470 goto sign_done;
471 }
472 }
473 }
474
475 sign_done: ;
476 }
477
478 ex ut1, ut2, ft, uf;
479 lst key;
480 lst xs;
481 exmap x2ax;
482 int nxi=0;
483 int nps = ps.nops();
484 ft = 0;
485 for(int i=0; i<nps; i++) {
486 if(is_zero(ns.op(i))) {
487 key.append(0);
488 continue;
489 }
490 key.append(1);
491 if(!is_zero(ns.op(i)-1)) x2ax[x(nxi)] = a(ns.op(i)) * x(nxi);
492 xs.append(x(nxi));
493 ft -= x(nxi) * ps.op(i); // only used when no cache item
494 nxi++;
495 }
496
497 static map<ex,exmap,ex_is_less> cache_by_prop;
498 exmap & cache = cache_by_prop[lst{ps,loops,tloops}];
499 if(!using_cache || cache.find(key)==cache.end()) { // no cache item
500 ut1 = 1;
501 ft = expand(ft);
502 ft = subs(ft, lsubs);
503 for(int i=0; i<loops.nops(); i++) {
504 auto t2 = ft.coeff(loops.op(i),2);
505 auto t1 = ft.coeff(loops.op(i),1);
506 auto t0 = ft.subs(loops.op(i)==0,nopat);
507 ut1 *= t2;
508 if(is_zero(t2)) return lst{0,0,0,1};
509 ft = exnormal(t0-t1*t1/(4*t2));
510 ft = expand(ft);
511 ft = subs(ft, lsubs);
512 }
513 ft = exnormal(ut1*ft);
514 ft = exnormal(subs(ft, lsubs));
515 ut1 = exnormal(subs(ut1, lsubs));
516
517 ut2 = 1;
518 ft = expand(ft);
519 ft = subs(ft, tsubs);
520 for(int i=0; i<tloops.nops(); i++) {
521 auto t2 = ft.coeff(tloops.op(i),2);
522 auto t1 = ft.coeff(tloops.op(i),1);
523 auto t0 = ft.subs(tloops.op(i)==0,nopat);
524 ut2 *= t2;
525 if(is_zero(t2)) return lst{0,0,0,1};
526 ft = exnormal(t0-t1*t1/(4*t2));
527 ft = expand(ft);
528 ft = subs(ft, tsubs);
529 }
530 ft = exnormal(ut2*ft);
531 ft = exnormal(subs(ft, tsubs));
532 ut2 = exnormal(subs(ut2, tsubs));
533
534 uf = exnormal(ut1*ut2*ft);
535 if(using_cache) cache[key] = lst{ut1,ut2,ft,uf};
536 } else {
537 auto cc = cache[key];
538 ut1 = cc.op(0);
539 ut2 = cc.op(1);
540 ft = cc.op(2);
541 uf = cc.op(3);
542 }
543 ut1 = ut1.subs(x2ax,nopat);
544 ut2 = ut2.subs(x2ax,nopat);
545 ft = ft.subs(x2ax,nopat);
546 uf = uf.subs(x2ax,nopat);
547
548 uf = uf.subs(MapPreSP);
549 auto xmap = SortPermutation(uf,xs);
550 uf = uf.subs(xmap,nopat);
551
552 // z Permuatations
553 if(tloops.nops()>1) {
554 lst zs;
555 auto nzi = tloops.nops();
556 for(int i=0; i<nzi; i++) zs.append(z(i+1));
557 auto zmap = SortPermutation(uf,zs);
558 for(auto kv : zmap) xmap[kv.first] = kv.second; // add to xmap
559 }
560
561 ut1 = (ut1.subs(xmap,nopat));
562 ut2 = (ut2.subs(xmap,nopat));
563 ft = (ft.subs(xmap,nopat));
564 return lst{ut1, ut2, ft, sign};
565 }
566
574 pair<exmap,lst> FindRules(vector<IBP*> fs, bool mi, std::function<lst(const IBP &, const ex &)> uf) {
575 vector<pair<IBP*,ex>> ibp_idx_vec;
576
577 for(auto & fi : fs) {
578 if(!has_w(fi->Replacement)) {
579 lst repl;
580 for(auto item : fi->Replacement) {
581 repl.append(item);
582 repl.append(w*item.op(0) == w*item.op(1));
583 }
584 fi->Replacement = repl;
585 }
586 }
587
588 if(mi) for(auto fi : fs) for(auto item : fi->MIntegral) ibp_idx_vec.push_back(make_pair(fi, item));
589 else for(auto fi : fs) for(auto item : fi->Integral) ibp_idx_vec.push_back(make_pair(fi, F(fi->ProblemNumber,item)));
590
591 exvector uf_smi_vec = GiNaC_Parallel(ibp_idx_vec.size(), [&ibp_idx_vec,&uf](int idx)->ex {
592 auto p = ibp_idx_vec[idx];
593 const IBP & fi = (*p.first);
594 auto mi = p.second;
595 auto ks = uf(fi,mi.subs(F(w1,w2)==w2));
596 int nk = ks.nops()-1;
597 lst key;
598 for(int i=0; i<nk; i++) key.append(expand(ks.op(i)));
599 lst pi = fi.Propagator;
600 return lst{ key, lst{ pi, ks.op(nk), mi } }; // ks.op(nk) -> the sign
601 }, "FR");
602
603 map<ex,lst,ex_is_less> group;
604 int ntotal = uf_smi_vec.size();
605 int nLimit = 10000;
606
607 for(auto item : uf_smi_vec) {
608 group[item.op(0)].append(item.op(1));
609 }
610
611 exmap rules;
612 lst int_lst;
613 exset pis;
614 if(true) { // single element case
615 exset ks, vs;
616 for(auto g : group) {
617 if(g.second.nops()==1) {
618 ks.insert(g.first);
619 vs.insert(g.second.op(0));
620 }
621 }
622 for(auto vi : vs) {
623 pis.insert(vi.op(0));
624 int_lst.append(vi.op(2));
625 }
626 for(auto ki : ks) group.erase(ki);
627 }
628
629 while(!group.empty()) {
630 if(pis.size()>0) {
631 exset ks;
632 for(auto g : group) {
633 ex c0, v0;
634 for(auto gi : g.second) {
635 auto itr = pis.find(gi.op(0));
636 if(itr!=pis.end()) {
637 ks.insert(g.first);
638 c0 = gi.op(1);
639 v0 = gi.op(2);
640 goto found;
641 }
642 }
643 continue; // if not found pi
644 found: ;
645 int_lst.append(v0);
646 for(auto gi : g.second) {
647 auto ci = gi.op(1);
648 auto vi = gi.op(2);
649 if(v0.is_equal(vi)) continue;
650 rules[vi] = v0 * c0 / ci;
651 }
652 }
653 for(auto ki : ks) group.erase(ki);
654 if(group.empty()) break;
655 }
656 pis.clear();
657
658 int cur = 0;
659 for(auto g : group) {
660 cur++;
661 if(cur>10) break;
662 pis.insert(g.second.op(0).op(0));
663 }
664 }
665
666 if(!In_GiNaC_Parallel && Verbose>2) cout << PRE << "\\--FindRules: " << WHITE << ntotal << " :> " << int_lst.nops() << RESET << " @ " << now(false) << endl;
667 return make_pair(rules,int_lst);
668 }
669
670 static matrix Redrowech(const matrix & mat) {
671 Fermat &fermat = Fermat::get();
672 int &v_max = fermat.vmax;
673
674 lst rep_vs;
675 ex tree = mat;
676 for(const_preorder_iterator i = tree.preorder_begin(); i != tree.preorder_end(); ++i) {
677 auto e = (*i);
678 if(is_a<symbol>(e) || e.match(a(w))) rep_vs.append(e);
679 }
680 rep_vs.sort();
681 rep_vs.unique();
682 sort_lst(rep_vs);
683
684 exmap v2f;
685 symtab st;
686 int fvi = 0;
687 for(auto vi : rep_vs) {
688 auto name = "v" + to_string(fvi);
689 v2f[vi] = Symbol(name);
690 st[name] = vi;
691 fvi++;
692 }
693
694 stringstream ss;
695 if(fvi>111) {
696 cout << rep_vs << endl;
697 throw Error("Fermat: Too many variables.");
698 }
699 if(fvi>v_max) {
700 for(int i=v_max; i<fvi; i++) ss << "&(J=v" << i << ");" << endl;
701 fermat.Execute(ss.str());
702 ss.clear();
703 ss.str("");
704 v_max = fvi;
705 }
706
707 int nrow = mat.rows();
708 int ncol = mat.cols();
709
710 ss << "Array m[" << nrow << "," << ncol << "];" << endl;
711 fermat.Execute(ss.str());
712 ss.clear();
713 ss.str("");
714
715 ss << "[m]:=[(";
716 for(int c=0; c<ncol; c++) {
717 for(int r=0; r<nrow; r++) {
718 ss << mat(r,c).subs(iEpsilon==0,nopat).subs(v2f,nopat) << ",";
719 }
720 }
721 ss << ")];" << endl;
722 ss << "Redrowech([m]);" << endl;
723 auto tmp = ss.str();
724 string_replace_all(tmp,",)]",")]");
725 fermat.Execute(tmp);
726 ss.clear();
727 ss.str("");
728
729 ss << "&(U=1);" << endl; // ugly printing, the whitespace matters
730 ss << "![m" << endl;
731 auto ostr = fermat.Execute(ss.str());
732 ss.clear();
733 ss.str("");
734 //fermat.Exit();
735
736 // note the order, before exfactor (normal_fermat will be called again here)
737 ss << "&(U=0);" << endl; // disable ugly printing
738 ss << "@([m]);" << endl;
739 ss << "&_G;" << endl;
740 fermat.Execute(ss.str());
741 ss.clear();
742 ss.str("");
743
744 // make sure last char is 0
745 if(ostr[ostr.length()-1]!='0') throw Error("Direc::Export, last char is NOT 0.");
746 ostr = ostr.substr(0, ostr.length()-1);
747 string_trim(ostr);
748
749 ostr.erase(0, ostr.find(":=")+2);
750 string_replace_all(ostr, "[", "{");
751 string_replace_all(ostr, "]", "}");
752 Parser fp(st);
753 matrix mr(nrow, ncol);
754 auto res = fp.Read(ostr);
755 for(int r=0; r<nrow; r++) {
756 auto cur = res.op(r);
757 for(int c=0; c<ncol; c++) mr(r,c) = cur.op(c);
758 }
759 return mr;
760 }
761
762 bool IBP::IsZero(ex sector) {
763 auto props = Propagator;
764 lst xs;
765 int nxi=0;
766 int nps = props.nops();
767 ex ft = 0;
768 for(int i=0; i<nps; i++) {
769 if(is_zero(sector.op(i))) continue;
770 xs.append(x(nxi));
771 ft -= x(nxi) * props.op(i);
772 nxi++;
773 }
774
775 ex ut = 1;
776 ft = normal_flint(ft);
777 ft = subs(ft, Replacement);
778 for(int i=0; i<Internal.nops(); i++) {
779 auto t2 = ft.coeff(Internal.op(i),2);
780 auto t1 = ft.coeff(Internal.op(i),1);
781 auto t0 = ft.subs(Internal.op(i)==0,nopat);
782 ut *= t2;
783 if(is_zero(t2)) return true;
784 ft = normal_flint(t0-t1*t1/(4*t2));
785 //ft = expand(ft);
786 ft = subs(ft, Replacement);
787 }
788 ut = normal_flint(subs(ut, Replacement));
789 ft = normal_flint(ut*ft);
790 ft = normal_flint(subs(ft, Replacement));
791
792 ex G = ut + ft;
793 ex sum = 0;
794 lst ks;
795 exmap ks20;
796 for(auto xi : xs) {
797 symbol ki;
798 ks.append(ki);
799 ks20[ki] = 0;
800 sum += ki * xi * diff_ex(G,xi);
801 }
802 sum -= G;
803 auto cvs = collect_lst(sum,x(w));
804 int rn = cvs.nops();
805 int cn = ks.nops();
806 matrix mat(rn,cn+1);
807 int ri = 0;
808 for(auto cv : cvs) {
809 int ci = 0;
810 for(auto ki : ks) {
811 mat(ri,ci) = cv.op(0).coeff(ki);
812 ci++;
813 }
814 mat(ri,cn) = cv.op(0).subs(ks20,nopat);
815 ri++;
816 }
817 auto mat2 = Redrowech(mat);
818 for(int ri=rn-1; ri>=0; ri--) {
819 for(int ci=0; ci<cn; ci++) {
820 if(!is_zero(mat2(ri,ci))) return true;
821 }
822 if(!is_zero(mat2(ri,cn))) return false;
823 }
824 return true;
825 }
826
827 exmap IBP::SP2Pn() { // sp -> {c0,c1,c2,...,cn} coefficient of each propagator, c0 is remaining constant
828 lst InExternal;
829 for(auto ii : Internal) InExternal.append(ii);
830 for(auto ii : External) InExternal.append(ii);
831
832 if(ISP.nops()<1) {
833 for(auto it : Internal) {
834 for(auto ii : InExternal) ISP.append(it*ii);
835 }
836 ISP.sort();
837 ISP.unique();
838 }
839
840 int pdim = Propagator.nops();
841 if(ISP.nops() > pdim) {
842 cout << "ISP = " << ISP << endl;
843 cout << "Propagator = " << Propagator << endl;
844 throw Error("IBP::SP2Pn: #(ISP) > #(Propagator).");
845 }
846
847 lst sp2s, s2sp, ss;
848 int _pic=0;
849 for(auto item : ISP) {
850 _pic++;
851 symbol si("sp"+to_string(_pic));
852 ss.append(si);
853 sp2s.append(w*item==w*si);
854 sp2s.append(item==si);
855 s2sp.append(si==item);
856 }
857
858 lst eqns;
859 for(int i=0; i<ISP.nops(); i++) { // note NOT pdim
860 auto eq = expand(Propagator.op(i)).subs(iEpsilon==0); // drop iEpsilon
861 eq = eq.subs(sp2s);
862 eq = eq.subs(Replacement);
863 if(eq.has(iWF(w))) throw Error("IBP::SP2Pn, iWF used in eq.");
864 eqns.append(eq == iWF(i));
865 }
866 auto s2p = lsolve(eqns, ss);
867 if(s2p.nops() != ISP.nops()) {
868 cout << ISP << endl << s2p << endl << eqns << endl;
869 throw Error("IBP::SP2Pn: lsolve failed.");
870 }
871
872 exmap smap;
873 for(auto r : s2p) {
874 ex k = r.op(0).subs(s2sp, nopat);
875 ex v = r.op(1);
876 ex chk = v.subs(iWF(w)==0);
877 lst res;
878 res.append(chk);
879 for(int i=0; i<ISP.nops(); i++) {
880 ex t = v.coeff(iWF(i));
881 res.append(t);
882 chk += t*iWF(i);
883 }
884 if(!normal(chk-v).is_zero()) throw Error("IBP::SP2Pn check failed.");
885 smap[k] = res;
886 }
887 return smap;
888 }
889
890 exmap IBP::Dinv(const lst & ns) {
891 lst InExternal;
892 for(auto ii : Internal) InExternal.append(ii);
893 for(auto ii : External) InExternal.append(ii);
894 auto & es = External;
895 int eN = es.nops();
896 int pN = Propagator.nops();
897 matrix G(eN, eN);
898 for(int r=0; r<eN; r++) for(int c=0; c<eN; c++) G(r,c) = (es.op(r)*es.op(c)).subs(Replacement);
899 matrix Gi = G.inverse(solve_algo::gauss);
900 // partial J/partial pi^2
901 exmap spmap;
902 auto sp2pn = SP2Pn();
903 for(int p1i=0; p1i<eN; p1i++) {
904 for(int p2i=p1i; p2i<eN; p2i++) {
905 ex p1 = es.op(p1i);
906 ex p2 = es.op(p2i);
907 ex pf = 1;
908 if(p1i==p2i) pf = 1/ex(2);
909 ex res = 0;
910 for(int pi=0; pi<pN; pi++) {
911 lst ns2 = ns;
912 ns2.let_op(pi) = ns.op(pi)+1;
913 ex dpi = -ns.op(pi)*diff_ex(Propagator.op(pi), p1);
914 for(int i=0; i<eN; i++) {
915 ex idpi = expand_ex(dpi*es.op(i)).subs(Replacement);
916 auto cvs = collect_lst(idpi, InExternal);
917 for(auto cv : cvs) {
918 if(is_zero(cv.op(1)-1)) res += cv.op(0)*pf*Gi(i,p2i)*F(ProblemNumber, ns2);
919 else {
920 auto f = sp2pn.find(cv.op(1));
921 if(f==sp2pn.end()) throw Error("IBP::DExt, Not found.");
922 auto cps = f->second;
923 res += cv.op(0)*pf*Gi(i,p2i)*cps.op(0)*F(ProblemNumber, ns2);
924 for(int j=1; j<pN+1; j++) {
925 if(is_zero(cps.op(j))) continue;
926 lst ns3 = ns2;
927 ns3.let_op(j-1) = ns2.op(j-1)-1;
928 res += cv.op(0)*pf*Gi(i,p2i)*cps.op(j)*F(ProblemNumber, ns3);
929 }
930 }
931 }
932 }
933 }
934 spmap[p1*p2] = collect_ex(res,F(w1,w2));
935 }}
936 return spmap;
937 }
938
939 ex IBP::D(const ex & x, const lst & ns) {
940 lst InExternal;
941 for(auto ii : Internal) InExternal.append(ii);
942 for(auto ii : External) InExternal.append(ii);
943 int pN = Propagator.nops();
944 auto sp2pn = SP2Pn();
945
946 ex res = 0;
947 for(int pi=0; pi<pN; pi++) { // Direct Diff for each Propagator
948 lst ns2 = ns;
949 ns2.let_op(pi) = ns.op(pi)+1;
950 ex Pi = Propagator.op(pi);
951 Pi = Pi.subs(Replacement);
952 ex dpi = -ns.op(pi)*diff_ex(Pi, x);
953 auto cvs = collect_lst(dpi, InExternal);
954 for(auto cv : cvs) {
955 if(is_zero(cv.op(1)-1)) res += cv.op(0)*F(ProblemNumber, ns2);
956 else {
957 auto f = sp2pn.find(cv.op(1));
958 if(f==sp2pn.end()) throw Error("IBP::DExt, Not found.");
959 auto cps = f->second;
960 res += cv.op(0)*cps.op(0)*F(ProblemNumber, ns2);
961 for(int j=1; j<pN+1; j++) {
962 if(is_zero(cps.op(j))) continue;
963 lst ns3 = ns2;
964 ns3.let_op(j-1) = ns2.op(j-1)-1;
965 res += cv.op(0)*cps.op(j)*F(ProblemNumber, ns3);
966 }
967 }
968 }
969 }
970
971 // InDirect Diff from external SP
972 auto dsp = Dinv(ns);
973 auto eN = External.nops();
974 for(int i=0; i<eN; i++) {
975 for(int j=i; j<eN; j++) {
976 ex sp = External.op(i) * External.op(j);
977 auto f = dsp.find(sp);
978 if(f==dsp.end()) throw Error("DESS::InitDE, sp NOT found.");
979 auto rsp = sp.subs(Replacement);
980 if(sp==rsp) throw Error("DESS::InitDE, sp==rsp, Replacement NOT work.");
981 res += f->second * diff_ex(rsp, x);
982 }}
983
984 return res;
985 }
986
987 void IBP::RM(bool keep_start_config) {
988 string spn = to_string(ProblemNumber);
989 if(!keep_start_config) {
990 file_remove(WorkingDir+"/"+spn+".start");
991 file_remove(WorkingDir+"/"+spn+".config");
992 }
993 file_remove(WorkingDir+"/"+spn+".intg");
994 file_remove(WorkingDir+"/"+spn+".tables");
995 }
996
997 void IBP::rm(const string & pat) {
998 string spn = to_string(ProblemNumber);
999 string fn = WorkingDir+"/"+spn+pat;
1000 if(file_exists(fn)) file_remove(fn);
1001 }
1002
1003
1004 ex GPolynomial(const IBP & ibp) {
1005
1006 auto props = ibp.Propagator;
1007 ex ut, ft, uf;
1008 lst key;
1009 lst xs;
1010 exmap x2ax;
1011 int nxi=0;
1012 int nps = props.nops();
1013 ft = 0;
1014 for(int i=0; i<nps; i++) {
1015 xs.append(x(nxi));
1016 ft -= x(nxi) * props.op(i); // only used when no cache item
1017 nxi++;
1018 }
1019
1020 ut = 1;
1021 ft = expand_ex(ft);
1022 ft = subs(ft, ibp.Replacement);
1023 for(int i=0; i<ibp.Internal.nops(); i++) {
1024 auto t2 = ft.coeff(ibp.Internal.op(i),2);
1025 auto t1 = ft.coeff(ibp.Internal.op(i),1);
1026 auto t0 = ft.subs(ibp.Internal.op(i)==0,nopat);
1027 ut *= t2;
1028 if(is_zero(t2)) return lst{0,0,1};
1029 ft = exnormal(t0-t1*t1/(4*t2));
1030 ft = expand_ex(ft);
1031 ft = subs(ft, ibp.Replacement);
1032 }
1033 ft = exnormal(ut*ft);
1034 ft = exnormal(subs(ft, ibp.Replacement));
1035 ut = exnormal(subs(ut, ibp.Replacement));
1036 uf = exnormal(ut+ft); // ut*ft, replay with ut+ft
1037
1038 uf = uf.subs(MapPreSP);
1039 return uf;
1040 }
1041
1042 void GPermutation(const ex & uf, const lst & xs) {
1043 auto expr = collect_ex(uf, xs);
1044 map<ex,vector<ex>,ex_is_less> pgrp;
1045
1046 if(true) { // only for polynomials
1047 auto cv_lst = collect_lst(expr, xs);
1048 exvector cvs;
1049 for(auto item : cv_lst) cvs.push_back(item);
1050 sort_vec(cvs); // first sort by coefficient
1051
1052 int nxi = xs.nops();
1053 bool first = true;
1054 lst xkey[nxi];
1055 lst subkey[nxi];
1056 ex clast;
1057 for(auto cv : cvs) {
1058 ex cc = cv.op(0);
1059 ex vv = cv.op(1);
1060 if(is_zero(cc)) continue;
1061 if(!first && !is_zero(cc-clast)) { // equal coefficient to the same key
1062 for(int i=0; i<nxi; i++) {
1063 sort_lst(subkey[i]);
1064 for(auto item : subkey[i]) xkey[i].append(item);
1065 subkey[i].remove_all();
1066 }
1067 }
1068 first = false;
1069 clast = cc;
1070 for(int i=0; i<nxi; i++) subkey[i].append(vv.degree(xs.op(i)));
1071 }
1072
1073 for(int i=0; i<nxi; i++) { // add last subkey
1074 sort_lst(subkey[i]); // need sort due to equal coefficient
1075 for(auto item : subkey[i]) xkey[i].append(item);
1076 subkey[i].remove_all();
1077 }
1078
1079 exvector key_xi;
1080 for(int i=0; i<nxi; i++) key_xi.push_back(lst{xkey[i], xs.op(i)});
1081 sort_vec(key_xi); // first sort by key
1082
1083 for(int i=0; i<nxi; i++) {
1084 auto xi = key_xi[i].op(1);
1085 auto xki = key_xi[i].op(0);
1086 pgrp[xki].push_back(xi);
1087 }
1088 }
1089
1090 // pgrp - needs to permuation explicitly
1091 long long npt = 1;
1092 for(auto pi : pgrp) {
1093 int nvi = pi.second.size();
1094 for(int i=1; i<=nvi; i++) npt *= i; // nvi!
1095 }
1096 for(long long np=0; np<npt; np++) {
1097 long long npc = np;
1098 exmap xmap_tmp;
1099 for(auto pi : pgrp) {
1100 auto vi = pi.second;
1101 int nvi = vi.size();
1102 if(nvi<2) continue;
1103 long long npti = 1;
1104 for(int i=1; i<=nvi; i++) npti *= i; // nvi!
1105 int ck = npc % npti; // kth permutation
1106 npc = npc / npti;
1107
1108 // https://stackoverflow.com/questions/1995328/are-there-any-better-methods-to-do-permutation-of-string
1109 auto vip = vi;
1110 int k = ck;
1111 for(int j=1; j<nvi; ++j) { // startoverflow: j starts from 1
1112 std::swap(vip[k%(j+1)], vip[j]);
1113 k=k/(j+1);
1114 }
1115
1116 for(int j=0; j<nvi; j++) if(vi[j]!=vip[j]) xmap_tmp[vi[j]] = vip[j];
1117 }
1118 if(xmap_tmp.size()>0) {
1119 ex expr_tmp = expr.subs(xmap_tmp,nopat);
1120 if(is_zero(expr-expr_tmp)) {
1121 auto xs_tmp = xs.subs(xmap_tmp,nopat);
1122 cout << xs_tmp << endl;
1123 }
1124 }
1125 }
1126
1127 }
1128
1129}
int * a
#define WHITE
Definition BASIC.h:87
#define RESET
Definition BASIC.h:79
IBP header file.
bool file_exists(const char *fn)
Definition Process.cpp:9
class used to wrap error message
Definition BASIC.h:242
IBP base class for IBP reduction.
Definition IBP.h:24
lst Internal
Definition IBP.h:27
lst MIntegral
Definition IBP.h:42
map< int, ex > Shift
Definition IBP.h:36
lst PIntegral
Definition IBP.h:40
lst ISP
Definition IBP.h:34
lst Replacement
Definition IBP.h:29
virtual void Export()
Definition IBP.h:46
void Reduce()
ex TO()
Definition IBP.cpp:60
lst DSP
Definition IBP.h:33
bool reCut
Definition IBP.h:37
lst Cut
Definition IBP.h:32
lst External
Definition IBP.h:28
lst Propagator
Definition IBP.h:30
bool IsAlwaysZero
Definition IBP.h:44
int ProblemNumber
Definition IBP.h:39
virtual void Import()
Definition IBP.h:48
void garExport(string garfn)
Definition IBP.cpp:28
string WorkingDir
Definition IBP.h:38
virtual void Run()
Definition IBP.h:47
lst Rules
Definition IBP.h:43
lst SECTOR
Definition IBP.h:35
class extended to GiNaC symbol class, represent a positive symbol
Definition BASIC.h:113
HepLib namespace.
Definition BASIC.cpp:17
ex expand_ex(ex const &expr_in, std::function< bool(const ex &)> has_func)
the expand like Mathematica
Definition BASIC.cpp:1188
bool ex_less(const ex &a, const ex &b)
Definition Sort.cpp:10
const iSymbol iEpsilon
ex sp(const ex &a, const ex &b)
translated the vector dot a.b to a*b, useful in SecDec
Definition Pair.cpp:237
void GPermutation(const ex &uf, const lst &xs)
Definition IBP.cpp:1042
ex GPolynomial(const IBP &ibp)
Definition IBP.cpp:1004
exmap MapPreSP
Definition Init.cpp:338
ex collect_ex(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica
Definition BASIC.cpp:1202
bool has_w(const ex &e)
Definition BASIC.cpp:2233
lst LoopUF(const IBP &ibp, const ex &idx)
UF function.
Definition IBP.cpp:318
pair< exmap, lst > FindRules(vector< IBP * > fs, bool mi, std::function< lst(const IBP &, const ex &)> uf)
Find Rules for Integral or Master Integral.
Definition IBP.cpp:574
lst UF(const ex &props, const ex &ns, const ex &loops, const ex &tloops, const ex &lsubs, const ex &tsubs)
UF function, from FIRE.m.
Definition IBP.cpp:428
bool using_cache
Definition Init.cpp:156
string now(bool use_date)
date/time string
Definition BASIC.cpp:525
ex w
Definition Init.cpp:93
const Symbol vs
exmap SortPermutation(const ex &in_expr, const lst &xs)
Sort for all permuations, and return xs w.r.t. 1st permutation.
Definition IBP.cpp:204
ex exnormal(const ex &expr, int opt)
normalize a expression
Definition BASIC.cpp:1916
ex normal_flint(const ex &expr, int opt=o_flint)
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_vec(exvector &ivec, bool less=true)
sort the list in less order, or the reverse
Definition Sort.cpp:54
ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand)
the differential like Mathematica
Definition BASIC.cpp:1063
int Verbose
Definition Init.cpp:142
void sort_lst(lst &ilst, bool less=true)
sort the list in less order, or the reverse
Definition Sort.cpp:79
bool file_remove(string fn)
Definition BASIC.h:285
void string_replace_all(string &str, const string &from, const string &to)
long long cache_limit
Definition Init.cpp:157
ex w1
Definition BASIC.h:499
unsigned nopat
Definition Init.cpp:91
exvector GiNaC_Parallel(int ntotal, std::function< ex(int)> f, const string &key)
GiNaC Parallel Evaluation using fork.
Definition BASIC.cpp:260
REGISTER_FUNCTION(GMat, do_not_evalf_params().print_func< FCFormat >(&GMat_fc_print).conjugate_func(mat_conj).set_return_type(return_types::commutative)) bool IsZero(const ex &e)
Definition Basic.cpp:1002
ex w2
Definition BASIC.h:499
void string_trim(string &str)
string PRE
Definition Init.cpp:143
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51