alpaqa 1.0.0a16
Nonconvex constrained optimization
Loading...
Searching...
No Matches
options.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <algorithm>
7#include <ranges>
8#include <span>
9#include <stdexcept>
10#include <string_view>
11#include <vector>
12
13#if ALPAQA_WITH_JSON
15#include <nlohmann/json.hpp>
16#include <fstream>
17#else
19#endif
20
21class Options {
22 private:
23 std::vector<std::string_view> opts_storage;
24 std::vector<unsigned> used_storage;
25 size_t num_json;
26#if ALPAQA_WITH_JSON
27 std::vector<nlohmann::json> json_storage;
28#endif
29
30 public:
31 Options(int argc, const char *const argv[])
32 : opts_storage{argv, argv + argc} {
33 // Arguments starting with an '@' sign refer to JSON files with options
34 auto with_at = [](std::string_view s) { return s.starts_with('@'); };
35 // JSON options are always applied before command-line options
36 auto non_json = std::ranges::stable_partition(opts_storage, with_at);
37 num_json = static_cast<size_t>(non_json.begin() - opts_storage.begin());
38#if ALPAQA_WITH_JSON
39 // Load the JSON data for each '@' option
40 auto load = [](std::string_view s) {
41 return load_json(std::string(s.substr(1)));
42 };
43 auto json_obj = std::views::transform(json_flags(), load);
44 json_storage = decltype(json_storage){json_obj.begin(), json_obj.end()};
45#else
46 if (num_json > 0)
47 throw std::logic_error(
48 "This version of alpaqa was compiled without JSON support: "
49 "cannot parse options " +
50 alpaqa::util::join_quote(json_flags(), {.sep = " "}));
51#endif
52 // Keep track of which options are used
53 used_storage.resize(opts_storage.size() - num_json);
54 }
55 [[nodiscard]] std::span<const std::string_view> json_flags() const {
56 return std::span{opts_storage}.first(num_json);
57 }
58 [[nodiscard]] std::span<const std::string_view> options() const {
59 return std::span{opts_storage}.subspan(num_json);
60 }
61 [[nodiscard]] std::span<unsigned> used() { return used_storage; }
62
63#if ALPAQA_WITH_JSON
64 [[nodiscard]] std::span<const nlohmann::json> json_data() const {
65 return json_storage;
66 }
67
68 private:
69 [[nodiscard]] static nlohmann::json load_json(const std::string &name) {
70 nlohmann::json j;
71 std::ifstream f{name};
72 if (!f)
73 throw std::runtime_error("Unable to open JSON file '" + name + "'");
74 try {
75 f >> j;
76 } catch (nlohmann::json::exception &e) {
77 throw std::runtime_error("Unable to parse JSON file '" + name +
78 "': " + e.what());
79 }
80 return j;
81 }
82#endif
83};
84
85template <class T>
86decltype(auto) set_params(T &t, std::string_view prefix, Options &opts) {
87#if ALPAQA_WITH_JSON
88 auto json_data = opts.json_data();
89 for (size_t i = 0; i < json_data.size(); ++i)
90 try {
91 if (auto j = json_data[i].find(prefix); j != json_data[i].end())
94 std::string fname{opts.json_flags()[i].substr(1)};
95 throw std::invalid_argument(
96 "Error in JSON file '" + fname + "' at '" +
97 std::string(prefix) +
98 alpaqa::util::join_quote(std::views::reverse(e.backtrace),
99 {.sep = "",
100 .empty = "",
101 .quote_left = ".",
102 .quote_right = ""}) +
103 "': " + e.what());
104 } catch (nlohmann::json::exception &e) {
105 std::string fname{opts.json_flags()[i].substr(1)};
106 throw std::invalid_argument("Error in JSON file '" + fname +
107 "': " + e.what());
108 }
109#endif
110 return alpaqa::params::set_params(t, prefix, opts.options(), opts.used());
111}
std::span< unsigned > used()
Definition options.hpp:61
std::span< const std::string_view > json_flags() const
Definition options.hpp:55
std::span< const std::string_view > options() const
Definition options.hpp:58
std::vector< unsigned > used_storage
Definition options.hpp:24
size_t num_json
Definition options.hpp:25
std::vector< std::string_view > opts_storage
Definition options.hpp:23
Options(int argc, const char *const argv[])
Definition options.hpp:31
void set_params(T &t, std::string_view prefix, std::span< const std::string_view > options, std::optional< std::span< unsigned > > used=std::nullopt)
Overwrites t based on the options that start with prefix.
Definition params.hpp:49
void set_param(T &t, const json &j)
Update/overwrite the first argument based on the JSON object j.
Definition json.tpp:24
std::string join_quote(std::ranges::input_range auto strings, join_quote_opt opt={})
Join the list of strings into a single string, using the separator given by opt.
decltype(auto) set_params(T &t, std::string_view prefix, Options &opts)
Definition options.hpp:86
Custom parameter parsing exception.
Definition json.hpp:39
std::vector< std::string > backtrace
Definition json.hpp:41