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);
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()) {
171 if(is_a<lst>(xi))
Scalelize(fe, ex_to<lst>(xi), cy);
187 auto yi = xi.subs(x(
w)==y(
w));
188 x2y.append(xi==cy*yi);
191 auto nnn = fe.op(0).nops();
192 for(
int i=0; i<nnn; i++) {
193 if(!fe.op(0).op(i).has(x(
w)))
continue;
194 auto tmp = fe.op(0).op(i).subs(x2y).subs(y2x);
196 tmp = numer_denom(tmp);
197 if(tmp.op(1).subs(x(
w)==1)<0) {
198 tmp[0] = ex(0)-tmp.op(0);
199 tmp[1] = ex(0)-tmp.op(1);
201 fe[0][i] = tmp.op(0);
209 det = numer_denom(det);
210 if(det.op(1).subs(x(
w)==1)<0) {
211 det[0] = ex(0)-det.op(0);
212 det[1] = ex(0)-det.op(1);
234 return exvector(std::move(ovec));
246 throw Error(
"Binarize: xij.size()!=2, " +
ex2str(xij));
250 ex ci = eqn.coeff(xi);
251 ex cj = eqn.coeff(xj);
252 if(!((ci*xi+cj*xj-eqn).is_zero() && is_a<numeric>(ci * cj) && (ci*cj)<0)) {
253 throw Error(
"Binarize: ((ci*xi+cj*xj-eqn).is_zero() && is_a<numeric>(ci * cj) && (ci*cj)<0)");
262 auto f1 = ex_to<lst>(fe.op(0));
263 auto e1 = ex_to<lst>(fe.op(1));
265 for(
int i=0; i<f1.nops(); i++) {
266 f1[i] = f1.op(i).subs(lst{xi==c1*yj/(1+c1)+yi,xj==yj/(1+c1)}).
subs(lst{yi==xi,yj==xj});
268 if(e1.op(0)==1) f1[0] = f1.op(0)/(1+c1);
269 else if(e1.op(1)==1) f1[1] = f1.op(1)/(1+c1);
279 auto f2 = ex_to<lst>(fe.op(0));
280 auto e2 = ex_to<lst>(fe.op(1));
282 for(
int i=0; i<f2.nops(); i++) {
283 f2[i] = f2.op(i).subs(lst{xj==c2*yi/(1+c2)+yj,xi==yi/(1+c2)}).
subs(lst{yi==xi,yj==xj});
285 if(e2.op(0)==1) f2[0] = f2.op(0)/(1+c2);
286 else if(e2.op(1)==1) f2[1] = f2.op(1)/(1+c2);
313 for(
auto xi : delta) {
315 if(!f.has(xi) || f.degree(xi)!=1)
continue;
316 auto cxi = f.coeff(xi);
318 int cxi_sgn =
xSign(cxi);
321 if(cxi_sgn<0) cxi = ex(0)-cxi;
324 for(
auto xc : ret) xcs.append(xc);
325 xcs.append(lst{xi, cxi});
342 auto nnn = xcs.nops();
343 for(
int i=0; i<nnn; i++) {
344 auto xi = xcs.op(i).op(0);
345 auto s = xcs.op(i).op(1);
346 auto yi = xi.subs(x(
w)==y(
w));
349 for(
int j=i+1; j<nnn; j++) {
350 xcs[j] = xcs.op(j).subs(xi==yi/s);
354 for(
auto ss : xcs) x2y[ss.op(0)]=ss.op(1);
357 if(ft.has(x(
w))) ft = ft.subs(x2y).subs(y(
w)==x(
w));
360 nnn = fe.op(0).nops();
361 for(
int i=0; i<nnn; i++) {
362 if(!fe.op(0).op(i).has(x(
w)))
continue;
363 auto tmp = fe.op(0).op(i).subs(x2y);
364 tmp = tmp.subs(y(
w)==x(
w));
365 auto num_den = numer_denom(tmp);
366 if(num_den.op(1).subs(x(
w)==1)<0) {
367 num_den[0] = ex(0)-num_den.op(0);
368 num_den[1] = ex(0)-num_den.op(1);
370 fe[0][i] = num_den.op(0);
371 if(num_den.op(1)!=1) {
378 inv_det = inv_det.subs(y(
w)==x(
w));
379 auto idet_num_den = numer_denom(inv_det);
380 if(idet_num_den.op(1).subs(x(
w)==1)<0) {
381 idet_num_den[0] = ex(0)-idet_num_den.op(0);
382 idet_num_den[1] = ex(0)-idet_num_den.op(1);
384 if(idet_num_den.op(0)!=1) {
388 if(idet_num_den.op(1)!=1) {
409 for(
auto xi : delta) {
410 if(!ft.has(xi) || ft.degree(xi)!=1)
continue;
412 auto cxi = ft.coeff(xi);
413 int cxi_sgn =
xSign(cxi);
414 auto re_ft = ft.subs(xi==0);
417 if(cxi_sgn<0) cxi = ex(0)-cxi;
420 ret.append(lst{xi, cxi});
422 for(
int i=0; i<ret.nops(); i++) xcs.append(ret.op(i));
426 if((mode>0) && (
xSign(re_ft)!=0)) {
427 xcs.append(lst{xi, cxi});
428 if(re_ft.subs(x(
w)==1)<0) re_ft = ex(0)-re_ft;
429 xcs.append(lst{0, re_ft});
433 if(fflst.nops()==1) {
435 auto ff = fflst.op(0).subs(x(
w)==s*x(
w));
436 if(
get_x_from(ff).size()==2 && ff.degree(s)==1 && ff.ldegree(s)==1) {
437 xcs.append(lst{xi, cxi});
438 xcs.append(lst{0, fflst.op(0)});
446 if(cclst.nops()==1) {
448 auto cc = cclst.op(0).subs(x(
w)==s*x(
w));
449 if(
get_x_from(cc).size()==2 && cc.degree(s)==1 && cc.ldegree(s)==1) {
450 bilst.append(lst{0, cclst.op(0)});
453 if(bilst.nops()!=1)
continue;
455 if(mode==3 &&
xSign(re_ft)!=0) {
457 xcs.append(bilst.op(0));
464 if(fflst.nops()==1) {
466 auto ff = fflst.op(0).subs(x(
w)==s*x(
w));
467 if(
get_x_from(ff).size()==2 && ff.degree(s)==1 && ff.ldegree(s)==1) {
468 bilst.append(lst{0, fflst.op(0)});
471 if(bilst.nops()!=2)
continue;
475 if(bilst.op(1).has(ii)) {
481 xcs.append(bilst.op(0));
482 xcs.append(bilst.op(1));
506 auto delta = delta_in;
507 auto ilast = ret.nops()-1;
509 if(is_zero(
get_op(ret,ilast,0))) {
511 for(
int i=ilast-1; i>=0; i--) rep_xs.append(
get_op(ret,i,0));
513 for(
auto xi : delta) {
514 if(!rep_xs.has(xi) && !
get_op(ret,ilast,1).has(xi)) {
521 for(
auto xi : delta) {
522 if(!rep_xs.has(xi)) {
527 if(is_zero(xs0))
throw Error(
"Partilize: (xs0.is_zero())");
531 for(
int i=0; i<fe.op(2).nops(); i++) {
532 if(fe.op(2).op(i).has(xs0)) {
537 if(dlti<0)
throw Error(
"Partilize: dlti<0 found.");
545 let_op(ret, ilast, 0, xfi);
546 for(
int i=ilast-1; i>=0; i--)
let_op(ret, i, 1,
get_op(ret,i,1)*xfi);
549 for(
int i=ilast; i>=0; i--) {
550 auto xi = ret.op(i).op(0);
552 auto yi = xi.subs(x(
w)==y(
w));
553 auto s = ret.op(i).op(1);
556 for(
int j=i-1; j>=0; j--) {
557 ret[j] = ret.op(j).subs(xi==yi/s);
561 for(
auto ss : ret) x2y.append(ss.op(0)==ss.op(1));
563 auto nnn = fe.op(0).nops();
564 for(
int i=0; i<nnn; i++) {
565 if(!fe.op(0).op(i).has(x(
w)))
continue;
566 auto tmp =
exfactor(fe.op(0).op(i).subs(x2y));
567 tmp = tmp.subs(y(
w)==x(
w));
568 auto num_den = numer_denom(tmp);
569 if(num_den.op(1).subs(x(
w)==1)<0) {
570 num_den[0] = ex(0)-num_den.op(0);
571 num_den[1] = ex(0)-num_den.op(1);
573 fe[0][i] = num_den.op(0);
574 if(num_den.op(1)!=1) {
581 auto idet_num_den = numer_denom(inv_det);
582 if(idet_num_den.op(1).subs(x(
w)==1)<0) {
583 idet_num_den[0] = ex(0)-idet_num_den.op(0);
584 idet_num_den[1] = ex(0)-idet_num_den.op(1);
586 if(idet_num_den.op(0)!=1) {
590 if(idet_num_den.op(1)!=1) {
597 for(
auto xi : delta) {
604 cout <<
"xcs = " << xcs << endl;
605 cout <<
"fe = " << fe_in << endl;
606 throw Error(
"Partilize: rm_xs = " +
ex2str(rm_xs) +
" & delta = " +
ex2str(delta));
613 auto sft = new_ft.subs(x(
w)==ss*x(
w));
614 if(sft.degree(ss)!=1 || sft.ldegree(ss)!=1)
throw Error(
"Partilize: ldegree/degree is NOT 1.");
619 auto ci = new_ft.coeff(xi);
621 xPos.append(xi); sPos += xi*ci;
623 xNeg.append(xi); sNeg -= xi*ci;
626 if(is_zero(sPos*sNeg))
throw Error(
"Partilize: sPos * sNeg = 0");
629 for(
int i=rm_xs.nops(); i>0; i--) {
630 auto xi = rm_xs.op(i-1);
631 if(is_zero(nx) && xNeg.has(xi)) nx = xi;
632 else if(is_zero(px) && xPos.has(xi)) px = xi;
633 if(!is_zero(px) && !is_zero(nx))
break;
648 for(
auto item : bilst) {
649 if(!
isProjective(item,delta))
throw Error(
"Partilize: something is wrong here.");
651 ret_lst.push_back(item);
661 exvector fe_lst, ret_lst;
662 fe_lst.push_back(in_fe);
663 static int total_modes = 5;
666 for(
int i=0; i<fe_lst.size(); i++) {
668 auto ft =
get_op(fe, 0, 0);
671 if(!
get_op(fe, 1, 0).is_zero()) {
672 throw Error(
"Evaluate: (!get_op(fe, 1, 0).is_zero())");
676 if(fe.nops()<3 ||
xSign(ft)!=0) {
678 ret_lst.push_back(fe);
683 for(
int mode=0; mode<total_modes; mode++) {
684 for(
int di=0; di<fe.op(2).nops(); di++) {
685 lst delta = ex_to<lst>(fe.op(2).op(di));
686 if(delta.nops()<2)
continue;
703 for(
auto item : bilst) fe_lst2.push_back(item);
710 for(
auto item : bilst) fe_lst2.push_back(item);
716 auto eq1 =
get_op(ret, ret.nops()-1, 1);
717 auto eq2 =
get_op(ret, ret.nops()-2, 1);
718 for(
auto item :
Binarize(fe, eq1)) {
719 for(
auto ii :
Binarize(item, eq2)) fe_lst2.push_back(ii);
728 ret_lst.push_back(fe);
732 if(fe_lst2.size()<1)
break;
736 return exvector(std::move(ret_lst));
740 int maxn(
const ex pols,
const ex xi) {
742 for(
auto item : pols) {
743 auto cxn = item.degree(xi);
744 if(max_xn<cxn) max_xn = cxn;
756 exvector ret_vec, run_vec, run2_vec;
759 for(
auto fe : run_vec) {
760 ex ft = fe.op(0).op(1);
766 auto c0 = ftx.subs(xi==0);
771 auto max_xn = maxn(fe.op(0),xi)+1;
772 auto wra = WRA(-
xSign(cx) * Pi/max_xn);
773 fe[0] = fe.op(0).subs(xi==exp(I*wra)*xi);
774 if(fe.op(1).op(0)!=1)
throw Error(
"WickRotation: fe.op(0).op(0)!=1.");
775 fe[0][0] = fe.op(0).op(0) * exp(I*wra);
776 ret_vec.push_back(fe);
781 for(
auto xi2 : xs2) {
782 if(item.degree(xi2)!=1)
continue;
783 auto xc0 = item.subs(xi2==0);
784 auto xc1 = item.coeff(xi2);
787 for(
auto xi3 : xs2) {
788 if(xi3==xi || xi3==xi2)
continue;
792 if(is_zero(xx))
continue;
795 for(
auto item2 : bfe) run2_vec.push_back(item2);
806 if(ftx.degree(xi)!=2)
continue;
808 auto c0 = ftx.coeff(xi,0);
809 auto c1 = ftx.coeff(xi,1);
810 auto c2 = ftx.coeff(xi,2);
814 auto max_xn = maxn(fe.op(0),xi)+1;
815 auto wra = WRA(-
xSign(c2) * Pi/max_xn);
816 fe[0] = fe.op(0).subs(xi==exp(I*wra)*xi);
817 fe[0][1] = c2*pow(xi,2)*exp(I*wra)+c1*xi+c0*exp(-I*wra);
818 if(fe.op(1).op(0)!=1)
throw Error(
"WickRotation: fe.op(0).op(0)!=1.");
819 fe[0][0] = fe.op(0).op(0) * exp(I*wra*(1+fe.op(1).op(1)));
820 ret_vec.push_back(fe);
825 for(
auto xi2 : xs2) {
826 if(item.degree(xi2)!=1)
continue;
827 auto xc0 = item.subs(xi2==0);
828 auto xc1 = item.coeff(xi2);
831 for(
auto xi3 : xs2) {
832 if(xi3==xi || xi3==xi2)
continue;
836 if(is_zero(xx))
continue;
839 for(
auto item2 : bfe) run2_vec.push_back(item2);
848 auto max_xn = maxn(fe.op(0),xi)+1;
849 auto wra = WRA(
xSign(c0) * Pi/max_xn);
850 fe[0] = fe.op(0).subs(xi==exp(I*wra)*xi);
851 fe[0][1] = c2*pow(xi,2)+c1*xi*exp(-I*wra)+c0*exp(-2*I*wra);
852 if(fe.op(1).op(0)!=1)
throw Error(
"WickRotation: fe.op(0).op(0)!=1.");
853 fe[0][0] = fe.op(0).op(0) * exp(I*wra*(1+2*fe.op(1).op(1)));
854 ret_vec.push_back(fe);
859 for(
auto xi2 : xs2) {
860 if(item.degree(xi2)!=1)
continue;
861 auto xc0 = item.subs(xi2==0);
862 auto xc1 = item.coeff(xi2);
865 for(
auto xi3 : xs2) {
866 if(xi3==xi || xi3==xi2)
continue;
870 if(is_zero(xx))
continue;
873 for(
auto item2 : bfe) run2_vec.push_back(item2);
883 for(
auto item : c0x) {
884 if(!is_a<numeric>(item) && !item.match(x(
w))) cc *= item;
888 if(
Factor(c0x).match(pow(
w,2))) {
891 for(
auto xi2 : xs2) {
892 if(item.degree(xi2)!=1)
continue;
893 auto xc0 = item.subs(xi2==0);
894 auto xc1 = item.coeff(xi2);
897 for(
auto xi3 : xs2) {
898 if(xi3==xi || xi3==xi2)
continue;
902 if(is_zero(xx))
continue;
905 for(
auto item2 : bfe) run2_vec.push_back(item2);
912 ret_vec.push_back(fe);
915 if(run2_vec.size()>0) {
920 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)