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 if(ps.has(xi)) { ok =
false;
break; }
123 ex npi = pi.subs(nsubs);
124 if(!is_a<numeric>(npi)) {
125 cout <<
"Found non-numeric(after nsubs): " << pi.subs(nsubs) << endl;
128 cout << endl << endl;
130 if(npi<0 || npi>nmax) { ok =
false;
break; }
132 if(ok) pts.append(ps);
141 for(
auto const & fi : fs) {
144 for(
auto const & si : cset) {
145 lst lstn, lst0, lstp;
146 for(
auto const & item : si) {
148 for(
int i=0; i<nx; i++) xmap[xs.op(i)] = item.op(i);
149 ex c =
exnormal(fi.subs(xmap).subs(nsubs));
150 if(!is_a<numeric>(c)) {
151 cout <<
"c(after nsbus)=" << c << endl;
152 throw Error(
"TriSector: c is NOT a number.");
154 if(c.is_zero()) lst0.append(item);
155 else if(c>0) lstp.append(item);
156 else lstn.append(item);
158 if(lstn.nops()==0 || lstp.nops()==0) {
162 for(
auto const & item : lst0) {
166 pts_set.insert(lstp);
167 pts_set.insert(lstn);
172 for(
auto const & pts : pts_set) {
173 vector<vector<int>> res;
174 if(pts.nops()>nx) res = QDelaunay(pts.subs(nsubs));
176 vector<int> n_vec(nx);
177 for(
int i=0; i<nx; i++) n_vec[i] = i;
178 res.push_back(n_vec);
180 for(
auto item : res) {
183 for(
int i=0; i<nx; i++) {
184 symbol ci(
"c"+to_string(i));
190 for(
int i=0; i<nx; i++) {
192 for(
int j=0; j<nx; j++) pt_vec[j] = pts.op(item[(i+j)%nx]);
194 for(
int j=1; j<nx; j++) {
196 for(
int k=0; k<nx; k++) eq += c_vec[k] * pt_vec[j][k];
200 ex sol = lsolve(eqs, c_lst);
201 sol =
subs(c_lst, ex_to<lst>(sol)).subs(c2i);
203 for(
int j=0; j<nx; j++) sgn += sol.op(j) * pt_vec[0].op(j);
204 sgn = sgn.subs(nsubs);
205 if(!is_a<numeric>(sgn)) {
206 cout <<
"sgn(after nsubs) = " << sgn << endl;
207 throw Error(
"TriSector: sgn is NOT a number!");
211 for(
int j=0; j<nx; j++) mat(i,j) = sgn * sol.op(j);
213 if(mat.determinant()!=0) {
214 mats.push_back(mat.inverse());
231 void Triangularize(exvector & FunExp,
const lst & fs,
const ex & xs,
const lst & nsubs) {
234 for(
auto xi : xs) xsum += xi;
235 auto fun_exp_lst = FunExp;
237 for(
auto fun_exp : fun_exp_lst) {
238 for(
auto const & mat : mats) {
239 lst funs = ex_to<lst>(fun_exp.op(0));
240 lst exps = ex_to<lst>(fun_exp.op(1));
241 lst dlts = ex_to<lst>(fun_exp.op(2));
243 for(
int r=0; r<xs.nops(); r++) {
245 for(
int c=0; c<xs.nops(); c++) xr += mat(r,c)*y(c);
248 funs = ex_to<lst>(
subs(funs,x2y));
249 ex det = mat.determinant();
250 ex ndet = det.subs(nsubs);
251 if(!is_a<numeric>(ndet)) {
252 cout <<
"ndet(after nsbus)=" << ndet << endl;
253 throw Error(
"Triangularize: ndet is NOT a number.");
255 if(ndet<0) det = -det;
256 ex ysum = xsum.subs(x2y);
258 for(
int i=0; i<xs.nops(); i++) {
259 ex c = ysum.coeff(y(i));
261 y2x[y(i)] = xs.op(i)/c;
263 funs = ex_to<lst>(
subs(funs,y2x));
266 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)