HepLib
SecDecG.cpp
Go to the documentation of this file.
1 
6 extern "C" {
7  #include <libqhull_r/qhull_ra.h>
8 }
9 #include "SD.h"
10 
11 namespace HepLib::SD {
12 
13  inline vector<int> zero_row_index(const matrix &mat) {
14  vector<int> ret;
15  for(int r=0; r<mat.rows(); r++) {
16  bool iszero = true;
17  for(int c=0; c<mat.cols(); c++) {
18  if(!mat(r,c).is_zero()) {
19  iszero = false;
20  break;
21  }
22  }
23  if(iszero) ret.push_back(r);
24  }
25  return ret;
26  }
27 
28  inline matrix mat_sub(matrix mat, int r, int nr, int c, int nc) {
29  matrix ret(nr, nc);
30  for(int ir=0; ir<nr; ir++) {
31  for(int ic=0; ic<nc; ic++) {
32  ret(ir, ic) = mat(r+ir, c+ic);
33  }
34  }
35  return ret;
36  }
37 
38  inline bool is_zero_row(const matrix &mat, int r) {
39  if(r>=mat.rows()) throw Error("is_zero_row, r>=mat.rows()");
40  for(int c=0; c<mat.cols(); c++) {
41  if(mat(r, c) !=0 ) return false;
42  }
43  return true;
44  }
45 
46  inline matrix remove_zero_rows(const matrix &mat) {
47  vector<int> zri = zero_row_index(mat);
48  if(zri.size()<1) return mat;
49  matrix ret(mat.rows()-zri.size(), mat.cols());
50 
51  int cr = 0;
52  for(int r=0; r<mat.rows(); r++) {
53  bool iszero = find(zri.begin(), zri.end(), r) != zri.end();
54  if(iszero) continue;
55  for(int c=0; c<mat.cols(); c++) {
56  ret(cr, c) = mat(r, c);
57  }
58  cr++;
59  }
60  return ret;
61  }
62 
63  inline vector<vector<int>> QHull(const matrix &dc, int dim) {
64  if(dim >= dc.cols()) return SecDecG::RunQHull(dc);
65 
66  matrix mdc(dc.rows()-1, dc.cols());
67  for(int r=0; r<mdc.rows(); r++) {
68  for(int c=0; c<mdc.cols(); c++) mdc(r, c) = dc(r+1, c) - dc(0, c);
69  }
70 
71  int n = mdc.cols();
72  mdc = mdc.transpose();
73  for(int i=0; i<n; i++) {
74  if(is_zero_row(mdc, i)) continue;
75  int pos = -1;
76  for(int c=0; c<mdc.cols(); c++) {
77  if(mdc(i,c)!=0) {
78  pos = c;
79  break;
80  }
81  }
82 
83  for(int j=i+1; j<n; j++) {
84  if(mdc(j,pos)!=0) {
85  matrix matj = mat_sub(mdc, j,1, 0,mdc.cols());
86  for(int c=0; c<mdc.cols(); c++) {
87  mdc(j, c)=matj(0,c) - mdc(i,c) * matj(0, pos)/mdc(i, pos);
88  }
89  }
90  }
91  }
92 
93  mdc = remove_zero_rows(mdc);
94  mdc = mdc.transpose();
95 
96  matrix tmp(mdc.rows()+1, mdc.cols());
97  for(int r=0; r<mdc.rows(); r++) {
98  for(int c=0; c<mdc.cols(); c++) {
99  tmp(r+1,c) = mdc(r,c);
100  }
101  }
102  for(int c=0; c<mdc.cols(); c++) {
103  tmp(0,c) = 0;
104  }
105  mdc = tmp;
106 
107  ex all_lcm = 1;
108  for(int r=0; r<mdc.rows(); r++) {
109  for(int c=0; c<mdc.cols(); c++) {
110  all_lcm = lcm(all_lcm, normal(mdc(r,c)).numer_denom().op(1));
111  //all_lcm = lcm(all_lcm, fermat_numer_denom(mdc(r,c)).op(1));
112  }
113  }
114  mdc = mdc.mul_scalar(all_lcm);
115  return SecDecG::RunQHull(mdc);
116  }
117 
118  static vector<matrix> Simplexify(const matrix &dc, int dim) {
119  static map<ex,vector<matrix>,ex_is_less> cache;
120  if(using_cache && cache_limit>0 && cache.size() > cache_limit) cache.clear();
121  ex key = lst{dc,dim};
122  if(using_cache && cache.find(key)!=cache.end()) return cache[key];
123 
124  int min = -1;
125  int i = 0;
126  auto tmat = dc;
127  vector<matrix> ret;
128  while (i<tmat.rows() && (min<0 || min>2)) {
129  vector<matrix> tmp_ret;
130  if (true) { // expand original Simplexify function
131  matrix dc = tmat;
132  if(dc.rows()-dim<=0) {
133  cerr << ErrColor << "Simplexify: (dc.rows()-dim<=0)" << RESET << endl;
134  throw Error("Simplexify failed.");
135  }
136 
137  if(dc.rows() == dim+1) tmp_ret.push_back(dc);
138  else {
139  auto tmp = QHull(dc, dim);
140  for(auto vi : tmp) {
141  bool found = find(vi.begin(), vi.end(), 0) != vi.end();
142  if(found) continue;
143  matrix mat(vi.size(), dc.cols());
144  for(int r=0; r<mat.rows(); r++) {
145  for(int c=0; c<mat.cols(); c++) mat(r,c) = dc(vi[r],c);
146  }
147  auto tmp = Simplexify(mat, dim-1);
148  for(auto it : tmp) {
149  matrix mat(it.rows()+1, it.cols());
150  for(int r=1; r<mat.rows(); r++) {
151  for(int c=0; c<mat.cols(); c++) mat(r,c) = it(r-1,c);
152  }
153  for(int c=0; c<mat.cols(); c++) mat(0,c) = dc(0,c);
154  tmp_ret.push_back(mat);
155  }
156  }
157  }
158  }
159 
160  if(tmp_ret.size()<min || min<0) {
161  min = tmp_ret.size();
162  ret = tmp_ret;
163  }
164  i++;
165  matrix tmp(tmat.rows(), tmat.cols());
166  for(int r=1; r<tmat.rows(); r++) {
167  for(int c=0; c<tmat.cols(); c++) tmp(r,c) = tmat(r-1, c);
168  }
169  for(int c=0; c<tmat.cols(); c++) tmp(0,c) = tmat(tmat.rows()-1, c);
170  tmat = tmp;
171  }
172  if(using_cache) cache[key]=ret;
173  return ret;
174  }
175 
176  vector<vector<int>> SecDecG::RunQHull(const matrix &pts) {
177  vector<vector<int>> ret;
178  int npts = pts.rows();
179  int dim = pts.cols();
180  ex imax = -1;
181  for(int r=0; r<npts; r++) {
182  for(int c=0; c<dim; c++) {
183  if(imax<abs(pts(r,c))) imax = abs(pts(r,c));
184  }
185  }
186 
187  qhT qh_qh;
188  qhT *qh= &qh_qh;
189  coordT* cpts = (coordT*)malloc(sizeof(coordT) * npts * dim);
190  for(int r=0; r<npts; r++) {
191  for(int c=0; c<dim; c++) {
192  if(imax<500) cpts[r*dim + c] = ex_to<numeric>(pts(r,c)).to_int();
193  else cpts[r*dim + c] = ex_to<numeric>(pts(r,c)).to_double();
194  }
195  }
196 
197  char opts[32];
198  sprintf(opts, "qhull Fv");
199  FILE* dev_null = fopen("/dev/null", "w");
200  int curlong, totlong;
201  boolT ismalloc = false;
202  QHULL_LIB_CHECK
203  qh_zero(qh, dev_null);
204  int exit_code = qh_new_qhull(qh, dim, npts, cpts, ismalloc, opts, NULL, dev_null);
205  if(exit_code!=0) {
206  qh_freeqhull(qh, !qh_ALL);
207  qh_memfreeshort(qh, &curlong, &totlong);
208  char opts[32];
209  sprintf(opts, "qhull QbB Fv");
210  qh_zero(qh, dev_null);
211  exit_code = qh_new_qhull(qh, dim, npts, cpts, ismalloc, opts, NULL, dev_null);
212  if(exit_code!=0) {
213  qh_freeqhull(qh, !qh_ALL);
214  qh_memfreeshort(qh, &curlong, &totlong);
215  char opts[32];
216  sprintf(opts, "qhull QJ Fv");
217  qh_zero(qh, dev_null);
218  exit_code = qh_new_qhull(qh, dim, npts, cpts, ismalloc, opts, NULL, dev_null);
219  if(exit_code!=0) {
220  fclose(dev_null);
221  free(cpts);
222  qh_freeqhull(qh, !qh_ALL);
223  qh_memfreeshort(qh, &curlong, &totlong);
224  throw Error("RuhQHull: qhull exit code "+to_string(exit_code));
225  }
226  }
227  }
228  fclose(dev_null);
229  free(cpts);
230 
231  facetT *facet;
232  vertexT *vertex, **vertexp;
233  FORALLfacets {
234  vector<int> lvec;
235  FOREACHvertex_(facet->vertices) {
236  lvec.push_back(qh_pointid(qh, vertex->point));
237  }
238  ret.push_back(lvec);
239  }
240 
241  qh_freeqhull(qh, !qh_ALL);
242  qh_memfreeshort(qh, &curlong, &totlong);
243  if (curlong || totlong) {
244  cout << "Qhull: Non-freed " << totlong << " bytes of long memory(" << curlong << " pieces)" << endl;
245  }
246 
247  if(ret.size()<=0) {
248  cerr << ErrColor << "RunQHull: (ret.size()<=0)" << RESET << endl;
249  throw Error("SecDecG::RunQHull failed.");
250  }
251 
252  return ret;
253  }
254 
255  vector<matrix> SecDecG::ZeroFaces(const matrix &pts) {
256  if(pts.rows()<=0) {
257  cerr << ErrColor << "ZeroFaces: (pts.rows()<=0)" << RESET << endl;
258  throw Error("SecDecG::ZeroFaces failed (1).");
259  }
260  auto zri = zero_row_index(pts);
261  if(zri.size() <= 0) {
262  cerr << ErrColor << "ZeroFaces: (zri.size() <= 0)" << RESET << endl;
263  throw Error("SecDecG::ZeroFaces failed.");
264  }
265  int zpos = zri[0];
266  auto QH = RunQHull(pts);
267  vector<matrix> ret;
268  for(auto vi : QH) {
269  bool iszero = find(vi.begin(), vi.end(), zpos) != vi.end();
270  if(iszero) {
271  matrix zmat(vi.size(), pts.cols());
272  for(int r=0; r<zmat.rows(); r++) {
273  for(int c=0; c<zmat.cols(); c++) {
274  zmat(r, c) = pts(vi[r], c);
275  }
276  }
277  ret.push_back(zmat);
278  }
279  }
280  return ret;
281  }
282 
283  matrix SecDecG::NormalVectors(const vector<matrix> &zfs) {
284  int ncols = zfs[0].cols();
285  int nrows = zfs.size();
286  matrix ret(nrows, ncols);
287  for(int ii=0; ii<nrows; ii++) {
288 
289  matrix dir;
290  if(ii==0) {
291  dir = mat_sub(remove_zero_rows(zfs[1]), 0, 1, 0, ncols);
292  } else {
293  dir = mat_sub(remove_zero_rows(zfs[0]), 0, 1, 0, ncols);
294  }
295 
296  matrix tmat = remove_zero_rows(zfs[ii]);
297  if(tmat.rows() >= zfs[ii].rows()) {
298  cerr << ErrColor << "NormalVectors: (tmat.rows() >= zfs[ii].rows())" << RESET << endl;
299  throw Error("SecDecG::NormalVectors failed (1).");
300  }
301 
302  for(int ti=0; ti<tmat.rows(); ti++) {
303  int pos = -1;
304  for(int tc=0; tc<tmat.cols(); tc++) {
305  if(tmat(ti, tc) !=0 ) {
306  pos = tc;
307  break;
308  }
309  }
310  if(pos == -1) continue;
311 
312  for(int tj=ti+1; tj<tmat.rows(); tj++) {
313  if(tmat(tj,pos)!=0) {
314  matrix matj = mat_sub(tmat, tj,1, 0,tmat.cols());
315  for(int tc=0; tc<tmat.cols(); tc++) {
316  tmat(tj, tc)=tmat(ti,pos)*matj(0,tc)-matj(0,pos)*tmat(ti,tc);
317  }
318  }
319  }
320  }
321 
322  tmat = remove_zero_rows(tmat);
323  if(tmat.rows()!=tmat.cols()-1) {
324  cerr << ErrColor << "NormalVectors: (tmat.rows()!=tmat.cols()-1)" << RESET << endl;
325  throw Error("SecDecG::NormalVectors failed.");
326  }
327  matrix tmat2(tmat.cols(), tmat.cols());
328  for(int r=0; r<tmat.rows(); r++) {
329  for(int c=0; c<tmat.cols(); c++) {
330  tmat2(r,c) = tmat(r,c);
331  }
332  }
333 
334  for(int c=0; c<tmat.cols(); c++) {
335  tmat2(tmat.cols()-1,c) = 1;
336  }
337  tmat = tmat2;
338 
339  auto det = tmat.determinant();
340  matrix vec(tmat.cols(), 1);
341  vec(tmat.cols()-1, 0) = det;
342  vec = tmat.inverse(solve_algo::gauss).mul(vec);
343  det = 0;
344  for(int r=0; r<vec.rows(); r++) {
345  det = gcd(det, vec(r,0));
346  }
347 
348  for(int r=0; r<vec.rows(); r++) {
349  vec(r,0) = vec(r,0)/det;
350  }
351 
352  if(dir.mul(vec)(0,0) < 0) vec=vec.mul_scalar(-1);
353 
354  for(int r=0; r<vec.rows(); r++) {
355  ret(ii,r) = vec(r,0);
356  }
357  }
358  return ret;
359  }
360 
361  matrix SecDecG::DualCone(const matrix &pts) {
362  auto zfs = ZeroFaces(pts);
363  if(zfs.size()<1 || zfs.size()<pts.cols()) return matrix(0,0);
364  auto nvs = NormalVectors(zfs);
365  ex sum_vec[nvs.rows()];
366  ex sum_lcm = 1;
367  for(int r=0; r<nvs.rows(); r++) {
368  sum_vec[r] = 0;
369  for(int c=0; c<nvs.cols(); c++) sum_vec[r] += nvs(r,c);
370  sum_lcm = lcm(sum_lcm, sum_vec[r]);
371  }
372 
373  matrix ret(nvs.rows(), nvs.cols());
374  for(int r=0; r<nvs.rows(); r++) {
375  for(int c=0; c<nvs.cols(); c++) ret(r, c) = sum_lcm/sum_vec[r]*nvs(r,c);
376  }
377  return ret;
378  }
379 
380  vector<matrix> SecDecG::SimplexCones(matrix pts) {
381  auto ds = DualCone(pts);
382  if(ds.rows() == 0) return vector<matrix>();
383 
384  if(ds.rows() < ds.cols()) {
385  cerr << ErrColor << "SimplexCones: (ds.rows() < ds.cols())" << RESET << endl;
386  throw Error("SecDecG::SimplexCones failed.");
387  }
388  if(ds.rank()<ds.cols()) return vector<matrix>();
389  return Simplexify(ds, ds.cols()-1);
390  }
391 
392  // return a replacement/transformation, using x(-1) as key for determinant
393  vector<exmap> SecDecG::x2y(const ex &xpol) {
394  if(xpol.has(y(w))) throw Error("SecDecG::x2y failed with y(w) found.");
395  auto cvs = collect_lst(xpol, x(w));
396  exvector vpols;
397  lst xpol2;
398  for(auto cv : cvs) {
399  if(is_zero(expand(cv.op(0)))) continue;
400  vpols.push_back(cv.op(1));
401  xpol2.append(cv.op(1));
402  }
403  xpol2.sort();
404  xpol2.unique();
405  auto xs = get_xy_from(xpol2);
406  auto nx = xs.size();
407  auto np = vpols.size();
408 
409  if(nx<2 || np<2) {
410  vector<exmap> vmap;
411  exmap nmap;
412  nmap[x(-1)] = 1;
413  for(int i=0; i<xs.size(); i++) nmap[xs[i]] = y(i);
414  vmap.push_back(nmap);
415  return vmap;
416  }
417 
418  sort(vpols.begin(), vpols.end(), [&xs](const auto &ain, const auto &bin) {
419  //auto a=ain; auto b=bin; // < < <
420  auto a=bin; auto b=ain; // > > >
421  int tai=0, tbi=0;
422  int ab = 0;
423  for(auto xi : xs) {
424  tai += a.degree(xi);
425  tbi += b.degree(xi);
426  if(ab==0 && tai!=tbi) ab = (tai<tbi) ? 1 : -1;
427  }
428  if(tai!=tbi) return (tai<tbi);
429  if(ab!=0) return (ab>0);
430  return ex_is_less()(a,b);
431  });
432 
433  matrix deg_mat(np, nx);
434  for(int r=0; r<np; r++) {
435  auto tmp = vpols[r];
436  for(int c=0; c<nx; c++) {
437  deg_mat(r, c) = tmp.degree(xs[c]);
438  }
439  }
440 
441  vector<matrix> vmat;
442  for(int r=0; r<deg_mat.rows(); r++) {
443  matrix tmp(deg_mat.rows()+xs.size(), deg_mat.cols());
444  for(int rr=0; rr<deg_mat.rows(); rr++) {
445  for(int c=0; c<deg_mat.cols(); c++) tmp(rr,c) = deg_mat(rr,c) - deg_mat(r, c);
446  }
447 
448  for(int rr=0; rr<tmp.cols(); rr++) {
449  tmp(rr+deg_mat.rows(),rr) = 1;
450  }
451  auto sc = SimplexCones(tmp);
452  for(auto isc : sc) vmat.push_back(isc);
453  }
454 
455  vector<map<ex,ex,ex_is_less>> ret;
456  for(int vi=0; vi<vmat.size(); vi++) {
457  matrix &tmp = vmat[vi];
458  for(int r=0; r<tmp.rows(); r++) {
459  ex row_gcd = 0;
460  for(int c=0; c<tmp.cols(); c++) row_gcd = gcd(row_gcd, tmp(r, c));
461  for(int c=0; c<tmp.cols(); c++) tmp(r, c) = tmp(r, c)/row_gcd;
462  }
463  if(tmp.determinant()<0) {
464  ex row0[tmp.cols()];
465  for(int c=0; c<tmp.cols(); c++) {
466  row0[c] = tmp(0, c);
467  tmp(0, c) = tmp(1, c);
468  }
469  for(int c=0; c<tmp.cols(); c++) tmp(1,c) = row0[c];
470  }
471 
472  tmp = tmp.transpose();
473  matrix Dxy(nx, nx);
474  exmap transmap;
475  for(int n=0; n<nx; n++) {
476  ex tt = 1;
477  for(int m=0; m<nx; m++) {
478  tt = tt*pow(y(m), tmp(n,m));
479  }
480  transmap[xs[n]] = tt;
481  for(int m=0; m<nx; m++) Dxy(n, m) = diff_ex(tt, y(m));
482  }
483  transmap[x(-1)] = Dxy.determinant();
484  ret.push_back(transmap);
485  }
486 
487  vmat.clear();
488  vmat.shrink_to_fit();
489  return ret;
490  }
491 
492 
493 }
int * a
Definition: Functions.cpp:234
#define RESET
Definition: BASIC.h:79
SecDec header file.
class used to wrap error message
Definition: BASIC.h:242
vector< exmap > x2y(const ex &xpol) override
Definition: SecDecG.cpp:393
static vector< vector< int > > RunQHull(const matrix &pts)
Definition: SecDecG.cpp:176
namespace for Numerical integration with Sector Decomposition method
Definition: AsyMB.cpp:10
exvector get_xy_from(ex pol)
Definition: Helpers.cpp:14
vector< vector< int > > QHull(const matrix &dc, int dim)
Definition: SecDecG.cpp:63
matrix mat_sub(matrix mat, int r, int nr, int c, int nc)
Definition: SecDecG.cpp:28
bool is_zero_row(const matrix &mat, int r)
Definition: SecDecG.cpp:38
vector< int > zero_row_index(const matrix &mat)
Definition: SecDecG.cpp:13
matrix remove_zero_rows(const matrix &mat)
Definition: SecDecG.cpp:46
const char * ErrColor
Definition: BASIC.cpp:246
bool using_cache
Definition: Init.cpp:153
ex w
Definition: Init.cpp:90
lst collect_lst(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica, reture the lst { {c1,v1}, {c2,v2}, ... }
Definition: BASIC.cpp:1222
ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand)
the differential like Mathematica
Definition: BASIC.cpp:1063
long long cache_limit
Definition: Init.cpp:154