2 #include <bernstein/bernstein.h>
3 #include <barvinok/evalue.h>
4 #include <barvinok/options.h>
5 #include <barvinok/util.h>
6 #include <barvinok/bernstein.h>
12 using namespace GiNaC
;
13 using namespace bernstein
;
14 using namespace barvinok
;
16 #define OPT_VARS (BV_OPT_LAST+1)
18 struct argp_option argp_options
[] = {
19 { "variables", OPT_VARS
, "int", 0,
20 "number of variables over which to maximize" },
21 { "verbose", 'V', 0, 0, },
30 static error_t
parse_opt(int key
, char *arg
, struct argp_state
*state
)
32 struct options
*options
= (struct options
*) state
->input
;
43 options
->nvar
= atoi(arg
);
46 return ARGP_ERR_UNKNOWN
;
52 #define ALLOC(type) (type*)malloc(sizeof(type))
53 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
55 enum token_type
{ TOKEN_UNKNOWN
= 256, TOKEN_VALUE
, TOKEN_IDENT
, TOKEN_GE
};
69 static struct token
*token_new(int line
, int col
)
71 struct token
*tok
= ALLOC(struct token
);
77 void token_free(struct token
*tok
)
79 if (tok
->type
== TOKEN_VALUE
)
80 value_clear(tok
->u
.v
);
81 else if (tok
->type
== TOKEN_IDENT
)
97 struct token
*tokens
[5];
101 static struct stream
* stream_new(FILE *file
)
104 struct stream
*s
= ALLOC(struct stream
);
107 s
->buffer
= (char*)malloc(s
->size
);
113 for (i
= 0; i
< 5; ++i
)
119 static void stream_free(struct stream
*s
)
122 assert(s
->n_token
== 0);
126 static int stream_getc(struct stream
*s
)
145 static void stream_ungetc(struct stream
*s
, int c
)
151 static void stream_push_char(struct stream
*s
, int c
)
153 if (s
->len
>= s
->size
) {
154 s
->size
= (3*s
->size
)/2;
155 s
->buffer
= (char*)realloc(s
->buffer
, s
->size
);
157 s
->buffer
[s
->len
++] = c
;
160 static struct token
*stream_push_token(struct stream
*s
, struct token
*tok
)
162 assert(s
->n_token
< 5);
163 s
->tokens
[s
->n_token
++] = tok
;
166 static struct token
*stream_next_token(struct stream
*s
)
173 return s
->tokens
[--s
->n_token
];
178 while ((c
= stream_getc(s
)) != -1 && isspace(c
))
198 tok
= token_new(line
, col
);
199 tok
->type
= (token_type
)c
;
202 if (c
== '-' || isdigit(c
)) {
203 tok
= token_new(line
, col
);
204 tok
->type
= TOKEN_VALUE
;
205 value_init(tok
->u
.v
);
206 stream_push_char(s
, c
);
207 while ((c
= stream_getc(s
)) != -1 && isdigit(c
))
208 stream_push_char(s
, c
);
211 if (s
->len
== 1 && s
->buffer
[0] == '-')
212 value_set_si(tok
->u
.v
, -1);
214 stream_push_char(s
, '\0');
215 mpz_set_str(tok
->u
.v
, s
->buffer
, 0);
220 tok
= token_new(line
, col
);
221 tok
->type
= TOKEN_IDENT
;
222 stream_push_char(s
, c
);
223 while ((c
= stream_getc(s
)) != -1 && isalpha(c
))
224 stream_push_char(s
, c
);
227 stream_push_char(s
, '\0');
228 tok
->u
.s
= strdup(s
->buffer
);
232 if ((c
= stream_getc(s
)) == '=') {
233 tok
= token_new(line
, col
);
234 tok
->type
= TOKEN_GE
;
241 tok
= token_new(line
, col
);
242 tok
->type
= TOKEN_UNKNOWN
;
246 void stream_error(struct stream
*s
, struct token
*tok
, char *msg
)
248 int line
= tok
? tok
->line
: s
->line
;
249 int col
= tok
? tok
->col
: s
->col
;
250 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
253 fprintf(stderr
, "got '%c'\n", tok
->type
);
260 struct parameter
*next
;
263 struct parameter
*parameter_new(char *name
, int pos
, struct parameter
*next
)
265 struct parameter
*p
= ALLOC(struct parameter
);
266 p
->name
= strdup(name
);
272 static int parameter_pos(struct parameter
**p
, char *s
)
274 int pos
= *p
? (*p
)->pos
+1 : 0;
277 for (q
= *p
; q
; q
= q
->next
) {
278 if (strcmp(q
->name
, s
) == 0)
284 *p
= parameter_new(s
, pos
, *p
);
288 static int optional_power(struct stream
*s
)
292 tok
= stream_next_token(s
);
295 if (tok
->type
!= '^') {
296 stream_push_token(s
, tok
);
300 tok
= stream_next_token(s
);
301 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
302 stream_error(s
, tok
, "expecting exponent");
304 stream_push_token(s
, tok
);
307 pow
= VALUE_TO_INT(tok
->u
.v
);
312 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
);
313 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
);
315 static evalue
*read_fract_like(struct stream
*s
, struct token
*tok
,
316 struct parameter
**p
)
325 if (tok
->type
== '[') {
327 error
= "expecting \"]\"";
329 } else if (tok
->type
== '{') {
331 error
= "expecting \"}\"";
337 arg
= evalue_read_term(s
, p
);
338 tok
= stream_next_token(s
);
339 if (!tok
|| tok
->type
!= next
) {
340 stream_error(s
, tok
, error
);
342 stream_push_token(s
, tok
);
345 pow
= optional_power(s
);
349 e
->x
.p
= new_enode(type
, pow
+2, -1);
350 value_clear(e
->x
.p
->arr
[0].d
);
351 e
->x
.p
->arr
[0] = *arg
;
353 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 1, 1);
355 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 0, 1);
360 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
)
365 tok
= stream_next_token(s
);
369 if (tok
->type
== '(') {
371 e
= evalue_read_term(s
, p
);
372 tok
= stream_next_token(s
);
373 if (!tok
|| tok
->type
!= ')') {
374 stream_error(s
, tok
, "expecting \")\"");
376 stream_push_token(s
, tok
);
379 } else if (tok
->type
== TOKEN_VALUE
) {
382 value_set_si(e
->d
, 1);
384 value_assign(e
->x
.n
, tok
->u
.v
);
386 tok
= stream_next_token(s
);
387 if (tok
&& tok
->type
== '/') {
389 tok
= stream_next_token(s
);
390 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
391 stream_error(s
, tok
, "expecting denominator");
393 stream_push_token(s
, tok
);
396 value_assign(e
->d
, tok
->u
.v
);
399 stream_push_token(s
, tok
);
400 } else if (tok
->type
== TOKEN_IDENT
) {
401 int pos
= parameter_pos(p
, tok
->u
.s
);
402 int pow
= optional_power(s
);
406 e
->x
.p
= new_enode(polynomial
, pow
+1, pos
+1);
407 evalue_set_si(&e
->x
.p
->arr
[pow
], 1, 1);
409 evalue_set_si(&e
->x
.p
->arr
[pow
], 0, 1);
410 } else if (tok
->type
== '[' || tok
->type
== '{')
411 e
= read_fract_like(s
, tok
, p
);
413 tok
= stream_next_token(s
);
414 if (tok
&& tok
->type
== '*') {
417 e2
= evalue_read_factor(s
, p
);
419 stream_error(s
, NULL
, "unexpected EOF");
423 free_evalue_refs(e2
);
426 stream_push_token(s
, tok
);
431 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
)
436 e
= evalue_read_factor(s
, p
);
440 tok
= stream_next_token(s
);
444 if (tok
->type
== '+') {
447 e2
= evalue_read_term(s
, p
);
449 stream_error(s
, NULL
, "unexpected EOF");
453 free_evalue_refs(e2
);
456 stream_push_token(s
, tok
);
464 struct constraint
*next
;
467 struct constraint
*constraint_new()
469 struct constraint
*c
= ALLOC(struct constraint
);
471 c
->v
= Vector_Alloc(16);
476 void constraint_free(struct constraint
*c
)
479 struct constraint
*next
= c
->next
;
486 void constraint_extend(struct constraint
*c
, int pos
)
489 if (pos
< c
->v
->Size
)
492 v
= Vector_Alloc((3*c
->v
->Size
)/2);
493 Vector_Copy(c
->v
->p
, v
->p
, c
->v
->Size
);
498 static int evalue_read_constraint(struct stream
*s
, struct parameter
**p
,
499 struct constraint
**constraints
)
502 struct constraint
*c
= NULL
;
504 while ((tok
= stream_next_token(s
))) {
507 if (tok
->type
== '+')
509 else if (tok
->type
== TOKEN_IDENT
) {
511 c
= constraint_new();
512 pos
= parameter_pos(p
, tok
->u
.s
);
513 constraint_extend(c
, 1+pos
);
514 value_set_si(c
->v
->p
[1+pos
], 1);
516 } else if (tok
->type
== TOKEN_VALUE
) {
518 c
= constraint_new();
519 tok2
= stream_next_token(s
);
520 if (tok2
&& tok2
->type
== TOKEN_IDENT
) {
521 pos
= parameter_pos(p
, tok2
->u
.s
);
522 constraint_extend(c
, 1+pos
);
523 value_assign(c
->v
->p
[1+pos
], tok
->u
.v
);
528 stream_push_token(s
, tok2
);
529 value_assign(c
->v
->p
[0], tok
->u
.v
);
532 } else if (tok
->type
== TOKEN_GE
|| tok
->type
== '=') {
533 int type
= tok
->type
== TOKEN_GE
;
535 tok
= stream_next_token(s
);
536 if (!tok
|| tok
->type
!= TOKEN_VALUE
|| value_notzero_p(tok
->u
.v
)) {
537 stream_error(s
, tok
, "expecting \"0\"");
539 stream_push_token(s
, tok
);
543 c
->next
= *constraints
;
550 stream_push_token(s
, tok
);
552 stream_error(s
, tok
, "unexpected token");
561 static struct constraint
*evalue_read_domain(struct stream
*s
, struct parameter
**p
,
564 struct constraint
*constraints
= NULL
;
568 tok
= stream_next_token(s
);
571 stream_push_token(s
, tok
);
574 while (evalue_read_constraint(s
, p
, &constraints
)) {
575 tok
= stream_next_token(s
);
577 stream_push_token(s
, tok
);
578 /* empty line separates domain from evalue */
579 if (tok
->line
> line
+1)
588 struct constraint
*constraints
;
590 struct section
*next
;
593 static char **extract_parameters(struct parameter
*p
, unsigned *nparam
)
598 *nparam
= p
? p
->pos
+1 : 0;
599 params
= ALLOCN(char *, *nparam
);
600 for (i
= 0; i
< *nparam
; ++i
) {
601 struct parameter
*next
= p
->next
;
602 params
[p
->pos
] = p
->name
;
609 static evalue
*evalue_read_partition(struct stream
*s
, char ***ppp
,
610 unsigned *nparam
, unsigned MaxRays
)
612 struct section
*part
= NULL
;
613 struct constraint
*constraints
;
616 struct parameter
*p
= NULL
;
618 while ((constraints
= evalue_read_domain(s
, &p
, MaxRays
))) {
619 evalue
*e
= evalue_read_term(s
, &p
);
621 stream_error(s
, NULL
, "missing evalue");
624 struct section
*sect
= ALLOC(struct section
);
625 sect
->constraints
= constraints
;
637 *ppp
= extract_parameters(p
, nparam
);
640 e
->x
.p
= new_enode(partition
, 2*m
, *nparam
);
642 for (j
= 0; j
< m
; ++j
) {
644 struct section
*next
= part
->next
;
645 struct constraint
*c
;
646 constraints
= part
->constraints
;
647 for (n
= 0, c
= constraints
; c
; ++n
, c
= c
->next
)
649 M
= Matrix_Alloc(n
, 1+*nparam
+1);
651 struct constraint
*next
= constraints
->next
;
652 Vector_Copy(constraints
->v
->p
+1, M
->p
[n
]+1, *nparam
);
653 if (constraints
->type
)
654 value_set_si(M
->p
[n
][0], 1);
655 value_assign(M
->p
[n
][1+*nparam
], constraints
->v
->p
[0]);
656 constraints
->next
= NULL
;
657 constraint_free(constraints
);
660 D
= Constraints2Polyhedron(M
, MaxRays
);
662 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*j
], D
);
663 value_clear(e
->x
.p
->arr
[2*j
+1].d
);
664 e
->x
.p
->arr
[2*j
+1] = *part
->e
;
673 static evalue
*evalue_read(FILE *in
, char ***ppp
, unsigned *nparam
,
676 struct stream
*s
= stream_new(in
);
679 struct parameter
*p
= NULL
;
681 if (!(tok
= stream_next_token(s
)))
684 if (tok
->type
== TOKEN_VALUE
) {
685 struct token
*tok2
= stream_next_token(s
);
687 stream_push_token(s
, tok2
);
688 stream_push_token(s
, tok
);
689 if (tok2
&& (tok2
->type
== TOKEN_IDENT
|| tok2
->type
== TOKEN_GE
))
690 e
= evalue_read_partition(s
, ppp
, nparam
, MaxRays
);
692 e
= evalue_read_term(s
, &p
);
693 *ppp
= extract_parameters(p
, nparam
);
695 } else if (tok
->type
== TOKEN_IDENT
) {
696 stream_push_token(s
, tok
);
697 e
= evalue_read_partition(s
, ppp
, nparam
, MaxRays
);
703 int main(int argc
, char **argv
)
706 char **all_vars
= NULL
;
708 struct options options
;
709 struct barvinok_options
*bv_options
= barvinok_options_new_with_defaults();
710 static struct argp argp
= { argp_options
, parse_opt
, 0, 0, 0 };
712 piecewise_lst
*pl
= NULL
;
714 argp_parse(&argp
, argc
, argv
, 0, 0, &options
);
716 EP
= evalue_read(stdin
, &all_vars
, &ntotal
, bv_options
->MaxRays
);
720 print_evalue(stderr
, EP
, all_vars
);
722 if (options
.nvar
== -1)
723 options
.nvar
= ntotal
;
725 U
= Universe_Polyhedron(ntotal
- options
.nvar
);
728 params
= constructParameterVector(all_vars
+options
.nvar
, ntotal
-options
.nvar
);
730 pl
= evalue_bernstein_coefficients(NULL
, EP
, U
, params
, bv_options
);
736 free_evalue_refs(EP
);
740 Free_ParamNames(all_vars
, ntotal
);
741 barvinok_options_free(bv_options
);