3 #include <polylib/polylibgmp.h>
5 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
7 static LPX
*init_lp(Polyhedron
*P
)
14 ind
= ALLOCN(int, 1+P
->Dimension
);
15 val
= ALLOCN(double, 1+P
->Dimension
);
16 lp
= lpx_create_prob();
17 lpx_set_obj_dir(lp
, LPX_MAX
);
18 lpx_add_rows(lp
, 2*P
->NbConstraints
);
19 lpx_add_cols(lp
, 2*P
->Dimension
);
20 for (i
= 0; i
< 2; ++i
) {
21 for (j
= 0; j
< P
->NbConstraints
; ++j
) {
22 for (k
= 0, l
= 0; k
< P
->Dimension
; ++k
) {
23 if (value_zero_p(P
->Constraint
[j
][1+k
]))
25 ind
[1+l
] = 1+i
*P
->Dimension
+k
;
26 val
[1+l
] = VALUE_TO_DOUBLE(P
->Constraint
[j
][1+k
]);
29 lpx_set_mat_row(lp
, 1+i
*P
->NbConstraints
+j
, l
, ind
, val
);
30 lpx_set_row_bnds(lp
, 1+i
*P
->NbConstraints
+j
, LPX_LO
,
31 -VALUE_TO_DOUBLE(P
->Constraint
[j
][1+P
->Dimension
]), 0);
33 for (k
= 0, l
= 0; k
< P
->Dimension
; ++k
) {
34 lpx_set_col_bnds(lp
, 1+i
*P
->Dimension
+k
, LPX_FR
, 0, 0);
42 static void set_lp_obj(LPX
*lp
, Value
*row
, int dim
)
45 for (j
= 0; j
< dim
; ++j
) {
46 lpx_set_obj_coef(lp
, 1+j
, VALUE_TO_DOUBLE(row
[j
]));
47 lpx_set_obj_coef(lp
, 1+dim
+j
, -VALUE_TO_DOUBLE(row
[j
]));
51 static int add_lp_row(LPX
*lp
, Value
*row
, int dim
)
54 int nr
= lpx_add_rows(lp
, 1);
58 ind
= ALLOCN(int, 1+2*dim
);
59 val
= ALLOCN(double, 1+2*dim
);
60 for (j
= 0, l
= 0; j
< dim
; ++j
) {
61 if (value_zero_p(row
[j
]))
64 val
[1+l
] = VALUE_TO_DOUBLE(row
[j
]);
66 val
[1+l
+1] = -VALUE_TO_DOUBLE(row
[j
]);
69 lpx_set_mat_row(lp
, nr
, l
, ind
, val
);
70 lpx_set_row_bnds(lp
, nr
, LPX_FX
, 0, 0);
77 static void del_lp_row(LPX
*lp
)
80 rows
[1] = lpx_get_num_rows(lp
);
81 lpx_del_rows(lp
, 1, rows
);
84 static void save_alpha(LPX
*lp
, int first
, int n
, double *alpha
)
88 for (i
= 0; i
< n
; ++i
)
89 alpha
[i
] = -lpx_get_row_dual(lp
, first
+i
);
92 /* This function implements the algorithm described in
93 * "An Implementation of the Generalized Basis Reduction Algorithm
94 * for Integer Programming" of Cook el al. to compute a reduced basis.
95 * We use \epsilon = 1/4.
97 Matrix
*reduced_basis(Polyhedron
*P
)
99 int dim
= P
->Dimension
;
101 Matrix
*basis
= Identity(dim
);
103 double F_old
, alpha
, F_new
;
108 double *alpha_buffer
[2];
113 if (P
->Dimension
== 1)
118 value_set_si(one
, 1);
120 b_tmp
= Vector_Alloc(dim
);
122 F
= ALLOCN(double, dim
);
123 alpha_buffer
[0] = ALLOCN(double, dim
);
124 alpha_buffer
[1] = ALLOCN(double, dim
);
125 alpha_saved
= alpha_buffer
[0];
129 lpx_set_int_parm(lp
, LPX_K_MSGLEV
, 0);
133 set_lp_obj(lp
, basis
->p
[0], dim
);
137 F
[0] = lpx_get_obj_val(lp
);
138 assert(F
[0] > -1e-10);
144 row
= lpx_get_num_rows(lp
)+1;
146 alpha
= alpha_saved
[i
];
148 row
= add_lp_row(lp
, basis
->p
[i
], dim
);
149 set_lp_obj(lp
, basis
->p
[i
+1], dim
);
152 F_new
= lpx_get_obj_val(lp
);
154 alpha
= -lpx_get_row_dual(lp
, row
);
157 save_alpha(lp
, row
-i
, i
, alpha_saved
);
162 assert(F
[i
+1] > -1e-10);
165 mu
[0] = (int)floor(alpha
+1e-10);
166 mu
[1] = (int)ceil(alpha
-1e-10);
169 value_set_si(tmp
, mu
[0]);
174 for (j
= 0; j
<= 1; ++j
) {
175 value_set_si(tmp
, mu
[j
]);
176 Vector_Combine(basis
->p
[i
+1], basis
->p
[i
], b_tmp
->p
, one
, tmp
, dim
);
177 set_lp_obj(lp
, b_tmp
->p
, dim
);
180 mu_F
[j
] = lpx_get_obj_val(lp
);
182 save_alpha(lp
, row
-i
, i
, alpha_buffer
[j
]);
185 if (mu_F
[0] < mu_F
[1])
190 value_set_si(tmp
, mu
[j
]);
192 alpha_saved
= alpha_buffer
[j
];
194 Vector_Combine(basis
->p
[i
+1], basis
->p
[i
], basis
->p
[i
+1], one
, tmp
, dim
);
196 assert(F_new
> -1e-10);
200 if (F_new
< 3*F_old
/4) {
201 Vector_Exchange(basis
->p
[i
], basis
->p
[i
+1], dim
);
210 add_lp_row(lp
, basis
->p
[i
], dim
);
220 free(alpha_buffer
[0]);
221 free(alpha_buffer
[1]);