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 pi : ps) {
119 ex npi = pi.subs(nsubs);
120 if(!is_a<numeric>(npi)) {
121 cout << "Found non-numeric(after nsubs): " << pi.subs(nsubs) << endl;
122 cout << eqs << endl;
123 cout << sol << endl;
124 cout << endl << endl;
125 }
126 if(npi<0 || npi>nmax) { ok = false; break; }
127 }
128 if(ok) pts.append(ps);
129 }
130 });
131 pts.sort();
132 pts.unique();
133
134 exset pts_set;
135 pts_set.insert(pts);
136 for(auto const & fi : fs) { // divide pts by the planes, i.e., equations
137 auto cset = pts_set;
138 pts_set.clear();
139 for(auto const & si : cset) {
140 lst lstn, lst0, lstp;
141 for(auto const & item : si) {
142 exmap xmap;
143 for(int i=0; i<nx; i++) xmap[xs.op(i)] = item.op(i);
144 ex c = exnormal(fi.subs(xmap).subs(nsubs)); // nsubs
145 if(!is_a<numeric>(c)) {
146 cout << "c(after nsbus)=" << c << endl;
147 throw Error("TriSector: c is NOT a number.");
148 }
149 if(c.is_zero()) lst0.append(item);
150 else if(c>0) lstp.append(item);
151 else lstn.append(item);
152 }
153 if(lstn.nops()==0 || lstp.nops()==0) {
154 pts_set.insert(si);
155 continue;
156 }
157 for(auto const & item : lst0) {
158 lstp.append(item);
159 lstn.append(item);
160 }
161 pts_set.insert(lstp);
162 pts_set.insert(lstn);
163 }
164 }
165
166 vector<matrix> mats;
167 for(auto const & pts : pts_set) { // redefine pts here
168 vector<vector<int>> res;
169 if(pts.nops()>nx) res = QDelaunay(pts.subs(nsubs)); // nsubs
170 else {
171 vector<int> n_vec(nx);
172 for(int i=0; i<nx; i++) n_vec[i] = i;
173 res.push_back(n_vec);
174 }
175 for(auto item : res) {
176 exvector c_vec(nx);
177 exmap c2i;
178 for(int i=0; i<nx; i++) {
179 symbol ci("c"+to_string(i));
180 c_vec[i] = ci;
181 c2i[ci] = 1;
182 }
183
184 matrix mat(nx,nx);
185 for(int i=0; i<nx; i++) {
186 exvector pt_vec(nx);
187 for(int j=0; j<nx; j++) pt_vec[j] = pts.op(item[(i+j)%nx]);
188 lst eqs;
189 for(int j=1; j<nx; j++) { // no eq0, pt_vec[0] used later
190 ex eq = 0;
191 for(int k=0; k<nx; k++) eq += c_vec[k] * pt_vec[j][k];
192 eqs.append(eq==0);
193 }
194 lst c_lst = vec2lst(c_vec);
195 ex sol = lsolve(eqs, c_lst);
196 sol = subs(c_lst, ex_to<lst>(sol)).subs(c2i); // one ci remains, just set it to 1
197 ex sgn = 0;
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!");
203 }
204 if(sgn<0) sgn = -1;
205 else sgn = 1;
206 for(int j=0; j<nx; j++) mat(i,j) = sgn * sol.op(j);
207 }
208 mats.push_back(mat.inverse());
209 }
210 }
211
212 return mats;
213 }
214
215
224 void Triangularize(exvector & FunExp, const lst & fs, const ex & xs, const lst & nsubs) {
225 auto mats = Triangularize(fs, xs, nsubs);
226 ex xsum = 0;
227 for(auto xi : xs) xsum += xi;
228 auto fun_exp_lst = FunExp;
229 FunExp.clear();
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));
235 exmap x2y;
236 for(int r=0; r<xs.nops(); r++) {
237 ex xr = 0;
238 for(int c=0; c<xs.nops(); c++) xr += mat(r,c)*y(c);
239 x2y[xs.op(r)] = xr;
240 }
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.");
247 }
248 if(ndet<0) det = -det;
249 ex ysum = xsum.subs(x2y);
250 exmap y2x;
251 for(int i=0; i<xs.nops(); i++) {
252 ex c = ysum.coeff(y(i));
253 det /= c;
254 y2x[y(i)] = xs.op(i)/c;
255 }
256 funs = ex_to<lst>(subs(funs,y2x));
257 funs.append(det);
258 exps.append(1);
259 FunExp.push_back(lst{funs, exps, dlts});
260 }
261 }
262 }
263
264
265}
#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:1916
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:902
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51