Skip to content

Commit

Permalink
Parallelize presolve problems
Browse files Browse the repository at this point in the history
  • Loading branch information
tbittar committed Sep 12, 2024
1 parent 5e5528f commit a4edb7c
Showing 1 changed file with 69 additions and 60 deletions.
129 changes: 69 additions & 60 deletions src/cpp/exe/presolve_problems/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#include <common.h>

#include <execution>
#include <filesystem>
#include <mutex>
#include <typeinfo>
#include <unordered_set>

Expand Down Expand Up @@ -42,68 +44,75 @@ int main(int argc, char **argv) {
CouplingMap presolvedCouplings;
std::string presolvedPrefix = "presolved-";
// Configure presolve and solve with 0 iteration
for (const auto &[pbName, candidates] : pbNameTocandidatesId) {
if (pbName == "master") {
// Copy couplings for master
for (auto &[varName, id] : couplings[pbName]) {
presolvedCouplings[pbName][varName] = id;
}
} else {
// Do the actual presolve work for subproblems
std::filesystem::path fullMpsPath = lpDir / pbName;
LoadXpress::XPRSrestore(xprsProb, fullMpsPath.c_str(), "");
LoadXpress::XPRSloadsecurevecs(xprsProb, 0, candidates.size(), nullptr,
candidates.data());
LoadXpress::XPRSsetintcontrol(xprsProb, XPRS_LPITERLIMIT, 0);
LoadXpress::XPRSlpoptimize(xprsProb, "");

// Write presolved problem MPS
std::filesystem::path presolvedFilename =
presolvedPrefix + fullMpsPath.filename().string();
std::filesystem::path presolvedPath =
fullMpsPath.parent_path() / presolvedFilename;

// Get candidates id in presolved problem
int nbCols(0);
int nbRows(0);
LoadXpress::XPRSgetintattrib(xprsProb, XPRS_COLS, &nbCols);
LoadXpress::XPRSgetintattrib(xprsProb, XPRS_ROWS, &nbRows);
std::vector<int> colMap(nbCols);
std::vector<int> rowMap(nbRows);
LoadXpress::XPRSgetpresolvemap(xprsProb, rowMap.data(), colMap.data());

std::unordered_set<int> initCandidatesIdSet(
pbNameTocandidatesId[pbName].begin(),
pbNameTocandidatesId[pbName].end());
// Use an unordered_map to store the indices of found values
std::unordered_map<int, int> initIdToPresolvedId;

for (int i = 0; i < colMap.size(); ++i) {
if (initCandidatesIdSet.find(colMap[i]) != initCandidatesIdSet.end()) {
initIdToPresolvedId[colMap[i]] = i;
initCandidatesIdSet.erase(colMap[i]);
if (initCandidatesIdSet.empty()) {
break;
std::for_each(
std::execution::par, pbNameTocandidatesId.begin(),
pbNameTocandidatesId.end(), [&](const auto &pbNameAndCandidate) {
auto [pbName, candidates] = pbNameAndCandidate;
if (pbName == "master") {
// Copy couplings for master
for (auto &[varName, id] : couplings[pbName]) {
presolvedCouplings[pbName][varName] = id;
}
} else {
// Do the actual presolve work for subproblems
std::filesystem::path fullMpsPath = lpDir / pbName;
LoadXpress::XPRSrestore(xprsProb, fullMpsPath.c_str(), "");
LoadXpress::XPRSloadsecurevecs(xprsProb, 0, candidates.size(),
nullptr, candidates.data());
LoadXpress::XPRSsetintcontrol(xprsProb, XPRS_LPITERLIMIT, 0);
LoadXpress::XPRSsetintcontrol(xprsProb, XPRS_THREADS, 1);
LoadXpress::XPRSlpoptimize(xprsProb, "");

// Write presolved problem MPS
std::filesystem::path presolvedFilename =
presolvedPrefix + fullMpsPath.filename().string();
std::filesystem::path presolvedPath =
fullMpsPath.parent_path() / presolvedFilename;

// Get candidates id in presolved problem
int nbCols(0);
int nbRows(0);
LoadXpress::XPRSgetintattrib(xprsProb, XPRS_COLS, &nbCols);
LoadXpress::XPRSgetintattrib(xprsProb, XPRS_ROWS, &nbRows);
std::vector<int> colMap(nbCols);
std::vector<int> rowMap(nbRows);
LoadXpress::XPRSgetpresolvemap(xprsProb, rowMap.data(),
colMap.data());

std::unordered_set<int> initCandidatesIdSet(
pbNameTocandidatesId[pbName].begin(),
pbNameTocandidatesId[pbName].end());
// Use an unordered_map to store the indices of found values
std::unordered_map<int, int> initIdToPresolvedId;

for (int i = 0; i < colMap.size(); ++i) {
if (initCandidatesIdSet.find(colMap[i]) !=
initCandidatesIdSet.end()) {
initIdToPresolvedId[colMap[i]] = i;
initCandidatesIdSet.erase(colMap[i]);
if (initCandidatesIdSet.empty()) {
break;
}
}
}
for (auto &[varName, id] : couplings[pbName]) {
presolvedCouplings[presolvedFilename.string()][varName] =
initIdToPresolvedId[id];
}

// Write and read again problem so that it is not in presolved state
// anymore, to be able to change obj function in Benders later on
// LoadXpress::XPRSsetintcontrol(xprsProb, XPRS_LPITERLIMIT,
// 2147483645);
LoadXpress::XPRSwriteprob(xprsProb, presolvedPath.c_str(), "");

XPRSprob xprsProbToSave;
LoadXpress::XPRScreateprob(&xprsProbToSave);
LoadXpress::XPRSreadprob(xprsProbToSave, presolvedPath.c_str(), "");
LoadXpress::XPRSsaveas(xprsProbToSave, presolvedPath.c_str());
std::filesystem::remove(presolvedPath);
}
}
for (auto &[varName, id] : couplings[pbName]) {
presolvedCouplings[presolvedFilename.string()][varName] =
initIdToPresolvedId[id];
}

// Write and read again problem so that it is not in presolved state
// anymore, to be able to change obj function in Benders later on
// LoadXpress::XPRSsetintcontrol(xprsProb, XPRS_LPITERLIMIT, 2147483645);
LoadXpress::XPRSwriteprob(xprsProb, presolvedPath.c_str(), "");

XPRSprob xprsProbToSave;
LoadXpress::XPRScreateprob(&xprsProbToSave);
LoadXpress::XPRSreadprob(xprsProbToSave, presolvedPath.c_str(), "");
LoadXpress::XPRSsaveas(xprsProbToSave, presolvedPath.c_str());
std::filesystem::remove(presolvedPath);
}
}
});

// Write structure for presolved problem
std::ofstream coupling_file(structureFilePath);
Expand Down

0 comments on commit a4edb7c

Please sign in to comment.