diff --git a/app/HighsRuntimeOptions.h b/app/HighsRuntimeOptions.h index 04d3133e4b..2892a2fa86 100644 --- a/app/HighsRuntimeOptions.h +++ b/app/HighsRuntimeOptions.h @@ -145,7 +145,7 @@ bool loadOptions(const HighsLogOptions& report_log_options, int argc, case HighsLoadOptionsStatus::kError: return false; case HighsLoadOptionsStatus::kEmpty: - writeOptionsToFile(stdout, options.records); + writeOptionsToFile(stdout, options.log_options, options.records); return false; default: break; diff --git a/app/RunHighs.cpp b/app/RunHighs.cpp index 8813755b4c..b5830bc370 100644 --- a/app/RunHighs.cpp +++ b/app/RunHighs.cpp @@ -47,6 +47,7 @@ int main(int argc, char** argv) { // settings defined in any options file. highs.passOptions(loaded_options); // highs.writeOptions("Options.md"); + highs.writeOptions("", true); // Load the model from model_file HighsStatus read_status = highs.readModel(model_file); diff --git a/check/TestOptions.cpp b/check/TestOptions.cpp index f511f8caef..b2a4142710 100644 --- a/check/TestOptions.cpp +++ b/check/TestOptions.cpp @@ -95,7 +95,7 @@ TEST_CASE("internal-options", "[highs_options]") { REQUIRE(options.small_matrix_value == 0.001); REQUIRE(options.mps_parser_type_free); - if (dev_run) reportOptions(stdout, options.records, true); + if (dev_run) reportOptions(stdout, report_log_options, options.records, true); return_status = checkOptions(report_log_options, options.records); REQUIRE(return_status == OptionStatus::kOk); @@ -157,7 +157,7 @@ TEST_CASE("internal-options", "[highs_options]") { if (dev_run) { printf("\nAfter setting allowed_matrix_scale_factor to 1\n"); - reportOptions(stdout, options.records); + reportOptions(stdout, report_log_options, options.records); } double allowed_matrix_scale_factor_double = 1e-7; @@ -174,7 +174,7 @@ TEST_CASE("internal-options", "[highs_options]") { if (dev_run) { printf("\nAfter testing HighsInt options\n"); - reportOptions(stdout, options.records); + reportOptions(stdout, report_log_options, options.records); } // Check setting double options @@ -231,7 +231,7 @@ TEST_CASE("internal-options", "[highs_options]") { options.log_options, options.records, model_file); REQUIRE(return_status == OptionStatus::kUnknownOption); - if (dev_run) reportOptions(stdout, options.records); + if (dev_run) reportOptions(stdout, report_log_options, options.records); bool get_mps_parser_type_free; return_status = diff --git a/src/Highs.h b/src/Highs.h index 8480b3db35..2986d292ff 100644 --- a/src/Highs.h +++ b/src/Highs.h @@ -312,11 +312,11 @@ class Highs { /** * @brief Write (deviations from default values of) the options to a - * file, with the extension ".html" producing HTML, otherwise using - * the standard format used to read options from a file. + * file, using the standard format used to read options from a file. + * Possible to write only deviations from default values. */ HighsStatus writeOptions(const std::string& filename, //!< The filename - const bool report_only_deviations = false) const; + const bool report_only_deviations = false); /** * @brief Returns the number of user-settable options diff --git a/src/lp_data/Highs.cpp b/src/lp_data/Highs.cpp index 8372d4aded..94ed199839 100644 --- a/src/lp_data/Highs.cpp +++ b/src/lp_data/Highs.cpp @@ -139,7 +139,8 @@ HighsStatus Highs::resetOptions() { } HighsStatus Highs::writeOptions(const std::string& filename, - const bool report_only_deviations) const { + const bool report_only_deviations) { + this->logHeader(); HighsStatus return_status = HighsStatus::kOk; FILE* file; HighsFileType file_type; @@ -148,15 +149,16 @@ HighsStatus Highs::writeOptions(const std::string& filename, openWriteFile(filename, "writeOptions", file, file_type), return_status, "openWriteFile"); if (return_status == HighsStatus::kError) return return_status; + if (filename == "") file_type = HighsFileType::kMinimal; // Report to user that options are being written to a file if (filename != "") highsLogUser(options_.log_options, HighsLogType::kInfo, "Writing the option values to %s\n", filename.c_str()); - return_status = - interpretCallStatus(options_.log_options, - writeOptionsToFile(file, options_.records, - report_only_deviations, file_type), - return_status, "writeOptionsToFile"); + return_status = interpretCallStatus( + options_.log_options, + writeOptionsToFile(file, options_.log_options, options_.records, + report_only_deviations, file_type), + return_status, "writeOptionsToFile"); if (file != stdout) fclose(file); return return_status; } diff --git a/src/lp_data/HighsOptions.cpp b/src/lp_data/HighsOptions.cpp index 29ddd37629..15c3fb6204 100644 --- a/src/lp_data/HighsOptions.cpp +++ b/src/lp_data/HighsOptions.cpp @@ -811,15 +811,17 @@ void resetLocalOptions(std::vector& option_records) { } } -HighsStatus writeOptionsToFile(FILE* file, +HighsStatus writeOptionsToFile(FILE* file, const HighsLogOptions& log_options, const std::vector& option_records, const bool report_only_deviations, const HighsFileType file_type) { - reportOptions(file, option_records, report_only_deviations, file_type); + reportOptions(file, log_options, option_records, report_only_deviations, + file_type); return HighsStatus::kOk; } -void reportOptions(FILE* file, const std::vector& option_records, +void reportOptions(FILE* file, const HighsLogOptions& log_options, + const std::vector& option_records, const bool report_only_deviations, const HighsFileType file_type) { HighsInt num_options = option_records.size(); @@ -831,22 +833,27 @@ void reportOptions(FILE* file, const std::vector& option_records, if (!kAdvancedInDocumentation) continue; } if (type == HighsOptionType::kBool) { - reportOption(file, ((OptionRecordBool*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordBool*)option_records[index])[0], report_only_deviations, file_type); } else if (type == HighsOptionType::kInt) { - reportOption(file, ((OptionRecordInt*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordInt*)option_records[index])[0], report_only_deviations, file_type); } else if (type == HighsOptionType::kDouble) { - reportOption(file, ((OptionRecordDouble*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordDouble*)option_records[index])[0], report_only_deviations, file_type); } else { - reportOption(file, ((OptionRecordString*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordString*)option_records[index])[0], report_only_deviations, file_type); } } } -void reportOption(FILE* file, const OptionRecordBool& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordBool& option, const bool report_only_deviations, const HighsFileType file_type) { if (!report_only_deviations || option.default_value != *option.value) { @@ -865,40 +872,53 @@ void reportOption(FILE* file, const OptionRecordBool& option, fprintf(file, "%s = %s\n", option.name.c_str(), highsBoolToString(*option.value).c_str()); } else { - fprintf(file, "%s = %s\n", option.name.c_str(), - highsBoolToString(*option.value).c_str()); + std::string line = + highsFormatToString("Set option %s to %s\n", option.name.c_str(), + highsBoolToString(*option.value).c_str()); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } -void reportOption(FILE* file, const OptionRecordInt& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordInt& option, const bool report_only_deviations, const HighsFileType file_type) { if (!report_only_deviations || option.default_value != *option.value) { if (file_type == HighsFileType::kMd) { - fprintf(file, - "## %s\n- %s\n- Type: integer\n- Range: {%" HIGHSINT_FORMAT - ", %" HIGHSINT_FORMAT "}\n- Default: %" HIGHSINT_FORMAT "\n\n", - highsInsertMdEscapes(option.name).c_str(), - highsInsertMdEscapes(option.description).c_str(), - option.lower_bound, option.upper_bound, option.default_value); + fprintf( + file, + "## %s\n- %s\n- Type: integer\n- Range: {%d, %d}\n- Default: %d\n\n", + highsInsertMdEscapes(option.name).c_str(), + highsInsertMdEscapes(option.description).c_str(), + int(option.lower_bound), int(option.upper_bound), + int(option.default_value)); } else if (file_type == HighsFileType::kFull) { fprintf(file, "\n# %s\n", option.description.c_str()); fprintf(file, "# [type: integer, advanced: %s, range: {%" HIGHSINT_FORMAT - ", %" HIGHSINT_FORMAT "}, default: %" HIGHSINT_FORMAT "]\n", + ", %d}, default: %d]\n", highsBoolToString(option.advanced).c_str(), option.lower_bound, - option.upper_bound, option.default_value); - fprintf(file, "%s = %" HIGHSINT_FORMAT "\n", option.name.c_str(), - *option.value); + int(option.upper_bound), int(option.default_value)); + fprintf(file, "%s = %d\n", option.name.c_str(), int(*option.value)); } else { - fprintf(file, "%s = %" HIGHSINT_FORMAT "\n", option.name.c_str(), - *option.value); + std::string line = highsFormatToString( + "Set option %s to %d\n", option.name.c_str(), int(*option.value)); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } -void reportOption(FILE* file, const OptionRecordDouble& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordDouble& option, const bool report_only_deviations, const HighsFileType file_type) { if (!report_only_deviations || option.default_value != *option.value) { @@ -917,12 +937,19 @@ void reportOption(FILE* file, const OptionRecordDouble& option, option.upper_bound, option.default_value); fprintf(file, "%s = %g\n", option.name.c_str(), *option.value); } else { - fprintf(file, "%s = %g\n", option.name.c_str(), *option.value); + std::string line = highsFormatToString( + "Set option %s to %g\n", option.name.c_str(), *option.value); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } -void reportOption(FILE* file, const OptionRecordString& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordString& option, const bool report_only_deviations, const HighsFileType file_type) { // Don't report for the options file if writing to an options file @@ -943,7 +970,14 @@ void reportOption(FILE* file, const OptionRecordString& option, option.default_value.c_str()); fprintf(file, "%s = %s\n", option.name.c_str(), (*option.value).c_str()); } else { - fprintf(file, "%s = %s\n", option.name.c_str(), (*option.value).c_str()); + std::string line = + highsFormatToString("Set option %s to \"%s\"\n", option.name.c_str(), + (*option.value).c_str()); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } diff --git a/src/lp_data/HighsOptions.h b/src/lp_data/HighsOptions.h index 842f432b00..ceeabbb1cc 100644 --- a/src/lp_data/HighsOptions.h +++ b/src/lp_data/HighsOptions.h @@ -233,22 +233,28 @@ OptionStatus getLocalOptionType( void resetLocalOptions(std::vector& option_records); HighsStatus writeOptionsToFile( - FILE* file, const std::vector& option_records, + FILE* file, const HighsLogOptions& report_log_options, + const std::vector& option_records, const bool report_only_deviations = false, const HighsFileType file_type = HighsFileType::kFull); -void reportOptions(FILE* file, const std::vector& option_records, +void reportOptions(FILE* file, const HighsLogOptions& report_log_options, + const std::vector& option_records, const bool report_only_deviations = false, const HighsFileType file_type = HighsFileType::kFull); -void reportOption(FILE* file, const OptionRecordBool& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordBool& option, const bool report_only_deviations, const HighsFileType file_type); -void reportOption(FILE* file, const OptionRecordInt& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordInt& option, const bool report_only_deviations, const HighsFileType file_type); -void reportOption(FILE* file, const OptionRecordDouble& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordDouble& option, const bool report_only_deviations, const HighsFileType file_type); -void reportOption(FILE* file, const OptionRecordString& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordString& option, const bool report_only_deviations, const HighsFileType file_type);