#include <cstdio>
#include "Highs.h"
#include "HighsRuntimeOptions.h"
static bool written_cli_copyright_line = false;
void cliCopyrightLine(const HighsLogOptions& log_options) {
if (written_cli_copyright_line) return;
highsLogUser(log_options, HighsLogType::kInfo,
"Command line parsed using CLI11 %s: Copyright (c) 2017-2025 "
"University of Cincinnati\n",
CLI11_VERSION);
written_cli_copyright_line = true;
}
int runHighsReturn(Highs& highs, const int status) {
highs.logHeader();
cliCopyrightLine(highs.getOptions().log_options);
highs.closeLogFile();
assert(highs.getOptions().log_options.log_stream == nullptr);
return status;
}
int runHighsReturn(Highs& highs, const HighsStatus status) {
return runHighsReturn(highs, int(status));
}
int main(int argc, char** argv) {
Highs highs;
const HighsOptions& options = highs.getOptions();
const HighsLogOptions& log_options = options.log_options;
HighsCommandLineOptions cmd_options;
HighsOptions loaded_options;
loaded_options.log_file = kHighsRunLogFile;
CLI::App app{""};
argv = app.ensure_utf8(argv);
setupCommandLineOptions(app, cmd_options);
try {
std::string usage_msg =
"usage:\n " + std::string(argv[0]) + " [options] [file]";
app.usage(usage_msg);
app.parse(argc, argv);
} catch (const CLI::CallForHelp& e) {
std::cout << app.help() << std::endl;
return runHighsReturn(highs, 0);
} catch (const CLI::CallForAllHelp& e) {
std::cout << app.help();
return runHighsReturn(highs, 0);
} catch (const CLI::RequiredError& e) {
std::cout << "Please specify filename in .mps|.lp|.ems format."
<< std::endl;
return runHighsReturn(highs, HighsStatus::kError);
} catch (const CLI::ExtrasError& e) {
std::cout << e.what() << std::endl;
std::cout << "Multiple files not supported." << std::endl;
return runHighsReturn(highs, HighsStatus::kError);
} catch (const CLI::ArgumentMismatch& e) {
std::cout << e.what() << std::endl;
std::cout << "Too many arguments provided. Please provide only one."
<< std::endl;
return runHighsReturn(highs, HighsStatus::kError);
} catch (const CLI::ParseError& e) {
std::cout << e.what() << std::endl;
return runHighsReturn(highs, app.exit(e));
}
if (!loadOptions(app, log_options, cmd_options, loaded_options))
return runHighsReturn(highs, HighsStatus::kError);
if (loaded_options.output_flag) highs.openLogFile(loaded_options.log_file);
highs.passOptions(loaded_options);
highs.logHeader();
cliCopyrightLine(log_options);
highs.writeOptions("", true);
HighsStatus read_status = highs.readModel(cmd_options.model_file);
if (read_status == HighsStatus::kError) {
highsLogUser(log_options, HighsLogType::kInfo, "Error loading file\n");
return runHighsReturn(highs, read_status);
}
if (options.write_presolved_model_file != "") {
HighsStatus status = highs.presolve();
if (status == HighsStatus::kError) return runHighsReturn(highs, status);
HighsPresolveStatus model_presolve_status = highs.getModelPresolveStatus();
const bool ok_to_write =
model_presolve_status == HighsPresolveStatus::kNotReduced ||
model_presolve_status == HighsPresolveStatus::kReduced ||
model_presolve_status == HighsPresolveStatus::kReducedToEmpty ||
model_presolve_status == HighsPresolveStatus::kTimeout;
if (!ok_to_write) {
highsLogUser(log_options, HighsLogType::kInfo,
"No presolved model to write to file\n");
return runHighsReturn(highs, status);
}
status = highs.writePresolvedModel(options.write_presolved_model_file);
return runHighsReturn(highs, status);
}
HighsStatus run_status = highs.run();
if (run_status == HighsStatus::kError) runHighsReturn(highs, run_status);
highs.resetGlobalScheduler(true);
return runHighsReturn(highs, run_status);
}