14#ifdef DLINEAR_ENABLED_QSOPTEX
15#include "dlinear/libs/libqsopt_ex.h"
17#ifdef DLINEAR_ENABLED_SOPLEX
18#include "dlinear/libs/libsoplex.h"
21#include "dlinear/util/OptionValue.hpp"
22#include "dlinear/util/exception.h"
23#include "dlinear/util/filesystem.h"
24#include "dlinear/util/logging.h"
25#include "dlinear/version.h"
29#define DLINEAR_PARSE_PARAM_BOOL(parser, name, ...) \
31 parser.add_argument(__VA_ARGS__) \
32 .help(dlinear::Config::help_##name) \
33 .default_value(dlinear::Config::default_##name) \
34 .implicit_value(!dlinear::Config::default_##name); \
37#define DLINEAR_PARSE_PARAM_SCAN(parser, name, scan_char, scan_type, ...) \
39 parser.add_argument(__VA_ARGS__) \
40 .help(dlinear::Config::help_##name) \
41 .default_value(dlinear::Config::default_##name) \
43 .scan<scan_char, scan_type>(); \
46#define DLINEAR_PARSE_PARAM_ENUM(parser, name, cmd_name, invalid_prompt, ...) \
48 parser.add_argument(cmd_name) \
49 .help(dlinear::Config::help_##name) \
50 .default_value(dlinear::Config::default_##name) \
51 .action([](const std::string &value) { \
53 DLINEAR_INVALID_ARGUMENT_EXPECTED(cmd_name, value, invalid_prompt); \
58#define DLINEAR_PARAM_TO_CONFIG(param_name, config_name, type) \
60 if (parser_.is_used(param_name)) config.m_##config_name().SetFromCommandLine(parser_.get<type>(param_name)); \
64 : parser_{DLINEAR_PROGRAM_NAME, DLINEAR_VERSION_STRING},
65 verbosity_{
Config::default_verbose_dlinear},
66#ifdef DLINEAR_ENABLED_QSOPTEX
67 qsoptex_hash_{QSopt_ex_repository_status()},
69#ifdef DLINEAR_ENABLED_SOPLEX
70 soplex_hash_{soplex::getGitHash()}
73 DLINEAR_TRACE(
"ArgParser::ArgParser");
82 DLINEAR_TRACE(
"ArgParser::parse: parsed args");
83 }
catch (
const std::runtime_error &err) {
84 std::cerr << err.what() <<
"\n" <<
parser_ << std::endl;
85 std::exit(EXIT_FAILURE);
86 }
catch (
const std::invalid_argument &err) {
87 std::cerr << err.what() <<
"\n\n" <<
parser_.usage() << std::endl;
88 std::exit(EXIT_FAILURE);
93 DLINEAR_TRACE(
"ArgParser::AddOptions: adding options");
95 parser_.add_argument(
"file").help(
"input file").default_value(
"");
96 parser_.add_argument(
"--onnx-file").help(
"ONNX file name").default_value(
"").nargs(1);
98 DLINEAR_PARSE_PARAM_BOOL(
parser_, csv,
"--csv");
99 DLINEAR_PARSE_PARAM_BOOL(
parser_, continuous_output,
"--continuous-output");
100 DLINEAR_PARSE_PARAM_BOOL(
parser_, complete,
"-c",
"--complete");
101 DLINEAR_PARSE_PARAM_BOOL(
parser_, debug_parsing,
"--debug-parsing");
102 DLINEAR_PARSE_PARAM_BOOL(
parser_, debug_scanning,
"--debug-scanning");
103 DLINEAR_PARSE_PARAM_BOOL(
parser_, disable_expansion,
"--disable-expansion");
104 DLINEAR_PARSE_PARAM_BOOL(
parser_, enforce_check_sat,
"--enforce-check-sat");
105 DLINEAR_PARSE_PARAM_BOOL(
parser_, optimize,
"-o",
"--optimize");
106 DLINEAR_PARSE_PARAM_BOOL(
parser_, produce_models,
"-m",
"--produce-models");
107 DLINEAR_PARSE_PARAM_BOOL(
parser_, skip_check_sat,
"--skip-check-sat");
108 DLINEAR_PARSE_PARAM_BOOL(
parser_, silent,
"-s",
"--silent");
109 DLINEAR_PARSE_PARAM_BOOL(
parser_, with_timings,
"-t",
"--timings");
110 DLINEAR_PARSE_PARAM_BOOL(
parser_, read_from_stdin,
"--in");
111 DLINEAR_PARSE_PARAM_BOOL(
parser_, verify,
"--verify");
114 DLINEAR_PARSE_PARAM_SCAN(
parser_, precision,
'g',
double,
"-p",
"--precision");
115 DLINEAR_PARSE_PARAM_SCAN(
parser_, random_seed,
'i',
unsigned int,
"-r",
"--random-seed");
116 DLINEAR_PARSE_PARAM_SCAN(
parser_, simplex_sat_phase,
'i',
int,
"--simplex-sat-phase");
117 DLINEAR_PARSE_PARAM_SCAN(
parser_, verbose_simplex,
'i',
int,
"--verbose-simplex");
119 parser_.add_argument(
"-V",
"--verbose")
120 .help(
"increase verbosity level. Can be used multiple times. Maximum verbosity level is 5 and default is 2")
121 .action([
this](
const auto &) {
126 parser_.add_argument(
"-q",
"--quiet")
127 .help(
"decrease verbosity level. Can be used multiple times. Minimum verbosity level is 0 and default is 2")
128 .action([
this](
const auto &) {
134 DLINEAR_PARSE_PARAM_ENUM(
136 "[ auto | pure-precision-boosting | pure-iterative-refinement | hybrid ] or [ 1 | 2 | 3 | 4 ]",
141 DLINEAR_PARSE_PARAM_ENUM(
parser_, format,
"--format",
"[ auto | smt2 | mps | vnnlib ] or [ 1 | 2 | 3 | 4 ]",
146 DLINEAR_PARSE_PARAM_ENUM(
parser_, lp_solver,
"--lp-solver",
"[ soplex | qsoptex ] or [ 1 | 2 ]",
149 DLINEAR_PARSE_PARAM_ENUM(
parser_, sat_solver,
"--sat-solver",
"[ cadical | picosat ] or [ 1 | 2 ]",
152 DLINEAR_PARSE_PARAM_ENUM(
parser_, sat_default_phase,
"--sat-default-phase",
153 "[ false | true | jeroslow-wang | random ] or [ 1 | 2 | 3 | 4 ]",
158 DLINEAR_PARSE_PARAM_ENUM(
159 parser_, bound_propagation_type,
"--bound-propagation-type",
160 "[ auto | eq-binomial | eq-polynomial | bound-polynomial ] or [ 1 | 2 | 3 | 4 ]",
165 DLINEAR_PARSE_PARAM_ENUM(
166 parser_, bound_propagation_frequency,
"--bound-propagation-frequency",
167 "[ auto | never | on-fixed | on-iteration | always ] or [ 1 | 2 | 3 | 4 | 5 ]",
173 DLINEAR_PARSE_PARAM_ENUM(
174 parser_, bound_implication_frequency,
"--bound-implication-frequency",
175 "[ auto | never | always ] or [ 1 | 2 | 3 ]",
180 DLINEAR_TRACE(
"ArgParser::ArgParser: added all arguments");
183std::ostream &operator<<(std::ostream &os,
const ArgParser &parser) {
return os << parser.
parser_ << std::endl; }
186 DLINEAR_TRACE(
"ArgParser::ToConfig: converting to Config");
190 if (
parser_.is_used(
"complete")) {
192 config.m_precision().SetFromCommandLine(0.0);
194 DLINEAR_PARAM_TO_CONFIG(
"bound-implication-frequency", bound_implication_frequency,
196 DLINEAR_PARAM_TO_CONFIG(
"bound-propagation-frequency", bound_propagation_frequency,
198 DLINEAR_PARAM_TO_CONFIG(
"csv", csv,
bool);
199 DLINEAR_PARAM_TO_CONFIG(
"continuous-output", continuous_output,
bool);
200 DLINEAR_PARAM_TO_CONFIG(
"debug-parsing", debug_parsing,
bool);
201 DLINEAR_PARAM_TO_CONFIG(
"debug-scanning", debug_scanning,
bool);
202 DLINEAR_PARAM_TO_CONFIG(
"disable-expansion", disable_expansion,
bool);
204 DLINEAR_PARAM_TO_CONFIG(
"enforce-check-sat", enforce_check_sat,
bool);
205 config.m_filename().SetFromCommandLine(
parser_.is_used(
"file") ?
parser_.get<std::string>(
"file") :
"");
210 DLINEAR_PARAM_TO_CONFIG(
"onnx-file", onnx_file, std::string);
211 DLINEAR_PARAM_TO_CONFIG(
"optimize", optimize,
bool);
212 DLINEAR_PARAM_TO_CONFIG(
"precision", precision,
double);
213 DLINEAR_PARAM_TO_CONFIG(
"produce-models", produce_models,
bool);
214 DLINEAR_PARAM_TO_CONFIG(
"random-seed", random_seed,
unsigned int);
215 DLINEAR_PARAM_TO_CONFIG(
"in", read_from_stdin,
bool);
218 DLINEAR_PARAM_TO_CONFIG(
"silent", silent,
bool);
219 DLINEAR_PARAM_TO_CONFIG(
"simplex-sat-phase", simplex_sat_phase,
int);
220 DLINEAR_PARAM_TO_CONFIG(
"skip-check-sat", skip_check_sat,
bool);
221 config.m_verbose_dlinear().SetFromCommandLine(
verbosity_);
222 DLINEAR_PARAM_TO_CONFIG(
"verbose-simplex", verbose_simplex,
int);
223 DLINEAR_PARAM_TO_CONFIG(
"verify", verify,
bool);
224 DLINEAR_PARAM_TO_CONFIG(
"timings", with_timings,
bool);
226 DLINEAR_TRACE_FMT(
"ArgParser::ToConfig: {}", config);
231 DLINEAR_TRACE(
"ArgParser::ValidateOptions: validating options");
233 DLINEAR_INVALID_ARGUMENT(
"--in",
"--in and file are mutually exclusive");
235 DLINEAR_INVALID_ARGUMENT(
"file",
"must be specified unless --in is used");
237 DLINEAR_INVALID_ARGUMENT(
"--in",
"a format must be specified with --format");
242 if (format ==
Config::Format::AUTO && extension !=
"smt2" && extension !=
"mps" && extension !=
"vnnlib") {
243 DLINEAR_INVALID_ARGUMENT(
"file",
"file must be .smt2, .mps or .vnnlib if --format is auto");
246 if (!
parser_.is_used(
"onnx-file"))
247 DLINEAR_INVALID_ARGUMENT(
"--onnx-file",
"must be provided with --format vnnlib");
248 if (!std::filesystem::is_regular_file(
parser_.get<std::string>(
"onnx-file")))
249 DLINEAR_INVALID_ARGUMENT(
"--onnx-file",
"cannot find file or the file is not a regular file");
253 if (!
parser_.is_used(
"in") && !std::filesystem::is_regular_file(
parser_.get<std::string>(
"file")))
254 DLINEAR_INVALID_ARGUMENT(
"file",
"cannot find file or the file is not a regular file");
256 DLINEAR_INVALID_ARGUMENT(
"--complete",
"--complete and --precision are mutually exclusive");
257 if (
parser_.get<
double>(
"precision") < 0) DLINEAR_INVALID_ARGUMENT(
"--precision",
"cannot be negative");
258 if (
parser_.get<
bool>(
"skip-check-sat") &&
parser_.get<
bool>(
"produce-models"))
259 DLINEAR_INVALID_ARGUMENT(
"--produce-models",
"--produce-models and --skip-check-sat are mutually exclusive");
261 DLINEAR_INVALID_ARGUMENT(
"--verbose",
"verbosity is forcefully set to 0 if --silent is provided");
263 DLINEAR_INVALID_ARGUMENT(
"--quiet",
"verbosity is already set to 0 if --silent is provided");
267 DLINEAR_INVALID_ARGUMENT(
"--lp-solver",
"QSopt_ex only supports 'auto' and 'pure-precision-boosting' modes");
268 if (
parser_.is_used(
"enforce-check-sat") &&
parser_.is_used(
"skip-check-sat"))
269 DLINEAR_INVALID_ARGUMENT(
"--enforce-check-sat",
"--enforce-check-sat and --skip-check-sat are mutually exclusive");
278 const std::string build_type{
"Debug"};
280 const std::string build_type{
"Release"};
283 if (!repo_stat.empty()) {
284 repo_stat =
" (repository: " + repo_stat +
")";
287 std::string vstr = fmt::format(
"{} (v{}): delta-complete SMT solver ({} Build) {}", DLINEAR_PROGRAM_NAME,
version(),
288 build_type, repo_stat);
Used to parse command line arguments and produce a corresponding Config object to be used throughout ...
const std::string soplex_hash_
The hash of the Soplex library. Used in the prompt.
void Parse(int argc, const char **argv)
Parse the command line arguments.
argparse::ArgumentParser parser_
The parser object.
void AddOptions()
Add all the options, positional arguments and flags to the parser.
int verbosity_
Verbosity level of the program.
void ValidateOptions()
Validate the options, ensuring the correctness of the parameters and the consistency of the options.
static std::string version()
Get read-only access to the version of the program.
const std::string qsoptex_hash_
The hash of the QSoptEx library. Used in the prompt.
ArgParser()
Construct a new argparser object.
std::string prompt() const
Get read-only access to the printable console prompt of the program.
Config ToConfig() const
Convert the parser to a Config.
static std::string repository_status()
Get read-only access to the hash status of the repository.
Simple dataclass used to store the configuration of the program.
OptionValue< bool > & m_complete()
Get read-only access to the complete parameter of the configuration.
SatSolver
Underlying SAT solver used by the abstract SAT solver.
@ CADICAL
Cadical Solver. Default option.
LPMode
LP mode used by the LP solver.
@ HYBRID
Use both modes, if available.
@ PURE_PRECISION_BOOSTING
Use the precision boosting mode, if available.
@ AUTO
Let the LP solver choose the mode. Default option.
@ PURE_ITERATIVE_REFINEMENT
Use the iterative refinement mode, if available.
Format
Format of the input file.
@ AUTO
Automatically detect the input format based on the file extension. Default option.
BoundPropagationType
Types of bound propagation supported by the bound propagator.
@ EQ_POLYNOMIAL
Only propagate bound in theory formulae in the form .
@ EQ_BINOMIAL
Only propagate bounds in theory formulas in the form .
@ BOUND_POLYNOMIAL
Propagate all possible constraints.
@ AUTO
Automatically select the best configuration based on expected performance. Default option.
LPSolver
Underlying LP solver used by the theory solver.
@ SOPLEX
Soplex Solver. Default option.
PreprocessingRunningFrequency
Frequency at which the preprocessors will run.
@ ON_ITERATION
Run this preprocess only at every iteration.
@ NEVER
Never run this preprocess, effectively disabling it.
@ ON_FIXED
Run this preprocess only once, on fixed literals, before all iterations.
@ AUTO
Automatically select the best configuration based on expected performance. Default option.
@ ALWAYS
Run this preprocess at every chance it gets. Usually combines ON_FIXED and ON_ITERATION.
SatDefaultPhase
Phase for the SAT solver.
@ RandomInitialPhase
Randomly assign a value to non fixed decision literals.
@ JeroslowWang
Default option.
@ True
Assign true to non fixed decision literals.
@ False
Assign false to non fixed decision literals.
void SetFromCommandLine(const T &value)
Sets the value to value which is given by a command-line argument.
Global namespace for the dlinear library.
std::string GetExtension(const std::string &name)
Get the extension of the file.