7 #include <libqhull_r/qhull_ra.h>
15 for(
int r=0; r<mat.rows(); r++) {
17 for(
int c=0; c<mat.cols(); c++) {
18 if(!mat(r,c).is_zero()) {
23 if(iszero) ret.push_back(r);
28 inline matrix
mat_sub(matrix mat,
int r,
int nr,
int c,
int 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);
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;
48 if(zri.size()<1)
return mat;
49 matrix ret(mat.rows()-zri.size(), mat.cols());
52 for(
int r=0; r<mat.rows(); r++) {
53 bool iszero = find(zri.begin(), zri.end(), r) != zri.end();
55 for(
int c=0; c<mat.cols(); c++) {
56 ret(cr, c) = mat(r, c);
63 inline vector<vector<int>>
QHull(
const matrix &dc,
int dim) {
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);
72 mdc = mdc.transpose();
73 for(
int i=0; i<n; i++) {
76 for(
int c=0; c<mdc.cols(); c++) {
83 for(
int j=i+1; j<n; j++) {
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);
94 mdc = mdc.transpose();
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);
102 for(
int c=0; c<mdc.cols(); c++) {
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));
114 mdc = mdc.mul_scalar(all_lcm);
118 static vector<matrix> Simplexify(
const matrix &dc,
int dim) {
119 static map<ex,vector<matrix>,ex_is_less> cache;
121 ex key = lst{dc,dim};
122 if(
using_cache && cache.find(key)!=cache.end())
return cache[key];
128 while (i<tmat.rows() && (min<0 || min>2)) {
129 vector<matrix> tmp_ret;
132 if(dc.rows()-dim<=0) {
133 cerr <<
ErrColor <<
"Simplexify: (dc.rows()-dim<=0)" <<
RESET << endl;
134 throw Error(
"Simplexify failed.");
137 if(dc.rows() == dim+1) tmp_ret.push_back(dc);
139 auto tmp =
QHull(dc, dim);
141 bool found = find(vi.begin(), vi.end(), 0) != vi.end();
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);
147 auto tmp = Simplexify(mat, dim-1);
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);
153 for(
int c=0; c<mat.cols(); c++) mat(0,c) = dc(0,c);
154 tmp_ret.push_back(mat);
160 if(tmp_ret.size()<min || min<0) {
161 min = tmp_ret.size();
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);
169 for(
int c=0; c<tmat.cols(); c++) tmp(0,c) = tmat(tmat.rows()-1, c);
177 vector<vector<int>> ret;
178 int npts = pts.rows();
179 int dim = pts.cols();
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));
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();
198 sprintf(opts,
"qhull Fv");
199 FILE* dev_null = fopen(
"/dev/null",
"w");
200 int curlong, totlong;
201 boolT ismalloc =
false;
203 qh_zero(qh, dev_null);
204 int exit_code = qh_new_qhull(qh, dim, npts, cpts, ismalloc, opts, NULL, dev_null);
206 qh_freeqhull(qh, !qh_ALL);
207 qh_memfreeshort(qh, &curlong, &totlong);
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);
213 qh_freeqhull(qh, !qh_ALL);
214 qh_memfreeshort(qh, &curlong, &totlong);
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);
222 qh_freeqhull(qh, !qh_ALL);
223 qh_memfreeshort(qh, &curlong, &totlong);
224 throw Error(
"RuhQHull: qhull exit code "+to_string(exit_code));
232 vertexT *vertex, **vertexp;
235 FOREACHvertex_(facet->vertices) {
236 lvec.push_back(qh_pointid(qh, vertex->point));
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;
248 cerr <<
ErrColor <<
"RunQHull: (ret.size()<=0)" <<
RESET << endl;
249 throw Error(
"SecDecG::RunQHull failed.");
255 vector<matrix> SecDecG::ZeroFaces(
const matrix &pts) {
257 cerr <<
ErrColor <<
"ZeroFaces: (pts.rows()<=0)" <<
RESET << endl;
258 throw Error(
"SecDecG::ZeroFaces failed (1).");
261 if(zri.size() <= 0) {
262 cerr <<
ErrColor <<
"ZeroFaces: (zri.size() <= 0)" <<
RESET << endl;
263 throw Error(
"SecDecG::ZeroFaces failed.");
269 bool iszero = find(vi.begin(), vi.end(), zpos) != vi.end();
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);
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++) {
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).");
302 for(
int ti=0; ti<tmat.rows(); ti++) {
304 for(
int tc=0; tc<tmat.cols(); tc++) {
305 if(tmat(ti, tc) !=0 ) {
310 if(pos == -1)
continue;
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);
323 if(tmat.rows()!=tmat.cols()-1) {
324 cerr <<
ErrColor <<
"NormalVectors: (tmat.rows()!=tmat.cols()-1)" <<
RESET << endl;
325 throw Error(
"SecDecG::NormalVectors failed.");
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);
334 for(
int c=0; c<tmat.cols(); c++) {
335 tmat2(tmat.cols()-1,c) = 1;
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);
344 for(
int r=0; r<vec.rows(); r++) {
345 det = gcd(det, vec(r,0));
348 for(
int r=0; r<vec.rows(); r++) {
349 vec(r,0) = vec(r,0)/det;
352 if(dir.mul(vec)(0,0) < 0) vec=vec.mul_scalar(-1);
354 for(
int r=0; r<vec.rows(); r++) {
355 ret(ii,r) = vec(r,0);
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()];
367 for(
int r=0; r<nvs.rows(); r++) {
369 for(
int c=0; c<nvs.cols(); c++) sum_vec[r] += nvs(r,c);
370 sum_lcm = lcm(sum_lcm, sum_vec[r]);
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);
380 vector<matrix> SecDecG::SimplexCones(matrix pts) {
381 auto ds = DualCone(pts);
382 if(ds.rows() == 0)
return vector<matrix>();
384 if(ds.rows() < ds.cols()) {
385 cerr <<
ErrColor <<
"SimplexCones: (ds.rows() < ds.cols())" <<
RESET << endl;
386 throw Error(
"SecDecG::SimplexCones failed.");
388 if(ds.rank()<ds.cols())
return vector<matrix>();
389 return Simplexify(ds, ds.cols()-1);
394 if(xpol.has(y(
w)))
throw Error(
"SecDecG::x2y failed with y(w) found.");
399 if(is_zero(expand(cv.op(0))))
continue;
400 vpols.push_back(cv.op(1));
401 xpol2.append(cv.op(1));
407 auto np = vpols.size();
413 for(
int i=0; i<xs.size(); i++) nmap[xs[i]] = y(i);
414 vmap.push_back(nmap);
418 sort(vpols.begin(), vpols.end(), [&xs](
const auto &ain,
const auto &bin) {
420 auto a=bin; auto b=ain;
426 if(ab==0 && tai!=tbi) ab = (tai<tbi) ? 1 : -1;
428 if(tai!=tbi) return (tai<tbi);
429 if(ab!=0)
return (ab>0);
430 return ex_is_less()(
a,b);
433 matrix deg_mat(np, nx);
434 for(
int r=0; r<np; r++) {
436 for(
int c=0; c<nx; c++) {
437 deg_mat(r, c) = tmp.degree(xs[c]);
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);
448 for(
int rr=0; rr<tmp.cols(); rr++) {
449 tmp(rr+deg_mat.rows(),rr) = 1;
451 auto sc = SimplexCones(tmp);
452 for(
auto isc : sc) vmat.push_back(isc);
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++) {
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;
463 if(tmp.determinant()<0) {
465 for(
int c=0; c<tmp.cols(); c++) {
467 tmp(0, c) = tmp(1, c);
469 for(
int c=0; c<tmp.cols(); c++) tmp(1,c) = row0[c];
472 tmp = tmp.transpose();
475 for(
int n=0; n<nx; n++) {
477 for(
int m=0; m<nx; m++) {
478 tt = tt*pow(y(m), tmp(n,m));
480 transmap[xs[n]] = tt;
481 for(
int m=0; m<nx; m++) Dxy(n, m) =
diff_ex(tt, y(m));
483 transmap[x(-1)] = Dxy.determinant();
484 ret.push_back(transmap);
488 vmat.shrink_to_fit();
class used to wrap error message
vector< exmap > x2y(const ex &xpol) override
static vector< vector< int > > RunQHull(const matrix &pts)
namespace for Numerical integration with Sector Decomposition method
exvector get_xy_from(ex pol)
vector< vector< int > > QHull(const matrix &dc, int dim)
matrix mat_sub(matrix mat, int r, int nr, int c, int nc)
bool is_zero_row(const matrix &mat, int r)
vector< int > zero_row_index(const matrix &mat)
matrix remove_zero_rows(const matrix &mat)
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}, ... }
ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand)
the differential like Mathematica