Skip to content

Commit 0a407c7

Browse files
committed
Improve LP scaling
1 parent 29bf82b commit 0a407c7

File tree

8 files changed

+71
-90
lines changed

8 files changed

+71
-90
lines changed

include/packingsolver/algorithms/common.hpp

+14
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,20 @@ inline bool equal(double v1, double v2)
6060
return std::abs(v1 - v2) <= 1e-9 * (std::max)((std::max)(1e-5, std::abs(v1)), std::abs(v2));
6161
}
6262

63+
template<typename T>
64+
double largest_power_of_two_lesser_or_equal(T value)
65+
{
66+
double res = 1;
67+
if (res > value) {
68+
while (res > value)
69+
res /= 2;
70+
} else {
71+
while (res * 2 < value)
72+
res *= 2;
73+
}
74+
return res;
75+
}
76+
6377

6478
enum class OptimizationMode
6579
{

src/algorithms/column_generation.hpp

+25-41
Original file line numberDiff line numberDiff line change
@@ -98,30 +98,6 @@ columngenerationsolver::Model get_model(
9898
{
9999
columngenerationsolver::Model model;
100100

101-
Profit maximum_bin_type_cost = 0;
102-
for (BinTypeId bin_type_id = 0;
103-
bin_type_id < instance.number_of_bin_types();
104-
++bin_type_id) {
105-
if (maximum_bin_type_cost < instance.bin_type(bin_type_id).cost)
106-
maximum_bin_type_cost = instance.bin_type(bin_type_id).cost;
107-
}
108-
109-
ItemPos maximum_item_type_demand = 0;
110-
for (ItemTypeId item_type_id = 0;
111-
item_type_id < instance.number_of_item_types();
112-
++item_type_id) {
113-
if (maximum_item_type_demand < instance.item_type(item_type_id).copies)
114-
maximum_item_type_demand = instance.item_type(item_type_id).copies;
115-
}
116-
117-
Profit maximum_item_profit = 0;
118-
for (ItemTypeId item_type_id = 0;
119-
item_type_id < instance.number_of_item_types();
120-
++item_type_id) {
121-
if (maximum_item_profit < instance.item_type(item_type_id).profit)
122-
maximum_item_profit = instance.item_type(item_type_id).profit;
123-
}
124-
125101
if (instance.objective() == Objective::VariableSizedBinPacking
126102
|| instance.objective() == Objective::BinPacking) {
127103
model.objective_sense = optimizationtools::ObjectiveDirection::Minimize;
@@ -196,33 +172,36 @@ std::vector<std::shared_ptr<const Column>> ColumnGenerationPricingSolver<Instanc
196172
}
197173

198174
template <typename Solution>
199-
std::vector<std::shared_ptr<const Column>> solution2column(
175+
std::vector<std::shared_ptr<const Column>> solution_to_columns(
200176
const Solution& solution)
201177
{
178+
const auto& instance = solution.instance();
179+
double multiplier_cost = largest_power_of_two_lesser_or_equal(instance.largest_bin_cost());
180+
double multiplier_profit = largest_power_of_two_lesser_or_equal(instance.largest_item_profit());
202181
std::vector<std::shared_ptr<const Column>> columns;
203182
for (BinPos bin_pos = 0;
204183
bin_pos < solution.number_of_different_bins();
205184
++bin_pos) {
206185
BinTypeId bin_type_id = solution.bin(bin_pos).bin_type_id;
207-
Solution extra_solution(solution.instance());
186+
Solution extra_solution(instance);
208187
extra_solution.append(solution, bin_pos, 1);
209188
Column column;
210-
if (solution.instance().objective() == Objective::VariableSizedBinPacking
211-
|| solution.instance().objective() == Objective::BinPacking) {
212-
column.objective_coefficient = extra_solution.cost();
213-
} else if (solution.instance().objective() == Objective::Knapsack) {
214-
column.objective_coefficient = extra_solution.profit();
189+
if (instance.objective() == Objective::VariableSizedBinPacking
190+
|| instance.objective() == Objective::BinPacking) {
191+
column.objective_coefficient = extra_solution.cost() / multiplier_cost;
192+
} else if (instance.objective() == Objective::Knapsack) {
193+
column.objective_coefficient = extra_solution.profit() / multiplier_profit;
215194
}
216195
columngenerationsolver::LinearTerm element;
217196
element.row = bin_type_id;
218197
element.coefficient = 1;
219198
column.elements.push_back(element);
220199
for (ItemTypeId item_type_id = 0;
221-
item_type_id < solution.instance().number_of_item_types();
200+
item_type_id < instance.number_of_item_types();
222201
++item_type_id) {
223202
if (extra_solution.item_copies(item_type_id) > 0) {
224203
columngenerationsolver::LinearTerm element;
225-
element.row = solution.instance().number_of_bin_types() + item_type_id;
204+
element.row = instance.number_of_bin_types() + item_type_id;
226205
element.coefficient = extra_solution.item_copies(item_type_id);
227206
column.elements.push_back(element);
228207
}
@@ -237,6 +216,9 @@ template <typename Instance, typename InstanceBuilder, typename Solution>
237216
PricingOutput ColumnGenerationPricingSolver<Instance, InstanceBuilder, Solution>::solve_pricing(
238217
const std::vector<Value>& duals)
239218
{
219+
double multiplier_cost = largest_power_of_two_lesser_or_equal(instance_.largest_bin_cost());
220+
double multiplier_profit = largest_power_of_two_lesser_or_equal(instance_.largest_item_profit());
221+
240222
//std::cout << "solve_pricing" << std::endl;
241223
PricingOutput output;
242224
Value reduced_cost_bound = 0.0;
@@ -257,7 +239,8 @@ PricingOutput ColumnGenerationPricingSolver<Instance, InstanceBuilder, Solution>
257239
for (ItemTypeId item_type_id = 0;
258240
item_type_id < instance_.number_of_item_types();
259241
++item_type_id) {
260-
ItemPos copies = instance_.item_type(item_type_id).copies - filled_demands_[item_type_id];
242+
const auto& item_type = instance_.item_type(item_type_id);
243+
ItemPos copies = item_type.copies - filled_demands_[item_type_id];
261244
if (copies == 0)
262245
continue;
263246

@@ -266,15 +249,16 @@ PricingOutput ColumnGenerationPricingSolver<Instance, InstanceBuilder, Solution>
266249
|| instance_.objective() == Objective::BinPacking) {
267250
profit = duals[instance_.number_of_bin_types() + item_type_id];
268251
} else if (instance_.objective() == Objective::Knapsack) {
269-
profit = instance_.item_type(item_type_id).profit
270-
- duals[instance_.number_of_bin_types() + item_type_id];
252+
profit = item_type.profit
253+
- duals[instance_.number_of_bin_types() + item_type_id]
254+
* multiplier_profit;
271255
}
272256

273257
//std::cout << "j " << j << " profit " << profit << std::endl;
274258
if (profit <= 0)
275259
continue;
276260
kp_instance_builder.add_item_type(
277-
instance_.item_type(item_type_id),
261+
item_type,
278262
profit,
279263
copies);
280264
kp2vbpp.push_back(item_type_id);
@@ -304,9 +288,9 @@ PricingOutput ColumnGenerationPricingSolver<Instance, InstanceBuilder, Solution>
304288

305289
if (instance_.objective() == Objective::VariableSizedBinPacking
306290
|| instance_.objective() == Objective::BinPacking) {
307-
column.objective_coefficient = extra_solution.cost();
291+
column.objective_coefficient = extra_solution.cost() / multiplier_cost;
308292
} else if (instance_.objective() == Objective::Knapsack) {
309-
column.objective_coefficient = extra_solution.profit();
293+
column.objective_coefficient = extra_solution.profit() / multiplier_profit;
310294
}
311295

312296
columngenerationsolver::LinearTerm element;
@@ -332,11 +316,11 @@ PricingOutput ColumnGenerationPricingSolver<Instance, InstanceBuilder, Solution>
332316
|| instance_.objective() == Objective::BinPacking) {
333317
reduced_cost_bound = (std::min)(
334318
reduced_cost_bound,
335-
bin_type.cost - duals[bin_type_id] - kp_output.knapsack_bound);
319+
bin_type.cost / multiplier_cost - duals[bin_type_id] - kp_output.knapsack_bound);
336320
} else if (instance_.objective() == Objective::Knapsack) {
337321
reduced_cost_bound = (std::max)(
338322
reduced_cost_bound,
339-
kp_output.knapsack_bound - duals[bin_type_id]);
323+
kp_output.knapsack_bound / multiplier_profit - duals[bin_type_id]);
340324
}
341325
}
342326
}

src/irregular/optimize.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,7 @@ void optimize_column_generation(
405405
cgslds_parameters.verbosity_level = 0;
406406
cgslds_parameters.timer = parameters.timer;
407407
cgslds_parameters.internal_diving = 1;
408-
cgslds_parameters.dummy_column_objective_coefficient = (std::max)(
409-
2 * instance.largest_bin_cost() * instance.largest_item_copies(),
410-
(Profit)1);
408+
cgslds_parameters.dummy_column_objective_coefficient = 2 * (double)instance.largest_item_copies();
411409
if (parameters.optimization_mode != OptimizationMode::Anytime)
412410
cgslds_parameters.automatic_stop = true;
413411
cgslds_parameters.new_solution_callback = [&instance, &algorithm_formatter](

src/onedimensional/optimize.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,7 @@ void optimize_column_generation(
377377
if (parameters.optimization_mode == OptimizationMode::Anytime)
378378
cgslds_parameters.timer.add_end_boolean(&algorithm_formatter.end_boolean());
379379
cgslds_parameters.internal_diving = 0;
380-
cgslds_parameters.dummy_column_objective_coefficient = (std::max)(
381-
2 * instance.largest_bin_cost() * instance.largest_item_copies(),
382-
(Profit)1);
380+
cgslds_parameters.dummy_column_objective_coefficient = 2 * (double)instance.largest_item_copies();
383381
if (parameters.optimization_mode != OptimizationMode::Anytime)
384382
cgslds_parameters.automatic_stop = true;
385383
cgslds_parameters.new_solution_callback = [&instance, &algorithm_formatter](

src/rectangle/benders_decomposition.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ BendersDecompositionOutput packingsolver::rectangle::benders_decomposition(
1515
{
1616
//std::cout << "benders_decomposition..." << std::endl;
1717
const BinType& bin_type = instance.bin_type(0);
18+
double multiplier_area = largest_power_of_two_lesser_or_equal(bin_type.area());
19+
double multiplier_profit = largest_power_of_two_lesser_or_equal(instance.largest_item_profit());
1820

1921
BendersDecompositionOutput output(instance);
2022
AlgorithmFormatter algorithm_formatter(instance, parameters, output);
@@ -96,7 +98,7 @@ BendersDecompositionOutput packingsolver::rectangle::benders_decomposition(
9698
column_lower_bounds.push_back(0);
9799
column_upper_bounds.push_back(1);
98100
column_types.push_back(1);
99-
objective.push_back(item_type.profit / highest_profit);
101+
objective.push_back(item_type.profit / multiplier_profit);
100102
}
101103
}
102104
// Set objective sense.
@@ -121,14 +123,14 @@ BendersDecompositionOutput packingsolver::rectangle::benders_decomposition(
121123
for (ItemPos copy = 0;
122124
copy < item_copies[item_type_id];
123125
++copy) {
124-
a_value.push_back((double)item_type.area() / bin_type.area());
126+
a_value.push_back((double)item_type.area() / multiplier_area);
125127
a_index.push_back(x[item_type_id][copy]);
126128
number_of_elements_in_rows.back()++;
127129
}
128130
}
129131
// Add row bounds
130132
row_lower_bounds.push_back(0);
131-
row_upper_bounds.push_back(1);
133+
row_upper_bounds.push_back((double)bin_type.area() / multiplier_area);
132134
}
133135

134136
// Constraints: dominated copies.

src/rectangle/optimize.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,7 @@ void optimize_column_generation(
334334
if (parameters.optimization_mode == OptimizationMode::Anytime)
335335
cgslds_parameters.timer.add_end_boolean(&algorithm_formatter.end_boolean());
336336
cgslds_parameters.internal_diving = 1;
337-
cgslds_parameters.dummy_column_objective_coefficient = (std::max)(
338-
2 * instance.largest_bin_cost() * instance.largest_item_copies(),
339-
(Profit)1);
337+
cgslds_parameters.dummy_column_objective_coefficient = 2 * (double)instance.largest_item_copies();
340338
if (parameters.optimization_mode != OptimizationMode::Anytime)
341339
cgslds_parameters.automatic_stop = true;
342340
cgslds_parameters.new_solution_callback = [&instance, &algorithm_formatter](

0 commit comments

Comments
 (0)