1 #include <barvinok/basis_reduction.h>
2 #include <barvinok/options.h>
4 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
6 static void save_alpha(GBR_LP
*lp
, int first
, int n
, GBR_type
*alpha
)
10 for (i
= 0; i
< n
; ++i
)
11 GBR_lp_get_alpha(lp
, first
+i
, &alpha
[i
]);
14 /* This function implements the algorithm described in
15 * "An Implementation of the Generalized Basis Reduction Algorithm
16 * for Integer Programming" of Cook el al. to compute a reduced basis.
17 * We use \epsilon = 1/4.
19 * If options->gbr_only_first is set, the user is only interested
20 * in the first direction. In this case we stop the basis reduction when
21 * - the width in the first direction becomes smaller than 2
23 * - we have moved forward all the way to the last direction
24 * and then back again all the way to the first direction.
26 Matrix
*Polyhedron_Reduced_Basis(Polyhedron
*P
,
27 struct barvinok_options
*options
)
29 int dim
= P
->Dimension
;
31 Matrix
*basis
= Identity(dim
);
33 GBR_type F_old
, alpha
, F_new
;
38 GBR_type
*alpha_buffer
[2];
39 GBR_type
*alpha_saved
;
46 if (P
->Dimension
== 1)
55 b_tmp
= Vector_Alloc(dim
);
57 F
= ALLOCN(GBR_type
, dim
);
58 alpha_buffer
[0] = ALLOCN(GBR_type
, dim
);
59 alpha_buffer
[1] = ALLOCN(GBR_type
, dim
);
60 alpha_saved
= alpha_buffer
[0];
62 for (i
= 0; i
< dim
; ++i
) {
64 GBR_init(alpha_buffer
[0][i
]);
65 GBR_init(alpha_buffer
[1][i
]);
81 GBR_lp_set_obj(lp
, basis
->p
[0], dim
);
82 options
->stats
->gbr_solved_lps
++;
85 GBR_lp_get_obj_val(lp
, &F
[0]);
89 row
= GBR_lp_next_row(lp
);
90 GBR_set(F_new
, F_saved
);
91 GBR_set(alpha
, alpha_saved
[i
]);
93 row
= GBR_lp_add_row(lp
, basis
->p
[i
], dim
);
94 GBR_lp_set_obj(lp
, basis
->p
[i
+1], dim
);
95 options
->stats
->gbr_solved_lps
++;
98 GBR_lp_get_obj_val(lp
, &F_new
);
100 GBR_lp_get_alpha(lp
, row
, &alpha
);
103 save_alpha(lp
, row
-i
, i
, alpha_saved
);
107 GBR_set(F
[i
+1], F_new
);
109 GBR_floor(mu
[0], alpha
);
110 GBR_ceil(mu
[1], alpha
);
112 if (value_eq(mu
[0], mu
[1]))
113 value_assign(tmp
, mu
[0]);
117 for (j
= 0; j
<= 1; ++j
) {
118 value_assign(tmp
, mu
[j
]);
119 Vector_Combine(basis
->p
[i
+1], basis
->p
[i
], b_tmp
->p
, one
, tmp
, dim
);
120 GBR_lp_set_obj(lp
, b_tmp
->p
, dim
);
121 options
->stats
->gbr_solved_lps
++;
122 if (GBR_lp_solve(lp
))
124 GBR_lp_get_obj_val(lp
, &mu_F
[j
]);
126 save_alpha(lp
, row
-i
, i
, alpha_buffer
[j
]);
129 if (GBR_lt(mu_F
[0], mu_F
[1]))
134 value_assign(tmp
, mu
[j
]);
135 GBR_set(F_new
, mu_F
[j
]);
136 alpha_saved
= alpha_buffer
[j
];
138 Vector_Combine(basis
->p
[i
+1], basis
->p
[i
], basis
->p
[i
+1], one
, tmp
, dim
);
140 GBR_set(F_old
, F
[i
]);
143 /* mu_F[0] = 4 * F_new; mu_F[1] = 3 * F_old */
144 GBR_set_ui(mu_F
[0], 4);
145 GBR_mul(mu_F
[0], mu_F
[0], F_new
);
146 GBR_set_ui(mu_F
[1], 3);
147 GBR_mul(mu_F
[1], mu_F
[1], F_old
);
148 if (GBR_lt(mu_F
[0], mu_F
[1])) {
149 Vector_Exchange(basis
->p
[i
], basis
->p
[i
+1], dim
);
152 GBR_set(F_saved
, F_new
);
156 GBR_set(F
[0], F_new
);
157 if (options
->gbr_only_first
&& GBR_lt(F
[0], two
))
161 GBR_lp_add_row(lp
, basis
->p
[i
], dim
);
177 for (i
= 0; i
< dim
; ++i
) {
179 GBR_clear(alpha_buffer
[0][i
]);
180 GBR_clear(alpha_buffer
[1][i
]);
183 free(alpha_buffer
[0]);
184 free(alpha_buffer
[1]);