2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 #include "isl_basis_reduction.h"
15 /* Call callback->add with the current sample value of the tableau "tab".
17 static int add_solution(struct isl_tab
*tab
, struct isl_scan_callback
*callback
)
19 struct isl_vec
*sample
;
23 sample
= isl_tab_get_sample_value(tab
);
27 return callback
->add(callback
, sample
);
30 static int scan_0D(struct isl_basic_set
*bset
,
31 struct isl_scan_callback
*callback
)
33 struct isl_vec
*sample
;
35 sample
= isl_vec_alloc(bset
->ctx
, 1);
36 isl_basic_set_free(bset
);
41 isl_int_set_si(sample
->el
[0], 1);
43 return callback
->add(callback
, sample
);
46 /* Look for all integer points in "bset", which is assumed to be unbounded,
47 * and call callback->add on each of them.
49 * We first compute a reduced basis for the set and then scan
50 * the set in the directions of this basis.
51 * We basically perform a depth first search, where in each level i
52 * we compute the range in the i-th basis vector direction, given
53 * fixed values in the directions of the previous basis vector.
54 * We then add an equality to the tableau fixing the value in the
55 * direction of the current basis vector to each value in the range
56 * in turn and then continue to the next level.
58 * The search is implemented iteratively. "level" identifies the current
59 * basis vector. "init" is true if we want the first value at the current
60 * level and false if we want the next value.
61 * Solutions are added in the leaves of the search tree, i.e., after
62 * we have fixed a value in each direction of the basis.
64 int isl_basic_set_scan(struct isl_basic_set
*bset
,
65 struct isl_scan_callback
*callback
)
68 struct isl_mat
*B
= NULL
;
69 struct isl_tab
*tab
= NULL
;
72 struct isl_tab_undo
**snap
;
75 enum isl_lp_result res
;
80 dim
= isl_basic_set_total_dim(bset
);
82 return scan_0D(bset
, callback
);
84 min
= isl_vec_alloc(bset
->ctx
, dim
);
85 max
= isl_vec_alloc(bset
->ctx
, dim
);
86 snap
= isl_alloc_array(bset
->ctx
, struct isl_tab_undo
*, dim
);
88 if (!min
|| !max
|| !snap
)
91 tab
= isl_tab_from_basic_set(bset
);
95 tab
->basis
= isl_mat_identity(bset
->ctx
, 1 + dim
);
97 tab
= isl_tab_compute_reduced_basis(tab
);
100 B
= isl_mat_copy(tab
->basis
);
110 res
= isl_tab_min(tab
, B
->row
[1 + level
],
111 bset
->ctx
->one
, &min
->el
[level
], NULL
, 0);
112 if (res
== isl_lp_empty
)
114 if (res
== isl_lp_error
|| res
== isl_lp_unbounded
)
116 isl_seq_neg(B
->row
[1 + level
] + 1,
117 B
->row
[1 + level
] + 1, dim
);
118 res
= isl_tab_min(tab
, B
->row
[1 + level
],
119 bset
->ctx
->one
, &max
->el
[level
], NULL
, 0);
120 isl_seq_neg(B
->row
[1 + level
] + 1,
121 B
->row
[1 + level
] + 1, dim
);
122 isl_int_neg(max
->el
[level
], max
->el
[level
]);
123 if (res
== isl_lp_empty
)
125 if (res
== isl_lp_error
|| res
== isl_lp_unbounded
)
127 snap
[level
] = isl_tab_snap(tab
);
129 isl_int_add_ui(min
->el
[level
], min
->el
[level
], 1);
131 if (empty
|| isl_int_gt(min
->el
[level
], max
->el
[level
])) {
135 if (isl_tab_rollback(tab
, snap
[level
]) < 0)
139 isl_int_neg(B
->row
[1 + level
][0], min
->el
[level
]);
140 tab
= isl_tab_add_valid_eq(tab
, B
->row
[1 + level
]);
141 isl_int_set_si(B
->row
[1 + level
][0], 0);
142 if (level
< dim
- 1) {
147 if (add_solution(tab
, callback
) < 0)
150 if (isl_tab_rollback(tab
, snap
[level
]) < 0)
158 isl_basic_set_free(bset
);
166 isl_basic_set_free(bset
);