2 //#include "fdstream.h"
3 #include <barvinok/util.h>
4 #include <barvinok/sample.h>
5 #include <barvinok/barvinok.h>
7 #include "evalue_util.h"
13 EDomain
*EDomain::new_from_ge_constraint(ge_constraint
*ge
, int sign
,
14 barvinok_options
*options
)
16 if (ge
->simplified
&& sign
== 0)
21 M2
= Matrix_Copy(ge
->M
);
24 value_decrement(M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1],
25 M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1]);
26 } else if (sign
== -1) {
29 value_set_si(mone
, -1);
30 Vector_Scale(M2
->p
[M2
->NbRows
-1]+1, M2
->p
[M2
->NbRows
-1]+1,
31 mone
, M2
->NbColumns
-1);
32 value_decrement(M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1],
33 M2
->p
[M2
->NbRows
-1][M2
->NbColumns
-1]);
36 value_set_si(M2
->p
[M2
->NbRows
-1][0], 0);
38 Polyhedron
*D2
= Constraints2Polyhedron(M2
, options
->MaxRays
);
39 ED
= new EDomain(D2
, ge
->D
, ge
->new_floors
);
45 static void print_term(ostream
& os
, Value v
, int pos
, int dim
,
46 char **names
, int *first
)
48 if (value_zero_p(v
)) {
49 if (first
&& *first
&& pos
>= dim
)
55 if (!*first
&& value_pos_p(v
))
60 if (value_mone_p(v
)) {
62 } else if (!value_one_p(v
))
63 os
<< VALUE_TO_INT(v
);
66 os
<< VALUE_TO_INT(v
);
69 void EDomain_floor::print(ostream
& os
, char **p
) const
74 for (int i
= 0; i
< v
->Size
-2; ++i
)
75 print_term(os
, v
->p
[1+i
], i
, v
->Size
-2, p
, &first
);
78 print_term(os
, v
->p
[0], v
->Size
-2, v
->Size
-2, p
, NULL
);
82 void EDomain::print_constraints(ostream
& os
, char **p
,
83 barvinok_options
*options
) const
88 Matrix
*M
= Matrix_Alloc(2*floors
.size(), 1+D
->Dimension
+1);
89 value_set_si(tmp
, -1);
90 for (int i
= 0; i
< floors
.size(); ++i
) {
91 value_set_si(M
->p
[2*i
][0], 1);
92 Vector_Copy(floors
[i
]->v
->p
+1, M
->p
[2*i
]+1, dimension());
93 value_assign(M
->p
[2*i
][1+D
->Dimension
], floors
[i
]->v
->p
[1+dimension()]);
94 value_oppose(M
->p
[2*i
][1+dimension()+i
], floors
[i
]->v
->p
[0]);
96 Vector_Scale(M
->p
[2*i
]+1, M
->p
[2*i
+1]+1, tmp
, D
->Dimension
+1);
97 value_addto(M
->p
[2*i
+1][1+D
->Dimension
], M
->p
[2*i
+1][1+D
->Dimension
],
98 M
->p
[2*i
+1][1+dimension()+i
]);
99 value_decrement(M
->p
[2*i
+1][1+D
->Dimension
], M
->p
[2*i
+1][1+D
->Dimension
]);
100 value_set_si(M
->p
[2*i
+1][0], 1);
102 Polyhedron
*E
= Constraints2Polyhedron(M
, options
->MaxRays
);
104 Polyhedron
*SD
= DomainSimplify(D
, E
, options
->MaxRays
);
108 unsigned dim
= dimension();
109 if (dim
< SD
->Dimension
) {
110 names
= new char * [SD
->Dimension
];
112 for (i
= 0; i
< dim
; ++i
)
114 for ( ; i
< SD
->Dimension
; ++i
) {
115 std::ostringstream strm
;
116 floors
[i
-dim
]->print(strm
, p
);
117 names
[i
] = strdup(strm
.str().c_str());
121 for (int i
= 0; i
< SD
->NbConstraints
; ++i
) {
123 int v
= First_Non_Zero(SD
->Constraint
[i
]+1, SD
->Dimension
);
128 if (value_pos_p(SD
->Constraint
[i
][v
+1])) {
129 print_term(os
, SD
->Constraint
[i
][v
+1], v
, SD
->Dimension
,
131 if (value_zero_p(SD
->Constraint
[i
][0]))
135 for (int j
= v
+1; j
<= SD
->Dimension
; ++j
) {
136 value_oppose(tmp
, SD
->Constraint
[i
][1+j
]);
137 print_term(os
, tmp
, j
, SD
->Dimension
,
141 value_oppose(tmp
, SD
->Constraint
[i
][1+v
]);
142 print_term(os
, tmp
, v
, SD
->Dimension
,
144 if (value_zero_p(SD
->Constraint
[i
][0]))
148 for (int j
= v
+1; j
<= SD
->Dimension
; ++j
)
149 print_term(os
, SD
->Constraint
[i
][1+j
], j
, SD
->Dimension
,
156 if (dim
< D
->Dimension
) {
157 for (int i
= dim
; i
< D
->Dimension
; ++i
)
164 void EDomain::print(FILE *out, char **p)
166 fdostream os(dup(fileno(out)));
167 for (int i = 0; i < floors.size(); ++i) {
168 os << "floor " << i << ": [";
169 evalue_print(os, floors[i]->e, p);
172 Polyhedron_Print(out, P_VALUE_FMT, D);
176 static int type_offset(enode
*p
)
178 return p
->type
== fractional
? 1 :
179 p
->type
== flooring
? 1 : 0;
182 static void add_coeff(Value
*cons
, int len
, evalue
*coeff
, int pos
)
186 assert(value_notzero_p(coeff
->d
));
190 value_lcm(cons
[0], coeff
->d
, &tmp
);
191 value_division(tmp
, tmp
, cons
[0]);
192 Vector_Scale(cons
, cons
, tmp
, len
);
193 value_division(tmp
, cons
[0], coeff
->d
);
194 value_addmul(cons
[pos
], tmp
, coeff
->x
.n
);
199 static int evalue2constraint_r(EDomain
*D
, evalue
*E
, Value
*cons
, int len
);
201 static void add_fract(evalue
*e
, Value
*cons
, int len
, int pos
)
205 evalue_set_si(&mone
, -1, 1);
207 /* contribution of alpha * fract(X) is
210 assert(e
->x
.p
->size
== 3);
212 value_init(argument
.d
);
213 evalue_copy(&argument
, &e
->x
.p
->arr
[0]);
214 emul(&e
->x
.p
->arr
[2], &argument
);
215 evalue2constraint_r(NULL
, &argument
, cons
, len
);
216 free_evalue_refs(&argument
);
218 /* - alpha * floor(X) */
219 emul(&mone
, &e
->x
.p
->arr
[2]);
220 add_coeff(cons
, len
, &e
->x
.p
->arr
[2], pos
);
221 emul(&mone
, &e
->x
.p
->arr
[2]);
223 free_evalue_refs(&mone
);
226 static int evalue2constraint_r(EDomain
*D
, evalue
*E
, Value
*cons
, int len
)
229 if (value_zero_p(E
->d
) && E
->x
.p
->type
== fractional
) {
231 assert(E
->x
.p
->size
== 3);
232 r
= evalue2constraint_r(D
, &E
->x
.p
->arr
[1], cons
, len
);
233 assert(value_notzero_p(E
->x
.p
->arr
[2].d
));
234 if (D
&& (i
= D
->find_floor(&E
->x
.p
->arr
[0])) >= 0) {
235 add_fract(E
, cons
, len
, 1+D
->D
->Dimension
-D
->floors
.size()+i
);
237 if (value_pos_p(E
->x
.p
->arr
[2].x
.n
)) {
240 value_init(coeff
.x
.n
);
241 value_set_si(coeff
.d
, 1);
242 evalue_denom(&E
->x
.p
->arr
[0], &coeff
.d
);
243 value_decrement(coeff
.x
.n
, coeff
.d
);
244 emul(&E
->x
.p
->arr
[2], &coeff
);
245 add_coeff(cons
, len
, &coeff
, len
-1);
246 free_evalue_refs(&coeff
);
250 } else if (value_zero_p(E
->d
)) {
251 assert(E
->x
.p
->type
== polynomial
);
252 assert(E
->x
.p
->size
== 2);
253 r
= evalue2constraint_r(D
, &E
->x
.p
->arr
[0], cons
, len
) || r
;
254 add_coeff(cons
, len
, &E
->x
.p
->arr
[1], E
->x
.p
->pos
);
256 add_coeff(cons
, len
, E
, len
-1);
261 EDomain_floor::EDomain_floor(const evalue
*f
, int dim
)
266 v
= Vector_Alloc(1+dim
+1);
267 value_set_si(v
->p
[0], 1);
268 evalue2constraint_r(NULL
, e
, v
->p
, v
->Size
);
273 void EDomain_floor::eval(Value
*values
, Value
*res
) const
275 Inner_Product(v
->p
+1, values
, v
->Size
-2, res
);
276 value_addto(*res
, *res
, v
->p
[v
->Size
-1]);
277 value_pdivision(*res
, *res
, v
->p
[0]);
280 int evalue2constraint(EDomain
*D
, evalue
*E
, Value
*cons
, int len
)
282 Vector_Set(cons
, 0, len
);
283 value_set_si(cons
[0], 1);
284 return evalue2constraint_r(D
, E
, cons
, len
);
287 bool EDomain::contains(Value
*point
, int len
) const
289 assert(len
<= D
->Dimension
);
290 if (len
== D
->Dimension
)
291 return in_domain(D
, point
);
293 Vector
*all_val
= Vector_Alloc(D
->Dimension
);
294 Vector_Copy(point
, all_val
->p
, len
);
295 for (int i
= len
-dimension(); i
< floors
.size(); ++i
)
296 floors
[i
]->eval(all_val
->p
, &all_val
->p
[dimension()+i
]);
297 bool in
= in_domain(D
, all_val
->p
);
298 Vector_Free(all_val
);
302 ge_constraint
*EDomain::compute_ge_constraint(evalue
*constraint
) const
304 ge_constraint
*ge
= new ge_constraint(this);
307 evalue_set_si(&mone
, -1, 1);
309 for (evalue
*e
= constraint
; value_zero_p(e
->d
);
310 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)]) {
312 if (e
->x
.p
->type
!= fractional
)
314 if (find_floor(&e
->x
.p
->arr
[0]) == -1)
318 int rows
= D
->NbConstraints
+2*fract
+1;
319 int cols
= 2+D
->Dimension
+fract
;
320 ge
->M
= Matrix_Alloc(rows
, cols
);
321 for (int i
= 0; i
< D
->NbConstraints
; ++i
) {
322 Vector_Copy(D
->Constraint
[i
], ge
->M
->p
[i
], 1+D
->Dimension
);
323 value_assign(ge
->M
->p
[i
][1+D
->Dimension
+fract
],
324 D
->Constraint
[i
][1+D
->Dimension
]);
326 value_set_si(ge
->M
->p
[rows
-1][0], 1);
329 for (e
= constraint
; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)]) {
330 if (e
->x
.p
->type
== fractional
) {
333 i
= find_floor(&e
->x
.p
->arr
[0]);
335 pos
= D
->Dimension
-floors
.size()+i
;
337 pos
= D
->Dimension
+fract
;
339 add_fract(e
, ge
->M
->p
[rows
-1], cols
, 1+pos
);
341 if (pos
< D
->Dimension
)
344 EDomain_floor
*new_floor
;
345 new_floor
= new EDomain_floor(&e
->x
.p
->arr
[0], dimension());
347 /* constraints for the new floor */
348 int row
= D
->NbConstraints
+2*fract
;
349 Vector_Copy(new_floor
->v
->p
+1, ge
->M
->p
[row
]+1, dimension());
350 value_assign(ge
->M
->p
[row
][cols
-1], new_floor
->v
->p
[1+dimension()]);
351 value_oppose(ge
->M
->p
[row
][1+D
->Dimension
+fract
], new_floor
->v
->p
[0]);
352 value_set_si(ge
->M
->p
[row
][0], 1);
353 assert(value_eq(ge
->M
->p
[row
][cols
-1], new_floor
->v
->p
[1+dimension()]));
354 assert(Vector_Equal(new_floor
->v
->p
+1, ge
->M
->p
[row
]+1, dimension()));
356 Vector_Scale(ge
->M
->p
[row
]+1, ge
->M
->p
[row
+1]+1, mone
.x
.n
, cols
-1);
357 value_set_si(ge
->M
->p
[row
+1][0], 1);
358 value_addto(ge
->M
->p
[row
+1][cols
-1], ge
->M
->p
[row
+1][cols
-1],
359 ge
->M
->p
[row
+1][1+D
->Dimension
+fract
]);
360 value_decrement(ge
->M
->p
[row
+1][cols
-1], ge
->M
->p
[row
+1][cols
-1]);
362 ge
->new_floors
.push_back(new_floor
);
366 assert(e
->x
.p
->type
== polynomial
);
367 assert(e
->x
.p
->size
== 2);
368 add_coeff(ge
->M
->p
[rows
-1], cols
, &e
->x
.p
->arr
[1], e
->x
.p
->pos
);
371 add_coeff(ge
->M
->p
[rows
-1], cols
, e
, cols
-1);
372 ge
->simplified
= ConstraintSimplify(ge
->M
->p
[rows
-1], ge
->M
->p
[rows
-1],
373 cols
, &ge
->M
->p
[rows
-1][0]);
374 value_set_si(ge
->M
->p
[rows
-1][0], 1);
375 free_evalue_refs(&mone
);
379 /* "align" matrix to have nrows by inserting
380 * the necessary number of rows and an equal number of columns at the end
381 * right before the constant row/column
383 static Matrix
*align_matrix_initial(Matrix
*M
, int nrows
)
386 int newrows
= nrows
- M
->NbRows
;
387 Matrix
*M2
= Matrix_Alloc(nrows
, newrows
+ M
->NbColumns
);
388 for (i
= 0; i
< M
->NbRows
-1; ++i
) {
389 Vector_Copy(M
->p
[i
], M2
->p
[i
], M
->NbColumns
-1);
390 value_assign(M2
->p
[i
][M2
->NbColumns
-1], M
->p
[i
][M
->NbColumns
-1]);
392 for (i
= 0; i
<= newrows
; ++i
)
393 value_assign(M2
->p
[M
->NbRows
-1+i
][M
->NbColumns
-1+i
],
394 M
->p
[M
->NbRows
-1][M
->NbColumns
-1]);
398 static Matrix
*InsertColumns(Matrix
*M
, int pos
, int n
)
403 R
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
+n
);
404 for (i
= 0; i
< M
->NbRows
; ++i
) {
405 Vector_Copy(M
->p
[i
], R
->p
[i
], pos
);
406 Vector_Copy(M
->p
[i
]+pos
, R
->p
[i
]+pos
+n
, M
->NbColumns
-pos
);
411 void EDomain_floor::substitute(evalue
**subs
, Matrix
*T
)
413 /* This is a hack. The EDomain_floor elements are possibly shared
414 * by many EDomain structures and we want to perform the substitution
421 evalue_substitute(e
, subs
);
423 assert(T
->NbRows
== v
->Size
-1);
424 Vector
*tmp
= Vector_Alloc(1+T
->NbColumns
);
425 Vector_Matrix_Product(v
->p
+1, T
, tmp
->p
+1);
426 value_multiply(tmp
->p
[0], v
->p
[0], T
->p
[T
->NbRows
-1][T
->NbColumns
-1]);
431 /* T is a homogeneous matrix that maps the original variables to the new variables.
432 * this has constraints in the new variables and this method
433 * transforms this to constraints in the original variables.
435 void EDomain::substitute(evalue
**subs
, Matrix
*T
, Matrix
*Eq
, unsigned MaxRays
)
437 int nexist
= floors
.size();
438 Matrix
*M
= align_matrix_initial(T
, T
->NbRows
+nexist
);
439 Polyhedron
*new_D
= DomainPreimage(D
, M
, MaxRays
);
444 M
= nexist
? InsertColumns(Eq
, 1+dimension(), nexist
) : Eq
;
445 new_D
= DomainAddConstraints(D
, M
, MaxRays
);
450 for (int i
= 0; i
< floors
.size(); ++i
)
451 floors
[i
]->substitute(subs
, T
);
454 static Matrix
*remove_equalities(Polyhedron
**P
, unsigned nparam
, unsigned MaxRays
)
456 /* Matrix "view" of equalities */
458 M
.NbRows
= (*P
)->NbEq
;
459 M
.NbColumns
= (*P
)->Dimension
+2;
460 M
.p_Init
= (*P
)->p_Init
;
461 M
.p
= (*P
)->Constraint
;
463 Matrix
*T
= compress_variables(&M
, nparam
);
473 *P
= Polyhedron_Preimage(*P
, T
, MaxRays
);
478 bool EDomain::not_empty(lexmin_options
*options
)
481 Polyhedron
*Porig
= P
;
483 POL_ENSURE_VERTICES(P
);
487 for (int i
= 0; i
< P
->NbRays
; ++i
)
488 if (value_one_p(P
->Ray
[i
][1+P
->Dimension
])) {
489 sample
= Vector_Alloc(P
->Dimension
+ 1);
490 Vector_Copy(P
->Ray
[i
]+1, sample
->p
, P
->Dimension
+1);
494 if (options
->emptiness_check
== BV_LEXMIN_EMPTINESS_CHECK_COUNT
) {
498 barvinok_count_with_options(P
, &cb
, options
->verify
.barvinok
);
499 notzero
= value_notzero_p(cb
);
505 while (P
&& !emptyQ2(P
) && P
->NbEq
> 0) {
507 Matrix
*T2
= remove_equalities(&P
, 0, options
->verify
.barvinok
->MaxRays
);
512 Matrix
*T3
= Matrix_Alloc(T
->NbRows
, T2
->NbColumns
);
513 Matrix_Product(T
, T2
, T3
);
523 sample
= Polyhedron_Sample(P
, options
->verify
.barvinok
);
526 Vector
*P_sample
= Vector_Alloc(Porig
->Dimension
+ 1);
527 Matrix_Vector_Product(T
, sample
->p
, P_sample
->p
);
538 assert(in_domain(Porig
, sample
->p
));
540 return sample
!= NULL
;