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

Create standard API and expose ports in legacy code #1987

Draft
wants to merge 2 commits into
base: poc_linearProblem
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions src/solver/optim/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
add_subdirectory(api)
add_subdirectory(impl)
add_subdirectory(standard_api)
23 changes: 0 additions & 23 deletions src/solver/optim/standard/CMakeLists.txt

This file was deleted.

25 changes: 25 additions & 0 deletions src/solver/optim/standard_api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
set(PROJ optim_standard_api
)
set(HEADERS
include/antares/optim/standard_api/Component.h
include/antares/optim/standard_api/ComponentFiller.h
include/antares/optim/standard_api/PortHolder.h
include/antares/optim/standard_api/PortConnection.h
)
set(SRC_OPTIM
${HEADERS}
ComponentFiller.cpp
)
source_group("solver\\optim\\standard_api" FILES ${SRC_OPTIM})

add_library(${PROJ} ${SRC_OPTIM})
add_library(Antares::${PROJ} ALIAS ${PROJ})

target_link_libraries(${PROJ}
Antares::optim_api
)

target_include_directories(${PROJ}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
Original file line number Diff line number Diff line change
@@ -1,44 +1,21 @@
#pragma once

#include "vector"
#include "antares/optim/api/LinearProblemFiller.h"
#include "Component.h"
#include "PortConnection.h"
#include "include/antares/optim/standard_api/ComponentFiller.h"

using namespace Antares::optim::api;
using namespace Antares::optim::standard_api;
using namespace std;

class ComponentFiller : public LinearProblemFiller
{
private:
PortConnectionsManager* portConnectionsManager_;
Component component_;
[[nodiscard]] map<string, double> getPortPin(string name, int timestamp, const LinearProblemData& linearProblemData) const;
public:
ComponentFiller(Component component, PortConnectionsManager &portConnectionsManager) :
portConnectionsManager_(&portConnectionsManager), component_(std::move(component))
{}
void addVariables(LinearProblem &problem, const LinearProblemData &data) override;
void addConstraints(LinearProblem &problem, const LinearProblemData &data) override;
void addObjective(LinearProblem &problem, const LinearProblemData &data) override;
void update(LinearProblem &problem, const LinearProblemData &data) override;
};

void ComponentFiller::addVariables(LinearProblem& problem, const LinearProblemData& data)
void ComponentFiller::addVariables(LinearProblem &problem, const LinearProblemData &data)
{
// TODO : remplacer par des AST
if (component_.getModel() == THERMAL)
{
for (auto ts : data.getTimeStamps()) {
if (component_.getModel() == THERMAL) {
for (auto ts: data.getTimeStamps()) {
string pVarName = "P_" + component_.getId() + "_" + to_string(ts);
double maxP = component_.getDoubleParameterValue("maxP");
problem.addNumVariable(pVarName, 0, maxP);
}
}
else if (component_.getModel() == BATTERY)
{
} else if (component_.getModel() == BATTERY) {
auto timestamps = data.getTimeStamps();
for (auto ts : timestamps) {
for (auto ts: timestamps) {
// P < 0 : charge
// P > 0 : décharge
string pVarName = "P_" + component_.getId() + "_" + to_string(ts);
Expand All @@ -52,15 +29,15 @@ void ComponentFiller::addVariables(LinearProblem& problem, const LinearProblemDa
}
}

void ComponentFiller::addConstraints(LinearProblem& problem, const LinearProblemData& data)
void ComponentFiller::addConstraints(LinearProblem &problem, const LinearProblemData &data)
{
// TODO : remplacer par des AST
if (component_.getModel() == BATTERY) {
if (!data.hasScalarData("initialStock_" + component_.getId())) {
throw;
}
double initialStock = data.getScalarData("initialStock_" + component_.getId());
for (auto ts : data.getTimeStamps()) {
for (auto ts: data.getTimeStamps()) {
string pVarName = "P_" + component_.getId() + "_" + to_string(ts);
auto p = &problem.getVariable(pVarName);
string stockVarName = "Stock_" + component_.getId() + "_" + to_string(ts);
Expand All @@ -70,33 +47,30 @@ void ComponentFiller::addConstraints(LinearProblem& problem, const LinearProblem
auto stockConstraint = &problem.addConstraint("Stock_constr_" + to_string(ts), 0, 0);
stockConstraint->SetCoefficient(e, 1);
stockConstraint->SetCoefficient(p, data.getTimeResolutionInMinutes() * 1.0 / 60.0);
if (ts > 0)
{
if (ts > 0) {
string stockVarNameTm1 = "Stock_" + component_.getId() + "_" + to_string(ts - 1);
auto previousE = &problem.getVariable(stockVarNameTm1);
stockConstraint->SetCoefficient(previousE, -1);
}
else
{
} else {
stockConstraint->SetLB(initialStock);
stockConstraint->SetUB(initialStock);
}
}
}
else if (component_.getModel() == BALANCE) {
} else if (component_.getModel() == BALANCE) {
string nodeName = component_.getStringParameterValue("nodeName");
if (!data.hasTimedData("consumption_" + nodeName)) {
throw;
}
auto consumption = data.getTimedData("consumption_" + nodeName);
for (auto ts : data.getTimeStamps()) {
for (auto ts: data.getTimeStamps()) {
// <!> IMPORTANT : we have to use the convention -production = -consumption, in order to be compatible
// with the legacy code's balance constraint
auto balanceConstraint =
&problem.addBalanceConstraint("Balance_" + nodeName + "_" + to_string(ts), -consumption[ts], nodeName, ts);
for (const auto& connection : portConnectionsManager_->getConectionsTo(this, "P")) {
for (const auto& varAndCoeff : connection.componentFiller->getPortPin(connection.portName, ts, data))
{
&problem.addBalanceConstraint("Balance_" + nodeName + "_" + to_string(ts), -consumption[ts],
nodeName, ts);
for (const auto &connection: portConnectionsManager_->getConnectionsTo(this, "P")) {
for (const auto &varAndCoeff: connection.connectableFiller->getPortPin(connection.portName, ts,
data)) {
auto p = &problem.getVariable(varAndCoeff.first);
balanceConstraint->SetCoefficient(p, varAndCoeff.second * -1.0);
}
Expand All @@ -105,15 +79,15 @@ void ComponentFiller::addConstraints(LinearProblem& problem, const LinearProblem
}
}

void ComponentFiller::addObjective(Antares::optim::api::LinearProblem& problem, const LinearProblemData& data)
void ComponentFiller::addObjective(Antares::optim::api::LinearProblem &problem, const LinearProblemData &data)
{
// TODO : remplacer par des AST
if (component_.getModel() == PRICE_MINIM) {
problem.setMinimization(true);
for (auto ts : data.getTimeStamps()) {
for (const auto& connection : portConnectionsManager_->getConectionsTo(this, "cost")) {
for (const auto& varAndCoeff : connection.componentFiller->getPortPin(connection.portName, ts, data))
{
for (auto ts: data.getTimeStamps()) {
for (const auto &connection: portConnectionsManager_->getConnectionsTo(this, "cost")) {
for (const auto &varAndCoeff: connection.connectableFiller->getPortPin(connection.portName, ts,
data)) {
auto variable = &problem.getVariable(varAndCoeff.first);
problem.setObjectiveCoefficient(*variable, varAndCoeff.second);
}
Expand All @@ -122,12 +96,12 @@ void ComponentFiller::addObjective(Antares::optim::api::LinearProblem& problem,
}
}

void ComponentFiller::update(Antares::optim::api::LinearProblem& problem, const LinearProblemData& data)
void ComponentFiller::update(Antares::optim::api::LinearProblem &problem, const LinearProblemData &data)
{
// ?
}

map<string, double> ComponentFiller::getPortPin(string name, int timestamp, const LinearProblemData& data) const
map<string, double> ComponentFiller::getPortPin(string name, int timestamp, const LinearProblemData &data) const
{
// TODO : remplacer par des AST
if (component_.getModel() == THERMAL) {
Expand All @@ -148,4 +122,4 @@ map<string, double> ComponentFiller::getPortPin(string name, int timestamp, cons
}
}
return {};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "string"
#include "map"

namespace Antares::optim::standard_api
{
enum Model
{
THERMAL,
BATTERY,
BALANCE,
PRICE_MINIM
};

class Component
{
private:
std::string id_;
Model model_;
std::map<std::string, double> doubleParameterValues_;
std::map<std::string, std::string> stringParameterValues_;
public:
Component(std::string id, Model model, std::map<std::string, double> doubleParameterValues,
std::map<std::string, std::string> stringParameterValues) : id_(std::move(id)), model_(model),
doubleParameterValues_(std::move(doubleParameterValues)),
stringParameterValues_(std::move(stringParameterValues))
{}

[[nodiscard]] std::string getId() const
{ return id_; }

[[nodiscard]] Model getModel() const
{ return model_; }

[[nodiscard]] double getDoubleParameterValue(const std::string &key) const
{ return doubleParameterValues_.at(key); }

[[nodiscard]] std::string getStringParameterValue(const std::string &key) const
{ return stringParameterValues_.at(key); }
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include "antares/optim/api/LinearProblemFiller.h"
#include "Component.h"
#include "PortConnection.h"

namespace Antares::optim::standard_api
{
class ComponentFiller : public Antares::optim::api::LinearProblemFiller, public PortHolder
{
private:
PortConnectionsManager *portConnectionsManager_;
Component component_;
public:
ComponentFiller(Component component, PortConnectionsManager &portConnectionsManager) :
portConnectionsManager_(&portConnectionsManager), component_(std::move(component))
{}

void addVariables(Antares::optim::api::LinearProblem &problem, const Antares::optim::api::LinearProblemData &data) override;

void addConstraints(Antares::optim::api::LinearProblem &problem, const Antares::optim::api::LinearProblemData &data) override;

void addObjective(Antares::optim::api::LinearProblem &problem, const Antares::optim::api::LinearProblemData &data) override;

void update(Antares::optim::api::LinearProblem &problem, const Antares::optim::api::LinearProblemData &data) override;

[[nodiscard]] std::map<std::string, double>
getPortPin(std::string name, int timestamp, const Antares::optim::api::LinearProblemData &linearProblemData) const override;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once

#include "vector"
#include "string"
#include "PortHolder.h"

// TODO: move this to optim::api?
namespace Antares::optim::standard_api
{
struct FillerAndPort
{
std::shared_ptr<PortHolder> connectableFiller;
std::string portName;
};

class PortConnection
{
private:
FillerAndPort fillerAndPort1; // TODO : à terme, ne pas référencer directement des fillers
FillerAndPort fillerAndPort2;
public:
PortConnection(FillerAndPort fillerAndPort1, FillerAndPort fillerAndPort2)
: fillerAndPort1(std::move(fillerAndPort1)), fillerAndPort2(std::move(fillerAndPort2))
{}

[[nodiscard]] FillerAndPort getFillerAndPort1() const
{ return fillerAndPort1; }

[[nodiscard]] FillerAndPort getFillerAndPort2() const
{ return fillerAndPort2; }
};

class PortConnectionsManager
{
private:
std::vector<PortConnection> connections;
public:
void addConnection(FillerAndPort fillerAndPort1, FillerAndPort fillerAndPort2)
{
connections.emplace_back(std::move(fillerAndPort1), std::move(fillerAndPort2));
}

std::vector<FillerAndPort>
getConnectionsTo(PortHolder *connectableFiller, const std::string &portId)
{
// TODO: implement a better search algorithm
std::vector<FillerAndPort> connectedComponents;
for (const auto &c: connections) {
if (c.getFillerAndPort1().connectableFiller.get() == connectableFiller
&& c.getFillerAndPort1().portName == portId) {
connectedComponents.emplace_back(c.getFillerAndPort2());
} else if (c.getFillerAndPort2().connectableFiller.get() == connectableFiller
&& c.getFillerAndPort2().portName == portId) {
connectedComponents.emplace_back(c.getFillerAndPort1());
}
}
return connectedComponents;
}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

// TODO: merge this into LinearProblemFiller API ?
namespace Antares::optim::standard_api
{
class PortHolder
{
public:
// Returns the linear expression of a port's pin
// port pin = sum(keys * values), key being the ID of a variable in the MIP
[[nodiscard]] virtual std::map<std::string, double> getPortPin(std::string name, int timestamp,
const Antares::optim::api::LinearProblemData &linearProblemData) const = 0;
};
}
32 changes: 0 additions & 32 deletions src/tests/poc/include/standard/Component.h

This file was deleted.

Loading
Loading