@@ -2273,7 +2273,7 @@ HighsStatus readSolutionFile(const std::string filename,
22732273 read_solution, read_basis,
22742274 in_file); // # Basis
22752275 HighsStatus basis_read_status =
2276- readBasisStream (log_options, read_basis, in_file);
2276+ readBasisStream (log_options, lp , read_basis, in_file);
22772277 // Return with basis read status
22782278 return readSolutionFileReturn (basis_read_status, solution, basis,
22792279 read_solution, read_basis, in_file);
@@ -2529,8 +2529,10 @@ HighsStatus assessLpPrimalSolution(const std::string message,
25292529 return HighsStatus::kOk ;
25302530}
25312531
2532- void writeBasisFile (FILE*& file, const HighsBasis& basis) {
2533- fprintf (file, " HiGHS v%d\n " , (int )HIGHS_VERSION_MAJOR);
2532+ void writeBasisFile (FILE*& file, const HighsOptions& options,
2533+ const HighsLp& lp, const HighsBasis& basis) {
2534+ /*
2535+ fprintf(file, "HiGHS_basis_file %s\n", kHighsBasisFileV2.c_str());
25342536 if (basis.valid == false) {
25352537 fprintf(file, "None\n");
25362538 return;
@@ -2542,16 +2544,59 @@ void writeBasisFile(FILE*& file, const HighsBasis& basis) {
25422544 fprintf(file, "# Rows %d\n", (int)basis.row_status.size());
25432545 for (const auto& status : basis.row_status) fprintf(file, "%d ", (int)status);
25442546 fprintf(file, "\n");
2547+ */
2548+ const HighsLogOptions& log_options = options.log_options ;
2549+ std::stringstream ss;
2550+ // Basis version line
2551+ ss.str (std::string ());
2552+ ss << highsFormatToString (" HiGHS_basis_file %s\n " , kHighsBasisFileV2 .c_str ());
2553+ highsFprintfString (file, log_options, ss.str ());
2554+ // Basis validity line
2555+ ss.str (std::string ());
2556+ if (basis.valid == false ) {
2557+ ss << highsFormatToString (" None\n " );
2558+ highsFprintfString (file, log_options, ss.str ());
2559+ return ;
2560+ }
2561+ assert (basis.col_status .size () == static_cast <size_t >(lp.num_col_ ));
2562+ assert (basis.row_status .size () == static_cast <size_t >(lp.num_row_ ));
2563+ assert (lp.col_names_ .size () == static_cast <size_t >(lp.num_col_ ));
2564+ assert (lp.row_names_ .size () == static_cast <size_t >(lp.num_row_ ));
2565+ ss << highsFormatToString (" Valid\n " );
2566+ highsFprintfString (file, log_options, ss.str ());
2567+ // Column count line
2568+ ss.str (std::string ());
2569+ ss << highsFormatToString (" # Columns %d\n " , int (lp.num_col_ ));
2570+ highsFprintfString (file, log_options, ss.str ());
2571+ for (HighsInt iCol = 0 ; iCol < lp.num_col_ ; iCol++) {
2572+ const std::string& name = lp.col_names_ [iCol];
2573+ assert (name.length () != 0 );
2574+ ss.str (std::string ());
2575+ ss << highsFormatToString (" %s %d\n " , name.c_str (), int (basis.col_status [iCol]));
2576+ highsFprintfString (file, log_options, ss.str ());
2577+ }
2578+ // Row count line
2579+ ss.str (std::string ());
2580+ ss << highsFormatToString (" # Rows %d\n " , int (lp.num_row_ ));
2581+ highsFprintfString (file, log_options, ss.str ());
2582+ for (HighsInt iRow = 0 ; iRow < lp.num_row_ ; iRow++) {
2583+ const std::string& name = lp.row_names_ [iRow];
2584+ assert (name.length () != 0 );
2585+ ss.str (std::string ());
2586+ ss << highsFormatToString (" %s %d\n " , name.c_str (), int (basis.row_status [iRow]));
2587+ highsFprintfString (file, log_options, ss.str ());
2588+ }
25452589}
25462590
2547- HighsStatus readBasisFile (const HighsLogOptions& log_options, HighsBasis& basis,
2591+ HighsStatus readBasisFile (const HighsLogOptions& log_options,
2592+ HighsLp& lp, HighsBasis& basis,
25482593 const std::string filename) {
25492594 // Opens a basis file as an ifstream
25502595 HighsStatus return_status = HighsStatus::kOk ;
25512596 std::ifstream in_file;
25522597 in_file.open (filename.c_str (), std::ios::in);
25532598 if (in_file.is_open ()) {
2554- return_status = readBasisStream (log_options, basis, in_file);
2599+ return_status = readBasisStream (log_options, lp, basis, in_file);
25552600 in_file.close ();
25562601 } else {
25572602 highsLogUser (log_options, HighsLogType::kError ,
@@ -2563,13 +2608,28 @@ HighsStatus readBasisFile(const HighsLogOptions& log_options, HighsBasis& basis,
25632608}
25642609
25652610HighsStatus readBasisStream (const HighsLogOptions& log_options,
2566- HighsBasis& basis, std::ifstream& in_file) {
2611+ HighsLp& lp, HighsBasis& basis,
2612+ std::ifstream& in_file) {
25672613 // Reads a basis as an ifstream, returning an error if what's read is
25682614 // inconsistent with the sizes of the HighsBasis passed in
25692615 HighsStatus return_status = HighsStatus::kOk ;
25702616 std::string string_highs, string_version;
25712617 in_file >> string_highs >> string_version;
2572- if (string_version == " v1" ) {
2618+ const bool v1 = string_version == kHighsBasisFileV1 ;
2619+ const bool v2 = string_version == kHighsBasisFileV2 ;
2620+ if (v2) {
2621+ // Form the column and row name hash
2622+ assert (lp.col_names_ .size () == static_cast <size_t >(lp.num_col_ ));
2623+ assert (lp.row_names_ .size () == static_cast <size_t >(lp.num_row_ ));
2624+ lp.col_hash_ .form (lp.col_names_ );
2625+ lp.row_hash_ .form (lp.row_names_ );
2626+ }
2627+ if (v1 || v2) {
2628+ if (v1) {
2629+ // Ability to read v1 basis files is deprecated
2630+ highsLogUser (log_options, HighsLogType::kWarning ,
2631+ " readBasisFile: Basis file format %s is deprecated\n " , kHighsBasisFileV1 .c_str ());
2632+ }
25732633 std::string keyword;
25742634 in_file >> keyword;
25752635 if (keyword == " None" ) {
@@ -2579,6 +2639,7 @@ HighsStatus readBasisStream(const HighsLogOptions& log_options,
25792639 const HighsInt basis_num_col = (HighsInt)basis.col_status .size ();
25802640 const HighsInt basis_num_row = (HighsInt)basis.row_status .size ();
25812641 HighsInt int_status;
2642+ std::string name;
25822643 assert (keyword == " Valid" );
25832644 HighsInt num_col, num_row;
25842645 // Read in the columns section
@@ -2592,9 +2653,28 @@ HighsStatus readBasisStream(const HighsLogOptions& log_options,
25922653 num_col, basis_num_col);
25932654 return HighsStatus::kError ;
25942655 }
2595- for (HighsInt iCol = 0 ; iCol < num_col; iCol++) {
2596- in_file >> int_status;
2597- basis.col_status [iCol] = (HighsBasisStatus)int_status;
2656+ if (v1) {
2657+ for (HighsInt iCol = 0 ; iCol < num_col; iCol++) {
2658+ in_file >> int_status;
2659+ basis.col_status [iCol] = (HighsBasisStatus)int_status;
2660+ }
2661+ } else {
2662+ for (HighsInt iColBasis = 0 ; iColBasis < num_col; iColBasis++) {
2663+ in_file >> name >> int_status;
2664+ auto search = lp.col_hash_ .name2index .find (name);
2665+ if (search == lp.col_hash_ .name2index .end ()) {
2666+ highsLogUser (log_options, HighsLogType::kError ,
2667+ " Highs::readBasisStream: column name %s is not found\n " , name.c_str ());
2668+ return HighsStatus::kError ;
2669+ }
2670+ if (search->second == kHashIsDuplicate ) {
2671+ highsLogUser (log_options, HighsLogType::kError ,
2672+ " Highs::readBasisStream: column name %s is duplicated\n " , name.c_str ());
2673+ return HighsStatus::kError ;
2674+ }
2675+ HighsInt iCol = search->second ;
2676+ basis.col_status [iCol] = HighsBasisStatus (int_status);
2677+ }
25982678 }
25992679 // Read in the rows section
26002680 in_file >> keyword >> keyword;
@@ -2607,9 +2687,28 @@ HighsStatus readBasisStream(const HighsLogOptions& log_options,
26072687 num_row, basis_num_row);
26082688 return HighsStatus::kError ;
26092689 }
2610- for (HighsInt iRow = 0 ; iRow < num_row; iRow++) {
2611- in_file >> int_status;
2612- basis.row_status [iRow] = (HighsBasisStatus)int_status;
2690+ if (v1) {
2691+ for (HighsInt iRow = 0 ; iRow < num_row; iRow++) {
2692+ in_file >> int_status;
2693+ basis.row_status [iRow] = (HighsBasisStatus)int_status;
2694+ }
2695+ } else {
2696+ for (HighsInt iRowBasis = 0 ; iRowBasis < num_row; iRowBasis++) {
2697+ in_file >> name >> int_status;
2698+ auto search = lp.row_hash_ .name2index .find (name);
2699+ if (search == lp.row_hash_ .name2index .end ()) {
2700+ highsLogUser (log_options, HighsLogType::kError ,
2701+ " Highs::readBasisStream: row name %s is not found\n " , name.c_str ());
2702+ return HighsStatus::kError ;
2703+ }
2704+ if (search->second == kHashIsDuplicate ) {
2705+ highsLogUser (log_options, HighsLogType::kError ,
2706+ " Highs::readBasisStream: row name %s is duplicated\n " , name.c_str ());
2707+ return HighsStatus::kError ;
2708+ }
2709+ HighsInt iRow = search->second ;
2710+ basis.row_status [iRow] = HighsBasisStatus (int_status);
2711+ }
26132712 }
26142713 } else {
26152714 highsLogUser (log_options, HighsLogType::kError ,
0 commit comments