12 #include <bernstein/bernstein.h>
13 #include "polynomial.h"
16 using namespace GiNaC
;
22 static std::string
int2String(int n
);
23 static unsigned int findMaxDegree(ex polynomial
, const exvector
& Vars
);
24 static matrix
getAiMatrix(unsigned int nbVert
);
25 static ex
getBasis(unsigned int nbVert
, matrix
&A
);
26 static ex
replaceVariablesInPolynomial(const ex
&poly
, const exvector
& V
,
28 static ex
powerMonomials(polynomial
&poly
, matrix
&A
, unsigned int nbVert
,
29 unsigned int maxDegree
, ex
&basis
);
30 static lst
getCoefficients(ex hom
, unsigned d
, const matrix
& A
);
32 exvector
constructParameterVector(const char * const *param_names
, unsigned nbParams
)
35 for (int i
= 0; i
< nbParams
; ++i
) {
36 P
[i
] = symbol(param_names
[i
]);
38 cout
<< "P: " << P
[i
] << endl
;
45 exvector
constructVariableVector(unsigned nbVariables
, const char *prefix
)
47 exvector
V(nbVariables
);
48 for (int i
= 0; i
< nbVariables
; ++i
) {
49 V
[i
] = symbol(prefix
+ int2String(i
));
51 cout
<< "V: " << V
[i
] << endl
;
58 numeric
value2numeric(const Value v
)
60 int sa
= v
[0]._mp_size
;
63 int abs_sa
= sa
< 0 ? -sa
: sa
;
65 for (int i
= abs_sa
-1; i
>= 0; --i
) {
66 res
= res
<< GMP_LIMB_BITS
;
67 res
= res
+ v
[0]._mp_d
[i
];
69 return numeric(sa
< 0 ? -res
: res
);
73 matrix
domainVertices(Param_Polyhedron
*PP
, Param_Domain
*Q
, const exvector
& params
)
76 unsigned nbVertices
= 0;
77 unsigned nbRows
, nbColumns
;
81 nbRows
= PP
->V
->Vertex
->NbRows
;
82 nbColumns
= PP
->V
->Vertex
->NbColumns
;
84 FORALL_PVertex_in_ParamPolyhedron(V
, Q
, PP
)
86 END_FORALL_PVertex_in_ParamPolyhedron
;
88 matrix
VM(nbVertices
, nbRows
); // vertices matrix
91 FORALL_PVertex_in_ParamPolyhedron(V
, Q
, PP
)
92 for (unsigned i
= 0; i
< nbRows
; i
++) {
94 for (unsigned j
= 0; j
< nbColumns
-2; j
++)
95 t
+= value2numeric(V
->Vertex
->p
[i
][j
]) * params
[j
];
96 t
+= value2numeric(V
->Vertex
->p
[i
][nbColumns
-2]);
97 t
/= value2numeric(V
->Vertex
->p
[i
][nbColumns
-1]);
99 cout
<< "T: " << t
<< endl
;
104 END_FORALL_PVertex_in_ParamPolyhedron
;
110 * Do the Bernstein Expansion
112 * vert: vertices matrix
113 * poly: polynomial expression
114 * vars: vector of variables
115 * Params: vector of parameter
117 lst
bernsteinExpansion(const matrix
& vert
, const ex
& poly
, const exvector
& vars
,
118 const exvector
& Params
)
120 if (is_exactly_a
<lst
>(poly
)) {
121 lst polylst
= ex_to
<lst
>(poly
);
122 lst::const_iterator j
= polylst
.begin();
124 lst coeff
= bernsteinExpansion(vert
, *j
, vars
, Params
);
126 for (++j
; j
!= polylst
.end(); ++j
) {
127 lst::const_iterator k
;
128 lst new_coeff
= bernsteinExpansion(vert
, *j
, vars
, Params
);
129 for (k
= new_coeff
.begin(); k
!= new_coeff
.end(); ++k
)
131 coeff
.sort().unique();
136 unsigned maxDegree
= findMaxDegree(poly
, vars
);
137 matrix A
= getAiMatrix(vert
.rows());
140 cout
<< endl
<< "Polynomial: " << poly
<< endl
<< endl
;
141 cout
<< vert
<< endl
<< endl
;
142 cout
<< A
<< endl
<< endl
;
145 // obtain the variables value on the basis and replace
146 ex substitutions
= evalm(A
* vert
);
147 ex polynom
= replaceVariablesInPolynomial(poly
, vars
, substitutions
);
150 cout
<< variables
<< endl
<< endl
;
151 cout
<< "Preliminar Expansion: " << polynom
<< endl
<< endl
;
154 ex basis
= getBasis(vert
.rows(), A
);
157 cout
<< "Basis: " << basis
<< endl
<< endl
;
160 // monomials to n degree
161 polynomial
p(polynom
);
162 ex maxDegreePolynomial
= powerMonomials(p
, A
, vert
.rows(), maxDegree
, basis
);
164 return getCoefficients(maxDegreePolynomial
, maxDegree
, A
);
168 * Construct A_i matrix
170 * nbVert: number of vertices
172 matrix
getAiMatrix(unsigned int nbVert
)
174 matrix
A(1, nbVert
); // a_i matrix
175 for(unsigned int i
= 0; i
< nbVert
; i
++) {
176 A(0,i
) = symbol("a" + int2String(i
));
178 cout
<< "A: " << A(0,i
) << endl
;
186 * Construct the basis
189 * nbVert: number of vertices
191 ex
getBasis(unsigned int nbVert
, matrix
&A
)
194 for(unsigned int i
= 0; i
< nbVert
; i
++) {
202 * Finds the less than maxDegree monomials and multiply them
205 * polynomial: original polynomial
207 * nbVert: number of vertices
208 * maxDegree: maximal polynomial multidegree
209 * basis: basis of the polytope
211 ex
powerMonomials(polynomial
&poly
, matrix
&A
, unsigned int nbVert
212 , unsigned int maxDegree
, ex
&basis
)
214 ex maxDegreePolynomial
;
216 cout
<< "- Degree --------------------------------------" << endl
;
218 for (size_t i
= 0; i
!= poly
.nbTerms(); ++i
) {
219 unsigned int degree
= 0; // degree of the monomial
221 for(unsigned int j
= 0; j
< nbVert
; j
++) {
222 degree
+= poly
.term(i
).degree(A(0,j
));
225 cout
<< poly
.term(i
) << " Degree: " << degree
;
227 if(degree
< maxDegree
) {
228 ex degreeUp
= poly
.term(i
) * pow(basis
, maxDegree
- degree
);
230 cout
<< " --> New Term: " << degreeUp
.expand();
232 maxDegreePolynomial
+= degreeUp
.expand();
234 maxDegreePolynomial
+= poly
.term(i
);
237 cout
<< endl
<< "-----------------------------------------------" << endl
;
242 cout
<< endl
<< "Final Expansion: " << maxDegreePolynomial
<< endl
<< endl
;
244 return maxDegreePolynomial
;
250 * Finds the coefficients of the polynomial in terms of the Bernstein basis
252 * hom: homogeneous polynomial of degree d
255 * For each monomial of multi-degree (k[0], k[1], ..., k[n-1])
256 * we divide the corresponding coefficient by the multinomial
257 * coefficient d!/k[0]! k[1]! ... k[n-1]!
259 * The code looks a bit complicated because it's an iterative
260 * implementation of a recursive procedure.
261 * For each variable from 0 to n-1, we loop over the possible
262 * powers: 0..d for the first; 0..d-k[0]=left[0] for the second; ...
263 * Just for fun, we loop through these in the opposite direction
264 * only for the first variable.
266 * c[i] contains the coefficient of the selected powers of the first i+1 vars
267 * multinom[i] contains the partial multinomial coefficient.
269 lst
getCoefficients(ex hom
, unsigned d
, const matrix
& A
)
274 /* we should probably notice sooner that there is just one vertex */
276 coeff
.append(hom
.coeff(A(0, 0), d
));
287 for (k
[0] = d
; k
[0] >= 0; --k
[0]) {
288 c
[0] = hom
.coeff(A(0, 0), k
[0]);
292 multinom
[i
] = multinom
[0];
295 for (int j
= 2; j
<= left
[i
-1]; ++j
)
297 coeff
.append(c
[i
-1].coeff(A(0, i
), left
[i
-1]) /
302 if (k
[i
] >= left
[i
-1]) {
309 c
[i
] = c
[i
-1].coeff(A(0, i
), k
[i
]);
310 left
[i
] = left
[i
-1] - k
[i
];
312 multinom
[i
+1] = multinom
[i
];
317 return coeff
.sort().unique();
321 // replace the variables in the polynomial
322 ex
replaceVariablesInPolynomial(const ex
&poly
, const exvector
&vars
,
327 for(unsigned int i
= 0; i
< vars
.size(); i
++) {
329 cout
<< "Replacing: " << vars
[i
] << " by " << substitutions
[i
] << endl
;
331 replace
.append(vars
[i
] == substitutions
[i
]);
333 ex polyRepl
= poly
.subs(replace
);
335 return(polyRepl
.expand());
339 /* Converts int n to string */
340 string
int2String(int n
)
342 char numeroVariable
[DIGITS
];
343 snprintf(numeroVariable
, DIGITS
, "%d", n
);
344 string
nroV(numeroVariable
);
351 * Find the maximum multi-degree of the polinomial
353 * polynomial: polynomial
354 * Vars: variables matrix
355 * nbVar: number of variables
357 static unsigned int findMaxDegree(ex polynomial
, const exvector
& Vars
, int pos
)
359 if (pos
>= Vars
.size())
363 for (int i
= 0; i
<= polynomial
.degree(Vars
[pos
]); ++i
) {
364 unsigned degree
= i
+ findMaxDegree(polynomial
.coeff(Vars
[pos
], i
),
372 unsigned int findMaxDegree(ex polynomial
, const exvector
& Vars
)
374 return findMaxDegree(polynomial
, Vars
, 0);