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

For short-term storage cumulative constraints #2546

Open
wants to merge 13 commits into
base: develop
Choose a base branch
from
4 changes: 2 additions & 2 deletions src/libs/antares/study/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ set(SRC_STUDY_PART_SHORT_TERM_STORAGE
parts/short-term-storage/series.cpp
include/antares/study/parts/short-term-storage/series.h
include/antares/study/parts/short-term-storage/cluster.h
include/antares/study/parts/short-term-storage/AdditionalConstraint.h
include/antares/study/parts/short-term-storage/AdditionalConstraints.h
parts/short-term-storage/cluster.cpp
parts/short-term-storage/AdditionalConstraint.cpp
parts/short-term-storage/AdditionalConstraints.cpp
)
source_group("study\\part\\short-term-storage" FILES ${SRC_STUDY_PART_SHORT_TERM_SOTRAGE})

Expand Down
10 changes: 6 additions & 4 deletions src/libs/antares/study/area/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,12 +1194,14 @@ bool AreaList::loadFromFolder(const StudyLoadOptions& options)

if (fs::exists(stsFolder))
{
for (const auto& [id, area]: areas)
for (const auto& area: areas | std::views::values)
{
fs::path folder = stsFolder / "clusters" / area->id.c_str();
fs::path cluster_folder = stsFolder / "clusters" / area->id.c_str();
ret = area->shortTermStorage.createSTStorageClustersFromIniFile(cluster_folder) &&
ret;

ret = area->shortTermStorage.createSTStorageClustersFromIniFile(folder) && ret;
ret = area->shortTermStorage.LoadConstraintsFromIniFile(folder) && ret;
const auto constraints_folder = stsFolder / "constraints" / area->id.c_str();
ret = area->shortTermStorage.LoadConstraintsFromIniFile(constraints_folder) && ret;
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,30 @@
#pragma once
#include <set>
#include <string>
#include <vector>

namespace Antares::Data::ShortTermStorage
{
struct SingleAdditionalConstraint
{
std::set<int> hours;
unsigned int globalIndex = 0;
unsigned int localIndex = 0;

bool isValidHoursRange() const;
};

struct AdditionalConstraint
struct AdditionalConstraints
{
std::string name;
std::string cluster_id;
std::string variable;
std::string operatorType;
std::set<int> hours;
double rhs;
// TODO a lot unused entries
//std::array<double, HOURS_PER_YEAR> rhs = {};
std::vector<double> rhs = {};

unsigned int globalIndex = 0;
std::vector<SingleAdditionalConstraint> constraints = {};

struct ValidateResult
{
Expand All @@ -48,6 +58,7 @@ struct AdditionalConstraint
private:
bool isValidVariable() const;
bool isValidOperatorType() const;
bool isValidHoursRange() const;

bool isValidHours() const;
};
} // namespace Antares::Data::ShortTermStorage
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

#include <antares/inifile/inifile.h>

#include "AdditionalConstraint.h"
#include "AdditionalConstraints.h"
#include "properties.h"
#include "series.h"

Expand All @@ -51,6 +51,6 @@ class STStorageCluster

std::shared_ptr<Series> series = std::make_shared<Series>();
mutable Properties properties;
std::vector<AdditionalConstraint> additional_constraints;
std::vector<AdditionalConstraints> additional_constraints;
};
} // namespace Antares::Data::ShortTermStorage
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <filesystem>
#include <string>

#include "AdditionalConstraint.h"
#include "cluster.h"

namespace Antares::Data::ShortTermStorage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ class Series

bool loadFile(const std::filesystem::path& folder, std::vector<double>& vect);
bool writeVectorToFile(const std::string& path, const std::vector<double>& vect);

void fillIfEmpty(std::vector<double>& v, double value);
} // namespace Antares::Data::ShortTermStorage
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
** You should have received a copy of the Mozilla Public Licence 2.0
** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
*/
#include "antares/study/parts/short-term-storage/AdditionalConstraint.h"
#include "antares/study/parts/short-term-storage/AdditionalConstraints.h"
#include <algorithm>

