Skip to content

Commit

Permalink
Now identifies that solution file is MIPLIB type
Browse files Browse the repository at this point in the history
  • Loading branch information
jajhall committed Oct 30, 2024
1 parent a8b5cc6 commit 08bb41d
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 48 deletions.
116 changes: 69 additions & 47 deletions src/lp_data/HighsLpUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,7 @@ HighsStatus readSolutionFile(const std::string filename,
}
std::string keyword;
std::string name;
double value;
HighsInt num_col;
HighsInt num_row;
const HighsInt lp_num_col = lp.num_col_;
Expand All @@ -2063,50 +2064,65 @@ HighsStatus readSolutionFile(const std::string filename,
read_basis.col_status.resize(lp_num_col);
read_basis.row_status.resize(lp_num_row);
std::string section_name;
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // Model status
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // Optimal
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); //
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // # Primal solution values
if (!readSolutionFileKeywordLineOk(keyword, in_file))
return readSolutionFileErrorReturn(in_file);
// Read in the primal solution values: return warning if there is none
if (keyword == "None")
return readSolutionFileReturn(HighsStatus::kWarning, solution, basis,
read_solution, read_basis, in_file);
// If there are primal solution values then keyword is the status
// and the next line is objective
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // EOL
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // Objective
// Next line should be "Columns" and correct number
if (!readSolutionFileHashKeywordIntLineOk(keyword, num_col, in_file))
return readSolutionFileErrorReturn(in_file);
assert(keyword == "Columns");
// The default style parameter is kSolutionStyleRaw, and this still
// allows sparse files to be read. Recognise the latter from num_col
// <= 0. Doesn't matter if num_col = 0, since there's nothing to
// read either way
const bool sparse = num_col <= 0;
if (style == kSolutionStyleSparse) assert(sparse);
if (sparse) {
num_col = -num_col;
assert(num_col <= lp_num_col);
} else {
if (num_col != lp_num_col) {
highsLogUser(log_options, HighsLogType::kError,
"readSolutionFile: Solution file is for %" HIGHSINT_FORMAT
" columns, not %" HIGHSINT_FORMAT "\n",
num_col, lp_num_col);
if (!readSolutionFileIdIgnoreLineOk(section_name, in_file))
return readSolutionFileErrorReturn(in_file); // Model (status) or =obj= (value)
const bool miplib_sol = section_name == "=obj=";
printf("Read \"%s\" as first term of first line of solution file: miplib_sol = %d\n", section_name.c_str(), miplib_sol);
bool sparse = false;
if (!miplib_sol) {
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // Optimal
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); //
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // # Primal solution values
if (!readSolutionFileKeywordLineOk(keyword, in_file))
return readSolutionFileErrorReturn(in_file);
// Read in the primal solution values: return warning if there is none
if (keyword == "None")
return readSolutionFileReturn(HighsStatus::kWarning, solution, basis,
read_solution, read_basis, in_file);
// If there are primal solution values then keyword is the status
// and the next line is objective
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // EOL
if (!readSolutionFileIgnoreLineOk(in_file))
return readSolutionFileErrorReturn(in_file); // Objective
// Next line should be "Columns" and correct number
if (!readSolutionFileHashKeywordIntLineOk(keyword, num_col, in_file))
return readSolutionFileErrorReturn(in_file);
assert(keyword == "Columns");
// The default style parameter is kSolutionStyleRaw, and this still
// allows sparse files to be read. Recognise the latter from num_col
// <= 0. Doesn't matter if num_col = 0, since there's nothing to
// read either way
sparse = num_col <= 0;
if (style == kSolutionStyleSparse) assert(sparse);
if (sparse) {
num_col = -num_col;
assert(num_col <= lp_num_col);
} else {
if (num_col != lp_num_col) {
highsLogUser(log_options, HighsLogType::kError,
"readSolutionFile: Solution file is for %" HIGHSINT_FORMAT
" columns, not %" HIGHSINT_FORMAT "\n",
num_col, lp_num_col);
return readSolutionFileErrorReturn(in_file);
}
}
}
double value;
if (sparse) {
if (miplib_sol) {
read_solution.col_value.assign(lp_num_col, 0);
for (;;) {
if (!readSolutionFileIdDoubleLineOk(name, value, in_file))
return readSolutionFileErrorReturn(in_file);
// Need to be able to hash names
HighsStatus status = HighsStatus::kError;
HighsInt iCol = 0;
read_solution.col_value[iCol] = value;
assert(123 == 456);
}
} else if (sparse) {
read_solution.col_value.assign(lp_num_col, 0);
HighsInt iCol;
for (HighsInt iX = 0; iX < num_col; iX++) {
Expand All @@ -2116,7 +2132,7 @@ HighsStatus readSolutionFile(const std::string filename,
}
} else {
for (HighsInt iCol = 0; iCol < num_col; iCol++) {
if (!readSolutionFileIdDoubleLineOk(value, in_file))
if (!readSolutionFileIdDoubleLineOk(name, value, in_file))
return readSolutionFileErrorReturn(in_file);
read_solution.col_value[iCol] = value;
}
Expand Down Expand Up @@ -2148,7 +2164,7 @@ HighsStatus readSolutionFile(const std::string filename,
// next.
const bool num_row_ok = num_row == lp_num_row;
for (HighsInt iRow = 0; iRow < num_row; iRow++) {
if (!readSolutionFileIdDoubleLineOk(value, in_file))
if (!readSolutionFileIdDoubleLineOk(name, value, in_file))
return readSolutionFileErrorReturn(in_file);
if (num_row_ok) read_solution.row_value[iRow] = value;
}
Expand Down Expand Up @@ -2191,7 +2207,7 @@ HighsStatus readSolutionFile(const std::string filename,
assert(keyword == "Columns");
double dual;
for (HighsInt iCol = 0; iCol < num_col; iCol++) {
if (!readSolutionFileIdDoubleLineOk(dual, in_file))
if (!readSolutionFileIdDoubleLineOk(name, dual, in_file))
return readSolutionFileErrorReturn(in_file);
read_solution.col_dual[iCol] = dual;
}
Expand All @@ -2202,7 +2218,7 @@ HighsStatus readSolutionFile(const std::string filename,
read_solution, read_basis, in_file);
assert(keyword == "Rows");
for (HighsInt iRow = 0; iRow < num_row; iRow++) {
if (!readSolutionFileIdDoubleLineOk(dual, in_file))
if (!readSolutionFileIdDoubleLineOk(name, dual, in_file))
return readSolutionFileErrorReturn(in_file);
read_solution.row_dual[iRow] = dual;
}
Expand Down Expand Up @@ -2272,8 +2288,14 @@ bool readSolutionFileHashKeywordIntLineOk(std::string& keyword, HighsInt& value,
return true;
}

bool readSolutionFileIdDoubleLineOk(double& value, std::ifstream& in_file) {
std::string id;
bool readSolutionFileIdIgnoreLineOk(std::string& id, std::ifstream& in_file) {
if (in_file.eof()) return false;
in_file >> id; // Id
in_file.ignore(kMaxLineLength, '\n');
return true;
}

bool readSolutionFileIdDoubleLineOk(std::string& id, double& value, std::ifstream& in_file) {
if (in_file.eof()) return false;
in_file >> id; // Id
if (in_file.eof()) return false;
Expand Down
3 changes: 2 additions & 1 deletion src/lp_data/HighsLpUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ bool readSolutionFileKeywordLineOk(std::string& keyword,
std::ifstream& in_file);
bool readSolutionFileHashKeywordIntLineOk(std::string& keyword, HighsInt& value,
std::ifstream& in_file);
bool readSolutionFileIdDoubleLineOk(double& value, std::ifstream& in_file);
bool readSolutionFileIdIgnoreLineOk(std::string& id, std::ifstream& in_file);
bool readSolutionFileIdDoubleLineOk(std::string& id, double& value, std::ifstream& in_file);
bool readSolutionFileIdDoubleIntLineOk(double& value, HighsInt& index,
std::ifstream& in_file);

Expand Down

0 comments on commit 08bb41d

Please sign in to comment.