1414#include " io/HighsIO.h"
1515#include " lp_data/HConst.h"
1616#include " lp_data/HighsLpUtils.h"
17- #include " lp_data/HighsModelUtils.h" // For utilModelStatusToString
17+ #include " lp_data/HighsModelUtils.h" // For utilModelStatusToString
1818#include " mip/HighsCutGeneration.h"
1919#include " mip/HighsDomainChange.h"
2020#include " mip/HighsLpRelaxation.h"
@@ -1649,49 +1649,57 @@ void HighsPrimalHeuristics::flushStatistics() {
16491649}
16501650
16511651double knapsackRecurrence (const HighsInt num_item,
1652- const std::vector<double >& value,
1653- const std::vector<HighsInt>& weight,
1654- const double capacity,
1655- std::vector<std::vector<double >> &dp_result,
1656- std::vector<std::vector<bool >> &use_item) {
1657- if (num_item == 0 || capacity == 0 )
1658- return 0 ; // Base case
1652+ const std::vector<double >& value,
1653+ const std::vector<HighsInt>& weight,
1654+ const double capacity,
1655+ std::vector<std::vector<double >>& dp_result,
1656+ std::vector<std::vector<bool >>& use_item) {
1657+ if (num_item == 0 || capacity == 0 ) return 0 ; // Base case
16591658
1660- if (dp_result[num_item][capacity] != -1 ) return dp_result[num_item][capacity]; // Check if result is already computed
1659+ if (dp_result[num_item][capacity] != -1 )
1660+ return dp_result[num_item]
1661+ [capacity]; // Check if result is already computed
16611662
16621663 // Exclude the item
1663- double exclude = knapsackRecurrence (num_item-1 , value, weight, capacity, dp_result, use_item);
1664+ double exclude = knapsackRecurrence (num_item - 1 , value, weight, capacity,
1665+ dp_result, use_item);
16641666
16651667 // Include the item (if it fits in the knapsack)
16661668 double include = 0 ;
1667- if (weight[num_item-1 ] <= capacity)
1668- include = value[num_item-1 ] + knapsackRecurrence (num_item-1 , value, weight, capacity - weight[num_item-1 ], dp_result, use_item);
1669+ if (weight[num_item - 1 ] <= capacity)
1670+ include = value[num_item - 1 ] +
1671+ knapsackRecurrence (num_item - 1 , value, weight,
1672+ capacity - weight[num_item - 1 ], dp_result,
1673+ use_item);
16691674
16701675 // Store whether the item is used with this capacity
16711676 use_item[num_item][capacity] = include > exclude;
16721677 // Store the result
1673- dp_result[num_item][capacity] = use_item[num_item][capacity] ? include : exclude;
1674-
1675- return dp_result[num_item][capacity];
1678+ dp_result[num_item][capacity] =
1679+ use_item[num_item][capacity] ? include : exclude;
16761680
1681+ return dp_result[num_item][capacity];
16771682}
16781683
16791684HighsModelStatus solveKnapsack (const HighsLogOptions& log_options,
1680- const HighsInt num_item,
1681- const std::vector<double >& value,
1682- const std::vector<HighsInt>& weight,
1683- const HighsInt capacity,
1684- double & solution_objective,
1685- std::vector<double >& solution) {
1685+ const HighsInt num_item,
1686+ const std::vector<double >& value,
1687+ const std::vector<HighsInt>& weight,
1688+ const HighsInt capacity,
1689+ double & solution_objective,
1690+ std::vector<double >& solution) {
16861691 assert (capacity > 0 );
1687-
1692+
16881693 // Set up the DP result array, indicating that no optimal objective
16891694 // values are known
1690- std::vector<std::vector<double >> dp_result (num_item + 1 , std::vector<double >(capacity + 1 , -1 ));
1695+ std::vector<std::vector<double >> dp_result (
1696+ num_item + 1 , std::vector<double >(capacity + 1 , -1 ));
16911697 // Set up the item use array, indicating that items are not used
1692- std::vector<std::vector<bool >> use_item (num_item + 1 , std::vector<bool >(capacity + 1 , false ));
1698+ std::vector<std::vector<bool >> use_item (
1699+ num_item + 1 , std::vector<bool >(capacity + 1 , false ));
16931700
1694- solution_objective = knapsackRecurrence (num_item, value, weight, capacity, dp_result, use_item);
1701+ solution_objective = knapsackRecurrence (num_item, value, weight, capacity,
1702+ dp_result, use_item);
16951703
16961704 // Deduce the solution
16971705 std::vector<HighsInt> knapsack_solution (num_item, 0 );
@@ -1708,15 +1716,17 @@ HighsModelStatus solveKnapsack(const HighsLogOptions& log_options,
17081716 }
17091717 const HighsInt capacity_violation = std::max (0 , -capacity_slack);
17101718 if (capacity_violation > 0 ) {
1711- highsLogUser (log_options, HighsLogType::kError ,
1712- " HighsPrimalHeuristics::solveKnapsack() Capacity violation is (%d)\n " ,
1713- int (capacity_violation));
1714- return HighsModelStatus::kSolveError ;
1719+ highsLogUser (
1720+ log_options, HighsLogType::kError ,
1721+ " HighsPrimalHeuristics::solveKnapsack() Capacity violation is (%d)\n " ,
1722+ int (capacity_violation));
1723+ return HighsModelStatus::kSolveError ;
17151724 }
17161725 return HighsModelStatus::kOptimal ;
17171726}
17181727
1719- HighsStatus HighsPrimalHeuristics::solveMipKnapsackReturn (const HighsStatus& return_status) {
1728+ HighsStatus HighsPrimalHeuristics::solveMipKnapsackReturn (
1729+ const HighsStatus& return_status) {
17201730 const HighsLp& lp = *(mipsolver.model_ );
17211731 std::stringstream ss;
17221732 if (!mipsolver.submip ) {
@@ -1730,24 +1740,28 @@ HighsStatus HighsPrimalHeuristics::solveMipKnapsackReturn(const HighsStatus& ret
17301740 // relate to the problem within the MIP solver. This is a
17311741 // minimization without offset
17321742 HighsInt sense = HighsInt (lp.sense_ );
1733- double mipsolver_objective = sense * mipsolver.solution_objective_ - lp.offset_ ;
1743+ double mipsolver_objective =
1744+ sense * mipsolver.solution_objective_ - lp.offset_ ;
17341745 mipsolver.bound_violation_ = 0 ;
17351746 mipsolver.integrality_violation_ = 0 ;
17361747 mipsolver.row_violation_ = 0 ;
17371748 mipsolver.mipdata_ ->lower_bound = mipsolver_objective;
17381749 mipsolver.mipdata_ ->upper_bound = mipsolver_objective;
17391750 mipsolver.gap_ = 0 ;
17401751 if (!mipsolver.submip )
1741- ss << highsFormatToString (" optimal objective by dynamic programming is %g" ,
1742- mipsolver.solution_objective_ );
1752+ ss << highsFormatToString (
1753+ " optimal objective by dynamic programming is %g" ,
1754+ mipsolver.solution_objective_ );
17431755 } else {
17441756 if (!mipsolver.submip )
1745- ss << highsFormatToString (" model status is %s" ,
1746- utilModelStatusToString (mipsolver.modelstatus_ ).c_str ());
1757+ ss << highsFormatToString (
1758+ " model status is %s" ,
1759+ utilModelStatusToString (mipsolver.modelstatus_ ).c_str ());
17471760 mipsolver.solution_ .clear ();
17481761 }
1749- if (!mipsolver.submip ) highsLogUser (mipsolver.options_mip_ ->log_options , HighsLogType::kInfo ,
1750- " \n %s\n " , ss.str ().c_str ());
1762+ if (!mipsolver.submip )
1763+ highsLogUser (mipsolver.options_mip_ ->log_options , HighsLogType::kInfo ,
1764+ " \n %s\n " , ss.str ().c_str ());
17511765 return return_status;
17521766}
17531767
@@ -1757,13 +1771,14 @@ HighsStatus HighsPrimalHeuristics::solveMipKnapsack() {
17571771 const HighsLogOptions& log_options = mipsolver.options_mip_ ->log_options ;
17581772 HighsInt capacity_;
17591773 assert (lp.isKnapsack (capacity_));
1760-
1774+
17611775 const bool upper = lp.row_upper_ [0 ] < kHighsInf ;
17621776 const HighsInt constraint_sign = upper ? 1 : -1 ;
1763- double double_capacity = upper ? lp.row_upper_ [0 ] : constraint_sign * lp.row_lower_ [0 ];
1777+ double double_capacity =
1778+ upper ? lp.row_upper_ [0 ] : constraint_sign * lp.row_lower_ [0 ];
17641779 const double capacity_margin = 1e-6 ;
1765- const HighsInt capacity = std::floor (double_capacity+ capacity_margin);
1766-
1780+ const HighsInt capacity = std::floor (double_capacity + capacity_margin);
1781+
17671782 if (capacity < 0 ) {
17681783 mipsolver.modelstatus_ = HighsModelStatus::kInfeasible ;
17691784 return solveMipKnapsackReturn (HighsStatus::kOk );
@@ -1779,45 +1794,50 @@ HighsStatus HighsPrimalHeuristics::solveMipKnapsack() {
17791794 std::vector<HighsInt> weight (lp.num_col_ , 0 );
17801795 assert (lp.a_matrix_ .format_ == MatrixFormat::kColwise );
17811796 for (HighsInt iCol = 0 ; iCol < lp.num_col_ ; iCol++) {
1782- for (HighsInt iEl = lp.a_matrix_ .start_ [iCol]; iEl < lp.a_matrix_ .start_ [iCol+1 ]; iEl++)
1797+ for (HighsInt iEl = lp.a_matrix_ .start_ [iCol];
1798+ iEl < lp.a_matrix_ .start_ [iCol + 1 ]; iEl++)
17831799 weight[iCol] = HighsInt (constraint_sign * lp.a_matrix_ .value_ [iEl]);
17841800 }
17851801 HighsInt sense = HighsInt (lp.sense_ );
17861802 // Set up the values for the knapsack solver. Since it solves a
17871803 // maximization problem, have to negate the costs if MIP is a
1788- // minimization
1804+ // minimization
17891805 std::vector<double > value;
17901806 for (HighsInt iCol = 0 ; iCol < lp.num_col_ ; iCol++)
17911807 value.push_back (-sense * lp.col_cost_ [iCol]);
17921808 // Solve the knapsack problem by DP
17931809 double knapsack_optimal_objective_value;
17941810 std::vector<double >& solution = mipsolver.solution_ ;
1795- mipsolver.modelstatus_ = solveKnapsack (log_options,
1796- lp.num_col_ , value, weight, capacity,
1797- knapsack_optimal_objective_value, solution);
1811+ mipsolver.modelstatus_ =
1812+ solveKnapsack (log_options, lp.num_col_ , value, weight, capacity,
1813+ knapsack_optimal_objective_value, solution);
17981814 if (mipsolver.modelstatus_ != HighsModelStatus::kOptimal )
17991815 return solveMipKnapsackReturn (HighsStatus::kError );
18001816
18011817 // Get the objective value corresponding to the original problem
1802- const double solution_objective = lp.offset_ - sense * knapsack_optimal_objective_value;
1818+ const double solution_objective =
1819+ lp.offset_ - sense * knapsack_optimal_objective_value;
18031820
18041821 // Compute the objective directly as a check
18051822 double check_objective = lp.offset_ ;
1806- for (HighsInt iCol = 0 ; iCol < lp.num_col_ ; iCol++)
1823+ for (HighsInt iCol = 0 ; iCol < lp.num_col_ ; iCol++)
18071824 check_objective += solution[iCol] * lp.col_cost_ [iCol];
18081825
1809- double abs_dl_solution_objective = std::fabs (solution_objective - check_objective);
1810- double rel_dl_solution_objective = abs_dl_solution_objective / (1.0 + std::fabs (mipsolver.solution_objective_ ));
1826+ double abs_dl_solution_objective =
1827+ std::fabs (solution_objective - check_objective);
1828+ double rel_dl_solution_objective =
1829+ abs_dl_solution_objective /
1830+ (1.0 + std::fabs (mipsolver.solution_objective_ ));
18111831 if (rel_dl_solution_objective > 1e-12 ) {
18121832 highsLogUser (log_options, HighsLogType::kError ,
1813- " HighsPrimalHeuristics::solveMipKnapsack() Relative optimal objective value mismatch of %g\n " ,
1814- rel_dl_solution_objective);
1815- mipsolver.modelstatus_ = HighsModelStatus::kSolveError ;
1816- return solveMipKnapsackReturn (HighsStatus::kError );
1833+ " HighsPrimalHeuristics::solveMipKnapsack() Relative optimal "
1834+ " objective value mismatch of %g\n " ,
1835+ rel_dl_solution_objective);
1836+ mipsolver.modelstatus_ = HighsModelStatus::kSolveError ;
1837+ return solveMipKnapsackReturn (HighsStatus::kError );
18171838 }
18181839 mipsolver.solution_objective_ = solution_objective;
18191840
18201841 assert (mipsolver.modelstatus_ == HighsModelStatus::kOptimal );
18211842 return solveMipKnapsackReturn (HighsStatus::kOk );
18221843}
1823-
0 commit comments