Skip to content

Commit

Permalink
2.5b build linear problem from components (#2558)
Browse files Browse the repository at this point in the history
- Build the problem from imported components
- Write the MPS file to ${PWD}/problem.mps
- Write the solution file to ${PWD}/solution.csv

---------

Co-authored-by: Vincent Payet <[email protected]>
  • Loading branch information
flomnes and payetvin authored Jan 10, 2025
1 parent c9cdfd1 commit eaf0373
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/solver/modeler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ target_link_libraries(modeler-lib
INTERFACE
Antares::loadModelerFiles
Antares::modelerParameters
Antares::optim-model-filler
Antares::modeler_api
# TODO FIXME don't depend on implementations
Antares::modeler-ortools-impl
)

target_link_libraries(antares-modeler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class ILinearProblem
/// Solve the problem, returns a IMipSolution
virtual IMipSolution* solve(bool verboseSolver) = 0;

virtual void WriteLP(const std::string& filename) = 0;

// Definition of infinity
virtual double infinity() const = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#pragma once

#include <map>
#include <string>
#include <vector>

#include "mipVariable.h"
Expand Down Expand Up @@ -51,6 +53,7 @@ class IMipSolution
virtual double getObjectiveValue() const = 0;
virtual double getOptimalValue(const IMipVariable* var) const = 0;
virtual std::vector<double> getOptimalValues(const std::vector<IMipVariable*>& vars) const = 0;
virtual const std::map<std::string, double>& getOptimalValues() const = 0;
};

} // namespace Antares::Solver::Modeler::Api
56 changes: 56 additions & 0 deletions src/solver/modeler/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@
* along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
*/

#include <fstream>

#include <antares/logs/logs.h>
#include <antares/solver/modeler/api/linearProblemBuilder.h>
#include <antares/solver/modeler/loadFiles/loadFiles.h>
#include <antares/solver/modeler/ortoolsImpl/linearProblem.h>
#include <antares/solver/modeler/parameters/parseModelerParameters.h>
#include <antares/solver/optim-model-filler/ComponentFiller.h>

using namespace Antares;
using namespace Antares::Solver;
Expand Down Expand Up @@ -53,6 +58,57 @@ int main(int argc, const char** argv)
logs.info() << "Libraries loaded";
const auto system = LoadFiles::loadSystem(studyPath, libraries);
logs.info() << "System loaded";

// Fillers, etc.
std::vector<Antares::Solver::Modeler::Api::LinearProblemFiller*> fillers;
// TODO memory
for (auto& [_, component]: system.Components())
{
fillers.push_back(new Antares::Optimization::ComponentFiller(component));
}

Antares::Solver::Modeler::Api::LinearProblemData LP_Data;
Antares::Solver::Modeler::Api::FillContext ctx = {0, 0};
// We force the usage of MIP solvers to check that integer variables are properly handled
// TODO determine the nature of the problem based on system.Components()
const bool isMip = true;
Antares::Solver::Modeler::OrtoolsImpl::OrtoolsLinearProblem pb(isMip, parameters.solver);
Antares::Solver::Modeler::Api::LinearProblemBuilder linear_problem_builder(fillers);
linear_problem_builder.build(pb, LP_Data, ctx);
for (auto& filler: fillers)
{
delete filler;
}

logs.info() << "Number of variables: " << pb.variableCount();
logs.info() << "Number of constraints: " << pb.constraintCount();

if (!parameters.noOutput)
{
logs.info() << "Writing problem.lp...";
auto mps_path = std::filesystem::current_path() / "problem.lp";
pb.WriteLP(mps_path.string());
}

logs.info() << "Launching resolution...";
auto* solution = pb.solve(parameters.solverLogs);
switch (solution->getStatus())
{
case Antares::Solver::Modeler::Api::MipStatus::OPTIMAL:
case Antares::Solver::Modeler::Api::MipStatus::FEASIBLE:
if (!parameters.noOutput)
{
logs.info() << "Writing variables...";
std::ofstream sol_out(std::filesystem::current_path() / "solution.csv");
for (const auto& [name, value]: solution->getOptimalValues())
{
sol_out << name << " " << value << std::endl;
}
}
break;
default:
logs.error() << "Problem during linear optimization";
}
}
catch (const LoadFiles::ErrorLoadingYaml&)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class OrtoolsLinearProblem: public Api::ILinearProblem
bool isMaximization() const override;

OrtoolsMipSolution* solve(bool verboseSolver) override;
void WriteLP(const std::string& filename) override;

double infinity() const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class OrtoolsMipSolution final: public Api::IMipSolution
double getOptimalValue(const Api::IMipVariable* var) const override;
std::vector<double> getOptimalValues(
const std::vector<Api::IMipVariable*>& vars) const override;
const std::map<std::string, double>& getOptimalValues() const override;

private:
operations_research::MPSolver::ResultStatus status_;
Expand Down
9 changes: 9 additions & 0 deletions src/solver/modeler/ortoolsImpl/linearProblem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

#include <exception>
#include <fstream>
#include <memory>
#include <ortools/linear_solver/linear_solver.h>

Expand Down Expand Up @@ -165,6 +166,14 @@ bool OrtoolsLinearProblem::isMaximization() const
return objective_->maximization();
}

void OrtoolsLinearProblem::WriteLP(const std::string& filename)
{
std::string out;
mpSolver_->ExportModelAsLpFormat(false, &out);
std::ofstream of(filename);
of << out;
}

MPSolver* OrtoolsLinearProblem::MpSolver() const
{
return mpSolver_;
Expand Down
5 changes: 5 additions & 0 deletions src/solver/modeler/ortoolsImpl/mipSolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,9 @@ std::vector<double> OrtoolsMipSolution::getOptimalValues(
return solution;
}

const std::map<std::string, double>& OrtoolsMipSolution::getOptimalValues() const
{
return solution_;
}

} // namespace Antares::Solver::Modeler::OrtoolsImpl

0 comments on commit eaf0373

Please sign in to comment.