HepLib
Loading...
Searching...
No Matches
AsyMB.cpp
Go to the documentation of this file.
1
6#include "SD.h"
7#include <math.h>
8#include <cmath>
9
10namespace HepLib::SD {
11
17 int SecDec::PRank(matrix m) {
18 int nr = m.rows();
19 int nc = m.cols();
20 int pr = 0;
21 if(nr>1) {
22 matrix pr_mat(nr, nc);
23 for(int ic=0; ic<nc; ic++) {
24 for(int ir=0; ir<nr; ir++) {
25 pr_mat(ir,ic) = m(ir,ic)-m(0,ic);
26 }
27 }
28 pr = pr_mat.rank();
29 }
30 return pr;
31 }
32
39 ex SecDec::PExpand(ex xpol, bool delta) {
40 lst nlst;
41 ex pol = collect_common_factors(xpol.expand());
42 if(is_a<mul>(pol)) {
43 ex tmp = 1;
44 for(int i=0; i<pol.nops(); i++) {
45 if(is_a<numeric>(pol.op(i))) continue;
46 if(pol.op(i).match(x(w))) continue;
47 if(pol.op(i).match(pow(x(w1),w2))) continue;
48 if(pol.op(i).match(pow(y(w1),w2))) continue;
49 if(pol.op(i).match(pow(vs,w))) continue;
50 tmp *= pol.op(i);
51 }
52 pol = tmp;
53 }
54 pol = pol.expand();
55 auto xs = get_xy_from(pol);
56 int nx = xs.size();
57 int id = delta ? nx-1 : nx;
58
59 lst lxs;
60 for(auto item : xs) lxs.append(item);
61 lxs.append(vs);
62 pol = pol.expand().collect(lxs, true);
63 int np = is_a<add>(pol) ? pol.nops() : 1;
64 matrix rs_mat(np, nx+1);
65
66 for(int n=0; n<np; n++) {
67 ex tmp = pol.op(n);
68 rs_mat(n,0) = tmp.degree(vs);
69 for(int ix=0; ix<nx; ix++) {
70 rs_mat(n, ix+1) = collect_ex(tmp, xs[ix]).degree(xs[ix]);
71 }
72 }
73
74 int pr = PRank(rs_mat);
75 if(pr-1 != id) return nlst;
76
77 matrix rp_mat(np, id+1);
78 for(int n=0; n<np; n++) {
79 for(int ix=0; ix<id+1; ix++) {
80 rp_mat(n,ix) = rs_mat(n,ix);
81 }
82 }
83 int rp = PRank(rp_mat);
84
85 if(pr != rp) {
86 cout << "pr=" << pr << ", rp=" << rp << endl;
87 throw Error("PExpand: projection method does not work.");
88 }
89
90 auto fs = SecDecG::RunQHull(rp_mat);
91 lst vs, ret;
92 for(int i=0; i<id+1; i++) {
93 symbol v;
94 vs.append(v);
95 }
96 auto vv = vs.op(id);
97 for(auto fi : fs) {
98 lst eqns;
99 for(auto pi : fi) {
100 ex eqn = rs_mat(pi,0);
101 for(int i=0; i<id; i++) {
102 eqn += vs.op(i) * rs_mat(pi,i+1);
103 }
104 eqns.append(eqn==vv);
105 }
106 auto lss = lsolve(eqns, vs);
107 if(lss.nops()>1) {
108 bool bf = true;
109 auto vs2 = subs(vs,lss);
110 for(int r=0; r<np; r++) {
111 ex eqn = rs_mat(r,0);
112 for(int i=0; i<id; i++) {
113 eqn += vs2.op(i) * rs_mat(r,i+1);
114 }
115 ex chk = eqn-vs2.op(id);
116 if(!is_a<numeric>(chk)) {
117 cerr << ErrColor << "chk is NOT a number: " << chk << RESET << endl;
118 throw Error("PExpand: chk is NOT a number.");
119 }
120 if(chk<0) {
121 bf = false;
122 break;
123 }
124 }
125 if(bf) {
126 vs2.let_op(id) = 0;
127 ex min = vs2.op(0);
128 for(auto vsi : vs2) {
129 if(vsi<min) min = vsi;
130 }
131 for(int i=0; i<vs2.nops(); i++) vs2.let_op(i) = vs2.op(i)-min;
132 ret.append(vs2);
133 }
134 }
135 }
136
137 lst lxs2;
138 for(auto item : xs) lxs2.append(item);
139 ret.prepend(lxs2);
140 return ret;
141 }
142
146 void SecDec::DoAsy() {
147
148 while(true) {
149 exvector funexp;
150 for(auto fe : FunExp) {
151 funexp.push_back(fe);
152 }
153 FunExp.clear();
154 FunExp.shrink_to_fit();
155
156 bool ret = false;
157 for(auto fe : funexp) {
158 if(fe.nops()<=2) {
159 cerr << ErrColor << "needs 3 elements: " << fe << RESET << endl;
160 throw Error("DoAsy: we needs 3 elements.");
161 }
162 ex ft = fe.op(0).op(1).subs(vs==0);
163 ex eqn;
164 bool ok2 = true;
165 auto xs = get_x_from(ft);
166 for(int i=0; i<xs.size(); i++) { // keep only 2 xi's
167 for(int j=i+1; j<xs.size(); j++) { // keep only 2 xi's
168 bool delta_ij = false;
169 for(int di=0; di<fe.op(2).nops(); di++) {
170 if(fe.op(2).op(di).has(xs[i]) && fe.op(2).op(di).has(xs[j])) {
171 delta_ij = true;
172 break;
173 }
174 }
175 if(!delta_ij) continue;
176
177 symbol xi("xi"), xj("xj");
178 auto ftt = ft.subs(lst{xs[i]==xi, xs[j]==xj});
179 ftt = Factor(ftt);
180 lst fts2;
181 if(is_a<mul>(ftt)) {
182 for(auto item : ftt) fts2.append(item);
183 } else {
184 fts2.append(ftt);
185 }
186 lst tmp_lst;
187 for(auto item : fts2) {
188 auto tmp = Factor(item.subs(x(w)==0));
189 if(is_a<mul>(tmp)) {
190 for(auto it : tmp) tmp_lst.append(it);
191 } else {
192 tmp_lst.append(tmp);
193 }
194 }
195 fts2 = tmp_lst;
196
197 for(auto item : fts2) {
198 auto tmp = item;
199 if(item.match(pow(w1,w2))) tmp = item.op(0);
200 if(tmp.degree(xi)==1 && tmp.degree(xj)==1) {
201 ex ci = tmp.coeff(xi);
202 ex cj = tmp.coeff(xj);
203 if((ci*xi+cj*xj-tmp).is_zero() && is_a<numeric>(ci*cj) && (ci*cj)<0) {
204 eqn = tmp.subs(lst{xi==xs[i], xj==xs[j]});
205 ok2 = false;
206 goto OK2;
207 }
208 }
209 }
210 }
211 }
212
213 OK2:
214 if(!ok2) {
215 auto xij = get_x_from(eqn);
216 ex xi = xij[0];
217 ex xj = xij[1];
218
219 ex ci = eqn.coeff(xi);
220 ex cj = eqn.coeff(xj);
221
222 // handle eqn==ci xi - cj xj
223 ret = true;
224 ci = abs(ci);
225 cj = abs(cj);
226 symbol yi,yj;
227 // Part I: ci xi-cj xj>0, i.e., xi>cj/ci xj
228 auto f1 = ex_to<lst>(fe.op(0));
229 auto e1 = ex_to<lst>(fe.op(1));
230 ex c1 = cj/ci;
231 for(int i=0; i<f1.nops(); i++) {
232 f1.let_op(i) = f1.op(i).subs(lst{xi==c1*yj/(1+c1)+yi,xj==yj/(1+c1)}).subs(lst{yi==xi,yj==xj});
233 }
234 if(e1.op(0)==1) f1.let_op(0) = f1.op(0)/(1+c1); // Jaccobi
235 else if(e1.op(1)==1) f1.let_op(1) = f1.op(1)/(1+c1);
236 else {
237 f1.append(1/(1+c1));
238 e1.append(1);
239 }
240
241 FunExp.push_back(lst{f1,e1,fe.op(2)});
242 // Part II: ci xi-cj xj<0, i.e., i.e., xj>ci/cj xi
243 auto f2 = ex_to<lst>(fe.op(0));
244 auto e2 = ex_to<lst>(fe.op(1));
245 ex c2 = ci/cj;
246 for(int i=0; i<f2.nops(); i++) {
247 f2.let_op(i) = f2.op(i).subs(lst{xj==c2*yi/(1+c2)+yj,xi==yi/(1+c2)}).subs(lst{yi==xi,yj==xj});
248 }
249 if(e2.op(0)==1) f2.let_op(0) = f2.op(0)/(1+c2); // Jaccobi
250 else if(e2.op(1)==1) f2.let_op(1) = f2.op(1)/(1+c2);
251 else {
252 f2.append(1/(1+c2));
253 e2.append(1);
254 }
255 FunExp.push_back(lst{f2,e2,fe.op(2)});
256 } else {
257 FunExp.push_back(fe);
258 }
259 }
260 if(!ret) break;
261 }
262
263
264 for(auto fe : FunExp) {
265 ex expn = 0;
266 symbol s;
267 for(int i=0; i<fe.op(0).nops(); i++) {
268 auto item = fe.op(0).op(i).subs(x(w)==s*y(w)).subs(y(w)==x(w));
269 if(!item.has(s)) continue;
270 item = collect_ex(item, s);
271 if(item.ldegree(s)!=item.degree(s)) {
272 cerr << ErrColor << "Not Homogeneous: " << s << RESET << endl;
273 throw Error("DoAsy: Not Homogeneous");
274 }
275 expn += item.degree(s) * fe.op(1).op(i);
276 }
277 auto xsize = get_x_from(fe.op(0)).size();
278 if(!normal(expn+xsize).is_zero()) {
279 cout << ErrColor << "expn=" << expn << ", xsize=" << xsize << RESET << endl;
280 throw Error("DoAsy: expn + xsize != 0.");
281 }
282 }
283
284
285 auto fes = FunExp;
286 FunExp.clear();
287 FunExp.shrink_to_fit();
288
289 for(auto fe : fes) {
290 ex xpol = 1;
291 lst uf;
292 for(int i=0; i<fe.op(0).nops(); i++) {
293 if(fe.op(1).op(i).info(info_flags::nonnegint)) continue;
294 uf.append(fe.op(0).op(i));
295 }
296 uf.sort();
297 uf.unique();
298 //sort_lst(uf);
299 for(auto item : uf) xpol *= item;
300 if(!xpol.has(vs)) {
301 FunExp.push_back(fe);
302 continue;
303 }
304
305 bool has_delta = true;
306 auto rs = PExpand(xpol, has_delta);
307 if(rs.nops()<1) {
308 throw Error("PExpand returned with nothing, even without hard region!");
309 }
310 if(Verbose>10) {
311 cout << PRE << "\\--Asy Regions:" << (rs.nops()-1) << endl;
312 if(rs.nops()>1) {
313 for(auto ri : rs) cout << " " << ri << endl;
314 }
315 }
316
317 auto r0 = rs.op(0);
318 auto r0y = subs(r0,x(w)==y(w));
319 for(int i=1; i<rs.nops(); i++) {
320 lst srepl;
321 auto ri = rs.op(i);
322 ex vs_pow = 0;
323 for(int j=0; j<r0.nops(); j++) {
324 srepl.append(r0.op(j)==r0y.op(j) * pow(vs, ri.op(j)));
325 vs_pow += ri.op(j);
326 }
327
328 auto fs = subs(fe.op(0), srepl);
329 fs = subs(fs, y(w)==x(w));
330 auto es = fe.op(1);
331 ex fpre = fs.op(0);
332 if(!(es.op(0)-1).is_zero()) {
333 cerr << ErrColor << "op(0) is Not 1: " << es << RESET << endl;
334 throw Error("DoAsy: op(0) is Not 1");
335 }
336
337 lst fs2, es2;
338 for(int j=1; j<fs.nops(); j++) {
339 auto fj = fs.op(j);
340 auto tmp = fj.expand();
341 auto vsp = 0;
342 try {
343 vsp = tmp.ldegree(vs);
344 } catch(exception &e) {
345 cout << e.what() << endl;
346 throw Error("DoAsy: non-integer exponent.");
347 }
348 vs_pow += vsp * es.op(j);
349 tmp = collect_common_factors(tmp)/pow(vs,vsp);
350 fs2.append(tmp);
351 es2.append(es.op(j));
352 }
353 exmap eps_map;
354 for(auto epi : eps_lst) eps_map[epi.op(0)] = 0;
355
356 auto vsn0 = vsRank(fpre); // maybe need to expand ep/eps first
357 auto vsn = vsn0 + vs_pow.subs(eps_map);
358 int di=0;
359 lst fss, ess;
360 fss.append(fs2);
361 ess.append(es2);
362 while(di<=vsN-vsn) { // fss, ess will get updated
363 lst fss2, ess2;
364 for(int ife=0; ife<fss.nops(); ife++) {
365 lst fs3 = ex_to<lst>(fss.op(ife));
366 lst es3 = ex_to<lst>(ess.op(ife));
367 if(di<vsN-vsn) {
368 for(int ii=0; ii<fs3.nops(); ii++) {
369 lst fs4 = fs3;
370 lst es4 = es3;
371 auto dit = diff_ex(fs4.op(ii),vs);
372 if(!dit.is_zero()) {
373 if((es4.op(ii)-1).is_zero()) {
374 fs4.let_op(ii) = dit;
375 } else {
376 fs4.append(es4.op(ii)*dit);
377 es4.let_op(ii) = es4.op(ii)-1;
378 es4.append(1);
379 }
380 fss2.append(fs4);
381 ess2.append(es4);
382 }
383 }
384 }
385 fs3 = ex_to<lst>(subs(fs3,vs==0));
386 fs3.prepend(fpre/factorial(di) * pow(vs,di+vs_pow));
387 es3.prepend(1);
388 FunExp.push_back(lst{fs3,es3,fe.op(2)});
389 }
390 fss = fss2;
391 ess = ess2;
392 di++;
393 }
394 }
395 }
396 }
397
401 void SecDec::MB() {
402 for(auto &fe : FunExp) {
403 if(fe.has(vz) || !fe.has(vs)) continue; // 2nd entrance
404
405 // check epz
406 if(fe.has(epz)) {
407 cout << ErrColor << "MB: epz found at fe = " << fe << RESET << endl;
408 throw Error("MB: epz found at fe.");
409 }
410
411 exmap eps_map;
412 ex epn = ex(1)/111;
413 for(auto epi : eps_lst) {
414 eps_map[epi.op(0)] = epn;
415 epn = epn / 13;
416 }
417
418 // check variables besides x or PL
419 // CV should only appear at kv.op(0).op(0), i.e., the prefactor
420 for(int i=2; i<fe.op(0).nops(); i++) {
421 // make sure only Constant/F terms can contain small variable: vs
422 if(i!=1 && fe.op(0).op(i).has(vz)) {
423 cout << "vz Found @ " << i << " of " << fe.op(0) << endl;
424 throw Error("MB: vz Found.");
425 }
426
427 auto tmp = fe.op(0).op(i).subs(lst{WRA(w)==0,x(w)==1,PL(w)==1}).subs(eps_map);
428 if(!is_a<numeric>(NN(tmp,20))) {
429 cout << ErrColor << tmp << RESET << endl;
430 cout << fe.op(0) << endl;
431 throw Error("MB: Extra Variable(^[ep,eps,PL,x]) Found.");
432 }
433 }
434
435 ex ft = fe.op(0).op(1);
436 if(ft.has(vs)) {
437 ft = collect_ex(ft, vs);
438 if(!ft.is_polynomial(vs) || (ft.degree(vs)-1)!=0) {
439 cout << ErrColor << "Not supported F-term with s: " << ft << RESET << endl;
440 throw Error("MB: Not supported F-term with s.");
441 }
442 ex expn = ex(0)-fe.op(1).op(1);
443 // (2*Pi*I) dropped out, since we will take residue later.
444 fe.let_op(0).let_op(0) = fe.op(0).op(0) * tgamma(expn+vz)*tgamma(ex(0)-vz)/tgamma(expn)*pow(vs,vz);
445 ex w1 = ft.coeff(vs);
446 ex w2 = ft.subs(vs==0);
447 if(!w2.is_zero()) {
448 if(xPositive(w1)) {
449 let_op_append(fe, 0, w1);
450 let_op_append(fe, 1, vz);
451 fe.let_op(0).let_op(1) = w2;
452 fe.let_op(1).let_op(1) = fe.op(1).op(1)-vz-epz;
453 } else if(xPositive(w2)) {
454 let_op_append(fe, 0, w2);
455 let_op_append(fe, 1, fe.op(1).op(1)-vz-epz);
456 fe.let_op(0).let_op(1) = w1;
457 fe.let_op(1).let_op(1) = vz;
458 } else if(xPositive(ex(0)-w1)) {
459 let_op_append(fe, 0, ex(0)-w1);
460 let_op_append(fe, 1, vz);
461 let_op_append(fe, 0, exp(-I*Pi*vz));
462 let_op_append(fe, 1, 1);
463 fe.let_op(0).let_op(1) = w2;
464 fe.let_op(1).let_op(1) = fe.op(1).op(1)-vz-epz;
465 } else if(xPositive(ex(0)-w2)) {
466 let_op_append(fe, 0, ex(0)-w2);
467 let_op_append(fe, 1, fe.op(1).op(1)-vz-epz);
468 let_op_append(fe, 0, exp(-I*Pi*(fe.op(1).op(1)-vz-epz)));
469 let_op_append(fe, 1, 1);
470 fe.let_op(0).let_op(1) = w1;
471 fe.let_op(1).let_op(1) = vz;
472 } else {
473 cout << "w1=" << w1 << endl;
474 cout << "w2=" << w2 << endl;
475 throw Error("MB: Neither w1 nor w2 is xPositive.");
476 }
477 }
478 }
479 }
480 }
481
482
483}
#define RESET
Definition BASIC.h:79
SecDec header file.
class used to wrap error message
Definition BASIC.h:242
static vector< vector< int > > RunQHull(const matrix &pts)
Definition SecDecG.cpp:176
static ex PExpand(ex xpol, bool delta=true)
PExpand from asy2.1.1.m.
Definition AsyMB.cpp:39
static int PRank(matrix m)
PRank from FIESTA.
Definition AsyMB.cpp:17
exvector FunExp
Definition SD.h:426
namespace for Numerical integration with Sector Decomposition method
Definition AsyMB.cpp:10
exvector get_xy_from(ex pol)
Definition Helpers.cpp:14
int vsRank(ex expr_in)
Definition Helpers.cpp:211
exvector get_x_from(ex pol)
Definition Helpers.cpp:29
ex Factor(const ex expr_in)
Definition Helpers.cpp:244
bool xPositive(ex const expr)
check the expr is xPositive, i.e., each x-monomial item is postive
Definition BASIC.cpp:1290
ex NN(ex expr, int digits)
the nuerical evaluation
Definition BASIC.cpp:1278
const char * ErrColor
Definition BASIC.cpp:246
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
ex w
Definition Init.cpp:93
const Symbol vs
const Symbol epz
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 let_op_append(ex &ex_in, const ex item)
append item into expression
Definition BASIC.cpp:1324
ex w1
Definition BASIC.h:499
ex w2
Definition BASIC.h:499
const Symbol vz
string PRE
Definition Init.cpp:143
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51