2 #include <barvinok/basis_reduction.h>
3 #include <barvinok/options.h>
5 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
7 static void save_alpha(GBR_LP
*lp
, int first
, int n
, GBR_type
*alpha
)
11 for (i
= 0; i
< n
; ++i
)
12 GBR_lp_get_alpha(lp
, first
+i
, &alpha
[i
]);
15 /* This function implements the algorithm described in
16 * "An Implementation of the Generalized Basis Reduction Algorithm
17 * for Integer Programming" of Cook el al. to compute a reduced basis.
18 * We use \epsilon = 1/4.
20 * If options->gbr_only_first is set, the user is only interested
21 * in the first direction. In this case we stop the basis reduction when
22 * - the width in the first direction becomes smaller than 2
24 * - we have moved forward all the way to the last direction
25 * and then back again all the way to the first direction.
27 Matrix
*Polyhedron_Reduced_Basis(Polyhedron
*P
,
28 struct barvinok_options
*options
)
30 int dim
= P
->Dimension
;
32 Matrix
*basis
= Identity(dim
);
34 GBR_type F_old
, alpha
, F_new
;
39 GBR_type
*alpha_buffer
[2];
40 GBR_type
*alpha_saved
;
47 if (P
->Dimension
== 1)
56 b_tmp
= Vector_Alloc(dim
);
58 F
= ALLOCN(GBR_type
, dim
);
59 alpha_buffer
[0] = ALLOCN(GBR_type
, dim
);
60 alpha_buffer
[1] = ALLOCN(GBR_type
, dim
);
61 alpha_saved
= alpha_buffer
[0];
63 for (i
= 0; i
< dim
; ++i
) {
65 GBR_init(alpha_buffer
[0][i
]);
66 GBR_init(alpha_buffer
[1][i
]);
82 GBR_lp_set_obj(lp
, basis
->p
[0], dim
);
83 options
->stats
->gbr_solved_lps
++;
86 GBR_lp_get_obj_val(lp
, &F
[0]);
90 row
= GBR_lp_next_row(lp
);
91 GBR_set(F_new
, F_saved
);
92 GBR_set(alpha
, alpha_saved
[i
]);
94 row
= GBR_lp_add_row(lp
, basis
->p
[i
], dim
);
95 GBR_lp_set_obj(lp
, basis
->p
[i
+1], dim
);
96 options
->stats
->gbr_solved_lps
++;
99 GBR_lp_get_obj_val(lp
, &F_new
);
101 GBR_lp_get_alpha(lp
, row
, &alpha
);
104 save_alpha(lp
, row
-i
, i
, alpha_saved
);
108 GBR_set(F
[i
+1], F_new
);
110 GBR_floor(mu
[0], alpha
);
111 GBR_ceil(mu
[1], alpha
);
113 if (value_eq(mu
[0], mu
[1]))
114 value_assign(tmp
, mu
[0]);
118 for (j
= 0; j
<= 1; ++j
) {
119 value_assign(tmp
, mu
[j
]);
120 Vector_Combine(basis
->p
[i
+1], basis
->p
[i
], b_tmp
->p
, one
, tmp
, dim
);
121 GBR_lp_set_obj(lp
, b_tmp
->p
, dim
);
122 options
->stats
->gbr_solved_lps
++;
123 if (GBR_lp_solve(lp
))
125 GBR_lp_get_obj_val(lp
, &mu_F
[j
]);
127 save_alpha(lp
, row
-i
, i
, alpha_buffer
[j
]);
130 if (GBR_lt(mu_F
[0], mu_F
[1]))
135 value_assign(tmp
, mu
[j
]);
136 GBR_set(F_new
, mu_F
[j
]);
137 alpha_saved
= alpha_buffer
[j
];
139 Vector_Combine(basis
->p
[i
+1], basis
->p
[i
], basis
->p
[i
+1], one
, tmp
, dim
);
141 GBR_set(F_old
, F
[i
]);
144 /* mu_F[0] = 4 * F_new; mu_F[1] = 3 * F_old */
145 GBR_set_ui(mu_F
[0], 4);
146 GBR_mul(mu_F
[0], mu_F
[0], F_new
);
147 GBR_set_ui(mu_F
[1], 3);
148 GBR_mul(mu_F
[1], mu_F
[1], F_old
);
149 if (GBR_lt(mu_F
[0], mu_F
[1])) {
150 Vector_Exchange(basis
->p
[i
], basis
->p
[i
+1], dim
);
153 GBR_set(F_saved
, F_new
);
157 GBR_set(F
[0], F_new
);
158 if (options
->gbr_only_first
&& GBR_lt(F
[0], two
))
162 GBR_lp_add_row(lp
, basis
->p
[i
], dim
);
178 for (i
= 0; i
< dim
; ++i
) {
180 GBR_clear(alpha_buffer
[0][i
]);
181 GBR_clear(alpha_buffer
[1][i
]);
184 free(alpha_buffer
[0]);
185 free(alpha_buffer
[1]);