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

High-level API: provide output path instead of returning it [ANT-2561] #2548

Merged
merged 8 commits into from
Jan 3, 2025
Merged
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
21 changes: 15 additions & 6 deletions src/api/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace Antares::API
{
SimulationResults APIInternal::run(
const IStudyLoader& study_loader,
const std::filesystem::path& output,
const Antares::Solver::Optimization::OptimizationOptions& optOptions)
{
try
Expand All @@ -43,9 +44,9 @@ SimulationResults APIInternal::run(
catch (const ::Antares::Error::StudyFolderDoesNotExist& e)
{
Antares::API::Error err{.reason = e.what()};
return {.simulationPath = "", .antares_problems = {}, .error = err};
return {.antares_problems = {}, .error = err};
}
return execute(optOptions);
return execute(output, optOptions);
}

/**
Expand All @@ -56,14 +57,15 @@ SimulationResults APIInternal::run(
* dupllication
*/
SimulationResults APIInternal::execute(
const std::filesystem::path& output,
const Antares::Solver::Optimization::OptimizationOptions& optOptions) const
{
// study_ == nullptr e.g when the -h flag is given
if (!study_)
{
using namespace std::string_literals;
Antares::API::Error err{.reason = "Couldn't create study"s};
return {.simulationPath{}, .antares_problems{}, .error = err};
return {.antares_problems{}, .error = err};
}

Settings settings;
Expand All @@ -75,10 +77,19 @@ SimulationResults APIInternal::execute(
auto ioQueueService = std::make_shared<Yuni::Job::QueueService>();
ioQueueService->maximumThreadCount(1);
ioQueueService->start();

study_->folderOutput = output;
auto resultWriter = Solver::resultWriterFactory(parameters.resultFormat,
study_->folderOutput,
ioQueueService,
durationCollector);

// In some cases (e.g tests) we don't want to write anything
if (!output.empty())
{
study_->saveAboutTheStudy(*resultWriter);
}

SimulationObserver simulationObserver;

optimizationInfo = simulationRun(*study_,
Expand All @@ -90,8 +101,6 @@ SimulationResults APIInternal::execute(
// Importing Time-Series if asked
study_->importTimeseriesIntoInput();

return {.simulationPath = study_->folderOutput,
.antares_problems = simulationObserver.acquireLps(),
.error{}};
return {.antares_problems = simulationObserver.acquireLps(), .error{}};
}
} // namespace Antares::API
10 changes: 4 additions & 6 deletions src/api/include/antares/api/SimulationResults.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <filesystem>
#include <optional>
#include <string>

#include "antares/solver/lps/LpsFromAntares.h"

namespace Antares::API
Expand All @@ -31,7 +32,8 @@ namespace Antares::API
* @struct Error
* @brief The Error structure is used to represent an error that occurred during the simulation.
*/
struct Error {
struct Error
{
/**
* @brief The reason for the error.
*/
Expand All @@ -45,10 +47,6 @@ struct Error {
*/
struct [[nodiscard("Contains results and potential error")]] SimulationResults
{
/**
* @brief The path to the simulation (output).
*/
std::filesystem::path simulationPath;
/**
* @brief weekly problems
*/
Expand All @@ -59,4 +57,4 @@ struct [[nodiscard("Contains results and potential error")]] SimulationResults
std::optional<Error> error;
};

}
} // namespace Antares::API
1 change: 1 addition & 0 deletions src/api/include/antares/api/solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ namespace Antares::API
*/
SimulationResults PerformSimulation(
const std::filesystem::path& study_path,
const std::filesystem::path& output,
const Antares::Solver::Optimization::OptimizationOptions& optOptions) noexcept;
} // namespace Antares::API
2 changes: 2 additions & 0 deletions src/api/private/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ class APIInternal
* @return SimulationResults object which contains the results of the simulation.
*/
SimulationResults run(const IStudyLoader& study_loader,
const std::filesystem::path& output,
const Antares::Solver::Optimization::OptimizationOptions& optOptions);

private:
std::shared_ptr<Antares::Data::Study> study_;
SimulationResults execute(
const std::filesystem::path& output,
const Antares::Solver::Optimization::OptimizationOptions& optOptions) const;
};

Expand Down
5 changes: 3 additions & 2 deletions src/api/solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@ namespace Antares::API

SimulationResults PerformSimulation(
const std::filesystem::path& study_path,
const std::filesystem::path& output,
const Antares::Solver::Optimization::OptimizationOptions& optOptions) noexcept
{
try
{
APIInternal api;
FileTreeStudyLoader study_loader(study_path);
return api.run(study_loader, optOptions);
return api.run(study_loader, output, optOptions);
}
catch (const std::exception& e)
{
Antares::API::Error err{.reason = e.what()};
return SimulationResults{.simulationPath = study_path, .antares_problems{}, .error = err};
return SimulationResults{.antares_problems{}, .error = err};
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/api_client_example/src/API_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

#include <utility>

Antares::API::SimulationResults solve(std::filesystem::path study_path)
Antares::API::SimulationResults solve(std::filesystem::path study_path,
std::filesystem::path output)
{
return Antares::API::PerformSimulation(std::move(study_path), {});
return Antares::API::PerformSimulation(std::move(study_path), std::move(output), {});
}
5 changes: 3 additions & 2 deletions src/api_client_example/src/API_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@

#pragma once

#include <antares/api/solver.h>
#include <antares/api/SimulationResults.h>
#include <antares/api/solver.h>

Antares::API::SimulationResults solve(std::filesystem::path study_path);
Antares::API::SimulationResults solve(std::filesystem::path study_path,
std::filesystem::path output);
8 changes: 5 additions & 3 deletions src/api_client_example/tests/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
#define BOOST_TEST_MODULE test_client_api

#include <boost/test/unit_test.hpp>

#include "API_client.h"

BOOST_AUTO_TEST_CASE(test_run) {
auto results = solve("dummy_study_test_client_api");
BOOST_AUTO_TEST_CASE(test_run)
{
auto results = solve("dummy_study_test_client_api", {});
BOOST_CHECK(results.error);
BOOST_CHECK(!results.error->reason.empty());
auto c = results.error->reason;
Expand All @@ -34,4 +36,4 @@ BOOST_AUTO_TEST_CASE(test_run) {
BOOST_CHECK(results.error->reason.find("folder") != std::string::npos);
BOOST_CHECK(results.error->reason.find("not") != std::string::npos);
BOOST_CHECK(results.error->reason.find("exist") != std::string::npos);
}
}
2 changes: 1 addition & 1 deletion src/format-code.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
if [ $# -eq 0 ]
then
# No arguments: format all
SOURCE_DIRS="analyzer/ libs/ solver/ tools/ config/ tests/ packaging/"
SOURCE_DIRS="analyzer/ libs/ solver/ tools/ config/ tests/ packaging/ api/"
SOURCE_FILES=$(find $SOURCE_DIRS -regextype egrep -regex ".*/*\.(c|cxx|cpp|cc|h|hxx|hpp)$" ! -path '*/antlr-interface/*')
else
# Format files provided as arguments
Expand Down
6 changes: 3 additions & 3 deletions src/solver/application/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,6 @@ void Application::readDataForTheStudy(Data::StudyLoadOptions& options)

Antares::Solver::initializeSignalHandlers(resultWriter);

// Save about-the-study files (comments, notes, etc.)
study.saveAboutTheStudy(*resultWriter);

// Name of the simulation (again, if the value has been overwritten)
if (!pSettings.simulationName.empty())
{
Expand Down Expand Up @@ -375,6 +372,9 @@ void Application::execute()
return;
}

// Save about-the-study files (comments, notes, etc.)
pStudy->saveAboutTheStudy(*resultWriter);

SystemMemoryLogger memoryReport;
memoryReport.interval(1000 * 60 * 5); // 5 minutes
memoryReport.start();
Expand Down
21 changes: 5 additions & 16 deletions src/tests/src/api_internal/test_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,17 @@ class InMemoryStudyLoader: public Antares::IStudyLoader
builder.study->initializeRuntimeInfos();
builder.setNumberMCyears(1);
builder.study->parameters.resultFormat = ResultFormat::inMemory;
builder.study->prepareOutput();
return std::move(builder.study);
}

bool success_ = true;
};

BOOST_AUTO_TEST_CASE(simulation_path_points_to_results)
{
Antares::API::APIInternal api;
auto study_loader = std::make_unique<InMemoryStudyLoader>();
auto results = api.run(*study_loader.get(), {});
BOOST_CHECK_EQUAL(results.simulationPath, std::filesystem::path{"no_output"});
// Testing for "no_output" is a bit weird, but it's the only way to test this without actually
// running the simulation
}

BOOST_AUTO_TEST_CASE(api_run_contains_antares_problem)
{
Antares::API::APIInternal api;
auto study_loader = std::make_unique<InMemoryStudyLoader>();
auto results = api.run(*study_loader.get(), {});
auto results = api.run(*study_loader, {}, {});

BOOST_CHECK(!results.antares_problems.empty());
BOOST_CHECK(!results.error);
Expand All @@ -83,7 +72,7 @@ BOOST_AUTO_TEST_CASE(result_failure_when_study_is_null)
{
Antares::API::APIInternal api;
auto study_loader = std::make_unique<InMemoryStudyLoader>(false);
auto results = api.run(*study_loader.get(), {});
auto results = api.run(*study_loader, {}, {});

BOOST_CHECK(results.error);
}
Expand All @@ -93,7 +82,7 @@ BOOST_AUTO_TEST_CASE(result_contains_problems)
{
Antares::API::APIInternal api;
auto study_loader = std::make_unique<InMemoryStudyLoader>();
auto results = api.run(*study_loader.get(), {});
auto results = api.run(*study_loader, {}, {});

BOOST_CHECK(!results.antares_problems.empty());
BOOST_CHECK(!results.error);
Expand All @@ -109,7 +98,7 @@ BOOST_AUTO_TEST_CASE(result_with_ortools_coin)
.solverLogs = false,
.solverParameters = ""};

auto results = api.run(*study_loader.get(), opt);
auto results = api.run(*study_loader, {}, opt);

BOOST_CHECK(!results.antares_problems.empty());
BOOST_CHECK(!results.error);
Expand All @@ -126,7 +115,7 @@ BOOST_AUTO_TEST_CASE(invalid_ortools_solver)
.solverLogs = true,
.solverParameters = ""};

auto shouldThrow = [&api, &study_loader, &opt] { return api.run(*study_loader.get(), opt); };
auto shouldThrow = [&api, &study_loader, &opt] { return api.run(*study_loader, {}, opt); };
BOOST_CHECK_EXCEPTION(shouldThrow(),
std::invalid_argument,
checkMessage("Solver this-solver-does-not-exist not found"));
Expand Down
2 changes: 1 addition & 1 deletion src/tests/src/api_lib/test_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
BOOST_AUTO_TEST_CASE(result_failure_when_study_path_invalid)
{
using namespace std::string_literals;
auto results = Antares::API::PerformSimulation("dummy"s, {});
auto results = Antares::API::PerformSimulation("dummy"s, {}, {});
BOOST_CHECK(results.error);
BOOST_CHECK(!results.error->reason.empty());
}
Loading