HepLib
Loading...
Searching...
No Matches
ChengWu.cpp
Go to the documentation of this file.
1
6#include "SD.h"
7#include <cmath>
8
9namespace HepLib::SD {
10
14 void SecDec::ChengWu(const ex & ft) {
15
16 if(is_a<lst>(ft) && ft.nops()>1) {
17 for(auto item : ft) {
18 for(auto &fe : FunExp) {
19 let_op_prepend(fe, 0, item);
20 let_op_prepend(fe, 1, 0);
21 }
22 }
23
24 int nt = ft.nops();
25 for(int i=0; i<nt; i++) {
26 auto FunExp2 = FunExp;
27 FunExp.clear();
28 FunExp.shrink_to_fit();
29 for(auto fe : FunExp2) {
30 auto ft2 = fe.op(0).op(0);
31 if(!fe.op(1).op(0).is_equal(0)) throw Error("SecDec::ChengWu exponent is NOT 0.");
34 auto fes = ChengWu::Apply(fe, ft2);
35 for(auto fe2 : fes) {
36 let_op_remove_first(fe2, 0);
37 let_op_remove_first(fe2, 1);
38 FunExp.push_back(fe2);
39 }
40 }
41 }
42 } else {
43 if(is_a<lst>(ft)) FunExp = ChengWu::Apply(FunExp, ft.op(0));
44 else FunExp = ChengWu::Apply(FunExp, ft);
45 //remove the first item in op(0) and op(1)
46 for(auto &fe : FunExp) {
49 }
50 }
51 }
52
61 exvector ChengWu::Apply(const exvector & fe_vec, const ex & ft) {
62 exvector ret_fe_vec;
63 for(auto fe : fe_vec) {
64 ex cft = ft;
65 if(is_zero(cft)) {
66 if(fe.op(0).nops()>1) cft = fe.op(0).op(1);
67 else cft = 1;
68 }
69 if(fe.nops()<3 || xSign(cft)!=0 || cft.has(WRA(w))) {
70 let_op_prepend(fe, 0, 1);
71 let_op_prepend(fe, 1, 0);
72 ret_fe_vec.push_back(fe);
73 continue;
74 }
75 auto deltas = fe.op(2);
76 for(int di=0; di<deltas.nops(); di++) {
77 Projectivize(fe, deltas.op(di)); // make sure projective
78 }
79 if(is_zero(ft)) cft = fe.op(0).op(1); // due to projective
80 let_op_prepend(fe, 0, cft);
81 let_op_prepend(fe, 1, 0);
82 auto ret = Evaluate(fe);
83 for(auto item : ret) ret_fe_vec.push_back(item);
84 }
85
86 return exvector(std::move(ret_fe_vec));
87 }
88
95 bool ChengWu::isProjective(const ex fe, const ex delta) {
96 static symbol s;
97 lst sRepl;
98 for(int j=0; j<delta.nops(); j++) sRepl.append(delta.op(j)==delta.op(j)*s);
99 ex over_all_sn = 0;
100 int nnn = fe.op(0).nops();
101 for(int i=0; i<nnn; i++) {
102 auto func = fe.op(0).op(i);
103 if(!func.has(x(w))) continue;
104 func = expand_ex(func.subs(sRepl),s);
105 auto sn = func.degree(s);
106 if(sn!=func.ldegree(s)) return false;
107 over_all_sn += sn*fe.op(1).op(i);
108 }
109 over_all_sn = normal(over_all_sn+delta.nops());
110 return over_all_sn.is_zero();
111 }
112
119 void ChengWu::Projectivize(ex &fe, const ex delta, const ex xsum_in) {
120 static symbol s;
121 lst sRepl;
122 for(int j=0; j<delta.nops(); j++) sRepl.append(delta.op(j)==delta.op(j)*s);
123 ex xsum = xsum_in;
124 if(xsum.is_zero()) {
125 for(auto xi : delta) xsum += xi;
126 }
127
128 ex over_all_sn = 0;
129 int nnn = fe.op(0).nops();
130 for(int i=0; i<nnn; i++) {
131 auto func = fe.op(0).op(i);
132 if(!func.has(x(w))) continue;
133 func = expand_ex(func.subs(sRepl),s);
134 auto sn = func.degree(s);
135 over_all_sn += sn*fe.op(1).op(i);
136 if(!is_a<add>(func)) func = lst{func};
137 ex tmp = 0;
138 for(auto ii : func) {
139 auto sni = ii.degree(s);
140 if(sni!=sn) tmp += ii.subs(s==1) * pow(xsum, sn-sni);
141 else tmp += ii.subs(s==1);
142 }
143 fe.let_op(0).let_op(i) = tmp;
144 }
145
146 over_all_sn = normal(over_all_sn+delta.nops());
147 if(!over_all_sn.is_zero()) {
148 let_op_append(fe, 0, xsum);
149 let_op_append(fe, 1, ex(0)-over_all_sn);
150 }
151 }
152
159 void ChengWu::Scalelize(ex &fe, const ex xi, const ex cy) {
160 if(is_a<lst>(xi)) Scalelize(fe, ex_to<lst>(xi), cy);
161 else Scalelize(fe, lst{xi}, cy);
162 }
163
170 void ChengWu::Scalelize(ex &fe, const lst xs, const ex cy) {
171 lst x2y, y2x;
172 for(auto xi : xs) {
173 if(cy.has(xi)) {
174 throw Error("Scalelize: cy has xi: " + ex2str(cy) + "/" + ex2str(xi));
175 }
176 auto yi = xi.subs(x(w)==y(w));
177 x2y.append(xi==cy*yi);
178 y2x.append(yi==xi);
179 }
180 auto nnn = fe.op(0).nops();
181 for(int i=0; i<nnn; i++) {
182 if(!fe.op(0).op(i).has(x(w))) continue;
183 auto tmp = fe.op(0).op(i).subs(x2y).subs(y2x);
184 tmp = exfactor(tmp);
185 tmp = numer_denom(tmp);
186 if(tmp.op(1).subs(x(w)==1)<0) {
187 tmp.let_op(0) = ex(0)-tmp.op(0);
188 tmp.let_op(1) = ex(0)-tmp.op(1);
189 }
190 fe.let_op(0).let_op(i) = tmp.op(0);
191 if(tmp.op(1)!=1) {
192 let_op_append(fe, 0, tmp.op(1));
193 let_op_append(fe, 1, ex(0)-fe.op(1).op(i));
194 }
195 }
196
197 ex det = exfactor(cy);
198 det = numer_denom(det);
199 if(det.op(1).subs(x(w)==1)<0) {
200 det.let_op(0) = ex(0)-det.op(0);
201 det.let_op(1) = ex(0)-det.op(1);
202 }
203 auto xn = xs.nops();
204 if(det.op(0)!=1) {
205 let_op_append(fe, 0, det.op(0));
206 let_op_append(fe, 1, xn);
207 }
208 if(det.op(1)!=1) {
209 let_op_append(fe, 0, det.op(1));
210 let_op_append(fe, 1, ex(0)-xn);
211 }
212 }
213
220 exvector ChengWu::Binarize(ex const fe, ex const eqn) {
221 exvector ovec;
222 Binarize(fe, eqn, ovec);
223 return exvector(std::move(ovec));
224 }
225
232 void ChengWu::Binarize(ex const fe, ex const eqn, exvector & ovec) {
233 auto xij = get_x_from(eqn);
234 if(xij.size()!=2) {
235 throw Error("Binarize: xij.size()!=2, " + ex2str(xij));
236 }
237 ex xi = xij[0];
238 ex xj = xij[1];
239 ex ci = eqn.coeff(xi);
240 ex cj = eqn.coeff(xj);
241 if(!((ci*xi+cj*xj-eqn).is_zero() && is_a<numeric>(ci * cj) && (ci*cj)<0)) {
242 throw Error("Binarize: ((ci*xi+cj*xj-eqn).is_zero() && is_a<numeric>(ci * cj) && (ci*cj)<0)");
243 }
244
245 bool pos1 = (ci>0);
246
247 ci = abs(ci);
248 cj = abs(cj);
249 symbol yi,yj;
250 // Part I: ci xi-cj xj>0, i.e., xi>cj/ci xj
251 auto f1 = ex_to<lst>(fe.op(0));
252 auto e1 = ex_to<lst>(fe.op(1));
253 ex c1 = cj/ci;
254 for(int i=0; i<f1.nops(); i++) {
255 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});
256 }
257 if(e1.op(0)==1) f1.let_op(0) = f1.op(0)/(1+c1); // Jaccobi
258 else if(e1.op(1)==1) f1.let_op(1) = f1.op(1)/(1+c1);
259 else {
260 f1.append(1/(1+c1));
261 e1.append(1);
262 }
263 auto fe1 = fe;
264 fe1.let_op(0) = f1;
265 fe1.let_op(1) = e1;
266
267 // Part II: ci xi-cj xj<0, i.e., i.e., xj>ci/cj xi
268 auto f2 = ex_to<lst>(fe.op(0));
269 auto e2 = ex_to<lst>(fe.op(1));
270 ex c2 = ci/cj;
271 for(int i=0; i<f2.nops(); i++) {
272 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});
273 }
274 if(e2.op(0)==1) f2.let_op(0) = f2.op(0)/(1+c2); // Jaccobi
275 else if(e2.op(1)==1) f2.let_op(1) = f2.op(1)/(1+c2);
276 else {
277 f2.append(1/(1+c2));
278 e2.append(1);
279 }
280 auto fe2 = fe;
281 fe2.let_op(0) = f2;
282 fe2.let_op(1) = e2;
283
284 // return vector
285 if(pos1) {
286 ovec.push_back(fe1);
287 ovec.push_back(fe2);
288 } else {
289 ovec.push_back(fe2);
290 ovec.push_back(fe1);
291 }
292 }
293
301 bool ChengWu::isLinearizable(const ex ft, const ex delta, lst & xcs) {
302 for(auto xi : delta) {
303 ex f = ft;
304 if(!f.has(xi) || f.degree(xi)!=1) continue;
305 auto cxi = f.coeff(xi);
306 f = f.subs(xi==0);
307 int cxi_sgn = xSign(cxi);
308
309 if(cxi_sgn!=0) {
310 if(cxi_sgn<0) cxi = ex(0)-cxi;
311 lst ret;
312 if(is_zero(f) || isLinearizable(f, delta, ret)) {
313 for(auto xc : ret) xcs.append(xc);
314 xcs.append(lst{xi, cxi});
315 return true;
316 }
317 }
318 }
319 return false;
320 }
321
328 void ChengWu::Linearize(const lst xcs_in, ex & fe, ex & ft) {
329 lst xcs = xcs_in;
330 ex inv_det = 1;
331 auto nnn = xcs.nops();
332 for(int i=0; i<nnn; i++) {
333 auto xi = xcs.op(i).op(0);
334 auto s = xcs.op(i).op(1);
335 auto yi = xi.subs(x(w)==y(w));
336 inv_det *= s;
337 xcs.let_op(i).let_op(1) = yi/s;
338 for(int j=i+1; j<nnn; j++) {
339 xcs.let_op(j) = xcs.op(j).subs(xi==yi/s);
340 }
341 }
342 exmap x2y;
343 for(auto ss : xcs) x2y[ss.op(0)]=ss.op(1);
344
345 // rescaling ft
346 if(ft.has(x(w))) ft = ft.subs(x2y).subs(y(w)==x(w));
347
348 // rescaling each item
349 nnn = fe.op(0).nops();
350 for(int i=0; i<nnn; i++) {
351 if(!fe.op(0).op(i).has(x(w))) continue;
352 auto tmp = fe.op(0).op(i).subs(x2y);
353 tmp = tmp.subs(y(w)==x(w));
354 auto num_den = numer_denom(tmp);
355 if(num_den.op(1).subs(x(w)==1)<0) {
356 num_den.let_op(0) = ex(0)-num_den.op(0);
357 num_den.let_op(1) = ex(0)-num_den.op(1);
358 }
359 fe.let_op(0).let_op(i) = num_den.op(0);
360 if(num_den.op(1)!=1) {
361 let_op_append(fe, 0, num_den.op(1));
362 let_op_append(fe, 1, ex(0)-fe.op(1).op(i));
363 }
364 }
365
366 // determinant
367 inv_det = inv_det.subs(y(w)==x(w));
368 auto idet_num_den = numer_denom(inv_det);
369 if(idet_num_den.op(1).subs(x(w)==1)<0) {
370 idet_num_den.let_op(0) = ex(0)-idet_num_den.op(0);
371 idet_num_den.let_op(1) = ex(0)-idet_num_den.op(1);
372 }
373 if(idet_num_den.op(0)!=1) {
374 let_op_append(fe, 0, idet_num_den.op(0));
375 let_op_append(fe, 1, -1);
376 }
377 if(idet_num_den.op(1)!=1) {
378 let_op_append(fe, 0, idet_num_den.op(1));
379 let_op_append(fe, 1, 1);
380 }
381 }
382
397 bool ChengWu::isPartilizable(const ex ft, const ex delta, lst &xcs, int mode) {
398 for(auto xi : delta) {
399 if(!ft.has(xi) || ft.degree(xi)!=1) continue;
400
401 auto cxi = ft.coeff(xi);
402 int cxi_sgn = xSign(cxi);
403 auto re_ft = ft.subs(xi==0);
404
405 if(cxi_sgn!=0) {
406 if(cxi_sgn<0) cxi = ex(0)-cxi;
407
408 lst ret;
409 ret.append(lst{xi, cxi});
410 if(is_zero(re_ft) || isPartilizable(re_ft, delta, ret, mode)) { // mode=0
411 for(int i=0; i<ret.nops(); i++) xcs.append(ret.op(i));
412 return true;
413 }
414
415 if((mode>0) && (xSign(re_ft)!=0)) { // mode=1: x_i P_i + G_0, with P_i and G_0 same-sign
416 xcs.append(lst{xi, cxi});
417 if(re_ft.subs(x(w)==1)<0) re_ft = ex(0)-re_ft;
418 xcs.append(lst{0, re_ft});
419 return true;
420 } else if(mode>1) { // mode=2: x_i P_i + G_0, with P-i same-sign, G_0 ~ (xm-xn)^n
421 auto fflst = SecDec::XRefined_lst(re_ft);
422 if(fflst.nops()==1) {
423 symbol s;
424 auto ff = fflst.op(0).subs(x(w)==s*x(w));
425 if(get_x_from(ff).size()==2 && ff.degree(s)==1 && ff.ldegree(s)==1) {
426 xcs.append(lst{xi, cxi});
427 xcs.append(lst{0, fflst.op(0)});
428 return true;
429 }
430 }
431 }
432 } else if(mode>2) {
433 lst bilst;
434 auto cclst = SecDec::XRefined_lst(cxi);
435 if(cclst.nops()==1) {
436 symbol s;
437 auto cc = cclst.op(0).subs(x(w)==s*x(w));
438 if(get_x_from(cc).size()==2 && cc.degree(s)==1 && cc.ldegree(s)==1) {
439 bilst.append(lst{0, cclst.op(0)});
440 }
441 } else continue;
442 if(bilst.nops()!=1) continue;
443
444 if(mode==3 && xSign(re_ft)!=0) {
445 // mode=3: x_i P_i + x_0 G_0 + Q_0, with P-i same-sign, G_0 ~ (xm-xn)^n & Q_0 same-sign
446 xcs.append(bilst.op(0));
447 return true;
448 }
449
450 if(mode==4) {
451 // mode=4: x_i P_i + x_0 G_0 + Q_0, with P-i same-sign, G_0~(xm-xn)^n & Q_0~(xm'-xn')^n'
452 auto fflst = SecDec::XRefined_lst(re_ft);
453 if(fflst.nops()==1) {
454 symbol s;
455 auto ff = fflst.op(0).subs(x(w)==s*x(w));
456 if(get_x_from(ff).size()==2 && ff.degree(s)==1 && ff.ldegree(s)==1) {
457 bilst.append(lst{0, fflst.op(0)});
458 }
459 } else continue;
460 if(bilst.nops()!=2) continue;
461
462 bool ok = true;
463 for(auto ii : get_x_from(bilst.op(0))) {
464 if(bilst.op(1).has(ii)) {
465 ok = false;
466 break;
467 }
468 }
469 if(ok) {
470 xcs.append(bilst.op(0));
471 xcs.append(bilst.op(1));
472 return true;
473 }
474 }
475 }
476
477 // TODO: other modes
478 }
479 return false;
480 }
481
489 void ChengWu::Partilize(const lst xcs, const lst delta_in, const ex fe_in, exvector & ret_lst) {
490 if(Verbose>10) {
491 cout << PRE << "\\--" << Color_HighLight << "ChengWu @xcs=" << xcs.nops() << RESET << endl;
492 }
493 lst ret = xcs;
494 auto fe = fe_in;
495 auto delta = delta_in;
496 auto ilast = ret.nops()-1;
497 ex inv_det = 1;
498 if(is_zero(get_op(ret,ilast,0))) {
499 lst rep_xs;
500 for(int i=ilast-1; i>=0; i--) rep_xs.append(get_op(ret,i,0));
501 ex xfi=0;
502 for(auto xi : delta) {
503 if(!rep_xs.has(xi) && !get_op(ret,ilast,1).has(xi)) {
504 xfi = xi;
505 break;
506 }
507 }
508 if(is_zero(xfi)) {
509 ex xs0=0;
510 for(auto xi : delta) {
511 if(!rep_xs.has(xi)) {
512 xs0 = xi;
513 break;
514 }
515 }
516 if(is_zero(xs0)) throw Error("Partilize: (xs0.is_zero())");
517 xfi = x(x_free_index(fe));
518 delta.append(xfi);
519 int dlti = -1;
520 for(int i=0; i<fe.op(2).nops(); i++) {
521 if(fe.op(2).op(i).has(xs0)) {
522 dlti = i;
523 break;
524 }
525 }
526 if(dlti<0) throw Error("Partilize: dlti<0 found.");
527 let_op_append(fe, 2, dlti, xfi);
528 let_op_append(fe, 0, xs0);
529 let_op_append(fe, 0, xfi+xs0);
530 let_op_append(fe, 1, 1);
531 let_op_append(fe, 1, -2);
532 }
533
534 let_op(ret, ilast, 0, xfi);
535 for(int i=ilast-1; i>=0; i--) let_op(ret, i, 1, get_op(ret,i,1)*xfi);
536 }
537 lst rm_xs;
538 for(int i=ilast; i>=0; i--) {
539 auto xi = ret.op(i).op(0);
540 rm_xs.append(xi);
541 auto yi = xi.subs(x(w)==y(w));
542 auto s = ret.op(i).op(1);
543 inv_det *= s;
544 ret.let_op(i).let_op(1) = yi/s;
545 for(int j=i-1; j>=0; j--) {
546 ret.let_op(j) = ret.op(j).subs(xi==yi/s);
547 }
548 }
549 lst x2y;
550 for(auto ss : ret) x2y.append(ss.op(0)==ss.op(1));
551
552 auto nnn = fe.op(0).nops();
553 for(int i=0; i<nnn; i++) {
554 if(!fe.op(0).op(i).has(x(w))) continue;
555 auto tmp = exfactor(fe.op(0).op(i).subs(x2y));
556 tmp = tmp.subs(y(w)==x(w));
557 auto num_den = numer_denom(tmp);
558 if(num_den.op(1).subs(x(w)==1)<0) {
559 num_den.let_op(0) = ex(0)-num_den.op(0);
560 num_den.let_op(1) = ex(0)-num_den.op(1);
561 }
562 fe.let_op(0).let_op(i) = num_den.op(0);
563 if(num_den.op(1)!=1) {
564 let_op_append(fe, 0, num_den.op(1));
565 let_op_append(fe, 1, ex(0)-fe.op(1).op(i));
566 }
567 }
568
569 inv_det = exfactor(inv_det.subs(y(w)==x(w)));
570 auto idet_num_den = numer_denom(inv_det);
571 if(idet_num_den.op(1).subs(x(w)==1)<0) {
572 idet_num_den.let_op(0) = ex(0)-idet_num_den.op(0);
573 idet_num_den.let_op(1) = ex(0)-idet_num_den.op(1);
574 }
575 if(idet_num_den.op(0)!=1) {
576 let_op_append(fe, 0, idet_num_den.op(0));
577 let_op_append(fe, 1, -1);
578 }
579 if(idet_num_den.op(1)!=1) {
580 let_op_append(fe, 0, idet_num_den.op(1));
581 let_op_append(fe, 1, 1);
582 }
583
584 if(!isProjective(fe,delta)) {
585 ex re_xi = 0;
586 for(auto xi : delta) {
587 if(!rm_xs.has(xi)) {
588 re_xi = xi;
589 break;
590 }
591 }
592 if(is_zero(re_xi)) {
593 cout << "xcs = " << xcs << endl;
594 cout << "fe = " << fe_in << endl;
595 throw Error("Partilize: rm_xs = " + ex2str(rm_xs) + " & delta = " + ex2str(delta));
596 }
597 Projectivize(fe, delta, re_xi);
598 }
599
600 auto new_ft = SecDec::XRefined(get_op(fe, 0, 0));
601 symbol ss;
602 auto sft = new_ft.subs(x(w)==ss*x(w));
603 if(sft.degree(ss)!=1 || sft.ldegree(ss)!=1) throw Error("Partilize: ldegree/degree is NOT 1.");
604 auto rxs = get_x_from(new_ft);
605 lst xPos, xNeg;
606 ex sPos=0, sNeg=0;
607 for(auto xi : rxs) {
608 auto ci = new_ft.coeff(xi);
609 if(ci>0) {
610 xPos.append(xi); sPos += xi*ci;
611 } else {
612 xNeg.append(xi); sNeg -= xi*ci;
613 }
614 }
615 if(is_zero(sPos*sNeg)) throw Error("Partilize: sPos * sNeg = 0");
616 ex px = 0;
617 ex nx = 0;
618 for(int i=rm_xs.nops(); i>0; i--) {
619 auto xi = rm_xs.op(i-1);
620 if(is_zero(nx) && xNeg.has(xi)) nx = xi;
621 else if(is_zero(px) && xPos.has(xi)) px = xi;
622 if(!is_zero(px) && !is_zero(nx)) break;
623 }
624 if(sNeg<sPos) {
625 ex s = sNeg/nx;
626 if(s!=1) Scalelize(fe,xPos,s);
627 s = sPos/px;
628 if(s!=1) Scalelize(fe,nx,s);
629 } else {
630 ex s = sPos/px;
631 if(s!=1) Scalelize(fe,xNeg,s);
632 s = sNeg/nx;
633 if(s!=1) Scalelize(fe,px,s);
634 }
635 ex eqn = px-nx;
636 auto bilst = Binarize(fe, eqn);
637 for(auto item : bilst) {
638 if(!isProjective(item,delta)) throw Error("Partilize: something is wrong here.");
639 let_op(item, 0, 0, 1);
640 ret_lst.push_back(item);
641 }
642 }
643
649 exvector ChengWu::Evaluate(const ex & in_fe) {
650 exvector fe_lst, ret_lst;
651 fe_lst.push_back(in_fe);
652 static int total_modes = 5;
653 while(true) {
654 exvector fe_lst2;
655 for(int i=0; i<fe_lst.size(); i++) {
656 auto fe = fe_lst[i];
657 auto ft = get_op(fe, 0, 0);
658
659 // make sure, otherwise Projectivise may change things
660 if(!get_op(fe, 1, 0).is_zero()) {
661 throw Error("Evaluate: (!get_op(fe, 1, 0).is_zero())");
662 }
663 ft = SecDec::XRefined(ft);
664
665 if(fe.nops()<3 || xSign(ft)!=0) {
666 let_op(fe, 0, 0, 1);
667 ret_lst.push_back(fe);
668 goto ok_label;
669 }
670
671 // loop modes and deltas
672 for(int mode=0; mode<total_modes; mode++) {
673 for(int di=0; di<fe.op(2).nops(); di++) {
674 lst delta = ex_to<lst>(fe.op(2).op(di));
675 if(delta.nops()<2) continue;
676
677 lst ret;
678 if(mode==0 && isPartilizable(ft, delta, ret, mode)) {
679 Partilize(ret, delta, fe, ret_lst);
680 goto ok_label;
681 }
682
683 ret.remove_all();
684 if(mode==1 && isPartilizable(ft, delta, ret, mode)) {
685 Partilize(ret, delta, fe, ret_lst);
686 goto ok_label;
687 }
688
689 ret.remove_all();
690 if(mode==2 && isPartilizable(ft, delta, ret, mode)) {
691 auto bilst = Binarize(fe, get_op(ret, ret.nops()-1, 1));
692 for(auto item : bilst) fe_lst2.push_back(item);
693 goto ok_label;
694 }
695
696 ret.remove_all();
697 if(mode==3 && isPartilizable(ft, delta, ret, mode)) {
698 auto bilst = Binarize(fe, get_op(ret, ret.nops()-1, 1));
699 for(auto item : bilst) fe_lst2.push_back(item);
700 goto ok_label;
701 }
702
703 ret.remove_all();
704 if(mode==4 && isPartilizable(ft, delta, ret, mode)) {
705 auto eq1 = get_op(ret, ret.nops()-1, 1);
706 auto eq2 = get_op(ret, ret.nops()-2, 1);
707 for(auto item : Binarize(fe, eq1)) {
708 for(auto ii : Binarize(item, eq2)) fe_lst2.push_back(ii);
709 }
710 goto ok_label;
711 }
712
713 //TODO: other mode
714
715 }}
716 let_op(fe, 0, 0, 2);
717 ret_lst.push_back(fe);
718
719 ok_label: ;
720 }
721 if(fe_lst2.size()<1) break;
722 fe_lst = fe_lst2;
723 }
724
725 return exvector(std::move(ret_lst));
726 }
727
728 namespace {
729 int maxn(const ex pols, const ex xi) {
730 int max_xn = -1;
731 for(auto item : pols) {
732 auto cxn = item.degree(xi);
733 if(max_xn<cxn) max_xn = cxn;
734 }
735 return max_xn;
736 }
737 }
738
744 exvector ChengWu::WickRotation(const exvector & fe_vec) {
745 exvector ret_vec, run_vec, run2_vec;
746 run_vec = fe_vec;
747 ReRun:
748 for(auto fe : run_vec) {
749 ex ft = fe.op(0).op(1);
750 auto xs = get_x_from(ft);
751
752 // Case: x(cx!=0) + (c0!=0)
753 for(auto xi : xs) {
754 auto ftx = collect_ex(ft,xi);
755 auto c0 = ftx.subs(xi==0);
756
757 auto cx = ftx-c0;
758 if(xSign(cx)!=0) {
759 if(xSign(c0)!=0) {
760 auto max_xn = maxn(fe.op(0),xi)+1;
761 auto wra = WRA(-xSign(cx) * Pi/max_xn);
762 fe.let_op(0) = fe.op(0).subs(xi==exp(I*wra)*xi);
763 if(fe.op(1).op(0)!=1) throw Error("WickRotation: fe.op(0).op(0)!=1.");
764 fe.let_op(0).let_op(0) = fe.op(0).op(0) * exp(I*wra);
765 ret_vec.push_back(fe);
766 goto next_fe;
767 } else {
768 auto item = SecDec::XRefined(c0);
769 auto xs2 = get_x_from(item);
770 for(auto xi2 : xs2) {
771 if(item.degree(xi2)!=1) continue;
772 auto xc0 = item.subs(xi2==0);
773 auto xc1 = item.coeff(xi2);
774 if(xSign(xc0)*xSign(xc1)<0) {
775 ex xx = 0;
776 for(auto xi3 : xs2) {
777 if(xi3==xi || xi3==xi2) continue;
778 xx = xi3;
779 break;
780 }
781 if(is_zero(xx)) continue;
782 Scalelize(fe,xi2,-xc0/xc1/xx);
783 auto bfe = Binarize(fe, xi2-xx);
784 for(auto item2 : bfe) run2_vec.push_back(item2);
785 goto next_fe;
786 }
787 }
788 }
789 }
790 }
791
792 // Case: a*x^2+b*x+c with a*c<0 or b*c>0
793 for(auto xi : xs) {
794 auto ftx = collect_ex(ft,xi);
795 if(ftx.degree(xi)!=2) continue;
796
797 auto c0 = ftx.coeff(xi,0);
798 auto c1 = ftx.coeff(xi,1);
799 auto c2 = ftx.coeff(xi,2);
800
801 if(xSign(c2) * xSign(c0) <0) {
802 if(xSign(c1)!=0) {
803 auto max_xn = maxn(fe.op(0),xi)+1;
804 auto wra = WRA(-xSign(c2) * Pi/max_xn);
805 fe.let_op(0) = fe.op(0).subs(xi==exp(I*wra)*xi);
806 fe.let_op(0).let_op(1) = c2*pow(xi,2)*exp(I*wra)+c1*xi+c0*exp(-I*wra);
807 if(fe.op(1).op(0)!=1) throw Error("WickRotation: fe.op(0).op(0)!=1.");
808 fe.let_op(0).let_op(0) = fe.op(0).op(0) * exp(I*wra*(1+fe.op(1).op(1)));
809 ret_vec.push_back(fe);
810 goto next_fe;
811 } else {
812 auto item = SecDec::XRefined(c1);
813 auto xs2 = get_x_from(item);
814 for(auto xi2 : xs2) {
815 if(item.degree(xi2)!=1) continue;
816 auto xc0 = item.subs(xi2==0);
817 auto xc1 = item.coeff(xi2);
818 if(xSign(xc0)*xSign(xc1)<0) {
819 ex xx = 0;
820 for(auto xi3 : xs2) {
821 if(xi3==xi || xi3==xi2) continue;
822 xx = xi3;
823 break;
824 }
825 if(is_zero(xx)) continue;
826 Scalelize(fe,xi2,-xc0/xc1/xx);
827 auto bfe = Binarize(fe, xi2-xx);
828 for(auto item2 : bfe) run2_vec.push_back(item2);
829 goto next_fe;
830 }
831 }
832 }
833 }
834
835 if(xSign(c1) * xSign(c0) >0) {
836 if(xSign(c2)!=0) {
837 auto max_xn = maxn(fe.op(0),xi)+1;
838 auto wra = WRA(xSign(c0) * Pi/max_xn);
839 fe.let_op(0) = fe.op(0).subs(xi==exp(I*wra)*xi);
840 fe.let_op(0).let_op(1) = c2*pow(xi,2)+c1*xi*exp(-I*wra)+c0*exp(-2*I*wra);
841 if(fe.op(1).op(0)!=1) throw Error("WickRotation: fe.op(0).op(0)!=1.");
842 fe.let_op(0).let_op(0) = fe.op(0).op(0) * exp(I*wra*(1+2*fe.op(1).op(1)));
843 ret_vec.push_back(fe);
844 goto next_fe;
845 } else {
846 auto item = SecDec::XRefined(c2);
847 auto xs2 = get_x_from(item);
848 for(auto xi2 : xs2) {
849 if(item.degree(xi2)!=1) continue;
850 auto xc0 = item.subs(xi2==0);
851 auto xc1 = item.coeff(xi2);
852 if(xSign(xc0)*xSign(xc1)<0) {
853 ex xx = 0;
854 for(auto xi3 : xs2) {
855 if(xi3==xi || xi3==xi2) continue;
856 xx = xi3;
857 break;
858 }
859 if(is_zero(xx)) continue;
860 Scalelize(fe,xi2,-xc0/xc1/xx);
861 auto bfe = Binarize(fe, xi2-xx);
862 for(auto item2 : bfe) run2_vec.push_back(item2);
863 goto next_fe;
864 }
865 }
866 }
867 }
868
869 auto c0x = Factor(c0);
870 if(is_a<mul>(c0x)) {
871 ex cc = 1;
872 for(auto item : c0x) {
873 if(!is_a<numeric>(item) && !item.match(x(w))) cc *= item;
874 }
875 c0x = cc;
876 }
877 if(Factor(c0x).match(pow(w,2))) {
878 auto item = SecDec::XRefined(c0x);
879 auto xs2 = get_x_from(item);
880 for(auto xi2 : xs2) {
881 if(item.degree(xi2)!=1) continue;
882 auto xc0 = item.subs(xi2==0);
883 auto xc1 = item.coeff(xi2);
884 if(xSign(xc0)*xSign(xc1)<0) {
885 ex xx = 0;
886 for(auto xi3 : xs2) {
887 if(xi3==xi || xi3==xi2) continue;
888 xx = xi3;
889 break;
890 }
891 if(is_zero(xx)) continue;
892 Scalelize(fe,xi2,-xc0/xc1/xx);
893 auto bfe = Binarize(fe, xi2-xx);
894 for(auto item2 : bfe) run2_vec.push_back(item2);
895 goto next_fe;
896 }
897 }
898 }
899 }
900
901 ret_vec.push_back(fe);
902 next_fe: ;
903 }
904 if(run2_vec.size()>0) {
905 run_vec = run2_vec;
906 run2_vec.clear();
907 goto ReRun;
908 }
909 return exvector(std::move(ret_vec));
910 }
911
912}
#define RESET
Definition BASIC.h:79
SecDec header file.
class used to wrap error message
Definition BASIC.h:242
static bool isPartilizable(const ex ft, const ex delta, lst &xcs, int mode=0)
isPartilize w.r.t. F-term, generized to isLinearizable
Definition ChengWu.cpp:397
static bool isLinearizable(const ex ft, const ex delta, lst &xcs)
Linearize w.r.t. F-term.
Definition ChengWu.cpp:301
static exvector Apply(const exvector &fe_vec, const ex &ft=0)
ChengWu-rized on the vector of fe, note that 1st element of the output, which needs to be droped,...
Definition ChengWu.cpp:61
static exvector Binarize(ex const fe, ex const eqn)
Binarize the input fe, w.r.t. the linear eqn.
Definition ChengWu.cpp:220
static void Projectivize(ex &fe, const ex delta, const ex xsum=0)
to Projectivize the input fe, the fe will be updated
Definition ChengWu.cpp:119
static void Partilize(const lst xcs, const lst delta, const ex fe, exvector &ret_lst)
Partilize function, generized to Linearize.
Definition ChengWu.cpp:489
static void Scalelize(ex &fe, const lst xs, const ex cy)
to Scalelize the input fe, the fe will be updated
Definition ChengWu.cpp:170
static bool isProjective(const ex fe, const ex delta)
to check the input fe is Projective or NOT w.r.t. delta
Definition ChengWu.cpp:95
static exvector Evaluate(const ex &fe)
ChengWu Internal, make sure ft in the first term, ONLY appear in ChengWu.cpp.
Definition ChengWu.cpp:649
static void Linearize(const lst xcs, ex &fe, ex &ft)
Linearize w.r.t. xcs_in.
Definition ChengWu.cpp:328
static exvector WickRotation(const exvector &fe_vec)
WickRotation, just check WRA exist or NOT to see successful or NOT. Still Experimental.
Definition ChengWu.cpp:744
static lst XRefined_lst(ex const &ft)
Definition Helpers.cpp:392
static ex XRefined(ex const &ft)
Definition Helpers.cpp:369
void ChengWu(const ex &ft=0)
ChengWu for SecDec class.
Definition ChengWu.cpp:14
exvector FunExp
Definition SD.h:426
namespace for Numerical integration with Sector Decomposition method
Definition AsyMB.cpp:10
int x_free_index(ex expr)
Definition Helpers.cpp:165
exvector get_x_from(ex pol)
Definition Helpers.cpp:29
ex Factor(const ex expr_in)
Definition Helpers.cpp:244
ex expand_ex(ex const &expr_in, std::function< bool(const ex &)> has_func)
the expand like Mathematica
Definition BASIC.cpp:1188
const char * Color_HighLight
Definition BASIC.cpp:248
ex exfactor(const ex &expr_in, int opt)
factorize a expression
Definition BASIC.cpp:1854
void let_op_prepend(ex &ex_in, const ex item)
preppend item into expression
Definition BASIC.cpp:1335
void let_op(ex &ex_in, int index1, int index2, const ex item)
update index1-th.index2-th of expression with item
Definition BASIC.cpp:1560
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
ex get_op(const ex ex_in, int index1, int index2)
return index1-th.index2-th of expression
Definition BASIC.cpp:1606
int Verbose
Definition Init.cpp:142
void let_op_append(ex &ex_in, const ex item)
append item into expression
Definition BASIC.cpp:1324
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
Definition BASIC.cpp:715
void let_op_remove_first(ex &ex_in)
remove first from expression
Definition BASIC.cpp:1355
int xSign(ex const expr)
the always sign for expr
Definition BASIC.cpp:1312
string PRE
Definition Init.cpp:143
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51