@@ -90,9 +90,9 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {
9090 if (dev_run) printf (" Num nodes = %d\n " , int (scratch_num_nodes));
9191
9292 std::string solution_file = test_name + model + " .sol" ;
93- if (dev_run) return_status = highs.writeSolution (" " );
94- return_status = highs. writeSolution (solution_file) ;
95- REQUIRE (return_status == HighsStatus::kOk );
93+ if (dev_run) REQUIRE ( highs.writeSolution (" " ) == HighsStatus:: kOk );
94+ ;
95+ REQUIRE (highs. writeSolution (solution_file) == HighsStatus::kOk );
9696
9797 highs.clear ();
9898
@@ -459,6 +459,118 @@ TEST_CASE("read-miplib-solution", "[highs_check_solution]") {
459459 h.resetGlobalScheduler (true );
460460}
461461
462+ TEST_CASE (" read-lp-file-solution" , " [highs_check_solution]" ) {
463+ const std::string test_name = Catch::getResultCapture ().getCurrentTestName ();
464+ const std::string model_file_name = test_name + " .lp" ;
465+ const std::string solution_file_name = test_name + " .sol" ;
466+ const bool with_names = false ;
467+ HighsLp lp;
468+ lp.num_col_ = 3 ;
469+ lp.num_row_ = 2 ;
470+ lp.col_cost_ = {0 , 1 , 1 };
471+ lp.col_lower_ = {0 , 10 , 0 };
472+ lp.col_upper_ = {kHighsInf , kHighsInf , kHighsInf };
473+ if (with_names) lp.col_names_ = {" x" , " y" , " z" };
474+ lp.row_lower_ = {1 , -kHighsInf };
475+ lp.row_upper_ = {kHighsInf , 2 };
476+ if (with_names) lp.row_names_ = {" r-lo" , " r-up" };
477+ lp.a_matrix_ .start_ = {0 , 2 , 2 , 4 };
478+ lp.a_matrix_ .index_ = {0 , 1 , 0 , 1 };
479+ lp.a_matrix_ .value_ = {1 , 1 , 1 , 1 };
480+ lp.integrality_ = {HighsVarType::kContinuous , HighsVarType::kContinuous ,
481+ HighsVarType::kInteger };
482+ Highs h;
483+ h.setOptionValue (" output_flag" , dev_run);
484+ REQUIRE (h.passModel (lp) == HighsStatus::kOk );
485+ h.run ();
486+ h.writeModel (model_file_name);
487+ h.writeSolution (solution_file_name);
488+
489+ h.readModel (model_file_name);
490+ h.writeModel (" " );
491+ h.readSolution (solution_file_name);
492+ h.run ();
493+
494+ std::remove (model_file_name.c_str ());
495+ std::remove (solution_file_name.c_str ());
496+
497+ h.resetGlobalScheduler (true );
498+ }
499+
500+ TEST_CASE (" read-lp-file-basis" , " [highs_check_solution]" ) {
501+ const std::string test_name = Catch::getResultCapture ().getCurrentTestName ();
502+ const std::string model_file_name = test_name + " .lp" ;
503+ const std::string basis_file_name = test_name + " .bas" ;
504+ const bool with_names = false ;
505+ HighsLp lp;
506+ lp.num_col_ = 3 ;
507+ lp.num_row_ = 2 ;
508+ lp.col_cost_ = {0 , 1 , 1 };
509+ lp.col_lower_ = {0 , 10 , 0 };
510+ lp.col_upper_ = {kHighsInf , kHighsInf , kHighsInf };
511+ if (with_names) lp.col_names_ = {" x" , " y" , " z" };
512+ lp.row_lower_ = {1 , -kHighsInf };
513+ lp.row_upper_ = {kHighsInf , 2 };
514+ if (with_names) lp.row_names_ = {" r-lo" , " r-up" };
515+ lp.a_matrix_ .start_ = {0 , 2 , 2 , 4 };
516+ lp.a_matrix_ .index_ = {0 , 1 , 0 , 1 };
517+ lp.a_matrix_ .value_ = {1 , 1 , 1 , 1 };
518+ Highs h;
519+ h.setOptionValue (" output_flag" , dev_run);
520+ REQUIRE (h.passModel (lp) == HighsStatus::kOk );
521+ h.run ();
522+ // Optimally x - basic; y - lower; z - lower
523+ h.writeModel (model_file_name);
524+ h.writeSolution (" " , 1 );
525+ h.writeBasis (" " );
526+ h.writeBasis (basis_file_name);
527+
528+ h.readModel (model_file_name);
529+ // Variables now ordered y; z; x
530+ h.writeModel (" " );
531+ h.readBasis (basis_file_name);
532+ // Old read basis yields initial basis: y - basic; z - lower; x -
533+ // lower, using basis for original ordering with new ordering. Not
534+ // optimal - in fact basis matrix B = [0] is singular!
535+ h.run ();
536+ REQUIRE (h.getInfo ().simplex_iteration_count == 0 );
537+
538+ std::remove (model_file_name.c_str ());
539+ std::remove (basis_file_name.c_str ());
540+
541+ h.resetGlobalScheduler (true );
542+ }
543+
544+ TEST_CASE (" read-lp-file-rgn" , " [highs_check_solution]" ) {
545+ const std::string test_name = Catch::getResultCapture ().getCurrentTestName ();
546+ const std::string filename =
547+ std::string (HIGHS_DIR) + " /check/instances/rgn.mps" ;
548+ const std::string model_file_name = test_name + " .lp" ;
549+ const std::string solution_file_name = test_name + " .sol" ;
550+ Highs h;
551+ h.setOptionValue (" output_flag" , dev_run);
552+ REQUIRE (h.readModel (filename) == HighsStatus::kOk );
553+ REQUIRE (h.run () == HighsStatus::kOk );
554+ REQUIRE (h.writeSolution (solution_file_name) == HighsStatus::kOk );
555+ REQUIRE (h.writeModel (model_file_name) == HighsStatus::kOk );
556+
557+ REQUIRE (h.readModel (model_file_name) == HighsStatus::kOk );
558+ REQUIRE (h.readSolution (solution_file_name) == HighsStatus::kOk );
559+ bool valid;
560+ bool integral;
561+ bool feasible;
562+ REQUIRE (h.assessPrimalSolution (valid, integral, feasible) ==
563+ HighsStatus::kOk );
564+ REQUIRE (valid);
565+ REQUIRE (integral);
566+ REQUIRE (feasible);
567+
568+ std::remove (model_file_name.c_str ());
569+ std::remove (solution_file_name.c_str ());
570+
571+ h.resetGlobalScheduler (true );
572+ }
573+
462574void runWriteReadCheckSolution (Highs& highs, const std::string& test_name,
463575 const std::string& model,
464576 const HighsModelStatus require_model_status,
@@ -478,9 +590,15 @@ void runWriteReadCheckSolution(Highs& highs, const std::string& test_name,
478590 if (dev_run)
479591 printf (" Writing solution in style %d to %s\n " , int (write_solution_style),
480592 solution_file.c_str ());
481- if (dev_run) return_status = highs.writeSolution (" " , write_solution_style);
482- return_status = highs.writeSolution (solution_file, write_solution_style);
483- REQUIRE (return_status == HighsStatus::kOk );
593+ // For models without names, Highs::writeSolution will return
594+ // HighsStatus::kWarning
595+ HighsStatus require_status = highs.getLp ().col_names_ .size ()
596+ ? HighsStatus::kOk
597+ : HighsStatus::kWarning ;
598+ REQUIRE (highs.writeSolution (solution_file, write_solution_style) ==
599+ require_status);
600+ if (dev_run)
601+ REQUIRE (highs.writeSolution (" " , write_solution_style) == HighsStatus::kOk );
484602
485603 const bool & value_valid = highs.getSolution ().value_valid ;
486604 bool valid, integral, feasible;
@@ -581,3 +699,42 @@ void runSetLpSolution(const std::string model) {
581699
582700 highs.resetGlobalScheduler (true );
583701}
702+
703+ TEST_CASE (" miplib-sol-file" , " [highs_filereader]" ) {
704+ const std::string test_name = Catch::getResultCapture ().getCurrentTestName ();
705+ std::string sol_file = test_name + " .sol" ;
706+ std::string lp_file = test_name + " .lp" ;
707+ FILE* file = fopen (lp_file.c_str (), " w" );
708+ std::string file_content =
709+ " Minimize\n obj: 2 sel_2 + sel_3\n Subject To\n r0: sel_0 - sel_1 + sel_4 "
710+ " >= "
711+ " 2\n End\n " ;
712+ if (dev_run) printf (" Using .lp file\n %s" , file_content.c_str ());
713+ fprintf (file, " %s" , file_content.c_str ());
714+ fclose (file);
715+ Highs h;
716+ h.setOptionValue (" output_flag" , dev_run);
717+ REQUIRE (h.readModel (lp_file) == HighsStatus::kOk );
718+
719+ file = fopen (sol_file.c_str (), " w" );
720+ file_content =
721+ " =obj= 203672547.1\n sel_0 1\n sel_1 0\n sel_2 0\n sel_3 0\n sel_4 1\n " ;
722+ if (dev_run) printf (" Using .sol file\n %s" , file_content.c_str ());
723+ fprintf (file, " %s" , file_content.c_str ());
724+ fclose (file);
725+ REQUIRE (h.readSolution (sol_file) == HighsStatus::kOk );
726+
727+ std::vector<double > solution = h.getSolution ().col_value ;
728+ REQUIRE (solution[0 ] == 0 );
729+ REQUIRE (solution[1 ] == 0 );
730+ REQUIRE (solution[2 ] == 1 );
731+ REQUIRE (solution[3 ] == 0 );
732+ REQUIRE (solution[4 ] == 1 );
733+
734+ REQUIRE (h.run () == HighsStatus::kOk );
735+
736+ std::remove (lp_file.c_str ());
737+ std::remove (sol_file.c_str ());
738+
739+ h.resetGlobalScheduler (true );
740+ }
0 commit comments