7 #define partition STL_PARTITION
12 #include <NTL/vec_ZZ.h>
13 #include <NTL/mat_ZZ.h>
16 #include <isl_set_polylib.h>
17 #include <barvinok/polylib.h>
18 #include <barvinok/barvinok.h>
19 #include <barvinok/evalue.h>
20 #include <barvinok/options.h>
21 #include <barvinok/util.h>
22 #include "conversion.h"
23 #include "decomposer.h"
24 #include "lattice_point.h"
25 #include "reduce_domain.h"
28 #include "evalue_util.h"
29 #include "remove_equalities.h"
33 #include "param_util.h"
35 #undef CS /* for Solaris 10 */
46 #define ALLOC(type) (type*)malloc(sizeof(type))
47 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
49 static int type_offset(enode
*p
)
51 return p
->type
== fractional
? 1 :
52 p
->type
== flooring
? 1 : 0;
55 void compute_evalue(evalue
*e
, Value
*val
, Value
*res
)
57 double d
= compute_evalue(e
, val
);
62 value_set_double(*res
, d
);
65 struct indicator_term
{
67 int pos
; /* number of rational vertex */
68 int n
; /* number of cone associated to given rational vertex */
72 indicator_term(unsigned dim
, int pos
) {
74 vertex
= new evalue
* [dim
];
79 indicator_term(unsigned dim
, int pos
, int n
) {
80 den
.SetDims(dim
, dim
);
81 vertex
= new evalue
* [dim
];
85 indicator_term(const indicator_term
& src
) {
90 unsigned dim
= den
.NumCols();
91 vertex
= new evalue
* [dim
];
92 for (int i
= 0; i
< dim
; ++i
) {
93 vertex
[i
] = ALLOC(evalue
);
94 value_init(vertex
[i
]->d
);
95 evalue_copy(vertex
[i
], src
.vertex
[i
]);
98 void swap(indicator_term
*other
) {
100 tmp
= sign
; sign
= other
->sign
; other
->sign
= tmp
;
101 tmp
= pos
; pos
= other
->pos
; other
->pos
= tmp
;
102 tmp
= n
; n
= other
->n
; other
->n
= tmp
;
103 mat_ZZ tmp_den
= den
; den
= other
->den
; other
->den
= tmp_den
;
104 unsigned dim
= den
.NumCols();
105 for (int i
= 0; i
< dim
; ++i
) {
106 evalue
*tmp
= vertex
[i
];
107 vertex
[i
] = other
->vertex
[i
];
108 other
->vertex
[i
] = tmp
;
112 unsigned dim
= den
.NumCols();
113 for (int i
= 0; i
< dim
; ++i
)
114 evalue_free(vertex
[i
]);
117 void print(ostream
& os
, char **p
) const;
118 void substitute(Matrix
*T
);
120 void substitute(evalue
*fract
, evalue
*val
);
121 void substitute(int pos
, evalue
*val
);
122 void reduce_in_domain(Polyhedron
*D
);
123 bool is_opposite(const indicator_term
*neg
) const;
124 vec_ZZ
eval(Value
*val
) const {
126 unsigned dim
= den
.NumCols();
130 for (int i
= 0; i
< dim
; ++i
) {
131 compute_evalue(vertex
[i
], val
, &tmp
);
139 static int evalue_rational_cmp(const evalue
*e1
, const evalue
*e2
)
147 assert(value_notzero_p(e1
->d
));
148 assert(value_notzero_p(e2
->d
));
149 value_multiply(m
, e1
->x
.n
, e2
->d
);
150 value_multiply(m2
, e2
->x
.n
, e1
->d
);
153 else if (value_gt(m
, m2
))
163 static int evalue_cmp(const evalue
*e1
, const evalue
*e2
)
165 if (value_notzero_p(e1
->d
)) {
166 if (value_zero_p(e2
->d
))
168 return evalue_rational_cmp(e1
, e2
);
170 if (value_notzero_p(e2
->d
))
172 if (e1
->x
.p
->type
!= e2
->x
.p
->type
)
173 return e1
->x
.p
->type
- e2
->x
.p
->type
;
174 if (e1
->x
.p
->size
!= e2
->x
.p
->size
)
175 return e1
->x
.p
->size
- e2
->x
.p
->size
;
176 if (e1
->x
.p
->pos
!= e2
->x
.p
->pos
)
177 return e1
->x
.p
->pos
- e2
->x
.p
->pos
;
178 assert(e1
->x
.p
->type
== polynomial
||
179 e1
->x
.p
->type
== fractional
||
180 e1
->x
.p
->type
== flooring
);
181 for (int i
= 0; i
< e1
->x
.p
->size
; ++i
) {
182 int s
= evalue_cmp(&e1
->x
.p
->arr
[i
], &e2
->x
.p
->arr
[i
]);
189 void evalue_length(evalue
*e
, int len
[2])
194 while (value_zero_p(e
->d
)) {
195 assert(e
->x
.p
->type
== polynomial
||
196 e
->x
.p
->type
== fractional
||
197 e
->x
.p
->type
== flooring
);
198 if (e
->x
.p
->type
== polynomial
)
202 int offset
= type_offset(e
->x
.p
);
203 assert(e
->x
.p
->size
== offset
+2);
204 e
= &e
->x
.p
->arr
[offset
];
208 static bool it_smaller(const indicator_term
* it1
, const indicator_term
* it2
)
212 int len1
[2], len2
[2];
213 unsigned dim
= it1
->den
.NumCols();
214 for (int i
= 0; i
< dim
; ++i
) {
215 evalue_length(it1
->vertex
[i
], len1
);
216 evalue_length(it2
->vertex
[i
], len2
);
217 if (len1
[0] != len2
[0])
218 return len1
[0] < len2
[0];
219 if (len1
[1] != len2
[1])
220 return len1
[1] < len2
[1];
222 if (it1
->pos
!= it2
->pos
)
223 return it1
->pos
< it2
->pos
;
224 if (it1
->n
!= it2
->n
)
225 return it1
->n
< it2
->n
;
226 int s
= lex_cmp(it1
->den
, it2
->den
);
229 for (int i
= 0; i
< dim
; ++i
) {
230 s
= evalue_cmp(it1
->vertex
[i
], it2
->vertex
[i
]);
234 assert(it1
->sign
!= 0);
235 assert(it2
->sign
!= 0);
236 if (it1
->sign
!= it2
->sign
)
237 return it1
->sign
> 0;
242 static const int requires_resort
;
243 bool operator()(const indicator_term
* it1
, const indicator_term
* it2
) const {
244 return it_smaller(it1
, it2
);
247 const int smaller_it::requires_resort
= 1;
249 struct smaller_it_p
{
250 static const int requires_resort
;
251 bool operator()(const indicator_term
* it1
, const indicator_term
* it2
) const {
255 const int smaller_it_p::requires_resort
= 0;
257 /* Returns true if this and neg are opposite using the knowledge
258 * that they have the same numerator.
259 * In particular, we check that the signs are different and that
260 * the denominator is the same.
262 bool indicator_term::is_opposite(const indicator_term
*neg
) const
264 if (sign
+ neg
->sign
!= 0)
271 void indicator_term::reduce_in_domain(Polyhedron
*D
)
273 for (int k
= 0; k
< den
.NumCols(); ++k
) {
274 reduce_evalue_in_domain(vertex
[k
], D
);
275 if (evalue_range_reduction_in_domain(vertex
[k
], D
))
276 reduce_evalue(vertex
[k
]);
280 void indicator_term::print(ostream
& os
, char **p
) const
282 unsigned dim
= den
.NumCols();
283 unsigned factors
= den
.NumRows();
291 for (int i
= 0; i
< dim
; ++i
) {
294 evalue_print(os
, vertex
[i
], p
);
297 for (int i
= 0; i
< factors
; ++i
) {
298 os
<< " + t" << i
<< "*[";
299 for (int j
= 0; j
< dim
; ++j
) {
306 os
<< " ((" << pos
<< ", " << n
<< ", " << (void*)this << "))";
309 /* Perform the substitution specified by T on the variables.
310 * T has dimension (newdim+nparam+1) x (olddim + nparam + 1).
311 * The substitution is performed as in gen_fun::substitute
313 void indicator_term::substitute(Matrix
*T
)
315 unsigned dim
= den
.NumCols();
316 unsigned nparam
= T
->NbColumns
- dim
- 1;
317 unsigned newdim
= T
->NbRows
- nparam
- 1;
320 matrix2zz(T
, trans
, newdim
, dim
);
321 trans
= transpose(trans
);
323 newvertex
= new evalue
* [newdim
];
326 v
.SetLength(nparam
+1);
329 value_init(factor
.d
);
330 value_set_si(factor
.d
, 1);
331 value_init(factor
.x
.n
);
332 for (int i
= 0; i
< newdim
; ++i
) {
333 values2zz(T
->p
[i
]+dim
, v
, nparam
+1);
334 newvertex
[i
] = multi_monom(v
);
336 for (int j
= 0; j
< dim
; ++j
) {
337 if (value_zero_p(T
->p
[i
][j
]))
341 evalue_copy(&term
, vertex
[j
]);
342 value_assign(factor
.x
.n
, T
->p
[i
][j
]);
343 emul(&factor
, &term
);
344 eadd(&term
, newvertex
[i
]);
345 free_evalue_refs(&term
);
348 free_evalue_refs(&factor
);
349 for (int i
= 0; i
< dim
; ++i
)
350 evalue_free(vertex
[i
]);
355 static void evalue_add_constant(evalue
*e
, ZZ v
)
360 /* go down to constant term */
361 while (value_zero_p(e
->d
))
362 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)];
365 value_multiply(tmp
, tmp
, e
->d
);
366 value_addto(e
->x
.n
, e
->x
.n
, tmp
);
371 /* Make all powers in denominator lexico-positive */
372 void indicator_term::normalize()
375 extra_vertex
.SetLength(den
.NumCols());
376 for (int r
= 0; r
< den
.NumRows(); ++r
) {
377 for (int k
= 0; k
< den
.NumCols(); ++k
) {
384 extra_vertex
+= den
[r
];
388 for (int k
= 0; k
< extra_vertex
.length(); ++k
)
389 if (extra_vertex
[k
] != 0)
390 evalue_add_constant(vertex
[k
], extra_vertex
[k
]);
393 static void substitute(evalue
*e
, evalue
*fract
, evalue
*val
)
397 for (t
= e
; value_zero_p(t
->d
); t
= &t
->x
.p
->arr
[type_offset(t
->x
.p
)]) {
398 if (t
->x
.p
->type
== fractional
&& eequal(&t
->x
.p
->arr
[0], fract
))
401 if (value_notzero_p(t
->d
))
404 free_evalue_refs(&t
->x
.p
->arr
[0]);
405 evalue
*term
= &t
->x
.p
->arr
[2];
412 free_evalue_refs(term
);
418 void indicator_term::substitute(evalue
*fract
, evalue
*val
)
420 unsigned dim
= den
.NumCols();
421 for (int i
= 0; i
< dim
; ++i
) {
422 ::substitute(vertex
[i
], fract
, val
);
426 static void substitute(evalue
*e
, int pos
, evalue
*val
)
430 for (t
= e
; value_zero_p(t
->d
); t
= &t
->x
.p
->arr
[type_offset(t
->x
.p
)]) {
431 if (t
->x
.p
->type
== polynomial
&& t
->x
.p
->pos
== pos
)
434 if (value_notzero_p(t
->d
))
437 evalue
*term
= &t
->x
.p
->arr
[1];
444 free_evalue_refs(term
);
450 void indicator_term::substitute(int pos
, evalue
*val
)
452 unsigned dim
= den
.NumCols();
453 for (int i
= 0; i
< dim
; ++i
) {
454 ::substitute(vertex
[i
], pos
, val
);
458 struct indicator_constructor
: public signed_cone_consumer
,
459 public vertex_decomposer
{
461 vector
<indicator_term
*> *terms
;
462 Matrix
*T
; /* Transformation to original space */
467 indicator_constructor(unsigned dim
, Param_Polyhedron
*PP
, Matrix
*T
) :
468 vertex_decomposer(PP
, *this), T(T
), nbV(PP
->nbV
) {
469 vertex
.SetLength(dim
);
470 terms
= new vector
<indicator_term
*>[PP
->nbV
];
472 ~indicator_constructor() {
473 for (int i
= 0; i
< nbV
; ++i
)
474 for (int j
= 0; j
< terms
[i
].size(); ++j
)
478 void print(ostream
& os
, char **p
);
480 virtual void handle(const signed_cone
& sc
, barvinok_options
*options
);
481 void decompose_at_vertex(Param_Vertices
*V
, int _i
,
482 barvinok_options
*options
) {
485 vertex_decomposer::decompose_at_vertex(V
, _i
, options
);
489 void indicator_constructor::handle(const signed_cone
& sc
, barvinok_options
*options
)
492 unsigned dim
= vertex
.length();
494 assert(sc
.rays
.NumRows() == dim
);
496 indicator_term
*term
= new indicator_term(dim
, pos
, n
++);
497 term
->sign
= sc
.sign
;
498 terms
[vert
].push_back(term
);
500 lattice_point(V
, sc
.rays
, vertex
, term
->vertex
, options
);
503 for (int r
= 0; r
< dim
; ++r
) {
504 for (int j
= 0; j
< dim
; ++j
) {
505 if (term
->den
[r
][j
] == 0)
507 if (term
->den
[r
][j
] > 0)
509 term
->sign
= -term
->sign
;
510 term
->den
[r
] = -term
->den
[r
];
511 vertex
+= term
->den
[r
];
516 for (int i
= 0; i
< dim
; ++i
) {
517 if (!term
->vertex
[i
]) {
518 term
->vertex
[i
] = ALLOC(evalue
);
519 value_init(term
->vertex
[i
]->d
);
520 value_init(term
->vertex
[i
]->x
.n
);
521 zz2value(vertex
[i
], term
->vertex
[i
]->x
.n
);
522 value_set_si(term
->vertex
[i
]->d
, 1);
527 evalue_add_constant(term
->vertex
[i
], vertex
[i
]);
535 lex_order_rows(term
->den
);
538 void indicator_constructor::print(ostream
& os
, char **p
)
540 for (int i
= 0; i
< PP
->nbV
; ++i
)
541 for (int j
= 0; j
< terms
[i
].size(); ++j
) {
542 os
<< "i: " << i
<< ", j: " << j
<< endl
;
543 terms
[i
][j
]->print(os
, p
);
548 struct order_cache_el
{
550 order_cache_el
copy() const {
552 for (int i
= 0; i
< e
.size(); ++i
) {
553 evalue
*c
= new evalue
;
555 evalue_copy(c
, e
[i
]);
561 for (int i
= 0; i
< e
.size(); ++i
) {
562 free_evalue_refs(e
[i
]);
569 evalue_set_si(&mone
, -1, 1);
570 for (int i
= 0; i
< e
.size(); ++i
)
572 free_evalue_refs(&mone
);
574 void print(ostream
& os
, char **p
);
577 void order_cache_el::print(ostream
& os
, char **p
)
580 for (int i
= 0; i
< e
.size(); ++i
) {
583 evalue_print(os
, e
[i
], p
);
589 vector
<order_cache_el
> lt
;
590 vector
<order_cache_el
> le
;
591 vector
<order_cache_el
> unknown
;
593 void clear_transients() {
594 for (int i
= 0; i
< le
.size(); ++i
)
596 for (int i
= 0; i
< unknown
.size(); ++i
)
603 for (int i
= 0; i
< lt
.size(); ++i
)
607 void add(order_cache_el
& cache_el
, order_sign sign
);
608 order_sign
check_lt(vector
<order_cache_el
>* list
,
609 const indicator_term
*a
, const indicator_term
*b
,
610 order_cache_el
& cache_el
);
611 order_sign
check_lt(const indicator_term
*a
, const indicator_term
*b
,
612 order_cache_el
& cache_el
);
613 order_sign
check_direct(const indicator_term
*a
, const indicator_term
*b
,
614 order_cache_el
& cache_el
);
615 order_sign
check(const indicator_term
*a
, const indicator_term
*b
,
616 order_cache_el
& cache_el
);
617 void copy(const order_cache
& cache
);
618 void print(ostream
& os
, char **p
);
621 void order_cache::copy(const order_cache
& cache
)
623 for (int i
= 0; i
< cache
.lt
.size(); ++i
) {
624 order_cache_el n
= cache
.lt
[i
].copy();
629 void order_cache::add(order_cache_el
& cache_el
, order_sign sign
)
631 if (sign
== order_lt
) {
632 lt
.push_back(cache_el
);
633 } else if (sign
== order_gt
) {
635 lt
.push_back(cache_el
);
636 } else if (sign
== order_le
) {
637 le
.push_back(cache_el
);
638 } else if (sign
== order_ge
) {
640 le
.push_back(cache_el
);
641 } else if (sign
== order_unknown
) {
642 unknown
.push_back(cache_el
);
644 assert(sign
== order_eq
);
651 static evalue
*ediff(const evalue
*a
, const evalue
*b
)
655 evalue_set_si(&mone
, -1, 1);
656 evalue
*diff
= new evalue
;
658 evalue_copy(diff
, b
);
662 free_evalue_refs(&mone
);
666 static bool evalue_first_difference(const evalue
*e1
, const evalue
*e2
,
667 const evalue
**d1
, const evalue
**d2
)
672 if (value_ne(e1
->d
, e2
->d
))
675 if (value_notzero_p(e1
->d
)) {
676 if (value_eq(e1
->x
.n
, e2
->x
.n
))
680 if (e1
->x
.p
->type
!= e2
->x
.p
->type
)
682 if (e1
->x
.p
->size
!= e2
->x
.p
->size
)
684 if (e1
->x
.p
->pos
!= e2
->x
.p
->pos
)
687 assert(e1
->x
.p
->type
== polynomial
||
688 e1
->x
.p
->type
== fractional
||
689 e1
->x
.p
->type
== flooring
);
690 int offset
= type_offset(e1
->x
.p
);
691 assert(e1
->x
.p
->size
== offset
+2);
692 for (int i
= 0; i
< e1
->x
.p
->size
; ++i
)
693 if (i
!= type_offset(e1
->x
.p
) &&
694 !eequal(&e1
->x
.p
->arr
[i
], &e2
->x
.p
->arr
[i
]))
697 return evalue_first_difference(&e1
->x
.p
->arr
[offset
],
698 &e2
->x
.p
->arr
[offset
], d1
, d2
);
701 static order_sign
evalue_diff_constant_sign(const evalue
*e1
, const evalue
*e2
)
703 if (!evalue_first_difference(e1
, e2
, &e1
, &e2
))
705 if (value_zero_p(e1
->d
) || value_zero_p(e2
->d
))
706 return order_undefined
;
707 int s
= evalue_rational_cmp(e1
, e2
);
716 order_sign
order_cache::check_lt(vector
<order_cache_el
>* list
,
717 const indicator_term
*a
, const indicator_term
*b
,
718 order_cache_el
& cache_el
)
720 order_sign sign
= order_undefined
;
721 for (int i
= 0; i
< list
->size(); ++i
) {
723 for (j
= cache_el
.e
.size(); j
< (*list
)[i
].e
.size(); ++j
)
724 cache_el
.e
.push_back(ediff(a
->vertex
[j
], b
->vertex
[j
]));
725 for (j
= 0; j
< (*list
)[i
].e
.size(); ++j
) {
726 order_sign diff_sign
;
727 diff_sign
= evalue_diff_constant_sign((*list
)[i
].e
[j
], cache_el
.e
[j
]);
728 if (diff_sign
== order_gt
) {
731 } else if (diff_sign
== order_lt
)
733 else if (diff_sign
== order_undefined
)
736 assert(diff_sign
== order_eq
);
738 if (j
== (*list
)[i
].e
.size())
739 sign
= list
== <
? order_lt
: order_le
;
740 if (sign
!= order_undefined
)
746 order_sign
order_cache::check_direct(const indicator_term
*a
,
747 const indicator_term
*b
,
748 order_cache_el
& cache_el
)
750 order_sign sign
= check_lt(<
, a
, b
, cache_el
);
751 if (sign
!= order_undefined
)
753 sign
= check_lt(&le
, a
, b
, cache_el
);
754 if (sign
!= order_undefined
)
757 for (int i
= 0; i
< unknown
.size(); ++i
) {
759 for (j
= cache_el
.e
.size(); j
< unknown
[i
].e
.size(); ++j
)
760 cache_el
.e
.push_back(ediff(a
->vertex
[j
], b
->vertex
[j
]));
761 for (j
= 0; j
< unknown
[i
].e
.size(); ++j
) {
762 if (!eequal(unknown
[i
].e
[j
], cache_el
.e
[j
]))
765 if (j
== unknown
[i
].e
.size()) {
766 sign
= order_unknown
;
773 order_sign
order_cache::check(const indicator_term
*a
, const indicator_term
*b
,
774 order_cache_el
& cache_el
)
776 order_sign sign
= check_direct(a
, b
, cache_el
);
777 if (sign
!= order_undefined
)
779 int size
= cache_el
.e
.size();
781 sign
= check_direct(a
, b
, cache_el
);
783 assert(cache_el
.e
.size() == size
);
784 if (sign
== order_undefined
)
786 if (sign
== order_lt
)
788 else if (sign
== order_le
)
791 assert(sign
== order_unknown
);
797 struct partial_order
{
800 typedef std::set
<const indicator_term
*, smaller_it
> head_type
;
802 typedef map
<const indicator_term
*, int, smaller_it
> pred_type
;
804 typedef map
<const indicator_term
*, vector
<const indicator_term
* >, smaller_it
> order_type
;
813 partial_order(indicator
*ind
) : ind(ind
) {}
814 void copy(const partial_order
& order
,
815 map
< const indicator_term
*, indicator_term
* > old2new
);
817 order_type::iterator i
;
818 pred_type::iterator j
;
819 head_type::iterator k
;
821 if (head
.key_comp().requires_resort
) {
823 for (k
= head
.begin(); k
!= head
.end(); ++k
)
829 if (pred
.key_comp().requires_resort
) {
831 for (j
= pred
.begin(); j
!= pred
.end(); ++j
)
832 new_pred
[(*j
).first
] = (*j
).second
;
837 if (lt
.key_comp().requires_resort
) {
839 for (i
= lt
.begin(); i
!= lt
.end(); ++i
)
840 m
[(*i
).first
] = (*i
).second
;
845 if (le
.key_comp().requires_resort
) {
847 for (i
= le
.begin(); i
!= le
.end(); ++i
)
848 m
[(*i
).first
] = (*i
).second
;
853 if (eq
.key_comp().requires_resort
) {
855 for (i
= eq
.begin(); i
!= eq
.end(); ++i
)
856 m
[(*i
).first
] = (*i
).second
;
861 if (pending
.key_comp().requires_resort
) {
863 for (i
= pending
.begin(); i
!= pending
.end(); ++i
)
864 m
[(*i
).first
] = (*i
).second
;
870 order_sign
compare(const indicator_term
*a
, const indicator_term
*b
);
871 void set_equal(const indicator_term
*a
, const indicator_term
*b
);
872 void unset_le(const indicator_term
*a
, const indicator_term
*b
);
873 void dec_pred(const indicator_term
*it
) {
874 if (--pred
[it
] == 0) {
879 void inc_pred(const indicator_term
*it
) {
880 if (head
.find(it
) != head
.end())
885 bool compared(const indicator_term
* a
, const indicator_term
* b
);
886 void add(const indicator_term
* it
, std::set
<const indicator_term
*> *filter
);
887 void remove(const indicator_term
* it
);
889 void print(ostream
& os
, char **p
);
891 /* replace references to orig to references to replacement */
892 void replace(const indicator_term
* orig
, indicator_term
* replacement
);
893 void sanity_check() const;
896 /* We actually replace the contents of orig by that of replacement,
897 * but we have to be careful since replacing the content changes
898 * the order of orig in the maps.
900 void partial_order::replace(const indicator_term
* orig
, indicator_term
* replacement
)
902 head_type::iterator k
;
904 bool is_head
= k
!= head
.end();
909 orig_pred
= pred
[orig
];
912 vector
<const indicator_term
* > orig_lt
;
913 vector
<const indicator_term
* > orig_le
;
914 vector
<const indicator_term
* > orig_eq
;
915 vector
<const indicator_term
* > orig_pending
;
916 order_type::iterator i
;
917 bool in_lt
= ((i
= lt
.find(orig
)) != lt
.end());
919 orig_lt
= (*i
).second
;
922 bool in_le
= ((i
= le
.find(orig
)) != le
.end());
924 orig_le
= (*i
).second
;
927 bool in_eq
= ((i
= eq
.find(orig
)) != eq
.end());
929 orig_eq
= (*i
).second
;
932 bool in_pending
= ((i
= pending
.find(orig
)) != pending
.end());
934 orig_pending
= (*i
).second
;
937 indicator_term
*old
= const_cast<indicator_term
*>(orig
);
938 old
->swap(replacement
);
942 pred
[old
] = orig_pred
;
950 pending
[old
] = orig_pending
;
953 void partial_order::unset_le(const indicator_term
*a
, const indicator_term
*b
)
955 vector
<const indicator_term
*>::iterator i
;
956 i
= std::find(le
[a
].begin(), le
[a
].end(), b
);
958 if (le
[a
].size() == 0)
961 i
= std::find(pending
[a
].begin(), pending
[a
].end(), b
);
962 if (i
!= pending
[a
].end())
966 void partial_order::set_equal(const indicator_term
*a
, const indicator_term
*b
)
968 if (eq
[a
].size() == 0)
970 if (eq
[b
].size() == 0)
975 if (pred
.key_comp()(b
, a
)) {
976 const indicator_term
*c
= a
;
981 const indicator_term
*base
= a
;
983 order_type::iterator i
;
985 for (int j
= 0; j
< eq
[b
].size(); ++j
) {
986 eq
[base
].push_back(eq
[b
][j
]);
987 eq
[eq
[b
][j
]][0] = base
;
993 for (int j
= 0; j
< lt
[b
].size(); ++j
) {
994 if (std::find(eq
[base
].begin(), eq
[base
].end(), lt
[b
][j
]) != eq
[base
].end())
996 else if (std::find(lt
[base
].begin(), lt
[base
].end(), lt
[b
][j
])
1000 lt
[base
].push_back(lt
[b
][j
]);
1006 if (i
!= le
.end()) {
1007 for (int j
= 0; j
< le
[b
].size(); ++j
) {
1008 if (std::find(eq
[base
].begin(), eq
[base
].end(), le
[b
][j
]) != eq
[base
].end())
1010 else if (std::find(le
[base
].begin(), le
[base
].end(), le
[b
][j
])
1014 le
[base
].push_back(le
[b
][j
]);
1019 i
= pending
.find(base
);
1020 if (i
!= pending
.end()) {
1021 vector
<const indicator_term
* > old
= pending
[base
];
1022 pending
[base
].clear();
1023 for (int j
= 0; j
< old
.size(); ++j
) {
1024 if (std::find(eq
[base
].begin(), eq
[base
].end(), old
[j
]) == eq
[base
].end())
1025 pending
[base
].push_back(old
[j
]);
1029 i
= pending
.find(b
);
1030 if (i
!= pending
.end()) {
1031 for (int j
= 0; j
< pending
[b
].size(); ++j
) {
1032 if (std::find(eq
[base
].begin(), eq
[base
].end(), pending
[b
][j
]) == eq
[base
].end())
1033 pending
[base
].push_back(pending
[b
][j
]);
1039 void partial_order::copy(const partial_order
& order
,
1040 map
< const indicator_term
*, indicator_term
* > old2new
)
1042 cache
.copy(order
.cache
);
1044 order_type::const_iterator i
;
1045 pred_type::const_iterator j
;
1046 head_type::const_iterator k
;
1048 for (k
= order
.head
.begin(); k
!= order
.head
.end(); ++k
)
1049 head
.insert(old2new
[*k
]);
1051 for (j
= order
.pred
.begin(); j
!= order
.pred
.end(); ++j
)
1052 pred
[old2new
[(*j
).first
]] = (*j
).second
;
1054 for (i
= order
.lt
.begin(); i
!= order
.lt
.end(); ++i
) {
1055 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1056 lt
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1058 for (i
= order
.le
.begin(); i
!= order
.le
.end(); ++i
) {
1059 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1060 le
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1062 for (i
= order
.eq
.begin(); i
!= order
.eq
.end(); ++i
) {
1063 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1064 eq
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1066 for (i
= order
.pending
.begin(); i
!= order
.pending
.end(); ++i
) {
1067 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1068 pending
[old2new
[(*i
).first
]].push_back(old2new
[(*i
).second
[j
]]);
1074 vector
<evalue
*> max
;
1076 void print(ostream
& os
, char **p
, barvinok_options
*options
) const;
1077 void substitute(Matrix
*T
, barvinok_options
*options
);
1078 Vector
*eval(Value
*val
, unsigned MaxRays
) const;
1081 for (int i
= 0; i
< max
.size(); ++i
) {
1082 free_evalue_refs(max
[i
]);
1090 * Project on first dim dimensions
1092 Polyhedron
* Polyhedron_Project_Initial(Polyhedron
*P
, int dim
)
1098 if (P
->Dimension
== dim
)
1099 return Polyhedron_Copy(P
);
1101 T
= Matrix_Alloc(dim
+1, P
->Dimension
+1);
1102 for (i
= 0; i
< dim
; ++i
)
1103 value_set_si(T
->p
[i
][i
], 1);
1104 value_set_si(T
->p
[dim
][P
->Dimension
], 1);
1105 I
= Polyhedron_Image(P
, T
, P
->NbConstraints
);
1111 vector
<indicator_term
*> term
;
1112 indicator_constructor
& ic
;
1113 partial_order order
;
1117 lexmin_options
*options
;
1118 vector
<evalue
*> substitutions
;
1120 indicator(indicator_constructor
& ic
, Param_Domain
*PD
, EDomain
*D
,
1121 lexmin_options
*options
) :
1122 ic(ic
), order(this), D(D
), P(NULL
), PD(PD
), options(options
) {}
1123 indicator(const indicator
& ind
, EDomain
*D
) :
1124 ic(ind
.ic
), order(this), D(NULL
), P(Polyhedron_Copy(ind
.P
)),
1125 PD(ind
.PD
), options(ind
.options
) {
1126 map
< const indicator_term
*, indicator_term
* > old2new
;
1127 for (int i
= 0; i
< ind
.term
.size(); ++i
) {
1128 indicator_term
*it
= new indicator_term(*ind
.term
[i
]);
1129 old2new
[ind
.term
[i
]] = it
;
1132 order
.copy(ind
.order
, old2new
);
1136 for (int i
= 0; i
< term
.size(); ++i
)
1144 void set_domain(EDomain
*D
) {
1145 order
.cache
.clear_transients();
1149 int nparam
= ic
.PP
->Constraints
->NbColumns
-2 - ic
.vertex
.length();
1150 if (options
->reduce
) {
1151 Polyhedron
*Q
= Polyhedron_Project_Initial(D
->D
, nparam
);
1152 Q
= DomainConstraintSimplify(Q
, options
->verify
->barvinok
->MaxRays
);
1153 if (!P
|| !PolyhedronIncludes(Q
, P
))
1154 reduce_in_domain(Q
);
1162 void add(const indicator_term
* it
);
1163 void remove(const indicator_term
* it
);
1164 void remove_initial_rational_vertices();
1165 void expand_rational_vertex(const indicator_term
*initial
);
1167 void print(ostream
& os
, char **p
);
1169 void peel(int i
, int j
);
1170 void combine(const indicator_term
*a
, const indicator_term
*b
);
1171 void add_substitution(evalue
*equation
);
1172 void perform_pending_substitutions();
1173 void reduce_in_domain(Polyhedron
*D
);
1174 bool handle_equal_numerators(const indicator_term
*base
);
1176 max_term
* create_max_term(const indicator_term
*it
);
1178 void substitute(evalue
*equation
);
1181 void partial_order::sanity_check() const
1183 order_type::const_iterator i
;
1184 order_type::const_iterator prev
;
1185 order_type::const_iterator l
;
1186 pred_type::const_iterator k
, prev_k
;
1188 for (k
= pred
.begin(); k
!= pred
.end(); prev_k
= k
, ++k
)
1189 if (k
!= pred
.begin())
1190 assert(pred
.key_comp()((*prev_k
).first
, (*k
).first
));
1191 for (i
= lt
.begin(); i
!= lt
.end(); prev
= i
, ++i
) {
1194 i_v
= (*i
).first
->eval(ind
->D
->sample
->p
);
1195 if (i
!= lt
.begin())
1196 assert(lt
.key_comp()((*prev
).first
, (*i
).first
));
1197 l
= eq
.find((*i
).first
);
1199 assert((*l
).second
.size() > 1);
1200 assert(head
.find((*i
).first
) != head
.end() ||
1201 pred
.find((*i
).first
) != pred
.end());
1202 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1203 k
= pred
.find((*i
).second
[j
]);
1204 assert(k
!= pred
.end());
1205 assert((*k
).second
!= 0);
1206 if ((*i
).first
->sign
!= 0 &&
1207 (*i
).second
[j
]->sign
!= 0 && ind
->D
->sample
) {
1208 vec_ZZ j_v
= (*i
).second
[j
]->eval(ind
->D
->sample
->p
);
1209 assert(lex_cmp(i_v
, j_v
) < 0);
1213 for (i
= le
.begin(); i
!= le
.end(); ++i
) {
1214 assert((*i
).second
.size() > 0);
1215 assert(head
.find((*i
).first
) != head
.end() ||
1216 pred
.find((*i
).first
) != pred
.end());
1217 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1218 k
= pred
.find((*i
).second
[j
]);
1219 assert(k
!= pred
.end());
1220 assert((*k
).second
!= 0);
1223 for (i
= eq
.begin(); i
!= eq
.end(); ++i
) {
1224 assert(head
.find((*i
).first
) != head
.end() ||
1225 pred
.find((*i
).first
) != pred
.end());
1226 assert((*i
).second
.size() >= 1);
1228 for (i
= pending
.begin(); i
!= pending
.end(); ++i
) {
1229 assert(head
.find((*i
).first
) != head
.end() ||
1230 pred
.find((*i
).first
) != pred
.end());
1231 for (int j
= 0; j
< (*i
).second
.size(); ++j
)
1232 assert(head
.find((*i
).second
[j
]) != head
.end() ||
1233 pred
.find((*i
).second
[j
]) != pred
.end());
1237 max_term
* indicator::create_max_term(const indicator_term
*it
)
1239 int dim
= it
->den
.NumCols();
1240 max_term
*maximum
= new max_term
;
1241 maximum
->domain
= new EDomain(D
);
1242 for (int j
= 0; j
< dim
; ++j
) {
1243 evalue
*E
= new evalue
;
1245 evalue_copy(E
, it
->vertex
[j
]);
1246 if (evalue_frac2floor_in_domain(E
, D
->D
))
1248 maximum
->max
.push_back(E
);
1253 static order_sign
evalue_sign(evalue
*diff
, EDomain
*D
, barvinok_options
*options
)
1255 order_sign sign
= order_eq
;
1258 evalue_set_si(&mone
, -1, 1);
1259 int len
= 1 + D
->D
->Dimension
+ 1;
1260 Vector
*c
= Vector_Alloc(len
);
1261 Matrix
*T
= Matrix_Alloc(2, len
-1);
1263 int fract
= evalue2constraint(D
, diff
, c
->p
, len
);
1264 Vector_Copy(c
->p
+1, T
->p
[0], len
-1);
1265 value_assign(T
->p
[1][len
-2], c
->p
[0]);
1267 order_sign upper_sign
= polyhedron_affine_sign(D
->D
, T
, options
);
1268 if (upper_sign
== order_lt
|| !fract
)
1272 evalue2constraint(D
, diff
, c
->p
, len
);
1274 Vector_Copy(c
->p
+1, T
->p
[0], len
-1);
1275 value_assign(T
->p
[1][len
-2], c
->p
[0]);
1277 order_sign neg_lower_sign
= polyhedron_affine_sign(D
->D
, T
, options
);
1279 if (neg_lower_sign
== order_lt
)
1281 else if (neg_lower_sign
== order_eq
|| neg_lower_sign
== order_le
) {
1282 if (upper_sign
== order_eq
|| upper_sign
== order_le
)
1287 if (upper_sign
== order_lt
|| upper_sign
== order_le
||
1288 upper_sign
== order_eq
)
1291 sign
= order_unknown
;
1297 free_evalue_refs(&mone
);
1302 /* An auxiliary class that keeps a reference to an evalue
1303 * and frees it when it goes out of scope.
1305 struct temp_evalue
{
1307 temp_evalue() : E(NULL
) {}
1308 temp_evalue(evalue
*e
) : E(e
) {}
1309 operator evalue
* () const { return E
; }
1310 evalue
*operator=(evalue
*e
) {
1312 free_evalue_refs(E
);
1320 free_evalue_refs(E
);
1326 static void substitute(vector
<indicator_term
*>& term
, evalue
*equation
)
1328 evalue
*fract
= NULL
;
1329 evalue
*val
= new evalue
;
1331 evalue_copy(val
, equation
);
1334 value_init(factor
.d
);
1335 value_init(factor
.x
.n
);
1338 for (e
= val
; value_zero_p(e
->d
) && e
->x
.p
->type
!= fractional
;
1339 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)])
1342 if (value_zero_p(e
->d
) && e
->x
.p
->type
== fractional
)
1343 fract
= &e
->x
.p
->arr
[0];
1345 for (e
= val
; value_zero_p(e
->d
) && e
->x
.p
->type
!= polynomial
;
1346 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)])
1348 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== polynomial
);
1351 int offset
= type_offset(e
->x
.p
);
1353 assert(value_notzero_p(e
->x
.p
->arr
[offset
+1].d
));
1354 assert(value_notzero_p(e
->x
.p
->arr
[offset
+1].x
.n
));
1355 if (value_neg_p(e
->x
.p
->arr
[offset
+1].x
.n
)) {
1356 value_oppose(factor
.d
, e
->x
.p
->arr
[offset
+1].x
.n
);
1357 value_assign(factor
.x
.n
, e
->x
.p
->arr
[offset
+1].d
);
1359 value_assign(factor
.d
, e
->x
.p
->arr
[offset
+1].x
.n
);
1360 value_oppose(factor
.x
.n
, e
->x
.p
->arr
[offset
+1].d
);
1363 free_evalue_refs(&e
->x
.p
->arr
[offset
+1]);
1366 *e
= e
->x
.p
->arr
[offset
];
1371 for (int i
= 0; i
< term
.size(); ++i
)
1372 term
[i
]->substitute(fract
, val
);
1374 free_evalue_refs(&p
->arr
[0]);
1376 for (int i
= 0; i
< term
.size(); ++i
)
1377 term
[i
]->substitute(p
->pos
, val
);
1380 free_evalue_refs(&factor
);
1381 free_evalue_refs(val
);
1387 order_sign
partial_order::compare(const indicator_term
*a
, const indicator_term
*b
)
1389 unsigned dim
= a
->den
.NumCols();
1390 order_sign sign
= order_eq
;
1391 bool rational
= a
->sign
== 0 || b
->sign
== 0;
1393 order_sign cached_sign
= order_eq
;
1394 for (int k
= 0; k
< dim
; ++k
) {
1395 cached_sign
= evalue_diff_constant_sign(a
->vertex
[k
], b
->vertex
[k
]);
1396 if (cached_sign
!= order_eq
)
1399 if (cached_sign
!= order_undefined
)
1402 order_cache_el cache_el
;
1403 cached_sign
= order_undefined
;
1405 cached_sign
= cache
.check(a
, b
, cache_el
);
1406 if (cached_sign
!= order_undefined
) {
1413 vector
<indicator_term
*> term
;
1415 for (int k
= 0; k
< dim
; ++k
) {
1416 /* compute a->vertex[k] - b->vertex[k] */
1418 if (cache_el
.e
.size() <= k
) {
1419 diff
= ediff(a
->vertex
[k
], b
->vertex
[k
]);
1420 cache_el
.e
.push_back(diff
);
1422 diff
= cache_el
.e
[k
];
1425 tdiff
= diff
= ediff(term
[0]->vertex
[k
], term
[1]->vertex
[k
]);
1426 order_sign diff_sign
;
1427 if (eequal(a
->vertex
[k
], b
->vertex
[k
]))
1428 diff_sign
= order_eq
;
1430 diff_sign
= evalue_sign(diff
, ind
->D
,
1431 ind
->options
->verify
->barvinok
);
1433 if (diff_sign
== order_undefined
) {
1434 assert(sign
== order_le
|| sign
== order_ge
);
1435 if (sign
== order_le
)
1441 if (diff_sign
== order_lt
) {
1442 if (sign
== order_eq
|| sign
== order_le
)
1445 sign
= order_unknown
;
1448 if (diff_sign
== order_gt
) {
1449 if (sign
== order_eq
|| sign
== order_ge
)
1452 sign
= order_unknown
;
1455 if (diff_sign
== order_eq
) {
1456 if (term
.size() == 0 && !rational
&& !EVALUE_IS_ZERO(*diff
))
1457 ind
->add_substitution(diff
);
1460 if ((diff_sign
== order_unknown
) ||
1461 ((diff_sign
== order_lt
|| diff_sign
== order_le
) && sign
== order_ge
) ||
1462 ((diff_sign
== order_gt
|| diff_sign
== order_ge
) && sign
== order_le
)) {
1463 sign
= order_unknown
;
1470 term
.push_back(new indicator_term(*a
));
1471 term
.push_back(new indicator_term(*b
));
1473 substitute(term
, diff
);
1477 cache
.add(cache_el
, sign
);
1489 bool partial_order::compared(const indicator_term
* a
, const indicator_term
* b
)
1491 order_type::iterator j
;
1494 if (j
!= lt
.end() && std::find(lt
[a
].begin(), lt
[a
].end(), b
) != lt
[a
].end())
1498 if (j
!= le
.end() && std::find(le
[a
].begin(), le
[a
].end(), b
) != le
[a
].end())
1504 void partial_order::add(const indicator_term
* it
,
1505 std::set
<const indicator_term
*> *filter
)
1507 if (eq
.find(it
) != eq
.end() && eq
[it
].size() == 1)
1510 head_type
head_copy(head
);
1515 head_type::iterator i
;
1516 for (i
= head_copy
.begin(); i
!= head_copy
.end(); ++i
) {
1519 if (eq
.find(*i
) != eq
.end() && eq
[*i
].size() == 1)
1522 if (filter
->find(*i
) == filter
->end())
1524 if (compared(*i
, it
))
1527 order_sign sign
= compare(it
, *i
);
1528 if (sign
== order_lt
) {
1529 lt
[it
].push_back(*i
);
1531 } else if (sign
== order_le
) {
1532 le
[it
].push_back(*i
);
1534 } else if (sign
== order_eq
) {
1537 } else if (sign
== order_gt
) {
1538 pending
[*i
].push_back(it
);
1539 lt
[*i
].push_back(it
);
1541 } else if (sign
== order_ge
) {
1542 pending
[*i
].push_back(it
);
1543 le
[*i
].push_back(it
);
1549 void partial_order::remove(const indicator_term
* it
)
1551 std::set
<const indicator_term
*> filter
;
1552 order_type::iterator i
;
1554 assert(head
.find(it
) != head
.end());
1557 if (i
!= eq
.end()) {
1558 assert(eq
[it
].size() >= 1);
1559 const indicator_term
*base
;
1560 if (eq
[it
].size() == 1) {
1564 vector
<const indicator_term
* >::iterator j
;
1565 j
= std::find(eq
[base
].begin(), eq
[base
].end(), it
);
1566 assert(j
!= eq
[base
].end());
1569 /* "it" may no longer be the smallest, since the order
1570 * structure may have been copied from another one.
1572 std::sort(eq
[it
].begin()+1, eq
[it
].end(), pred
.key_comp());
1573 assert(eq
[it
][0] == it
);
1574 eq
[it
].erase(eq
[it
].begin());
1579 for (int j
= 1; j
< eq
[base
].size(); ++j
)
1580 eq
[eq
[base
][j
]][0] = base
;
1583 if (i
!= lt
.end()) {
1589 if (i
!= le
.end()) {
1594 i
= pending
.find(it
);
1595 if (i
!= pending
.end()) {
1596 pending
[base
] = pending
[it
];
1601 if (eq
[base
].size() == 1)
1610 if (i
!= lt
.end()) {
1611 for (int j
= 0; j
< lt
[it
].size(); ++j
) {
1612 filter
.insert(lt
[it
][j
]);
1613 dec_pred(lt
[it
][j
]);
1619 if (i
!= le
.end()) {
1620 for (int j
= 0; j
< le
[it
].size(); ++j
) {
1621 filter
.insert(le
[it
][j
]);
1622 dec_pred(le
[it
][j
]);
1629 i
= pending
.find(it
);
1630 if (i
!= pending
.end()) {
1631 vector
<const indicator_term
*> it_pending
= pending
[it
];
1633 for (int j
= 0; j
< it_pending
.size(); ++j
) {
1634 filter
.erase(it_pending
[j
]);
1635 add(it_pending
[j
], &filter
);
1640 void partial_order::print(ostream
& os
, char **p
)
1642 order_type::iterator i
;
1643 pred_type::iterator j
;
1644 head_type::iterator k
;
1645 for (k
= head
.begin(); k
!= head
.end(); ++k
) {
1649 for (j
= pred
.begin(); j
!= pred
.end(); ++j
) {
1650 (*j
).first
->print(os
, p
);
1651 os
<< ": " << (*j
).second
<< endl
;
1653 for (i
= lt
.begin(); i
!= lt
.end(); ++i
) {
1654 (*i
).first
->print(os
, p
);
1655 assert(head
.find((*i
).first
) != head
.end() ||
1656 pred
.find((*i
).first
) != pred
.end());
1657 if (pred
.find((*i
).first
) != pred
.end())
1658 os
<< "(" << pred
[(*i
).first
] << ")";
1660 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1663 (*i
).second
[j
]->print(os
, p
);
1664 assert(pred
.find((*i
).second
[j
]) != pred
.end());
1665 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1669 for (i
= le
.begin(); i
!= le
.end(); ++i
) {
1670 (*i
).first
->print(os
, p
);
1671 assert(head
.find((*i
).first
) != head
.end() ||
1672 pred
.find((*i
).first
) != pred
.end());
1673 if (pred
.find((*i
).first
) != pred
.end())
1674 os
<< "(" << pred
[(*i
).first
] << ")";
1676 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1679 (*i
).second
[j
]->print(os
, p
);
1680 assert(pred
.find((*i
).second
[j
]) != pred
.end());
1681 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1685 for (i
= eq
.begin(); i
!= eq
.end(); ++i
) {
1686 if ((*i
).second
.size() <= 1)
1688 (*i
).first
->print(os
, p
);
1689 assert(head
.find((*i
).first
) != head
.end() ||
1690 pred
.find((*i
).first
) != pred
.end());
1691 if (pred
.find((*i
).first
) != pred
.end())
1692 os
<< "(" << pred
[(*i
).first
] << ")";
1693 for (int j
= 1; j
< (*i
).second
.size(); ++j
) {
1696 (*i
).second
[j
]->print(os
, p
);
1697 assert(head
.find((*i
).second
[j
]) != head
.end() ||
1698 pred
.find((*i
).second
[j
]) != pred
.end());
1699 if (pred
.find((*i
).second
[j
]) != pred
.end())
1700 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1704 for (i
= pending
.begin(); i
!= pending
.end(); ++i
) {
1705 os
<< "pending on ";
1706 (*i
).first
->print(os
, p
);
1707 assert(head
.find((*i
).first
) != head
.end() ||
1708 pred
.find((*i
).first
) != pred
.end());
1709 if (pred
.find((*i
).first
) != pred
.end())
1710 os
<< "(" << pred
[(*i
).first
] << ")";
1712 for (int j
= 0; j
< (*i
).second
.size(); ++j
) {
1715 (*i
).second
[j
]->print(os
, p
);
1716 assert(pred
.find((*i
).second
[j
]) != pred
.end());
1717 os
<< "(" << pred
[(*i
).second
[j
]] << ")";
1723 void indicator::add(const indicator_term
* it
)
1725 indicator_term
*nt
= new indicator_term(*it
);
1726 if (options
->reduce
)
1727 nt
->reduce_in_domain(P
? P
: D
->D
);
1729 order
.add(nt
, NULL
);
1730 assert(term
.size() == order
.head
.size() + order
.pred
.size());
1733 void indicator::remove(const indicator_term
* it
)
1735 vector
<indicator_term
*>::iterator i
;
1736 i
= std::find(term
.begin(), term
.end(), it
);
1737 assert(i
!= term
.end());
1740 assert(term
.size() == order
.head
.size() + order
.pred
.size());
1744 void indicator::expand_rational_vertex(const indicator_term
*initial
)
1746 int pos
= initial
->pos
;
1748 if (ic
.terms
[pos
].size() == 0) {
1750 FORALL_PVertex_in_ParamPolyhedron(V
, PD
, ic
.PP
) // _i is internal counter
1752 ic
.decompose_at_vertex(V
, pos
, options
->verify
->barvinok
);
1755 END_FORALL_PVertex_in_ParamPolyhedron
;
1757 for (int j
= 0; j
< ic
.terms
[pos
].size(); ++j
)
1758 add(ic
.terms
[pos
][j
]);
1761 void indicator::remove_initial_rational_vertices()
1764 const indicator_term
*initial
= NULL
;
1765 partial_order::head_type::iterator i
;
1766 for (i
= order
.head
.begin(); i
!= order
.head
.end(); ++i
) {
1767 if ((*i
)->sign
!= 0)
1769 if (order
.eq
.find(*i
) != order
.eq
.end() && order
.eq
[*i
].size() <= 1)
1776 expand_rational_vertex(initial
);
1780 void indicator::reduce_in_domain(Polyhedron
*D
)
1782 for (int i
= 0; i
< term
.size(); ++i
)
1783 term
[i
]->reduce_in_domain(D
);
1786 void indicator::print(ostream
& os
, char **p
)
1788 assert(term
.size() == order
.head
.size() + order
.pred
.size());
1789 for (int i
= 0; i
< term
.size(); ++i
) {
1790 term
[i
]->print(os
, p
);
1792 os
<< ": " << term
[i
]->eval(D
->sample
->p
);
1799 /* Remove pairs of opposite terms */
1800 void indicator::simplify()
1802 for (int i
= 0; i
< term
.size(); ++i
) {
1803 for (int j
= i
+1; j
< term
.size(); ++j
) {
1804 if (term
[i
]->sign
+ term
[j
]->sign
!= 0)
1806 if (term
[i
]->den
!= term
[j
]->den
)
1809 for (k
= 0; k
< term
[i
]->den
.NumCols(); ++k
)
1810 if (!eequal(term
[i
]->vertex
[k
], term
[j
]->vertex
[k
]))
1812 if (k
< term
[i
]->den
.NumCols())
1816 term
.erase(term
.begin()+j
);
1817 term
.erase(term
.begin()+i
);
1824 void indicator::peel(int i
, int j
)
1832 int dim
= term
[i
]->den
.NumCols();
1837 int n_common
= 0, n_i
= 0, n_j
= 0;
1839 common
.SetDims(min(term
[i
]->den
.NumRows(), term
[j
]->den
.NumRows()), dim
);
1840 rest_i
.SetDims(term
[i
]->den
.NumRows(), dim
);
1841 rest_j
.SetDims(term
[j
]->den
.NumRows(), dim
);
1844 for (k
= 0, l
= 0; k
< term
[i
]->den
.NumRows() && l
< term
[j
]->den
.NumRows(); ) {
1845 int s
= lex_cmp(term
[i
]->den
[k
], term
[j
]->den
[l
]);
1847 common
[n_common
++] = term
[i
]->den
[k
];
1851 rest_i
[n_i
++] = term
[i
]->den
[k
++];
1853 rest_j
[n_j
++] = term
[j
]->den
[l
++];
1855 while (k
< term
[i
]->den
.NumRows())
1856 rest_i
[n_i
++] = term
[i
]->den
[k
++];
1857 while (l
< term
[j
]->den
.NumRows())
1858 rest_j
[n_j
++] = term
[j
]->den
[l
++];
1859 common
.SetDims(n_common
, dim
);
1860 rest_i
.SetDims(n_i
, dim
);
1861 rest_j
.SetDims(n_j
, dim
);
1863 for (k
= 0; k
<= n_i
; ++k
) {
1864 indicator_term
*it
= new indicator_term(*term
[i
]);
1865 it
->den
.SetDims(n_common
+ k
, dim
);
1866 for (l
= 0; l
< n_common
; ++l
)
1867 it
->den
[l
] = common
[l
];
1868 for (l
= 0; l
< k
; ++l
)
1869 it
->den
[n_common
+l
] = rest_i
[l
];
1870 lex_order_rows(it
->den
);
1872 for (l
= 0; l
< dim
; ++l
)
1873 evalue_add_constant(it
->vertex
[l
], rest_i
[k
-1][l
]);
1877 for (k
= 0; k
<= n_j
; ++k
) {
1878 indicator_term
*it
= new indicator_term(*term
[j
]);
1879 it
->den
.SetDims(n_common
+ k
, dim
);
1880 for (l
= 0; l
< n_common
; ++l
)
1881 it
->den
[l
] = common
[l
];
1882 for (l
= 0; l
< k
; ++l
)
1883 it
->den
[n_common
+l
] = rest_j
[l
];
1884 lex_order_rows(it
->den
);
1886 for (l
= 0; l
< dim
; ++l
)
1887 evalue_add_constant(it
->vertex
[l
], rest_j
[k
-1][l
]);
1890 term
.erase(term
.begin()+j
);
1891 term
.erase(term
.begin()+i
);
1894 void indicator::combine(const indicator_term
*a
, const indicator_term
*b
)
1896 int dim
= a
->den
.NumCols();
1899 mat_ZZ rest_i
; /* factors in a, but not in b */
1900 mat_ZZ rest_j
; /* factors in b, but not in a */
1901 int n_common
= 0, n_i
= 0, n_j
= 0;
1903 common
.SetDims(min(a
->den
.NumRows(), b
->den
.NumRows()), dim
);
1904 rest_i
.SetDims(a
->den
.NumRows(), dim
);
1905 rest_j
.SetDims(b
->den
.NumRows(), dim
);
1908 for (k
= 0, l
= 0; k
< a
->den
.NumRows() && l
< b
->den
.NumRows(); ) {
1909 int s
= lex_cmp(a
->den
[k
], b
->den
[l
]);
1911 common
[n_common
++] = a
->den
[k
];
1915 rest_i
[n_i
++] = a
->den
[k
++];
1917 rest_j
[n_j
++] = b
->den
[l
++];
1919 while (k
< a
->den
.NumRows())
1920 rest_i
[n_i
++] = a
->den
[k
++];
1921 while (l
< b
->den
.NumRows())
1922 rest_j
[n_j
++] = b
->den
[l
++];
1923 common
.SetDims(n_common
, dim
);
1924 rest_i
.SetDims(n_i
, dim
);
1925 rest_j
.SetDims(n_j
, dim
);
1927 assert(order
.eq
[a
].size() > 1);
1928 indicator_term
*prev
;
1931 for (int k
= n_i
-1; k
>= 0; --k
) {
1932 indicator_term
*it
= new indicator_term(*b
);
1933 it
->den
.SetDims(n_common
+ n_j
+ n_i
-k
, dim
);
1934 for (int l
= k
; l
< n_i
; ++l
)
1935 it
->den
[n_common
+n_j
+l
-k
] = rest_i
[l
];
1936 lex_order_rows(it
->den
);
1937 for (int m
= 0; m
< dim
; ++m
)
1938 evalue_add_constant(it
->vertex
[m
], rest_i
[k
][m
]);
1939 it
->sign
= -it
->sign
;
1941 order
.pending
[it
].push_back(prev
);
1942 order
.lt
[it
].push_back(prev
);
1943 order
.inc_pred(prev
);
1946 order
.head
.insert(it
);
1950 indicator_term
*it
= new indicator_term(*b
);
1951 it
->den
.SetDims(n_common
+ n_i
+ n_j
, dim
);
1952 for (l
= 0; l
< n_i
; ++l
)
1953 it
->den
[n_common
+n_j
+l
] = rest_i
[l
];
1954 lex_order_rows(it
->den
);
1956 order
.pending
[a
].push_back(prev
);
1957 order
.lt
[a
].push_back(prev
);
1958 order
.inc_pred(prev
);
1959 order
.replace(b
, it
);
1964 for (int k
= n_j
-1; k
>= 0; --k
) {
1965 indicator_term
*it
= new indicator_term(*a
);
1966 it
->den
.SetDims(n_common
+ n_i
+ n_j
-k
, dim
);
1967 for (int l
= k
; l
< n_j
; ++l
)
1968 it
->den
[n_common
+n_i
+l
-k
] = rest_j
[l
];
1969 lex_order_rows(it
->den
);
1970 for (int m
= 0; m
< dim
; ++m
)
1971 evalue_add_constant(it
->vertex
[m
], rest_j
[k
][m
]);
1972 it
->sign
= -it
->sign
;
1974 order
.pending
[it
].push_back(prev
);
1975 order
.lt
[it
].push_back(prev
);
1976 order
.inc_pred(prev
);
1979 order
.head
.insert(it
);
1983 indicator_term
*it
= new indicator_term(*a
);
1984 it
->den
.SetDims(n_common
+ n_i
+ n_j
, dim
);
1985 for (l
= 0; l
< n_j
; ++l
)
1986 it
->den
[n_common
+n_i
+l
] = rest_j
[l
];
1987 lex_order_rows(it
->den
);
1989 order
.pending
[a
].push_back(prev
);
1990 order
.lt
[a
].push_back(prev
);
1991 order
.inc_pred(prev
);
1992 order
.replace(a
, it
);
1996 assert(term
.size() == order
.head
.size() + order
.pred
.size());
1999 bool indicator::handle_equal_numerators(const indicator_term
*base
)
2001 for (int i
= 0; i
< order
.eq
[base
].size(); ++i
) {
2002 for (int j
= i
+1; j
< order
.eq
[base
].size(); ++j
) {
2003 if (order
.eq
[base
][i
]->is_opposite(order
.eq
[base
][j
])) {
2004 remove(order
.eq
[base
][j
]);
2005 remove(i
? order
.eq
[base
][i
] : base
);
2010 for (int j
= 1; j
< order
.eq
[base
].size(); ++j
)
2011 if (order
.eq
[base
][j
]->sign
!= base
->sign
) {
2012 combine(base
, order
.eq
[base
][j
]);
2018 void indicator::substitute(evalue
*equation
)
2020 ::substitute(term
, equation
);
2023 void indicator::add_substitution(evalue
*equation
)
2025 for (int i
= 0; i
< substitutions
.size(); ++i
)
2026 if (eequal(substitutions
[i
], equation
))
2028 evalue
*copy
= new evalue();
2029 value_init(copy
->d
);
2030 evalue_copy(copy
, equation
);
2031 substitutions
.push_back(copy
);
2034 void indicator::perform_pending_substitutions()
2036 if (substitutions
.size() == 0)
2039 for (int i
= 0; i
< substitutions
.size(); ++i
) {
2040 substitute(substitutions
[i
]);
2041 free_evalue_refs(substitutions
[i
]);
2042 delete substitutions
[i
];
2044 substitutions
.clear();
2048 static void print_varlist(ostream
& os
, int n
, char **names
)
2052 for (i
= 0; i
< n
; ++i
) {
2060 void max_term::print(ostream
& os
, char **p
, barvinok_options
*options
) const
2063 print_varlist(os
, domain
->dimension(), p
);
2066 for (int i
= 0; i
< max
.size(); ++i
) {
2069 evalue_print(os
, max
[i
], p
);
2073 domain
->print_constraints(os
, p
, options
);
2077 /* T maps the compressed parameters to the original parameters,
2078 * while this max_term is based on the compressed parameters
2079 * and we want get the original parameters back.
2081 void max_term::substitute(Matrix
*T
, barvinok_options
*options
)
2083 assert(domain
->dimension() == T
->NbColumns
-1);
2085 Matrix
*inv
= left_inverse(T
, &Eq
);
2088 value_init(denom
.d
);
2089 value_init(denom
.x
.n
);
2090 value_set_si(denom
.x
.n
, 1);
2091 value_assign(denom
.d
, inv
->p
[inv
->NbRows
-1][inv
->NbColumns
-1]);
2094 v
.SetLength(inv
->NbColumns
);
2095 evalue
**subs
= new evalue
*[inv
->NbRows
-1];
2096 for (int i
= 0; i
< inv
->NbRows
-1; ++i
) {
2097 values2zz(inv
->p
[i
], v
, v
.length());
2098 subs
[i
] = multi_monom(v
);
2099 emul(&denom
, subs
[i
]);
2101 free_evalue_refs(&denom
);
2103 domain
->substitute(subs
, inv
, Eq
, options
->MaxRays
);
2106 for (int i
= 0; i
< max
.size(); ++i
) {
2107 evalue_substitute(max
[i
], subs
);
2108 reduce_evalue(max
[i
]);
2111 for (int i
= 0; i
< inv
->NbRows
-1; ++i
) {
2112 free_evalue_refs(subs
[i
]);
2119 Vector
*max_term::eval(Value
*val
, unsigned MaxRays
) const
2121 if (!domain
->contains(val
, domain
->dimension()))
2123 Vector
*res
= Vector_Alloc(max
.size());
2124 for (int i
= 0; i
< max
.size(); ++i
) {
2125 compute_evalue(max
[i
], val
, &res
->p
[i
]);
2132 enum sign
{ le
, ge
, lge
} sign
;
2134 split (evalue
*c
, enum sign s
) : constraint(c
), sign(s
) {}
2137 static void split_on(const split
& sp
, EDomain
*D
,
2138 EDomain
**Dlt
, EDomain
**Deq
, EDomain
**Dgt
,
2139 lexmin_options
*options
)
2145 ge_constraint
*ge
= D
->compute_ge_constraint(sp
.constraint
);
2146 if (sp
.sign
== split::lge
|| sp
.sign
== split::ge
)
2147 ED
[2] = EDomain::new_from_ge_constraint(ge
, 1, options
->verify
->barvinok
);
2150 if (sp
.sign
== split::lge
|| sp
.sign
== split::le
)
2151 ED
[0] = EDomain::new_from_ge_constraint(ge
, -1, options
->verify
->barvinok
);
2155 assert(sp
.sign
== split::lge
|| sp
.sign
== split::ge
|| sp
.sign
== split::le
);
2156 ED
[1] = EDomain::new_from_ge_constraint(ge
, 0, options
->verify
->barvinok
);
2160 for (int i
= 0; i
< 3; ++i
) {
2163 if (D
->sample
&& ED
[i
]->contains(D
->sample
->p
, D
->sample
->Size
-1)) {
2164 ED
[i
]->sample
= Vector_Alloc(D
->sample
->Size
);
2165 Vector_Copy(D
->sample
->p
, ED
[i
]->sample
->p
, D
->sample
->Size
);
2166 } else if (emptyQ2(ED
[i
]->D
) ||
2167 (options
->emptiness_check
!= BV_LEXMIN_EMPTINESS_CHECK_NONE
&&
2168 !(ED
[i
]->not_empty(options
)))) {
2178 ostream
& operator<< (ostream
& os
, const vector
<int> & v
)
2181 for (int i
= 0; i
< v
.size(); ++i
) {
2190 void construct_rational_vertices(Param_Polyhedron
*PP
, Matrix
*T
, unsigned dim
,
2191 int nparam
, vector
<indicator_term
*>& vertices
)
2200 v
.SetLength(nparam
+1);
2203 value_init(factor
.d
);
2204 value_init(factor
.x
.n
);
2205 value_set_si(factor
.x
.n
, 1);
2206 value_set_si(factor
.d
, 1);
2208 for (i
= 0, PV
= PP
->V
; PV
; ++i
, PV
= PV
->next
) {
2209 indicator_term
*term
= new indicator_term(dim
, i
);
2210 vertices
.push_back(term
);
2211 Matrix
*M
= Matrix_Alloc(PV
->Vertex
->NbRows
+nparam
+1, nparam
+1);
2212 value_set_si(lcm
, 1);
2213 for (int j
= 0; j
< PV
->Vertex
->NbRows
; ++j
)
2214 value_lcm(lcm
, lcm
, PV
->Vertex
->p
[j
][nparam
+1]);
2215 value_assign(M
->p
[M
->NbRows
-1][M
->NbColumns
-1], lcm
);
2216 for (int j
= 0; j
< PV
->Vertex
->NbRows
; ++j
) {
2217 value_division(tmp
, lcm
, PV
->Vertex
->p
[j
][nparam
+1]);
2218 Vector_Scale(PV
->Vertex
->p
[j
], M
->p
[j
], tmp
, nparam
+1);
2220 for (int j
= 0; j
< nparam
; ++j
)
2221 value_assign(M
->p
[PV
->Vertex
->NbRows
+j
][j
], lcm
);
2223 Matrix
*M2
= Matrix_Alloc(T
->NbRows
, M
->NbColumns
);
2224 Matrix_Product(T
, M
, M2
);
2228 for (int j
= 0; j
< dim
; ++j
) {
2229 values2zz(M
->p
[j
], v
, nparam
+1);
2230 term
->vertex
[j
] = multi_monom(v
);
2231 value_assign(factor
.d
, lcm
);
2232 emul(&factor
, term
->vertex
[j
]);
2236 assert(i
== PP
->nbV
);
2237 free_evalue_refs(&factor
);
2242 static vector
<max_term
*> lexmin(indicator
& ind
, unsigned nparam
,
2245 vector
<max_term
*> maxima
;
2246 partial_order::head_type::iterator i
;
2247 vector
<int> best_score
;
2248 vector
<int> second_score
;
2249 vector
<int> neg_score
;
2252 ind
.perform_pending_substitutions();
2253 const indicator_term
*best
= NULL
, *second
= NULL
, *neg
= NULL
,
2254 *neg_eq
= NULL
, *neg_le
= NULL
;
2255 for (i
= ind
.order
.head
.begin(); i
!= ind
.order
.head
.end(); ++i
) {
2257 const indicator_term
*term
= *i
;
2258 if (term
->sign
== 0) {
2259 ind
.expand_rational_vertex(term
);
2263 if (ind
.order
.eq
.find(term
) != ind
.order
.eq
.end()) {
2265 if (ind
.order
.eq
[term
].size() <= 1)
2267 for (j
= 1; j
< ind
.order
.eq
[term
].size(); ++j
)
2268 if (ind
.order
.pred
.find(ind
.order
.eq
[term
][j
]) !=
2269 ind
.order
.pred
.end())
2271 if (j
< ind
.order
.eq
[term
].size())
2273 score
.push_back(ind
.order
.eq
[term
].size());
2276 if (ind
.order
.le
.find(term
) != ind
.order
.le
.end())
2277 score
.push_back(ind
.order
.le
[term
].size());
2280 if (ind
.order
.lt
.find(term
) != ind
.order
.lt
.end())
2281 score
.push_back(-ind
.order
.lt
[term
].size());
2285 if (term
->sign
> 0) {
2286 if (!best
|| score
< best_score
) {
2288 second_score
= best_score
;
2291 } else if (!second
|| score
< second_score
) {
2293 second_score
= score
;
2296 if (!neg_eq
&& ind
.order
.eq
.find(term
) != ind
.order
.eq
.end()) {
2297 for (int j
= 1; j
< ind
.order
.eq
[term
].size(); ++j
)
2298 if (ind
.order
.eq
[term
][j
]->sign
!= term
->sign
) {
2303 if (!neg_le
&& ind
.order
.le
.find(term
) != ind
.order
.le
.end())
2305 if (!neg
|| score
< neg_score
) {
2311 if (i
!= ind
.order
.head
.end())
2314 if (!best
&& neg_eq
) {
2315 assert(ind
.order
.eq
[neg_eq
].size() != 0);
2316 bool handled
= ind
.handle_equal_numerators(neg_eq
);
2321 if (!best
&& neg_le
) {
2322 /* The smallest term is negative and <= some positive term */
2328 /* apparently there can be negative initial term on empty domains */
2329 if (ind
.options
->emptiness_check
!= BV_LEXMIN_EMPTINESS_CHECK_NONE
&&
2330 ind
.options
->verify
->barvinok
->lp_solver
== BV_LP_POLYLIB
)
2335 if (!second
&& !neg
) {
2336 const indicator_term
*rat
= NULL
;
2338 if (ind
.order
.le
.find(best
) == ind
.order
.le
.end()) {
2339 if (ind
.order
.eq
.find(best
) != ind
.order
.eq
.end()) {
2340 bool handled
= ind
.handle_equal_numerators(best
);
2341 if (ind
.options
->emptiness_check
!=
2342 BV_LEXMIN_EMPTINESS_CHECK_NONE
&&
2343 ind
.options
->verify
->barvinok
->lp_solver
== BV_LP_POLYLIB
)
2345 /* If !handled then the leading coefficient is bigger than one;
2346 * must be an empty domain
2353 maxima
.push_back(ind
.create_max_term(best
));
2356 for (int j
= 0; j
< ind
.order
.le
[best
].size(); ++j
) {
2357 if (ind
.order
.le
[best
][j
]->sign
== 0) {
2358 if (!rat
&& ind
.order
.pred
[ind
.order
.le
[best
][j
]] == 1)
2359 rat
= ind
.order
.le
[best
][j
];
2360 } else if (ind
.order
.le
[best
][j
]->sign
> 0) {
2361 second
= ind
.order
.le
[best
][j
];
2364 neg
= ind
.order
.le
[best
][j
];
2367 if (!second
&& !neg
) {
2369 ind
.order
.unset_le(best
, rat
);
2370 ind
.expand_rational_vertex(rat
);
2377 ind
.order
.unset_le(best
, second
);
2383 unsigned dim
= best
->den
.NumCols();
2386 for (int k
= 0; k
< dim
; ++k
) {
2387 diff
= ediff(best
->vertex
[k
], second
->vertex
[k
]);
2388 sign
= evalue_sign(diff
, ind
.D
, ind
.options
->verify
->barvinok
);
2390 /* neg can never be smaller than best, unless it may still cancel.
2391 * This can happen if positive terms have been determined to
2392 * be equal or less than or equal to some negative term.
2394 if (second
== neg
&& !neg_eq
&& !neg_le
) {
2395 if (sign
== order_ge
)
2397 if (sign
== order_unknown
)
2401 if (sign
!= order_eq
)
2403 if (!EVALUE_IS_ZERO(*diff
)) {
2404 ind
.add_substitution(diff
);
2405 ind
.perform_pending_substitutions();
2408 if (sign
== order_eq
) {
2409 ind
.order
.set_equal(best
, second
);
2412 if (sign
== order_lt
) {
2413 ind
.order
.lt
[best
].push_back(second
);
2414 ind
.order
.inc_pred(second
);
2417 if (sign
== order_gt
) {
2418 ind
.order
.lt
[second
].push_back(best
);
2419 ind
.order
.inc_pred(best
);
2423 split
sp(diff
, sign
== order_le
? split::le
:
2424 sign
== order_ge
? split::ge
: split::lge
);
2426 EDomain
*Dlt
, *Deq
, *Dgt
;
2427 split_on(sp
, ind
.D
, &Dlt
, &Deq
, &Dgt
, ind
.options
);
2428 if (ind
.options
->emptiness_check
!= BV_LEXMIN_EMPTINESS_CHECK_NONE
)
2429 assert(Dlt
|| Deq
|| Dgt
);
2430 else if (!(Dlt
|| Deq
|| Dgt
))
2431 /* Must have been empty all along */
2434 if (Deq
&& (Dlt
|| Dgt
)) {
2435 int locsize
= loc
.size();
2437 indicator
indeq(ind
, Deq
);
2439 indeq
.add_substitution(diff
);
2440 indeq
.perform_pending_substitutions();
2441 vector
<max_term
*> maxeq
= lexmin(indeq
, nparam
, loc
);
2442 maxima
.insert(maxima
.end(), maxeq
.begin(), maxeq
.end());
2443 loc
.resize(locsize
);
2446 int locsize
= loc
.size();
2448 indicator
indgt(ind
, Dgt
);
2450 /* we don't know the new location of these terms in indgt */
2452 indgt.order.lt[second].push_back(best);
2453 indgt.order.inc_pred(best);
2455 vector
<max_term
*> maxgt
= lexmin(indgt
, nparam
, loc
);
2456 maxima
.insert(maxima
.end(), maxgt
.begin(), maxgt
.end());
2457 loc
.resize(locsize
);
2462 ind
.set_domain(Deq
);
2463 ind
.add_substitution(diff
);
2464 ind
.perform_pending_substitutions();
2468 ind
.set_domain(Dlt
);
2469 ind
.order
.lt
[best
].push_back(second
);
2470 ind
.order
.inc_pred(second
);
2474 ind
.set_domain(Dgt
);
2475 ind
.order
.lt
[second
].push_back(best
);
2476 ind
.order
.inc_pred(best
);
2483 static void lexmin_base(Polyhedron
*P
, Polyhedron
*C
,
2484 Matrix
*CP
, Matrix
*T
,
2485 vector
<max_term
*>& all_max
,
2486 lexmin_options
*options
)
2488 unsigned nparam
= C
->Dimension
;
2489 Param_Polyhedron
*PP
= NULL
;
2491 PP
= Polyhedron2Param_Polyhedron(P
, C
, options
->verify
->barvinok
);
2493 unsigned dim
= P
->Dimension
- nparam
;
2497 indicator_constructor
ic(dim
, PP
, T
);
2499 vector
<indicator_term
*> all_vertices
;
2500 construct_rational_vertices(PP
, T
, T
? T
->NbRows
-nparam
-1 : dim
,
2501 nparam
, all_vertices
);
2503 Polyhedron
*TC
= true_context(P
, C
, options
->verify
->barvinok
->MaxRays
);
2504 FORALL_REDUCED_DOMAIN(PP
, TC
, nd
, options
->verify
->barvinok
, i
, D
, rVD
)
2507 EDomain
*epVD
= new EDomain(rVD
);
2508 indicator
ind(ic
, D
, epVD
, options
);
2510 FORALL_PVertex_in_ParamPolyhedron(V
,D
,PP
) // _i is internal counter
2511 ind
.add(all_vertices
[_i
]);
2512 END_FORALL_PVertex_in_ParamPolyhedron
;
2514 ind
.remove_initial_rational_vertices();
2517 vector
<max_term
*> maxima
= lexmin(ind
, nparam
, loc
);
2519 for (int j
= 0; j
< maxima
.size(); ++j
)
2520 maxima
[j
]->substitute(CP
, options
->verify
->barvinok
);
2521 all_max
.insert(all_max
.end(), maxima
.begin(), maxima
.end());
2524 END_FORALL_REDUCED_DOMAIN
2525 Polyhedron_Free(TC
);
2526 for (int i
= 0; i
< all_vertices
.size(); ++i
)
2527 delete all_vertices
[i
];
2528 Param_Polyhedron_Free(PP
);
2531 static vector
<max_term
*> lexmin(Polyhedron
*P
, Polyhedron
*C
,
2532 lexmin_options
*options
)
2534 unsigned nparam
= C
->Dimension
;
2535 Matrix
*T
= NULL
, *CP
= NULL
;
2536 Polyhedron
*Porig
= P
;
2537 Polyhedron
*Corig
= C
;
2538 vector
<max_term
*> all_max
;
2543 POL_ENSURE_VERTICES(P
);
2548 assert(P
->NbBid
== 0);
2551 remove_all_equalities(&P
, &C
, &CP
, &T
, nparam
,
2552 options
->verify
->barvinok
->MaxRays
);
2554 lexmin_base(P
, C
, CP
, T
, all_max
, options
);
2567 static void verify_results(Polyhedron
*A
, Polyhedron
*C
,
2568 vector
<max_term
*>& maxima
,
2569 struct verify_options
*options
);
2571 /* Turn the set dimensions of "context" into parameters and return
2572 * the corresponding parameter domain.
2574 static struct isl_basic_set
*to_parameter_domain(struct isl_basic_set
*context
)
2576 context
= isl_basic_set_move_dims(context
, isl_dim_param
, 0,
2577 isl_dim_set
, 0, isl_basic_set_dim(context
, isl_dim_set
));
2578 context
= isl_basic_set_params(context
);
2582 int main(int argc
, char **argv
)
2585 isl_basic_set
*context
, *bset
;
2590 int urs_unknowns
= 0;
2591 int print_solution
= 1;
2592 struct lexmin_options
*options
= lexmin_options_new_with_defaults();
2594 options
->verify
->barvinok
->lookup_table
= 0;
2596 argc
= lexmin_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
2597 ctx
= isl_ctx_alloc_with_options(&lexmin_options_args
, options
);
2599 context
= isl_basic_set_read_from_file(ctx
, stdin
);
2601 n
= fscanf(stdin
, "%d", &neg_one
);
2603 assert(neg_one
== -1);
2604 bset
= isl_basic_set_read_from_file(ctx
, stdin
);
2606 while (fgets(s
, sizeof(s
), stdin
)) {
2607 if (strncasecmp(s
, "Maximize", 8) == 0) {
2608 fprintf(stderr
, "Maximize option not supported\n");
2611 if (strncasecmp(s
, "Rational", 8) == 0) {
2612 fprintf(stderr
, "Rational option not supported\n");
2615 if (strncasecmp(s
, "Urs_parms", 9) == 0)
2617 if (strncasecmp(s
, "Urs_unknowns", 12) == 0)
2621 context
= isl_basic_set_intersect(context
,
2622 isl_basic_set_positive_orthant(isl_basic_set_get_space(context
)));
2623 context
= to_parameter_domain(context
);
2624 nparam
= isl_basic_set_dim(context
, isl_dim_param
);
2625 if (nparam
!= isl_basic_set_dim(bset
, isl_dim_param
)) {
2626 int dim
= isl_basic_set_dim(bset
, isl_dim_set
);
2627 bset
= isl_basic_set_move_dims(bset
, isl_dim_param
, 0,
2628 isl_dim_set
, dim
- nparam
, nparam
);
2631 bset
= isl_basic_set_intersect(bset
,
2632 isl_basic_set_positive_orthant(isl_basic_set_get_space(bset
)));
2634 if (options
->verify
->verify
)
2637 A
= isl_basic_set_to_polylib(bset
);
2638 verify_options_set_range(options
->verify
, A
->Dimension
);
2639 C
= isl_basic_set_to_polylib(context
);
2640 vector
<max_term
*> maxima
= lexmin(A
, C
, options
);
2641 if (print_solution
) {
2643 param_names
= util_generate_names(C
->Dimension
, "p");
2644 for (int i
= 0; i
< maxima
.size(); ++i
)
2645 maxima
[i
]->print(cout
, param_names
,
2646 options
->verify
->barvinok
);
2647 util_free_names(C
->Dimension
, param_names
);
2650 if (options
->verify
->verify
)
2651 verify_results(A
, C
, maxima
, options
->verify
);
2653 for (int i
= 0; i
< maxima
.size(); ++i
)
2659 isl_basic_set_free(bset
);
2660 isl_basic_set_free(context
);
2666 static bool lexmin(int pos
, Polyhedron
*P
, Value
*context
)
2675 value_init(LB
); value_init(UB
); value_init(k
);
2678 lu_flags
= lower_upper_bounds(pos
,P
,context
,&LB
,&UB
);
2679 assert(!(lu_flags
& LB_INFINITY
));
2681 value_set_si(context
[pos
],0);
2682 if (!lu_flags
&& value_lt(UB
,LB
)) {
2683 value_clear(LB
); value_clear(UB
); value_clear(k
);
2687 value_assign(context
[pos
], LB
);
2688 value_clear(LB
); value_clear(UB
); value_clear(k
);
2691 for (value_assign(k
,LB
); lu_flags
|| value_le(k
,UB
); value_increment(k
,k
)) {
2692 value_assign(context
[pos
],k
);
2693 if ((found
= lexmin(pos
+1, P
->next
, context
)))
2697 value_set_si(context
[pos
],0);
2698 value_clear(LB
); value_clear(UB
); value_clear(k
);
2702 static void print_list(FILE *out
, Value
*z
, const char* brackets
, int len
)
2704 fprintf(out
, "%c", brackets
[0]);
2705 value_print(out
, VALUE_FMT
,z
[0]);
2706 for (int k
= 1; k
< len
; ++k
) {
2708 value_print(out
, VALUE_FMT
,z
[k
]);
2710 fprintf(out
, "%c", brackets
[1]);
2713 static int check_poly_lexmin(const struct check_poly_data
*data
,
2714 int nparam
, Value
*z
,
2715 const struct verify_options
*options
);
2717 struct check_poly_lexmin_data
: public check_poly_data
{
2719 vector
<max_term
*>& maxima
;
2721 check_poly_lexmin_data(Polyhedron
*S
, Value
*z
,
2722 vector
<max_term
*>& maxima
) : S(S
), maxima(maxima
) {
2724 this->check
= &check_poly_lexmin
;
2728 static int check_poly_lexmin(const struct check_poly_data
*data
,
2729 int nparam
, Value
*z
,
2730 const struct verify_options
*options
)
2732 const check_poly_lexmin_data
*lexmin_data
;
2733 lexmin_data
= static_cast<const check_poly_lexmin_data
*>(data
);
2734 Polyhedron
*S
= lexmin_data
->S
;
2735 vector
<max_term
*>& maxima
= lexmin_data
->maxima
;
2737 bool found
= lexmin(1, S
, lexmin_data
->z
);
2739 if (options
->print_all
) {
2741 print_list(stdout
, z
, "()", nparam
);
2744 print_list(stdout
, lexmin_data
->z
+1, "[]", S
->Dimension
-nparam
);
2749 for (int i
= 0; i
< maxima
.size(); ++i
)
2750 if ((min
= maxima
[i
]->eval(z
, options
->barvinok
->MaxRays
)))
2753 int ok
= !(found
^ !!min
);
2755 for (int i
= 0; i
< S
->Dimension
-nparam
; ++i
)
2756 if (value_ne(lexmin_data
->z
[1+i
], min
->p
[i
])) {
2763 fprintf(stderr
, "Error !\n");
2764 fprintf(stderr
, "lexmin");
2765 print_list(stderr
, z
, "()", nparam
);
2766 fprintf(stderr
, " should be ");
2768 print_list(stderr
, lexmin_data
->z
+1, "[]", S
->Dimension
-nparam
);
2769 fprintf(stderr
, " while digging gives ");
2771 print_list(stderr
, min
->p
, "[]", S
->Dimension
-nparam
);
2772 fprintf(stderr
, ".\n");
2774 } else if (options
->print_all
)
2779 for (k
= 1; k
<= S
->Dimension
-nparam
; ++k
)
2780 value_set_si(lexmin_data
->z
[k
], 0);
2785 void verify_results(Polyhedron
*A
, Polyhedron
*C
, vector
<max_term
*>& maxima
,
2786 struct verify_options
*options
)
2789 unsigned nparam
= C
->Dimension
;
2790 unsigned MaxRays
= options
->barvinok
->MaxRays
;
2793 CS
= check_poly_context_scan(A
, &C
, nparam
, options
);
2795 p
= Vector_Alloc(A
->Dimension
+2);
2796 value_set_si(p
->p
[A
->Dimension
+1], 1);
2798 S
= Polyhedron_Scan(A
, C
, MaxRays
& POL_NO_DUAL
? 0 : MaxRays
);
2800 check_poly_init(C
, options
);
2803 if (!(CS
&& emptyQ2(CS
))) {
2804 check_poly_lexmin_data
data(S
, p
->p
, maxima
);
2805 check_poly(CS
, &data
, nparam
, 0, p
->p
+S
->Dimension
-nparam
+1, options
);
2810 if (!options
->print_all
)