16 if(is_a<lst>(ft) && ft.nops()>1) {
25 for(
int i=0; i<nt; i++) {
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.");
63 for(
auto fe : fe_vec) {
66 if(fe.op(0).nops()>1) cft = fe.op(0).op(1);
69 if(fe.nops()<3 ||
xSign(cft)!=0 || cft.has(WRA(
w))) {
72 ret_fe_vec.push_back(fe);
75 auto deltas = fe.op(2);
76 for(
int di=0; di<deltas.nops(); di++) {
79 if(is_zero(ft)) cft = fe.op(0).op(1);
83 for(
auto item : ret) ret_fe_vec.push_back(item);
86 return exvector(std::move(ret_fe_vec));
98 for(
int j=0; j<delta.nops(); j++) sRepl.append(delta.op(j)==delta.op(j)*s);
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;
105 auto sn = func.degree(s);
106 if(sn!=func.ldegree(s))
return false;
107 over_all_sn += sn*fe.op(1).op(i);
109 over_all_sn = normal(over_all_sn+delta.nops());
110 return over_all_sn.is_zero();
122 for(
int j=0; j<delta.nops(); j++) sRepl.append(delta.op(j)==delta.op(j)*s);
125 for(
auto xi : delta) xsum += xi;
129 int nnn = fe.op(0).nops();
130 for(
int i=0; i<nnn; i++) {
131 auto funcs = fe.op(0).op(i);
132 if(!funcs.has(x(
w)))
continue;
133 if(!is_a<mul>(funcs)) funcs = lst{ funcs };
135 for(
auto func : funcs) {
137 if(func.match(pow(
w1,
w2))) {
142 auto sn = func.degree(s);
143 over_all_sn += sn*fe.op(1).op(i)*nn;
144 if(!is_a<add>(func)) func = lst{func};
146 for(
auto ii : func) {
147 auto sni = ii.degree(s);
148 if(sni!=sn) tmp += ii.subs(s==1) * pow(xsum, sn-sni);
149 else tmp += ii.subs(s==1);
151 if(nn!=1) tmp = pow(tmp,nn);
157 over_all_sn = normal(over_all_sn+delta.nops());
158 if(!over_all_sn.is_zero()) {
172 if(is_a<lst>(xi))
Scalelize(fe, ex_to<lst>(xi), cy);
188 auto yi = xi.subs(x(
w)==y(
w));
189 x2y.append(xi==cy*yi);
192 auto nnn = fe.op(0).nops();
193 for(
int i=0; i<nnn; i++) {
194 if(!fe.op(0).op(i).has(x(
w)))
continue;
195 auto tmp = fe.op(0).op(i).subs(x2y).subs(y2x);
197 tmp = numer_denom(tmp);
198 if(tmp.op(1).subs(x(
w)==1)<0) {
199 tmp[0] = ex(0)-tmp.op(0);
200 tmp[1] = ex(0)-tmp.op(1);
202 fe[0][i] = tmp.op(0);
210 det = numer_denom(det);
211 if(det.op(1).subs(x(
w)==1)<0) {
212 det[0] = ex(0)-det.op(0);
213 det[1] = ex(0)-det.op(1);
235 return exvector(std::move(ovec));
247 throw Error(
"Binarize: xij.size()!=2, " +
ex2str(xij));
251 ex ci = eqn.coeff(xi);
252 ex cj = eqn.coeff(xj);
253 if(!((ci*xi+cj*xj-eqn).is_zero() && is_a<numeric>(ci * cj) && (ci*cj)<0)) {
254 throw Error(
"Binarize: ((ci*xi+cj*xj-eqn).is_zero() && is_a<numeric>(ci * cj) && (ci*cj)<0)");
263 auto f1 = ex_to<lst>(fe.op(0));
264 auto e1 = ex_to<lst>(fe.op(1));
266 for(
int i=0; i<f1.nops(); i++) {
267 f1[i] = f1.op(i).subs(lst{xi==c1*yj/(1+c1)+yi,xj==yj/(1+c1)}).
subs(lst{yi==xi,yj==xj});
269 if(e1.op(0)==1) f1[0] = f1.op(0)/(1+c1);
270 else if(e1.op(1)==1) f1[1] = f1.op(1)/(1+c1);
280 auto f2 = ex_to<lst>(fe.op(0));
281 auto e2 = ex_to<lst>(fe.op(1));
283 for(
int i=0; i<f2.nops(); i++) {
284 f2[i] = f2.op(i).subs(lst{xj==c2*yi/(1+c2)+yj,xi==yi/(1+c2)}).
subs(lst{yi==xi,yj==xj});
286 if(e2.op(0)==1) f2[0] = f2.op(0)/(1+c2);
287 else if(e2.op(1)==1) f2[1] = f2.op(1)/(1+c2);
314 for(
auto xi : delta) {
316 if(!f.has(xi) || f.degree(xi)!=1)
continue;
317 auto cxi = f.coeff(xi);
319 int cxi_sgn =
xSign(cxi);
322 if(cxi_sgn<0) cxi = ex(0)-cxi;
325 for(
auto xc : ret) xcs.append(xc);
326 xcs.append(lst{xi, cxi});
343 auto nnn = xcs.nops();
344 for(
int i=0; i<nnn; i++) {
345 auto xi = xcs.op(i).op(0);
346 auto s = xcs.op(i).op(1);
347 auto yi = xi.subs(x(
w)==y(
w));
350 for(
int j=i+1; j<nnn; j++) {
351 xcs[j] = xcs.op(j).subs(xi==yi/s);
355 for(
auto ss : xcs) x2y[ss.op(0)]=ss.op(1);
358 if(ft.has(x(
w))) ft = ft.subs(x2y).subs(y(
w)==x(
w));
361 nnn = fe.op(0).nops();
362 for(
int i=0; i<nnn; i++) {
363 if(!fe.op(0).op(i).has(x(
w)))
continue;
364 auto tmp = fe.op(0).op(i).subs(x2y);
365 tmp = tmp.subs(y(
w)==x(
w));
366 auto num_den = numer_denom(tmp);
367 if(num_den.op(1).subs(x(
w)==1)<0) {
368 num_den[0] = ex(0)-num_den.op(0);
369 num_den[1] = ex(0)-num_den.op(1);
371 fe[0][i] = num_den.op(0);
372 if(num_den.op(1)!=1) {
379 inv_det = inv_det.subs(y(
w)==x(
w));
380 auto idet_num_den = numer_denom(inv_det);
381 if(idet_num_den.op(1).subs(x(
w)==1)<0) {
382 idet_num_den[0] = ex(0)-idet_num_den.op(0);
383 idet_num_den[1] = ex(0)-idet_num_den.op(1);
385 if(idet_num_den.op(0)!=1) {
389 if(idet_num_den.op(1)!=1) {
410 for(
auto xi : delta) {
411 if(!ft.has(xi) || ft.degree(xi)!=1)
continue;
413 auto cxi = ft.coeff(xi);
414 int cxi_sgn =
xSign(cxi);
415 auto re_ft = ft.subs(xi==0);
418 if(cxi_sgn<0) cxi = ex(0)-cxi;
421 ret.append(lst{xi, cxi});
423 for(
int i=0; i<ret.nops(); i++) xcs.append(ret.op(i));
427 if((mode>0) && (
xSign(re_ft)!=0)) {
428 xcs.append(lst{xi, cxi});
429 if(re_ft.subs(x(
w)==1)<0) re_ft = ex(0)-re_ft;
430 xcs.append(lst{0, re_ft});
434 if(fflst.nops()==1) {
436 auto ff = fflst.op(0).subs(x(
w)==s*x(
w));
437 if(
get_x_from(ff).size()==2 && ff.degree(s)==1 && ff.ldegree(s)==1) {
438 xcs.append(lst{xi, cxi});
439 xcs.append(lst{0, fflst.op(0)});
447 if(cclst.nops()==1) {
449 auto cc = cclst.op(0).subs(x(
w)==s*x(
w));
450 if(
get_x_from(cc).size()==2 && cc.degree(s)==1 && cc.ldegree(s)==1) {
451 bilst.append(lst{0, cclst.op(0)});
454 if(bilst.nops()!=1)
continue;
456 if(mode==3 &&
xSign(re_ft)!=0) {
458 xcs.append(bilst.op(0));
465 if(fflst.nops()==1) {
467 auto ff = fflst.op(0).subs(x(
w)==s*x(
w));
468 if(
get_x_from(ff).size()==2 && ff.degree(s)==1 && ff.ldegree(s)==1) {
469 bilst.append(lst{0, fflst.op(0)});
472 if(bilst.nops()!=2)
continue;
476 if(bilst.op(1).has(ii)) {
482 xcs.append(bilst.op(0));
483 xcs.append(bilst.op(1));
507 auto delta = delta_in;
508 auto ilast = ret.nops()-1;
510 if(is_zero(
get_op(ret,ilast,0))) {
512 for(
int i=ilast-1; i>=0; i--) rep_xs.append(
get_op(ret,i,0));
514 for(
auto xi : delta) {
515 if(!rep_xs.has(xi) && !
get_op(ret,ilast,1).has(xi)) {
522 for(
auto xi : delta) {
523 if(!rep_xs.has(xi)) {
528 if(is_zero(xs0))
throw Error(
"Partilize: (xs0.is_zero())");
532 for(
int i=0; i<fe.op(2).nops(); i++) {
533 if(fe.op(2).op(i).has(xs0)) {
538 if(dlti<0)
throw Error(
"Partilize: dlti<0 found.");
546 let_op(ret, ilast, 0, xfi);
547 for(
int i=ilast-1; i>=0; i--)
let_op(ret, i, 1,
get_op(ret,i,1)*xfi);
550 for(
int i=ilast; i>=0; i--) {
551 auto xi = ret.op(i).op(0);
553 auto yi = xi.subs(x(
w)==y(
w));
554 auto s = ret.op(i).op(1);
557 for(
int j=i-1; j>=0; j--) {
558 ret[j] = ret.op(j).subs(xi==yi/s);
562 for(
auto ss : ret) x2y.append(ss.op(0)==ss.op(1));
564 auto nnn = fe.op(0).nops();
565 for(
int i=0; i<nnn; i++) {
566 if(!fe.op(0).op(i).has(x(
w)))
continue;
567 auto tmp =
exfactor(fe.op(0).op(i).subs(x2y));
568 tmp = tmp.subs(y(
w)==x(
w));
569 auto num_den = numer_denom(tmp);
570 if(num_den.op(1).subs(x(
w)==1)<0) {
571 num_den[0] = ex(0)-num_den.op(0);
572 num_den[1] = ex(0)-num_den.op(1);
574 fe[0][i] = num_den.op(0);
575 if(num_den.op(1)!=1) {
582 auto idet_num_den = numer_denom(inv_det);
583 if(idet_num_den.op(1).subs(x(
w)==1)<0) {
584 idet_num_den[0] = ex(0)-idet_num_den.op(0);
585 idet_num_den[1] = ex(0)-idet_num_den.op(1);
587 if(idet_num_den.op(0)!=1) {
591 if(idet_num_den.op(1)!=1) {
598 for(
auto xi : delta) {
605 cout <<
"xcs = " << xcs << endl;
606 cout <<
"fe = " << fe_in << endl;
607 throw Error(
"Partilize: rm_xs = " +
ex2str(rm_xs) +
" & delta = " +
ex2str(delta));
614 auto sft = new_ft.subs(x(
w)==ss*x(
w));
615 if(sft.degree(ss)!=1 || sft.ldegree(ss)!=1)
throw Error(
"Partilize: ldegree/degree is NOT 1.");
620 auto ci = new_ft.coeff(xi);
622 xPos.append(xi); sPos += xi*ci;
624 xNeg.append(xi); sNeg -= xi*ci;
627 if(is_zero(sPos*sNeg))
throw Error(
"Partilize: sPos * sNeg = 0");
630 for(
int i=rm_xs.nops(); i>0; i--) {
631 auto xi = rm_xs.op(i-1);
632 if(is_zero(nx) && xNeg.has(xi)) nx = xi;
633 else if(is_zero(px) && xPos.has(xi)) px = xi;
634 if(!is_zero(px) && !is_zero(nx))
break;
649 for(
auto item : bilst) {
651 cout << item << endl;
652 cout << delta << endl;
653 throw Error(
"Partilize: something is wrong here.");
656 ret_lst.push_back(item);
666 exvector fe_lst, ret_lst;
667 fe_lst.push_back(in_fe);
668 static int total_modes = 5;
671 for(
int i=0; i<fe_lst.size(); i++) {
673 auto ft =
get_op(fe, 0, 0);
676 if(!
get_op(fe, 1, 0).is_zero()) {
677 throw Error(
"Evaluate: (!get_op(fe, 1, 0).is_zero())");
681 if(fe.nops()<3 ||
xSign(ft)!=0) {
683 ret_lst.push_back(fe);
688 for(
int mode=0; mode<total_modes; mode++) {
689 for(
int di=0; di<fe.op(2).nops(); di++) {
690 lst delta = ex_to<lst>(fe.op(2).op(di));
691 if(delta.nops()<2)
continue;
708 for(
auto item : bilst) fe_lst2.push_back(item);
715 for(
auto item : bilst) fe_lst2.push_back(item);
721 auto eq1 =
get_op(ret, ret.nops()-1, 1);
722 auto eq2 =
get_op(ret, ret.nops()-2, 1);
723 for(
auto item :
Binarize(fe, eq1)) {
724 for(
auto ii :
Binarize(item, eq2)) fe_lst2.push_back(ii);
733 ret_lst.push_back(fe);
737 if(fe_lst2.size()<1)
break;
741 return exvector(std::move(ret_lst));
745 int maxn(
const ex pols,
const ex xi) {
747 for(
auto item : pols) {
748 auto cxn = item.degree(xi);
749 if(max_xn<cxn) max_xn = cxn;
761 exvector ret_vec, run_vec, run2_vec;
764 for(
auto fe : run_vec) {
765 ex ft = fe.op(0).op(1);
771 auto c0 = ftx.subs(xi==0);
776 auto max_xn = maxn(fe.op(0),xi)+1;
777 auto wra = WRA(-
xSign(cx) * Pi/max_xn);
778 fe[0] = fe.op(0).subs(xi==exp(I*wra)*xi);
779 if(fe.op(1).op(0)!=1)
throw Error(
"WickRotation: fe.op(0).op(0)!=1.");
780 fe[0][0] = fe.op(0).op(0) * exp(I*wra);
781 ret_vec.push_back(fe);
786 for(
auto xi2 : xs2) {
787 if(item.degree(xi2)!=1)
continue;
788 auto xc0 = item.subs(xi2==0);
789 auto xc1 = item.coeff(xi2);
792 for(
auto xi3 : xs2) {
793 if(xi3==xi || xi3==xi2)
continue;
797 if(is_zero(xx))
continue;
800 for(
auto item2 : bfe) run2_vec.push_back(item2);
811 if(ftx.degree(xi)!=2)
continue;
813 auto c0 = ftx.coeff(xi,0);
814 auto c1 = ftx.coeff(xi,1);
815 auto c2 = ftx.coeff(xi,2);
819 auto max_xn = maxn(fe.op(0),xi)+1;
820 auto wra = WRA(-
xSign(c2) * Pi/max_xn);
821 fe[0] = fe.op(0).subs(xi==exp(I*wra)*xi);
822 fe[0][1] = c2*pow(xi,2)*exp(I*wra)+c1*xi+c0*exp(-I*wra);
823 if(fe.op(1).op(0)!=1)
throw Error(
"WickRotation: fe.op(0).op(0)!=1.");
824 fe[0][0] = fe.op(0).op(0) * exp(I*wra*(1+fe.op(1).op(1)));
825 ret_vec.push_back(fe);
830 for(
auto xi2 : xs2) {
831 if(item.degree(xi2)!=1)
continue;
832 auto xc0 = item.subs(xi2==0);
833 auto xc1 = item.coeff(xi2);
836 for(
auto xi3 : xs2) {
837 if(xi3==xi || xi3==xi2)
continue;
841 if(is_zero(xx))
continue;
844 for(
auto item2 : bfe) run2_vec.push_back(item2);
853 auto max_xn = maxn(fe.op(0),xi)+1;
854 auto wra = WRA(
xSign(c0) * Pi/max_xn);
855 fe[0] = fe.op(0).subs(xi==exp(I*wra)*xi);
856 fe[0][1] = c2*pow(xi,2)+c1*xi*exp(-I*wra)+c0*exp(-2*I*wra);
857 if(fe.op(1).op(0)!=1)
throw Error(
"WickRotation: fe.op(0).op(0)!=1.");
858 fe[0][0] = fe.op(0).op(0) * exp(I*wra*(1+2*fe.op(1).op(1)));
859 ret_vec.push_back(fe);
864 for(
auto xi2 : xs2) {
865 if(item.degree(xi2)!=1)
continue;
866 auto xc0 = item.subs(xi2==0);
867 auto xc1 = item.coeff(xi2);
870 for(
auto xi3 : xs2) {
871 if(xi3==xi || xi3==xi2)
continue;
875 if(is_zero(xx))
continue;
878 for(
auto item2 : bfe) run2_vec.push_back(item2);
888 for(
auto item : c0x) {
889 if(!is_a<numeric>(item) && !item.match(x(
w))) cc *= item;
893 if(
Factor(c0x).match(pow(
w,2))) {
896 for(
auto xi2 : xs2) {
897 if(item.degree(xi2)!=1)
continue;
898 auto xc0 = item.subs(xi2==0);
899 auto xc1 = item.coeff(xi2);
902 for(
auto xi3 : xs2) {
903 if(xi3==xi || xi3==xi2)
continue;
907 if(is_zero(xx))
continue;
910 for(
auto item2 : bfe) run2_vec.push_back(item2);
917 ret_vec.push_back(fe);
920 if(run2_vec.size()>0) {
925 return exvector(std::move(ret_vec));
class used to wrap error message
static bool isPartilizable(const ex ft, const ex delta, lst &xcs, int mode=0)
isPartilize w.r.t. F-term, generized to isLinearizable
static bool isLinearizable(const ex ft, const ex delta, lst &xcs)
Linearize w.r.t. F-term.
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,...
static exvector Binarize(ex const fe, ex const eqn)
Binarize the input fe, w.r.t. the linear eqn.
static void Projectivize(ex &fe, const ex delta, const ex xsum=0)
to Projectivize the input fe, the fe will be updated
static void Partilize(const lst xcs, const lst delta, const ex fe, exvector &ret_lst)
Partilize function, generized to Linearize.
static void Scalelize(ex &fe, const lst xs, const ex cy)
to Scalelize the input fe, the fe will be updated
static bool isProjective(const ex fe, const ex delta)
to check the input fe is Projective or NOT w.r.t. delta
static exvector Evaluate(const ex &fe)
ChengWu Internal, make sure ft in the first term, ONLY appear in ChengWu.cpp.
static void Linearize(const lst xcs, ex &fe, ex &ft)
Linearize w.r.t. xcs_in.
static exvector WickRotation(const exvector &fe_vec)
WickRotation, just check WRA exist or NOT to see successful or NOT. Still Experimental.
static lst XRefined_lst(ex const &ft)
static ex XRefined(ex const &ft)
void ChengWu(const ex &ft=0)
ChengWu for SecDec class.
namespace for Numerical integration with Sector Decomposition method
int x_free_index(ex expr)
exvector get_x_from(ex pol)
ex Factor(const ex expr_in)
ex expand_ex(ex const &expr_in, std::function< bool(const ex &)> has_func)
the expand like Mathematica
const char * Color_HighLight
ex exfactor(const ex &expr_in, int opt)
factorize a expression
void let_op_prepend(ex &ex_in, const ex item)
preppend item into expression
void let_op(ex &ex_in, int index1, int index2, const ex item)
update index1-th.index2-th of expression with item
ex collect_ex(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica
ex get_op(const ex ex_in, int index1, int index2)
return index1-th.index2-th of expression
void let_op_append(ex &ex_in, const ex item)
append item into expression
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
void let_op_remove_first(ex &ex_in)
remove first from expression
int xSign(ex const expr)
the always sign for expr
ex subs(const ex &e, init_list sl)