8 #include <libqhull_r/qhull_ra.h>
14 vector<vector<int>> QDelaunay(
const ex & pts,
int nshift=1) {
15 vector<vector<int>> ret;
16 int npts = pts.nops();
17 int dim = pts.op(0).nops()-nshift;
22 coordT* cpts = (coordT*)malloc(
sizeof(coordT) * npts * dim);
23 for(
int r=0; r<npts; r++) {
24 for(
int c=0; c<dim; c++) {
25 cpts[r*dim + c] = ex_to<numeric>(pts.op(r).op(c)).to_double();
30 sprintf(opts,
"qhull d Qbb QJ Qt i");
31 FILE* dev_null = fopen(
"/dev/null",
"w");
33 boolT ismalloc =
false;
36 qh_zero(qh, dev_null);
38 int exit_code = qh_new_qhull(qh, dim, npts, cpts, ismalloc, opts, NULL, dev_null);
39 if(exit_code!=0)
throw Error(
"QDelaunay: qhull exit code "+to_string(exit_code));
44 vertexT *vertex, **vertexp;
46 if(!facet->upperdelaunay) {
48 FOREACHvertex_(facet->vertices) {
49 lvec.push_back(qh_pointid(qh, vertex->point));
55 qh_freeqhull(qh, !qh_ALL);
56 qh_memfreeshort(qh, &curlong, &totlong);
57 if (curlong || totlong) {
58 cout <<
"QDelaunay: Non-freed " << totlong <<
" bytes of long memory(" << curlong <<
" pieces)" << endl;
62 cerr <<
ErrColor <<
"QDelaunay: (ret.size()<=0)" <<
RESET << endl;
63 throw Error(
"QDelaunay failed.");
77 vector<matrix>
Triangularize(
const lst & fs_in,
const ex & xs_in,
const lst & nsubs) {
78 int nx = xs_in.nops();
83 for(
int i=0; i<nx; i++) mat(i,i) = 1;
89 for(
int i=0; i<nx; i++) {
90 symbol xi(
"x"+to_string(i));
95 for(
int i=0; i<nx; i++) {
96 fs.append(xs_in.op(i));
97 x2x[xs_in.op(i)] = xs.op(i);
99 for(
int i=0; i<fs.nops(); i++) {
100 lst tls = {fs.op(i), -fs.op(i)};
102 fs.let_op(i) = tls.op(0);
106 fs = ex_to<lst>(
subs(fs,x2x));
112 lst eqs = lst{ xsum==nmax };
113 for(
int i=0; i<nx1; i++) eqs.append(fs.op(is[i])==0);
114 auto sol = lsolve(eqs, xs);
116 auto ps =
subs(xs,ex_to<lst>(sol));
119 ex npi = pi.subs(nsubs);
120 if(!is_a<numeric>(npi)) {
121 cout <<
"Found non-numeric(after nsubs): " << pi.subs(nsubs) << endl;
124 cout << endl << endl;
126 if(npi<0 || npi>nmax) { ok =
false;
break; }
128 if(ok) pts.append(ps);
136 for(
auto const & fi : fs) {
139 for(
auto const & si : cset) {
140 lst lstn, lst0, lstp;
141 for(
auto const & item : si) {
143 for(
int i=0; i<nx; i++) xmap[xs.op(i)] = item.op(i);
144 ex c =
exnormal(fi.subs(xmap).subs(nsubs));
145 if(!is_a<numeric>(c)) {
146 cout <<
"c(after nsbus)=" << c << endl;
147 throw Error(
"TriSector: c is NOT a number.");
149 if(c.is_zero()) lst0.append(item);
150 else if(c>0) lstp.append(item);
151 else lstn.append(item);
153 if(lstn.nops()==0 || lstp.nops()==0) {
157 for(
auto const & item : lst0) {
161 pts_set.insert(lstp);
162 pts_set.insert(lstn);
167 for(
auto const & pts : pts_set) {
168 vector<vector<int>> res;
169 if(pts.nops()>nx) res = QDelaunay(pts.subs(nsubs));
171 vector<int> n_vec(nx);
172 for(
int i=0; i<nx; i++) n_vec[i] = i;
173 res.push_back(n_vec);
175 for(
auto item : res) {
178 for(
int i=0; i<nx; i++) {
179 symbol ci(
"c"+to_string(i));
185 for(
int i=0; i<nx; i++) {
187 for(
int j=0; j<nx; j++) pt_vec[j] = pts.op(item[(i+j)%nx]);
189 for(
int j=1; j<nx; j++) {
191 for(
int k=0; k<nx; k++) eq += c_vec[k] * pt_vec[j][k];
195 ex sol = lsolve(eqs, c_lst);
196 sol =
subs(c_lst, ex_to<lst>(sol)).subs(c2i);
198 for(
int j=0; j<nx; j++) sgn += sol.op(j) * pt_vec[0].op(j);
199 sgn = sgn.subs(nsubs);
200 if(!is_a<numeric>(sgn)) {
201 cout <<
"sgn(after nsubs) = " << sgn << endl;
202 throw Error(
"TriSector: sgn is NOT a number!");
206 for(
int j=0; j<nx; j++) mat(i,j) = sgn * sol.op(j);
208 mats.push_back(mat.inverse());
224 void Triangularize(exvector & FunExp,
const lst & fs,
const ex & xs,
const lst & nsubs) {
227 for(
auto xi : xs) xsum += xi;
228 auto fun_exp_lst = FunExp;
230 for(
auto fun_exp : fun_exp_lst) {
231 for(
auto const & mat : mats) {
232 lst funs = ex_to<lst>(fun_exp.op(0));
233 lst exps = ex_to<lst>(fun_exp.op(1));
234 lst dlts = ex_to<lst>(fun_exp.op(2));
236 for(
int r=0; r<xs.nops(); r++) {
238 for(
int c=0; c<xs.nops(); c++) xr += mat(r,c)*y(c);
241 funs = ex_to<lst>(
subs(funs,x2y));
242 ex det = mat.determinant();
243 ex ndet = det.subs(nsubs);
244 if(!is_a<numeric>(ndet)) {
245 cout <<
"ndet(after nsbus)=" << ndet << endl;
246 throw Error(
"Triangularize: ndet is NOT a number.");
248 if(ndet<0) det = -det;
249 ex ysum = xsum.subs(x2y);
251 for(
int i=0; i<xs.nops(); i++) {
252 ex c = ysum.coeff(y(i));
254 y2x[y(i)] = xs.op(i)/c;
256 funs = ex_to<lst>(
subs(funs,y2x));
259 FunExp.push_back(lst{funs, exps, dlts});
class used to wrap error message
namespace for Numerical integration with Sector Decomposition method
vector< matrix > Triangularize(const lst &fs_in, const ex &xs_in, const lst &nsubs={})
to Triangularize the domain with each xi from 0 to +infinity
void Combinations(int n, int m, std::function< void(const int *)> f)
ex exnormal(const ex &expr, int opt)
normalize a expression
void sort_lst(lst &ilst, bool less=true)
sort the list in less order, or the reverse
lst vec2lst(const exvector &ev)
convert exvector to lst
ex subs(const ex &e, init_list sl)