namespace Antares::Data::ShortTermStorage
{
AdditionalConstraint::ValidateResult AdditionalConstraint::validate() const
AdditionalConstraints::ValidateResult AdditionalConstraints::validate() const
{
if (cluster_id.empty())
{
Expand All @@ -39,26 +40,38 @@ AdditionalConstraint::ValidateResult AdditionalConstraint::validate() const
return {false, "Invalid operator type. Must be 'less', 'equal', or 'greater'."};
}

if (!isValidHoursRange())
if (!isValidHours())
{
return {false, "Hours set contains invalid values. Must be between 1 and 168."};
return {false, "Hours sets contains invalid values. Must be between 1 and 168."};
}

return {true, ""};
}

bool AdditionalConstraint::isValidHoursRange() const
bool SingleAdditionalConstraint::isValidHoursRange() const
{
// `hours` is a sorted set; begin() gives the smallest and prev(end()) gives the largest.
return !hours.empty() && *hours.begin() >= 1 && *std::prev(hours.end()) <= 168;
return !hours.empty() && *hours.begin()
>= 1 && *std::prev(
hours.end()) <= 168;
}

bool AdditionalConstraint::isValidVariable() const
bool AdditionalConstraints::isValidHours() const
{
return std::ranges::all_of(constraints.begin(),
constraints.end(),
[](const auto& constraint)
{
return constraint.isValidHoursRange();
});
}


bool AdditionalConstraints::isValidVariable() const
{
return variable == "injection" || variable == "withdrawal" || variable == "netting";
}

bool AdditionalConstraint::isValidOperatorType() const
bool AdditionalConstraints::isValidOperatorType() const
{
return operatorType == "less" || operatorType == "equal" || operatorType == "greater";
}
Expand Down
92 changes: 69 additions & 23 deletions src/libs/antares/study/parts/short-term-storage/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <algorithm>
#include <numeric>
#include <regex>
#include <string>

#include <yuni/io/file.h>
Expand Down Expand Up @@ -87,8 +88,8 @@ bool STStorageInput::LoadConstraintsFromIniFile(const fs::path& parent_path)

for (auto* section = ini.firstSection; section; section = section->next)
{
AdditionalConstraint constraint;
constraint.name = section->name.c_str();
AdditionalConstraints additional_constraints;
additional_constraints.name = section->name.c_str();
for (auto* property = section->firstProperty; property; property = property->next)
{
const std::string key = property->key;
Expand All @@ -99,43 +100,77 @@ bool STStorageInput::LoadConstraintsFromIniFile(const fs::path& parent_path)
// TODO do i have to transform the name to id? TransformNameIntoID
std::string clusterName;
value.to<std::string>(clusterName);
constraint.cluster_id = transformNameIntoID(clusterName);
additional_constraints.cluster_id = transformNameIntoID(clusterName);
}
else if (key == "variable")
{
value.to<std::string>(constraint.variable);
value.to<std::string>(additional_constraints.variable);
}
else if (key == "operator")
{
value.to<std::string>(constraint.operatorType);
value.to<std::string>(additional_constraints.operatorType);
}
else if (key == "hours")
{
std::stringstream ss(value.c_str());
std::string hour;
while (std::getline(ss, hour, ','))
//
// std::stringstream ss(value.c_str());
// std::string hour;
// while (std::getline(ss, hour, ','))
// {
// int hourVal = std::stoi(hour);
// constraint.hours.insert(hourVal);
// }

// Split the `hours` field into multiple groups
std::string hoursStr = value.c_str();
std::regex groupRegex(R"(\[(.*?)\])");
// Match each group enclosed in square brackets
auto groupsBegin = std::sregex_iterator(hoursStr.begin(),
hoursStr.end(),
groupRegex);
auto groupsEnd = std::sregex_iterator();
unsigned int localIndex = 0;
for (auto it = groupsBegin; it != groupsEnd; ++it)
{
int hourVal = std::stoi(hour);
constraint.hours.insert(hourVal);
// Extract the contents of the square brackets
std::string group = (*it)[1].str();
std::stringstream ss(group);
std::string hour;
std::set<int> hourSet;

while (std::getline(ss, hour, ','))
{
int hourVal = std::stoi(hour);
hourSet.insert(hourVal);
}
if (!hourSet.empty())
{
// Add this group to the `hours` vec
additional_constraints.constraints.push_back(
{.hours = hourSet, .localIndex = localIndex});
++localIndex;
}
}
}
else if (key == "rhs")
{
property->value.to<double>(constraint.rhs);
}
}

if (auto ret = constraint.validate(); !ret.ok)
// try to read the rhs
loadFile(parent_path / ("rhs_" + additional_constraints.name + ".txt"),
additional_constraints.rhs);
fillIfEmpty(additional_constraints.rhs, 0.0);

if (auto [ok, error_msg] = additional_constraints.validate(); !ok)
{
logs.error() << "Invalid constraint in section: " << section->name;
logs.error() << ret.error_msg;
logs.error() << error_msg;
return false;
}

auto it = std::find_if(storagesByIndex.begin(),
storagesByIndex.end(),
[&constraint](const STStorageCluster& cluster)
{ return cluster.id == constraint.cluster_id; });
auto it = std::ranges::find_if(storagesByIndex,
[&additional_constraints](const STStorageCluster& cluster)
{
return cluster.id == additional_constraints.cluster_id;
});
if (it == storagesByIndex.end())
{
logs.warning() << " from file " << pathIni;
Expand All @@ -145,7 +180,7 @@ bool STStorageInput::LoadConstraintsFromIniFile(const fs::path& parent_path)
}
else
{
it->additional_constraints.push_back(constraint);
it->additional_constraints.push_back(additional_constraints);
}
}

