Skip to content

Commit d7dd70c

Browse files
committed
Now to tighten HighsLp::isKnapsack
1 parent 10839f7 commit d7dd70c

File tree

6 files changed

+45
-44
lines changed

6 files changed

+45
-44
lines changed

highs/lp_data/HighsLp.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ bool HighsLp::isBip() const {
3737
return true;
3838
}
3939

40-
bool HighsLp::isKnapsack(HighsInt& knapsack_rhs) const {
40+
bool HighsLp::isKnapsack(HighsInt& capacity) const {
4141
// Has to kave one constraint
4242
if (this->num_row_ != 1) return false;
4343
// Has to be a binary integer programming problem
@@ -51,9 +51,9 @@ bool HighsLp::isKnapsack(HighsInt& knapsack_rhs) const {
5151
if (constraint_sign * this->a_matrix_.value_[iEl] < 0) return false;
5252
// Problem is knapsack!
5353
//
54-
// Get the RHS: if it is negative, then the problem is infeasible
55-
knapsack_rhs = upper ? this->row_upper_[0] : constraint_sign*this->row_lower_[0];
56-
assert(knapsack_rhs >= 0);
54+
// Get the capacity: if it is negative, then the problem is infeasible
55+
capacity = upper ? this->row_upper_[0] : constraint_sign*this->row_lower_[0];
56+
assert(capacity >= 0);
5757
return true;
5858
}
5959

highs/lp_data/HighsLp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class HighsLp {
6666
bool equalScaling(const HighsLp& lp) const;
6767
bool isMip() const;
6868
bool isBip() const;
69-
bool isKnapsack(HighsInt& knapsack_rhs) const;
69+
bool isKnapsack(HighsInt& capacity) const;
7070
bool hasSemiVariables() const;
7171
bool hasInfiniteCost(const double infinite_cost) const;
7272
bool hasMods() const;

highs/mip/HighsMipSolver.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ void HighsMipSolver::run() {
9090

9191
// Determine whether this is a knapsack problem and, if so, at least
9292
// update the data on knapsack sub-MIPs
93-
HighsInt knapsack_rhs = 0;
94-
if (orig_model_->isKnapsack(knapsack_rhs)) {
93+
HighsInt capacity = 0;
94+
if (orig_model_->isKnapsack(capacity)) {
9595
mipdata_->knapsack_data_.num_problem++;
9696
mipdata_->knapsack_data_.sum_variables += orig_model_->num_col_;
97-
mipdata_->knapsack_data_.sum_rhs += knapsack_rhs;
97+
mipdata_->knapsack_data_.sum_capacity += capacity;
9898
// Solve as a knapsack
9999
HighsStatus call_status = mipdata_->heuristics.solveKnapsack();
100100
assert(call_status == HighsStatus::kOk);
@@ -868,9 +868,9 @@ void HighsMipSolver::cleanupSolve() {
868868
" Knapsack sub-MIPs %d\n", knapsack_data.num_problem);
869869
if (knapsack_data.num_problem > 0)
870870
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
871-
" Mean var count %d\n Mean RHS %d\n",
871+
" Mean var count %d\n Mean capacity %d\n",
872872
int((1.0 * knapsack_data.sum_variables) / knapsack_data.num_problem),
873-
int((1.0 * knapsack_data.sum_rhs) / knapsack_data.num_problem));
873+
int((1.0 * knapsack_data.sum_capacity) / knapsack_data.num_problem));
874874

875875
if (!timeless_log) analysis_.reportMipTimer();
876876

highs/mip/HighsMipSolverData.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,13 +2790,13 @@ void HighsPrimaDualIntegral::initialise() { this->value = -kHighsInf; }
27902790
void HighsKnapsackData::initialise() {
27912791
num_problem = 0;
27922792
sum_variables = 0;
2793-
sum_rhs = 0;
2793+
sum_capacity = 0;
27942794
}
27952795

27962796
void HighsKnapsackData::add(const HighsKnapsackData& knapsack_data) {
27972797
this->num_problem += knapsack_data.num_problem;
27982798
this->sum_variables += knapsack_data.sum_variables;
2799-
this->sum_rhs += knapsack_data.sum_rhs;
2799+
this->sum_capacity += knapsack_data.sum_capacity;
28002800
}
28012801

28022802

highs/mip/HighsMipSolverData.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
struct HighsKnapsackData {
3434
HighsInt num_problem;
3535
int64_t sum_variables;
36-
int64_t sum_rhs;
36+
int64_t sum_capacity;
3737
void initialise();
3838
void add(const HighsKnapsackData& knapsack_data);
3939
};

highs/mip/HighsPrimalHeuristics.cpp

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,31 +1647,31 @@ void HighsPrimalHeuristics::flushStatistics() {
16471647
lp_iterations = 0;
16481648
}
16491649

1650-
double knapsackRecurrence(const std::vector<HighsInt>& weights,
1651-
const std::vector<double>& values,
1652-
const HighsInt num_col,
1650+
double knapsackRecurrence(const std::vector<HighsInt>& weight,
1651+
const std::vector<double>& value,
1652+
const HighsInt num_item,
16531653
const double rhs,
1654-
std::vector<std::vector<double>> &dp,
1655-
std::vector<std::vector<bool>> &use) {
1656-
if (num_col == 0 || rhs == 0)
1654+
std::vector<std::vector<double>> &dp_result,
1655+
std::vector<std::vector<bool>> &use_item) {
1656+
if (num_item == 0 || rhs == 0)
16571657
return 0; // Base case
16581658

1659-
if (dp[num_col][rhs] != -1) return dp[num_col][rhs]; // Check if result is already computed
1659+
if (dp_result[num_item][rhs] != -1) return dp_result[num_item][rhs]; // Check if result is already computed
16601660

16611661
// Exclude the item
1662-
double exclude = knapsackRecurrence(weights, values, num_col-1, rhs, dp, use);
1662+
double exclude = knapsackRecurrence(weight, value, num_item-1, rhs, dp_result, use_item);
16631663

16641664
// Include the item (if it fits in the knapsack)
16651665
double include = 0;
1666-
if (weights[num_col-1] <= rhs)
1667-
include = values[num_col-1] + knapsackRecurrence(weights, values, num_col-1, rhs - weights[num_col-1], dp, use);
1666+
if (weight[num_item-1] <= rhs)
1667+
include = value[num_item-1] + knapsackRecurrence(weight, value, num_item-1, rhs - weight[num_item-1], dp_result, use_item);
16681668

16691669
// Store whether the item is used with this RHS
1670-
use[num_col][rhs] = include > exclude;
1670+
use_item[num_item][rhs] = include > exclude;
16711671
// Store the result
1672-
dp[num_col][rhs] = use[num_col][rhs] ? include : exclude;
1672+
dp_result[num_item][rhs] = use_item[num_item][rhs] ? include : exclude;
16731673

1674-
return dp[num_col][rhs];
1674+
return dp_result[num_item][rhs];
16751675

16761676
}
16771677
HighsStatus HighsPrimalHeuristics::solveKnapsackReturn(const HighsStatus& return_status) {
@@ -1698,57 +1698,58 @@ HighsStatus HighsPrimalHeuristics::solveKnapsackReturn(const HighsStatus& return
16981698
HighsStatus HighsPrimalHeuristics::solveKnapsack() {
16991699
HighsLp lp = *(mipsolver.model_);
17001700
// const HighsLp& lp = mipsolver.mipdata_->model_;
1701-
HighsInt knapsack_rhs_;
1702-
assert(lp.isKnapsack(knapsack_rhs_));
1703-
const HighsInt knapsack_rhs = knapsack_rhs_;
1701+
HighsInt capacity_;
1702+
assert(lp.isKnapsack(capacity_));
1703+
const HighsInt capacity = capacity_;
17041704

17051705
const bool upper = lp.row_upper_[0] < kHighsInf;
17061706
const HighsInt constraint_sign = upper ? 1 : -1;
1707-
if (knapsack_rhs < 0) {
1707+
if (capacity < 0) {
17081708
mipsolver.modelstatus_ = HighsModelStatus::kInfeasible;
17091709
return solveKnapsackReturn(HighsStatus::kOk);
1710-
} else if (knapsack_rhs == 0) {
1710+
} else if (capacity == 0) {
17111711
// Trivial knapsack with zero solution
17121712
mipsolver.solution_.assign(lp.num_col_, 0);
17131713
mipsolver.solution_objective_ = lp.offset_;
17141714
mipsolver.modelstatus_ = HighsModelStatus::kOptimal;
17151715
return solveKnapsackReturn(HighsStatus::kOk);
17161716
}
1717-
// Set up the weightsfor the knapsack solver. They might not all be
1717+
// Set up the weights for the knapsack solver. They might not all be
17181718
// nonzero, so have to scatter into a zeroed vector
1719-
std::vector<HighsInt> weights(lp.num_col_, 0);
1719+
std::vector<HighsInt> weight(lp.num_col_, 0);
17201720
assert(lp.a_matrix_.format_ == MatrixFormat::kColwise);
17211721
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
17221722
for (HighsInt iEl = lp.a_matrix_.start_[iCol]; iEl < lp.a_matrix_.start_[iCol+1]; iEl++)
1723-
weights[iCol] = HighsInt(constraint_sign * lp.a_matrix_.value_[iEl]);
1723+
weight[iCol] = HighsInt(constraint_sign * lp.a_matrix_.value_[iEl]);
17241724
}
17251725
HighsInt sense = HighsInt(lp.sense_);
17261726
// Set up the values for the knapsack solver. Since it solves a
17271727
// maximization problem, have to negate the costs if MIP is a
17281728
// minimization
1729-
std::vector<double> values;
1729+
std::vector<double> value;
17301730
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++)
1731-
values.push_back(-sense * lp.col_cost_[iCol]);
1732-
// Set up the DP array, indicating that no objectives are know
1733-
std::vector<std::vector<double>> dp(lp.num_col_ + 1, std::vector<double>(knapsack_rhs + 1, -1));
1731+
value.push_back(-sense * lp.col_cost_[iCol]);
1732+
// Set up the DP result array, indicating that no objectives are
1733+
// know
1734+
std::vector<std::vector<double>> dp_result(lp.num_col_ + 1, std::vector<double>(capacity + 1, -1));
17341735
// Set up the item use array, indicating that items are not used
1735-
std::vector<std::vector<bool>> use(lp.num_col_ + 1, std::vector<bool>(knapsack_rhs + 1, false));
1736+
std::vector<std::vector<bool>> use_item(lp.num_col_ + 1, std::vector<bool>(capacity + 1, false));
17361737
// Solve the knapsack problem by DP
1737-
double knapsack_optimal_objective_value = knapsackRecurrence(weights, values, lp.num_col_, knapsack_rhs, dp, use);
1738+
double knapsack_optimal_objective_value = knapsackRecurrence(weight, value, lp.num_col_, capacity, dp_result, use_item);
17381739
// Deduce the solution
17391740
std::vector<HighsInt> knapsack_solution(lp.num_col_, 0);
17401741
// Variables are set to 1 if "used", and have to track the RHS of
17411742
// the subproblem after variables are assigned so that the correct
17421743
// entry of use is accessed
1743-
HighsInt knapsack_solution_rhs = knapsack_rhs;
1744+
HighsInt knapsack_solution_rhs = capacity;
17441745
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
1745-
if (use[iCol][knapsack_solution_rhs]) {
1746+
if (use_item[iCol][knapsack_solution_rhs]) {
17461747
knapsack_solution[iCol] = 1;
1747-
knapsack_solution_rhs -= weights[iCol];
1748+
knapsack_solution_rhs -= weight[iCol];
17481749
}
17491750
}
17501751
const double row_violation = std::max(0, -knapsack_solution_rhs);
1751-
const double rel_row_violation = row_violation / (1.0 * knapsack_rhs);
1752+
const double rel_row_violation = row_violation / (1.0 * capacity);
17521753

17531754
if (rel_row_violation > 1e-12) {
17541755
highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kError,

0 commit comments

Comments
 (0)