HepLib
Loading...
Searching...
No Matches
Triangularize.cpp
Go to the documentation of this file.
1
6#include "SD.h"
7extern "C" {
8 #include <libqhull_r/qhull_ra.h>
9}
10
11namespace HepLib::SD {
12
13 namespace {
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;
18
19 qhT qh_qh;
20 qhT *qh= &qh_qh;
21
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();
26 }
27 }
28
29 char opts[32];
30 sprintf(opts, "qhull d Qbb QJ Qt i");
31 FILE* dev_null = fopen("/dev/null", "w");
32 int curlong, totlong;
33 boolT ismalloc = false;
34
35 QHULL_LIB_CHECK
36 qh_zero(qh, dev_null);
37
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));
40 fclose(dev_null);
41 free(cpts);
42
43 facetT *facet;
44 vertexT *vertex, **vertexp;
45 FORALLfacets {
46 if(!facet->upperdelaunay) {
47 vector<int> lvec;
48 FOREACHvertex_(facet->vertices) {
49 lvec.push_back(qh_pointid(qh, vertex->point));
50 }
51 ret.push_back(lvec);
52 }
53 }
54
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;
59 }
60
61 if(ret.size()<=0) {
62 cerr << ErrColor << "QDelaunay: (ret.size()<=0)" << RESET << endl;
63 throw Error("QDelaunay failed.");
64 }
65
66 return ret;
67 }
68 }
69
77 vector<matrix> Triangularize(const lst & fs_in, const ex & xs_in, const lst & nsubs) {
78 int nx = xs_in.nops();
79 lst fs = fs_in;
80 if(fs.nops()<1) {
81 vector<matrix> mats;
82 matrix mat(nx,nx);
83 for(int i=0; i<nx; i++) mat(i,i) = 1;
84 mats.push_back(mat);
85 return mats;
86 }
87 lst xs;
88 ex xsum = 0;
89 for(int i=0; i<nx; i++) {
90 symbol xi("x"+to_string(i));
91 xs.append(xi);
92 xsum += xi;
93 }
94 exmap x2x;
95 for(int i=0; i<nx; i++) {
96 fs.append(xs_in.op(i));
97 x2x[xs_in.op(i)] = xs.op(i);
98 }
99 for(int i=0; i<fs.nops(); i++) {
100 lst tls = {fs.op(i), -fs.op(i)};
101 sort_lst(tls);
102 fs.let_op(i) = tls.op(0);
103 }
104 fs.sort();
105 fs.unique();
106 fs = ex_to<lst>(subs(fs,x2x));
107 int n = fs.nops();
108 lst pts;
109 int nmax = 1;
110 int nx1 = nx-1;
111 Combinations(fs.nops(), nx1, [&](const int is[]){
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);
115 if(sol.nops()>0) {
116 auto ps = subs(xs,ex_to<lst>(sol));
117 bool ok = true;
118 for(auto xi : xs) {
119 if(ps.has(xi)) { ok = false; break; }
120 }
121 if(ok) {
122 for(auto pi : ps) {
123 ex npi = pi.subs(nsubs);
124 if(!is_a<numeric>(npi)) {
125 cout << "Found non-numeric(after nsubs): " << pi.subs(nsubs) << endl;
126 cout << eqs << endl;
127 cout << sol << endl;
128 cout << endl << endl;
129 }
130 if(npi<0 || npi>nmax) { ok = false; break; }
131 }
132 if(ok) pts.append(ps);
133 }
134 }
135 });
136 pts.sort();
137 pts.unique();
138
139 exset pts_set;
140 pts_set.insert(pts);
141 for(auto const & fi : fs) { // divide pts by the planes, i.e., equations
142 auto cset = pts_set;
143 pts_set.clear();
144 for(auto const & si : cset) {
145 lst lstn, lst0, lstp;
146 for(auto const & item : si) {
147 exmap xmap;
148 for(int i=0; i<nx; i++) xmap[xs.op(i)] = item.op(i);
149 ex c = exnormal(fi.subs(xmap).subs(nsubs)); // nsubs
150 if(!is_a<numeric>(c)) {
151 cout << "c(after nsbus)=" << c << endl;
152 throw Error("TriSector: c is NOT a number.");
153 }
154 if(c.is_zero()) lst0.append(item);
155 else if(c>0) lstp.append(item);
156 else lstn.append(item);
157 }
158 if(lstn.nops()==0 || lstp.nops()==0) {
159 pts_set.insert(si);
160 continue;
161 }
162 for(auto const & item : lst0) {
163 lstp.append(item);
164 lstn.append(item);
165 }
166 pts_set.insert(lstp);
167 pts_set.insert(lstn);
168 }
169 }
170
171 vector<matrix> mats;
172 for(auto const & pts : pts_set) { // redefine pts here
173 vector<vector<int>> res;
174 if(pts.nops()>nx) res = QDelaunay(pts.subs(nsubs)); // nsubs
175 else {
176 vector<int> n_vec(nx);
177 for(int i=0; i<nx; i++) n_vec[i] = i;
178 res.push_back(n_vec);
179 }
180 for(auto item : res) {
181 exvector c_vec(nx);
182 exmap c2i;
183 for(int i=0; i<nx; i++) {
184 symbol ci("c"+to_string(i));
185 c_vec[i] = ci;
186 c2i[ci] = 1;
187 }
188
189 matrix mat(nx,nx);
190 for(int i=0; i<nx; i++) {
191 exvector pt_vec(nx);
192 for(int j=0; j<nx; j++) pt_vec[j] = pts.op(item[(i+j)%nx]);
193 lst eqs;
194 for(int j=1; j<nx; j++) { // no eq0, pt_vec[0] used later
195 ex eq = 0;
196 for(int k=0; k<nx; k++) eq += c_vec[k] * pt_vec[j][k];
197 eqs.append(eq==0);
198 }
199 lst c_lst = vec2lst(c_vec);
200 ex sol = lsolve(eqs, c_lst);
201 sol = subs(c_lst, ex_to<lst>(sol)).subs(c2i); // one ci remains, just set it to 1
202 ex sgn = 0;
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!");
208 }
209 if(sgn<0) sgn = -1;
210 else sgn = 1;
211 for(int j=0; j<nx; j++) mat(i,j) = sgn * sol.op(j);
212 }
213 if(mat.determinant()!=0) { // if det==0, the volume is zero, no contribution
214 mats.push_back(mat.inverse());
215 }
216 }
217 }
218
219 return mats;
220 }
221
222
231 void Triangularize(exvector & FunExp, const lst & fs, const ex & xs, const lst & nsubs) {
232 auto mats = Triangularize(fs, xs, nsubs);
233 ex xsum = 0;
234 for(auto xi : xs) xsum += xi;
235 auto fun_exp_lst = FunExp;
236 FunExp.clear();
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));
242 exmap x2y;
243 for(int r=0; r<xs.nops(); r++) {
244 ex xr = 0;
245 for(int c=0; c<xs.nops(); c++) xr += mat(r,c)*y(c);
246 x2y[xs.op(r)] = xr;
247 }
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.");
254 }
255 if(ndet<0) det = -det;
256 ex ysum = xsum.subs(x2y);
257 exmap y2x;
258 for(int i=0; i<xs.nops(); i++) {
259 ex c = ysum.coeff(y(i));
260 det /= c;
261 y2x[y(i)] = xs.op(i)/c;
262 }
263 funs = ex_to<lst>(subs(funs,y2x));
264 funs.append(det);
265 exps.append(1);
266 FunExp.push_back(lst{funs, exps, dlts});
267 }
268 }
269 }
270
271
272}
#define RESET
Definition BASIC.h:79
SecDec header file.
class used to wrap error message
Definition BASIC.h:242
namespace for Numerical integration with Sector Decomposition method
Definition AsyMB.cpp:10
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)
const char * ErrColor
Definition BASIC.cpp:246
ex exnormal(const ex &expr, int opt)
normalize a expression
Definition BASIC.cpp:1918
void sort_lst(lst &ilst, bool less=true)
sort the list in less order, or the reverse
Definition Sort.cpp:79
lst vec2lst(const exvector &ev)
convert exvector to lst
Definition BASIC.cpp:904
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51