Expand Down Expand Up @@ -197,8 +232,19 @@ std::size_t STStorageInput::cumulativeConstraintCount() const
return std::accumulate(storagesByIndex.begin(),
storagesByIndex.end(),
0,
[](int acc, const auto& cluster)
{ return acc + cluster.additional_constraints.size(); });
[](size_t outer_constraint_count, const auto& cluster)
{
return outer_constraint_count + std::accumulate(
cluster.additional_constraints.begin(),
cluster.additional_constraints.end(),
0,
[](size_t inner_constraint_count,
const auto& additional_constraints)
{
return inner_constraint_count +
additional_constraints.constraints.size();
});
});
}

std::size_t STStorageInput::count() const
Expand Down
14 changes: 7 additions & 7 deletions src/libs/antares/study/parts/short-term-storage/series.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,16 @@ bool loadFile(const fs::path& path, std::vector<double>& vect)
return true;
}

void Series::fillDefaultSeriesIfEmpty()
void fillIfEmpty(std::vector<double>& v, double value)
{
auto fillIfEmpty = [](std::vector<double>& v, double value)
if (v.empty())
{
if (v.empty())
{
v.resize(HOURS_PER_YEAR, value);
}
};
v.resize(HOURS_PER_YEAR, value);
}
};

void Series::fillDefaultSeriesIfEmpty()
{
fillIfEmpty(maxInjectionModulation, 1.0);
fillIfEmpty(maxWithdrawalModulation, 1.0);
fillIfEmpty(inflows, 0.0);
Expand Down
35 changes: 20 additions & 15 deletions src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,28 +130,33 @@ void ShortTermStorageCumulation::add(int pays)

for (const auto& storage: data.ShortTermStorage[pays])
{
for (const auto& constraint: storage.additional_constraints)
for (const auto& additional_constraints: storage.additional_constraints)
{
// sum (var[h]) sign rhs, h in list provided by user where:
// var = injection for InjectionCumulationConstraint
// var = withdrawal for WithdrawalCumulationConstraint
// var = injectionEfficiency * injection - withdrawalEfficiency * withdrawal for Netting
auto constraintHelper = cumulationConstraintFromVariable(constraint.variable);
namer.ShortTermStorageCumulation(constraintHelper->name(),
builder.data.nombreDeContraintes,
storage.name,
constraint.name);
const auto index = storage.clusterGlobalIndex;
data.CorrespondanceCntNativesCntOptimHebdomadaires
.ShortTermStorageCumulation[constraint.globalIndex]
= builder.data.nombreDeContraintes;

for (const auto& hour: constraint.hours)
auto constraintHelper = cumulationConstraintFromVariable(
additional_constraints.variable);
for (const auto& [hours, globalIndex, localIndex]: additional_constraints.constraints)
{
builder.updateHourWithinWeek(hour - 1);
constraintHelper->build(builder, index, storage);
namer.ShortTermStorageCumulation(
constraintHelper->name(),
builder.data.nombreDeContraintes,
storage.name,
additional_constraints.name + "_" + std::to_string(localIndex));
const auto index = storage.clusterGlobalIndex;
data.CorrespondanceCntNativesCntOptimHebdomadaires
.ShortTermStorageCumulation[globalIndex]
= builder.data.nombreDeContraintes;

for (const auto& hour: hours)
{
builder.updateHourWithinWeek(hour - 1);
constraintHelper->build(builder, index, storage);
}
builder.SetOperator(ConvertSense(additional_constraints.operatorType)).build();
}
builder.SetOperator(ConvertSense(constraint.operatorType)).build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,11 @@ int OPT_DecompteDesVariablesEtDesContraintesDuProblemeAOptimiser(PROBLEME_HEBDO*
}
if (!storage.additional_constraints.empty())
{
ProblemeAResoudre->NombreDeContraintes += storage.additional_constraints.size();
for (const auto& additional_constraints: storage.additional_constraints)
{
ProblemeAResoudre->NombreDeContraintes += additional_constraints.constraints
.size();
}
}
}
}
Expand Down
Loading
Loading