66#include " catch.hpp"
77#include " io/FilereaderLp.h"
88
9- const bool dev_run = true ; // false;
9+ const bool dev_run = false ;
1010const double inf = kHighsInf ;
1111const double double_equal_tolerance = 1e-5 ;
1212
@@ -954,7 +954,7 @@ TEST_CASE("test-qp-hot-start", "[qpsolver]") {
954954 const std::string filename =
955955 std::string (HIGHS_DIR) + " /check/instances/primal1.mps" ;
956956 REQUIRE (highs.readModel (filename) == HighsStatus::kOk );
957- highs.getBasis ().print (" test-qp-hot-start" );
957+ // highs.getBasis().print("test-qp-hot-start");
958958 required_objective_function_value = -0.035012965733477348 ;
959959 } else if (k == 2 ) {
960960 // Not currently tested
@@ -1150,12 +1150,13 @@ TEST_CASE("rowless-qp", "[qpsolver]") {
11501150
11511151TEST_CASE (" test-qp-atwood" , " [qpsolver]" ) {
11521152 Highs h;
1153- // highs .setOptionValue("output_flag", dev_run);
1153+ h .setOptionValue (" output_flag" , dev_run);
11541154 std::string filename =
11551155 std::string (HIGHS_DIR) + " /check/instances/atwood0.mps" ;
11561156 REQUIRE (h.readModel (filename) == HighsStatus::kOk );
11571157
1158- const double primal_feasibility_tolerance = h.getOptions ().primal_feasibility_tolerance ;
1158+ const double primal_feasibility_tolerance =
1159+ h.getOptions ().primal_feasibility_tolerance ;
11591160
11601161 const double required_objective0 = 4.16347077e-02 ;
11611162 const double required_objective1 = 2.91530651e-02 ;
@@ -1165,15 +1166,28 @@ TEST_CASE("test-qp-atwood", "[qpsolver]") {
11651166 const HighsBasis& basis_ = h.getBasis ();
11661167 REQUIRE (model.lp_ .row_lower_ [1 ] == 0.26 );
11671168
1169+ // After solving QP0, the lower bound on the second constraint is
1170+ // reduced to give QP1, so the optimal solution of QP0 is feasible
1171+ // for QP1. It should be possible to hot start QP1 using the optimal
1172+ // basis of QP0, but that basis has a null space dimension of 1, and
1173+ // the QP solver currently only hot starts from a vertex
1174+ // solution. This has a null space dimension of 0, although any free
1175+ // variables are considered as a special case (see primal1.mps),
1176+ // leading to a positive initial null space.
1177+ //
1178+ // Previously, this test case exposed a bug in hot start of the ASM
1179+ // solver, so it's a useful test case as/when hot start is improved.
1180+
11681181 const bool hot_start = true ;
1169- for (HighsInt k= 0 ; k < 2 ; k++) {
1182+ for (HighsInt k = 0 ; k < 2 ; k++) {
11701183 REQUIRE (h.run () == HighsStatus::kOk );
11711184 HighsSolution solution = h.getSolution ();
11721185 HighsBasis basis = basis_;
11731186
11741187 HighsInt num_basic = 0 ;
11751188 HighsInt num_non_basic = 0 ;
11761189 const HighsLp& lp = model.lp_ ;
1190+ /*
11771191 printf("\nColumns\n");
11781192 for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
11791193 double lower = lp.col_lower_[iCol];
@@ -1182,16 +1196,13 @@ TEST_CASE("test-qp-atwood", "[qpsolver]") {
11821196 double rsdu = std::min(value-lower, upper-value);
11831197 HighsBasisStatus status = basis_.col_status[iCol];
11841198 printf("%2d [%11.4g, %11.4g, %11.4g] %11.4g %s\n",
1185- int (iCol), lower, value, upper, rsdu, h.basisStatusToString (status).c_str ());
1186- if (status == HighsBasisStatus::kBasic ) {
1187- num_basic++;
1188- } else if (status == HighsBasisStatus::kNonbasic ) {
1189- num_non_basic++;
1190- } else {
1191- REQUIRE (rsdu <= primal_feasibility_tolerance);
1199+ int(iCol), lower, value, upper, rsdu,
1200+ h.basisStatusToString(status).c_str()); if (status ==
1201+ HighsBasisStatus::kBasic) { num_basic++; } else if (status ==
1202+ HighsBasisStatus::kNonbasic) { num_non_basic++; } else { REQUIRE(rsdu <=
1203+ primal_feasibility_tolerance);
11921204 }
11931205 }
1194-
11951206 printf("Rows\n");
11961207 for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
11971208 double lower = lp.row_lower_[iRow];
@@ -1200,25 +1211,24 @@ TEST_CASE("test-qp-atwood", "[qpsolver]") {
12001211 double rsdu = std::min(value-lower, upper-value);
12011212 HighsBasisStatus status = basis_.row_status[iRow];
12021213 printf("%2d [%11.4g, %11.4g, %11.4g] %11.4g %s\n",
1203- int (iRow), lower, value, upper, rsdu, h.basisStatusToString (status).c_str ());
1204- if (status == HighsBasisStatus::kBasic ) {
1205- num_basic++;
1206- } else if (status == HighsBasisStatus::kNonbasic ) {
1207- num_non_basic++;
1208- } else {
1209- REQUIRE (rsdu <= primal_feasibility_tolerance);
1214+ int(iRow), lower, value, upper, rsdu,
1215+ h.basisStatusToString(status).c_str()); if (status ==
1216+ HighsBasisStatus::kBasic) { num_basic++; } else if (status ==
1217+ HighsBasisStatus::kNonbasic) { num_non_basic++; } else { REQUIRE(rsdu <=
1218+ primal_feasibility_tolerance);
12101219 }
12111220 }
1212- printf (" QP has %d basic and %d nonbasic variables\n " , int (num_basic), int (num_non_basic));
1213-
1221+ printf("QP has %d basic and %d nonbasic variables\n", int(num_basic),
1222+ int(num_non_basic));
1223+ */
12141224 if (k == 0 ) {
12151225 const double objective0 = h.getInfo ().objective_function_value ;
12161226 REQUIRE (std::fabs (objective0 - required_objective0) < 1e-4 );
12171227 } else {
12181228 const double objective1 = h.getInfo ().objective_function_value ;
12191229 REQUIRE (std::fabs (objective1 - required_objective1) < 1e-4 );
1220- }
1221-
1230+ }
1231+
12221232 double lower = 0.25 ;
12231233 double upper = kHighsInf ;
12241234 h.changeRowBounds (1 , lower, upper);
@@ -1231,6 +1241,6 @@ TEST_CASE("test-qp-atwood", "[qpsolver]") {
12311241 assert (basis_.valid );
12321242 }
12331243 }
1234-
1244+
12351245 h.resetGlobalScheduler (true );
12361246}
0 commit comments