ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_options.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9/*------------------------------------------------------------------------*/
10
11// By default, e.g., for library usage, the 'opts.report' value is zero
12// ('false') but can be set to '1' by the stand alone solver. Using here
13// a static default value avoids that the stand alone solver reports that
14// '--report=1' is different from the default in 'print ()' below.
15//
17
18/*------------------------------------------------------------------------*/
19
20// The order of initializations of static objects is undefined and thus we
21// can not assume that this table is already initialized if a solver and
22// thus the constructor of 'Options' is called. Therefore we just have to
23// reinitialize this table in every call to 'Options::Options'. This does
24// not produce a data race even for parallel initialization since the
25// same values are written by all threads under the assumption that the
26// 'reportdefault' is set before any solver is initialized. We do have to
27// perform this static initialization though, since 'has' is static and does
28// not require that the 'Options' constructor was called.
29
30Option Options::table[] = {
31#define OPTION(N, V, L, H, O, P, R, D) \
32 {#N, (int) V, (int) L, (int) H, (int) O, (bool) P, D},
34#undef OPTION
35};
36
37/*------------------------------------------------------------------------*/
38
39// Binary search in 'table', which requires option names to be sorted, which
40// in turned is checked at start-up in 'Options::Options'.
41
42Option *Options::has (const char *name) {
43 size_t l = 0, r = number_of_options;
44 while (l < r) {
45 size_t m = l + (r - l) / 2;
46 Option *res = &table[m];
47 int tmp = strcmp (name, res->name);
48 if (!tmp)
49 return res;
50 if (tmp < 0)
51 r = m;
52 if (tmp > 0)
53 l = m + 1;
54 }
55 return 0;
56}
57
58/*------------------------------------------------------------------------*/
59
60bool Options::parse_long_option (const char *arg, string &name, int &val) {
61 if (arg[0] != '-' || arg[1] != '-')
62 return false;
63 const bool has_no_prefix =
64 (arg[2] == 'n' && arg[3] == 'o' && arg[4] == '-');
65 const size_t offset = has_no_prefix ? 5 : 2;
66 name = arg + offset;
67 const size_t pos = name.find_first_of ('=');
68 if (pos != string::npos)
69 name[pos] = 0;
70 if (!Options::has (name.c_str ()))
71 return false;
72 if (pos == string::npos)
73 val = !has_no_prefix;
74 else {
75 const char *val_str = name.c_str () + pos + 1;
76 if (!parse_int_str (val_str, val))
77 return false;
78 }
79 return true;
80}
81
82/*------------------------------------------------------------------------*/
83
84void Options::initialize_from_environment (int &val, const char *name,
85 const int L, const int H) {
86 char key[80], *q;
87 const char *p;
88 CADICAL_assert (strlen (name) + strlen ("CADICAL_") + 1 < sizeof (key));
89 for (p = "CADICAL_", q = key; *p; p++)
90 *q++ = *p;
91 for (p = name; *p; p++)
92 *q++ = toupper (*p);
93 CADICAL_assert (q < key + sizeof (key));
94 *q = 0;
95 const char *val_str = getenv (key);
96 if (!val_str)
97 return;
98 if (!parse_int_str (val_str, val))
99 return;
100 if (val < L)
101 val = L;
102 if (val > H)
103 val = H;
104}
105
106// Initialize all the options to their default value 'V'.
107
108Options::Options (Internal *s) : internal (s) {
109 CADICAL_assert (number_of_options == sizeof Options::table / sizeof (Option));
110
111 // First initialize them according to defaults in 'options.hpp'.
112 //
113 const char *prev = "";
114 size_t i = 0;
115#define OPTION(N, V, L, H, O, P, R, D) \
116 do { \
117 if ((L) > (V)) \
118 FATAL ("'" #N "' default '" #V "' " \
119 "lower minimum '" #L "' in 'options.hpp'"); \
120 if ((H) < (V)) \
121 FATAL ("'" #N "' default '" #V "' " \
122 "larger maximum '" #H "' in 'options.hpp'"); \
123 if (strcmp (prev, #N) > 0) \
124 FATAL ("'%s' ordered before '" #N "' in 'options.hpp'", prev); \
125 N = (int) (V); \
126 CADICAL_assert (&val (i) == &N); \
127 /* The order of initializing static data is undefined and thus */ \
128 /* it might be the case that the 'table' is not initialized yet. */ \
129 /* Thus this construction just reinitializes the table too even */ \
130 /* though it might not be necessary. */ \
131 CADICAL_assert (!table[i].name || !strcmp (table[i].name, #N)); \
132 table[i] = {#N, (int) (V), (int) (L), (int) (H), \
133 (int) (O), (bool) (P), D}; \
134 prev = #N; \
135 i++; \
136 } while (0);
137 OPTIONS
138#undef OPTION
139
140 // Check consistency in debugging mode.
141 //
142#ifndef CADICAL_NDEBUG
143 CADICAL_assert (i == number_of_options);
144 CADICAL_assert (!has ("aaaaa"));
145 CADICAL_assert (!has ("non-existing-option"));
146 CADICAL_assert (!has ("zzzzz"));
147#endif
148
149 // Now overwrite default options with environment values.
150 //
151#define OPTION(N, V, L, H, O, P, R, D) \
152 initialize_from_environment (N, #N, L, H);
153 OPTIONS
154#undef OPTION
155}
156
157/*------------------------------------------------------------------------*/
158
159void Options::set (Option *o, int new_val) {
160 CADICAL_assert (o);
161 int &val = o->val (this), old_val = val;
162 if (old_val == new_val) {
163 LOG ("keeping value '%d' of option '%s'", old_val, o->name);
164 return;
165 }
166 if (new_val < o->lo) {
167 LOG ("bounding '%d' to lower limit '%d' for option '%s'", new_val,
168 o->lo, o->name);
169 new_val = o->lo;
170 }
171 if (new_val > o->hi) {
172 LOG ("bounding '%d' to upper limit '%d' for option '%s'", new_val,
173 o->hi, o->name);
174 new_val = o->hi;
175 }
176 val = new_val;
177 LOG ("set option 'set (\"%s\", %d)' from '%d'", o->name, new_val,
178 old_val);
179}
180
181// Explicit option value setting.
182
183bool Options::set (const char *name, int val) {
184 Option *o = has (name);
185 if (!o)
186 return false;
187 set (o, val);
188 return true;
189}
190
191int Options::get (const char *name) {
192 Option *o = has (name);
193 return o ? o->val (this) : 0;
194}
195
196/*------------------------------------------------------------------------*/
197
199 unsigned different = 0;
200#ifdef CADICAL_QUIET
201 const bool verbose = false;
202#endif
203 char buffer[256];
204 // We prefer the macro iteration here since '[VLH]' might be '1e9' etc.
205#define OPTION(N, V, L, H, O, P, R, D) \
206 if (N != (V)) \
207 different++; \
208 if (verbose || N != (V)) { \
209 if ((L) == 0 && (H) == 1) { \
210 snprintf (buffer, sizeof buffer, "--" #N "=%s", \
211 (N ? "true" : "false")); \
212 MSG (" %s%-30s%s (%s default %s'%s'%s)", \
213 ((N == (V)) ? "" : tout.bright_yellow_code ()), buffer, \
214 ((N == (V)) ? "" : tout.normal_code ()), \
215 ((N == (V)) ? "same as" : "different from"), \
216 ((N == (V)) ? tout.green_code () : tout.yellow_code ()), \
217 (bool) (V) ? "true" : "false", tout.normal_code ()); \
218 } else { \
219 snprintf (buffer, sizeof buffer, "--" #N "=%d", N); \
220 MSG (" %s%-30s%s (%s default %s'" #V "'%s)", \
221 ((N == (V)) ? "" : tout.bright_yellow_code ()), buffer, \
222 ((N == (V)) ? "" : tout.normal_code ()), \
223 ((N == (V)) ? "same as" : "different from"), \
224 ((N == (V)) ? tout.green_code () : tout.yellow_code ()), \
225 tout.normal_code ()); \
226 } \
227 }
228 OPTIONS
229#undef OPTION
230 if (!different)
231 MSG ("all options are set to their default value");
232}
233
234/*------------------------------------------------------------------------*/
235
237 // We prefer the macro iteration here since '[VLH]' might be '1e9' etc.
238#define OPTION(N, V, L, H, O, P, R, D) \
239 if ((L) == 0 && (H) == 1) \
240 printf (" %-26s " D " [%s]\n", "--" #N "=bool", \
241 (bool) (V) ? "true" : "false"); \
242 else \
243 printf (" %-26s " D " [" #V "]\n", "--" #N "=" #L ".." #H);
244 OPTIONS
245#undef OPTION
246}
247
248/*------------------------------------------------------------------------*/
249
251
252 if (val < 0) {
253 LOG ("ignoring negative optimization mode '%d'", val);
254 return;
255 }
256
257 const int max_val = 31;
258 if (val > max_val) {
259 LOG ("optimization argument '%d' reduced to '%d'", val, max_val);
260 val = max_val;
261 }
262
263 int64_t factor2 = 1;
264 for (int i = 0; i < val && factor2 <= INT_MAX; i++)
265 factor2 *= 2;
266
267 int64_t factor10 = 1;
268 for (int i = 0; i < val && factor10 <= INT_MAX; i++)
269 factor10 *= 10;
270
271 unsigned increased = 0;
272#define OPTION(N, V, L, H, O, P, R, D) \
273 do { \
274 if (!(O)) \
275 break; \
276 const int64_t factor1 = ((O) == 1 ? factor2 : factor10); \
277 int64_t new_val = factor1 * (int64_t) (V); \
278 if (new_val > (H)) \
279 new_val = (H); \
280 if (new_val == (int) (V)) \
281 break; \
282 LOG ("optimization mode '%d' for '%s' " \
283 "gives '%" PRId64 "' instead of '%d", \
284 val, #N, new_val, (int) (V)); \
285 CADICAL_assert (new_val <= INT_MAX); \
286 N = (int) new_val; \
287 increased++; \
288 } while (0);
289 OPTIONS
290#undef OPTION
291 if (increased)
292 MSG ("optimization mode '-O%d' increased %u limits", val, increased);
293}
294
295/*------------------------------------------------------------------------*/
296
297void Options::disable_preprocessing () {
298 size_t count = 0;
299#define OPTION(N, V, L, H, O, P, R, D) \
300 do { \
301 if (!(P)) \
302 break; \
303 if (!(N)) \
304 break; \
305 LOG ("plain mode disables '%s'", #N); \
306 CADICAL_assert ((L) == 0); \
307 CADICAL_assert ((H) == 1); \
308 count++; \
309 N = 0; \
310 } while (0);
311 OPTIONS
312#undef OPTION
313 LOG ("forced plain mode disabled %zd preprocessing options", count);
314#ifndef LOGGING
315 (void) count;
316#endif
317}
318
320 Option *o = has (name);
321 return o ? o->preprocessing : false;
322}
323
324/*------------------------------------------------------------------------*/
325
326void Options::reset_default_values () {
327 size_t count = 0;
328#define OPTION(N, V, L, H, O, P, R, D) \
329 do { \
330 if (!(R)) \
331 break; \
332 if (N == (V)) \
333 break; \
334 LOG ("resetting option '%s' to default %s", #N, #V); \
335 count++; \
336 N = (int) (V); \
337 } while (0);
338 OPTIONS
339#undef OPTION
340 LOG ("reset %zd options to their default values", count);
341#ifndef LOGGING
342 (void) count;
343#endif
344}
345
346/*------------------------------------------------------------------------*/
347
348void Options::copy (Options &other) const {
349#ifdef LOGGING
350 Internal *internal = other.internal;
351#endif
352#define OPTION(N, V, L, H, O, P, R, D) \
353 if ((N) == (int) (V)) \
354 LOG ("keeping non default option '--%s=%s'", #N, #V); \
355 else if ((N) != (int) (V)) { \
356 LOG ("overwriting default option by '--%s=%d'", #N, N); \
357 other.N = N; \
358 }
359 OPTIONS
360#undef OPTION
361}
362
363} // namespace CaDiCaL
364
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
friend struct Option
Definition options.hpp:321
void copy(Options &other) const
void optimize(int val)
static int reportdefault
Definition options.hpp:341
int get(const char *name)
static Option * has(const char *name)
OPTIONS int & val(size_t idx)
Definition options.hpp:363
static bool is_preprocessing_option(const char *name)
static bool parse_long_option(const char *, string &, int &)
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
#define MSG(...)
Definition message.hpp:49
char * name
Definition main.h:24
enum keys key
Definition main.h:25
bool parse_int_str(const char *val_str, int &val)
#define OPTIONS
Definition options.hpp:24
const char * name
Definition options.hpp:295
int & val(Options *)
Definition options.hpp:412
int strlen()
int strcmp()
char * getenv()