3 //#include "fdstream.h"
4 #include <barvinok/util.h>
5 #include <barvinok/sample.h>
6 #include <barvinok/barvinok.h>
8 #include "evalue_util.h"
14 EDomain
*EDomain::new_from_ge_constraint(ge_constraint
*ge
, int sign
,
15 barvinok_options
*options
)
17 if (ge
->simplified
&& sign
== 0)
22 M2
= Matrix_Copy(ge
->M
);
25 value_decrement(M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1],
26 M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1]);
27 } else if (sign
== -1) {
30 value_set_si(mone
, -1);
31 Vector_Scale(M2
->p
[M2
->NbRows
-1]+1, M2
->p
[M2
->NbRows
-1]+1,
32 mone
, M2
->NbColumns
-1);
33 value_decrement(M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1],
34 M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1]);
37 value_set_si(M2
->p
[M2
->NbRows
-1][0], 0);
39 Polyhedron
*D2
= Constraints2Polyhedron(M2
, options
->MaxRays
);
40 ED
= new EDomain(D2
, ge
->D
, ge
->new_floors
);
46 static void print_term(ostream
& os
, Value v
, int pos
, int dim
,
47 char **names
, int *first
)
49 if (value_zero_p(v
)) {
50 if (first
&& *first
&& pos
>= dim
)
56 if (!*first
&& value_pos_p(v
))
61 if (value_mone_p(v
)) {
63 } else if (!value_one_p(v
))
64 os
<< VALUE_TO_INT(v
);
67 os
<< VALUE_TO_INT(v
);
70 void EDomain_floor::print(ostream
& os
, char **p
) const
75 for (int i
= 0; i
< v
->Size
-2; ++i
)
76 print_term(os
, v
->p
[1+i
], i
, v
->Size
-2, p
, &first
);
79 print_term(os
, v
->p
[0], v
->Size
-2, v
->Size
-2, p
, NULL
);
83 void EDomain::print_constraints(ostream
& os
, char **p
,
84 barvinok_options
*options
) const
89 Matrix
*M
= Matrix_Alloc(2*floors
.size(), 1+D
->Dimension
+1);
90 value_set_si(tmp
, -1);
91 for (int i
= 0; i
< floors
.size(); ++i
) {
92 value_set_si(M
->p
[2*i
][0], 1);
93 Vector_Copy(floors
[i
]->v
->p
+1, M
->p
[2*i
]+1, dimension());
94 value_assign(M
->p
[2*i
][1+D
->Dimension
], floors
[i
]->v
->p
[1+dimension()]);
95 value_oppose(M
->p
[2*i
][1+dimension()+i
], floors
[i
]->v
->p
[0]);
97 Vector_Scale(M
->p
[2*i
]+1, M
->p
[2*i
+1]+1, tmp
, D
->Dimension
+1);
98 value_addto(M
->p
[2*i
+1][1+D
->Dimension
], M
->p
[2*i
+1][1+D
->Dimension
],
99 M
->p
[2*i
+1][1+dimension()+i
]);
100 value_decrement(M
->p
[2*i
+1][1+D
->Dimension
], M
->p
[2*i
+1][1+D
->Dimension
]);
101 value_set_si(M
->p
[2*i
+1][0], 1);
103 Polyhedron
*E
= Constraints2Polyhedron(M
, options
->MaxRays
);
105 Polyhedron
*SD
= DomainSimplify(D
, E
, options
->MaxRays
);
109 unsigned dim
= dimension();
110 if (dim
< SD
->Dimension
) {
111 names
= new char * [SD
->Dimension
];
113 for (i
= 0; i
< dim
; ++i
)
115 for ( ; i
< SD
->Dimension
; ++i
) {
116 std::ostringstream strm
;
117 floors
[i
-dim
]->print(strm
, p
);
118 names
[i
] = strdup(strm
.str().c_str());
122 for (int i
= 0; i
< SD
->NbConstraints
; ++i
) {
124 int v
= First_Non_Zero(SD
->Constraint
[i
]+1, SD
->Dimension
);
129 if (value_pos_p(SD
->Constraint
[i
][v
+1])) {
130 print_term(os
, SD
->Constraint
[i
][v
+1], v
, SD
->Dimension
,
132 if (value_zero_p(SD
->Constraint
[i
][0]))
136 for (int j
= v
+1; j
<= SD
->Dimension
; ++j
) {
137 value_oppose(tmp
, SD
->Constraint
[i
][1+j
]);
138 print_term(os
, tmp
, j
, SD
->Dimension
,
142 value_oppose(tmp
, SD
->Constraint
[i
][1+v
]);
143 print_term(os
, tmp
, v
, SD
->Dimension
,
145 if (value_zero_p(SD
->Constraint
[i
][0]))
149 for (int j
= v
+1; j
<= SD
->Dimension
; ++j
)
150 print_term(os
, SD
->Constraint
[i
][1+j
], j
, SD
->Dimension
,
157 if (dim
< D
->Dimension
) {
158 for (int i
= dim
; i
< D
->Dimension
; ++i
)
165 void EDomain::print(FILE *out, char **p)
167 fdostream os(dup(fileno(out)));
168 for (int i = 0; i < floors.size(); ++i) {
169 os << "floor " << i << ": [";
170 evalue_print(os, floors[i]->e, p);
173 Polyhedron_Print(out, P_VALUE_FMT, D);
177 static int type_offset(enode
*p
)
179 return p
->type
== fractional
? 1 :
180 p
->type
== flooring
? 1 : 0;
183 static void add_coeff(Value
*cons
, int len
, evalue
*coeff
, int pos
)
187 assert(value_notzero_p(coeff
->d
));
191 value_lcm(tmp
, cons
[0], coeff
->d
);
192 value_division(tmp
, tmp
, cons
[0]);
193 Vector_Scale(cons
, cons
, tmp
, len
);
194 value_division(tmp
, cons
[0], coeff
->d
);
195 value_addmul(cons
[pos
], tmp
, coeff
->x
.n
);
200 static int evalue2constraint_r(EDomain
*D
, evalue
*E
, Value
*cons
, int len
);
202 static void add_fract(evalue
*e
, Value
*cons
, int len
, int pos
)
206 evalue_set_si(&mone
, -1, 1);
208 /* contribution of alpha * fract(X) is
211 assert(e
->x
.p
->size
== 3);
213 value_init(argument
.d
);
214 evalue_copy(&argument
, &e
->x
.p
->arr
[0]);
215 emul(&e
->x
.p
->arr
[2], &argument
);
216 evalue2constraint_r(NULL
, &argument
, cons
, len
);
217 free_evalue_refs(&argument
);
219 /* - alpha * floor(X) */
220 emul(&mone
, &e
->x
.p
->arr
[2]);
221 add_coeff(cons
, len
, &e
->x
.p
->arr
[2], pos
);
222 emul(&mone
, &e
->x
.p
->arr
[2]);
224 free_evalue_refs(&mone
);
227 static int evalue2constraint_r(EDomain
*D
, evalue
*E
, Value
*cons
, int len
)
230 if (value_zero_p(E
->d
) && E
->x
.p
->type
== fractional
) {
232 assert(E
->x
.p
->size
== 3);
233 r
= evalue2constraint_r(D
, &E
->x
.p
->arr
[1], cons
, len
);
234 assert(value_notzero_p(E
->x
.p
->arr
[2].d
));
235 if (D
&& (i
= D
->find_floor(&E
->x
.p
->arr
[0])) >= 0) {
236 add_fract(E
, cons
, len
, 1+D
->D
->Dimension
-D
->floors
.size()+i
);
238 if (value_pos_p(E
->x
.p
->arr
[2].x
.n
)) {
241 value_init(coeff
.x
.n
);
242 value_set_si(coeff
.d
, 1);
243 evalue_denom(&E
->x
.p
->arr
[0], &coeff
.d
);
244 value_decrement(coeff
.x
.n
, coeff
.d
);
245 emul(&E
->x
.p
->arr
[2], &coeff
);
246 add_coeff(cons
, len
, &coeff
, len
-1);
247 free_evalue_refs(&coeff
);
251 } else if (value_zero_p(E
->d
)) {
252 assert(E
->x
.p
->type
== polynomial
);
253 assert(E
->x
.p
->size
== 2);
254 r
= evalue2constraint_r(D
, &E
->x
.p
->arr
[0], cons
, len
) || r
;
255 add_coeff(cons
, len
, &E
->x
.p
->arr
[1], E
->x
.p
->pos
);
257 add_coeff(cons
, len
, E
, len
-1);
262 EDomain_floor::EDomain_floor(const evalue
*f
, int dim
)
267 v
= Vector_Alloc(1+dim
+1);
268 value_set_si(v
->p
[0], 1);
269 evalue2constraint_r(NULL
, e
, v
->p
, v
->Size
);
274 void EDomain_floor::eval(Value
*values
, Value
*res
) const
276 Inner_Product(v
->p
+1, values
, v
->Size
-2, res
);
277 value_addto(*res
, *res
, v
->p
[v
->Size
-1]);
278 value_pdivision(*res
, *res
, v
->p
[0]);
281 int evalue2constraint(EDomain
*D
, evalue
*E
, Value
*cons
, int len
)
283 Vector_Set(cons
, 0, len
);
284 value_set_si(cons
[0], 1);
285 return evalue2constraint_r(D
, E
, cons
, len
);
288 bool EDomain::contains(Value
*point
, int len
) const
290 assert(len
<= D
->Dimension
);
291 if (len
== D
->Dimension
)
292 return in_domain(D
, point
);
294 Vector
*all_val
= Vector_Alloc(D
->Dimension
);
295 Vector_Copy(point
, all_val
->p
, len
);
296 for (int i
= len
-dimension(); i
< floors
.size(); ++i
)
297 floors
[i
]->eval(all_val
->p
, &all_val
->p
[dimension()+i
]);
298 bool in
= in_domain(D
, all_val
->p
);
299 Vector_Free(all_val
);
303 ge_constraint
*EDomain::compute_ge_constraint(evalue
*constraint
) const
305 ge_constraint
*ge
= new ge_constraint(this);
308 evalue_set_si(&mone
, -1, 1);
310 for (evalue
*e
= constraint
; value_zero_p(e
->d
);
311 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)]) {
313 if (e
->x
.p
->type
!= fractional
)
315 if (find_floor(&e
->x
.p
->arr
[0]) == -1)
319 int rows
= D
->NbConstraints
+2*fract
+1;
320 int cols
= 2+D
->Dimension
+fract
;
321 ge
->M
= Matrix_Alloc(rows
, cols
);
322 for (int i
= 0; i
< D
->NbConstraints
; ++i
) {
323 Vector_Copy(D
->Constraint
[i
], ge
->M
->p
[i
], 1+D
->Dimension
);
324 value_assign(ge
->M
->p
[i
][1+D
->Dimension
+fract
],
325 D
->Constraint
[i
][1+D
->Dimension
]);
327 value_set_si(ge
->M
->p
[rows
-1][0], 1);
330 for (e
= constraint
; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)]) {
331 if (e
->x
.p
->type
== fractional
) {
334 i
= find_floor(&e
->x
.p
->arr
[0]);
336 pos
= D
->Dimension
-floors
.size()+i
;
338 pos
= D
->Dimension
+fract
;
340 add_fract(e
, ge
->M
->p
[rows
-1], cols
, 1+pos
);
342 if (pos
< D
->Dimension
)
345 EDomain_floor
*new_floor
;
346 new_floor
= new EDomain_floor(&e
->x
.p
->arr
[0], dimension());
348 /* constraints for the new floor */
349 int row
= D
->NbConstraints
+2*fract
;
350 Vector_Copy(new_floor
->v
->p
+1, ge
->M
->p
[row
]+1, dimension());
351 value_assign(ge
->M
->p
[row
][cols
-1], new_floor
->v
->p
[1+dimension()]);
352 value_oppose(ge
->M
->p
[row
][1+D
->Dimension
+fract
], new_floor
->v
->p
[0]);
353 value_set_si(ge
->M
->p
[row
][0], 1);
354 assert(value_eq(ge
->M
->p
[row
][cols
-1], new_floor
->v
->p
[1+dimension()]));
355 assert(Vector_Equal(new_floor
->v
->p
+1, ge
->M
->p
[row
]+1, dimension()));
357 Vector_Scale(ge
->M
->p
[row
]+1, ge
->M
->p
[row
+1]+1, mone
.x
.n
, cols
-1);
358 value_set_si(ge
->M
->p
[row
+1][0], 1);
359 value_addto(ge
->M
->p
[row
+1][cols
-1], ge
->M
->p
[row
+1][cols
-1],
360 ge
->M
->p
[row
+1][1+D
->Dimension
+fract
]);
361 value_decrement(ge
->M
->p
[row
+1][cols
-1], ge
->M
->p
[row
+1][cols
-1]);
363 ge
->new_floors
.push_back(new_floor
);
367 assert(e
->x
.p
->type
== polynomial
);
368 assert(e
->x
.p
->size
== 2);
369 add_coeff(ge
->M
->p
[rows
-1], cols
, &e
->x
.p
->arr
[1], e
->x
.p
->pos
);
372 add_coeff(ge
->M
->p
[rows
-1], cols
, e
, cols
-1);
373 ge
->simplified
= ConstraintSimplify(ge
->M
->p
[rows
-1], ge
->M
->p
[rows
-1],
374 cols
, &ge
->M
->p
[rows
-1][0]);
375 value_set_si(ge
->M
->p
[rows
-1][0], 1);
376 free_evalue_refs(&mone
);
380 /* "align" matrix to have nrows by inserting
381 * the necessary number of rows and an equal number of columns at the end
382 * right before the constant row/column
384 static Matrix
*align_matrix_initial(Matrix
*M
, int nrows
)
387 int newrows
= nrows
- M
->NbRows
;
388 Matrix
*M2
= Matrix_Alloc(nrows
, newrows
+ M
->NbColumns
);
389 for (i
= 0; i
< M
->NbRows
-1; ++i
) {
390 Vector_Copy(M
->p
[i
], M2
->p
[i
], M
->NbColumns
-1);
391 value_assign(M2
->p
[i
][M2
->NbColumns
-1], M
->p
[i
][M
->NbColumns
-1]);
393 for (i
= 0; i
<= newrows
; ++i
)
394 value_assign(M2
->p
[M
->NbRows
-1+i
][M
->NbColumns
-1+i
],
395 M
->p
[M
->NbRows
-1][M
->NbColumns
-1]);
399 static Matrix
*InsertColumns(Matrix
*M
, int pos
, int n
)
404 R
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
+n
);
405 for (i
= 0; i
< M
->NbRows
; ++i
) {
406 Vector_Copy(M
->p
[i
], R
->p
[i
], pos
);
407 Vector_Copy(M
->p
[i
]+pos
, R
->p
[i
]+pos
+n
, M
->NbColumns
-pos
);
412 void EDomain_floor::substitute(evalue
**subs
, Matrix
*T
)
414 /* This is a hack. The EDomain_floor elements are possibly shared
415 * by many EDomain structures and we want to perform the substitution
422 evalue_substitute(e
, subs
);
424 assert(T
->NbRows
== v
->Size
-1);
425 Vector
*tmp
= Vector_Alloc(1+T
->NbColumns
);
426 Vector_Matrix_Product(v
->p
+1, T
, tmp
->p
+1);
427 value_multiply(tmp
->p
[0], v
->p
[0], T
->p
[T
->NbRows
-1][T
->NbColumns
-1]);
432 /* T is a homogeneous matrix that maps the original variables to the new variables.
433 * this has constraints in the new variables and this method
434 * transforms this to constraints in the original variables.
436 void EDomain::substitute(evalue
**subs
, Matrix
*T
, Matrix
*Eq
, unsigned MaxRays
)
438 int nexist
= floors
.size();
439 Matrix
*M
= align_matrix_initial(T
, T
->NbRows
+nexist
);
440 Polyhedron
*new_D
= DomainPreimage(D
, M
, MaxRays
);
445 M
= nexist
? InsertColumns(Eq
, 1+dimension(), nexist
) : Eq
;
446 new_D
= DomainAddConstraints(D
, M
, MaxRays
);
451 for (int i
= 0; i
< floors
.size(); ++i
)
452 floors
[i
]->substitute(subs
, T
);
455 static Matrix
*remove_equalities(Polyhedron
**P
, unsigned nparam
, unsigned MaxRays
)
458 Polyhedron_Matrix_View(*P
, &M
, (*P
)->NbEq
);
460 Matrix
*T
= compress_variables(&M
, nparam
);
470 *P
= Polyhedron_Preimage(*P
, T
, MaxRays
);
475 bool EDomain::not_empty(lexmin_options
*options
)
478 Polyhedron
*Porig
= P
;
480 POL_ENSURE_VERTICES(P
);
484 for (int i
= 0; i
< P
->NbRays
; ++i
)
485 if (value_one_p(P
->Ray
[i
][1+P
->Dimension
])) {
486 sample
= Vector_Alloc(P
->Dimension
+ 1);
487 Vector_Copy(P
->Ray
[i
]+1, sample
->p
, P
->Dimension
+1);
491 if (options
->emptiness_check
== BV_LEXMIN_EMPTINESS_CHECK_COUNT
) {
495 barvinok_count_with_options(P
, &cb
, options
->verify
.barvinok
);
496 notzero
= value_notzero_p(cb
);
502 while (P
&& !emptyQ2(P
) && P
->NbEq
> 0) {
504 Matrix
*T2
= remove_equalities(&P
, 0, options
->verify
.barvinok
->MaxRays
);
509 Matrix
*T3
= Matrix_Alloc(T
->NbRows
, T2
->NbColumns
);
510 Matrix_Product(T
, T2
, T3
);
520 sample
= Polyhedron_Sample(P
, options
->verify
.barvinok
);
523 Vector
*P_sample
= Vector_Alloc(Porig
->Dimension
+ 1);
524 Matrix_Vector_Product(T
, sample
->p
, P_sample
->p
);
535 assert(in_domain(Porig
, sample
->p
));
537 return sample
!= NULL
;