3 #include <barvinok/evalue.h>
4 #include <barvinok/util.h>
5 #include <barvinok/barvinok.h>
8 #include "verif_ehrhart.h"
10 /* The input of this example program is the same as that of testehrhart
11 * in the PolyLib distribution, i.e., a polytope in combined
12 * data and parameter space, a context polytope in parameter space
13 * and (optionally) the names of the parameters.
14 * Both polytopes are in PolyLib notation.
17 struct argp_option argp_options
[] = {
18 { "convert", 'c', 0, 0, "convert fractionals to periodics" },
19 { "floor", 'f', 0, 0, "convert fractionals to floorings" },
21 { "series", 's', 0, 0, "compute rational generating function" },
22 { "explicit", 'e', 0, 0, "convert rgf to psp" },
28 struct barvinok_options
*barvinok
;
35 struct verify_options verify
;
38 static error_t
parse_opt(int key
, char *arg
, struct argp_state
*state
)
40 struct arguments
*options
= (struct arguments
*) state
->input
;
44 state
->child_inputs
[0] = options
->barvinok
;
45 state
->child_inputs
[1] = &options
->verify
;
50 options
->function
= 0;
63 options
->function
= 1;
72 return ARGP_ERR_UNKNOWN
;
77 static int check_series(Polyhedron
*S
, Polyhedron
*CS
, gen_fun
*gf
,
78 int nparam
, int pos
, Value
*z
, int print_all
)
90 /* Computes the coefficient */
91 gf
->coefficient(&z
[S
->Dimension
-nparam
+1], &c
);
93 /* if c=0 we may be out of context. */
94 /* scanning is useless in this case*/
98 value_print(stdout
,VALUE_FMT
,z
[S
->Dimension
-nparam
+1]);
99 for(k
=S
->Dimension
-nparam
+2;k
<=S
->Dimension
;++k
) {
101 value_print(stdout
,VALUE_FMT
,z
[k
]);
104 value_print(stdout
,VALUE_FMT
,c
);
108 /* Manually count the number of points */
109 count_points(1,S
,z
,&tmp
);
111 printf(", count = ");
112 value_print(stdout
, P_VALUE_FMT
, tmp
);
116 if (value_ne(tmp
,c
)) {
119 fprintf(stderr
,"Error !\n");
120 fprintf(stderr
,"EP( ");
121 value_print(stderr
,VALUE_FMT
,z
[S
->Dimension
-nparam
+1]);
122 for (k
=S
->Dimension
-nparam
+2;k
<=S
->Dimension
;++k
) {
123 fprintf(stderr
,", ");
124 value_print(stderr
,VALUE_FMT
,z
[k
]);
126 fprintf(stderr
," ) should be ");
127 value_print(stderr
,VALUE_FMT
,tmp
);
128 fprintf(stderr
,", while EP eval gives ");
129 value_print(stderr
,VALUE_FMT
,c
);
130 fprintf(stderr
,".\n");
131 #ifndef DONT_BREAK_ON_ERROR
132 value_clear(c
); value_clear(tmp
);
135 } else if (print_all
)
139 !(lower_upper_bounds(1+pos
, CS
, &z
[S
->Dimension
-nparam
], &LB
, &UB
));
141 for (value_assign(tmp
,LB
); value_le(tmp
,UB
); value_increment(tmp
,tmp
)) {
143 k
= VALUE_TO_INT(tmp
);
144 if(!pos
&& !(k
%st
)) {
149 value_assign(z
[pos
+S
->Dimension
-nparam
+1],tmp
);
150 if (!check_series(S
, CS
->next
, gf
, nparam
, pos
+1, z
, print_all
)) {
151 value_clear(c
); value_clear(tmp
);
157 value_set_si(z
[pos
+S
->Dimension
-nparam
+1],0);
167 static int verify(Polyhedron
*P
, Polyhedron
**C
, Enumeration
*en
, gen_fun
*gf
,
170 Polyhedron
*CC
, *PP
, *CS
, *S
, *U
;
175 /******* Compute true context *******/
176 CC
= align_context(*C
, P
->Dimension
, options
->barvinok
->MaxRays
);
177 PP
= DomainIntersection(P
, CC
, options
->barvinok
->MaxRays
);
179 C1
= Matrix_Alloc((*C
)->Dimension
+1, P
->Dimension
+1);
181 for (int i
= 0; i
< C1
->NbRows
; i
++)
182 for (int j
= 0; j
< C1
->NbColumns
; j
++)
183 if (i
== j
-P
->Dimension
+(*C
)->Dimension
)
184 value_set_si(C1
->p
[i
][j
], 1);
186 value_set_si(C1
->p
[i
][j
], 0);
187 CC
= Polyhedron_Image(PP
, C1
, options
->barvinok
->MaxRays
);
193 /* Intersect context with range */
194 if ((*C
)->Dimension
> 0) {
195 MM
= Matrix_Alloc(2*(*C
)->Dimension
, (*C
)->Dimension
+2);
196 for (int i
= 0; i
< (*C
)->Dimension
; ++i
) {
197 value_set_si(MM
->p
[2*i
][0], 1);
198 value_set_si(MM
->p
[2*i
][1+i
], 1);
199 value_set_si(MM
->p
[2*i
][1+(*C
)->Dimension
], -options
->verify
.m
);
200 value_set_si(MM
->p
[2*i
+1][0], 1);
201 value_set_si(MM
->p
[2*i
+1][1+i
], -1);
202 value_set_si(MM
->p
[2*i
+1][1+(*C
)->Dimension
], options
->verify
.M
);
204 CC
= AddConstraints(MM
->p
[0], 2*(*C
)->Dimension
, *C
,
205 options
->barvinok
->MaxRays
);
206 U
= Universe_Polyhedron(0);
207 CS
= Polyhedron_Scan(CC
, U
, options
->barvinok
->MaxRays
);
214 p
= Vector_Alloc(P
->Dimension
+2);
215 value_set_si(p
->p
[P
->Dimension
+1], 1);
217 /* S = scanning list of polyhedra */
218 S
= Polyhedron_Scan(P
, *C
, options
->barvinok
->MaxRays
);
220 if (!options
->verify
.print_all
)
221 if ((*C
)->Dimension
> 0) {
222 int d
= options
->verify
.M
- options
->verify
.m
;
227 for (int i
= options
->verify
.m
; i
<= options
->verify
.M
; i
+= st
)
233 /******* CHECK NOW *********/
235 if (!options
->series
|| options
->function
) {
236 if (!check_poly(S
, CS
, en
, (*C
)->Dimension
, 0, p
->p
,
237 options
->verify
.print_all
))
240 if (!check_series(S
, CS
, gf
, (*C
)->Dimension
, 0, p
->p
,
241 options
->verify
.print_all
))
248 fprintf(stderr
,"Check failed !\n");
250 if (!options
->verify
.print_all
)
260 int main(int argc
, char **argv
)
265 Enumeration
*en
= NULL
;
268 int print_solution
= 1;
270 struct arguments options
;
271 static struct argp_child argp_children
[] = {
272 { &barvinok_argp
, 0, 0, 0 },
273 { &verify_argp
, 0, "verification", 1 },
276 static struct argp argp
= { argp_options
, parse_opt
, 0, 0, argp_children
};
277 struct barvinok_options
*bv_options
= barvinok_options_new_with_defaults();
279 options
.barvinok
= bv_options
;
280 argp_parse(&argp
, argc
, argv
, 0, 0, &options
);
283 A
= Constraints2Polyhedron(M
, bv_options
->MaxRays
);
286 C
= Constraints2Polyhedron(M
, bv_options
->MaxRays
);
288 param_name
= Read_ParamNames(stdin
, C
->Dimension
);
290 if (options
.verify
.verify
) {
291 verify_options_set_range(&options
.verify
, A
);
292 if (!options
.verbose
)
296 if (print_solution
) {
297 Polyhedron_Print(stdout
, P_VALUE_FMT
, A
);
298 Polyhedron_Print(stdout
, P_VALUE_FMT
, C
);
301 if (options
.series
) {
302 gf
= barvinok_series_with_options(A
, C
, bv_options
);
303 if (print_solution
) {
304 gf
->print(std::cout
, C
->Dimension
, param_name
);
307 if (options
.function
) {
310 print_evalue(stdout
, EP
, param_name
);
313 EP
= barvinok_enumerate_with_options(A
, C
, bv_options
);
315 print_evalue(stdout
, EP
, param_name
);
317 printf("\nSize: %d\n", evalue_size(EP
));
319 fprintf(stderr
, "WARNING: floor conversion not supported\n");
320 evalue_frac2floor2(EP
, 0);
321 print_evalue(stdout
, EP
, param_name
);
322 } else if (options
.convert
) {
323 evalue_mod2table(EP
, C
->Dimension
);
324 print_evalue(stdout
, EP
, param_name
);
326 printf("\nSize: %d\n", evalue_size(EP
));
330 if (options
.verify
.verify
) {
332 en
= partition2enumeration(EP
);
335 result
= verify(A
, &C
, en
, gf
, &options
);
339 Enumeration_Free(en
);
343 free_evalue_refs(EP
);
347 Free_ParamNames(param_name
, C
->Dimension
);