diff --git a/check/TestFilereader.cpp b/check/TestFilereader.cpp index 98c0ecae26..bd6c709c1e 100644 --- a/check/TestFilereader.cpp +++ b/check/TestFilereader.cpp @@ -10,7 +10,7 @@ #include "lp_data/HighsLp.h" #include "lp_data/HighsLpUtils.h" -const bool dev_run = true; +const bool dev_run = false; TEST_CASE("filereader-edge-cases", "[highs_filereader]") { std::string model = ""; @@ -348,9 +348,10 @@ TEST_CASE("filereader-comment", "[highs_filereader]") { // Check that comments - either whole line with * in first column, // or rest of line following */$ are handled correctly const double optimal_objective_value = -4; - std::string model_file = std::string(HIGHS_DIR) + "/check/instances/comment.mps"; + std::string model_file = + std::string(HIGHS_DIR) + "/check/instances/comment.mps"; Highs highs; - highs.setOptionValue("output_flag", dev_run); + // highs.setOptionValue("output_flag", dev_run); REQUIRE(highs.readModel(model_file) == HighsStatus::kOk); REQUIRE(highs.run() == HighsStatus::kOk); double objective_value = highs.getInfo().objective_function_value; diff --git a/src/io/HMpsFF.cpp b/src/io/HMpsFF.cpp index 9aa9bbe952..9f9b3fbb55 100644 --- a/src/io/HMpsFF.cpp +++ b/src/io/HMpsFF.cpp @@ -219,8 +219,8 @@ bool HMpsFF::getMpsLine(std::istream& file, std::string& strline, bool& skip) { // Remove any trailing comment const size_t p = strline.find_first_of(mps_comment_chars); if (p <= strline.length()) { - // A comment character has been found, so erase from it to the end - // of the line and check whether the line is now empty + // A comment character has been found, so erase from it to the end + // of the line and check whether the line is now empty strline.erase(p); skip = is_empty(strline); } @@ -466,7 +466,8 @@ HighsInt HMpsFF::getColIdx(const std::string& colname, const bool add_if_new) { HMpsFF::Parsekey HMpsFF::parseDefault(const HighsLogOptions& log_options, std::istream& file) { std::string strline, word; - if (getline(file, strline)) { + bool skip; + if (getMpsLine(file, strline, skip)) { strline = trim(strline); if (strline.empty()) return HMpsFF::Parsekey::kComment; size_t s, e; @@ -513,8 +514,9 @@ HMpsFF::Parsekey HMpsFF::parseObjsense(const HighsLogOptions& log_options, std::istream& file) { std::string strline, word; - while (getline(file, strline)) { - if (is_empty(strline) || strline[0] == '*') continue; + bool skip; + while (getMpsLine(file, strline, skip)) { + if (skip) continue; size_t start = 0; size_t end = 0; @@ -607,9 +609,7 @@ HMpsFF::Parsekey HMpsFF::parseRows(const HighsLogOptions& log_options, } std::string rowname = first_word(strline, start + 1); - printf("HMpsFF::parseRows rowname = \"%s\"; strline = \"%s\"\n", rowname.c_str(), strline.c_str()); size_t rowname_end = first_word_end(strline, start + 1); - printf("HMpsFF::parseRows rowname_end = %d\n", int(rowname_end)); // Detect if file is in fixed format. if (!is_end(strline, rowname_end)) { @@ -691,22 +691,18 @@ typename HMpsFF::Parsekey HMpsFF::parseCols(const HighsLogOptions& log_options, assert(-1 == rowidx || -2 == rowidx); }; - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; HMpsFF::Parsekey key = checkFirstWord(strline, start, end, word); @@ -998,22 +994,18 @@ HMpsFF::Parsekey HMpsFF::parseRhs(const HighsLogOptions& log_options, has_obj_entry_ = false; bool has_entry = false; - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; size_t begin = 0; size_t end = 0; @@ -1164,22 +1156,18 @@ HMpsFF::Parsekey HMpsFF::parseBounds(const HighsLogOptions& log_options, has_lower.assign(num_col, false); has_upper.assign(num_col, false); - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; size_t begin = 0; size_t end = 0; @@ -1443,22 +1431,18 @@ HMpsFF::Parsekey HMpsFF::parseRanges(const HighsLogOptions& log_options, // Initialise tracking for duplicate entries has_row_entry_.assign(num_row, false); - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; size_t begin, end; std::string word; @@ -1596,21 +1580,18 @@ typename HMpsFF::Parsekey HMpsFF::parseHessian( size_t end_coeff_name; HighsInt colidx, rowidx; - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; size_t begin = 0; size_t end = 0; @@ -1723,7 +1704,8 @@ typename HMpsFF::Parsekey HMpsFF::parseQuadRows( "Row name \"%s\" in %s section is not defined: ignored\n", rowname.c_str(), section_name.c_str()); // read lines until start of new section - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { size_t begin = 0; size_t end = 0; HMpsFF::Parsekey key = checkFirstWord(strline, begin, end, col_name); @@ -1746,21 +1728,18 @@ typename HMpsFF::Parsekey HMpsFF::parseQuadRows( auto& qentries = (rowidx == -1 ? q_entries : qrows_entries[rowidx]); - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; size_t begin = 0; size_t end = 0; @@ -1899,22 +1878,18 @@ typename HMpsFF::Parsekey HMpsFF::parseCones(const HighsLogOptions& log_options, // now parse the cone entries: one column per line std::string strline; - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; size_t begin; std::string colname; @@ -1942,22 +1917,18 @@ typename HMpsFF::Parsekey HMpsFF::parseSos(const HighsLogOptions& log_options, const HMpsFF::Parsekey keyword) { std::string strline, word; - while (getline(file, strline)) { + bool skip; + while (getMpsLine(file, strline, skip)) { double current = getWallTime(); if (time_limit > 0 && current - start_time > time_limit) return HMpsFF::Parsekey::kTimeout; - if (kAnyFirstNonBlankAsStarImpliesComment) { - trim(strline); - if (strline.size() == 0 || strline[0] == '*') continue; - } else { - if (strline.size() > 0) { - // Just look for comment character in column 1 - if (strline[0] == '*') continue; - } - trim(strline); - if (strline.size() == 0) continue; + if (strline.size() > 0) { + // Just look for comment character in column 1 + if (strline[0] == '*') continue; } + trim(strline); + if (strline.size() == 0) continue; size_t begin, end; std::string word; diff --git a/src/io/HMpsFF.h b/src/io/HMpsFF.h index cd5dc5c22b..b5c86ae177 100644 --- a/src/io/HMpsFF.h +++ b/src/io/HMpsFF.h @@ -126,7 +126,6 @@ class HMpsFF { HighsInt fillMatrix(const HighsLogOptions& log_options); HighsInt fillHessian(const HighsLogOptions& log_options); - const bool kAnyFirstNonBlankAsStarImpliesComment = false; /// how to treat variables that appear in COLUMNS section first /// assume them to be binary as in the original IBM interpretation /// or integer with default bounds diff --git a/src/util/stringutil.h b/src/util/stringutil.h index 3c0a9c819d..25ac72c0ef 100644 --- a/src/util/stringutil.h +++ b/src/util/stringutil.h @@ -28,13 +28,17 @@ void strTrim(char* str); void tolower(std::string& str); const std::string default_non_chars = "\t\n\v\f\r "; -std::string& ltrim(std::string& str, const std::string& chars = default_non_chars); -std::string& rtrim(std::string& str, const std::string& chars = default_non_chars); -std::string& trim(std::string& str, const std::string& chars = default_non_chars); +std::string& ltrim(std::string& str, + const std::string& chars = default_non_chars); +std::string& rtrim(std::string& str, + const std::string& chars = default_non_chars); +std::string& trim(std::string& str, + const std::string& chars = default_non_chars); bool is_empty(std::string& str, const std::string& chars = default_non_chars); bool is_empty(char c, const std::string& chars = default_non_chars); -bool is_end(std::string& str, size_t end, const std::string& chars = default_non_chars); +bool is_end(std::string& str, size_t end, + const std::string& chars = default_non_chars); // todo: replace with pair of references rather than string ret value to avoid // copy and also using function below. or do it properly with iterators.