HepLib
Loading...
Searching...
No Matches
SecDecG.cpp
Go to the documentation of this file.
1
6extern "C" {
7 #include <libqhull_r/qhull_ra.h>
8}
9#include "SD.h"
10
11namespace 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
#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
matrix mat_sub(matrix mat, int r, int nr, int c, int nc)
Definition SecDecG.cpp:28
vector< int > zero_row_index(const matrix &mat)
Definition SecDecG.cpp:13
bool is_zero_row(const matrix &mat, int r)
Definition SecDecG.cpp:38
matrix remove_zero_rows(const matrix &mat)
Definition SecDecG.cpp:46
vector< vector< int > > QHull(const matrix &dc, int dim)
Definition SecDecG.cpp:63
const char * ErrColor
Definition BASIC.cpp:246
bool using_cache
Definition Init.cpp:156
ex w
Definition Init.cpp:93
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:157