From 68e2052145fec41588aa94ef7621648d97210aab Mon Sep 17 00:00:00 2001 From: Christian Valente Date: Tue, 22 Oct 2024 07:58:28 -0700 Subject: [PATCH] Baron: removed PL as not supported. Added signal handling/propagation. --- solvers/baronmp/baronmpbackend.cc | 20 ++++++++--- solvers/baronmp/baronmpcommon.cc | 18 +++++----- solvers/baronmp/baronmpcommon.h | 8 +++++ solvers/baronmp/baronmpmodelapi.cc | 54 +++++++++++++++++------------- solvers/baronmp/baronmpmodelapi.h | 2 -- 5 files changed, 64 insertions(+), 38 deletions(-) diff --git a/solvers/baronmp/baronmpbackend.cc b/solvers/baronmp/baronmpbackend.cc index a44be5ec0..f8f01a6d3 100644 --- a/solvers/baronmp/baronmpbackend.cc +++ b/solvers/baronmp/baronmpbackend.cc @@ -6,6 +6,12 @@ #include "mp/flat/model_api_base.h" #include "baronmpbackend.h" + +#ifndef WIN32 +#include // for kill() +#endif + + extern "C" { #include "baronmp-ampls-c-api.h" // Baronmp AMPLS C API } @@ -15,12 +21,18 @@ namespace { bool InterruptBaronmp(void* prob) { - - //return BARONMP_Interrupt((baronmp_prob*)prob); + #ifndef WIN32 + kill(mp::BaronmpCommon::pid, SIGINT); + #else + if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, mp::BaronmpCommon::pid)) { + std::cerr << "GenerateConsoleCtrlEvent failed (" << GetLastError() << ").\n"; + return false; + } + #endif return true; } -} // namespace {} +} std::unique_ptr CreateBaronmpBackend() { return std::unique_ptr{new mp::BaronmpBackend()}; @@ -121,8 +133,6 @@ int BaronmpBackend::BarrierIterations() const { void BaronmpBackend::SetInterrupter(mp::Interrupter *inter) { inter->SetHandler(InterruptBaronmp, lp()); - // TODO Check interrupter - //BARONMP_CCALL( CPXsetterminate (env(), &terminate_flag) ); } void BaronmpBackend::Solve() { diff --git a/solvers/baronmp/baronmpcommon.cc b/solvers/baronmp/baronmpcommon.cc index f7558de5d..331e20c6e 100644 --- a/solvers/baronmp/baronmpcommon.cc +++ b/solvers/baronmp/baronmpcommon.cc @@ -39,6 +39,7 @@ namespace mp { #else constexpr const char* EXENAME = "baronin"; char SEP = '/'; + volatile pid_t BaronmpCommon::pid=-5; #endif int BaronmpCommon::runBaron(const std::string& arg) { @@ -102,11 +103,12 @@ int BaronmpCommon::run(const std::vector& args) { ZeroMemory(&pi, sizeof(pi)); // Create the process - if (!CreateProcess(NULL, cmdline.data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + if (!CreateProcess(NULL, cmdline.data(), NULL, + NULL, TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) { fmt::print(stderr, "CreateProcess failed ({})\n", GetLastError()); return -1; } - + pid = pi.dwProcessId; // Wait until the process exits WaitForSingleObject(pi.hProcess, INFINITE); @@ -126,7 +128,7 @@ int BaronmpCommon::run(const std::vector& args) { char **environ= *_NSGetEnviron(); #endif // Unix-like system implementation using fork and execve - pid_t pid = fork(); + pid = fork(); if (pid == -1) { fmt::print(stderr, "fork failed: {}\n", strerror(errno)); @@ -147,17 +149,17 @@ int BaronmpCommon::run(const std::vector& args) { else { // Parent process: wait for the child to complete int status; - if (waitpid(pid, &status, 0) == -1) { - fmt::print(stderr, "waitpid failed: {}\n", strerror(errno)); - return -1; - } + do { + pid = waitpid(pid, &status, 0); + } while (pid == -1 && errno == EINTR); // Retry if interrupted by a signal + if (WIFEXITED(status)) { return WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { fmt::print(stderr, "Process terminated by signal {}\n", WTERMSIG(status)); - return -1; + return 0; } } #endif diff --git a/solvers/baronmp/baronmpcommon.h b/solvers/baronmp/baronmpcommon.h index 1249bcbd1..f284be440 100644 --- a/solvers/baronmp/baronmpcommon.h +++ b/solvers/baronmp/baronmpcommon.h @@ -298,6 +298,11 @@ class BaronmpCommon : public Backend2ModelAPIConnector { public: +#ifndef WIN32 + static volatile pid_t pid; + #else + DWORD pid; +#endif static constexpr double Infinity() { return INFINITY; } static constexpr double MinusInfinity() { return -INFINITY; } const std::string FILENAME_BAR = "amplmodel.bar"; @@ -402,6 +407,9 @@ class ResFileData { double ObjectiveValue() const { + + if(objective_values.size() == 0) + return 0; return objective_values[objective_values.size() - 1]; } diff --git a/solvers/baronmp/baronmpmodelapi.cc b/solvers/baronmp/baronmpmodelapi.cc index ede5be8f9..55b1fd882 100644 --- a/solvers/baronmp/baronmpmodelapi.cc +++ b/solvers/baronmp/baronmpmodelapi.cc @@ -110,19 +110,29 @@ namespace mp { nVarsInteger(indicesInt.size()); } + void addCoefficient(fmt::MemoryWriter &w, double coeff, bool first) + { + if (coeff > 0) { + if (!first) w << " + "; + // Omit '1*' for positive coefficient 1 + if (coeff != 1) + w << coeff << "*"; + } + else { // Coefficient is negative + // If the coefficient is -1, just print ' - ', otherwise print the coefficient + if (coeff == -1) w << " - "; + else w << coeff << "*"; + } + } void appendLinearTerm(fmt::MemoryWriter &w, double coeff, const char* vname, bool first = false) { - if ((!first) && (coeff > 0)) - w << "+"; - if (std::fabs(coeff) != 1.0) w << coeff << "*"; + addCoefficient(w, coeff, first); w << vname; } void appendQuadTerm(fmt::MemoryWriter &w, double coeff, const char* v1, const char* v2=nullptr, bool first = false) { - if ((!first) && (coeff > 0)) - w << " +"; - if (std::fabs(coeff) != 1.0) w << coeff << "*"; + addCoefficient(w, coeff, first); if(v2) w << v1 << "*" << v2; else @@ -303,31 +313,30 @@ void BaronmpModelAPI::AddConstraint(const LogConstraint& cc) { } void BaronmpModelAPI::AddConstraint(const ExpAConstraint& cc) { - // TODO - fmt::print("Adding ExpA constraint \"{}\"\n", cc.GetName()); + // a^v + fmt::MemoryWriter w; + w<< createConName(cc.GetName()) << ": "; + w << fmt::format("{} = {} ^ {};\n", varName(cc.GetResultVar()), cc.GetParameters()[0],varName( cc.GetArguments()[0])); + cons.push_back(w.str()); } - - void BaronmpModelAPI::AddConstraint(const LogAConstraint& cc) { - // TODO - fmt::print("Adding LogA constraint \"{}\"\n", cc.GetName()); + fmt::MemoryWriter w; + w<< createConName(cc.GetName()) << ": "; + w << fmt::format("{} = log({})/log({});\n", varName(cc.GetResultVar()), + varName( cc.GetArguments()[0]), cc.GetParameters()[0]); + cons.push_back(w.str()); } void BaronmpModelAPI::AddConstraint(const PowConstraint& cc) { - // TODO -} - - - -void BaronmpModelAPI::AddConstraint(const PLConstraint& plc) { - fmt::print("Adding PL constraint \"{}\"\n", plc.GetName()); - // todo + // v ^ a + fmt::MemoryWriter w; + w<< createConName(cc.GetName()) << ": "; + w << fmt::format("{} = {} ^ {};\n", varName(cc.GetResultVar()),varName( cc.GetArguments()[0]), cc.GetParameters()[0]); + cons.push_back(w.str()); } - template void BaronmpModelAPI::addTopLevel(const NLBaseAssign& c) { - fmt::print("addTopLevel(const NLBaseAssign)\n"); const auto var = GetVariable(c); fmt::MemoryWriter w; w << createConName(c.GetName()) << ": "; @@ -336,7 +345,6 @@ template void BaronmpModelAPI::addTopLevel(const NLBaseAssign const auto& frm = GetExpression(c); w << frm.ToString(false); w << ";\n"; - fmt::print("{}\n", w.str()); cons.push_back(w.str()); } diff --git a/solvers/baronmp/baronmpmodelapi.h b/solvers/baronmp/baronmpmodelapi.h index 85b42b2df..19256c77e 100644 --- a/solvers/baronmp/baronmpmodelapi.h +++ b/solvers/baronmp/baronmpmodelapi.h @@ -297,8 +297,6 @@ class BaronmpModelAPI : /// Some non linear constraints. /// See constr_std.h for more. - ACCEPT_CONSTRAINT(PLConstraint, Recommended, CG_General) - void AddConstraint(const PLConstraint& cc); ACCEPT_CONSTRAINT(MaxConstraint, Recommended, CG_General) void AddConstraint(const MaxConstraint& mc); ACCEPT_CONSTRAINT(MinConstraint, Recommended, CG_General)