6 #define partition STL_PARTITION
10 #include <NTL/vec_ZZ.h>
11 #include <NTL/mat_ZZ.h>
12 #include <barvinok/barvinok.h>
13 #include <barvinok/evalue.h>
14 #include <barvinok/options.h>
15 #include <barvinok/util.h>
16 #include "conversion.h"
17 #include "decomposer.h"
18 #include "lattice_point.h"
19 #include "reduce_domain.h"
22 #include "evalue_util.h"
23 #include "remove_equalities.h"
27 #include "param_util.h"
29 #undef CS /* for Solaris 10 */
42 #define ALLOC(type) (type*)malloc(sizeof(type))
43 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
45 static int type_offset(enode
*p
)
47 return p
->type
== fractional
? 1 :
48 p
->type
== flooring
? 1 : 0;
51 void compute_evalue(evalue
*e
, Value
*val
, Value
*res
)
53 double d
= compute_evalue(e
, val
);
58 value_set_double(*res
, d
);
61 struct indicator_term
{
63 int pos
; /* number of rational vertex */
64 int n
; /* number of cone associated to given rational vertex */
68 indicator_term(unsigned dim
, int pos
) {
70 vertex
= new evalue
* [dim
];
75 indicator_term(unsigned dim
, int pos
, int n
) {
76 den
.SetDims(dim
, dim
);
77 vertex
= new evalue
* [dim
];
81 indicator_term(const indicator_term
& src
) {
86 unsigned dim
= den
.NumCols();
87 vertex
= new evalue
* [dim
];
88 for (int i
= 0; i
< dim
; ++i
) {
89 vertex
[i
] = new evalue();
90 value_init(vertex
[i
]->d
);
91 evalue_copy(vertex
[i
], src
.vertex
[i
]);
94 void swap(indicator_term
*other
) {
96 tmp
= sign
; sign
= other
->sign
; other
->sign
= tmp
;
97 tmp
= pos
; pos
= other
->pos
; other
->pos
= tmp
;
98 tmp
= n
; n
= other
->n
; other
->n
= tmp
;
99 mat_ZZ tmp_den
= den
; den
= other
->den
; other
->den
= tmp_den
;
100 unsigned dim
= den
.NumCols();
101 for (int i
= 0; i
< dim
; ++i
) {
102 evalue
*tmp
= vertex
[i
];
103 vertex
[i
] = other
->vertex
[i
];
104 other
->vertex
[i
] = tmp
;
108 unsigned dim
= den
.NumCols();
109 for (int i
= 0; i
< dim
; ++i
)
110 evalue_free(vertex
[i
]);
113 void print(ostream
& os
, char **p
) const;
114 void substitute(Matrix
*T
);
116 void substitute(evalue
*fract
, evalue
*val
);
117 void substitute(int pos
, evalue
*val
);
118 void reduce_in_domain(Polyhedron
*D
);
119 bool is_opposite(const indicator_term
*neg
) const;
120 vec_ZZ
eval(Value
*val
) const {
122 unsigned dim
= den
.NumCols();
126 for (int i
= 0; i
< dim
; ++i
) {
127 compute_evalue(vertex
[i
], val
, &tmp
);
135 static int evalue_rational_cmp(const evalue
*e1
, const evalue
*e2
)
143 assert(value_notzero_p(e1
->d
));
144 assert(value_notzero_p(e2
->d
));
145 value_multiply(m
, e1
->x
.n
, e2
->d
);
146 value_multiply(m2
, e2
->x
.n
, e1
->d
);
149 else if (value_gt(m
, m2
))
159 static int evalue_cmp(const evalue
*e1
, const evalue
*e2
)
161 if (value_notzero_p(e1
->d
)) {
162 if (value_zero_p(e2
->d
))
164 return evalue_rational_cmp(e1
, e2
);
166 if (value_notzero_p(e2
->d
))
168 if (e1
->x
.p
->type
!= e2
->x
.p
->type
)
169 return e1
->x
.p
->type
- e2
->x
.p
->type
;
170 if (e1
->x
.p
->size
!= e2
->x
.p
->size
)
171 return e1
->x
.p
->size
- e2
->x
.p
->size
;
172 if (e1
->x
.p
->pos
!= e2
->x
.p
->pos
)
173 return e1
->x
.p
->pos
- e2
->x
.p
->pos
;
174 assert(e1
->x
.p
->type
== polynomial
||
175 e1
->x
.p
->type
== fractional
||
176 e1
->x
.p
->type
== flooring
);
177 for (int i
= 0; i
< e1
->x
.p
->size
; ++i
) {
178 int s
= evalue_cmp(&e1
->x
.p
->arr
[i
], &e2
->x
.p
->arr
[i
]);
185 void evalue_length(evalue
*e
, int len
[2])
190 while (value_zero_p(e
->d
)) {
191 assert(e
->x
.p
->type
== polynomial
||
192 e
->x
.p
->type
== fractional
||
193 e
->x
.p
->type
== flooring
);
194 if (e
->x
.p
->type
== polynomial
)
198 int offset
= type_offset(e
->x
.p
);
199 assert(e
->x
.p
->size
== offset
+2);
200 e
= &e
->x
.p
->arr
[offset
];
204 static bool it_smaller(const indicator_term
* it1
, const indicator_term
* it2
)
208 int len1
[2], len2
[2];
209 unsigned dim
= it1
->den
.NumCols();
210 for (int i
= 0; i
< dim
; ++i
) {
211 evalue_length(it1
->vertex
[i
], len1
);
212 evalue_length(it2
->vertex
[i
], len2
);
213 if (len1
[0] != len2
[0])
214 return len1
[0] < len2
[0];
215 if (len1
[1] != len2
[1])
216 return len1
[1] < len2
[1];
218 if (it1
->pos
!= it2
->pos
)
219 return it1
->pos
< it2
->pos
;
220 if (it1
->n
!= it2
->n
)
221 return it1
->n
< it2
->n
;
222 int s
= lex_cmp(it1
->den
, it2
->den
);
225 for (int i
= 0; i
< dim
; ++i
) {
226 s
= evalue_cmp(it1
->vertex
[i
], it2
->vertex
[i
]);
230 assert(it1
->sign
!= 0);
231 assert(it2
->sign
!= 0);
232 if (it1
->sign
!= it2
->sign
)
233 return it1
->sign
> 0;
238 static const int requires_resort
;
239 bool operator()(const indicator_term
* it1
, const indicator_term
* it2
) const {
240 return it_smaller(it1
, it2
);
243 const int smaller_it::requires_resort
= 1;
245 struct smaller_it_p
{
246 static const int requires_resort
;
247 bool operator()(const indicator_term
* it1
, const indicator_term
* it2
) const {
251 const int smaller_it_p::requires_resort
= 0;
253 /* Returns true if this and neg are opposite using the knowledge
254 * that they have the same numerator.
255 * In particular, we check that the signs are different and that
256 * the denominator is the same.
258 bool indicator_term::is_opposite(const indicator_term
*neg
) const
260 if (sign
+ neg
->sign
!= 0)
267 void indicator_term::reduce_in_domain(Polyhedron
*D
)
269 for (int k
= 0; k
< den
.NumCols(); ++k
) {
270 reduce_evalue_in_domain(vertex
[k
], D
);
271 if (evalue_range_reduction_in_domain(vertex
[k
], D
))
272 reduce_evalue(vertex
[k
]);
276 void indicator_term::print(ostream
& os
, char **p
) const
278 unsigned dim
= den
.NumCols();
279 unsigned factors
= den
.NumRows();
287 for (int i
= 0; i
< dim
; ++i
) {
290 evalue_print(os
, vertex
[i
], p
);
293 for (int i
= 0; i
< factors
; ++i
) {
294 os
<< " + t" << i
<< "*[";
295 for (int j
= 0; j
< dim
; ++j
) {
302 os
<< " ((" << pos
<< ", " << n
<< ", " << (void*)this << "))";
305 /* Perform the substitution specified by T on the variables.
306 * T has dimension (newdim+nparam+1) x (olddim + nparam + 1).
307 * The substitution is performed as in gen_fun::substitute
309 void indicator_term::substitute(Matrix
*T
)
311 unsigned dim
= den
.NumCols();
312 unsigned nparam
= T
->NbColumns
- dim
- 1;
313 unsigned newdim
= T
->NbRows
- nparam
- 1;
316 matrix2zz(T
, trans
, newdim
, dim
);
317 trans
= transpose(trans
);
319 newvertex
= new evalue
* [newdim
];
322 v
.SetLength(nparam
+1);
325 value_init(factor
.d
);
326 value_set_si(factor
.d
, 1);
327 value_init(factor
.x
.n
);
328 for (int i
= 0; i
< newdim
; ++i
) {
329 values2zz(T
->p
[i
]+dim
, v
, nparam
+1);
330 newvertex
[i
] = multi_monom(v
);
332 for (int j
= 0; j
< dim
; ++j
) {
333 if (value_zero_p(T
->p
[i
][j
]))
337 evalue_copy(&term
, vertex
[j
]);
338 value_assign(factor
.x
.n
, T
->p
[i
][j
]);
339 emul(&factor
, &term
);
340 eadd(&term
, newvertex
[i
]);
341 free_evalue_refs(&term
);
344 free_evalue_refs(&factor
);
345 for (int i
= 0; i
< dim
; ++i
)
346 evalue_free(vertex
[i
]);
351 static void evalue_add_constant(evalue
*e
, ZZ v
)
356 /* go down to constant term */
357 while (value_zero_p(e
->d
))
358 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)];
361 value_multiply(tmp
, tmp
, e
->d
);
362 value_addto(e
->x
.n
, e
->x
.n
, tmp
);
367 /* Make all powers in denominator lexico-positive */
368 void indicator_term::normalize()
371 extra_vertex
.SetLength(den
.NumCols());
372 for (int r
= 0; r
< den
.NumRows(); ++r
) {
373 for (int k
= 0; k
< den
.NumCols(); ++k
) {
380 extra_vertex
+= den
[r
];
384 for (int k
= 0; k
< extra_vertex
.length(); ++k
)
385 if (extra_vertex
[k
] != 0)
386 evalue_add_constant(vertex
[k
], extra_vertex
[k
]);
389 static void substitute(evalue
*e
, evalue
*fract
, evalue
*val
)
393 for (t
= e
; value_zero_p(t
->d
); t
= &t
->x
.p
->arr
[type_offset(t
->x
.p
)]) {
394 if (t
->x
.p
->type
== fractional
&& eequal(&t
->x
.p
->arr
[0], fract
))
397 if (value_notzero_p(t
->d
))
400 free_evalue_refs(&t
->x
.p
->arr
[0]);
401 evalue
*term
= &t
->x
.p
->arr
[2];
408 free_evalue_refs(term
);
414 void indicator_term::substitute(evalue
*fract
, evalue
*val
)
416 unsigned dim
= den
.NumCols();
417 for (int i
= 0; i
< dim
; ++i
) {
418 ::substitute(vertex
[i
], fract
, val
);
422 static void substitute(evalue
*e
, int pos
, evalue
*val
)
426 for (t
= e
; value_zero_p(t
->d
); t
= &t
->x
.p
->arr
[type_offset(t
->x
.p
)]) {
427 if (t
->x
.p
->type
== polynomial
&& t
->x
.p
->pos
== pos
)
430 if (value_notzero_p(t
->d
))
433 evalue
*term
= &t
->x
.p
->arr
[1];
440 free_evalue_refs(term
);
446 void indicator_term::substitute(int pos
, evalue
*val
)
448 unsigned dim
= den
.NumCols();
449 for (int i
= 0; i
< dim
; ++i
) {
450 ::substitute(vertex
[i
], pos
, val
);
454 struct indicator_constructor
: public signed_cone_consumer
,
455 public vertex_decomposer
{
457 vector
<indicator_term
*> *terms
;
458 Matrix
*T
; /* Transformation to original space */
463 indicator_constructor(Polyhedron
*P
, unsigned dim
, Param_Polyhedron
*PP
,
465 vertex_decomposer(PP
, *this), T(T
), nbV(PP
->nbV
) {
466 vertex
.SetLength(dim
);
467 terms
= new vector
<indicator_term
*>[PP
->nbV
];
469 ~indicator_constructor() {
470 for (int i
= 0; i
< nbV
; ++i
)
471 for (int j
= 0; j
< terms
[i
].size(); ++j
)
475 void substitute(Matrix
*T
);
477 void print(ostream
& os
, char **p
);
479 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
);
480 void decompose_at_vertex(Param_Vertices
*V
, int _i
,
481 barvinok_options
*options
) {
484 vertex_decomposer::decompose_at_vertex(V
, _i
, options
);
488 void indicator_constructor::handle(const signed_cone
& sc
, barvinok_options
*options
)
491 unsigned dim
= vertex
.length();
493 assert(sc
.rays
.NumRows() == dim
);
495 indicator_term
*term
= new indicator_term(dim
, pos
, n
++);
496 term
->sign
= sc
.sign
;
497 terms
[vert
].push_back(term
);
499 lattice_point(V
, sc
.rays
, vertex
, term
->vertex
, options
);
502 for (int r
= 0; r
< dim
; ++r
) {
503 for (int j
= 0; j
< dim
; ++j
) {
504 if (term
->den
[r
][j
] == 0)
506 if (term
->den
[r
][j
] > 0)
508 term
->sign
= -term
->sign
;
509 term
->den
[r
] = -term
->den
[r
];
510 vertex
+= term
->den
[r
];
515 for (int i
= 0; i
< dim
; ++i
) {
516 if (!term
->vertex
[i
]) {
517 term
->vertex
[i
] = ALLOC(evalue
);
518 value_init(term
->vertex
[i
]->d
);
519 value_init(term
->vertex
[i
]->x
.n
);
520 zz2value(vertex
[i
], term
->vertex
[i
]->x
.n
);
521 value_set_si(term
->vertex
[i
]->d
, 1);
526 evalue_add_constant(term
->vertex
[i
], vertex
[i
]);
534 lex_order_rows(term
->den
);
537 void indicator_constructor::print(ostream
& os
, char **p
)
539 for (int i
= 0; i
< PP
->nbV
; ++i
)
540 for (int j
= 0; j
< terms
[i
].size(); ++j
) {
541 os
<< "i: " << i
<< ", j: " << j
<< endl
;
542 terms
[i
][j
]->print(os
, p
);
547 void indicator_constructor::normalize()
549 for (int i
= 0; i
< PP
->nbV
; ++i
)
550 for (int j
= 0; j
< terms
[i
].size(); ++j
) {
552 vertex
.SetLength(terms
[i
][j
]->den
.NumCols());
553 for (int r
= 0; r
< terms
[i
][j
]->den
.NumRows(); ++r
) {
554 for (int k
= 0; k
< terms
[i
][j
]->den
.NumCols(); ++k
) {
555 if (terms
[i
][j
]->den
[r
][k
] == 0)
557 if (terms
[i
][j
]->den
[r
][k
] > 0)
559 terms
[i
][j
]->sign
= -terms
[i
][j
]->sign
;
560 terms
[i
][j
]->den
[r
] = -terms
[i
][j
]->den
[r
];
561 vertex
+= terms
[i
][j
]->den
[r
];
565 lex_order_rows(terms
[i
][j
]->den
);
566 for (int k
= 0; k
< vertex
.length(); ++k
)
568 evalue_add_constant(terms
[i
][j
]->vertex
[k
], vertex
[k
]);
572 struct order_cache_el
{
574 order_cache_el
copy() const {
576 for (int i
= 0; i
< e
.size(); ++i
) {
577 evalue
*c
= new evalue
;
579 evalue_copy(c
, e
[i
]);
585 for (int i
= 0; i
< e
.size(); ++i
) {
586 free_evalue_refs(e
[i
]);
593 evalue_set_si(&mone
, -1, 1);
594 for (int i
= 0; i
< e
.size(); ++i
)
596 free_evalue_refs(&mone
);
598 void print(ostream
& os
, char **p
);
601 void order_cache_el::print(ostream
& os
, char **p
)
604 for (int i
= 0; i
< e
.size(); ++i
) {
607 evalue_print(os
, e
[i
], p
);
613 vector
<order_cache_el
> lt
;
614 vector
<order_cache_el
> le
;
615 vector
<order_cache_el
> unknown
;
617 void clear_transients() {
618 for (int i
= 0; i
< le
.size(); ++i
)
620 for (int i
= 0; i
< unknown
.size(); ++i
)
627 for (int i
= 0; i
< lt
.size(); ++i
)
631 void add(order_cache_el
& cache_el
, order_sign sign
);
632 order_sign
check_lt(vector
<order_cache_el
>* list
,
633 const indicator_term
*a
, const indicator_term
*b
,
634 order_cache_el
& cache_el
);
635 order_sign
check_lt(const indicator_term
*a
, const indicator_term
*b
,
636 order_cache_el
& cache_el
);
637 order_sign
check_direct(const indicator_term
*a
, const indicator_term
*b
,
638 order_cache_el
& cache_el
);
639 order_sign
check(const indicator_term
*a
, const indicator_term
*b
,
640 order_cache_el
& cache_el
);
641 void copy(const order_cache
& cache
);
642 void print(ostream
& os
, char **p
);
645 void order_cache::copy(const order_cache
& cache
)
647 for (int i
= 0; i
< cache
.lt
.size(); ++i
) {
648 order_cache_el n
= cache
.lt
[i
].copy();
653 void order_cache::add(order_cache_el
& cache_el
, order_sign sign
)
655 if (sign
== order_lt
) {
656 lt
.push_back(cache_el
);
657 } else if (sign
== order_gt
) {
659 lt
.push_back(cache_el
);
660 } else if (sign
== order_le
) {
661 le
.push_back(cache_el
);
662 } else if (sign
== order_ge
) {
664 le
.push_back(cache_el
);
665 } else if (sign
== order_unknown
) {
666 unknown
.push_back(cache_el
);
668 assert(sign
== order_eq
);
675 static evalue
*ediff(const evalue
*a
, const evalue
*b
)
679 evalue_set_si(&mone
, -1, 1);
680 evalue
*diff
= new evalue
;
682 evalue_copy(diff
, b
);
686 free_evalue_refs(&mone
);
690 static bool evalue_first_difference(const evalue
*e1
, const evalue
*e2
,
691 const evalue
**d1
, const evalue
**d2
)
696 if (value_ne(e1
->d
, e2
->d
))
699 if (value_notzero_p(e1
->d
)) {
700 if (value_eq(e1
->x
.n
, e2
->x
.n
))
704 if (e1
->x
.p
->type
!= e2
->x
.p
->type
)
706 if (e1
->x
.p
->size
!= e2
->x
.p
->size
)
708 if (e1
->x
.p
->pos
!= e2
->x
.p
->pos
)
711 assert(e1
->x
.p
->type
== polynomial
||
712 e1
->x
.p
->type
== fractional
||
713 e1
->x
.p
->type
== flooring
);
714 int offset
= type_offset(e1
->x
.p
);
715 assert(e1
->x
.p
->size
== offset
+2);
716 for (int i
= 0; i
< e1
->x
.p
->size
; ++i
)
717 if (i
!= type_offset(e1
->x
.p
) &&
718 !eequal(&e1
->x
.p
->arr
[i
], &e2
->x
.p
->arr
[i
]))
721 return evalue_first_difference(&e1
->x
.p
->arr
[offset
],
722 &e2
->x
.p
->arr
[offset
], d1
, d2
);
725 static order_sign
evalue_diff_constant_sign(const evalue
*e1
, const evalue
*e2
)
727 if (!evalue_first_difference(e1
, e2
, &e1
, &e2
))
729 if (value_zero_p(e1
->d
) || value_zero_p(e2
->d
))
730 return order_undefined
;
731 int s
= evalue_rational_cmp(e1
, e2
);
740 order_sign
order_cache::check_lt(vector
<order_cache_el
>* list
,
741 const indicator_term
*a
, const indicator_term
*b
,
742 order_cache_el
& cache_el
)
744 order_sign sign
= order_undefined
;
745 for (int i
= 0; i
< list
->size(); ++i
) {
747 for (j
= cache_el
.e
.size(); j
< (*list
)[i
].e
.size(); ++j
)
748 cache_el
.e
.push_back(ediff(a
->vertex
[j
], b
->vertex
[j
]));
749 for (j
= 0; j
< (*list
)[i
].e
.size(); ++j
) {
750 order_sign diff_sign
;
751 diff_sign
= evalue_diff_constant_sign((*list
)[i
].e
[j
], cache_el
.e
[j
]);
752 if (diff_sign
== order_gt
) {
755 } else if (diff_sign
== order_lt
)
757 else if (diff_sign
== order_undefined
)
760 assert(diff_sign
== order_eq
);
762 if (j
== (*list
)[i
].e
.size())
763 sign
= list
== <
? order_lt
: order_le
;
764 if (sign
!= order_undefined
)
770 order_sign
order_cache::check_direct(const indicator_term
*a
,
771 const indicator_term
*b
,
772 order_cache_el
& cache_el
)
774 order_sign sign
= check_lt(<
, a
, b
, cache_el
);
775 if (sign
!= order_undefined
)
777 sign
= check_lt(&le
, a
, b
, cache_el
);
778 if (sign
!= order_undefined
)
781 for (int i
= 0; i
< unknown
.size(); ++i
) {
783 for (j
= cache_el
.e
.size(); j
< unknown
[i
].e
.size(); ++j
)
784 cache_el
.e
.push_back(ediff(a
->vertex
[j
], b
->vertex
[j
]));
785 for (j
= 0; j
< unknown
[i
].e
.size(); ++j
) {
786 if (!eequal(unknown
[i
].e
[j
], cache_el
.e
[j
]))
789 if (j
== unknown
[i
].e
.size()) {
790 sign
= order_unknown
;
797 order_sign
order_cache::check(const indicator_term
*a
, const indicator_term
*b
,
798 order_cache_el
& cache_el
)
800 order_sign sign
= check_direct(a
, b
, cache_el
);
801 if (sign
!= order_undefined
)
803 int size
= cache_el
.e
.size();
805 sign
= check_direct(a
, b
, cache_el
);
807 assert(cache_el
.e
.size() == size
);
808 if (sign
== order_undefined
)
810 if (sign
== order_lt
)
812 else if (sign
== order_le
)
815 assert(sign
== order_unknown
);
821 struct partial_order
{
824 typedef std::set
<const indicator_term
*, smaller_it
> head_type
;
826 typedef map
<const indicator_term
*, int, smaller_it
> pred_type
;
828 typedef map
<const indicator_term
*, vector
<const indicator_term
* >, smaller_it
> order_type
;
837 partial_order(indicator
*ind
) : ind(ind
) {}
838 void copy(const partial_order
& order
,
839 map
< const indicator_term
*, indicator_term
* > old2new
);
841 order_type::iterator i
;
842 pred_type::iterator j
;
843 head_type::iterator k
;
845 if (head
.key_comp().requires_resort
) {
847 for (k
= head
.begin(); k
!= head
.end(); ++k
)
853 if (pred
.key_comp().requires_resort
) {
855 for (j
= pred
.begin(); j
!= pred
.end(); ++j
)
856 new_pred
[(*j
).first
] = (*j
).second
;
861 if (lt
.key_comp().requires_resort
) {
863 for (i
= lt
.begin(); i
!= lt
.end(); ++i
)
864 m
[(*i
).first
] = (*i
).second
;
869 if (le
.key_comp().requires_resort
) {
871 for (i
= le
.begin(); i
!= le
.end(); ++i
)
872 m
[(*i
).first
] = (*i
).second
;
877 if (eq
.key_comp().requires_resort
) {
879 for (i
= eq
.begin(); i
!= eq
.end(); ++i
)
880 m
[(*i
).first
] = (*i
).second
;
885 if (pending
.key_comp().requires_resort
) {
887 for (i
= pending
.begin(); i
!= pending
.end(); ++i
)
888 m
[(*i
).first
] = (*i
).second
;
894 order_sign
compare(const indicator_term
*a
, const indicator_term
*b
);
895 void set_equal(const indicator_term
*a
, const indicator_term
*b
);
896 void unset_le(const indicator_term
*a
, const indicator_term
*b
);
897 void dec_pred(const indicator_term
*it
) {
898 if (--pred
[it
] == 0) {
903 void inc_pred(const indicator_term
*it
) {
904 if (head
.find(it
) != head
.end())
909 bool compared(const indicator_term
* a
, const indicator_term
* b
);
910 void add(const indicator_term
* it
, std::set
<const indicator_term
*> *filter
);
911 void remove(const indicator_term
* it
);
913 void print(ostream
& os
, char **p
);
915 /* replace references to orig to references to replacement */
916 void replace(const indicator_term
* orig
, indicator_term
* replacement
);
917 void sanity_check() const;
920 /* We actually replace the contents of orig by that of replacement,
921 * but we have to be careful since replacing the content changes
922 * the order of orig in the maps.
924 void partial_order::replace(const indicator_term
* orig
, indicator_term
* replacement
)
926 head_type::iterator k
;
928 bool is_head
= k
!= head
.end();
933 orig_pred
= pred
[orig
];
936 vector
<const indicator_term
* > orig_lt
;
937 vector
<const indicator_term
* > orig_le
;
938 vector
<const indicator_term
* > orig_eq
;
939 vector
<const indicator_term
* > orig_pending
;
940 order_type::iterator i
;
941 bool in_lt
= ((i
= lt
.find(orig
)) != lt
.end());
943 orig_lt
= (*i
).second
;
946 bool in_le
= ((i
= le
.find(orig
)) != le
.end());
948 orig_le
= (*i
).second
;
951 bool in_eq
= ((i
= eq
.find(orig
)) != eq
.end());
953 orig_eq
= (*i
).second
;
956 bool in_pending
= ((i
= pending
.find(orig
)) != pending
.end());
958 orig_pending
= (*i
).second
;
961 indicator_term
*old
= const_cast<indicator_term
*>(orig
);
962 old
->swap(replacement
);
966 pred
[old
] = orig_pred
;
974 pending
[old
] = orig_pending
;
977 void partial_order::unset_le(const indicator_term
*a
, const indicator_term
*b
)
979 vector
<const indicator_term
*>::iterator i
;
980 i
= std::find(le
[a
].begin(), le
[a
].end(), b
);
982 if (le
[a
].size() == 0)
985 i
= std::find(pending
[a
].begin(), pending
[a
].end(), b
);
986 if (i
!= pending
[a
].end())
990 void partial_order::set_equal(const indicator_term
*a
, const indicator_term
*b
)
992 if (eq
[a
].size() == 0)
994 if (eq
[b
].size() == 0)
999 if (pred
.key_comp()(b
, a
)) {
1000 const indicator_term
*c
= a
;
1005 const indicator_term
*base
= a
;
1007 order_type::iterator i
;
1009 for (int j
= 0; j
< eq
[b
].size(); ++j
) {
1010 eq
[base
].push_back(eq
[b
][j
]);
1011 eq
[eq
[b
][j
]][0] = base
;
1016 if (i
!= lt
.end()) {
1017 for (int j
= 0; j
< lt
[b
].size(); ++j
) {
1018 if (std::find(eq
[base
].begin(), eq
[base
].end(), lt
[b
][j
]) != eq
[base
].end())
1020 else if (std::find(lt
[base
].begin(), lt
[base
].end(), lt
[b
][j
])
1024 lt
[base
].push_back(lt
[b
][j
]);
1030 if (i
!= le
.end()) {
1031 for (int j
= 0; j
< le
[b
].size(); ++j
) {
1032 if (std::find(eq
[base
].begin(), eq
[base
].end(), le
[b
][j
]) != eq
[base
].end())
1034 else if (std::find(le
[base
].begin(), le
[base
].end(), le
[b
][j
])
1038 le
[base
].push_back(le
[b
][j
]);
1043 i
= pending
.find(base
);
1044 if (i
!= pending
.end()) {
1045 vector
<const indicator_term
* > old
= pending
[base
];
1046 pending
[base
].clear();
1047 for (int j
= 0; j
< old
.size(); ++j
) {
1048 if (std::find(eq
[base
].begin(), eq
[base
].end(), old
[j
]) == eq
[base
].end())
1049 pending
[base
].push_back(old
[j
]);
1053 i
= pending
.find(b
);
1054 if (i
!= pending
.end()) {
1055 for (int j
= 0; j
< pending
[b
].size(); ++j
) {
1056 if (std::find(eq
[base
].begin(), eq
[base
].end(), pending
[b
][j
]) == eq
[base
].end())
1057 pending
[base
].push_back(pending
[b
][j
]);
1063 void partial_order::copy(const partial_order
& order
,
1064 map
< const indicator_term
*, indicator_term
* > old2new
)
1066 cache
.copy(order
.cache
);
1068 order_type::const_iterator i
;
1069 pred_type::const_iterator j
;
1070 head_type::const_iterator k
;
1072 for (k
= order
.head
.begin(); k
!= order
.head
.end(); ++k
)
1073 head
.insert(old2new
[*k
]);
1075 for (j
= order
.pred
.begin(); j
!= order
.pred
.end(); ++j
)
1076 pred
[old2new
[(*j
).first
]] = (*j
).second
;
1078 for (i
= order
.lt
.begin(); i
!= order
.lt
.end(); ++i
) {
1079 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1080 lt
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1082 for (i
= order
.le
.begin(); i
!= order
.le
.end(); ++i
) {
1083 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1084 le
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1086 for (i
= order
.eq
.begin(); i
!= order
.eq
.end(); ++i
) {
1087 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1088 eq
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1090 for (i
= order
.pending
.begin(); i
!= order
.pending
.end(); ++i
) {
1091 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1092 pending
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1098 vector
<evalue
*> max
;
1100 void print(ostream
& os
, char **p
, barvinok_options
*options
) const;
1101 void substitute(Matrix
*T
, barvinok_options
*options
);
1102 Vector
*eval(Value
*val
, unsigned MaxRays
) const;
1105 for (int i
= 0; i
< max
.size(); ++i
) {
1106 free_evalue_refs(max
[i
]);
1114 * Project on first dim dimensions
1116 Polyhedron
* Polyhedron_Project_Initial(Polyhedron
*P
, int dim
)
1122 if (P
->Dimension
== dim
)
1123 return Polyhedron_Copy(P
);
1125 T
= Matrix_Alloc(dim
+1, P
->Dimension
+1);
1126 for (i
= 0; i
< dim
; ++i
)
1127 value_set_si(T
->p
[i
][i
], 1);
1128 value_set_si(T
->p
[dim
][P
->Dimension
], 1);
1129 I
= Polyhedron_Image(P
, T
, P
->NbConstraints
);
1135 vector
<indicator_term
*> term
;
1136 indicator_constructor
& ic
;
1137 partial_order order
;
1141 lexmin_options
*options
;
1142 vector
<evalue
*> substitutions
;
1144 indicator(indicator_constructor
& ic
, Param_Domain
*PD
, EDomain
*D
,
1145 lexmin_options
*options
) :
1146 ic(ic
), PD(PD
), D(D
), order(this), options(options
), P(NULL
) {}
1147 indicator(const indicator
& ind
, EDomain
*D
) :
1148 ic(ind
.ic
), PD(ind
.PD
), D(NULL
), order(this), options(ind
.options
),
1149 P(Polyhedron_Copy(ind
.P
)) {
1150 map
< const indicator_term
*, indicator_term
* > old2new
;
1151 for (int i
= 0; i
< ind
.term
.size(); ++i
) {
1152 indicator_term
*it
= new indicator_term(*ind
.term
[i
]);
1153 old2new
[ind
.term
[i
]] = it
;
1156 order
.copy(ind
.order
, old2new
);
1160 for (int i
= 0; i
< term
.size(); ++i
)
1168 void set_domain(EDomain
*D
) {
1169 order
.cache
.clear_transients();
1173 int nparam
= ic
.PP
->Constraints
->NbColumns
-2 - ic
.vertex
.length();
1174 if (options
->reduce
) {
1175 Polyhedron
*Q
= Polyhedron_Project_Initial(D
->D
, nparam
);
1176 Q
= DomainConstraintSimplify(Q
, options
->verify
->barvinok
->MaxRays
);
1177 if (!P
|| !PolyhedronIncludes(Q
, P
))
1178 reduce_in_domain(Q
);
1186 void add(const indicator_term
* it
);
1187 void remove(const indicator_term
* it
);
1188 void remove_initial_rational_vertices();
1189 void expand_rational_vertex(const indicator_term
*initial
);
1191 void print(ostream
& os
, char **p
);
1193 void peel(int i
, int j
);
1194 void combine(const indicator_term
*a
, const indicator_term
*b
);
1195 void add_substitution(evalue
*equation
);
1196 void perform_pending_substitutions();
1197 void reduce_in_domain(Polyhedron
*D
);
1198 bool handle_equal_numerators(const indicator_term
*base
);
1200 max_term
* create_max_term(const indicator_term
*it
);
1202 void substitute(evalue
*equation
);
1205 void partial_order::sanity_check() const
1207 order_type::const_iterator i
;
1208 order_type::const_iterator prev
;
1209 order_type::const_iterator l
;
1210 pred_type::const_iterator k
, prev_k
;
1212 for (k
= pred
.begin(); k
!= pred
.end(); prev_k
= k
, ++k
)
1213 if (k
!= pred
.begin())
1214 assert(pred
.key_comp()((*prev_k
).first
, (*k
).first
));
1215 for (i
= lt
.begin(); i
!= lt
.end(); prev
= i
, ++i
) {
1218 i_v
= (*i
).first
->eval(ind
->D
->sample
->p
);
1219 if (i
!= lt
.begin())
1220 assert(lt
.key_comp()((*prev
).first
, (*i
).first
));
1221 l
= eq
.find((*i
).first
);
1223 assert((*l
).second
.size() > 1);
1224 assert(head
.find((*i
).first
) != head
.end() ||
1225 pred
.find((*i
).first
) != pred
.end());
1226 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1227 k
= pred
.find((*i
).second
[j
]);
1228 assert(k
!= pred
.end());
1229 assert((*k
).second
!= 0);
1230 if ((*i
).first
->sign
!= 0 &&
1231 (*i
).second
[j
]->sign
!= 0 && ind
->D
->sample
) {
1232 vec_ZZ j_v
= (*i
).second
[j
]->eval(ind
->D
->sample
->p
);
1233 assert(lex_cmp(i_v
, j_v
) < 0);
1237 for (i
= le
.begin(); i
!= le
.end(); ++i
) {
1238 assert((*i
).second
.size() > 0);
1239 assert(head
.find((*i
).first
) != head
.end() ||
1240 pred
.find((*i
).first
) != pred
.end());
1241 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1242 k
= pred
.find((*i
).second
[j
]);
1243 assert(k
!= pred
.end());
1244 assert((*k
).second
!= 0);
1247 for (i
= eq
.begin(); i
!= eq
.end(); ++i
) {
1248 assert(head
.find((*i
).first
) != head
.end() ||
1249 pred
.find((*i
).first
) != pred
.end());
1250 assert((*i
).second
.size() >= 1);
1252 for (i
= pending
.begin(); i
!= pending
.end(); ++i
) {
1253 assert(head
.find((*i
).first
) != head
.end() ||
1254 pred
.find((*i
).first
) != pred
.end());
1255 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1256 assert(head
.find((*i
).second
[j
]) != head
.end() ||
1257 pred
.find((*i
).second
[j
]) != pred
.end());
1261 max_term
* indicator::create_max_term(const indicator_term
*it
)
1263 int dim
= it
->den
.NumCols();
1264 int nparam
= ic
.PP
->Constraints
->NbColumns
-2 - ic
.vertex
.length();
1265 max_term
*maximum
= new max_term
;
1266 maximum
->domain
= new EDomain(D
);
1267 for (int j
= 0; j
< dim
; ++j
) {
1268 evalue
*E
= new evalue
;
1270 evalue_copy(E
, it
->vertex
[j
]);
1271 if (evalue_frac2floor_in_domain(E
, D
->D
))
1273 maximum
->max
.push_back(E
);
1278 static order_sign
evalue_sign(evalue
*diff
, EDomain
*D
, barvinok_options
*options
)
1280 order_sign sign
= order_eq
;
1283 evalue_set_si(&mone
, -1, 1);
1284 int len
= 1 + D
->D
->Dimension
+ 1;
1285 Vector
*c
= Vector_Alloc(len
);
1286 Matrix
*T
= Matrix_Alloc(2, len
-1);
1288 int fract
= evalue2constraint(D
, diff
, c
->p
, len
);
1289 Vector_Copy(c
->p
+1, T
->p
[0], len
-1);
1290 value_assign(T
->p
[1][len
-2], c
->p
[0]);
1292 order_sign upper_sign
= polyhedron_affine_sign(D
->D
, T
, options
);
1293 if (upper_sign
== order_lt
|| !fract
)
1297 evalue2constraint(D
, diff
, c
->p
, len
);
1299 Vector_Copy(c
->p
+1, T
->p
[0], len
-1);
1300 value_assign(T
->p
[1][len
-2], c
->p
[0]);
1302 order_sign neg_lower_sign
= polyhedron_affine_sign(D
->D
, T
, options
);
1304 if (neg_lower_sign
== order_lt
)
1306 else if (neg_lower_sign
== order_eq
|| neg_lower_sign
== order_le
) {
1307 if (upper_sign
== order_eq
|| upper_sign
== order_le
)
1312 if (upper_sign
== order_lt
|| upper_sign
== order_le
||
1313 upper_sign
== order_eq
)
1316 sign
= order_unknown
;
1322 free_evalue_refs(&mone
);
1327 /* An auxiliary class that keeps a reference to an evalue
1328 * and frees it when it goes out of scope.
1330 struct temp_evalue
{
1332 temp_evalue() : E(NULL
) {}
1333 temp_evalue(evalue
*e
) : E(e
) {}
1334 operator evalue
* () const { return E
; }
1335 evalue
*operator=(evalue
*e
) {
1337 free_evalue_refs(E
);
1345 free_evalue_refs(E
);
1351 static void substitute(vector
<indicator_term
*>& term
, evalue
*equation
)
1353 evalue
*fract
= NULL
;
1354 evalue
*val
= new evalue
;
1356 evalue_copy(val
, equation
);
1359 value_init(factor
.d
);
1360 value_init(factor
.x
.n
);
1363 for (e
= val
; value_zero_p(e
->d
) && e
->x
.p
->type
!= fractional
;
1364 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)])
1367 if (value_zero_p(e
->d
) && e
->x
.p
->type
== fractional
)
1368 fract
= &e
->x
.p
->arr
[0];
1370 for (e
= val
; value_zero_p(e
->d
) && e
->x
.p
->type
!= polynomial
;
1371 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)])
1373 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== polynomial
);
1376 int offset
= type_offset(e
->x
.p
);
1378 assert(value_notzero_p(e
->x
.p
->arr
[offset
+1].d
));
1379 assert(value_notzero_p(e
->x
.p
->arr
[offset
+1].x
.n
));
1380 if (value_neg_p(e
->x
.p
->arr
[offset
+1].x
.n
)) {
1381 value_oppose(factor
.d
, e
->x
.p
->arr
[offset
+1].x
.n
);
1382 value_assign(factor
.x
.n
, e
->x
.p
->arr
[offset
+1].d
);
1384 value_assign(factor
.d
, e
->x
.p
->arr
[offset
+1].x
.n
);
1385 value_oppose(factor
.x
.n
, e
->x
.p
->arr
[offset
+1].d
);
1388 free_evalue_refs(&e
->x
.p
->arr
[offset
+1]);
1391 *e
= e
->x
.p
->arr
[offset
];
1396 for (int i
= 0; i
< term
.size(); ++i
)
1397 term
[i
]->substitute(fract
, val
);
1399 free_evalue_refs(&p
->arr
[0]);
1401 for (int i
= 0; i
< term
.size(); ++i
)
1402 term
[i
]->substitute(p
->pos
, val
);
1405 free_evalue_refs(&factor
);
1406 free_evalue_refs(val
);
1412 order_sign
partial_order::compare(const indicator_term
*a
, const indicator_term
*b
)
1414 unsigned dim
= a
->den
.NumCols();
1415 order_sign sign
= order_eq
;
1416 EDomain
*D
= ind
->D
;
1417 unsigned MaxRays
= ind
->options
->verify
->barvinok
->MaxRays
;
1418 bool rational
= a
->sign
== 0 || b
->sign
== 0;
1420 order_sign cached_sign
= order_eq
;
1421 for (int k
= 0; k
< dim
; ++k
) {
1422 cached_sign
= evalue_diff_constant_sign(a
->vertex
[k
], b
->vertex
[k
]);
1423 if (cached_sign
!= order_eq
)
1426 if (cached_sign
!= order_undefined
)
1429 order_cache_el cache_el
;
1430 cached_sign
= order_undefined
;
1432 cached_sign
= cache
.check(a
, b
, cache_el
);
1433 if (cached_sign
!= order_undefined
) {
1438 if (rational
&& POL_ISSET(MaxRays
, POL_INTEGER
)) {
1439 ind
->options
->verify
->barvinok
->MaxRays
&= ~POL_INTEGER
;
1440 if (ind
->options
->verify
->barvinok
->MaxRays
)
1441 ind
->options
->verify
->barvinok
->MaxRays
|= POL_HIGH_BIT
;
1446 vector
<indicator_term
*> term
;
1448 for (int k
= 0; k
< dim
; ++k
) {
1449 /* compute a->vertex[k] - b->vertex[k] */
1451 if (cache_el
.e
.size() <= k
) {
1452 diff
= ediff(a
->vertex
[k
], b
->vertex
[k
]);
1453 cache_el
.e
.push_back(diff
);
1455 diff
= cache_el
.e
[k
];
1458 tdiff
= diff
= ediff(term
[0]->vertex
[k
], term
[1]->vertex
[k
]);
1459 order_sign diff_sign
;
1461 diff_sign
= order_undefined
;
1462 else if (eequal(a
->vertex
[k
], b
->vertex
[k
]))
1463 diff_sign
= order_eq
;
1465 diff_sign
= evalue_sign(diff
, D
, ind
->options
->verify
->barvinok
);
1467 if (diff_sign
== order_undefined
) {
1468 assert(sign
== order_le
|| sign
== order_ge
);
1469 if (sign
== order_le
)
1475 if (diff_sign
== order_lt
) {
1476 if (sign
== order_eq
|| sign
== order_le
)
1479 sign
= order_unknown
;
1482 if (diff_sign
== order_gt
) {
1483 if (sign
== order_eq
|| sign
== order_ge
)
1486 sign
= order_unknown
;
1489 if (diff_sign
== order_eq
) {
1490 if (D
== ind
->D
&& term
.size() == 0 && !rational
&&
1491 !EVALUE_IS_ZERO(*diff
))
1492 ind
->add_substitution(diff
);
1495 if ((diff_sign
== order_unknown
) ||
1496 ((diff_sign
== order_lt
|| diff_sign
== order_le
) && sign
== order_ge
) ||
1497 ((diff_sign
== order_gt
|| diff_sign
== order_ge
) && sign
== order_le
)) {
1498 sign
= order_unknown
;
1505 term
.push_back(new indicator_term(*a
));
1506 term
.push_back(new indicator_term(*b
));
1508 substitute(term
, diff
);
1512 cache
.add(cache_el
, sign
);
1516 if (D
&& D
!= ind
->D
)
1524 ind
->options
->verify
->barvinok
->MaxRays
= MaxRays
;
1528 bool partial_order::compared(const indicator_term
* a
, const indicator_term
* b
)
1530 order_type::iterator j
;
1533 if (j
!= lt
.end() && std::find(lt
[a
].begin(), lt
[a
].end(), b
) != lt
[a
].end())
1537 if (j
!= le
.end() && std::find(le
[a
].begin(), le
[a
].end(), b
) != le
[a
].end())
1543 void partial_order::add(const indicator_term
* it
,
1544 std::set
<const indicator_term
*> *filter
)
1546 if (eq
.find(it
) != eq
.end() && eq
[it
].size() == 1)
1549 head_type
head_copy(head
);
1554 head_type::iterator i
;
1555 for (i
= head_copy
.begin(); i
!= head_copy
.end(); ++i
) {
1558 if (eq
.find(*i
) != eq
.end() && eq
[*i
].size() == 1)
1561 if (filter
->find(*i
) == filter
->end())
1563 if (compared(*i
, it
))
1566 order_sign sign
= compare(it
, *i
);
1567 if (sign
== order_lt
) {
1568 lt
[it
].push_back(*i
);
1570 } else if (sign
== order_le
) {
1571 le
[it
].push_back(*i
);
1573 } else if (sign
== order_eq
) {
1576 } else if (sign
== order_gt
) {
1577 pending
[*i
].push_back(it
);
1578 lt
[*i
].push_back(it
);
1580 } else if (sign
== order_ge
) {
1581 pending
[*i
].push_back(it
);
1582 le
[*i
].push_back(it
);
1588 void partial_order::remove(const indicator_term
* it
)
1590 std::set
<const indicator_term
*> filter
;
1591 order_type::iterator i
;
1593 assert(head
.find(it
) != head
.end());
1596 if (i
!= eq
.end()) {
1597 assert(eq
[it
].size() >= 1);
1598 const indicator_term
*base
;
1599 if (eq
[it
].size() == 1) {
1603 vector
<const indicator_term
* >::iterator j
;
1604 j
= std::find(eq
[base
].begin(), eq
[base
].end(), it
);
1605 assert(j
!= eq
[base
].end());
1608 /* "it" may no longer be the smallest, since the order
1609 * structure may have been copied from another one.
1611 std::sort(eq
[it
].begin()+1, eq
[it
].end(), pred
.key_comp());
1612 assert(eq
[it
][0] == it
);
1613 eq
[it
].erase(eq
[it
].begin());
1618 for (int j
= 1; j
< eq
[base
].size(); ++j
)
1619 eq
[eq
[base
][j
]][0] = base
;
1622 if (i
!= lt
.end()) {
1628 if (i
!= le
.end()) {
1633 i
= pending
.find(it
);
1634 if (i
!= pending
.end()) {
1635 pending
[base
] = pending
[it
];
1640 if (eq
[base
].size() == 1)
1649 if (i
!= lt
.end()) {
1650 for (int j
= 0; j
< lt
[it
].size(); ++j
) {
1651 filter
.insert(lt
[it
][j
]);
1652 dec_pred(lt
[it
][j
]);
1658 if (i
!= le
.end()) {
1659 for (int j
= 0; j
< le
[it
].size(); ++j
) {
1660 filter
.insert(le
[it
][j
]);
1661 dec_pred(le
[it
][j
]);
1668 i
= pending
.find(it
);
1669 if (i
!= pending
.end()) {
1670 vector
<const indicator_term
*> it_pending
= pending
[it
];
1672 for (int j
= 0; j
< it_pending
.size(); ++j
) {
1673 filter
.erase(it_pending
[j
]);
1674 add(it_pending
[j
], &filter
);
1679 void partial_order::print(ostream
& os
, char **p
)
1681 order_type::iterator i
;
1682 pred_type::iterator j
;
1683 head_type::iterator k
;
1684 for (k
= head
.begin(); k
!= head
.end(); ++k
) {
1688 for (j
= pred
.begin(); j
!= pred
.end(); ++j
) {
1689 (*j
).first
->print(os
, p
);
1690 os
<< ": " << (*j
).second
<< endl
;
1692 for (i
= lt
.begin(); i
!= lt
.end(); ++i
) {
1693 (*i
).first
->print(os
, p
);
1694 assert(head
.find((*i
).first
) != head
.end() ||
1695 pred
.find((*i
).first
) != pred
.end());
1696 if (pred
.find((*i
).first
) != pred
.end())
1697 os
<< "(" << pred
[(*i
).first
] << ")";
1699 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1702 (*i
).second
[j
]->print(os
, p
);
1703 assert(pred
.find((*i
).second
[j
]) != pred
.end());
1704 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1708 for (i
= le
.begin(); i
!= le
.end(); ++i
) {
1709 (*i
).first
->print(os
, p
);
1710 assert(head
.find((*i
).first
) != head
.end() ||
1711 pred
.find((*i
).first
) != pred
.end());
1712 if (pred
.find((*i
).first
) != pred
.end())
1713 os
<< "(" << pred
[(*i
).first
] << ")";
1715 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1718 (*i
).second
[j
]->print(os
, p
);
1719 assert(pred
.find((*i
).second
[j
]) != pred
.end());
1720 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1724 for (i
= eq
.begin(); i
!= eq
.end(); ++i
) {
1725 if ((*i
).second
.size() <= 1)
1727 (*i
).first
->print(os
, p
);
1728 assert(head
.find((*i
).first
) != head
.end() ||
1729 pred
.find((*i
).first
) != pred
.end());
1730 if (pred
.find((*i
).first
) != pred
.end())
1731 os
<< "(" << pred
[(*i
).first
] << ")";
1732 for (int j
= 1; j
< (*i
).second
.size(); ++j
) {
1735 (*i
).second
[j
]->print(os
, p
);
1736 assert(head
.find((*i
).second
[j
]) != head
.end() ||
1737 pred
.find((*i
).second
[j
]) != pred
.end());
1738 if (pred
.find((*i
).second
[j
]) != pred
.end())
1739 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1743 for (i
= pending
.begin(); i
!= pending
.end(); ++i
) {
1744 os
<< "pending on ";
1745 (*i
).first
->print(os
, p
);
1746 assert(head
.find((*i
).first
) != head
.end() ||
1747 pred
.find((*i
).first
) != pred
.end());
1748 if (pred
.find((*i
).first
) != pred
.end())
1749 os
<< "(" << pred
[(*i
).first
] << ")";
1751 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1754 (*i
).second
[j
]->print(os
, p
);
1755 assert(pred
.find((*i
).second
[j
]) != pred
.end());
1756 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1762 void indicator::add(const indicator_term
* it
)
1764 indicator_term
*nt
= new indicator_term(*it
);
1765 if (options
->reduce
)
1766 nt
->reduce_in_domain(P
? P
: D
->D
);
1768 order
.add(nt
, NULL
);
1769 assert(term
.size() == order
.head
.size() + order
.pred
.size());
1772 void indicator::remove(const indicator_term
* it
)
1774 vector
<indicator_term
*>::iterator i
;
1775 i
= std::find(term
.begin(), term
.end(), it
);
1776 assert(i
!= term
.end());
1779 assert(term
.size() == order
.head
.size() + order
.pred
.size());
1783 void indicator::expand_rational_vertex(const indicator_term
*initial
)
1785 int pos
= initial
->pos
;
1787 if (ic
.terms
[pos
].size() == 0) {
1789 FORALL_PVertex_in_ParamPolyhedron(V
, PD
, ic
.PP
) // _i is internal counter
1791 ic
.decompose_at_vertex(V
, pos
, options
->verify
->barvinok
);
1794 END_FORALL_PVertex_in_ParamPolyhedron
;
1796 for (int j
= 0; j
< ic
.terms
[pos
].size(); ++j
)
1797 add(ic
.terms
[pos
][j
]);
1800 void indicator::remove_initial_rational_vertices()
1803 const indicator_term
*initial
= NULL
;
1804 partial_order::head_type::iterator i
;
1805 for (i
= order
.head
.begin(); i
!= order
.head
.end(); ++i
) {
1806 if ((*i
)->sign
!= 0)
1808 if (order
.eq
.find(*i
) != order
.eq
.end() && order
.eq
[*i
].size() <= 1)
1815 expand_rational_vertex(initial
);
1819 void indicator::reduce_in_domain(Polyhedron
*D
)
1821 for (int i
= 0; i
< term
.size(); ++i
)
1822 term
[i
]->reduce_in_domain(D
);
1825 void indicator::print(ostream
& os
, char **p
)
1827 assert(term
.size() == order
.head
.size() + order
.pred
.size());
1828 for (int i
= 0; i
< term
.size(); ++i
) {
1829 term
[i
]->print(os
, p
);
1831 os
<< ": " << term
[i
]->eval(D
->sample
->p
);
1838 /* Remove pairs of opposite terms */
1839 void indicator::simplify()
1841 for (int i
= 0; i
< term
.size(); ++i
) {
1842 for (int j
= i
+1; j
< term
.size(); ++j
) {
1843 if (term
[i
]->sign
+ term
[j
]->sign
!= 0)
1845 if (term
[i
]->den
!= term
[j
]->den
)
1848 for (k
= 0; k
< term
[i
]->den
.NumCols(); ++k
)
1849 if (!eequal(term
[i
]->vertex
[k
], term
[j
]->vertex
[k
]))
1851 if (k
< term
[i
]->den
.NumCols())
1855 term
.erase(term
.begin()+j
);
1856 term
.erase(term
.begin()+i
);
1863 void indicator::peel(int i
, int j
)
1871 int dim
= term
[i
]->den
.NumCols();
1876 int n_common
= 0, n_i
= 0, n_j
= 0;
1878 common
.SetDims(min(term
[i
]->den
.NumRows(), term
[j
]->den
.NumRows()), dim
);
1879 rest_i
.SetDims(term
[i
]->den
.NumRows(), dim
);
1880 rest_j
.SetDims(term
[j
]->den
.NumRows(), dim
);
1883 for (k
= 0, l
= 0; k
< term
[i
]->den
.NumRows() && l
< term
[j
]->den
.NumRows(); ) {
1884 int s
= lex_cmp(term
[i
]->den
[k
], term
[j
]->den
[l
]);
1886 common
[n_common
++] = term
[i
]->den
[k
];
1890 rest_i
[n_i
++] = term
[i
]->den
[k
++];
1892 rest_j
[n_j
++] = term
[j
]->den
[l
++];
1894 while (k
< term
[i
]->den
.NumRows())
1895 rest_i
[n_i
++] = term
[i
]->den
[k
++];
1896 while (l
< term
[j
]->den
.NumRows())
1897 rest_j
[n_j
++] = term
[j
]->den
[l
++];
1898 common
.SetDims(n_common
, dim
);
1899 rest_i
.SetDims(n_i
, dim
);
1900 rest_j
.SetDims(n_j
, dim
);
1902 for (k
= 0; k
<= n_i
; ++k
) {
1903 indicator_term
*it
= new indicator_term(*term
[i
]);
1904 it
->den
.SetDims(n_common
+ k
, dim
);
1905 for (l
= 0; l
< n_common
; ++l
)
1906 it
->den
[l
] = common
[l
];
1907 for (l
= 0; l
< k
; ++l
)
1908 it
->den
[n_common
+l
] = rest_i
[l
];
1909 lex_order_rows(it
->den
);
1911 for (l
= 0; l
< dim
; ++l
)
1912 evalue_add_constant(it
->vertex
[l
], rest_i
[k
-1][l
]);
1916 for (k
= 0; k
<= n_j
; ++k
) {
1917 indicator_term
*it
= new indicator_term(*term
[j
]);
1918 it
->den
.SetDims(n_common
+ k
, dim
);
1919 for (l
= 0; l
< n_common
; ++l
)
1920 it
->den
[l
] = common
[l
];
1921 for (l
= 0; l
< k
; ++l
)
1922 it
->den
[n_common
+l
] = rest_j
[l
];
1923 lex_order_rows(it
->den
);
1925 for (l
= 0; l
< dim
; ++l
)
1926 evalue_add_constant(it
->vertex
[l
], rest_j
[k
-1][l
]);
1929 term
.erase(term
.begin()+j
);
1930 term
.erase(term
.begin()+i
);
1933 void indicator::combine(const indicator_term
*a
, const indicator_term
*b
)
1935 int dim
= a
->den
.NumCols();
1938 mat_ZZ rest_i
; /* factors in a, but not in b */
1939 mat_ZZ rest_j
; /* factors in b, but not in a */
1940 int n_common
= 0, n_i
= 0, n_j
= 0;
1942 common
.SetDims(min(a
->den
.NumRows(), b
->den
.NumRows()), dim
);
1943 rest_i
.SetDims(a
->den
.NumRows(), dim
);
1944 rest_j
.SetDims(b
->den
.NumRows(), dim
);
1947 for (k
= 0, l
= 0; k
< a
->den
.NumRows() && l
< b
->den
.NumRows(); ) {
1948 int s
= lex_cmp(a
->den
[k
], b
->den
[l
]);
1950 common
[n_common
++] = a
->den
[k
];
1954 rest_i
[n_i
++] = a
->den
[k
++];
1956 rest_j
[n_j
++] = b
->den
[l
++];
1958 while (k
< a
->den
.NumRows())
1959 rest_i
[n_i
++] = a
->den
[k
++];
1960 while (l
< b
->den
.NumRows())
1961 rest_j
[n_j
++] = b
->den
[l
++];
1962 common
.SetDims(n_common
, dim
);
1963 rest_i
.SetDims(n_i
, dim
);
1964 rest_j
.SetDims(n_j
, dim
);
1966 assert(order
.eq
[a
].size() > 1);
1967 indicator_term
*prev
;
1970 for (int k
= n_i
-1; k
>= 0; --k
) {
1971 indicator_term
*it
= new indicator_term(*b
);
1972 it
->den
.SetDims(n_common
+ n_j
+ n_i
-k
, dim
);
1973 for (int l
= k
; l
< n_i
; ++l
)
1974 it
->den
[n_common
+n_j
+l
-k
] = rest_i
[l
];
1975 lex_order_rows(it
->den
);
1976 for (int m
= 0; m
< dim
; ++m
)
1977 evalue_add_constant(it
->vertex
[m
], rest_i
[k
][m
]);
1978 it
->sign
= -it
->sign
;
1980 order
.pending
[it
].push_back(prev
);
1981 order
.lt
[it
].push_back(prev
);
1982 order
.inc_pred(prev
);
1985 order
.head
.insert(it
);
1989 indicator_term
*it
= new indicator_term(*b
);
1990 it
->den
.SetDims(n_common
+ n_i
+ n_j
, dim
);
1991 for (l
= 0; l
< n_i
; ++l
)
1992 it
->den
[n_common
+n_j
+l
] = rest_i
[l
];
1993 lex_order_rows(it
->den
);
1995 order
.pending
[a
].push_back(prev
);
1996 order
.lt
[a
].push_back(prev
);
1997 order
.inc_pred(prev
);
1998 order
.replace(b
, it
);
2003 for (int k
= n_j
-1; k
>= 0; --k
) {
2004 indicator_term
*it
= new indicator_term(*a
);
2005 it
->den
.SetDims(n_common
+ n_i
+ n_j
-k
, dim
);
2006 for (int l
= k
; l
< n_j
; ++l
)
2007 it
->den
[n_common
+n_i
+l
-k
] = rest_j
[l
];
2008 lex_order_rows(it
->den
);
2009 for (int m
= 0; m
< dim
; ++m
)
2010 evalue_add_constant(it
->vertex
[m
], rest_j
[k
][m
]);
2011 it
->sign
= -it
->sign
;
2013 order
.pending
[it
].push_back(prev
);
2014 order
.lt
[it
].push_back(prev
);
2015 order
.inc_pred(prev
);
2018 order
.head
.insert(it
);
2022 indicator_term
*it
= new indicator_term(*a
);
2023 it
->den
.SetDims(n_common
+ n_i
+ n_j
, dim
);
2024 for (l
= 0; l
< n_j
; ++l
)
2025 it
->den
[n_common
+n_i
+l
] = rest_j
[l
];
2026 lex_order_rows(it
->den
);
2028 order
.pending
[a
].push_back(prev
);
2029 order
.lt
[a
].push_back(prev
);
2030 order
.inc_pred(prev
);
2031 order
.replace(a
, it
);
2035 assert(term
.size() == order
.head
.size() + order
.pred
.size());
2038 bool indicator::handle_equal_numerators(const indicator_term
*base
)
2040 for (int i
= 0; i
< order
.eq
[base
].size(); ++i
) {
2041 for (int j
= i
+1; j
< order
.eq
[base
].size(); ++j
) {
2042 if (order
.eq
[base
][i
]->is_opposite(order
.eq
[base
][j
])) {
2043 remove(order
.eq
[base
][j
]);
2044 remove(i
? order
.eq
[base
][i
] : base
);
2049 for (int j
= 1; j
< order
.eq
[base
].size(); ++j
)
2050 if (order
.eq
[base
][j
]->sign
!= base
->sign
) {
2051 combine(base
, order
.eq
[base
][j
]);
2057 void indicator::substitute(evalue
*equation
)
2059 ::substitute(term
, equation
);
2062 void indicator::add_substitution(evalue
*equation
)
2064 for (int i
= 0; i
< substitutions
.size(); ++i
)
2065 if (eequal(substitutions
[i
], equation
))
2067 evalue
*copy
= new evalue();
2068 value_init(copy
->d
);
2069 evalue_copy(copy
, equation
);
2070 substitutions
.push_back(copy
);
2073 void indicator::perform_pending_substitutions()
2075 if (substitutions
.size() == 0)
2078 for (int i
= 0; i
< substitutions
.size(); ++i
) {
2079 substitute(substitutions
[i
]);
2080 free_evalue_refs(substitutions
[i
]);
2081 delete substitutions
[i
];
2083 substitutions
.clear();
2087 static void print_varlist(ostream
& os
, int n
, char **names
)
2091 for (i
= 0; i
< n
; ++i
) {
2099 void max_term::print(ostream
& os
, char **p
, barvinok_options
*options
) const
2102 print_varlist(os
, domain
->dimension(), p
);
2105 for (int i
= 0; i
< max
.size(); ++i
) {
2108 evalue_print(os
, max
[i
], p
);
2112 domain
->print_constraints(os
, p
, options
);
2116 /* T maps the compressed parameters to the original parameters,
2117 * while this max_term is based on the compressed parameters
2118 * and we want get the original parameters back.
2120 void max_term::substitute(Matrix
*T
, barvinok_options
*options
)
2122 assert(domain
->dimension() == T
->NbColumns
-1);
2123 int nexist
= domain
->D
->Dimension
- (T
->NbColumns
-1);
2125 Matrix
*inv
= left_inverse(T
, &Eq
);
2128 value_init(denom
.d
);
2129 value_init(denom
.x
.n
);
2130 value_set_si(denom
.x
.n
, 1);
2131 value_assign(denom
.d
, inv
->p
[inv
->NbRows
-1][inv
->NbColumns
-1]);
2134 v
.SetLength(inv
->NbColumns
);
2135 evalue
**subs
= new evalue
*[inv
->NbRows
-1];
2136 for (int i
= 0; i
< inv
->NbRows
-1; ++i
) {
2137 values2zz(inv
->p
[i
], v
, v
.length());
2138 subs
[i
] = multi_monom(v
);
2139 emul(&denom
, subs
[i
]);
2141 free_evalue_refs(&denom
);
2143 domain
->substitute(subs
, inv
, Eq
, options
->MaxRays
);
2146 for (int i
= 0; i
< max
.size(); ++i
) {
2147 evalue_substitute(max
[i
], subs
);
2148 reduce_evalue(max
[i
]);
2151 for (int i
= 0; i
< inv
->NbRows
-1; ++i
) {
2152 free_evalue_refs(subs
[i
]);
2159 Vector
*max_term::eval(Value
*val
, unsigned MaxRays
) const
2161 if (!domain
->contains(val
, domain
->dimension()))
2163 Vector
*res
= Vector_Alloc(max
.size());
2164 for (int i
= 0; i
< max
.size(); ++i
) {
2165 compute_evalue(max
[i
], val
, &res
->p
[i
]);
2172 enum sign
{ le
, ge
, lge
} sign
;
2174 split (evalue
*c
, enum sign s
) : constraint(c
), sign(s
) {}
2177 static void split_on(const split
& sp
, EDomain
*D
,
2178 EDomain
**Dlt
, EDomain
**Deq
, EDomain
**Dgt
,
2179 lexmin_options
*options
)
2185 ge_constraint
*ge
= D
->compute_ge_constraint(sp
.constraint
);
2186 if (sp
.sign
== split::lge
|| sp
.sign
== split::ge
)
2187 ED
[2] = EDomain::new_from_ge_constraint(ge
, 1, options
->verify
->barvinok
);
2190 if (sp
.sign
== split::lge
|| sp
.sign
== split::le
)
2191 ED
[0] = EDomain::new_from_ge_constraint(ge
, -1, options
->verify
->barvinok
);
2195 assert(sp
.sign
== split::lge
|| sp
.sign
== split::ge
|| sp
.sign
== split::le
);
2196 ED
[1] = EDomain::new_from_ge_constraint(ge
, 0, options
->verify
->barvinok
);
2200 for (int i
= 0; i
< 3; ++i
) {
2203 if (D
->sample
&& ED
[i
]->contains(D
->sample
->p
, D
->sample
->Size
-1)) {
2204 ED
[i
]->sample
= Vector_Alloc(D
->sample
->Size
);
2205 Vector_Copy(D
->sample
->p
, ED
[i
]->sample
->p
, D
->sample
->Size
);
2206 } else if (emptyQ2(ED
[i
]->D
) ||
2207 (options
->emptiness_check
!= BV_LEXMIN_EMPTINESS_CHECK_NONE
&&
2208 !(ED
[i
]->not_empty(options
)))) {
2218 ostream
& operator<< (ostream
& os
, const vector
<int> & v
)
2221 for (int i
= 0; i
< v
.size(); ++i
) {
2230 static bool isTranslation(Matrix
*M
)
2233 if (M
->NbRows
!= M
->NbColumns
)
2236 for (i
= 0;i
< M
->NbRows
; i
++)
2237 for (j
= 0; j
< M
->NbColumns
-1; j
++)
2239 if(value_notone_p(M
->p
[i
][j
]))
2242 if(value_notzero_p(M
->p
[i
][j
]))
2245 return value_one_p(M
->p
[M
->NbRows
-1][M
->NbColumns
-1]);
2248 static Matrix
*compress_parameters(Polyhedron
**P
, Polyhedron
**C
,
2249 unsigned nparam
, unsigned MaxRays
)
2253 /* compress_parms doesn't like equalities that only involve parameters */
2254 for (int i
= 0; i
< (*P
)->NbEq
; ++i
)
2255 assert(First_Non_Zero((*P
)->Constraint
[i
]+1, (*P
)->Dimension
-nparam
) != -1);
2257 M
= Matrix_Alloc((*P
)->NbEq
, (*P
)->Dimension
+2);
2258 Vector_Copy((*P
)->Constraint
[0], M
->p
[0], (*P
)->NbEq
* ((*P
)->Dimension
+2));
2259 CP
= compress_parms(M
, nparam
);
2262 if (isTranslation(CP
)) {
2267 T
= align_matrix(CP
, (*P
)->Dimension
+1);
2268 *P
= Polyhedron_Preimage(*P
, T
, MaxRays
);
2271 *C
= Polyhedron_Preimage(*C
, CP
, MaxRays
);
2276 void construct_rational_vertices(Param_Polyhedron
*PP
, Matrix
*T
, unsigned dim
,
2277 int nparam
, vector
<indicator_term
*>& vertices
)
2286 v
.SetLength(nparam
+1);
2289 value_init(factor
.d
);
2290 value_init(factor
.x
.n
);
2291 value_set_si(factor
.x
.n
, 1);
2292 value_set_si(factor
.d
, 1);
2294 for (i
= 0, PV
= PP
->V
; PV
; ++i
, PV
= PV
->next
) {
2295 indicator_term
*term
= new indicator_term(dim
, i
);
2296 vertices
.push_back(term
);
2297 Matrix
*M
= Matrix_Alloc(PV
->Vertex
->NbRows
+nparam
+1, nparam
+1);
2298 value_set_si(lcm
, 1);
2299 for (int j
= 0; j
< PV
->Vertex
->NbRows
; ++j
)
2300 value_lcm(lcm
, lcm
, PV
->Vertex
->p
[j
][nparam
+1]);
2301 value_assign(M
->p
[M
->NbRows
-1][M
->NbColumns
-1], lcm
);
2302 for (int j
= 0; j
< PV
->Vertex
->NbRows
; ++j
) {
2303 value_division(tmp
, lcm
, PV
->Vertex
->p
[j
][nparam
+1]);
2304 Vector_Scale(PV
->Vertex
->p
[j
], M
->p
[j
], tmp
, nparam
+1);
2306 for (int j
= 0; j
< nparam
; ++j
)
2307 value_assign(M
->p
[PV
->Vertex
->NbRows
+j
][j
], lcm
);
2309 Matrix
*M2
= Matrix_Alloc(T
->NbRows
, M
->NbColumns
);
2310 Matrix_Product(T
, M
, M2
);
2314 for (int j
= 0; j
< dim
; ++j
) {
2315 values2zz(M
->p
[j
], v
, nparam
+1);
2316 term
->vertex
[j
] = multi_monom(v
);
2317 value_assign(factor
.d
, lcm
);
2318 emul(&factor
, term
->vertex
[j
]);
2322 assert(i
== PP
->nbV
);
2323 free_evalue_refs(&factor
);
2328 static vector
<max_term
*> lexmin(indicator
& ind
, unsigned nparam
,
2331 vector
<max_term
*> maxima
;
2332 partial_order::head_type::iterator i
;
2333 vector
<int> best_score
;
2334 vector
<int> second_score
;
2335 vector
<int> neg_score
;
2338 ind
.perform_pending_substitutions();
2339 const indicator_term
*best
= NULL
, *second
= NULL
, *neg
= NULL
,
2340 *neg_eq
= NULL
, *neg_le
= NULL
;
2341 for (i
= ind
.order
.head
.begin(); i
!= ind
.order
.head
.end(); ++i
) {
2343 const indicator_term
*term
= *i
;
2344 if (term
->sign
== 0) {
2345 ind
.expand_rational_vertex(term
);
2349 if (ind
.order
.eq
.find(term
) != ind
.order
.eq
.end()) {
2351 if (ind
.order
.eq
[term
].size() <= 1)
2353 for (j
= 1; j
< ind
.order
.eq
[term
].size(); ++j
)
2354 if (ind
.order
.pred
.find(ind
.order
.eq
[term
][j
]) !=
2355 ind
.order
.pred
.end())
2357 if (j
< ind
.order
.eq
[term
].size())
2359 score
.push_back(ind
.order
.eq
[term
].size());
2362 if (ind
.order
.le
.find(term
) != ind
.order
.le
.end())
2363 score
.push_back(ind
.order
.le
[term
].size());
2366 if (ind
.order
.lt
.find(term
) != ind
.order
.lt
.end())
2367 score
.push_back(-ind
.order
.lt
[term
].size());
2371 if (term
->sign
> 0) {
2372 if (!best
|| score
< best_score
) {
2374 second_score
= best_score
;
2377 } else if (!second
|| score
< second_score
) {
2379 second_score
= score
;
2382 if (!neg_eq
&& ind
.order
.eq
.find(term
) != ind
.order
.eq
.end()) {
2383 for (int j
= 1; j
< ind
.order
.eq
[term
].size(); ++j
)
2384 if (ind
.order
.eq
[term
][j
]->sign
!= term
->sign
) {
2389 if (!neg_le
&& ind
.order
.le
.find(term
) != ind
.order
.le
.end())
2391 if (!neg
|| score
< neg_score
) {
2397 if (i
!= ind
.order
.head
.end())
2400 if (!best
&& neg_eq
) {
2401 assert(ind
.order
.eq
[neg_eq
].size() != 0);
2402 bool handled
= ind
.handle_equal_numerators(neg_eq
);
2407 if (!best
&& neg_le
) {
2408 /* The smallest term is negative and <= some positive term */
2414 /* apparently there can be negative initial term on empty domains */
2415 if (ind
.options
->emptiness_check
!= BV_LEXMIN_EMPTINESS_CHECK_NONE
&&
2416 ind
.options
->verify
->barvinok
->lp_solver
== BV_LP_POLYLIB
)
2421 if (!second
&& !neg
) {
2422 const indicator_term
*rat
= NULL
;
2424 if (ind
.order
.le
.find(best
) == ind
.order
.le
.end()) {
2425 if (ind
.order
.eq
.find(best
) != ind
.order
.eq
.end()) {
2426 bool handled
= ind
.handle_equal_numerators(best
);
2427 if (ind
.options
->emptiness_check
!=
2428 BV_LEXMIN_EMPTINESS_CHECK_NONE
&&
2429 ind
.options
->verify
->barvinok
->lp_solver
== BV_LP_POLYLIB
)
2431 /* If !handled then the leading coefficient is bigger than one;
2432 * must be an empty domain
2439 maxima
.push_back(ind
.create_max_term(best
));
2442 for (int j
= 0; j
< ind
.order
.le
[best
].size(); ++j
) {
2443 if (ind
.order
.le
[best
][j
]->sign
== 0) {
2444 if (!rat
&& ind
.order
.pred
[ind
.order
.le
[best
][j
]] == 1)
2445 rat
= ind
.order
.le
[best
][j
];
2446 } else if (ind
.order
.le
[best
][j
]->sign
> 0) {
2447 second
= ind
.order
.le
[best
][j
];
2450 neg
= ind
.order
.le
[best
][j
];
2453 if (!second
&& !neg
) {
2455 ind
.order
.unset_le(best
, rat
);
2456 ind
.expand_rational_vertex(rat
);
2463 ind
.order
.unset_le(best
, second
);
2469 unsigned dim
= best
->den
.NumCols();
2472 for (int k
= 0; k
< dim
; ++k
) {
2473 diff
= ediff(best
->vertex
[k
], second
->vertex
[k
]);
2474 sign
= evalue_sign(diff
, ind
.D
, ind
.options
->verify
->barvinok
);
2476 /* neg can never be smaller than best, unless it may still cancel.
2477 * This can happen if positive terms have been determined to
2478 * be equal or less than or equal to some negative term.
2480 if (second
== neg
&& !neg_eq
&& !neg_le
) {
2481 if (sign
== order_ge
)
2483 if (sign
== order_unknown
)
2487 if (sign
!= order_eq
)
2489 if (!EVALUE_IS_ZERO(*diff
)) {
2490 ind
.add_substitution(diff
);
2491 ind
.perform_pending_substitutions();
2494 if (sign
== order_eq
) {
2495 ind
.order
.set_equal(best
, second
);
2498 if (sign
== order_lt
) {
2499 ind
.order
.lt
[best
].push_back(second
);
2500 ind
.order
.inc_pred(second
);
2503 if (sign
== order_gt
) {
2504 ind
.order
.lt
[second
].push_back(best
);
2505 ind
.order
.inc_pred(best
);
2509 split
sp(diff
, sign
== order_le
? split::le
:
2510 sign
== order_ge
? split::ge
: split::lge
);
2512 EDomain
*Dlt
, *Deq
, *Dgt
;
2513 split_on(sp
, ind
.D
, &Dlt
, &Deq
, &Dgt
, ind
.options
);
2514 if (ind
.options
->emptiness_check
!= BV_LEXMIN_EMPTINESS_CHECK_NONE
)
2515 assert(Dlt
|| Deq
|| Dgt
);
2516 else if (!(Dlt
|| Deq
|| Dgt
))
2517 /* Must have been empty all along */
2520 if (Deq
&& (Dlt
|| Dgt
)) {
2521 int locsize
= loc
.size();
2523 indicator
indeq(ind
, Deq
);
2525 indeq
.add_substitution(diff
);
2526 indeq
.perform_pending_substitutions();
2527 vector
<max_term
*> maxeq
= lexmin(indeq
, nparam
, loc
);
2528 maxima
.insert(maxima
.end(), maxeq
.begin(), maxeq
.end());
2529 loc
.resize(locsize
);
2532 int locsize
= loc
.size();
2534 indicator
indgt(ind
, Dgt
);
2536 /* we don't know the new location of these terms in indgt */
2538 indgt.order.lt[second].push_back(best);
2539 indgt.order.inc_pred(best);
2541 vector
<max_term
*> maxgt
= lexmin(indgt
, nparam
, loc
);
2542 maxima
.insert(maxima
.end(), maxgt
.begin(), maxgt
.end());
2543 loc
.resize(locsize
);
2548 ind
.set_domain(Deq
);
2549 ind
.add_substitution(diff
);
2550 ind
.perform_pending_substitutions();
2554 ind
.set_domain(Dlt
);
2555 ind
.order
.lt
[best
].push_back(second
);
2556 ind
.order
.inc_pred(second
);
2560 ind
.set_domain(Dgt
);
2561 ind
.order
.lt
[second
].push_back(best
);
2562 ind
.order
.inc_pred(best
);
2569 static void lexmin_base(Polyhedron
*P
, Polyhedron
*C
,
2570 Matrix
*CP
, Matrix
*T
,
2571 vector
<max_term
*>& all_max
,
2572 lexmin_options
*options
)
2574 unsigned nparam
= C
->Dimension
;
2575 Param_Polyhedron
*PP
= NULL
;
2577 PP
= Polyhedron2Param_Polyhedron(P
, C
, options
->verify
->barvinok
);
2579 unsigned dim
= P
->Dimension
- nparam
;
2583 indicator_constructor
ic(P
, dim
, PP
, T
);
2585 vector
<indicator_term
*> all_vertices
;
2586 construct_rational_vertices(PP
, T
, T
? T
->NbRows
-nparam
-1 : dim
,
2587 nparam
, all_vertices
);
2589 Polyhedron
*TC
= true_context(P
, C
, options
->verify
->barvinok
->MaxRays
);
2590 FORALL_REDUCED_DOMAIN(PP
, TC
, nd
, options
->verify
->barvinok
, i
, D
, rVD
)
2593 EDomain
*epVD
= new EDomain(rVD
);
2594 indicator
ind(ic
, D
, epVD
, options
);
2596 FORALL_PVertex_in_ParamPolyhedron(V
,D
,PP
) // _i is internal counter
2597 ind
.add(all_vertices
[_i
]);
2598 END_FORALL_PVertex_in_ParamPolyhedron
;
2600 ind
.remove_initial_rational_vertices();
2603 vector
<max_term
*> maxima
= lexmin(ind
, nparam
, loc
);
2605 for (int j
= 0; j
< maxima
.size(); ++j
)
2606 maxima
[j
]->substitute(CP
, options
->verify
->barvinok
);
2607 all_max
.insert(all_max
.end(), maxima
.begin(), maxima
.end());
2610 END_FORALL_REDUCED_DOMAIN
2611 Polyhedron_Free(TC
);
2612 for (int i
= 0; i
< all_vertices
.size(); ++i
)
2613 delete all_vertices
[i
];
2614 Param_Polyhedron_Free(PP
);
2617 static vector
<max_term
*> lexmin(Polyhedron
*P
, Polyhedron
*C
,
2618 lexmin_options
*options
)
2620 unsigned nparam
= C
->Dimension
;
2621 Matrix
*T
= NULL
, *CP
= NULL
;
2622 Polyhedron
*Porig
= P
;
2623 Polyhedron
*Corig
= C
;
2624 vector
<max_term
*> all_max
;
2629 POL_ENSURE_VERTICES(P
);
2634 assert(P
->NbBid
== 0);
2637 remove_all_equalities(&P
, &C
, &CP
, &T
, nparam
,
2638 options
->verify
->barvinok
->MaxRays
);
2640 lexmin_base(P
, C
, CP
, T
, all_max
, options
);
2654 static void verify_results(Polyhedron
*A
, Polyhedron
*C
,
2655 vector
<max_term
*>& maxima
,
2656 struct verify_options
*options
);
2658 int main(int argc
, char **argv
)
2663 char **iter_names
, **param_names
;
2664 int print_solution
= 1;
2665 struct lexmin_options
*options
= lexmin_options_new_with_defaults();
2666 options
->verify
->barvinok
->lookup_table
= 0;
2668 argc
= lexmin_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
2671 C
= Constraints2Polyhedron(MA
, options
->verify
->barvinok
->MaxRays
);
2673 fscanf(stdin
, " %d", &bignum
);
2674 assert(bignum
== -1);
2676 A
= Constraints2Polyhedron(MA
, options
->verify
->barvinok
->MaxRays
);
2679 verify_options_set_range(options
->verify
, A
->Dimension
);
2681 if (options
->verify
->verify
)
2684 iter_names
= util_generate_names(A
->Dimension
- C
->Dimension
, "i");
2685 param_names
= util_generate_names(C
->Dimension
, "p");
2686 if (print_solution
) {
2687 Polyhedron_Print(stdout
, P_VALUE_FMT
, A
);
2688 Polyhedron_Print(stdout
, P_VALUE_FMT
, C
);
2690 vector
<max_term
*> maxima
= lexmin(A
, C
, options
);
2692 for (int i
= 0; i
< maxima
.size(); ++i
)
2693 maxima
[i
]->print(cout
, param_names
, options
->verify
->barvinok
);
2695 if (options
->verify
->verify
)
2696 verify_results(A
, C
, maxima
, options
->verify
);
2698 for (int i
= 0; i
< maxima
.size(); ++i
)
2701 util_free_names(A
->Dimension
- C
->Dimension
, iter_names
);
2702 util_free_names(C
->Dimension
, param_names
);
2706 lexmin_options_free(options
);
2711 static bool lexmin(int pos
, Polyhedron
*P
, Value
*context
)
2720 value_init(LB
); value_init(UB
); value_init(k
);
2723 lu_flags
= lower_upper_bounds(pos
,P
,context
,&LB
,&UB
);
2724 assert(!(lu_flags
& LB_INFINITY
));
2726 value_set_si(context
[pos
],0);
2727 if (!lu_flags
&& value_lt(UB
,LB
)) {
2728 value_clear(LB
); value_clear(UB
); value_clear(k
);
2732 value_assign(context
[pos
], LB
);
2733 value_clear(LB
); value_clear(UB
); value_clear(k
);
2736 for (value_assign(k
,LB
); lu_flags
|| value_le(k
,UB
); value_increment(k
,k
)) {
2737 value_assign(context
[pos
],k
);
2738 if ((found
= lexmin(pos
+1, P
->next
, context
)))
2742 value_set_si(context
[pos
],0);
2743 value_clear(LB
); value_clear(UB
); value_clear(k
);
2747 static void print_list(FILE *out
, Value
*z
, const char* brackets
, int len
)
2749 fprintf(out
, "%c", brackets
[0]);
2750 value_print(out
, VALUE_FMT
,z
[0]);
2751 for (int k
= 1; k
< len
; ++k
) {
2753 value_print(out
, VALUE_FMT
,z
[k
]);
2755 fprintf(out
, "%c", brackets
[1]);
2758 static int check_poly_lexmin(const struct check_poly_data
*data
,
2759 int nparam
, Value
*z
,
2760 const struct verify_options
*options
);
2762 struct check_poly_lexmin_data
: public check_poly_data
{
2764 vector
<max_term
*>& maxima
;
2766 check_poly_lexmin_data(Polyhedron
*S
, Value
*z
,
2767 vector
<max_term
*>& maxima
) : S(S
), maxima(maxima
) {
2769 this->check
= &check_poly_lexmin
;
2773 static int check_poly_lexmin(const struct check_poly_data
*data
,
2774 int nparam
, Value
*z
,
2775 const struct verify_options
*options
)
2777 const check_poly_lexmin_data
*lexmin_data
;
2778 lexmin_data
= static_cast<const check_poly_lexmin_data
*>(data
);
2779 Polyhedron
*S
= lexmin_data
->S
;
2780 vector
<max_term
*>& maxima
= lexmin_data
->maxima
;
2782 bool found
= lexmin(1, S
, lexmin_data
->z
);
2784 if (options
->print_all
) {
2786 print_list(stdout
, z
, "()", nparam
);
2789 print_list(stdout
, lexmin_data
->z
+1, "[]", S
->Dimension
-nparam
);
2794 for (int i
= 0; i
< maxima
.size(); ++i
)
2795 if ((min
= maxima
[i
]->eval(z
, options
->barvinok
->MaxRays
)))
2798 int ok
= !(found
^ !!min
);
2800 for (int i
= 0; i
< S
->Dimension
-nparam
; ++i
)
2801 if (value_ne(lexmin_data
->z
[1+i
], min
->p
[i
])) {
2808 fprintf(stderr
, "Error !\n");
2809 fprintf(stderr
, "lexmin");
2810 print_list(stderr
, z
, "()", nparam
);
2811 fprintf(stderr
, " should be ");
2813 print_list(stderr
, lexmin_data
->z
+1, "[]", S
->Dimension
-nparam
);
2814 fprintf(stderr
, " while digging gives ");
2816 print_list(stderr
, min
->p
, "[]", S
->Dimension
-nparam
);
2817 fprintf(stderr
, ".\n");
2819 } else if (options
->print_all
)
2824 for (k
= 1; k
<= S
->Dimension
-nparam
; ++k
)
2825 value_set_si(lexmin_data
->z
[k
], 0);
2828 void verify_results(Polyhedron
*A
, Polyhedron
*C
, vector
<max_term
*>& maxima
,
2829 struct verify_options
*options
)
2832 unsigned nparam
= C
->Dimension
;
2833 unsigned MaxRays
= options
->barvinok
->MaxRays
;
2838 CS
= check_poly_context_scan(A
, &C
, nparam
, options
);
2840 p
= Vector_Alloc(A
->Dimension
+2);
2841 value_set_si(p
->p
[A
->Dimension
+1], 1);
2843 S
= Polyhedron_Scan(A
, C
, MaxRays
& POL_NO_DUAL
? 0 : MaxRays
);
2845 check_poly_init(C
, options
);
2848 if (!(CS
&& emptyQ2(CS
))) {
2849 check_poly_lexmin_data
data(S
, p
->p
, maxima
);
2850 check_poly(CS
, &data
, nparam
, 0, p
->p
+S
->Dimension
-nparam
+1, options
);
2855 if (!options
->print_all
)