12 int ep_ldegree(
const ex & e) {
14 auto nd = ee.numer_denom();
15 if(nd.op(0).is_polynomial(
ep) && nd.op(1).is_polynomial(
ep)) {
16 return nd.op(0).ldegree(
ep) - nd.op(1).ldegree(
ep);
18 cout <<
"numer or denom is NOT a polynormial of ep." << endl;
27 Family(
int pn_) :
pn(pn_) { }
30 exmap _sp2x_(
const ex & ips,
const ex &
eps) {
35 if(sp2x.find(ip*ipx)==sp2x.end()) {
38 sp2x[
w*ip*ipx] =
w*xi;
52 bool is_complete(
const ex & props,
const ex & ips,
const ex &
eps) {
53 auto sp2x = _sp2x_(ips,
eps);
54 auto ps =
subs(props, sp2x);
57 for(
int r=0; r<n; r++) {
59 for(
int c=0; c<n; c++) {
60 mat(r,c) = ps.op(c).coeff(xi);
65 bool is_complete(
const ex & props,
const exmap & sp2x) {
66 auto ps =
subs(props, sp2x);
69 for(
int r=0; r<n; r++) {
71 for(
int c=0; c<n; c++) {
72 mat(r,c) = ps.op(c).coeff(xi);
79 bool Exp2AMFLOW::is_loop(
const ex & e) {
80 for(
auto ei :
Internal) if(ei.is_equal(e)) return true;
87If[Length[$ScriptCommandLine]<2, Print["Usage: wolframescript -f "<>ToString[$ScriptCommandLine[[1]]]<>" <n>"];Quit[]];
88current = DirectoryName@If[$FrontEnd===Null,$InputFileName,NotebookFileName[]];
92SetReductionOptions["IBPReducer"->"Kira"];
93ID = ToExpression[$ScriptCommandLine[[2]]];
94PropsInts=Get[FileNameJoin[{current,ToString[ID]<>".m"}]];
96AMFlowInfo["Family"] = Symbol["I"<>ToString[ID]];
97AMFlowInfo["Loop"] = <<Loop>>;
98AMFlowInfo["Leg"] = <<Leg>>;
99AMFlowInfo["Conservation"] = { };
100AMFlowInfo["Replacement"] = <<Replacement>>;
101AMFlowInfo["Propagator"] = PropsInts[[1]]/.<<M2M2>>;
102AMFlowInfo["Numeric"] = <<Numeric>>;
103AMFlowInfo["NThread"] = <<NThread>>;
105integrals = Map[(j[Symbol["I"<>ToString[ID]], Sequence@@#])&, PropsInts[[2]]];
106precision = <<Precision>>;
107epsorder = 2*Length@AMFlowInfo["Loop"]-PropsInts[[3]] + <<Order>>;
108sol = SolveIntegrals[integrals, precision, epsorder];
109Put[sol, FileNameJoin[{current, "sol"<>ToString[ID]<>".m"}]];
134 system((
"mkdir -p "+dir).c_str());
140 cout <<
"Replacing linear propagators ..." << endl;
143 find(res, F(
w1,
w2), pq_fs);
145 for(
auto f : pq_fs) {
146 lst ps = ex_to<lst>(f.op(0));
147 lst ns = ex_to<lst>(f.op(1));
149 for(
int i=0; i<ps.nops(); i++) {
152 if(ps.op(i).has(ip*ip)) {
159 if(!is_a<mul>(pi) || !pi.nops()==2) {
160 cout <<
"prop: " << pi << endl;
161 cout <<
"prop is NOT the form of a*b" << endl;
167 }
else if(ns.op(i)!=0) {
169 cout <<
"n of qi.pi is NOT -1" << endl;
172 auto pa = pi.op(0), pb = pi.op(1);
175 bool ic = is_complete(ps, sp2x);
176 if(!ic && is_loop(pa)) {
178 ic = is_complete(ps, sp2x);
180 if(!ic && is_loop(pb)) {
182 ic = is_complete(ps, sp2x);
185 cout <<
"1st: ic is NOT true!" << endl;
194 }
else if(ns_p.nops()>0) {
195 auto idx =
ex2int(ns_p.op(0));
197 auto pidx = ps.op(idx);
204 bool ic = is_complete(ps, sp2x);
205 if(!ic && is_loop(pa)) {
207 ic = is_complete(ps, sp2x);
209 if(!ic && is_loop(pb)) {
211 ic = is_complete(ps, sp2x);
214 cout <<
"2nd: ic is NOT true!" << endl;
218 auto xps =
subs(ps,sp2x);
219 auto xpidx = pidx.subs(sp2x);
222 cout <<
"xps still has ip" << endl;
223 cout <<
"xps: " << xps << endl;
227 cout <<
"xpidx still has ip" << endl;
228 cout <<
"xpidx: " << xpidx << endl;
233 ex xeq = 0, eq = 0, fres = 0;
235 for(
int ii=0; ii<ps.nops(); ii++) {
237 xeq += yi*xps.op(ii);
240 nn[ii] = ns.op(ii)-1;
241 fres += yi*F(ps, nn);
245 for(
int ii=0; ii<ps.nops(); ii++) {
247 eqs.append(xeq.coeff(xi)==xpidx.coeff(xi));
249 auto sol = lsolve(eqs,ys);
251 if(sol.nops()<1 || sol.has(x(
w))) {
252 cout <<
"wrong sol: " << sol << endl;
255 auto rem = pidx-eq.subs(sol);
256 fres = fres.subs(sol);
258 fres += rem * F(ps, ns);
264 cout <<
"Failed: chk=" << chk << endl;
266 }
else if(!f.op(0).is_equal(ps)) {
267 pq_f2f[f] = F(ps, ns);
270 cout <<
"Failed: chk=" << chk << endl;
275 cout <<
"Collecting ..." << endl;
278 if(e.match(F(
w1,
w2))) {
279 auto itr = pq_f2f.find(e);
280 if(itr==pq_f2f.end())
return e;
281 else return itr->second;
282 }
else return e.map(self);
299 find(res, F(
w1,
w2), fs);
300 map<ex,Family,ex_is_less> p2f;
304 auto itr = p2f.find(f.op(0));
305 if(itr == p2f.end()) {
306 itr = p2f.insert(make_pair(f.op(0), Family(
pn))).first;
309 itr->second.intg.append(f.op(1));
310 f2f[f] = F(itr->second.pn, f.op(1));
314 if(e.match(F(
w1,
w2))) {
315 auto itr = f2f.find(e);
317 cout <<
"F Not Found" << endl;
321 }
else return e.map(self);
324 cout <<
"Exporting res.txt ..." << endl;
329current = If[$FrontEnd===Null,$InputFileName,NotebookFileName[]]//DirectoryName;
332sols = Flatten@Table[Import[FileNameJoin[{current,"sol"<>ToString[i]<>".m"}]], {i,0,<<NN>>}];
333res = C2M@Import[FileNameJoin[{current, "res.txt"}]];
334res = res/.{F[p_, n_] :> j[Symbol["I"<>ToString[p]], Sequence@@n]} /. Dispatch@sols;
342 int tot = p2f.size(), cur = 0;
345 cout <<
"[ " << cur <<
" / " << tot <<
"] pn = " << kv.second.pn << endl;
346 cout << kv.first << endl;
347 cout << kv.second.intg << endl;
350 lst prop = ex_to<lst>(kv.first);
351 auto & f = kv.second;
352 for(
int i=0; i<prop.nops(); i++) {
355 if(prop.op(i).has(ip*ip)) {
361 cout <<
"Propagators: " << prop.op(i) <<
" @ pos: " << i << endl;
362 cout <<
"Integrals: " << f.intg << endl;
369 auto ns = f.intg.op(idx);
370 ex cc = res.coeff(F(f.pn, ns)).subs(Numeric);
371 cc = cc.subs(d==4-2*ep);
372 auto ldeg = ep_ldegree(cc);
377 for(
auto ldeg : order_vec) {
378 if(order>ldeg) order =
ex2int(ldeg);
381 ex2file(lst{ prop, f.intg, order }, dir+
"/"+to_string(f.pn)+
".m");
393using namespace HepLib;
395int main(int argc, char ** argv) {
398 lst Replacement = str2lst("<<Replacement>>");
401 if(argc>1) n = string(argv[1]);
403 garRead("data.gar", data);
404 int tot = ex2int(data["total"]);
407 ex res = data["res"];
409 for(int i=0; i<tot; i++) {
410 ex ri = file2ex(to_string(i)+".out");
411 for(auto item : ri) rules.append(item);
413 res = res.subs(rules).subs(Replacement).subs(d==4-2*ep);
414 res = series_ex(res,ep,ex2int(data["Order"]));
415 res = collect_ex(res, lst{ ep });
416 res = chop(res, str2ex("1E-15"));
417 cout << endl << res << endl << endl;
421 if(pn+1>tot || pn<0) return 0;
424 //amf.Mode = Fit::Modes::All;
426 amf.Replacement = Replacement;
427 amf.Internal = ex_to<lst>(data["Internal"]);
428 amf.External = ex_to<lst>(data["External"]);
430 amf.Propagator = ex_to<lst>(data[n].op(0));
431 amf.Integral = ex_to<lst>(data[n].op(1));
433 int tot_order = 2*amf.Internal.nops() + ex2int(data["Order"]) - ex2int(data[n].op(2));
434 amf.Parallel(ex2int(data["Precision"]), tot_order);
437 for(int i=0; i<amf.Integral.nops(); i++) {
438 rules.append(F(pn, amf.Integral.op(i)) == amf.NIntegral.op(i));
441 ex2file(rules, n+".out");
449 system((
"mkdir -p "+dir).c_str());
453 map<string, ex> data_export;
458 data_export[
"Order"] =
Order;
465 find(res, F(
w1,
w2), fs);
466 map<ex,Family,ex_is_less> p2f;
470 auto itr = p2f.find(f.op(0));
471 if(itr == p2f.end()) {
472 itr = p2f.insert(make_pair(f.op(0), Family(
pn))).first;
475 itr->second.intg.append(f.op(1));
476 f2f[f] = F(itr->second.pn, f.op(1));
479 res = MapFunction([&](
const ex & e, MapFunction &self)->ex{
480 if(e.match(F(
w1,
w2))) {
481 auto itr = f2f.find(e);
483 cout <<
"F Not Found" << endl;
487 }
else return e.map(self);
489 data_export[
"res"] = res;
491 int tot = p2f.size();
493 lst prop = ex_to<lst>(kv.first);
494 auto & f = kv.second;
498 auto ns = f.intg.op(idx);
499 ex cc = res.coeff(F(f.pn, ns)).subs(Replacement);
500 cc = cc.subs(d==4-2*ep);
501 auto ldeg = ep_ldegree(cc);
506 for(
auto ldeg : order_vec) {
507 if(order>ldeg) order =
ex2int(ldeg);
510 data_export[to_string(f.pn)] = lst{ prop, f.intg, order };
512 data_export[
"total"] = tot;
514 garWrite(dir+
"/data.gar", data_export);
516 str2file(
"heplib++ -o AMF AMF.cpp\nseq 0 "+to_string(tot-1)+
" | parallel -j 4 ./AMF {}\n./AMF res\n", dir+
"/run.sh");
void Export(const ex &expr, const string &dir)
void Export(const ex &expr, const string &dir)
class to wrap map_function of GiNaC
void ex2file(const ex &expr, string filename)
export expression file
ex collect_ex(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica
ex F2ex(const ex &expr_in)
convert F(ps, ns) to normal ex, ns is like FIRE convention
map< string, int > GiNaC_Parallel_Verb
ex exnormal(const ex &expr, int opt)
normalize a expression
void string_replace_all(string &str, const string &from, const string &to)
void garWrite(const string &garfn, const map< string, ex > &resMap)
garWrite to write the string-key map to the archive
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
void str2file(const string &ostr, string filename)
export string to a file
exvector GiNaC_Parallel(int ntotal, std::function< ex(int)> f, const string &key)
GiNaC Parallel Evaluation using fork.
int ex2int(ex num)
ex to integer
ex subs(const ex &e, init_list sl)