4 #include <barvinok/options.h>
5 #include <barvinok/util.h>
8 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
10 #define EMPTY_DOMAIN -2
12 static glp_prob
*solve_lp(int dir
, Matrix
*C
, Value
*f
, Value denom
)
19 unsigned dim
= C
->NbColumns
-2;
21 ind
= ALLOCN(int, 1+dim
);
22 val
= ALLOCN(double, 1+dim
);
23 lp
= glp_create_prob();
24 glp_set_obj_dir(lp
, dir
);
25 glp_add_rows(lp
, C
->NbRows
);
26 glp_add_cols(lp
, dim
);
28 for (j
= 0; j
< C
->NbRows
; ++j
) {
29 int type
= value_zero_p(C
->p
[j
][0]) ? GLP_FX
: GLP_LO
;
30 for (k
= 0, l
= 0; k
< dim
; ++k
) {
31 if (value_zero_p(C
->p
[j
][1+k
]))
34 val
[1+l
] = VALUE_TO_DOUBLE(C
->p
[j
][1+k
]);
37 glp_set_mat_row(lp
, 1+j
, l
, ind
, val
);
38 glp_set_row_bnds(lp
, 1+j
, type
,
39 -VALUE_TO_DOUBLE(C
->p
[j
][1+dim
]), 0);
41 for (k
= 0, l
= 0; k
< dim
; ++k
) {
42 glp_set_col_bnds(lp
, 1+k
, GLP_FR
, 0, 0);
47 /* objective function */
48 for (j
= 0; j
< dim
; ++j
)
49 glp_set_obj_coef(lp
, 1+j
, VALUE_TO_DOUBLE(f
[j
]) /
50 VALUE_TO_DOUBLE(denom
));
51 glp_set_obj_coef(lp
, 0, VALUE_TO_DOUBLE(f
[dim
]) /
52 VALUE_TO_DOUBLE(denom
));
56 parm
.msg_lev
= GLP_MSG_OFF
;
57 glp_simplex(lp
, &parm
);
62 static enum lp_result
constraints_affine_minmax(int dir
, Matrix
*C
,
63 Value
*f
, Value denom
, Value
*opt
)
65 enum lp_result res
= lp_ok
;
66 glp_prob
*lp
= solve_lp(dir
, C
, f
, denom
);
68 switch (glp_get_status(lp
)) {
71 value_set_si(*opt
, (int)ceil(glp_get_obj_val(lp
)-1e-10));
73 value_set_si(*opt
, (int)floor(glp_get_obj_val(lp
)+1e-10));
88 static int constraints_affine_minmax_sign(int dir
, Matrix
*C
, Matrix
*T
,
94 unsigned dim
= C
->NbColumns
-2;
95 assert(dim
== T
->NbColumns
-1);
96 assert(T
->NbRows
== 2);
98 lp
= solve_lp(dir
, C
, T
->p
[0], T
->p
[1][dim
]);
99 switch (glp_get_status(lp
)) {
101 opt
= glp_get_obj_val(lp
);
103 sign
= opt
< 0 ? -1 : opt
> 0 ? 1 : 0;
105 if (opt
< -0.5/VALUE_TO_DOUBLE(T
->p
[1][dim
]))
107 else if (opt
> 0.5/VALUE_TO_DOUBLE(T
->p
[1][dim
]))
129 enum order_sign
glpk_polyhedron_affine_sign_0D(Polyhedron
*D
, Matrix
*T
)
134 POL_ENSURE_VERTICES(D
);
137 return order_undefined
;
139 sgn
= value_sign(T
->p
[0][0]);
141 return sgn
< 0 ? order_lt
: sgn
== 0 ? order_eq
: order_gt
;
144 enum order_sign
glpk_polyhedron_affine_sign(Polyhedron
*D
, Matrix
*T
,
145 struct barvinok_options
*options
)
147 int rational
= !POL_ISSET(options
->MaxRays
, POL_INTEGER
);
151 return order_undefined
;
153 if (D
->Dimension
== 0)
154 return glpk_polyhedron_affine_sign_0D(D
, T
);
156 Polyhedron_Matrix_View(D
, &M
, D
->NbConstraints
);
157 int min
= constraints_affine_minmax_sign(GLP_MIN
, &M
, T
, rational
);
158 if (min
== EMPTY_DOMAIN
)
159 return order_undefined
;
162 int max
= constraints_affine_minmax_sign(GLP_MAX
, &M
, T
, rational
);
163 assert(max
!= EMPTY_DOMAIN
);
172 return order_unknown
;
175 enum lp_result
glpk_constraints_opt(Matrix
*C
, Value
*obj
, Value denom
,
176 enum lp_dir dir
, Value
*opt
)
178 int glpk_dir
= dir
== lp_min
? GLP_MIN
: GLP_MAX
;
179 return constraints_affine_minmax(glpk_dir
, C
, obj
, denom
, opt
);