Skip to content

Commit

Permalink
Merge pull request #4382 from rte-france/main
Browse files Browse the repository at this point in the history
 Use absl's locale-independent conversion functions in XPRESS MPSolver interface
  • Loading branch information
lperron authored Sep 21, 2024
2 parents fd00bf8 + 54f2f90 commit 9f41024
Showing 1 changed file with 20 additions and 26 deletions.
46 changes: 20 additions & 26 deletions ortools/linear_solver/xpress_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <mutex>
#include <string>

#include "absl/strings/numbers.h"
#include "absl/strings/str_format.h"
#include "ortools/base/logging.h"
#include "ortools/base/timer.h"
Expand Down Expand Up @@ -227,7 +228,7 @@ class XpressMPCallbackContext : public MPCallbackContext {
: xprsprob_(xprsprob),
event_(event),
num_nodes_(num_nodes),
variable_values_(0) {};
variable_values_(0){};

// Implementation of the interface.
MPCallbackEvent Event() override { return event_; };
Expand Down Expand Up @@ -260,7 +261,7 @@ class XpressMPCallbackContext : public MPCallbackContext {
// Wraps the MPCallback in order to catch and store exceptions
class MPCallbackWrapper {
public:
explicit MPCallbackWrapper(MPCallback* callback) : callback_(callback) {};
explicit MPCallbackWrapper(MPCallback* callback) : callback_(callback){};
MPCallback* GetCallback() const { return callback_; }
// Since our (C++) call-back functions are called from the XPRESS (C) code,
// exceptions thrown in our call-back code are not caught by XPRESS.
Expand Down Expand Up @@ -2106,29 +2107,21 @@ void splitMyString(const std::string& str, Container& cont, char delim = ' ') {
}
}

const char* stringToCharPtr(std::string& var) { return var.c_str(); }

// Save the existing locale, use the "C" locale to ensure that
// string -> double conversion is done ignoring the locale.
struct ScopedLocale {
ScopedLocale() {
oldLocale = std::setlocale(LC_NUMERIC, nullptr);
auto newLocale = std::setlocale(LC_NUMERIC, "C");
CHECK_EQ(std::string(newLocale), "C");
}
~ScopedLocale() { std::setlocale(LC_NUMERIC, oldLocale); }

private:
const char* oldLocale;
};
bool stringToCharPtr(const std::string& var, const char** out) {
*out = var.c_str();
return true;
}

#define setParamIfPossible_MACRO(target_map, setter, converter) \
#define setParamIfPossible_MACRO(target_map, setter, converter, type) \
{ \
auto matchingParamIter = (target_map).find(paramAndValuePair.first); \
if (matchingParamIter != (target_map).end()) { \
const auto convertedValue = converter(paramAndValuePair.second); \
VLOG(1) << "Setting parameter " << paramAndValuePair.first \
<< " to value " << convertedValue << std::endl; \
type convertedValue; \
bool ret = converter(paramAndValuePair.second, &convertedValue); \
if (ret) { \
VLOG(1) << "Setting parameter " << paramAndValuePair.first \
<< " to value " << convertedValue << std::endl; \
} \
setter(mLp, matchingParamIter->second, convertedValue); \
continue; \
} \
Expand All @@ -2153,14 +2146,15 @@ bool XpressInterface::SetSolverSpecificParametersAsString(
}
}

ScopedLocale locale;
for (auto& paramAndValuePair : paramAndValuePairList) {
setParamIfPossible_MACRO(mapIntegerControls_, XPRSsetintcontrol, std::stoi);
setParamIfPossible_MACRO(mapDoubleControls_, XPRSsetdblcontrol, std::stod);
setParamIfPossible_MACRO(mapIntegerControls_, XPRSsetintcontrol,
absl::SimpleAtoi<int>, int);
setParamIfPossible_MACRO(mapDoubleControls_, XPRSsetdblcontrol,
absl::SimpleAtod, double);
setParamIfPossible_MACRO(mapStringControls_, XPRSsetstrcontrol,
stringToCharPtr);
stringToCharPtr, const char*);
setParamIfPossible_MACRO(mapInteger64Controls_, XPRSsetintcontrol64,
std::stoll);
absl::SimpleAtoi<int64_t>, int64_t);
LOG(ERROR) << "Unknown parameter " << paramName << " : function "
<< __FUNCTION__ << std::endl;
return false;
Expand Down

0 comments on commit 9f41024

Please sign in to comment.