Skip to content

Commit

Permalink
Increment variable names every week (#956)
Browse files Browse the repository at this point in the history
- When using ortools in anatres-solver, variables index is reset to zero
every week. This PR allows the usage of that mode in xpansion by
incremeting the variable index using the week index.
- Also, ortools is now activated
  • Loading branch information
pet-mit authored Oct 25, 2024
1 parent a977075 commit fba823e
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/cpp/lpnamer/model/Problem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
#include "antares-xpansion/lpnamer/model/ProblemNameParser.h"

void Problem::read_prob_mps(const std::filesystem::path& filename) {
mc_year = MCYear(filename);
std::tie(mc_year, week) = McYearAndWeek(filename);
solver_abstract_->read_prob_mps(filename);
}
14 changes: 8 additions & 6 deletions src/cpp/lpnamer/model/ProblemNameParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
#include <boost/tokenizer.hpp>
#include "antares-xpansion/lpnamer/model/ProblemNameParser.h"

unsigned int MCYear(const std::filesystem::path &file_path) {
return MCYear(file_path.filename().string());
std::pair<unsigned int, unsigned int> McYearAndWeek(const std::filesystem::path &file_path) {
return McYearAndWeek(file_path.filename().string());
}
unsigned int MCYear(const std::string &problem_file_name) {
std::pair<unsigned int, unsigned int> McYearAndWeek(const std::string &problem_file_name) {
boost::tokenizer<> tok(problem_file_name);
auto prefix = tok.begin();
std::string year = *(++prefix);
unsigned int mc_year = std::stoi(year);
return mc_year;
std::string str = *(++prefix);
unsigned int mc_year = std::stoi(str);
str = *(++prefix);
unsigned int week = std::stoi(str);
return {mc_year, week};
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ class Problem : public SolverAbstract {

public:
[[nodiscard]] unsigned int McYear() const { return mc_year; }
[[nodiscard]] unsigned int Week() const { return week; }

unsigned int mc_year = 0;
unsigned int week = 0;

int get_number_of_instances() override {
return solver_abstract_->get_number_of_instances();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
#include <filesystem>
#include <cstring>

unsigned int MCYear(const std::string &problem_file_name);
unsigned int MCYear(const std::filesystem::path &file_path);

std::pair<unsigned int, unsigned int> McYearAndWeek(const std::string &problem_file_name);
std::pair<unsigned int, unsigned int> McYearAndWeek(const std::filesystem::path &file_path);

#endif // ANTARESXPANSION_TESTS_CPP_LP_NAMER_PROBLEMCONSTRUCTIONTEST_CPP_PROBLEMNAMEPARSER_H_
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

#include "antares-xpansion/xpansion_interfaces/LogUtils.h"
#include "antares-xpansion/multisolver_interface/SolverFactory.h"
#include "antares-xpansion/helpers/solver_utils.h"

/**
*
Expand All @@ -26,6 +25,8 @@ AntaresProblemToXpansionProblemTranslator::translateToXpansionProblem(
auto constant = lps.constantProblemData;
auto hebdo = lps.weeklyProblems.at({year, week});
problem->_name = hebdo.name;
problem->mc_year = year;
problem->week = week;

std::vector<int> tmp(constant.VariablesCount, 0);
std::vector<char> coltypes(constant.VariablesCount, 'C');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// Created by marechaljas on 09/11/22.
//

#include <utility>

#include "antares-xpansion/lpnamer/problem_modifier/ProblemVariablesFromProblemAdapter.h"

#include <utility>

const std::string SEPARATOR = "::";
const std::string AREA_SEPARATOR = "$$";
const char WITHESPACESUBSTITUTE = '*';
Expand Down Expand Up @@ -34,9 +34,16 @@ void ReadLinkZones(const std::string& input, std::string& origin,
' ');
}

int ReadTimeStep(const std::string& input) {
int ReadTimeStep(const std::string& input, const unsigned int week) {
// input format should be x<timeStep>
return std::stoi(StringBetweenChevrons(input));
int timestep_in_problem = std::stoi(StringBetweenChevrons(input));
// Two possible cases:
// - either index is yearly (starts at (week-1)*167) => nothing to do
// - or the index is weekly (starts at 0) => it needs to be shifted by +(week-1)*167
if (timestep_in_problem < (week - 1) * 168) {
timestep_in_problem += (week - 1) * 168;
}
return timestep_in_problem;
}

void updateMapColumn(const std::vector<ActiveLink>& links,
Expand Down Expand Up @@ -90,17 +97,20 @@ void ProblemVariablesFromProblemAdapter::extract_variables(
ReadLinkZones(split_name[1], origin, destination);

updateMapColumn(active_links_, origin, destination, var_index,
ReadTimeStep(split_name[2]), p_ntc_columns);
ReadTimeStep(split_name[2], problem_->Week()),
p_ntc_columns);
} else if (split_name[0] ==
variable_name_config.cost_origin_variable_name) {
ReadLinkZones(split_name[1], origin, destination);
updateMapColumn(active_links_, origin, destination, var_index,
ReadTimeStep(split_name[2]), p_direct_cost_columns);
ReadTimeStep(split_name[2], problem_->Week()),
p_direct_cost_columns);
} else if (split_name[0] ==
variable_name_config.cost_extremite_variable_name) {
ReadLinkZones(split_name[1], origin, destination);
updateMapColumn(active_links_, origin, destination, var_index,
ReadTimeStep(split_name[2]), p_indirect_cost_columns);
ReadTimeStep(split_name[2], problem_->Week()),
p_indirect_cost_columns);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/python/antares_xpansion/antares_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ def _set_simulation_name(self):
self.simulation_name = list_of_dirs[-1]

def _get_antares_cmd(self):
cmd = [str(self.antares_exe_path), self.data_dir, self.ANTARES_N_CPU_OPTION, str(self.antares_n_cpu), self.zip_option]
cmd = [str(self.antares_exe_path), self.data_dir, self.ANTARES_N_CPU_OPTION, str(self.antares_n_cpu), self.zip_option,
"--use-ortools", "--ortools-solver=sirius"]
simulator_version = version.parse(__antares_simulator_version__)
simulator_version_with_named_mps = version.parse(self.FIRST_VERSION_WITH_NAMED_PROBLEMS)
if (simulator_version.major > simulator_version_with_named_mps.major) or (simulator_version.major >= simulator_version_with_named_mps.major and simulator_version.minor >= simulator_version_with_named_mps.minor):
Expand Down
1 change: 1 addition & 0 deletions tests/cpp/lp_namer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ add_executable (lp_namer_tests
MpsTxtWriterTest.cpp
AntaresProblemToXpansionProblemTranslatorTest.cpp
GeneralDataReadetTests.cpp
ProblemVariablesFromProblemAdapterTest.cpp
)

target_link_libraries (lp_namer_tests PRIVATE
Expand Down
17 changes: 10 additions & 7 deletions tests/cpp/lp_namer/ProblemConstructionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <filesystem>
#include "antares-xpansion/lpnamer/model/ProblemNameParser.h"
#include "antares-xpansion/lpnamer/model/Problem.h"
#include "antares-xpansion/multisolver_interface/SolverFactory.h"
#include "NOOPSolver.h"

struct ProblemNameCase {
Expand All @@ -19,10 +18,11 @@ class ProblemConstructionTest: public testing::TestWithParam<ProblemNameCase> {
};

TEST_F(ProblemConstructionTest, ExtractMCYear1FromName) {
std::string file_name = "problem-1-1-20220214-124051.mps";
std::string file_name = "problem-1-37-20220214-124051.mps";

unsigned int res = MCYear(file_name);
EXPECT_EQ(res, 1);
auto [year, week] = McYearAndWeek(file_name);
EXPECT_EQ(year, 1);
EXPECT_EQ(week, 37);
}

ProblemNameCase cases[] = {
Expand All @@ -33,15 +33,17 @@ ProblemNameCase cases[] = {
};
TEST_P(ProblemConstructionTest, ExtractSeveralFileNameCase) {
auto const& input = GetParam();
EXPECT_EQ(MCYear(input.problem_name), input.expected_mc_year);
EXPECT_EQ(McYearAndWeek(input.problem_name).first, input.expected_mc_year);
}
INSTANTIATE_TEST_SUITE_P(BulkTest, ProblemConstructionTest,
testing::ValuesIn(cases));

TEST_F(ProblemConstructionTest, ExtractMCYearFromPath) {
std::filesystem::path path = std::filesystem::path("path") / "To" / "inner-dir" / "problem-2-1-20220214-124051.mps";
std::filesystem::path path = std::filesystem::path("path") / "To" / "inner-dir" / "problem-2-10-20220214-124051.mps";

EXPECT_EQ(MCYear(path), 2);
auto [year, week] = McYearAndWeek(path);
EXPECT_EQ(year, 2);
EXPECT_EQ(week, 10);
}


Expand All @@ -52,4 +54,5 @@ TEST_F(ProblemConstructionTest, McYearAvailableInProblem) {
std::filesystem::path file_name("Path/To/inner-dir/problem-3-45-20220214-124051.mps");
problem->read_prob_mps(file_name);
EXPECT_EQ(problem->McYear(), 3);
EXPECT_EQ(problem->Week(), 45);
}
103 changes: 103 additions & 0 deletions tests/cpp/lp_namer/ProblemVariablesFromProblemAdapterTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// Created by mitripet on 24/10/24.
//

#include <gtest/gtest.h>

#include "LoggerBuilder.h"
#include "antares-xpansion/lpnamer/problem_modifier/FileProblemProviderAdapter.h"
#include "antares-xpansion/lpnamer/problem_modifier/ProblemVariablesFromProblemAdapter.h"

std::string mpsWithIndexStartingAt0() {
return R"(NAME MINIMIP
ROWS
N OBJ
COLUMNS
NTCDirect::link<area1$$area2>::v0<0> OBJ -5.0
NTCDirect::link<area1$$area2>::v1<1> OBJ -4.0
IntercoDirectCost::link<area1$$area2>::v2<2> OBJ -5.0
IntercoDirectCost::link<area1$$area2>::v3<3> OBJ -4.0
IntercoIndirectCost::link<area1$$area2>::v4<1> OBJ -5.0
IntercoIndirectCost::link<area1$$area2>::v5<3> OBJ -4.0
ENDATA)";
}

std::string mpsWithIndexStartingAt168() {
return R"(NAME MINIMIP
ROWS
N OBJ
COLUMNS
NTCDirect::link<area1$$area2>::v0<168> OBJ -5.0
NTCDirect::link<area1$$area2>::v1<169> OBJ -4.0
IntercoDirectCost::link<area1$$area2>::v2<170> OBJ -5.0
IntercoDirectCost::link<area1$$area2>::v3<171> OBJ -4.0
IntercoIndirectCost::link<area1$$area2>::v4<169> OBJ -5.0
IntercoIndirectCost::link<area1$$area2>::v5<171> OBJ -4.0
ENDATA)";
}

ProblemVariables provideVariables(std::string problem_name, std::string mps) {
auto mps_path = std::filesystem::temp_directory_path() / problem_name;
std::ofstream writer(mps_path);
writer << mps;
writer.close();
auto solverLogger = SolverLogManager();
FileProblemProviderAdapter problem_provider(mps_path, problem_name);
auto problem = problem_provider.provide_problem("XPRESS", solverLogger);
auto logger = emptyLogger();
ActiveLink al(0, "area1 - area2", "area1", "area2", 0, logger);
ProblemVariablesFromProblemAdapter variables_provider(problem, {al},
emptyLogger());
return variables_provider.Provide();
}

void checkVarTimeSteps(ProblemVariables vars,
std::vector<int> expected_timesteps) {
EXPECT_EQ(vars.ntc_columns.size(), 1);
EXPECT_EQ(vars.ntc_columns.at(0).size(), 2);
EXPECT_EQ(vars.ntc_columns.at(0).at(0),
ColumnToChange(0, expected_timesteps[0]));
EXPECT_EQ(vars.ntc_columns.at(0).at(1),
ColumnToChange(1, expected_timesteps[1]));

EXPECT_EQ(vars.direct_cost_columns.size(), 1);
EXPECT_EQ(vars.direct_cost_columns.at(0).size(), 2);
EXPECT_EQ(vars.direct_cost_columns.at(0).at(0),
ColumnToChange(2, expected_timesteps[2]));
EXPECT_EQ(vars.direct_cost_columns.at(0).at(1),
ColumnToChange(3, expected_timesteps[3]));

EXPECT_EQ(vars.indirect_cost_columns.size(), 1);
EXPECT_EQ(vars.indirect_cost_columns.at(0).size(), 2);
EXPECT_EQ(vars.indirect_cost_columns.at(0).at(0),
ColumnToChange(4, expected_timesteps[4]));
EXPECT_EQ(vars.indirect_cost_columns.at(0).at(1),
ColumnToChange(5, expected_timesteps[5]));
}

TEST(ProblemVariablesFromProblemAdapterTest, ProvideVariablesForWeek1) {
auto vars = provideVariables("problem-1-1--optim-nb-1.mps",
mpsWithIndexStartingAt0());
checkVarTimeSteps(vars, {0, 1, 2, 3, 1, 3});
}

TEST(ProblemVariablesFromProblemAdapterTest,
ProvideVariablesForWeek2StartingAt0) {
auto vars = provideVariables("problem-1-2--optim-nb-2.mps",
mpsWithIndexStartingAt0());
checkVarTimeSteps(vars, {168, 169, 170, 171, 169, 171});
}

TEST(ProblemVariablesFromProblemAdapterTest,
ProvideVariablesForWeek2StartingAt168) {
auto vars = provideVariables("problem-1-2--optim-nb-1.mps",
mpsWithIndexStartingAt168());
checkVarTimeSteps(vars, {168, 169, 170, 171, 169, 171});
}

TEST(ProblemVariablesFromProblemAdapterTest,
ProvideVariablesForWeek27StartingAt0) {
auto vars = provideVariables("problem-1-27--optim-nb-2.mps",
mpsWithIndexStartingAt0());
checkVarTimeSteps(vars, {4368, 4369, 4370, 4371, 4369, 4371});
}
33 changes: 18 additions & 15 deletions tests/python/test_antares_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from tests.build_config_reader import get_antares_solver_path
from antares_xpansion.__version__ import __antares_simulator_version__

SUBPROCESS_RUN = "antares_xpansion.antares_driver.subprocess.run"


Expand Down Expand Up @@ -238,18 +239,20 @@ def get_settings_dir(antares_study_path: Path):

class TestAntaresDriver:
def setup_method(self):
#TODO update antares version which comes with named problems
#self.nammed_problems = version.parse(__antares_simulator_version__) >= version.parse("8.6")
self.nammed_problems=True
# TODO update antares version which comes with named problems
# self.nammed_problems = version.parse(__antares_simulator_version__) >= version.parse("8.6")
self.nammed_problems = True

def test_antares_cmd(self, tmp_path):
study_dir = tmp_path
exe_path = "/Path/to/bin1"
antares_driver = AntaresDriver(exe_path)
# mock subprocess.run
with patch(SUBPROCESS_RUN, autospec=True) as run_function:
antares_driver.launch(study_dir, 1)
expected_cmd = [exe_path, study_dir, "--force-parallel", "1", "-z"]
if(self.nammed_problems):
expected_cmd = [exe_path, study_dir, "--force-parallel", "1", "-z", "--use-ortools",
"--ortools-solver=sirius"]
if (self.nammed_problems):
expected_cmd.append("--named-mps-problems")

run_function.assert_called_once_with(
Expand All @@ -265,8 +268,8 @@ def test_antares_cmd_force_parallel_option(self, tmp_path):
antares_driver.launch(study_dir, n_cpu)

expected_cmd = [exe_path, study_dir,
"--force-parallel", str(n_cpu), "-z"]
if(self.nammed_problems):
"--force-parallel", str(n_cpu), "-z", "--use-ortools", "--ortools-solver=sirius"]
if (self.nammed_problems):
expected_cmd.append("--named-mps-problems")
run_function.assert_called_once_with(
expected_cmd, shell=False, stdout=-3, stderr=-3
Expand All @@ -285,9 +288,9 @@ def test_invalid_n_cpu(self, tmp_path):
study_dir,
"--force-parallel",
str(expected_n_cpu),
"-z"
"-z", "--use-ortools", "--ortools-solver=sirius"
]
if(self.nammed_problems):
if (self.nammed_problems):
expected_cmd.append("--named-mps-problems")
run_function.assert_called_once_with(
expected_cmd, shell=False, stdout=-3, stderr=-3
Expand All @@ -303,8 +306,8 @@ def test_remove_log_file(self, tmp_path):
with patch(SUBPROCESS_RUN, autospec=True) as run_function:
antares_driver.launch(study_dir, n_cpu)
expected_cmd = [str(exe_path), study_dir,
"--force-parallel", str(n_cpu), "-z"]
if(self.nammed_problems):
"--force-parallel", str(n_cpu), "-z", "--use-ortools", "--ortools-solver=sirius"]
if (self.nammed_problems):
expected_cmd.append("--named-mps-problems")
run_function.assert_called_once_with(
expected_cmd, shell=False, stdout=-3, stderr=-3
Expand Down Expand Up @@ -366,8 +369,8 @@ def test_preserve_adequacy_option_after_run(self, tmp_path):
with patch(SUBPROCESS_RUN, autospec=True) as run_function:
antares_driver.launch(study_dir, n_cpu)
expected_cmd = [str(exe_path), study_dir,
"--force-parallel", str(n_cpu), "-z"]
if(self.nammed_problems):
"--force-parallel", str(n_cpu), "-z", "--use-ortools", "--ortools-solver=sirius"]
if (self.nammed_problems):
expected_cmd.append("--named-mps-problems")
run_function.assert_called_once_with(
expected_cmd, shell=False, stdout=-3, stderr=-3
Expand All @@ -392,8 +395,8 @@ def test_preserve_general_file_section_missing(self, tmp_path):
with patch(SUBPROCESS_RUN, autospec=True) as run_function:
antares_driver.launch(study_dir, n_cpu)
expected_cmd = [str(exe_path), study_dir,
"--force-parallel", str(n_cpu), "-z"]
if(self.nammed_problems):
"--force-parallel", str(n_cpu), "-z", "--use-ortools", "--ortools-solver=sirius"]
if (self.nammed_problems):
expected_cmd.append("--named-mps-problems")
run_function.assert_called_once_with(
expected_cmd, shell=False, stdout=-3, stderr=-3
Expand Down

0 comments on commit fba823e

Please sign in to comment.