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 func = fe.op(0).op(i);
132 if(!func.has(x(
w)))
continue;
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};
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);
143 fe.let_op(0).let_op(i) = tmp;
146 over_all_sn = normal(over_all_sn+delta.nops());
147 if(!over_all_sn.is_zero()) {
160 if(is_a<lst>(xi))
Scalelize(fe, ex_to<lst>(xi), cy);
176 auto yi = xi.subs(x(
w)==y(
w));
177 x2y.append(xi==cy*yi);
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);
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);
190 fe.let_op(0).let_op(i) = tmp.op(0);
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);
223 return exvector(std::move(ovec));
235 throw Error(
"Binarize: xij.size()!=2, " +
ex2str(xij));
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)");
251 auto f1 = ex_to<lst>(fe.op(0));
252 auto e1 = ex_to<lst>(fe.op(1));
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});
257 if(e1.op(0)==1) f1.let_op(0) = f1.op(0)/(1+c1);
258 else if(e1.op(1)==1) f1.let_op(1) = f1.op(1)/(1+c1);
268 auto f2 = ex_to<lst>(fe.op(0));
269 auto e2 = ex_to<lst>(fe.op(1));
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});
274 if(e2.op(0)==1) f2.let_op(0) = f2.op(0)/(1+c2);
275 else if(e2.op(1)==1) f2.let_op(1) = f2.op(1)/(1+c2);
302 for(
auto xi : delta) {
304 if(!f.has(xi) || f.degree(xi)!=1)
continue;
305 auto cxi = f.coeff(xi);
307 int cxi_sgn =
xSign(cxi);
310 if(cxi_sgn<0) cxi = ex(0)-cxi;
313 for(
auto xc : ret) xcs.append(xc);
314 xcs.append(lst{xi, cxi});
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));
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);
343 for(
auto ss : xcs) x2y[ss.op(0)]=ss.op(1);
346 if(ft.has(x(
w))) ft = ft.subs(x2y).subs(y(
w)==x(
w));
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);
359 fe.let_op(0).let_op(i) = num_den.op(0);
360 if(num_den.op(1)!=1) {
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);
373 if(idet_num_den.op(0)!=1) {
377 if(idet_num_den.op(1)!=1) {
398 for(
auto xi : delta) {
399 if(!ft.has(xi) || ft.degree(xi)!=1)
continue;
401 auto cxi = ft.coeff(xi);
402 int cxi_sgn =
xSign(cxi);
403 auto re_ft = ft.subs(xi==0);
406 if(cxi_sgn<0) cxi = ex(0)-cxi;
409 ret.append(lst{xi, cxi});
411 for(
int i=0; i<ret.nops(); i++) xcs.append(ret.op(i));
415 if((mode>0) && (
xSign(re_ft)!=0)) {
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});
422 if(fflst.nops()==1) {
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)});
435 if(cclst.nops()==1) {
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)});
442 if(bilst.nops()!=1)
continue;
444 if(mode==3 &&
xSign(re_ft)!=0) {
446 xcs.append(bilst.op(0));
453 if(fflst.nops()==1) {
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)});
460 if(bilst.nops()!=2)
continue;
464 if(bilst.op(1).has(ii)) {
470 xcs.append(bilst.op(0));
471 xcs.append(bilst.op(1));
495 auto delta = delta_in;
496 auto ilast = ret.nops()-1;
498 if(is_zero(
get_op(ret,ilast,0))) {
500 for(
int i=ilast-1; i>=0; i--) rep_xs.append(
get_op(ret,i,0));
502 for(
auto xi : delta) {
503 if(!rep_xs.has(xi) && !
get_op(ret,ilast,1).has(xi)) {
510 for(
auto xi : delta) {
511 if(!rep_xs.has(xi)) {
516 if(is_zero(xs0))
throw Error(
"Partilize: (xs0.is_zero())");
520 for(
int i=0; i<fe.op(2).nops(); i++) {
521 if(fe.op(2).op(i).has(xs0)) {
526 if(dlti<0)
throw Error(
"Partilize: dlti<0 found.");
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);
538 for(
int i=ilast; i>=0; i--) {
539 auto xi = ret.op(i).op(0);
541 auto yi = xi.subs(x(
w)==y(
w));
542 auto s = ret.op(i).op(1);
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);
550 for(
auto ss : ret) x2y.append(ss.op(0)==ss.op(1));
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);
562 fe.let_op(0).let_op(i) = num_den.op(0);
563 if(num_den.op(1)!=1) {
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);
575 if(idet_num_den.op(0)!=1) {
579 if(idet_num_den.op(1)!=1) {
586 for(
auto xi : delta) {
593 cout <<
"xcs = " << xcs << endl;
594 cout <<
"fe = " << fe_in << endl;
595 throw Error(
"Partilize: rm_xs = " +
ex2str(rm_xs) +
" & delta = " +
ex2str(delta));
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.");
608 auto ci = new_ft.coeff(xi);
610 xPos.append(xi); sPos += xi*ci;
612 xNeg.append(xi); sNeg -= xi*ci;
615 if(is_zero(sPos*sNeg))
throw Error(
"Partilize: sPos * sNeg = 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;
637 for(
auto item : bilst) {
638 if(!
isProjective(item,delta))
throw Error(
"Partilize: something is wrong here.");
640 ret_lst.push_back(item);
650 exvector fe_lst, ret_lst;
651 fe_lst.push_back(in_fe);
652 static int total_modes = 5;
655 for(
int i=0; i<fe_lst.size(); i++) {
657 auto ft =
get_op(fe, 0, 0);
660 if(!
get_op(fe, 1, 0).is_zero()) {
661 throw Error(
"Evaluate: (!get_op(fe, 1, 0).is_zero())");
665 if(fe.nops()<3 ||
xSign(ft)!=0) {
667 ret_lst.push_back(fe);
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;
692 for(
auto item : bilst) fe_lst2.push_back(item);
699 for(
auto item : bilst) fe_lst2.push_back(item);
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);
717 ret_lst.push_back(fe);
721 if(fe_lst2.size()<1)
break;
725 return exvector(std::move(ret_lst));
729 int maxn(
const ex pols,
const ex xi) {
731 for(
auto item : pols) {
732 auto cxn = item.degree(xi);
733 if(max_xn<cxn) max_xn = cxn;
745 exvector ret_vec, run_vec, run2_vec;
748 for(
auto fe : run_vec) {
749 ex ft = fe.op(0).op(1);
755 auto c0 = ftx.subs(xi==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);
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);
776 for(
auto xi3 : xs2) {
777 if(xi3==xi || xi3==xi2)
continue;
781 if(is_zero(xx))
continue;
784 for(
auto item2 : bfe) run2_vec.push_back(item2);
795 if(ftx.degree(xi)!=2)
continue;
797 auto c0 = ftx.coeff(xi,0);
798 auto c1 = ftx.coeff(xi,1);
799 auto c2 = ftx.coeff(xi,2);
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);
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);
820 for(
auto xi3 : xs2) {
821 if(xi3==xi || xi3==xi2)
continue;
825 if(is_zero(xx))
continue;
828 for(
auto item2 : bfe) run2_vec.push_back(item2);
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);
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);
854 for(
auto xi3 : xs2) {
855 if(xi3==xi || xi3==xi2)
continue;
859 if(is_zero(xx))
continue;
862 for(
auto item2 : bfe) run2_vec.push_back(item2);
872 for(
auto item : c0x) {
873 if(!is_a<numeric>(item) && !item.match(x(
w))) cc *= item;
877 if(
Factor(c0x).match(pow(
w,2))) {
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);
886 for(
auto xi3 : xs2) {
887 if(xi3==xi || xi3==xi2)
continue;
891 if(is_zero(xx))
continue;
894 for(
auto item2 : bfe) run2_vec.push_back(item2);
901 ret_vec.push_back(fe);
904 if(run2_vec.size()>0) {
909 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)