Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3rd try at scenario building #2033

Draft
wants to merge 9 commits into
base: poc_linearProblem
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/solver/optim/api/LinearProblemBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,33 @@ void LinearProblemBuilder::addFiller(std::shared_ptr<LinearProblemFiller> filler
fillers_.push_back(filler);
}

void LinearProblemBuilder::build(const LinearProblemData& data) {
if (built) {
void LinearProblemBuilder::build(const LinearProblemData& data, const BuildContext& buildCtx)
{
if (built)
{
// TODO
throw;
}
for (auto filler : fillers_)
{
filler->addVariables(*linearProblem_, data);
filler->addVariables(*linearProblem_, data, buildCtx);
}
for (auto filler : fillers_)
{
filler->addConstraints(*linearProblem_, data);
filler->addConstraints(*linearProblem_, data, buildCtx);
}
for (auto filler : fillers_)
{
filler->addObjective(*linearProblem_, data);
filler->addObjective(*linearProblem_, data, buildCtx);
}
built = true;
}

void LinearProblemBuilder::update(const LinearProblemData& data) const {
void LinearProblemBuilder::update(const LinearProblemData& data) const
{
// TODO : throw if timestamps have changed ?
if (!built) {
if (!built)
{
// TODO
throw;
}
Expand All @@ -46,7 +50,8 @@ void LinearProblemBuilder::update(const LinearProblemData& data) const {
MipSolution LinearProblemBuilder::solve(const operations_research::MPSolverParameters& param)
{
// TODO : move to new interface LinearProblemSolver ??
if (!built) {
if (!built)
{
// TODO
throw;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,23 @@
*/
#pragma once

#include <vector>
#include "LinearProblemFiller.h"
#include "vector"

namespace Antares::optim::api
{
class LinearProblemBuilder final
{
private:
LinearProblem* linearProblem_;
std::vector<std::shared_ptr<LinearProblemFiller>> fillers_{};
bool built = false;
public:
explicit LinearProblemBuilder(LinearProblem& linearProblem) : linearProblem_(&linearProblem) {};
void addFiller(std::shared_ptr<LinearProblemFiller> filler);
void build(const LinearProblemData& data);
void update(const LinearProblemData& data) const;
MipSolution solve(const operations_research::MPSolverParameters& param);
};
}
class LinearProblemBuilder final
{
private:
LinearProblem* linearProblem_;
std::vector<std::shared_ptr<LinearProblemFiller>> fillers_{};
bool built = false;

public:
explicit LinearProblemBuilder(LinearProblem& linearProblem) : linearProblem_(&linearProblem){};
void addFiller(std::shared_ptr<LinearProblemFiller> filler);
void build(const LinearProblemData& data, const BuildContext& ctx);
void update(const LinearProblemData& data) const;
MipSolution solve(const operations_research::MPSolverParameters& param);
};
} // namespace Antares::optim::api
117 changes: 84 additions & 33 deletions src/solver/optim/api/include/antares/optim/api/LinearProblemData.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,96 @@
#pragma once

#include <utility>
#include <vector>
#include "antares/solver/simulation/sim_structure_probleme_economique.h"

#include "vector"

namespace Antares::optim::api
{
class LinearProblemData final
class LinearProblemData final
{
private:
// TODO : timestamps or timesteps?
int timeResolutionInMinutes_;
std::map<std::string, std::vector<double>> scalarData_;
std::map<std::string, std::vector<std::vector<double>>> timedData_;
// TODO : handle scenarios, and data vectorized on scenarios, on time, or on both
public:
explicit LinearProblemData(
int timeResolutionInMinutes,
const std::map<std::string, std::vector<double>>& scalarData,
const std::map<std::string, std::vector<std::vector<double>>>& timedData) :
Comment on lines +46 to +47
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const std::map<std::string, std::vector<double>>& scalarData,
const std::map<std::string, std::vector<std::vector<double>>>& timedData) :
const std::map<std::string, std::vector<double>>& scalarDataPerScenario,
const std::map<std::string, std::vector<std::vector<double>>>& timedDataPerScenario) :

timeResolutionInMinutes_(timeResolutionInMinutes),
scalarData_(scalarData),
timedData_(timedData){
// TODO: some coherence check on data
// for example, check that timed data are all of same size = size of timeStamps_
};
[[nodiscard]] int getTimeResolutionInMinutes() const
{
return timeResolutionInMinutes_;
}
[[nodiscard]] bool hasScalarData(const std::string& key) const
{
return scalarData_.contains(key);
}
[[nodiscard]] double getScalarData(const std::string& key, unsigned int scenario) const
{
private:
// TODO : timestamps or timesteps?
std::vector<int> timeStamps_;
int timeResolutionInMinutes_;
std::map<std::string, double> scalarData_;
std::map<std::string, std::vector<double>> timedData_;
// TODO : handle scenarios, and data vectorized on scenarios, on time, or on both
public:
explicit LinearProblemData(const std::vector<int> &timeStamps, int timeResolutionInMinutes,
const std::map<std::string, double> &scalarData,
const std::map<std::string, std::vector<double>> &timedData) :
timeStamps_(timeStamps), timeResolutionInMinutes_(timeResolutionInMinutes),
scalarData_(scalarData), timedData_(timedData)
switch (scalarData_.at(key).size())
{
// TODO: some coherence check on data
// for example, check that timed data are all of same size = size of timeStamps_
};
[[nodiscard]] std::vector<int> getTimeStamps() const { return timeStamps_; }
[[nodiscard]] int getTimeResolutionInMinutes() const { return timeResolutionInMinutes_; }
[[nodiscard]] bool hasScalarData(const std::string& key) const { return scalarData_.contains(key); }
[[nodiscard]] double getScalarData(const std::string& key) const { return scalarData_.at(key); }
[[nodiscard]] bool hasTimedData(const std::string& key) const { return timedData_.contains(key); }
[[nodiscard]] const std::vector<double>& getTimedData(const std::string& key) const { return timedData_.at(key); }
case 1:
return scalarData_.at(key)[0];
default:
return scalarData_.at(key)[scenario];
}
}
[[nodiscard]] bool hasTimedData(const std::string& key) const
{
return timedData_.contains(key);
}
[[nodiscard]] const std::vector<double>& getTimedData(const std::string& key,
unsigned int scenario) const
{
switch (timedData_.at(key).size())
{
case 1:
return timedData_.at(key)[0];
default:
return timedData_.at(key)[scenario];
}
}

// TODO: remove this when legacy support is dropped
// TODO: meanwhile, instead of having a nested struct, create a daughter class?
struct Legacy {
const std::vector<CORRESPONDANCES_DES_CONTRAINTES>* constraintMapping;
const std::vector<const char*>* areaNames;
};
Legacy legacy;
// TODO: remove this when legacy support is dropped
// TODO: meanwhile, instead of having a nested struct, create a daughter class?
struct Legacy
{
const std::vector<CORRESPONDANCES_DES_CONTRAINTES>* constraintMapping;
const std::vector<const char*>* areaNames;
};
Legacy legacy;
}; // namespace Antares::optim::api

// TODO[FOM] Move to dedicated header file
struct BuildContext final
{
using ScenarioID = unsigned int;
using TimeStampID = int;

[[nodiscard]] std::vector<TimeStampID> getTimeStamps() const
{
return timeStamps;
}

[[nodiscard]] std::vector<ScenarioID> getScenarios() const
{
return scenarios;
}

BuildContext(std::vector<ScenarioID> scenarios, std::vector<TimeStampID> timeStamps) :
scenarios(scenarios), timeStamps(timeStamps)
{
}
const std::vector<ScenarioID> scenarios;
const std::vector<TimeStampID> timeStamps;
};

}
} // namespace Antares::optim::api
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,31 @@

namespace Antares::optim::api
{
class LinearProblemFiller
{
public:
virtual void addVariables(LinearProblem& problem, const LinearProblemData& data) = 0;
virtual void addConstraints(LinearProblem& problem, const LinearProblemData& data) = 0;
virtual void addObjective(LinearProblem& problem, const LinearProblemData& data) = 0;
virtual void update(LinearProblem& problem, const LinearProblemData& data) = 0;
// TODO : see if update is really needed in target solution
// Currently used to update the MIP from week to week by only changing LB/UB & coefs
// (see sim_structure_contrainte_economique.h & ApportNaturelHoraire)
// This may be dropped in the target solution (thus we'll have to re-create the MIP) for 2 reasons:
// - we may have to add/remove variables & constraints
// - OR-Tools does not allow changing the names of variables & constraints, which is necessary if we want the
// variables & constraints to be indexed by the number of the week in the year
virtual ~LinearProblemFiller() = default;
};
}
class LinearProblemFiller
{
public:
virtual void addVariables(LinearProblem& problem,
const LinearProblemData& data,
const BuildContext&)
= 0;
virtual void addConstraints(LinearProblem& problem,
const LinearProblemData& data,
const BuildContext&)
= 0;
virtual void addObjective(LinearProblem& problem,
const LinearProblemData& data,
const BuildContext&)
= 0;
virtual void update(LinearProblem& problem, const LinearProblemData& data) = 0;
// TODO : see if update is really needed in target solution
// Currently used to update the MIP from week to week by only changing LB/UB & coefs
// (see sim_structure_contrainte_economique.h & ApportNaturelHoraire)
// This may be dropped in the target solution (thus we'll have to re-create the MIP) for 2
// reasons:
// - we may have to add/remove variables & constraints
// - OR-Tools does not allow changing the names of variables & constraints, which is necessary
// if we want the
// variables & constraints to be indexed by the number of the week in the year
virtual ~LinearProblemFiller() = default;
};
} // namespace Antares::optim::api
29 changes: 18 additions & 11 deletions src/solver/optim/impl/LinearProblemImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@ LinearProblemImpl::LinearProblemImpl(bool isMip, const std::string& solverName)
this->mpSolver = MPSolverFactory(isMip, solverName);
}


MPVariable& LinearProblemImpl::addNumVariable(string name, double lb, double ub)
{
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints with the same name
// This is pretty dangerous, so we have to forbid it ourselves
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints
// with the same name This is pretty dangerous, so we have to forbid it ourselves
return *mpSolver->MakeNumVar(lb, ub, name);
}

MPVariable& LinearProblemImpl::addIntVariable(string name, double lb, double ub)
{
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints with the same name
// This is pretty dangerous, so we have to forbid it ourselves
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints
// with the same name This is pretty dangerous, so we have to forbid it ourselves
return *mpSolver->MakeIntVar(lb, ub, name);
}

Expand All @@ -34,15 +33,18 @@ MPVariable& LinearProblemImpl::getVariable(string name)

MPConstraint& LinearProblemImpl::addConstraint(string name, double lb, double ub)
{
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints with the same name
// This is pretty dangerous, so we have to forbid it ourselves
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints
// with the same name This is pretty dangerous, so we have to forbid it ourselves
return *mpSolver->MakeRowConstraint(lb, ub, name);
}

MPConstraint& LinearProblemImpl::addBalanceConstraint(string name, double bound, string nodeName, int timestep)
MPConstraint& LinearProblemImpl::addBalanceConstraint(string name,
double bound,
string nodeName,
int timestep)
{
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints with the same name
// This is pretty dangerous, so we have to forbid it ourselves
// TODO: OR-Tools does not seem to care if you try to add two different variables / constraints
// with the same name This is pretty dangerous, so we have to forbid it ourselves
// TODO: log ignored arguments
return this->addConstraint(name, bound, bound);
}
Expand All @@ -63,12 +65,17 @@ void LinearProblemImpl::setObjectiveCoefficient(const MPVariable& variable, doub

void LinearProblemImpl::setMinimization(bool isMinim)
{
isMinim ? mpSolver->MutableObjective()->SetMinimization() : mpSolver->MutableObjective()->SetMaximization();
isMinim ? mpSolver->MutableObjective()->SetMinimization()
: mpSolver->MutableObjective()->SetMaximization();
}

MipSolution LinearProblemImpl::solve(const operations_research::MPSolverParameters& param)
{
mpSolver->EnableOutput();
// std::string model;
// std::ofstream m("/tmp/model.lp");
// if (m && mpSolver->ExportModelAsLpFormat(false, &model))
// m << model;
auto status = mpSolver->Solve(param);
// TODO remove this
// std::string str;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,29 @@ class LinearProblemImpl : public Antares::optim::api::LinearProblem
operations_research::MPSolver* mpSolver{};
// TODO: remove this constructor when legacy support is dropped
LinearProblemImpl();
public :
std::set<std::string> constraintNames_;

public:
LinearProblemImpl(bool isMip, const std::string& solverName);
operations_research::MPVariable& addNumVariable(std::string name, double lb, double ub) override;
operations_research::MPVariable& addIntVariable(std::string name, double lb, double ub) override;
operations_research::MPVariable& addNumVariable(std::string name,
double lb,
double ub) override;
operations_research::MPVariable& addIntVariable(std::string name,
double lb,
double ub) override;
operations_research::MPVariable& getVariable(std::string name) override;
operations_research::MPConstraint& addConstraint(std::string name, double lb, double ub) override;
operations_research::MPConstraint& addBalanceConstraint(std::string name, double bound, std::string nodeName, int timestep) override;
operations_research::MPConstraint& addConstraint(std::string name,
double lb,
double ub) override;
operations_research::MPConstraint& addBalanceConstraint(std::string name,
double bound,
std::string nodeName,
int timestep) override;
operations_research::MPConstraint& getConstraint(std::string name) override;
void setObjectiveCoefficient(const operations_research::MPVariable& variable, double coefficient) override;
void setObjectiveCoefficient(const operations_research::MPVariable& variable,
double coefficient) override;
void setMinimization(bool isMinim) override;
Antares::optim::api::MipSolution solve(const operations_research::MPSolverParameters& param) override;
Antares::optim::api::MipSolution solve(
const operations_research::MPSolverParameters& param) override;
virtual ~LinearProblemImpl() override;
};
Loading
Loading