1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3 /*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8 /* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12 #include <minizinc/ast.hh>
13 #include <minizinc/astexception.hh>
14 #include <minizinc/astiterator.hh>
15 #include <minizinc/builtins.hh>
16 #include <minizinc/config.hh>
17 #include <minizinc/eval_par.hh>
18 #include <minizinc/file_utils.hh>
19 #include <minizinc/flat_exp.hh>
20 #include <minizinc/flatten_internal.hh>
21 #include <minizinc/output.hh>
22 #include <minizinc/prettyprinter.hh>
23 #include <minizinc/support/regex.hh>
24 #include <minizinc/typecheck.hh>
25
26 #include <climits>
27 #include <cmath>
28 #include <iomanip>
29 #include <random>
30 #include <regex>
31
32 namespace MiniZinc {
33
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_e b,bool fromGlobals=false)34 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
35 FunctionI::builtin_e b, bool fromGlobals = false) {
36 FunctionI* fi = m->matchFn(env, id, t, false);
37 if (fi != nullptr) {
38 fi->builtins.e = b;
39 } else if (!fromGlobals) {
40 std::ostringstream ss;
41 ss << "no definition found for builtin " << id;
42 throw InternalError(ss.str());
43 }
44 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_f b,bool fromGlobals=false)45 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
46 FunctionI::builtin_f b, bool fromGlobals = false) {
47 FunctionI* fi = m->matchFn(env, id, t, false);
48 if (fi != nullptr) {
49 fi->builtins.f = b;
50 } else if (!fromGlobals) {
51 std::ostringstream ss;
52 ss << "no definition found for builtin " << id;
53 throw InternalError(ss.str());
54 }
55 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_i b,bool fromGlobals=false)56 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
57 FunctionI::builtin_i b, bool fromGlobals = false) {
58 FunctionI* fi = m->matchFn(env, id, t, false);
59 if (fi != nullptr) {
60 fi->builtins.i = b;
61 } else if (!fromGlobals) {
62 std::ostringstream ss;
63 ss << "no definition found for builtin " << id;
64 throw InternalError(ss.str());
65 }
66 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_b b,bool fromGlobals=false)67 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
68 FunctionI::builtin_b b, bool fromGlobals = false) {
69 FunctionI* fi = m->matchFn(env, id, t, false);
70 if (fi != nullptr) {
71 fi->builtins.b = b;
72 } else if (!fromGlobals) {
73 std::ostringstream ss;
74 ss << "no definition found for builtin " << id;
75 throw InternalError(ss.str());
76 }
77 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_s b,bool fromGlobals=false)78 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
79 FunctionI::builtin_s b, bool fromGlobals = false) {
80 FunctionI* fi = m->matchFn(env, id, t, false);
81 if (fi != nullptr) {
82 fi->builtins.s = b;
83 } else if (!fromGlobals) {
84 std::ostringstream ss;
85 ss << "no definition found for builtin " << id;
86 throw InternalError(ss.str());
87 }
88 }
rb(EnvI & env,Model * m,const ASTString & id,const std::vector<Type> & t,FunctionI::builtin_str b,bool fromGlobals=false)89 void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
90 FunctionI::builtin_str b, bool fromGlobals = false) {
91 FunctionI* fi = m->matchFn(env, id, t, false);
92 if (fi != nullptr) {
93 fi->builtins.str = b;
94 } else if (!fromGlobals) {
95 std::ostringstream ss;
96 ss << "no definition found for builtin " << id;
97 throw InternalError(ss.str());
98 }
99 }
100
b_int_min(EnvI & env,Call * call)101 IntVal b_int_min(EnvI& env, Call* call) {
102 switch (call->argCount()) {
103 case 1:
104 if (call->arg(0)->type().isSet()) {
105 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
106 } else {
107 GCLock lock;
108 ArrayLit* al = eval_array_lit(env, call->arg(0));
109 if (al->size() == 0) {
110 throw ResultUndefinedError(env, al->loc(), "minimum of empty array is undefined");
111 }
112 IntVal m = eval_int(env, (*al)[0]);
113 for (unsigned int i = 1; i < al->size(); i++) {
114 m = std::min(m, eval_int(env, (*al)[i]));
115 }
116 return m;
117 }
118 case 2: {
119 return std::min(eval_int(env, call->arg(0)), eval_int(env, call->arg(1)));
120 }
121 default:
122 throw EvalError(env, Location(), "dynamic type error");
123 }
124 }
125
b_int_max(EnvI & env,Call * call)126 IntVal b_int_max(EnvI& env, Call* call) {
127 switch (call->argCount()) {
128 case 1:
129 if (call->arg(0)->type().isSet()) {
130 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
131 } else {
132 GCLock lock;
133 ArrayLit* al = eval_array_lit(env, call->arg(0));
134 if (al->size() == 0) {
135 throw ResultUndefinedError(env, al->loc(), "maximum of empty array is undefined");
136 }
137 IntVal m = eval_int(env, (*al)[0]);
138 for (unsigned int i = 1; i < al->size(); i++) {
139 m = std::max(m, eval_int(env, (*al)[i]));
140 }
141 return m;
142 }
143 case 2: {
144 return std::max(eval_int(env, call->arg(0)), eval_int(env, call->arg(1)));
145 }
146 default:
147 throw EvalError(env, Location(), "dynamic type error");
148 }
149 }
150
b_arg_min_bool(EnvI & env,Call * call)151 IntVal b_arg_min_bool(EnvI& env, Call* call) {
152 GCLock lock;
153 ArrayLit* al = eval_array_lit(env, call->arg(0));
154 if (al->size() == 0) {
155 throw ResultUndefinedError(env, al->loc(), "arg_min of empty array is undefined");
156 }
157 assert(al->dims() == 1);
158 for (unsigned int i = 0; i < al->size(); i++) {
159 bool val = eval_bool(env, (*al)[i]);
160 if (!val) {
161 return IntVal(i) + al->min(0);
162 }
163 }
164 return al->min(0);
165 }
b_arg_max_bool(EnvI & env,Call * call)166 IntVal b_arg_max_bool(EnvI& env, Call* call) {
167 GCLock lock;
168 ArrayLit* al = eval_array_lit(env, call->arg(0));
169 if (al->size() == 0) {
170 throw ResultUndefinedError(env, al->loc(), "arg_max of empty array is undefined");
171 }
172 assert(al->dims() == 1);
173 for (unsigned int i = 0; i < al->size(); i++) {
174 bool val = eval_bool(env, (*al)[i]);
175 if (val) {
176 return IntVal(i) + al->min(0);
177 }
178 }
179 return al->min(0);
180 }
b_arg_min_int(EnvI & env,Call * call)181 IntVal b_arg_min_int(EnvI& env, Call* call) {
182 GCLock lock;
183 ArrayLit* al = eval_array_lit(env, call->arg(0));
184 if (al->size() == 0) {
185 throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined");
186 }
187 assert(al->dims() == 1);
188 IntVal m = eval_int(env, (*al)[0]);
189 unsigned int m_idx = 0;
190 for (unsigned int i = 1; i < al->size(); i++) {
191 IntVal mi = eval_int(env, (*al)[i]);
192 if (mi < m) {
193 m = mi;
194 m_idx = i;
195 }
196 }
197 return IntVal(m_idx) + al->min(0);
198 }
b_arg_max_int(EnvI & env,Call * call)199 IntVal b_arg_max_int(EnvI& env, Call* call) {
200 GCLock lock;
201 ArrayLit* al = eval_array_lit(env, call->arg(0));
202 if (al->size() == 0) {
203 throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined");
204 }
205 assert(al->dims() == 1);
206 IntVal m = eval_int(env, (*al)[0]);
207 unsigned int m_idx = 0;
208 for (unsigned int i = 1; i < al->size(); i++) {
209 IntVal mi = eval_int(env, (*al)[i]);
210 if (mi > m) {
211 m = mi;
212 m_idx = i;
213 }
214 }
215 return IntVal(m_idx) + al->min(0);
216 }
b_arg_min_float(EnvI & env,Call * call)217 IntVal b_arg_min_float(EnvI& env, Call* call) {
218 GCLock lock;
219 ArrayLit* al = eval_array_lit(env, call->arg(0));
220 if (al->size() == 0) {
221 throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined");
222 }
223 assert(al->dims() == 1);
224 FloatVal m = eval_float(env, (*al)[0]);
225 unsigned int m_idx = 0;
226 for (unsigned int i = 1; i < al->size(); i++) {
227 FloatVal mi = eval_float(env, (*al)[i]);
228 if (mi < m) {
229 m = mi;
230 m_idx = i;
231 }
232 }
233 return IntVal(m_idx) + al->min(0);
234 }
b_arg_max_float(EnvI & env,Call * call)235 IntVal b_arg_max_float(EnvI& env, Call* call) {
236 GCLock lock;
237 ArrayLit* al = eval_array_lit(env, call->arg(0));
238 if (al->size() == 0) {
239 throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined");
240 }
241 assert(al->dims() == 1);
242 FloatVal m = eval_float(env, (*al)[0]);
243 unsigned int m_idx = 0;
244 for (unsigned int i = 1; i < al->size(); i++) {
245 FloatVal mi = eval_float(env, (*al)[i]);
246 if (mi > m) {
247 m = mi;
248 m_idx = i;
249 }
250 }
251 return IntVal(m_idx) + al->min(0);
252 }
253
b_abs_int(EnvI & env,Call * call)254 IntVal b_abs_int(EnvI& env, Call* call) {
255 assert(call->argCount() == 1);
256 return std::abs(eval_int(env, call->arg(0)));
257 }
258
b_abs_float(EnvI & env,Call * call)259 FloatVal b_abs_float(EnvI& env, Call* call) {
260 assert(call->argCount() == 1);
261 return std::abs(eval_float(env, call->arg(0)));
262 }
263
b_has_bounds_int(EnvI & env,Call * call)264 bool b_has_bounds_int(EnvI& env, Call* call) {
265 if (call->argCount() != 1) {
266 throw EvalError(env, Location(), "dynamic type error");
267 }
268 IntBounds ib = compute_int_bounds(env, call->arg(0));
269 return ib.valid && ib.l.isFinite() && ib.u.isFinite();
270 }
b_has_bounds_float(EnvI & env,Call * call)271 bool b_has_bounds_float(EnvI& env, Call* call) {
272 if (call->argCount() != 1) {
273 throw EvalError(env, Location(), "dynamic type error");
274 }
275 FloatBounds fb = compute_float_bounds(env, call->arg(0));
276 return fb.valid;
277 }
278
lb_varoptint(EnvI & env,Expression * e)279 IntVal lb_varoptint(EnvI& env, Expression* e) {
280 IntBounds b = compute_int_bounds(env, e);
281 if (b.valid) {
282 return b.l;
283 }
284 return -IntVal::infinity();
285 }
b_lb_varoptint(EnvI & env,Call * call)286 IntVal b_lb_varoptint(EnvI& env, Call* call) {
287 if (call->argCount() != 1) {
288 throw EvalError(env, Location(), "dynamic type error");
289 }
290 return lb_varoptint(env, call->arg(0));
291 }
292
b_occurs(EnvI & env,Call * call)293 bool b_occurs(EnvI& env, Call* call) {
294 GCLock lock;
295 return eval_par(env, call->arg(0)) != constants().absent;
296 }
297
b_deopt_int(EnvI & env,Call * call)298 IntVal b_deopt_int(EnvI& env, Call* call) {
299 GCLock lock;
300 Expression* e = eval_par(env, call->arg(0));
301 if (e == constants().absent) {
302 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
303 }
304 return eval_int(env, e);
305 }
306
b_deopt_bool(EnvI & env,Call * call)307 bool b_deopt_bool(EnvI& env, Call* call) {
308 GCLock lock;
309 Expression* e = eval_par(env, call->arg(0));
310 if (e == constants().absent) {
311 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
312 }
313 return eval_bool(env, e);
314 }
315
b_deopt_float(EnvI & env,Call * call)316 FloatVal b_deopt_float(EnvI& env, Call* call) {
317 GCLock lock;
318 Expression* e = eval_par(env, call->arg(0));
319 if (e == constants().absent) {
320 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
321 }
322 return eval_float(env, e);
323 }
324
b_deopt_intset(EnvI & env,Call * call)325 IntSetVal* b_deopt_intset(EnvI& env, Call* call) {
326 GCLock lock;
327 Expression* e = eval_par(env, call->arg(0));
328 if (e == constants().absent) {
329 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
330 }
331 return eval_intset(env, e);
332 }
333
b_deopt_string(EnvI & env,Call * call)334 std::string b_deopt_string(EnvI& env, Call* call) {
335 GCLock lock;
336 Expression* e = eval_par(env, call->arg(0));
337 if (e == constants().absent) {
338 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
339 }
340 return eval_string(env, e);
341 }
342
b_deopt_expr(EnvI & env,Call * call)343 Expression* b_deopt_expr(EnvI& env, Call* call) {
344 GCLock lock;
345 Expression* e = eval_par(env, call->arg(0));
346 if (e == constants().absent) {
347 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
348 }
349 return e;
350 };
351
b_array_lb_int(EnvI & env,Call * call)352 IntVal b_array_lb_int(EnvI& env, Call* call) {
353 assert(call->argCount() == 1);
354 Expression* e = follow_id_to_decl(call->arg(0));
355
356 bool foundMin = false;
357 IntVal array_lb = -IntVal::infinity();
358
359 if (auto* vd = e->dynamicCast<VarDecl>()) {
360 if (vd->ti()->domain() != nullptr) {
361 GCLock lock;
362 IntSetVal* isv = eval_intset(env, vd->ti()->domain());
363 if (isv->size() != 0) {
364 array_lb = isv->min();
365 foundMin = true;
366 }
367 }
368 e = vd->e();
369 }
370
371 if (e != nullptr) {
372 GCLock lock;
373 ArrayLit* al = eval_array_lit(env, e);
374 if (al->size() == 0) {
375 throw EvalError(env, Location(), "lower bound of empty array undefined");
376 }
377 IntVal min = IntVal::infinity();
378 for (unsigned int i = 0; i < al->size(); i++) {
379 IntBounds ib = compute_int_bounds(env, (*al)[i]);
380 if (!ib.valid) {
381 goto b_array_lb_int_done;
382 }
383 min = std::min(min, ib.l);
384 }
385 if (foundMin) {
386 array_lb = std::max(array_lb, min);
387 } else {
388 array_lb = min;
389 }
390 foundMin = true;
391 }
392 b_array_lb_int_done:
393 if (foundMin) {
394 return array_lb;
395 } else {
396 return -IntVal::infinity();
397 }
398 }
399
ub_varoptint(EnvI & env,Expression * e)400 IntVal ub_varoptint(EnvI& env, Expression* e) {
401 IntBounds b = compute_int_bounds(env, e);
402 if (b.valid) {
403 return b.u;
404 }
405 return IntVal::infinity();
406 }
b_ub_varoptint(EnvI & env,Call * call)407 IntVal b_ub_varoptint(EnvI& env, Call* call) {
408 if (call->argCount() != 1) {
409 throw EvalError(env, Location(), "dynamic type error");
410 }
411 return ub_varoptint(env, call->arg(0));
412 }
413
b_array_ub_int(EnvI & env,Call * call)414 IntVal b_array_ub_int(EnvI& env, Call* call) {
415 assert(call->argCount() == 1);
416 Expression* e = follow_id_to_decl(call->arg(0));
417
418 bool foundMax = false;
419 IntVal array_ub = IntVal::infinity();
420
421 if (auto* vd = e->dynamicCast<VarDecl>()) {
422 if (vd->ti()->domain() != nullptr) {
423 GCLock lock;
424 IntSetVal* isv = eval_intset(env, vd->ti()->domain());
425 if (isv->size() != 0) {
426 array_ub = isv->max();
427 foundMax = true;
428 }
429 }
430 e = vd->e();
431 }
432
433 if (e != nullptr) {
434 GCLock lock;
435 ArrayLit* al = eval_array_lit(env, e);
436 if (al->size() == 0) {
437 throw EvalError(env, Location(), "upper bound of empty array undefined");
438 }
439 IntVal max = -IntVal::infinity();
440 for (unsigned int i = 0; i < al->size(); i++) {
441 IntBounds ib = compute_int_bounds(env, (*al)[i]);
442 if (!ib.valid) {
443 goto b_array_ub_int_done;
444 }
445 max = std::max(max, ib.u);
446 }
447 if (foundMax) {
448 array_ub = std::min(array_ub, max);
449 } else {
450 array_ub = max;
451 }
452 foundMax = true;
453 }
454 b_array_ub_int_done:
455 if (foundMax) {
456 return array_ub;
457 } else {
458 return IntVal::infinity();
459 }
460 }
461
b_idiv(EnvI & env,Call * call)462 IntVal b_idiv(EnvI& env, Call* call) {
463 assert(call->argCount() == 2);
464 IntVal a = eval_int(env, call->arg(0));
465 IntVal b = eval_int(env, call->arg(1));
466 if (b == 0) {
467 throw ResultUndefinedError(env, call->loc(), "division by zero");
468 }
469 return a / b;
470 }
b_mod(EnvI & env,Call * call)471 IntVal b_mod(EnvI& env, Call* call) {
472 assert(call->argCount() == 2);
473 IntVal a = eval_int(env, call->arg(0));
474 IntVal b = eval_int(env, call->arg(1));
475 if (b == 0) {
476 throw ResultUndefinedError(env, call->loc(), "division by zero");
477 }
478 return a % b;
479 }
b_fdiv(EnvI & env,Call * call)480 FloatVal b_fdiv(EnvI& env, Call* call) {
481 assert(call->argCount() == 2);
482 FloatVal a = eval_float(env, call->arg(0));
483 FloatVal b = eval_float(env, call->arg(1));
484 if (b == 0.0) {
485 throw ResultUndefinedError(env, call->loc(), "division by zero");
486 }
487 return a / b;
488 }
b_dotdot(EnvI & env,Call * call)489 IntSetVal* b_dotdot(EnvI& env, Call* call) {
490 assert(call->argCount() == 2);
491 IntVal a = eval_int(env, call->arg(0));
492 IntVal b = eval_int(env, call->arg(1));
493 return IntSetVal::a(a, b);
494 }
495
b_sum_int(EnvI & env,Call * call)496 IntVal b_sum_int(EnvI& env, Call* call) {
497 assert(call->argCount() == 1);
498 GCLock lock;
499 ArrayLit* al = eval_array_lit(env, call->arg(0));
500 if (al->size() == 0) {
501 return 0;
502 }
503 IntVal m = 0;
504 for (unsigned int i = 0; i < al->size(); i++) {
505 m += eval_int(env, (*al)[i]);
506 }
507 return m;
508 }
509
b_product_int(EnvI & env,Call * call)510 IntVal b_product_int(EnvI& env, Call* call) {
511 assert(call->argCount() == 1);
512 GCLock lock;
513 ArrayLit* al = eval_array_lit(env, call->arg(0));
514 if (al->size() == 0) {
515 return 1;
516 }
517 IntVal m = 1;
518 for (unsigned int i = 0; i < al->size(); i++) {
519 m *= eval_int(env, (*al)[i]);
520 }
521 return m;
522 }
523
b_product_float(EnvI & env,Call * call)524 FloatVal b_product_float(EnvI& env, Call* call) {
525 assert(call->argCount() == 1);
526 GCLock lock;
527 ArrayLit* al = eval_array_lit(env, call->arg(0));
528 if (al->size() == 0) {
529 return 1;
530 }
531 FloatVal m = 1.0;
532 for (unsigned int i = 0; i < al->size(); i++) {
533 m *= eval_float(env, (*al)[i]);
534 }
535 return m;
536 }
537
lb_varoptfloat(EnvI & env,Expression * e)538 FloatVal lb_varoptfloat(EnvI& env, Expression* e) {
539 FloatBounds b = compute_float_bounds(env, e);
540 if (b.valid) {
541 return b.l;
542 }
543 throw EvalError(env, e->loc(), "cannot determine bounds");
544 }
ub_varoptfloat(EnvI & env,Expression * e)545 FloatVal ub_varoptfloat(EnvI& env, Expression* e) {
546 FloatBounds b = compute_float_bounds(env, e);
547 if (b.valid) {
548 return b.u;
549 }
550 throw EvalError(env, e->loc(), "cannot determine bounds");
551 }
552
b_lb_varoptfloat(EnvI & env,Call * call)553 FloatVal b_lb_varoptfloat(EnvI& env, Call* call) {
554 if (call->argCount() != 1) {
555 throw EvalError(env, Location(), "dynamic type error");
556 }
557 return lb_varoptfloat(env, call->arg(0));
558 }
b_ub_varoptfloat(EnvI & env,Call * call)559 FloatVal b_ub_varoptfloat(EnvI& env, Call* call) {
560 if (call->argCount() != 1) {
561 throw EvalError(env, Location(), "dynamic type error");
562 }
563 return ub_varoptfloat(env, call->arg(0));
564 }
565
b_array_lb_float(EnvI & env,Call * call)566 FloatVal b_array_lb_float(EnvI& env, Call* call) {
567 assert(call->argCount() == 1);
568 Expression* e = follow_id_to_decl(call->arg(0));
569
570 bool foundMin = false;
571 FloatVal array_lb = 0.0;
572
573 if (auto* vd = e->dynamicCast<VarDecl>()) {
574 if (vd->ti()->domain() != nullptr) {
575 FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain());
576 array_lb = fsv->min();
577 foundMin = true;
578 }
579 e = vd->e();
580 }
581
582 if (e != nullptr) {
583 GCLock lock;
584 ArrayLit* al = eval_array_lit(env, e);
585 if (al->size() == 0) {
586 throw EvalError(env, Location(), "lower bound of empty array undefined");
587 }
588 bool min_valid = false;
589 FloatVal min = 0.0;
590 for (unsigned int i = 0; i < al->size(); i++) {
591 FloatBounds fb = compute_float_bounds(env, (*al)[i]);
592 if (!fb.valid) {
593 goto b_array_lb_float_done;
594 }
595 if (min_valid) {
596 min = std::min(min, fb.l);
597 } else {
598 min_valid = true;
599 min = fb.l;
600 }
601 }
602 assert(min_valid);
603 if (foundMin) {
604 array_lb = std::max(array_lb, min);
605 } else {
606 array_lb = min;
607 }
608 foundMin = true;
609 }
610 b_array_lb_float_done:
611 if (foundMin) {
612 return array_lb;
613 } else {
614 throw EvalError(env, e->loc(), "cannot determine lower bound");
615 }
616 }
617
b_array_ub_float(EnvI & env,Call * call)618 FloatVal b_array_ub_float(EnvI& env, Call* call) {
619 assert(call->argCount() == 1);
620 Expression* e = follow_id_to_decl(call->arg(0));
621
622 bool foundMax = false;
623 FloatVal array_ub = 0.0;
624
625 if (auto* vd = e->dynamicCast<VarDecl>()) {
626 if (vd->ti()->domain() != nullptr) {
627 FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain());
628 array_ub = fsv->max();
629 foundMax = true;
630 }
631 e = vd->e();
632 }
633
634 if (e != nullptr) {
635 GCLock lock;
636 ArrayLit* al = eval_array_lit(env, e);
637 if (al->size() == 0) {
638 throw EvalError(env, Location(), "upper bound of empty array undefined");
639 }
640 bool max_valid = false;
641 FloatVal max = 0.0;
642 for (unsigned int i = 0; i < al->size(); i++) {
643 FloatBounds fb = compute_float_bounds(env, (*al)[i]);
644 if (!fb.valid) {
645 goto b_array_ub_float_done;
646 }
647 if (max_valid) {
648 max = std::max(max, fb.u);
649 } else {
650 max_valid = true;
651 max = fb.u;
652 }
653 }
654 assert(max_valid);
655 if (foundMax) {
656 array_ub = std::min(array_ub, max);
657 } else {
658 array_ub = max;
659 }
660 foundMax = true;
661 }
662 b_array_ub_float_done:
663 if (foundMax) {
664 return array_ub;
665 } else {
666 throw EvalError(env, e->loc(), "cannot determine upper bound");
667 }
668 }
669
b_sum_float(EnvI & env,Call * call)670 FloatVal b_sum_float(EnvI& env, Call* call) {
671 assert(call->argCount() == 1);
672 GCLock lock;
673 ArrayLit* al = eval_array_lit(env, call->arg(0));
674 if (al->size() == 0) {
675 return 0;
676 }
677 FloatVal m = 0;
678 for (unsigned int i = 0; i < al->size(); i++) {
679 m += eval_float(env, (*al)[i]);
680 }
681 return m;
682 }
683
b_float_min(EnvI & env,Call * call)684 FloatVal b_float_min(EnvI& env, Call* call) {
685 switch (call->argCount()) {
686 case 1:
687 if (call->arg(0)->type().isSet()) {
688 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
689 } else {
690 GCLock lock;
691 ArrayLit* al = eval_array_lit(env, call->arg(0));
692 if (al->size() == 0) {
693 throw EvalError(env, al->loc(), "min on empty array undefined");
694 }
695 FloatVal m = eval_float(env, (*al)[0]);
696 for (unsigned int i = 1; i < al->size(); i++) {
697 m = std::min(m, eval_float(env, (*al)[i]));
698 }
699 return m;
700 }
701 case 2: {
702 return std::min(eval_float(env, call->arg(0)), eval_float(env, call->arg(1)));
703 }
704 default:
705 throw EvalError(env, Location(), "dynamic type error");
706 }
707 }
708
b_float_max(EnvI & env,Call * call)709 FloatVal b_float_max(EnvI& env, Call* call) {
710 switch (call->argCount()) {
711 case 1:
712 if (call->arg(0)->type().isSet()) {
713 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
714 } else {
715 GCLock lock;
716 ArrayLit* al = eval_array_lit(env, call->arg(0));
717 if (al->size() == 0) {
718 throw EvalError(env, al->loc(), "max on empty array undefined");
719 }
720 FloatVal m = eval_float(env, (*al)[0]);
721 for (unsigned int i = 1; i < al->size(); i++) {
722 m = std::max(m, eval_float(env, (*al)[i]));
723 }
724 return m;
725 }
726 case 2: {
727 return std::max(eval_float(env, call->arg(0)), eval_float(env, call->arg(1)));
728 }
729 default:
730 throw EvalError(env, Location(), "dynamic type error");
731 }
732 }
733
b_index_set(EnvI & env,Expression * e,int i)734 IntSetVal* b_index_set(EnvI& env, Expression* e, int i) {
735 if (e->eid() != Expression::E_ID) {
736 GCLock lock;
737 ArrayLit* al = eval_array_lit(env, e);
738 if (al->dims() < i) {
739 throw EvalError(env, e->loc(), "index_set: wrong dimension");
740 }
741 return IntSetVal::a(al->min(i - 1), al->max(i - 1));
742 }
743 Id* id = e->cast<Id>();
744 if (id->decl() == nullptr) {
745 throw EvalError(env, id->loc(), "undefined identifier");
746 }
747 if ((id->decl()->ti()->ranges().size() == 1 &&
748 id->decl()->ti()->ranges()[0]->domain() != nullptr &&
749 id->decl()->ti()->ranges()[0]->domain()->isa<TIId>()) ||
750 (static_cast<int>(id->decl()->ti()->ranges().size()) >= i &&
751 (id->decl()->ti()->ranges()[i - 1]->domain() == nullptr ||
752 id->decl()->ti()->ranges()[i - 1]->domain()->isa<TIId>()))) {
753 GCLock lock;
754 ArrayLit* al = eval_array_lit(env, id);
755 if (al->dims() < i) {
756 throw EvalError(env, id->loc(), "index_set: wrong dimension");
757 }
758 return IntSetVal::a(al->min(i - 1), al->max(i - 1));
759 }
760 if (static_cast<int>(id->decl()->ti()->ranges().size()) < i) {
761 throw EvalError(env, id->loc(), "index_set: wrong dimension");
762 }
763 return eval_intset(env, id->decl()->ti()->ranges()[i - 1]->domain());
764 }
b_index_sets_agree(EnvI & env,Call * call)765 bool b_index_sets_agree(EnvI& env, Call* call) {
766 if (call->argCount() != 2) {
767 throw EvalError(env, Location(), "index_sets_agree needs exactly two arguments");
768 }
769 GCLock lock;
770 ArrayLit* al0 = eval_array_lit(env, call->arg(0));
771 ArrayLit* al1 = eval_array_lit(env, call->arg(1));
772 if (al0->type().dim() != al1->type().dim()) {
773 return false;
774 }
775 for (int i = 1; i <= al0->type().dim(); i++) {
776 IntSetVal* index0 = b_index_set(env, al0, i);
777 IntSetVal* index1 = b_index_set(env, al1, i);
778 if (!index0->equal(index1)) {
779 return false;
780 }
781 }
782 return true;
783 }
b_index_set1(EnvI & env,Call * call)784 IntSetVal* b_index_set1(EnvI& env, Call* call) {
785 if (call->argCount() != 1) {
786 throw EvalError(env, Location(), "index_set needs exactly one argument");
787 }
788 return b_index_set(env, call->arg(0), 1);
789 }
b_index_set2(EnvI & env,Call * call)790 IntSetVal* b_index_set2(EnvI& env, Call* call) {
791 if (call->argCount() != 1) {
792 throw EvalError(env, Location(), "index_set needs exactly one argument");
793 }
794 return b_index_set(env, call->arg(0), 2);
795 }
b_index_set3(EnvI & env,Call * call)796 IntSetVal* b_index_set3(EnvI& env, Call* call) {
797 if (call->argCount() != 1) {
798 throw EvalError(env, Location(), "index_set needs exactly one argument");
799 }
800 return b_index_set(env, call->arg(0), 3);
801 }
b_index_set4(EnvI & env,Call * call)802 IntSetVal* b_index_set4(EnvI& env, Call* call) {
803 if (call->argCount() != 1) {
804 throw EvalError(env, Location(), "index_set needs exactly one argument");
805 }
806 return b_index_set(env, call->arg(0), 4);
807 }
b_index_set5(EnvI & env,Call * call)808 IntSetVal* b_index_set5(EnvI& env, Call* call) {
809 if (call->argCount() != 1) {
810 throw EvalError(env, Location(), "index_set needs exactly one argument");
811 }
812 return b_index_set(env, call->arg(0), 5);
813 }
b_index_set6(EnvI & env,Call * call)814 IntSetVal* b_index_set6(EnvI& env, Call* call) {
815 if (call->argCount() != 1) {
816 throw EvalError(env, Location(), "index_set needs exactly one argument");
817 }
818 return b_index_set(env, call->arg(0), 6);
819 }
820
b_min_parsetint(EnvI & env,Call * call)821 IntVal b_min_parsetint(EnvI& env, Call* call) {
822 assert(call->argCount() == 1);
823 IntSetVal* isv = eval_intset(env, call->arg(0));
824 return isv->min();
825 }
b_max_parsetint(EnvI & env,Call * call)826 IntVal b_max_parsetint(EnvI& env, Call* call) {
827 assert(call->argCount() == 1);
828 IntSetVal* isv = eval_intset(env, call->arg(0));
829 return isv->max();
830 }
b_lb_set(EnvI & env,Call * e)831 IntSetVal* b_lb_set(EnvI& env, Call* e) {
832 Expression* ee = follow_id_to_value(e->arg(0));
833 if (ee->type().isPar()) {
834 return eval_intset(env, ee);
835 }
836 return IntSetVal::a();
837 }
b_ub_set(EnvI & env,Expression * e)838 IntSetVal* b_ub_set(EnvI& env, Expression* e) {
839 IntSetVal* isv = compute_intset_bounds(env, e);
840 if (isv != nullptr) {
841 return isv;
842 }
843 throw EvalError(env, e->loc(), "cannot determine bounds of set expression");
844 }
b_ub_set(EnvI & env,Call * call)845 IntSetVal* b_ub_set(EnvI& env, Call* call) {
846 assert(call->argCount() == 1);
847 return b_ub_set(env, call->arg(0));
848 }
b_has_ub_set(EnvI & env,Call * call)849 bool b_has_ub_set(EnvI& env, Call* call) {
850 Expression* e = call->arg(0);
851 for (;;) {
852 switch (e->eid()) {
853 case Expression::E_SETLIT:
854 return true;
855 case Expression::E_ID: {
856 Id* id = e->cast<Id>();
857 if (id->decl() == nullptr) {
858 throw EvalError(env, id->loc(), "undefined identifier");
859 }
860 if (id->decl()->e() == nullptr) {
861 return id->decl()->ti()->domain() != nullptr;
862 }
863 e = id->decl()->e();
864
865 } break;
866 default:
867 throw EvalError(env, e->loc(), "invalid argument to has_ub_set");
868 }
869 }
870 }
871
b_array_ub_set(EnvI & env,Call * call)872 IntSetVal* b_array_ub_set(EnvI& env, Call* call) {
873 assert(call->argCount() == 1);
874 GCLock lock;
875 ArrayLit* al = eval_array_lit(env, call->arg(0));
876 if (al->size() == 0) {
877 throw EvalError(env, Location(), "upper bound of empty array undefined");
878 }
879 IntSetVal* ub = b_ub_set(env, (*al)[0]);
880 for (unsigned int i = 1; i < al->size(); i++) {
881 IntSetRanges isr(ub);
882 IntSetRanges r(b_ub_set(env, (*al)[i]));
883 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
884 ub = IntSetVal::ai(u);
885 }
886 return ub;
887 }
888
b_dom_varint(EnvI & env,Expression * e)889 IntSetVal* b_dom_varint(EnvI& env, Expression* e) {
890 Id* lastid = nullptr;
891 Expression* cur = e;
892 for (;;) {
893 if (cur == nullptr) {
894 if (lastid == nullptr || lastid->decl()->ti()->domain() == nullptr) {
895 IntBounds b = compute_int_bounds(env, e);
896 if (b.valid) {
897 return IntSetVal::a(b.l, b.u);
898 }
899 return IntSetVal::a(-IntVal::infinity(), IntVal::infinity());
900 }
901 return eval_intset(env, lastid->decl()->ti()->domain());
902 }
903 switch (cur->eid()) {
904 case Expression::E_INTLIT: {
905 IntVal v = cur->cast<IntLit>()->v();
906 return IntSetVal::a(v, v);
907 }
908 case Expression::E_ID: {
909 lastid = cur->cast<Id>();
910 if (lastid == constants().absent) {
911 return IntSetVal::a(-IntVal::infinity(), IntVal::infinity());
912 }
913 if (lastid->decl() == nullptr) {
914 throw EvalError(env, lastid->loc(), "undefined identifier");
915 }
916 cur = lastid->decl()->e();
917 } break;
918 case Expression::E_ARRAYACCESS: {
919 bool success;
920 cur = eval_arrayaccess(env, cur->cast<ArrayAccess>(), success);
921 if (!success) {
922 cur = nullptr;
923 }
924 } break;
925 default:
926 cur = nullptr;
927 break;
928 }
929 }
930 }
b_dom_varint(EnvI & env,Call * call)931 IntSetVal* b_dom_varint(EnvI& env, Call* call) {
932 assert(call->argCount() == 1);
933 return b_dom_varint(env, call->arg(0));
934 }
935
b_dom_bounds_array(EnvI & env,Call * call)936 IntSetVal* b_dom_bounds_array(EnvI& env, Call* call) {
937 assert(call->argCount() == 1);
938 Expression* arg_e = call->arg(0);
939 Expression* e = follow_id_to_decl(arg_e);
940
941 bool foundBounds = false;
942 IntVal array_lb = -IntVal::infinity();
943 IntVal array_ub = IntVal::infinity();
944
945 if (auto* vd = e->dynamicCast<VarDecl>()) {
946 if (vd->ti()->domain() != nullptr) {
947 GCLock lock;
948 IntSetVal* isv = eval_intset(env, vd->ti()->domain());
949 if (isv->size() != 0) {
950 array_lb = isv->min();
951 array_ub = isv->max();
952 foundBounds = true;
953 }
954 }
955 e = vd->e();
956 if (e == nullptr) {
957 e = vd->flat()->e();
958 }
959 }
960
961 if (foundBounds) {
962 return IntSetVal::a(array_lb, array_ub);
963 }
964
965 if (e != nullptr) {
966 GCLock lock;
967 ArrayLit* al = eval_array_lit(env, e);
968 if (al->size() == 0) {
969 throw EvalError(env, Location(), "lower bound of empty array undefined");
970 }
971 IntVal min = IntVal::infinity();
972 IntVal max = -IntVal::infinity();
973 for (unsigned int i = 0; i < al->size(); i++) {
974 IntBounds ib = compute_int_bounds(env, (*al)[i]);
975 if (!ib.valid) {
976 goto b_array_lb_int_done;
977 }
978 min = std::min(min, ib.l);
979 max = std::max(max, ib.u);
980 }
981 array_lb = std::max(array_lb, min);
982 array_ub = std::min(array_ub, max);
983 foundBounds = true;
984 }
985 b_array_lb_int_done:
986 if (foundBounds) {
987 return IntSetVal::a(array_lb, array_ub);
988 } else {
989 throw EvalError(env, e->loc(), "cannot determine lower bound");
990 }
991 }
992
b_dom_array(EnvI & env,Call * call)993 IntSetVal* b_dom_array(EnvI& env, Call* call) {
994 assert(call->argCount() == 1);
995 Expression* ae = call->arg(0);
996 ArrayLit* al = nullptr;
997 while (al == nullptr) {
998 switch (ae->eid()) {
999 case Expression::E_ARRAYLIT:
1000 al = ae->cast<ArrayLit>();
1001 break;
1002 case Expression::E_ID: {
1003 Id* id = ae->cast<Id>();
1004 if (id->decl() == nullptr) {
1005 throw EvalError(env, id->loc(), "undefined identifier");
1006 }
1007 if (id->decl()->e() == nullptr) {
1008 if (id->decl()->flat() == nullptr) {
1009 throw EvalError(env, id->loc(), "array without initialiser");
1010 }
1011 if (id->decl()->flat()->e() == nullptr) {
1012 throw EvalError(env, id->loc(), "array without initialiser");
1013 }
1014 ae = id->decl()->flat()->e();
1015
1016 } else {
1017 ae = id->decl()->e();
1018 }
1019 } break;
1020 default:
1021 throw EvalError(env, ae->loc(), "invalid argument to dom");
1022 }
1023 }
1024 if (al->size() == 0) {
1025 return IntSetVal::a();
1026 }
1027 IntSetVal* isv = b_dom_varint(env, (*al)[0]);
1028 for (unsigned int i = 1; i < al->size(); i++) {
1029 IntSetRanges isr(isv);
1030 IntSetRanges r(b_dom_varint(env, (*al)[i]));
1031 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
1032 isv = IntSetVal::ai(u);
1033 }
1034 return isv;
1035 }
b_compute_div_bounds(EnvI & env,Call * call)1036 IntSetVal* b_compute_div_bounds(EnvI& env, Call* call) {
1037 assert(call->argCount() == 2);
1038 IntBounds bx = compute_int_bounds(env, call->arg(0));
1039 if (!bx.valid) {
1040 throw EvalError(env, call->arg(0)->loc(), "cannot determine bounds");
1041 }
1042 /// TODO: better bounds if only some input bounds are infinite
1043 if (!bx.l.isFinite() || !bx.u.isFinite()) {
1044 return constants().infinity->isv();
1045 }
1046 IntBounds by = compute_int_bounds(env, call->arg(1));
1047 if (!by.valid) {
1048 throw EvalError(env, call->arg(1)->loc(), "cannot determine bounds");
1049 }
1050 if (!by.l.isFinite() || !by.u.isFinite()) {
1051 return constants().infinity->isv();
1052 }
1053 Ranges::Const<IntVal> byr(by.l, by.u);
1054 Ranges::Const<IntVal> by0(0, 0);
1055 Ranges::Diff<IntVal, Ranges::Const<IntVal>, Ranges::Const<IntVal>> byr0(byr, by0);
1056
1057 IntVal min = IntVal::maxint();
1058 IntVal max = IntVal::minint();
1059 if (byr0()) {
1060 min = std::min(min, bx.l / byr0.min());
1061 min = std::min(min, bx.l / byr0.max());
1062 min = std::min(min, bx.u / byr0.min());
1063 min = std::min(min, bx.u / byr0.max());
1064 max = std::max(max, bx.l / byr0.min());
1065 max = std::max(max, bx.l / byr0.max());
1066 max = std::max(max, bx.u / byr0.min());
1067 max = std::max(max, bx.u / byr0.max());
1068 ++byr0;
1069 if (byr0()) {
1070 min = std::min(min, bx.l / byr0.min());
1071 min = std::min(min, bx.l / byr0.max());
1072 min = std::min(min, bx.u / byr0.min());
1073 min = std::min(min, bx.u / byr0.max());
1074 max = std::max(max, bx.l / byr0.min());
1075 max = std::max(max, bx.l / byr0.max());
1076 max = std::max(max, bx.u / byr0.min());
1077 max = std::max(max, bx.u / byr0.max());
1078 }
1079 }
1080 return IntSetVal::a(min, max);
1081 }
1082
1083 // NOLINTNEXTLINE(readability-identifier-naming)
b_arrayXd(EnvI & env,Call * call,int d)1084 ArrayLit* b_arrayXd(EnvI& env, Call* call, int d) {
1085 GCLock lock;
1086 bool check_form = call->ann().contains(constants().ann.array_check_form);
1087 ArrayLit* al = eval_array_lit(env, call->arg(d));
1088 std::vector<std::pair<int, int>> dims(d);
1089 unsigned int dim1d = 1;
1090
1091 if (check_form && d != al->dims()) {
1092 std::ostringstream ss;
1093 ss << "number of dimensions of original array (" << al->dims()
1094 << ") does not match the given number of index sets (" << d << ")";
1095 throw EvalError(env, call->loc(), ss.str());
1096 }
1097
1098 for (int i = 0; i < d; i++) {
1099 IntSetVal* di = eval_intset(env, call->arg(i));
1100 if (di->size() == 0) {
1101 dims[i] = std::pair<int, int>(1, 0);
1102 dim1d = 0;
1103 } else if (di->size() != 1) {
1104 throw EvalError(env, call->arg(i)->loc(), "arrayXd only defined for ranges");
1105 } else {
1106 dims[i] = std::pair<int, int>(static_cast<int>(di->min(0).toInt()),
1107 static_cast<int>(di->max(0).toInt()));
1108 dim1d *= dims[i].second - dims[i].first + 1;
1109 if (check_form && dims[i].second - dims[i].first != al->max(i) - al->min(i)) {
1110 std::ostringstream ss;
1111 ss << "index set " << i + 1 << " (" << dims[i].first << ".." << dims[i].second
1112 << ") does not match index set " << i + 1 << " of original array (" << al->min(i) << ".."
1113 << al->max(i) << ")";
1114 throw EvalError(env, call->arg(i)->loc(), ss.str());
1115 }
1116 }
1117 }
1118 if (dim1d != al->size()) {
1119 throw EvalError(env, al->loc(), "mismatch in array dimensions");
1120 }
1121 auto* ret = new ArrayLit(al->loc(), *al, dims);
1122 Type t = al->type();
1123 t.dim(d);
1124 ret->type(t);
1125 ret->flat(al->flat());
1126 return ret;
1127 }
b_array1d_list(EnvI & env,Call * call)1128 Expression* b_array1d_list(EnvI& env, Call* call) {
1129 GCLock lock;
1130 ArrayLit* al = eval_array_lit(env, call->arg(0));
1131 if (al->dims() == 1 && al->min(0) == 1) {
1132 return call->arg(0)->isa<Id>() ? call->arg(0) : al;
1133 }
1134 auto* ret = new ArrayLit(al->loc(), *al);
1135 Type t = al->type();
1136 t.dim(1);
1137 ret->type(t);
1138 ret->flat(al->flat());
1139 return ret;
1140 }
b_array1d(EnvI & env,Call * call)1141 Expression* b_array1d(EnvI& env, Call* call) { return b_arrayXd(env, call, 1); }
b_array2d(EnvI & env,Call * call)1142 Expression* b_array2d(EnvI& env, Call* call) { return b_arrayXd(env, call, 2); }
b_array3d(EnvI & env,Call * call)1143 Expression* b_array3d(EnvI& env, Call* call) { return b_arrayXd(env, call, 3); }
b_array4d(EnvI & env,Call * call)1144 Expression* b_array4d(EnvI& env, Call* call) { return b_arrayXd(env, call, 4); }
b_array5d(EnvI & env,Call * call)1145 Expression* b_array5d(EnvI& env, Call* call) { return b_arrayXd(env, call, 5); }
b_array6d(EnvI & env,Call * call)1146 Expression* b_array6d(EnvI& env, Call* call) { return b_arrayXd(env, call, 6); }
1147
1148 // NOLINTNEXTLINE(readability-identifier-naming)
b_arrayXd(EnvI & env,Call * call)1149 Expression* b_arrayXd(EnvI& env, Call* call) {
1150 GCLock lock;
1151 ArrayLit* al0 = eval_array_lit(env, call->arg(0));
1152 ArrayLit* al1 = eval_array_lit(env, call->arg(1));
1153 if (al0->dims() == al1->dims()) {
1154 bool sameDims = true;
1155 for (unsigned int i = al0->dims(); (i--) != 0U;) {
1156 if (al0->min(i) != al1->min(i) || al0->max(i) != al1->max(i)) {
1157 sameDims = false;
1158 break;
1159 }
1160 }
1161 if (sameDims) {
1162 return call->arg(1)->isa<Id>() ? call->arg(1) : al1;
1163 }
1164 }
1165 std::vector<std::pair<int, int>> dims(al0->dims());
1166 for (unsigned int i = al0->dims(); (i--) != 0U;) {
1167 dims[i] = std::make_pair(al0->min(i), al0->max(i));
1168 }
1169 auto* ret = new ArrayLit(al1->loc(), *al1, dims);
1170 Type t = al1->type();
1171 t.dim(static_cast<int>(dims.size()));
1172 ret->type(t);
1173 ret->flat(al1->flat());
1174 return ret;
1175 }
1176
b_length(EnvI & env,Call * call)1177 IntVal b_length(EnvI& env, Call* call) {
1178 GCLock lock;
1179 ArrayLit* al = eval_array_lit(env, call->arg(0));
1180 return al->size();
1181 }
1182
b_bool2int(EnvI & env,Call * call)1183 IntVal b_bool2int(EnvI& env, Call* call) { return eval_bool(env, call->arg(0)) ? 1 : 0; }
1184
b_forall_par(EnvI & env,Call * call)1185 bool b_forall_par(EnvI& env, Call* call) {
1186 if (call->argCount() != 1) {
1187 throw EvalError(env, Location(), "forall needs exactly one argument");
1188 }
1189 GCLock lock;
1190 ArrayLit* al = eval_array_lit(env, call->arg(0));
1191 for (unsigned int i = al->size(); (i--) != 0U;) {
1192 if (!eval_bool(env, (*al)[i])) {
1193 return false;
1194 }
1195 }
1196 return true;
1197 }
b_exists_par(EnvI & env,Call * call)1198 bool b_exists_par(EnvI& env, Call* call) {
1199 if (call->argCount() != 1) {
1200 throw EvalError(env, Location(), "exists needs exactly one argument");
1201 }
1202 GCLock lock;
1203 ArrayLit* al = eval_array_lit(env, call->arg(0));
1204 for (unsigned int i = al->size(); (i--) != 0U;) {
1205 if (eval_bool(env, (*al)[i])) {
1206 return true;
1207 }
1208 }
1209 return false;
1210 }
b_clause_par(EnvI & env,Call * call)1211 bool b_clause_par(EnvI& env, Call* call) {
1212 if (call->argCount() != 2) {
1213 throw EvalError(env, Location(), "clause needs exactly two arguments");
1214 }
1215 GCLock lock;
1216 ArrayLit* al = eval_array_lit(env, call->arg(0));
1217 for (unsigned int i = al->size(); (i--) != 0U;) {
1218 if (eval_bool(env, (*al)[i])) {
1219 return true;
1220 }
1221 }
1222 al = eval_array_lit(env, call->arg(1));
1223 for (unsigned int i = al->size(); (i--) != 0U;) {
1224 if (!eval_bool(env, (*al)[i])) {
1225 return true;
1226 }
1227 }
1228 return false;
1229 }
b_xorall_par(EnvI & env,Call * call)1230 bool b_xorall_par(EnvI& env, Call* call) {
1231 if (call->argCount() != 1) {
1232 throw EvalError(env, Location(), "xorall needs exactly one argument");
1233 }
1234 GCLock lock;
1235 int count = 0;
1236 ArrayLit* al = eval_array_lit(env, call->arg(0));
1237 for (unsigned int i = al->size(); (i--) != 0U;) {
1238 count += static_cast<int>(eval_bool(env, (*al)[i]));
1239 }
1240 return count % 2 == 1;
1241 }
b_iffall_par(EnvI & env,Call * call)1242 bool b_iffall_par(EnvI& env, Call* call) {
1243 if (call->argCount() != 1) {
1244 throw EvalError(env, Location(), "xorall needs exactly one argument");
1245 }
1246 GCLock lock;
1247 int count = 0;
1248 ArrayLit* al = eval_array_lit(env, call->arg(0));
1249 for (unsigned int i = al->size(); (i--) != 0U;) {
1250 count += static_cast<int>(eval_bool(env, (*al)[i]));
1251 }
1252 return count % 2 == 0;
1253 }
b_not_par(EnvI & env,Call * call)1254 bool b_not_par(EnvI& env, Call* call) {
1255 assert(call->argCount() == 1);
1256 return !eval_bool(env, call->arg(0));
1257 }
1258
b_card(EnvI & env,Call * call)1259 IntVal b_card(EnvI& env, Call* call) {
1260 if (call->argCount() != 1) {
1261 throw EvalError(env, Location(), "card needs exactly one argument");
1262 }
1263 IntSetVal* isv = eval_intset(env, call->arg(0));
1264 IntSetRanges isr(isv);
1265 return Ranges::cardinality(isr);
1266 }
1267
exp_is_fixed(EnvI & env,Expression * e)1268 Expression* exp_is_fixed(EnvI& env, Expression* e) {
1269 GCLock lock;
1270 Expression* cur = e;
1271 for (;;) {
1272 if (cur == nullptr) {
1273 return nullptr;
1274 }
1275 if (cur->type().isPar()) {
1276 return eval_par(env, cur);
1277 }
1278 switch (cur->eid()) {
1279 case Expression::E_ID:
1280 cur = cur->cast<Id>()->decl();
1281 break;
1282 case Expression::E_VARDECL:
1283 if (cur->type().st() != Type::ST_SET) {
1284 Expression* dom = cur->cast<VarDecl>()->ti()->domain();
1285 if ((dom != nullptr) &&
1286 (dom->isa<IntLit>() || dom->isa<BoolLit>() || dom->isa<FloatLit>())) {
1287 return dom;
1288 }
1289 if ((dom != nullptr) && dom->isa<SetLit>()) {
1290 auto* sl = dom->cast<SetLit>();
1291 auto* isv = sl->isv();
1292 if ((isv != nullptr) && isv->min() == isv->max()) {
1293 return IntLit::a(isv->min());
1294 }
1295 auto* fsv = sl->fsv();
1296 if ((fsv != nullptr) && fsv->min() == fsv->max()) {
1297 return FloatLit::a(fsv->min());
1298 }
1299 }
1300 }
1301 cur = cur->cast<VarDecl>()->e();
1302 break;
1303 default:
1304 return nullptr;
1305 }
1306 }
1307 }
1308
b_is_fixed(EnvI & env,Call * call)1309 bool b_is_fixed(EnvI& env, Call* call) {
1310 assert(call->argCount() == 1);
1311 return exp_is_fixed(env, call->arg(0)) != nullptr;
1312 }
1313
b_is_fixed_array(EnvI & env,Call * call)1314 bool b_is_fixed_array(EnvI& env, Call* call) {
1315 assert(call->argCount() == 1);
1316 GCLock lock;
1317 ArrayLit* al = eval_array_lit(env, call->arg(0));
1318 if (al->size() == 0) {
1319 return true;
1320 }
1321 for (unsigned int i = 0; i < al->size(); i++) {
1322 if (exp_is_fixed(env, (*al)[i]) == nullptr) {
1323 return false;
1324 }
1325 }
1326 return true;
1327 }
1328
b_is_same(EnvI & env,Call * call)1329 bool b_is_same(EnvI& env, Call* call) {
1330 assert(call->argCount() == 2);
1331 return follow_id_to_decl(call->arg(0)) == follow_id_to_decl(call->arg(1));
1332 }
1333
b_fix(EnvI & env,Call * call)1334 Expression* b_fix(EnvI& env, Call* call) {
1335 assert(call->argCount() == 1);
1336 Expression* ret = exp_is_fixed(env, call->arg(0));
1337 if (ret == nullptr) {
1338 throw EvalError(env, call->arg(0)->loc(), "expression is not fixed");
1339 }
1340 return ret;
1341 }
1342
b_fix_int(EnvI & env,Call * call)1343 IntVal b_fix_int(EnvI& env, Call* call) { return eval_int(env, b_fix(env, call)); }
b_fix_bool(EnvI & env,Call * call)1344 bool b_fix_bool(EnvI& env, Call* call) { return eval_bool(env, b_fix(env, call)); }
b_fix_float(EnvI & env,Call * call)1345 FloatVal b_fix_float(EnvI& env, Call* call) { return eval_float(env, b_fix(env, call)); }
b_fix_set(EnvI & env,Call * call)1346 IntSetVal* b_fix_set(EnvI& env, Call* call) { return eval_intset(env, b_fix(env, call)); }
1347
b_fix_array(EnvI & env,Call * call)1348 Expression* b_fix_array(EnvI& env, Call* call) {
1349 assert(call->argCount() == 1);
1350 GCLock lock;
1351 ArrayLit* al = eval_array_lit(env, call->arg(0));
1352 std::vector<Expression*> fixed(al->size());
1353 for (unsigned int i = 0; i < fixed.size(); i++) {
1354 fixed[i] = exp_is_fixed(env, (*al)[i]);
1355 if (fixed[i] == nullptr) {
1356 throw EvalError(env, (*al)[i]->loc(), "expression is not fixed");
1357 }
1358 }
1359 auto* ret = new ArrayLit(Location(), fixed);
1360 Type tt = al->type();
1361 tt.ti(Type::TI_PAR);
1362 ret->type(tt);
1363 return ret;
1364 }
1365
b_has_ann(EnvI & env,Call * call)1366 bool b_has_ann(EnvI& env, Call* call) {
1367 assert(call->argCount() == 2);
1368 Expression* expr = call->arg(0);
1369 if (!expr->isa<Id>()) {
1370 // Argument is a literal, unable to verify annotations
1371 return false;
1372 }
1373 expr = follow_id_to_decl(expr);
1374 Expression* ann = call->arg(1);
1375 if (ann->isa<Id>()) {
1376 return expr->ann().contains(ann);
1377 }
1378 auto* key = ann->cast<Call>();
1379 if (Call* c = expr->ann().getCall(key->id())) {
1380 if (c->argCount() != key->argCount()) {
1381 return false;
1382 }
1383 for (int i = 0; i < c->argCount(); ++i) {
1384 if (c->arg(i)->type() != key->arg(i)->type()) {
1385 return false;
1386 }
1387 if (c->arg(i)->type().isPar()) {
1388 GCLock lock;
1389 Expression* check_eq = new BinOp(Location().introduce(), c->arg(i), BOT_EQ, key->arg(i));
1390 check_eq->type(Type::parbool());
1391 if (!eval_bool(env, check_eq)) {
1392 return false;
1393 }
1394 } else {
1395 if (c->arg(i)->isa<Id>() && key->arg(i)->isa<Id>()) {
1396 if (follow_id_to_decl(c->arg(i)) != follow_id_to_decl(key->arg(i))) {
1397 return false;
1398 }
1399 } else {
1400 throw EvalError(env, call->loc(), "Unable to determine equality of variable expressions");
1401 }
1402 }
1403 }
1404 return true;
1405 }
1406 return false;
1407 }
1408
b_annotate(EnvI & env,Call * call)1409 bool b_annotate(EnvI& env, Call* call) {
1410 assert(call->argCount() == 2);
1411 Expression* expr = call->arg(0);
1412 if (!expr->isa<Id>()) {
1413 // Argument is a literal, unable to annotate
1414 std::ostringstream ss;
1415 ss << "Unable to annotate literal expression `" << *expr << "'.";
1416 env.addWarning(ss.str());
1417 return true;
1418 }
1419 auto* var_decl = follow_id_to_decl(expr)->cast<VarDecl>();
1420 // Add annotation
1421 Expression* ann = call->arg(1);
1422 var_decl->ann().add(ann);
1423 // Increase usage count of the annotation
1424 if (auto* ann_decl = follow_id_to_decl(ann)->dynamicCast<VarDecl>()) {
1425 auto var_it = env.varOccurrences.idx.find(var_decl->id());
1426 assert(var_it != env.varOccurrences.idx.end());
1427 env.varOccurrences.add(ann_decl, (*env.flat())[var_it->second]);
1428 }
1429 return true;
1430 }
1431
b_int2float(EnvI & env,Call * call)1432 FloatVal b_int2float(EnvI& env, Call* call) { return eval_int(env, call->arg(0)); }
b_ceil(EnvI & env,Call * call)1433 IntVal b_ceil(EnvI& env, Call* call) {
1434 return static_cast<IntVal>(std::ceil(eval_float(env, call->arg(0))));
1435 }
b_floor(EnvI & env,Call * call)1436 IntVal b_floor(EnvI& env, Call* call) {
1437 return static_cast<IntVal>(std::floor(eval_float(env, call->arg(0))));
1438 }
b_round(EnvI & env,Call * call)1439 IntVal b_round(EnvI& env, Call* call) {
1440 /// Cast to int truncates, so cannot just add 0.5 and cast
1441 return {static_cast<long long>(std::round(eval_float(env, call->arg(0)).toDouble()))};
1442 }
b_log10(EnvI & env,Call * call)1443 FloatVal b_log10(EnvI& env, Call* call) {
1444 return std::log10(eval_float(env, call->arg(0)).toDouble());
1445 }
b_log2(EnvI & env,Call * call)1446 FloatVal b_log2(EnvI& env, Call* call) {
1447 return std::log(eval_float(env, call->arg(0)).toDouble()) / std::log(2.0);
1448 }
b_ln(EnvI & env,Call * call)1449 FloatVal b_ln(EnvI& env, Call* call) { return std::log(eval_float(env, call->arg(0)).toDouble()); }
b_log(EnvI & env,Call * call)1450 FloatVal b_log(EnvI& env, Call* call) {
1451 return std::log(eval_float(env, call->arg(1)).toDouble()) /
1452 std::log(eval_float(env, call->arg(0)).toDouble());
1453 }
b_exp(EnvI & env,Call * call)1454 FloatVal b_exp(EnvI& env, Call* call) { return std::exp(eval_float(env, call->arg(0)).toDouble()); }
b_pow(EnvI & env,Call * call)1455 FloatVal b_pow(EnvI& env, Call* call) {
1456 return std::pow(eval_float(env, call->arg(0)).toDouble(),
1457 eval_float(env, call->arg(1)).toDouble());
1458 }
b_pow_int(EnvI & env,Call * call)1459 IntVal b_pow_int(EnvI& env, Call* call) {
1460 IntVal p = eval_int(env, call->arg(0));
1461 IntVal r = 1;
1462 long long int e = eval_int(env, call->arg(1)).toInt();
1463 if (e < 0) {
1464 throw EvalError(env, call->arg(1)->loc(), "Cannot raise integer to a negative power");
1465 }
1466 for (long long int i = e; (i--) != 0;) {
1467 r = r * p;
1468 }
1469 return r;
1470 }
b_sqrt(EnvI & env,Call * call)1471 FloatVal b_sqrt(EnvI& env, Call* call) {
1472 return std::sqrt(eval_float(env, call->arg(0)).toDouble());
1473 }
1474
b_assert_bool(EnvI & env,Call * call)1475 bool b_assert_bool(EnvI& env, Call* call) {
1476 assert(call->argCount() == 2);
1477 GCLock lock;
1478 Expression* cond_e;
1479 if (call->arg(0)->type().cv()) {
1480 Ctx ctx;
1481 ctx.b = C_MIX;
1482 cond_e = flat_cv_exp(env, ctx, call->arg(0))();
1483 } else {
1484 cond_e = call->arg(0);
1485 }
1486 if (eval_bool(env, cond_e)) {
1487 return true;
1488 }
1489 Expression* msg_e;
1490 if (call->arg(1)->type().cv()) {
1491 msg_e = flat_cv_exp(env, Ctx(), call->arg(1))();
1492 } else {
1493 msg_e = call->arg(1);
1494 }
1495 std::ostringstream ss;
1496 ss << "Assertion failed: " << eval_string(env, msg_e);
1497 throw EvalError(env, call->arg(0)->loc(), ss.str());
1498 }
1499
b_assert(EnvI & env,Call * call)1500 Expression* b_assert(EnvI& env, Call* call) {
1501 assert(call->argCount() == 3);
1502 GCLock lock;
1503 Expression* cond_e;
1504 if (call->arg(0)->type().cv()) {
1505 Ctx ctx;
1506 ctx.b = C_MIX;
1507 cond_e = flat_cv_exp(env, ctx, call->arg(0))();
1508 } else {
1509 cond_e = call->arg(0);
1510 }
1511 if (eval_bool(env, cond_e)) {
1512 return call->arg(2);
1513 }
1514 Expression* msg_e;
1515 if (call->arg(1)->type().cv()) {
1516 msg_e = flat_cv_exp(env, Ctx(), call->arg(1))();
1517 } else {
1518 msg_e = call->arg(1);
1519 }
1520 std::ostringstream ss;
1521 ss << "Assertion failed: " << eval_string(env, msg_e);
1522 throw EvalError(env, call->arg(0)->loc(), ss.str());
1523 }
1524
b_mzn_deprecate(EnvI & env,Call * call)1525 Expression* b_mzn_deprecate(EnvI& env, Call* call) {
1526 assert(call->argCount() == 4);
1527 GCLock lock;
1528 std::string fnName = eval_string(env, call->arg(0));
1529 if (env.deprecationWarnings.find(fnName) == env.deprecationWarnings.end()) {
1530 env.deprecationWarnings.insert(fnName);
1531 env.dumpStack(env.errstream, false);
1532 env.errstream << " The function/predicate `" << fnName;
1533 env.errstream << "' was deprecated in MiniZinc version " << eval_string(env, call->arg(1));
1534 env.errstream << ".\n More information can be found at " << eval_string(env, call->arg(2))
1535 << ".\n";
1536 }
1537 return call->arg(3);
1538 }
1539
b_abort(EnvI & env,Call * call)1540 bool b_abort(EnvI& env, Call* call) {
1541 GCLock lock;
1542 Expression* msg_e;
1543 if (call->arg(0)->type().cv()) {
1544 msg_e = flat_cv_exp(env, Ctx(), call->arg(0))();
1545 } else {
1546 msg_e = call->arg(0);
1547 }
1548 std::ostringstream ss;
1549 ss << "Abort: " << eval_string(env, msg_e);
1550 throw EvalError(env, call->arg(0)->loc(), ss.str());
1551 }
1552
b_mzn_symmetry_breaking_constraint(EnvI & env,Call * call)1553 Expression* b_mzn_symmetry_breaking_constraint(EnvI& env, Call* call) {
1554 GCLock lock;
1555 Call* check = new Call(Location().introduce(),
1556 ASTString("mzn_check_ignore_symmetry_breaking_constraints"), {});
1557 check->type(Type::parbool());
1558 check->decl(env.model->matchFn(env, check, false, true));
1559 if (eval_bool(env, check)) {
1560 return constants().literalTrue;
1561 }
1562 Call* nc = new Call(call->loc(), ASTString("symmetry_breaking_constraint"), {call->arg(0)});
1563 nc->type(Type::varbool());
1564 nc->decl(env.model->matchFn(env, nc, false, true));
1565 return nc;
1566 }
1567
b_mzn_redundant_constraint(EnvI & env,Call * call)1568 Expression* b_mzn_redundant_constraint(EnvI& env, Call* call) {
1569 GCLock lock;
1570 Call* check =
1571 new Call(Location().introduce(), ASTString("mzn_check_ignore_redundant_constraints"), {});
1572 check->type(Type::parbool());
1573 check->decl(env.model->matchFn(env, check, false, true));
1574 if (eval_bool(env, check)) {
1575 return constants().literalTrue;
1576 }
1577 Call* nc = new Call(call->loc(), ASTString("redundant_constraint"), {call->arg(0)});
1578 nc->type(Type::varbool());
1579 nc->decl(env.model->matchFn(env, nc, false, true));
1580 return nc;
1581 }
1582
b_trace(EnvI & env,Call * call)1583 Expression* b_trace(EnvI& env, Call* call) {
1584 GCLock lock;
1585 Expression* msg_e;
1586 if (call->arg(0)->type().cv()) {
1587 msg_e = flat_cv_exp(env, Ctx(), call->arg(0))();
1588 } else {
1589 msg_e = call->arg(0);
1590 }
1591 env.errstream << eval_string(env, msg_e);
1592 return call->argCount() == 1 ? constants().literalTrue : call->arg(1);
1593 }
1594
b_trace_stdout(EnvI & env,Call * call)1595 Expression* b_trace_stdout(EnvI& env, Call* call) {
1596 GCLock lock;
1597 Expression* msg_e;
1598 if (call->arg(0)->type().cv()) {
1599 msg_e = flat_cv_exp(env, Ctx(), call->arg(0))();
1600 } else {
1601 msg_e = call->arg(0);
1602 }
1603 env.errstream << eval_string(env, msg_e);
1604 return call->argCount() == 1 ? constants().literalTrue : call->arg(1);
1605 }
1606
b_trace_logstream(EnvI & env,Call * call)1607 Expression* b_trace_logstream(EnvI& env, Call* call) {
1608 GCLock lock;
1609 StringLit* msg;
1610 if (call->arg(0)->type().cv()) {
1611 msg = flat_cv_exp(env, Ctx(), call->arg(0))()->cast<StringLit>();
1612 } else {
1613 msg = eval_par(env, call->arg(0))->cast<StringLit>();
1614 }
1615 env.logstream << msg->v();
1616 return call->argCount() == 1 ? constants().literalTrue : call->arg(1);
1617 }
b_logstream(EnvI & env,Call * call)1618 std::string b_logstream(EnvI& env, Call* call) { return env.logstream.str(); }
1619
b_in_redundant_constraint(EnvI & env,Call *)1620 bool b_in_redundant_constraint(EnvI& env, Call* /*call*/) { return env.inRedundantConstraint > 0; }
1621
b_in_symmetry_breaking_constraint(EnvI & env,Call *)1622 bool b_in_symmetry_breaking_constraint(EnvI& env, Call* /*call*/) {
1623 return env.inSymmetryBreakingConstraint > 0;
1624 }
1625
b_set2array(EnvI & env,Call * call)1626 Expression* b_set2array(EnvI& env, Call* call) {
1627 assert(call->argCount() == 1);
1628 GCLock lock;
1629 IntSetVal* isv = eval_intset(env, call->arg(0));
1630 std::vector<Expression*> elems;
1631 IntSetRanges isr(isv);
1632 for (Ranges::ToValues<IntSetRanges> isr_v(isr); isr_v(); ++isr_v) {
1633 elems.push_back(IntLit::a(isr_v.val()));
1634 }
1635 auto* al = new ArrayLit(call->arg(0)->loc(), elems);
1636 al->type(Type::parint(1));
1637 return al;
1638 }
1639
b_string_length(EnvI & env,Call * call)1640 IntVal b_string_length(EnvI& env, Call* call) {
1641 GCLock lock;
1642 std::string s = eval_string(env, call->arg(0));
1643 return s.size();
1644 }
1645
show(EnvI & env,Expression * exp)1646 std::string show(EnvI& env, Expression* exp) {
1647 std::ostringstream oss;
1648 GCLock lock;
1649 Printer p(oss, 0, false);
1650 Expression* e = follow_id_to_decl(exp);
1651 if (auto* vd = e->dynamicCast<VarDecl>()) {
1652 if ((vd->e() != nullptr) && !vd->e()->isa<Call>()) {
1653 e = vd->e();
1654 } else {
1655 e = vd->id();
1656 }
1657 }
1658 if (e->type().isPar()) {
1659 e = eval_par(env, e);
1660 }
1661 if (e->type().dim() > 0) {
1662 e = eval_array_lit(env, e);
1663 }
1664 if (auto* al = e->dynamicCast<ArrayLit>()) {
1665 oss << "[";
1666 for (unsigned int i = 0; i < al->size(); i++) {
1667 p.print((*al)[i]);
1668 if (i < al->size() - 1) {
1669 oss << ", ";
1670 }
1671 }
1672 oss << "]";
1673 } else {
1674 p.print(e);
1675 }
1676 return oss.str();
1677 }
b_show(EnvI & env,Call * call)1678 std::string b_show(EnvI& env, Call* call) { return show(env, call->arg(0)); }
b_show_dzn_id(EnvI & env,Call * call)1679 std::string b_show_dzn_id(EnvI& env, Call* call) {
1680 GCLock lock;
1681 std::string s = eval_string(env, call->arg(0));
1682 size_t nonIdChar =
1683 s.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
1684 size_t nonIdBegin = s.find_first_of("0123456789_");
1685 if (nonIdChar != std::string::npos || nonIdBegin == 0) {
1686 s = "'" + s + "'";
1687 }
1688 return s;
1689 }
1690
b_show_json_basic(EnvI & env,Expression * e)1691 std::string b_show_json_basic(EnvI& env, Expression* e) {
1692 std::ostringstream oss;
1693 Printer p(oss, 0, false);
1694 if (auto* sl = e->dynamicCast<SetLit>()) {
1695 oss << "{ \"set\" : [";
1696 if (IntSetVal* isv = sl->isv()) {
1697 bool first = true;
1698 for (IntSetRanges isr(isv); isr(); ++isr) {
1699 if (first) {
1700 first = false;
1701 } else {
1702 oss << ",";
1703 }
1704 if (isr.min() == isr.max()) {
1705 oss << isr.min();
1706 } else {
1707 oss << "[" << isr.min() << "," << isr.max() << "]";
1708 }
1709 }
1710 } else if (FloatSetVal* fsv = sl->fsv()) {
1711 bool first = true;
1712 for (FloatSetRanges fsr(fsv); fsr(); ++fsr) {
1713 if (first) {
1714 first = false;
1715 } else {
1716 oss << ",";
1717 }
1718 if (fsr.min() == fsr.max()) {
1719 pp_floatval(oss, fsr.min());
1720 } else {
1721 oss << "[";
1722 pp_floatval(oss, fsr.min());
1723 oss << ",";
1724 pp_floatval(oss, fsr.max());
1725 oss << "]";
1726 }
1727 }
1728 } else {
1729 for (unsigned int i = 0; i < sl->v().size(); i++) {
1730 p.print(sl->v()[i]);
1731 if (i < sl->v().size() - 1) {
1732 oss << ",";
1733 }
1734 }
1735 }
1736 oss << "]}";
1737 } else if (e == constants().absent) {
1738 oss << "null";
1739 } else {
1740 p.print(e);
1741 }
1742 return oss.str();
1743 }
1744
b_show_json(EnvI & env,Call * call)1745 std::string b_show_json(EnvI& env, Call* call) {
1746 Expression* exp = call->arg(0);
1747 GCLock lock;
1748 Expression* e = eval_par(env, exp);
1749 if (e->type().isvar()) {
1750 std::ostringstream oss;
1751 Printer p(oss, 0, false);
1752 p.print(e);
1753 return oss.str();
1754 }
1755 if (auto* al = e->dynamicCast<ArrayLit>()) {
1756 std::vector<unsigned int> dims(al->dims() - 1);
1757 if (!dims.empty()) {
1758 dims[0] = al->max(al->dims() - 1) - al->min(al->dims() - 1) + 1;
1759 }
1760
1761 for (int i = 1; i < al->dims() - 1; i++) {
1762 dims[i] = dims[i - 1] * (al->max(al->dims() - 1 - i) - al->min(al->dims() - 1 - i) + 1);
1763 }
1764
1765 std::ostringstream oss;
1766 oss << "[";
1767 for (unsigned int i = 0; i < al->size(); i++) {
1768 for (unsigned int dim : dims) {
1769 if (i % dim == 0) {
1770 oss << "[";
1771 }
1772 }
1773 oss << b_show_json_basic(env, (*al)[i]);
1774 for (unsigned int dim : dims) {
1775 if (i % dim == dim - 1) {
1776 oss << "]";
1777 }
1778 }
1779
1780 if (i < al->size() - 1) {
1781 oss << ", ";
1782 }
1783 }
1784 oss << "]";
1785
1786 return oss.str();
1787 }
1788 return b_show_json_basic(env, e);
1789 }
1790
b_output_json(EnvI & env,Call * call)1791 Expression* b_output_json(EnvI& env, Call* call) {
1792 return create_json_output(env, false, false, false);
1793 }
b_output_json_parameters(EnvI & env,Call * call)1794 Expression* b_output_json_parameters(EnvI& env, Call* call) {
1795 std::vector<Expression*> outputVars;
1796 outputVars.push_back(new StringLit(Location().introduce(), "{\n"));
1797
1798 class JSONParVisitor : public ItemVisitor {
1799 protected:
1800 EnvI& _e;
1801 std::vector<Expression*>& _outputVars;
1802 bool _firstVar;
1803
1804 public:
1805 JSONParVisitor(EnvI& e, std::vector<Expression*>& outputVars)
1806 : _e(e), _outputVars(outputVars), _firstVar(true) {}
1807 void vVarDeclI(VarDeclI* vdi) {
1808 VarDecl* vd = vdi->e();
1809 if (vd->ann().contains(constants().ann.rhs_from_assignment)) {
1810 std::ostringstream s;
1811 if (_firstVar) {
1812 _firstVar = false;
1813 } else {
1814 s << ",\n";
1815 }
1816 s << " \"" << vd->id()->str() << "\""
1817 << " : ";
1818 auto* sl = new StringLit(Location().introduce(), s.str());
1819 _outputVars.push_back(sl);
1820
1821 std::vector<Expression*> showArgs(1);
1822 showArgs[0] = vd->id();
1823 Call* show = new Call(Location().introduce(), "showJSON", showArgs);
1824 show->type(Type::parstring());
1825 FunctionI* fi = _e.model->matchFn(_e, show, false);
1826 assert(fi);
1827 show->decl(fi);
1828 _outputVars.push_back(show);
1829 }
1830 }
1831 } jsonov(env, outputVars);
1832
1833 iter_items(jsonov, env.model);
1834 outputVars.push_back(new StringLit(Location().introduce(), "\n}\n"));
1835 return new ArrayLit(Location().introduce(), outputVars);
1836 }
1837
b_format(EnvI & env,Call * call)1838 std::string b_format(EnvI& env, Call* call) {
1839 int width = 0;
1840 int prec = -1;
1841 GCLock lock;
1842 Expression* e;
1843 if (call->argCount() > 1) {
1844 width = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1845 if (call->argCount() == 2) {
1846 e = eval_par(env, call->arg(1));
1847 } else {
1848 assert(call->argCount() == 3);
1849 prec = static_cast<int>(eval_int(env, call->arg(1)).toInt());
1850 if (prec < 0) {
1851 throw EvalError(env, call->arg(1)->loc(), "output precision cannot be negative");
1852 }
1853 e = eval_par(env, call->arg(2));
1854 }
1855 } else {
1856 e = eval_par(env, call->arg(0));
1857 }
1858 if (e->type() == Type::parint()) {
1859 long long int i = eval_int(env, e).toInt();
1860 std::ostringstream formatted;
1861 if (width > 0) {
1862 formatted.width(width);
1863 } else if (width < 0) {
1864 formatted.width(-width);
1865 formatted.flags(std::ios::left);
1866 }
1867 if (prec != -1) {
1868 formatted.precision(prec);
1869 }
1870 formatted << i;
1871 return formatted.str();
1872 }
1873 if (e->type() == Type::parfloat()) {
1874 FloatVal i = eval_float(env, e);
1875 std::ostringstream formatted;
1876 if (width > 0) {
1877 formatted.width(width);
1878 } else if (width < 0) {
1879 formatted.width(-width);
1880 formatted.flags(std::ios::left);
1881 }
1882 formatted.setf(std::ios::fixed);
1883 formatted.precision(std::numeric_limits<double>::digits10 + 2);
1884 if (prec != -1) {
1885 formatted.precision(prec);
1886 }
1887 formatted << i;
1888 return formatted.str();
1889 }
1890 std::string s = show(env, e);
1891 if (prec >= 0 && prec < s.size()) {
1892 s = s.substr(0, prec);
1893 }
1894 std::ostringstream oss;
1895 if (s.size() < std::abs(width)) {
1896 int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size()));
1897 if (addLeft < 0) {
1898 addLeft = 0;
1899 }
1900 int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0;
1901 if (addRight < 0) {
1902 addRight = 0;
1903 }
1904 for (int i = addLeft; (i--) != 0;) {
1905 oss << " ";
1906 }
1907 oss << s;
1908 for (int i = addRight; (i--) != 0;) {
1909 oss << " ";
1910 }
1911 return oss.str();
1912 }
1913 return s;
1914 }
1915
b_format_justify_string(EnvI & env,Call * call)1916 std::string b_format_justify_string(EnvI& env, Call* call) {
1917 int width = 0;
1918 GCLock lock;
1919 Expression* e;
1920 width = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1921 e = eval_par(env, call->arg(1));
1922 std::string s = eval_string(env, e);
1923 std::ostringstream oss;
1924 if (s.size() < std::abs(width)) {
1925 int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size()));
1926 if (addLeft < 0) {
1927 addLeft = 0;
1928 }
1929 int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0;
1930 if (addRight < 0) {
1931 addRight = 0;
1932 }
1933 for (int i = addLeft; (i--) != 0;) {
1934 oss << " ";
1935 }
1936 oss << s;
1937 for (int i = addRight; (i--) != 0;) {
1938 oss << " ";
1939 }
1940 return oss.str();
1941 }
1942 return s;
1943 }
1944
b_show_int(EnvI & env,Call * call)1945 std::string b_show_int(EnvI& env, Call* call) {
1946 assert(call->argCount() == 2);
1947 GCLock lock;
1948 Expression* e = eval_par(env, call->arg(1));
1949 std::ostringstream oss;
1950 if (auto* iv = e->dynamicCast<IntLit>()) {
1951 int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1952 std::ostringstream oss_length;
1953 oss_length << iv->v();
1954 int iv_length = static_cast<int>(oss_length.str().size());
1955 int addLeft = justify < 0 ? 0 : (justify - iv_length);
1956 if (addLeft < 0) {
1957 addLeft = 0;
1958 }
1959 int addRight = justify < 0 ? (-justify - iv_length) : 0;
1960 if (addRight < 0) {
1961 addRight = 0;
1962 }
1963 for (int i = addLeft; (i--) != 0;) {
1964 oss << " ";
1965 }
1966 oss << iv->v();
1967 for (int i = addRight; (i--) != 0;) {
1968 oss << " ";
1969 }
1970 } else {
1971 Printer p(oss, 0, false);
1972 p.print(e);
1973 }
1974 return oss.str();
1975 }
1976
b_show_float(EnvI & env,Call * call)1977 std::string b_show_float(EnvI& env, Call* call) {
1978 assert(call->argCount() == 3);
1979 GCLock lock;
1980 Expression* e = eval_par(env, call->arg(2));
1981 std::ostringstream oss;
1982 if (auto* fv = e->dynamicCast<FloatLit>()) {
1983 int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1984 int prec = static_cast<int>(eval_int(env, call->arg(1)).toInt());
1985 if (prec < 0) {
1986 throw EvalError(env, call->arg(1)->loc(),
1987 "number of digits in show_float cannot be negative");
1988 }
1989 std::ostringstream oss_length;
1990 oss_length << std::setprecision(prec) << std::fixed << fv->v();
1991 int fv_length = static_cast<int>(oss_length.str().size());
1992 int addLeft = justify < 0 ? 0 : (justify - fv_length);
1993 if (addLeft < 0) {
1994 addLeft = 0;
1995 }
1996 int addRight = justify < 0 ? (-justify - fv_length) : 0;
1997 if (addRight < 0) {
1998 addRight = 0;
1999 }
2000 for (int i = addLeft; (i--) != 0;) {
2001 oss << " ";
2002 }
2003 oss << std::setprecision(prec) << std::fixed << fv->v();
2004 for (int i = addRight; (i--) != 0;) {
2005 oss << " ";
2006 }
2007 } else {
2008 Printer p(oss, 0, false);
2009 p.print(e);
2010 }
2011 return oss.str();
2012 }
2013
b_file_path(EnvI &,Call * call)2014 std::string b_file_path(EnvI& /*env*/, Call* call) {
2015 return FileUtils::file_path(
2016 std::string(call->loc().filename().c_str(), call->loc().filename().size()));
2017 }
2018
b_concat(EnvI & env,Call * call)2019 std::string b_concat(EnvI& env, Call* call) {
2020 assert(call->argCount() == 1);
2021 GCLock lock;
2022 ArrayLit* al = eval_array_lit(env, call->arg(0));
2023 std::ostringstream oss;
2024 for (unsigned int i = 0; i < al->size(); i++) {
2025 oss << eval_string(env, (*al)[i]);
2026 }
2027 return oss.str();
2028 }
2029
b_join(EnvI & env,Call * call)2030 std::string b_join(EnvI& env, Call* call) {
2031 assert(call->argCount() == 2);
2032 std::string sep = eval_string(env, call->arg(0));
2033 GCLock lock;
2034 ArrayLit* al = eval_array_lit(env, call->arg(1));
2035 std::ostringstream oss;
2036 for (unsigned int i = 0; i < al->size(); i++) {
2037 oss << eval_string(env, (*al)[i]);
2038 if (i < al->size() - 1) {
2039 oss << sep;
2040 }
2041 }
2042 return oss.str();
2043 }
2044
b_array_union(EnvI & env,Call * call)2045 IntSetVal* b_array_union(EnvI& env, Call* call) {
2046 assert(call->argCount() == 1);
2047 ArrayLit* al = eval_array_lit(env, call->arg(0));
2048 if (al->size() == 0) {
2049 return IntSetVal::a();
2050 }
2051 IntSetVal* isv = eval_intset(env, (*al)[0]);
2052 for (unsigned int i = 0; i < al->size(); i++) {
2053 IntSetRanges i0(isv);
2054 IntSetRanges i1(eval_intset(env, (*al)[i]));
2055 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(i0, i1);
2056 isv = IntSetVal::ai(u);
2057 }
2058 return isv;
2059 }
2060
b_array_intersect(EnvI & env,Call * call)2061 IntSetVal* b_array_intersect(EnvI& env, Call* call) {
2062 assert(call->argCount() == 1);
2063 ArrayLit* al = eval_array_lit(env, call->arg(0));
2064 std::vector<IntSetVal::Range> ranges;
2065 if (al->size() > 0) {
2066 IntSetVal* i0 = eval_intset(env, (*al)[0]);
2067 if (i0->size() > 0) {
2068 IntSetRanges i0r(i0);
2069 IntVal min = i0r.min();
2070 while (i0r()) {
2071 // Initialize with last interval
2072 IntVal max = i0r.max();
2073 // Intersect with all other intervals
2074 restart:
2075 for (unsigned int j = al->size(); (j--) != 0U;) {
2076 IntSetRanges ij(eval_intset(env, (*al)[j]));
2077 // Skip intervals that are too small
2078 while (ij() && (ij.max() < min)) {
2079 ++ij;
2080 }
2081 if (!ij()) {
2082 goto done;
2083 }
2084 if (ij.min() > max) {
2085 min = ij.min();
2086 max = ij.max();
2087 goto restart;
2088 }
2089 // Now the intervals overlap
2090 if (min < ij.min()) {
2091 min = ij.min();
2092 }
2093 if (max > ij.max()) {
2094 max = ij.max();
2095 }
2096 }
2097 ranges.emplace_back(min, max);
2098 // The next interval must be at least two elements away
2099 min = max + 2;
2100 }
2101 done:
2102 return IntSetVal::a(ranges);
2103 } else {
2104 return IntSetVal::a();
2105 }
2106 } else {
2107 return IntSetVal::a();
2108 }
2109 }
2110
b_sort_by_int(EnvI & env,Call * call)2111 Expression* b_sort_by_int(EnvI& env, Call* call) {
2112 assert(call->argCount() == 2);
2113 ArrayLit* al = eval_array_lit(env, call->arg(0));
2114 ArrayLit* order_e = eval_array_lit(env, call->arg(1));
2115 std::vector<IntVal> order(order_e->size());
2116 std::vector<int> a(order_e->size());
2117 for (unsigned int i = 0; i < order.size(); i++) {
2118 a[i] = i;
2119 order[i] = eval_int(env, (*order_e)[i]);
2120 }
2121 struct Ord {
2122 std::vector<IntVal>& order;
2123 Ord(std::vector<IntVal>& order0) : order(order0) {}
2124 bool operator()(int i, int j) { return order[i] < order[j]; }
2125 } _ord(order);
2126 std::stable_sort(a.begin(), a.end(), _ord);
2127 std::vector<Expression*> sorted(a.size());
2128 for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) {
2129 sorted[i] = (*al)[a[i]];
2130 }
2131 auto* al_sorted = new ArrayLit(al->loc(), sorted);
2132 al_sorted->type(al->type());
2133 return al_sorted;
2134 }
2135
b_sort_by_float(EnvI & env,Call * call)2136 Expression* b_sort_by_float(EnvI& env, Call* call) {
2137 assert(call->argCount() == 2);
2138 ArrayLit* al = eval_array_lit(env, call->arg(0));
2139 ArrayLit* order_e = eval_array_lit(env, call->arg(1));
2140 std::vector<FloatVal> order(order_e->size());
2141 std::vector<int> a(order_e->size());
2142 for (unsigned int i = 0; i < order.size(); i++) {
2143 a[i] = i;
2144 order[i] = eval_float(env, (*order_e)[i]);
2145 }
2146 struct Ord {
2147 std::vector<FloatVal>& order;
2148 Ord(std::vector<FloatVal>& order0) : order(order0) {}
2149 bool operator()(int i, int j) { return order[i] < order[j]; }
2150 } _ord(order);
2151 std::stable_sort(a.begin(), a.end(), _ord);
2152 std::vector<Expression*> sorted(a.size());
2153 for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) {
2154 sorted[i] = (*al)[a[i]];
2155 }
2156 auto* al_sorted = new ArrayLit(al->loc(), sorted);
2157 al_sorted->type(al->type());
2158 return al_sorted;
2159 }
2160
b_sort(EnvI & env,Call * call)2161 Expression* b_sort(EnvI& env, Call* call) {
2162 assert(call->argCount() == 1);
2163 ArrayLit* al = eval_array_lit(env, call->arg(0));
2164 std::vector<Expression*> sorted(al->size());
2165 for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) {
2166 sorted[i] = (*al)[i];
2167 }
2168 struct Ord {
2169 EnvI& env;
2170 Ord(EnvI& env0) : env(env0) {}
2171 bool operator()(Expression* e0, Expression* e1) {
2172 switch (e0->type().bt()) {
2173 case Type::BT_INT:
2174 return eval_int(env, e0) < eval_int(env, e1);
2175 case Type::BT_BOOL:
2176 return static_cast<int>(eval_bool(env, e0)) < static_cast<int>(eval_bool(env, e1));
2177 case Type::BT_FLOAT:
2178 return eval_float(env, e0) < eval_float(env, e1);
2179 default:
2180 throw EvalError(env, e0->loc(), "unsupported type for sorting");
2181 }
2182 }
2183 } _ord(env);
2184 std::sort(sorted.begin(), sorted.end(), _ord);
2185 auto* al_sorted = new ArrayLit(al->loc(), sorted);
2186 al_sorted->type(al->type());
2187 return al_sorted;
2188 }
2189
b_inverse(EnvI & env,Call * call)2190 Expression* b_inverse(EnvI& env, Call* call) {
2191 assert(call->argCount() == 1);
2192 ArrayLit* al = eval_array_lit(env, call->arg(0));
2193 if (al->size() == 0) {
2194 return al;
2195 }
2196 int min_idx = al->min(0);
2197
2198 std::vector<IntVal> ivs(al->size());
2199 IntVal minVal = eval_int(env, (*al)[0]);
2200 IntVal maxVal = minVal;
2201 ivs[0] = minVal;
2202 for (unsigned int i = 1; i < al->size(); i++) {
2203 IntVal ii = eval_int(env, (*al)[i]);
2204 ivs[i] = ii;
2205 minVal = std::min(minVal, ii);
2206 maxVal = std::max(maxVal, ii);
2207 }
2208 if (maxVal - minVal + 1 != al->size()) {
2209 throw ResultUndefinedError(env, call->loc(),
2210 "inverse on non-contiguous set of values is undefined");
2211 }
2212
2213 std::vector<Expression*> inv(al->size());
2214 std::vector<bool> used(al->size());
2215 for (unsigned int i = 0; i < ivs.size(); i++) {
2216 used[(ivs[i] - minVal).toInt()] = true;
2217 inv[(ivs[i] - minVal).toInt()] = IntLit::a(i + min_idx);
2218 }
2219 for (bool b : used) {
2220 if (!b) {
2221 throw ResultUndefinedError(env, call->loc(),
2222 "inverse on non-contiguous set of values is undefined");
2223 }
2224 }
2225 auto* al_inv = new ArrayLit(al->loc(), inv, {{minVal.toInt(), maxVal.toInt()}});
2226 al_inv->type(al->type());
2227 return al_inv;
2228 }
2229
b_set_to_ranges_int(EnvI & env,Call * call)2230 Expression* b_set_to_ranges_int(EnvI& env, Call* call) {
2231 assert(call->argCount() == 1);
2232 IntSetVal* isv = eval_intset(env, call->arg(0));
2233 std::vector<Expression*> v(isv->size() * 2);
2234 for (unsigned int i = 0; i < isv->size(); i++) {
2235 v[2 * i] = IntLit::a(isv->min(i));
2236 v[2 * i + 1] = IntLit::a(isv->max(i));
2237 }
2238 auto* al = new ArrayLit(call->loc().introduce(), v);
2239 al->type(Type::parint(1));
2240 return al;
2241 }
2242
b_set_to_ranges_float(EnvI & env,Call * call)2243 Expression* b_set_to_ranges_float(EnvI& env, Call* call) {
2244 assert(call->argCount() == 1);
2245 FloatSetVal* fsv = eval_floatset(env, call->arg(0));
2246 std::vector<Expression*> v(fsv->size() * 2);
2247 for (unsigned int i = 0; i < fsv->size(); i++) {
2248 v[2 * i] = FloatLit::a(fsv->min(i));
2249 v[2 * i + 1] = FloatLit::a(fsv->max(i));
2250 }
2251 auto* al = new ArrayLit(call->loc().introduce(), v);
2252 al->type(Type::parfloat(1));
2253 return al;
2254 }
2255
rnd_generator()2256 std::default_random_engine& rnd_generator() {
2257 // TODO: initiate with seed if given as annotation/in command line
2258 static std::default_random_engine g;
2259 return g;
2260 }
2261
b_normal_float_float(EnvI & env,Call * call)2262 FloatVal b_normal_float_float(EnvI& env, Call* call) {
2263 assert(call->argCount() == 2);
2264 const double mean = eval_float(env, call->arg(0)).toDouble();
2265 const double stdv = eval_float(env, call->arg(1)).toDouble();
2266 std::normal_distribution<double> distribution(mean, stdv);
2267 // return a sample from the distribution
2268 return distribution(rnd_generator());
2269 }
2270
b_normal_int_float(EnvI & env,Call * call)2271 FloatVal b_normal_int_float(EnvI& env, Call* call) {
2272 assert(call->argCount() == 2);
2273 const double mean = double(eval_int(env, call->arg(0)).toInt());
2274 const double stdv = eval_float(env, call->arg(1)).toDouble();
2275 std::normal_distribution<double> distribution(mean, stdv);
2276 // return a sample from the distribution
2277 return distribution(rnd_generator());
2278 }
2279
b_uniform_float(EnvI & env,Call * call)2280 FloatVal b_uniform_float(EnvI& env, Call* call) {
2281 assert(call->argCount() == 2);
2282 const double lb = eval_float(env, call->arg(0)).toDouble();
2283 const double ub = eval_float(env, call->arg(1)).toDouble();
2284 if (lb > ub) {
2285 std::stringstream ssm;
2286 ssm << "lowerbound of uniform distribution \"" << lb
2287 << "\" is higher than its upperbound: " << ub;
2288 throw EvalError(env, call->arg(0)->loc(), ssm.str());
2289 }
2290 std::uniform_real_distribution<double> distribution(lb, ub);
2291 // return a sample from the distribution
2292 return distribution(rnd_generator());
2293 }
2294
b_uniform_int(EnvI & env,Call * call)2295 IntVal b_uniform_int(EnvI& env, Call* call) {
2296 assert(call->argCount() == 2);
2297 const long long int lb = eval_int(env, call->arg(0)).toInt();
2298 const long long int ub = eval_int(env, call->arg(1)).toInt();
2299 if (lb > ub) {
2300 std::stringstream ssm;
2301 ssm << "lowerbound of uniform distribution \"" << lb
2302 << "\" is higher than its upperbound: " << ub;
2303 throw EvalError(env, call->arg(0)->loc(), ssm.str());
2304 }
2305 std::uniform_int_distribution<long long int> distribution(lb, ub);
2306 // return a sample from the distribution
2307 return IntVal(distribution(rnd_generator()));
2308 }
2309
b_poisson_int(EnvI & env,Call * call)2310 IntVal b_poisson_int(EnvI& env, Call* call) {
2311 assert(call->argCount() == 1);
2312 long long int mean = eval_int(env, call->arg(0)).toInt();
2313 std::poisson_distribution<long long int> distribution(static_cast<double>(mean));
2314 // return a sample from the distribution
2315 return IntVal(distribution(rnd_generator()));
2316 }
2317
b_poisson_float(EnvI & env,Call * call)2318 IntVal b_poisson_float(EnvI& env, Call* call) {
2319 assert(call->argCount() == 1);
2320 double mean = eval_float(env, call->arg(0)).toDouble();
2321 std::poisson_distribution<long long int> distribution(mean);
2322 // return a sample from the distribution
2323 return IntVal(distribution(rnd_generator()));
2324 }
2325
b_gamma_float_float(EnvI & env,Call * call)2326 FloatVal b_gamma_float_float(EnvI& env, Call* call) {
2327 assert(call->argCount() == 2);
2328 const double alpha = eval_float(env, call->arg(0)).toDouble();
2329 const double beta = eval_float(env, call->arg(1)).toDouble();
2330 std::gamma_distribution<double> distribution(alpha, beta);
2331 // return a sample from the distribution
2332 return distribution(rnd_generator());
2333 }
2334
b_gamma_int_float(EnvI & env,Call * call)2335 FloatVal b_gamma_int_float(EnvI& env, Call* call) {
2336 assert(call->argCount() == 2);
2337 const double alpha = eval_float(env, call->arg(0)).toDouble();
2338 const double beta = eval_float(env, call->arg(1)).toDouble();
2339 std::gamma_distribution<double> distribution(alpha, beta);
2340 // return a sample from the distribution
2341 return distribution(rnd_generator());
2342 }
2343
b_weibull_int_float(EnvI & env,Call * call)2344 FloatVal b_weibull_int_float(EnvI& env, Call* call) {
2345 assert(call->argCount() == 2);
2346 const double shape = double(eval_int(env, call->arg(0)).toInt());
2347 if (shape < 0) {
2348 std::stringstream ssm;
2349 ssm << "The shape factor for the weibull distribution \"" << shape
2350 << "\" has to be greater than zero.";
2351 throw EvalError(env, call->arg(0)->loc(), ssm.str());
2352 }
2353 const double scale = eval_float(env, call->arg(1)).toDouble();
2354 if (scale < 0) {
2355 std::stringstream ssm;
2356 ssm << "The scale factor for the weibull distribution \"" << scale
2357 << "\" has to be greater than zero.";
2358 throw EvalError(env, call->arg(1)->loc(), ssm.str());
2359 }
2360 std::weibull_distribution<double> distribution(shape, scale);
2361 // return a sample from the distribution
2362 return distribution(rnd_generator());
2363 }
2364
b_weibull_float_float(EnvI & env,Call * call)2365 FloatVal b_weibull_float_float(EnvI& env, Call* call) {
2366 assert(call->argCount() == 2);
2367 const double shape = eval_float(env, call->arg(0)).toDouble();
2368 if (shape < 0) {
2369 std::stringstream ssm;
2370 ssm << "The shape factor for the weibull distribution \"" << shape
2371 << "\" has to be greater than zero.";
2372 throw EvalError(env, call->arg(0)->loc(), ssm.str());
2373 }
2374 const double scale = eval_float(env, call->arg(1)).toDouble();
2375 if (scale < 0) {
2376 std::stringstream ssm;
2377 ssm << "The scale factor for the weibull distribution \"" << scale
2378 << "\" has to be greater than zero.";
2379 throw EvalError(env, call->arg(1)->loc(), ssm.str());
2380 }
2381 std::weibull_distribution<double> distribution(shape, scale);
2382 // return a sample from the distribution
2383 return distribution(rnd_generator());
2384 }
2385
b_exponential_float(EnvI & env,Call * call)2386 FloatVal b_exponential_float(EnvI& env, Call* call) {
2387 assert(call->argCount() == 1);
2388 const double lambda = eval_float(env, call->arg(0)).toDouble();
2389 if (lambda < 0) {
2390 std::stringstream ssm;
2391 ssm << "The lambda-parameter for the exponential distribution function \"" << lambda
2392 << "\" has to be greater than zero.";
2393 throw EvalError(env, call->arg(0)->loc(), ssm.str());
2394 }
2395 std::exponential_distribution<double> distribution(lambda);
2396 // return a sample from the distribution
2397 return distribution(rnd_generator());
2398 }
2399
b_exponential_int(EnvI & env,Call * call)2400 FloatVal b_exponential_int(EnvI& env, Call* call) {
2401 assert(call->argCount() == 1);
2402 const double lambda = double(eval_int(env, call->arg(0)).toInt());
2403 if (lambda < 0) {
2404 std::stringstream ssm;
2405 ssm << "The lambda-parameter for the exponential distribution function \"" << lambda
2406 << "\" has to be greater than zero.";
2407 throw EvalError(env, call->arg(0)->loc(), ssm.str());
2408 }
2409 std::exponential_distribution<double> distribution(lambda);
2410 // return a sample from the distribution
2411 return distribution(rnd_generator());
2412 }
2413
b_lognormal_float_float(EnvI & env,Call * call)2414 FloatVal b_lognormal_float_float(EnvI& env, Call* call) {
2415 assert(call->argCount() == 2);
2416 const double mean = eval_float(env, call->arg(0)).toDouble();
2417 const double stdv = eval_float(env, call->arg(1)).toDouble();
2418 std::lognormal_distribution<double> distribution(mean, stdv);
2419 // return a sample from the distribution
2420 return distribution(rnd_generator());
2421 }
2422
b_lognormal_int_float(EnvI & env,Call * call)2423 FloatVal b_lognormal_int_float(EnvI& env, Call* call) {
2424 assert(call->argCount() == 2);
2425 const double mean = double(eval_int(env, call->arg(0)).toInt());
2426 const double stdv = eval_float(env, call->arg(1)).toDouble();
2427 std::lognormal_distribution<double> distribution(mean, stdv);
2428 // return a sample from the distribution
2429 return distribution(rnd_generator());
2430 }
2431
b_chisquared_float(EnvI & env,Call * call)2432 FloatVal b_chisquared_float(EnvI& env, Call* call) {
2433 assert(call->argCount() == 1);
2434 const double lambda = eval_float(env, call->arg(0)).toDouble();
2435 std::exponential_distribution<double> distribution(lambda);
2436 // return a sample from the distribution
2437 return distribution(rnd_generator());
2438 }
2439
b_chisquared_int(EnvI & env,Call * call)2440 FloatVal b_chisquared_int(EnvI& env, Call* call) {
2441 assert(call->argCount() == 1);
2442 const double lambda = double(eval_int(env, call->arg(0)).toInt());
2443 std::exponential_distribution<double> distribution(lambda);
2444 // return a sample from the distribution
2445 return distribution(rnd_generator());
2446 }
2447
b_cauchy_float_float(EnvI & env,Call * call)2448 FloatVal b_cauchy_float_float(EnvI& env, Call* call) {
2449 assert(call->argCount() == 2);
2450 const double mean = eval_float(env, call->arg(0)).toDouble();
2451 const double scale = eval_float(env, call->arg(1)).toDouble();
2452 std::cauchy_distribution<double> distribution(mean, scale);
2453 // return a sample from the distribution
2454 return distribution(rnd_generator());
2455 }
2456
b_cauchy_int_float(EnvI & env,Call * call)2457 FloatVal b_cauchy_int_float(EnvI& env, Call* call) {
2458 assert(call->argCount() == 2);
2459 const double mean = double(eval_int(env, call->arg(0)).toInt());
2460 const double scale = eval_float(env, call->arg(1)).toDouble();
2461 std::cauchy_distribution<double> distribution(mean, scale);
2462 // return a sample from the distribution
2463 return distribution(rnd_generator());
2464 }
2465
b_fdistribution_float_float(EnvI & env,Call * call)2466 FloatVal b_fdistribution_float_float(EnvI& env, Call* call) {
2467 assert(call->argCount() == 2);
2468 const double d1 = eval_float(env, call->arg(0)).toDouble();
2469 const double d2 = eval_float(env, call->arg(1)).toDouble();
2470 std::fisher_f_distribution<double> distribution(d1, d2);
2471 // return a sample from the distribution
2472 return distribution(rnd_generator());
2473 }
2474
b_fdistribution_int_int(EnvI & env,Call * call)2475 FloatVal b_fdistribution_int_int(EnvI& env, Call* call) {
2476 assert(call->argCount() == 2);
2477 const double d1 = double(eval_int(env, call->arg(0)).toInt());
2478 const double d2 = double(eval_int(env, call->arg(1)).toInt());
2479 std::fisher_f_distribution<double> distribution(d1, d2);
2480 // return a sample from the distribution
2481 return distribution(rnd_generator());
2482 }
2483
b_tdistribution_float(EnvI & env,Call * call)2484 FloatVal b_tdistribution_float(EnvI& env, Call* call) {
2485 assert(call->argCount() == 1);
2486 const double sampleSize = eval_float(env, call->arg(0)).toDouble();
2487 std::student_t_distribution<double> distribution(sampleSize);
2488 // return a sample from the distribution
2489 return distribution(rnd_generator());
2490 }
2491
b_tdistribution_int(EnvI & env,Call * call)2492 FloatVal b_tdistribution_int(EnvI& env, Call* call) {
2493 assert(call->argCount() == 1);
2494 const double sampleSize = double(eval_int(env, call->arg(0)).toInt());
2495 std::student_t_distribution<double> distribution(sampleSize);
2496 // return a sample from the distribution
2497 return distribution(rnd_generator());
2498 }
2499
b_discrete_distribution(EnvI & env,Call * call)2500 IntVal b_discrete_distribution(EnvI& env, Call* call) {
2501 assert(call->argCount() == 1);
2502 GCLock lock;
2503 ArrayLit* al = eval_array_lit(env, call->arg(0));
2504 if (al->dims() != 1) {
2505 std::stringstream ssm;
2506 ssm << "expecting 1-dimensional array of weights for discrete distribution instead of: " << *al
2507 << std::endl;
2508 throw EvalError(env, al->loc(), ssm.str());
2509 }
2510 std::vector<long long int> weights(al->size());
2511 for (unsigned int i = 0; i < al->size(); i++) {
2512 weights[i] = eval_int(env, (*al)[i]).toInt();
2513 }
2514 #ifdef _MSC_VER
2515 std::size_t i(0);
2516 std::discrete_distribution<long long int> distribution(
2517 weights.size(), 0.0, 1.0, [&weights, &i](double d) { return weights[i++]; });
2518 #else
2519 std::discrete_distribution<long long int> distribution(weights.begin(), weights.end());
2520 #endif
2521 // return a sample from the distribution
2522 IntVal iv = IntVal(distribution(rnd_generator()));
2523 return iv;
2524 }
2525
b_bernoulli(EnvI & env,Call * call)2526 bool b_bernoulli(EnvI& env, Call* call) {
2527 assert(call->argCount() == 1);
2528 const double p = eval_float(env, call->arg(0)).toDouble();
2529 std::bernoulli_distribution distribution(p);
2530 // return a sample from the distribution
2531 return distribution(rnd_generator());
2532 }
2533
b_binomial(EnvI & env,Call * call)2534 IntVal b_binomial(EnvI& env, Call* call) {
2535 assert(call->argCount() == 2);
2536 double t = double(eval_int(env, call->arg(0)).toInt());
2537 double p = eval_float(env, call->arg(1)).toDouble();
2538 std::binomial_distribution<long long int> distribution(t, p);
2539 // return a sample from the distribution
2540 return IntVal(distribution(rnd_generator()));
2541 }
2542
b_atan(EnvI & env,Call * call)2543 FloatVal b_atan(EnvI& env, Call* call) {
2544 assert(call->argCount() == 1);
2545 GCLock lock;
2546 FloatVal f = eval_float(env, call->arg(0));
2547 return std::atan(f.toDouble());
2548 }
2549
b_cos(EnvI & env,Call * call)2550 FloatVal b_cos(EnvI& env, Call* call) {
2551 assert(call->argCount() == 1);
2552 GCLock lock;
2553 FloatVal f = eval_float(env, call->arg(0));
2554 return std::cos(f.toDouble());
2555 }
2556
b_sin(EnvI & env,Call * call)2557 FloatVal b_sin(EnvI& env, Call* call) {
2558 assert(call->argCount() == 1);
2559 GCLock lock;
2560 FloatVal f = eval_float(env, call->arg(0));
2561 return std::sin(f.toDouble());
2562 }
2563
b_asin(EnvI & env,Call * call)2564 FloatVal b_asin(EnvI& env, Call* call) {
2565 assert(call->argCount() == 1);
2566 GCLock lock;
2567 FloatVal f = eval_float(env, call->arg(0));
2568 return std::asin(f.toDouble());
2569 }
2570
b_acos(EnvI & env,Call * call)2571 FloatVal b_acos(EnvI& env, Call* call) {
2572 assert(call->argCount() == 1);
2573 GCLock lock;
2574 FloatVal f = eval_float(env, call->arg(0));
2575 return std::acos(f.toDouble());
2576 }
2577
b_tan(EnvI & env,Call * call)2578 FloatVal b_tan(EnvI& env, Call* call) {
2579 assert(call->argCount() == 1);
2580 GCLock lock;
2581 FloatVal f = eval_float(env, call->arg(0));
2582 return std::tan(f.toDouble());
2583 }
2584
b_to_enum(EnvI & env,Call * call)2585 IntVal b_to_enum(EnvI& env, Call* call) {
2586 assert(call->argCount() == 2);
2587 IntSetVal* isv = eval_intset(env, call->arg(0));
2588 IntVal v = eval_int(env, call->arg(1));
2589 if (!isv->contains(v)) {
2590 throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
2591 }
2592 return v;
2593 }
2594
b_enum_next(EnvI & env,Call * call)2595 IntVal b_enum_next(EnvI& env, Call* call) {
2596 IntSetVal* isv = eval_intset(env, call->arg(0));
2597 IntVal v = eval_int(env, call->arg(1));
2598 if (!isv->contains(v + 1)) {
2599 throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
2600 }
2601 return v + 1;
2602 }
2603
b_enum_prev(EnvI & env,Call * call)2604 IntVal b_enum_prev(EnvI& env, Call* call) {
2605 IntSetVal* isv = eval_intset(env, call->arg(0));
2606 IntVal v = eval_int(env, call->arg(1));
2607 if (!isv->contains(v - 1)) {
2608 throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
2609 }
2610 return v - 1;
2611 }
2612
b_mzn_compiler_version(EnvI &,Call *)2613 IntVal b_mzn_compiler_version(EnvI& /*env*/, Call* /*call*/) {
2614 return atoi(MZN_VERSION_MAJOR) * 10000 + atoi(MZN_VERSION_MINOR) * 1000 + atoi(MZN_VERSION_PATCH);
2615 }
2616
b_slice(EnvI & env,Call * call)2617 Expression* b_slice(EnvI& env, Call* call) {
2618 ArrayLit* al = eval_array_lit(env, call->arg(0));
2619
2620 ArrayLit* slice = eval_array_lit(env, call->arg(1));
2621 std::vector<std::pair<int, int>> newSlice(slice->size());
2622 for (unsigned int i = 0; i < slice->size(); i++) {
2623 IntSetVal* isv = eval_intset(env, (*slice)[i]);
2624 if (isv->size() == 0) {
2625 newSlice[i] = std::pair<int, int>(1, 0);
2626 } else {
2627 if (isv->size() > 1) {
2628 throw ResultUndefinedError(env, call->loc(), "array slice must be contiguous");
2629 }
2630 int sl_min = isv->min().isFinite() ? static_cast<int>(isv->min().toInt()) : al->min(i);
2631 int sl_max = isv->max().isFinite() ? static_cast<int>(isv->max().toInt()) : al->max(i);
2632 if (sl_min < al->min(i) || sl_max > al->max(i)) {
2633 throw ResultUndefinedError(env, call->loc(), "array slice out of bounds");
2634 }
2635 newSlice[i] = std::pair<int, int>(sl_min, sl_max);
2636 }
2637 }
2638
2639 std::vector<std::pair<int, int>> newDims(call->argCount() - 2);
2640 for (unsigned int i = 0; i < newDims.size(); i++) {
2641 IntSetVal* isv = eval_intset(env, call->arg(2 + i));
2642 if (isv->size() == 0) {
2643 newDims[i] = std::pair<int, int>(1, 0);
2644 } else {
2645 newDims[i] = std::pair<int, int>(static_cast<int>(isv->min().toInt()),
2646 static_cast<int>(isv->max().toInt()));
2647 }
2648 }
2649 auto* ret = new ArrayLit(al->loc(), al, newDims, newSlice);
2650 ret->type(call->type());
2651 return ret;
2652 }
2653
b_regular_from_string(EnvI & env,Call * call)2654 Expression* b_regular_from_string(EnvI& env, Call* call) {
2655 #ifdef HAS_GECODE
2656 using namespace Gecode;
2657 ArrayLit* vars = eval_array_lit(env, call->arg(0));
2658 std::string expr = eval_string(env, call->arg(1));
2659
2660 IntSetVal* dom;
2661 if (vars->size() == 0) {
2662 dom = IntSetVal::a();
2663 } else {
2664 dom = b_dom_varint(env, (*vars)[0]);
2665 for (unsigned int i = 1; i < vars->size(); i++) {
2666 IntSetRanges isr(dom);
2667 IntSetRanges r(b_dom_varint(env, (*vars)[i]));
2668 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
2669 dom = IntSetVal::ai(u);
2670 }
2671 }
2672 long long int card = dom->max().toInt() - dom->min().toInt() + 1;
2673 int offset = 1 - static_cast<int>(dom->min().toInt());
2674
2675 // Replace all occurrences of enum constructor calls
2676 std::regex constructor_call(
2677 "([A-Za-z][A-Za-z0-9_]*|'[^'\\xa\\xd\\x0]*')[[:space:]]*\\([[:space:]]*([A-Za-z][A-Za-z0-9_]*"
2678 "|'[^'\\xa\\xd\\x0]*'|([0-9]*))[[:space:]]*\\)",
2679 std::regex_constants::egrep);
2680 while (std::regex_search(expr, constructor_call)) {
2681 std::ostringstream oss;
2682 auto id_re_it =
2683 std::sregex_token_iterator(expr.begin(), expr.end(), constructor_call, {-1, 1, 2, 3});
2684 for (; id_re_it != std::sregex_token_iterator();) {
2685 std::string rest = *id_re_it;
2686 oss << rest;
2687 ++id_re_it;
2688 if (id_re_it == std::sregex_token_iterator()) {
2689 break;
2690 }
2691 std::string id1 = *id_re_it;
2692 ++id_re_it;
2693 std::string id2 = *id_re_it;
2694 ++id_re_it;
2695 std::string val3 = *id_re_it;
2696 ++id_re_it;
2697 // Enum constructor call, get both items
2698 Expression* arg;
2699 if (val3.empty()) {
2700 auto it = env.reverseEnum.find(id2);
2701 if (it == env.reverseEnum.end()) {
2702 throw std::runtime_error("Unknown identifier: " + id2);
2703 }
2704 auto* id2_vd = it->second->dynamicCast<VarDeclI>();
2705 if (id2_vd == nullptr) {
2706 throw std::runtime_error("identifier " + id2 + " is not an enum constant");
2707 }
2708 arg = id2_vd->e()->id();
2709 } else {
2710 int v = std::stoi(val3);
2711 arg = IntLit::a(v);
2712 }
2713 auto it = env.reverseEnum.find(id1);
2714 if (it == env.reverseEnum.end()) {
2715 throw std::runtime_error("Unknown identifier: " + id2);
2716 }
2717 if (auto* id1_vdi = it->second->dynamicCast<VarDeclI>()) {
2718 // this is not an enum constructor, simply output both values
2719 IntVal result1 = eval_int(env, id1_vdi->e()->id());
2720 IntVal result2 = eval_int(env, arg);
2721 oss << result1 << "(" << result2 << ")";
2722 } else {
2723 auto* fi = it->second->cast<FunctionI>();
2724 Call* c = new Call(Location().introduce(), fi->id(), {arg});
2725 c->type(fi->rtype(env, {arg->type()}, true));
2726 c->decl(fi);
2727
2728 IntVal result = eval_int(env, c);
2729 oss << result;
2730 }
2731 }
2732 expr = oss.str();
2733 }
2734
2735 // Replace all remaining enum identifiers
2736 std::regex enumid("[A-Za-z][A-Za-z0-9_]*|'[^'\\xa\\xd\\x0]*'", std::regex_constants::egrep);
2737 auto id_re_it = std::sregex_token_iterator(expr.begin(), expr.end(), enumid, {-1, 0});
2738 std::ostringstream oss;
2739 for (; id_re_it != std::sregex_token_iterator();) {
2740 std::string rest = *id_re_it;
2741 oss << rest;
2742 ++id_re_it;
2743 if (id_re_it == std::sregex_token_iterator()) {
2744 break;
2745 }
2746 std::string id1 = *id_re_it;
2747 ++id_re_it;
2748 auto it = env.reverseEnum.find(id1);
2749 if (it == env.reverseEnum.end()) {
2750 throw std::runtime_error("Unknown identifier: " + id1);
2751 }
2752 auto* id1_vd = it->second->dynamicCast<VarDeclI>();
2753 if (id1_vd == nullptr) {
2754 throw std::runtime_error("identifier " + id1 + " is not an enum constant");
2755 }
2756 IntVal result1 = eval_int(env, id1_vd->e()->id());
2757 oss << result1;
2758 }
2759 expr = oss.str();
2760
2761 std::unique_ptr<REG> regex;
2762 try {
2763 regex = regex_from_string(expr, *dom);
2764 } catch (const std::exception& e) {
2765 throw SyntaxError(call->arg(1)->loc(), e.what());
2766 }
2767 DFA dfa = DFA(*regex);
2768
2769 std::vector<std::vector<Expression*>> reg_trans(
2770 dfa.n_states(), std::vector<Expression*>(static_cast<size_t>(card), IntLit::a(IntVal(0))));
2771
2772 DFA::Transitions trans(dfa);
2773 while (trans()) {
2774 // std::cerr << trans.i_state() + 1 << " -- " << trans.symbol() << " --> " <<
2775 // trans.o_state() + 1 << "\n";
2776 if (trans.symbol() >= dom->min().toInt() && trans.symbol() <= dom->max().toInt()) {
2777 reg_trans[trans.i_state()][trans.symbol() + offset - 1] =
2778 IntLit::a(IntVal(trans.o_state() + 1));
2779 }
2780 ++trans;
2781 }
2782
2783 std::vector<Expression*> args(6);
2784 if (offset == 0) {
2785 args[0] = vars; // x
2786 } else {
2787 std::vector<Expression*> nvars(vars->size());
2788 IntLit* loffset = IntLit::a(IntVal(offset));
2789 for (int i = 0; i < nvars.size(); ++i) {
2790 nvars[i] = new BinOp(call->loc().introduce(), (*vars)[i], BOT_PLUS, loffset);
2791 nvars[i]->type(Type::varint());
2792 }
2793 args[0] = new ArrayLit(call->loc().introduce(), nvars); // x
2794 args[0]->type(Type::varint(1));
2795 }
2796 args[1] = IntLit::a(IntVal(dfa.n_states())); // Q
2797 args[1]->type(Type::parint());
2798 args[2] = IntLit::a(IntVal(card)); // S
2799 args[2]->type(Type::parint());
2800 args[3] = new ArrayLit(call->loc().introduce(), reg_trans); // d
2801 args[3]->type(Type::parint(2));
2802 args[4] = IntLit::a(IntVal(1)); // q0
2803 args[4]->type(Type::parint());
2804 args[5] = new SetLit(call->loc().introduce(),
2805 IntSetVal::a(IntVal(dfa.final_fst() + 1), IntVal(dfa.final_lst()))); // F
2806 args[5]->type(Type::parsetint());
2807
2808 auto* nc = new Call(call->loc().introduce(), "regular", args);
2809 nc->type(Type::varbool());
2810
2811 return nc;
2812 #else
2813 throw FlatteningError(
2814 env, call->loc(),
2815 "MiniZinc was compiled without built-in Gecode, cannot parse regular expression");
2816 #endif
2817 }
2818
b_show_checker_output(EnvI & env,Call * call)2819 Expression* b_show_checker_output(EnvI& env, Call* call) {
2820 // Get checker output
2821 env.checkerOutput.flush();
2822 std::string output = env.checkerOutput.str();
2823 // Reset checker output
2824 env.checkerOutput.str("");
2825 env.checkerOutput.clear();
2826 return new StringLit(call->loc().introduce(), output);
2827 }
2828
register_builtins(Env & e)2829 void register_builtins(Env& e) {
2830 EnvI& env = e.envi();
2831 Model* m = env.model;
2832
2833 std::vector<Type> t_intint(2);
2834 t_intint[0] = Type::parint();
2835 t_intint[1] = Type::parint();
2836
2837 std::vector<Type> t_intarray(1);
2838 t_intarray[0] = Type::parint(-1);
2839
2840 GCLock lock;
2841
2842 rb(env, m, ASTString("min"), t_intint, b_int_min);
2843 rb(env, m, ASTString("min"), t_intarray, b_int_min);
2844 rb(env, m, ASTString("max"), t_intint, b_int_max);
2845 rb(env, m, ASTString("max"), t_intarray, b_int_max);
2846 rb(env, m, constants().ids.sum, t_intarray, b_sum_int);
2847 rb(env, m, ASTString("product"), t_intarray, b_product_int);
2848 rb(env, m, ASTString("pow"), t_intint, b_pow_int);
2849
2850 rb(env, m, ASTString("'div'"), t_intint, b_idiv);
2851 rb(env, m, ASTString("'mod'"), t_intint, b_mod);
2852 rb(env, m, ASTString("'..'"), t_intint, b_dotdot);
2853 {
2854 std::vector<Type> t({Type::parfloat(), Type::parfloat()});
2855 rb(env, m, ASTString("'/'"), t, b_fdiv);
2856 }
2857 {
2858 std::vector<Type> t(2);
2859 t[0] = Type::top(-1);
2860 t[1] = Type::top(-1);
2861 rb(env, m, ASTString("index_sets_agree"), t, b_index_sets_agree);
2862 }
2863 {
2864 std::vector<Type> t_anyarray1(1);
2865 t_anyarray1[0] = Type::optvartop(1);
2866 rb(env, m, ASTString("index_set"), t_anyarray1, b_index_set1);
2867 }
2868 {
2869 std::vector<Type> t_anyarray2(1);
2870 t_anyarray2[0] = Type::optvartop(2);
2871 rb(env, m, ASTString("index_set_1of2"), t_anyarray2, b_index_set1);
2872 rb(env, m, ASTString("index_set_2of2"), t_anyarray2, b_index_set2);
2873 }
2874 {
2875 std::vector<Type> t_anyarray3(1);
2876 t_anyarray3[0] = Type::optvartop(3);
2877 rb(env, m, ASTString("index_set_1of3"), t_anyarray3, b_index_set1);
2878 rb(env, m, ASTString("index_set_2of3"), t_anyarray3, b_index_set2);
2879 rb(env, m, ASTString("index_set_3of3"), t_anyarray3, b_index_set3);
2880 }
2881 {
2882 std::vector<Type> t_anyarray4(1);
2883 t_anyarray4[0] = Type::optvartop(4);
2884 rb(env, m, ASTString("index_set_1of4"), t_anyarray4, b_index_set1);
2885 rb(env, m, ASTString("index_set_2of4"), t_anyarray4, b_index_set2);
2886 rb(env, m, ASTString("index_set_3of4"), t_anyarray4, b_index_set3);
2887 rb(env, m, ASTString("index_set_4of4"), t_anyarray4, b_index_set4);
2888 }
2889 {
2890 std::vector<Type> t_anyarray5(1);
2891 t_anyarray5[0] = Type::optvartop(5);
2892 rb(env, m, ASTString("index_set_1of5"), t_anyarray5, b_index_set1);
2893 rb(env, m, ASTString("index_set_2of5"), t_anyarray5, b_index_set2);
2894 rb(env, m, ASTString("index_set_3of5"), t_anyarray5, b_index_set3);
2895 rb(env, m, ASTString("index_set_4of5"), t_anyarray5, b_index_set4);
2896 rb(env, m, ASTString("index_set_5of5"), t_anyarray5, b_index_set5);
2897 }
2898 {
2899 std::vector<Type> t_anyarray6(1);
2900 t_anyarray6[0] = Type::optvartop(6);
2901 rb(env, m, ASTString("index_set_1of6"), t_anyarray6, b_index_set1);
2902 rb(env, m, ASTString("index_set_2of6"), t_anyarray6, b_index_set2);
2903 rb(env, m, ASTString("index_set_3of6"), t_anyarray6, b_index_set3);
2904 rb(env, m, ASTString("index_set_4of6"), t_anyarray6, b_index_set4);
2905 rb(env, m, ASTString("index_set_5of6"), t_anyarray6, b_index_set5);
2906 rb(env, m, ASTString("index_set_6of6"), t_anyarray6, b_index_set6);
2907 }
2908 {
2909 std::vector<Type> t_arrayXd(1);
2910 t_arrayXd[0] = Type::top(-1);
2911 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2912 t_arrayXd[0].ot(Type::OT_OPTIONAL);
2913 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2914 t_arrayXd[0] = Type::vartop(-1);
2915 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2916 t_arrayXd[0] = Type::optvartop(-1);
2917 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2918 }
2919 {
2920 std::vector<Type> t_arrayXd(2);
2921 t_arrayXd[0] = Type::parsetint();
2922 t_arrayXd[1] = Type::top(-1);
2923 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2924 t_arrayXd[1].ot(Type::OT_OPTIONAL);
2925 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2926 t_arrayXd[1] = Type::vartop(-1);
2927 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2928 t_arrayXd[1] = Type::optvartop(-1);
2929 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2930 }
2931 {
2932 std::vector<Type> t_arrayXd(2);
2933 t_arrayXd[0] = Type::optvartop(-1);
2934 t_arrayXd[1] = Type::top(-1);
2935 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2936 t_arrayXd[1].ot(Type::OT_OPTIONAL);
2937 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2938 t_arrayXd[1] = Type::vartop(-1);
2939 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2940 t_arrayXd[1] = Type::optvartop(-1);
2941 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2942 }
2943 {
2944 std::vector<Type> t_arrayXd(3);
2945 t_arrayXd[0] = Type::parsetint();
2946 t_arrayXd[1] = Type::parsetint();
2947 t_arrayXd[2] = Type::top(-1);
2948 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2949 t_arrayXd[2].ot(Type::OT_OPTIONAL);
2950 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2951 t_arrayXd[2] = Type::vartop(-1);
2952 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2953 t_arrayXd[2] = Type::optvartop(-1);
2954 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2955 }
2956 {
2957 std::vector<Type> t_arrayXd(4);
2958 t_arrayXd[0] = Type::parsetint();
2959 t_arrayXd[1] = Type::parsetint();
2960 t_arrayXd[2] = Type::parsetint();
2961 t_arrayXd[3] = Type::top(-1);
2962 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2963 t_arrayXd[3].ot(Type::OT_OPTIONAL);
2964 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2965 t_arrayXd[3] = Type::vartop(-1);
2966 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2967 t_arrayXd[3] = Type::optvartop(-1);
2968 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2969 }
2970 {
2971 std::vector<Type> t_arrayXd(5);
2972 t_arrayXd[0] = Type::parsetint();
2973 t_arrayXd[1] = Type::parsetint();
2974 t_arrayXd[2] = Type::parsetint();
2975 t_arrayXd[3] = Type::parsetint();
2976 t_arrayXd[4] = Type::top(-1);
2977 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2978 t_arrayXd[4].ot(Type::OT_OPTIONAL);
2979 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2980 t_arrayXd[4] = Type::vartop(-1);
2981 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2982 t_arrayXd[4] = Type::optvartop(-1);
2983 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2984 }
2985 {
2986 std::vector<Type> t_arrayXd(6);
2987 t_arrayXd[0] = Type::parsetint();
2988 t_arrayXd[1] = Type::parsetint();
2989 t_arrayXd[2] = Type::parsetint();
2990 t_arrayXd[3] = Type::parsetint();
2991 t_arrayXd[4] = Type::parsetint();
2992 t_arrayXd[5] = Type::top(-1);
2993 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2994 t_arrayXd[5].ot(Type::OT_OPTIONAL);
2995 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2996 t_arrayXd[5] = Type::vartop(-1);
2997 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2998 t_arrayXd[5] = Type::optvartop(-1);
2999 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
3000 }
3001 {
3002 std::vector<Type> t_arrayXd(7);
3003 t_arrayXd[0] = Type::parsetint();
3004 t_arrayXd[1] = Type::parsetint();
3005 t_arrayXd[2] = Type::parsetint();
3006 t_arrayXd[3] = Type::parsetint();
3007 t_arrayXd[4] = Type::parsetint();
3008 t_arrayXd[5] = Type::parsetint();
3009 t_arrayXd[6] = Type::top(-1);
3010 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3011 t_arrayXd[6].ot(Type::OT_OPTIONAL);
3012 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3013 t_arrayXd[6] = Type::vartop(-1);
3014 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3015 t_arrayXd[6] = Type::optvartop(-1);
3016 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
3017 }
3018 {
3019 std::vector<Type> stv(3);
3020 stv[0] = Type::partop(-1);
3021 stv[1] = Type::parsetint(1);
3022 stv[2] = Type::parsetint();
3023 rb(env, m, ASTString("slice_1d"), stv, b_slice);
3024 stv[0] = Type::vartop(-1);
3025 rb(env, m, ASTString("slice_1d"), stv, b_slice);
3026 stv[0] = Type::optvartop(-1);
3027 rb(env, m, ASTString("slice_1d"), stv, b_slice);
3028 stv[0] = Type::optpartop(-1);
3029 rb(env, m, ASTString("slice_1d"), stv, b_slice);
3030
3031 stv.push_back(Type::parsetint());
3032 stv[0] = Type::partop(-1);
3033 rb(env, m, ASTString("slice_2d"), stv, b_slice);
3034 stv[0] = Type::vartop(-1);
3035 rb(env, m, ASTString("slice_2d"), stv, b_slice);
3036 stv[0] = Type::optvartop(-1);
3037 rb(env, m, ASTString("slice_2d"), stv, b_slice);
3038 stv[0] = Type::optpartop(-1);
3039 rb(env, m, ASTString("slice_2d"), stv, b_slice);
3040
3041 stv.push_back(Type::parsetint());
3042 stv[0] = Type::partop(-1);
3043 rb(env, m, ASTString("slice_3d"), stv, b_slice);
3044 stv[0] = Type::vartop(-1);
3045 rb(env, m, ASTString("slice_3d"), stv, b_slice);
3046 stv[0] = Type::optvartop(-1);
3047 rb(env, m, ASTString("slice_3d"), stv, b_slice);
3048 stv[0] = Type::optpartop(-1);
3049 rb(env, m, ASTString("slice_3d"), stv, b_slice);
3050
3051 stv.push_back(Type::parsetint());
3052 stv[0] = Type::partop(-1);
3053 rb(env, m, ASTString("slice_4d"), stv, b_slice);
3054 stv[0] = Type::vartop(-1);
3055 rb(env, m, ASTString("slice_4d"), stv, b_slice);
3056 stv[0] = Type::optvartop(-1);
3057 rb(env, m, ASTString("slice_4d"), stv, b_slice);
3058 stv[0] = Type::optpartop(-1);
3059 rb(env, m, ASTString("slice_4d"), stv, b_slice);
3060
3061 stv.push_back(Type::parsetint());
3062 stv[0] = Type::partop(-1);
3063 rb(env, m, ASTString("slice_5d"), stv, b_slice);
3064 stv[0] = Type::vartop(-1);
3065 rb(env, m, ASTString("slice_5d"), stv, b_slice);
3066 stv[0] = Type::optvartop(-1);
3067 rb(env, m, ASTString("slice_5d"), stv, b_slice);
3068 stv[0] = Type::optpartop(-1);
3069 rb(env, m, ASTString("slice_5d"), stv, b_slice);
3070
3071 stv.push_back(Type::parsetint());
3072 stv[0] = Type::partop(-1);
3073 rb(env, m, ASTString("slice_6d"), stv, b_slice);
3074 stv[0] = Type::vartop(-1);
3075 rb(env, m, ASTString("slice_6d"), stv, b_slice);
3076 stv[0] = Type::optvartop(-1);
3077 rb(env, m, ASTString("slice_6d"), stv, b_slice);
3078 stv[0] = Type::optpartop(-1);
3079 rb(env, m, ASTString("slice_6d"), stv, b_slice);
3080 }
3081 {
3082 std::vector<Type> t(2);
3083 t[0] = Type::parbool();
3084 t[1] = Type::parstring();
3085 rb(env, m, constants().ids.assert, t, b_assert_bool);
3086 }
3087 {
3088 std::vector<Type> t(3);
3089 t[0] = Type::parbool();
3090 t[1] = Type::parstring();
3091 t[2] = Type::top();
3092 rb(env, m, constants().ids.assert, t, b_assert);
3093 t[2] = Type::optpartop();
3094 rb(env, m, constants().ids.assert, t, b_assert);
3095 t[2] = Type::vartop();
3096 rb(env, m, constants().ids.assert, t, b_assert);
3097 t[2] = Type::optvartop();
3098 rb(env, m, constants().ids.assert, t, b_assert);
3099 t[2] = Type::top(-1);
3100 rb(env, m, constants().ids.assert, t, b_assert);
3101 t[2] = Type::optpartop(-1);
3102 rb(env, m, constants().ids.assert, t, b_assert);
3103 t[2] = Type::vartop(-1);
3104 rb(env, m, constants().ids.assert, t, b_assert);
3105 t[2] = Type::optvartop(-1);
3106 rb(env, m, constants().ids.assert, t, b_assert);
3107 }
3108 {
3109 std::vector<Type> t(4);
3110 t[0] = Type::parstring();
3111 t[1] = Type::parstring();
3112 t[2] = Type::parstring();
3113 t[3] = Type::top();
3114 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3115 t[3] = Type::vartop();
3116 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3117 t[3] = Type::optvartop();
3118 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3119 t[3] = Type::top(-1);
3120 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3121 t[3] = Type::vartop(-1);
3122 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3123 t[3] = Type::optvartop(-1);
3124 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate);
3125 }
3126 {
3127 rb(env, m, constants().ids.mzn_symmetry_breaking_constraint, {Type::varbool()},
3128 b_mzn_symmetry_breaking_constraint);
3129 rb(env, m, constants().ids.mzn_redundant_constraint, {Type::varbool()},
3130 b_mzn_redundant_constraint);
3131 }
3132 {
3133 std::vector<Type> t(1);
3134 t[0] = Type::parstring();
3135 rb(env, m, ASTString("abort"), t, b_abort);
3136 rb(env, m, constants().ids.trace, t, b_trace);
3137 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3138 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3139 }
3140 {
3141 std::vector<Type> t;
3142 rb(env, m, ASTString("logstream_to_string"), t, b_logstream);
3143 }
3144 {
3145 std::vector<Type> t(2);
3146 t[0] = Type::parstring();
3147 t[1] = Type::top();
3148 rb(env, m, constants().ids.trace, t, b_trace);
3149 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3150 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3151 t[1] = Type::optpartop();
3152 rb(env, m, constants().ids.trace, t, b_trace);
3153 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3154 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3155 t[1] = Type::vartop();
3156 rb(env, m, constants().ids.trace, t, b_trace);
3157 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3158 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3159 t[1] = Type::optvartop();
3160 rb(env, m, constants().ids.trace, t, b_trace);
3161 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3162 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3163 t[1] = Type::top(-1);
3164 rb(env, m, constants().ids.trace, t, b_trace);
3165 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3166 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3167 t[1] = Type::optpartop(-1);
3168 rb(env, m, constants().ids.trace, t, b_trace);
3169 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3170 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3171 t[1] = Type::vartop(-1);
3172 rb(env, m, constants().ids.trace, t, b_trace);
3173 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3174 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3175 t[1] = Type::optvartop(-1);
3176 rb(env, m, constants().ids.trace, t, b_trace);
3177 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
3178 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream);
3179 }
3180 {
3181 rb(env, m, ASTString("mzn_in_redundant_constraint"), std::vector<Type>(),
3182 b_in_redundant_constraint);
3183 }
3184 {
3185 rb(env, m, ASTString("mzn_in_symmetry_breaking_constraint"), std::vector<Type>(),
3186 b_in_symmetry_breaking_constraint);
3187 }
3188 {
3189 std::vector<Type> t_length(1);
3190 t_length[0] = Type::optvartop(-1);
3191 rb(env, m, ASTString("length"), t_length, b_length);
3192 }
3193 {
3194 std::vector<Type> t(1);
3195 t[0] = Type::parbool();
3196 rb(env, m, constants().ids.bool2int, t, b_bool2int);
3197 }
3198 {
3199 std::vector<Type> t(1);
3200 t[0] = Type::parbool(-1);
3201 rb(env, m, constants().ids.forall, t, b_forall_par);
3202 rb(env, m, constants().ids.exists, t, b_exists_par);
3203 rb(env, m, ASTString("xorall"), t, b_xorall_par);
3204 rb(env, m, ASTString("iffall"), t, b_iffall_par);
3205 }
3206 { rb(env, m, constants().ids.bool_not, {Type::parbool()}, b_not_par); }
3207 {
3208 std::vector<Type> t(2);
3209 t[0] = Type::parbool(-1);
3210 t[1] = Type::parbool(-1);
3211 rb(env, m, constants().ids.clause, t, b_clause_par);
3212 }
3213 {
3214 std::vector<Type> t(1);
3215 t[0] = Type::varsetint();
3216 rb(env, m, ASTString("ub"), t, b_ub_set);
3217 rb(env, m, ASTString("lb"), t, b_lb_set);
3218 }
3219 {
3220 std::vector<Type> t(1);
3221 t[0] = Type::varsetint(1);
3222 rb(env, m, ASTString("ub_array"), t, b_array_ub_set);
3223 }
3224 {
3225 std::vector<Type> t(1);
3226 t[0] = Type::varint();
3227 rb(env, m, ASTString("dom"), t, b_dom_varint);
3228 t[0].ot(Type::OT_OPTIONAL);
3229 rb(env, m, ASTString("dom"), t, b_dom_varint);
3230 }
3231 {
3232 std::vector<Type> t(1);
3233 t[0] = Type::varint(-1);
3234 rb(env, m, ASTString("dom_array"), t, b_dom_array);
3235 rb(env, m, ASTString("dom_bounds_array"), t, b_dom_bounds_array);
3236 t[0].ot(Type::OT_OPTIONAL);
3237 rb(env, m, ASTString("dom_array"), t, b_dom_array);
3238 rb(env, m, ASTString("dom_bounds_array"), t, b_dom_bounds_array);
3239 }
3240 {
3241 std::vector<Type> t(1);
3242 t[0] = Type::parsetint();
3243 rb(env, m, ASTString("min"), t, b_min_parsetint);
3244 }
3245 {
3246 std::vector<Type> t(1);
3247 t[0] = Type::parsetint();
3248 rb(env, m, ASTString("max"), t, b_max_parsetint);
3249 }
3250 {
3251 std::vector<Type> t(1);
3252 t[0] = Type::varint();
3253 t[0].ot(Type::OT_OPTIONAL);
3254 rb(env, m, ASTString("lb"), t, b_lb_varoptint);
3255 }
3256 {
3257 std::vector<Type> t(1);
3258 t[0] = Type::varint();
3259 t[0].ot(Type::OT_OPTIONAL);
3260 rb(env, m, ASTString("ub"), t, b_ub_varoptint);
3261 }
3262 {
3263 std::vector<Type> t(1);
3264 t[0] = Type::varint();
3265 rb(env, m, ASTString("lb"), t, b_lb_varoptint);
3266 }
3267 {
3268 std::vector<Type> t(1);
3269 t[0] = Type::varint();
3270 rb(env, m, ASTString("ub"), t, b_ub_varoptint);
3271 }
3272 {
3273 std::vector<Type> t(1);
3274 t[0] = Type::varint(-1);
3275 t[0].ot(Type::OT_OPTIONAL);
3276 rb(env, m, ASTString("lb_array"), t, b_array_lb_int);
3277 }
3278 {
3279 std::vector<Type> t(1);
3280 t[0] = Type::varint(-1);
3281 t[0].ot(Type::OT_OPTIONAL);
3282 rb(env, m, ASTString("ub_array"), t, b_array_ub_int);
3283 }
3284 {
3285 std::vector<Type> t(1);
3286 t[0] = Type::varfloat();
3287 t[0].ot(Type::OT_OPTIONAL);
3288 rb(env, m, ASTString("lb"), t, b_lb_varoptfloat);
3289 }
3290 {
3291 std::vector<Type> t(1);
3292 t[0] = Type::varfloat();
3293 t[0].ot(Type::OT_OPTIONAL);
3294 rb(env, m, ASTString("ub"), t, b_ub_varoptfloat);
3295 }
3296 {
3297 std::vector<Type> t(1);
3298 t[0] = Type::varfloat();
3299 rb(env, m, ASTString("lb"), t, b_lb_varoptfloat);
3300 }
3301 {
3302 std::vector<Type> t(1);
3303 t[0] = Type::varfloat();
3304 rb(env, m, ASTString("ub"), t, b_ub_varoptfloat);
3305 }
3306 {
3307 std::vector<Type> t(1);
3308 t[0] = Type::varfloat(-1);
3309 t[0].ot(Type::OT_OPTIONAL);
3310 rb(env, m, ASTString("lb_array"), t, b_array_lb_float);
3311 }
3312 {
3313 std::vector<Type> t(1);
3314 t[0] = Type::varfloat(-1);
3315 t[0].ot(Type::OT_OPTIONAL);
3316 rb(env, m, ASTString("ub_array"), t, b_array_ub_float);
3317 }
3318 {
3319 std::vector<Type> t(1);
3320 t[0] = Type::parsetint();
3321 rb(env, m, ASTString("card"), t, b_card);
3322 }
3323 {
3324 std::vector<Type> t(1);
3325 t[0] = Type::parsetint();
3326 rb(env, m, ASTString("set_to_ranges"), t, b_set_to_ranges_int);
3327 t[0] = Type::parsetfloat();
3328 rb(env, m, ASTString("set_to_ranges"), t, b_set_to_ranges_float);
3329 }
3330 {
3331 std::vector<Type> t(1);
3332 t[0] = Type::parint();
3333 rb(env, m, ASTString("abs"), t, b_abs_int);
3334 t[0] = Type::parfloat();
3335 rb(env, m, ASTString("abs"), t, b_abs_float);
3336 }
3337 {
3338 std::vector<Type> t(1);
3339 t[0] = Type::varint();
3340 rb(env, m, ASTString("has_bounds"), t, b_has_bounds_int);
3341 }
3342 {
3343 std::vector<Type> t(1);
3344 t[0] = Type::varfloat();
3345 rb(env, m, ASTString("has_bounds"), t, b_has_bounds_float);
3346 }
3347 {
3348 std::vector<Type> t(1);
3349 t[0] = Type::varsetint();
3350 rb(env, m, ASTString("has_ub_set"), t, b_has_ub_set);
3351 }
3352 {
3353 std::vector<Type> t(1);
3354 t[0] = Type::optvartop();
3355 rb(env, m, ASTString("is_fixed"), t, b_is_fixed);
3356 t[0] = Type::varsetint();
3357 rb(env, m, ASTString("is_fixed"), t, b_is_fixed);
3358 Type setoftop;
3359 setoftop.bt(Type::BT_TOP);
3360 setoftop.st(Type::ST_SET);
3361 setoftop.ti(Type::TI_PAR);
3362 setoftop.ot(Type::OT_PRESENT);
3363 t[0] = setoftop;
3364 rb(env, m, ASTString("is_fixed"), t, b_is_fixed);
3365 }
3366 {
3367 std::vector<Type> t(1);
3368 t[0] = Type::optvartop(-1);
3369 rb(env, m, ASTString("is_fixed"), t, b_is_fixed_array);
3370 }
3371 {
3372 std::vector<Type> t(2);
3373 t[0] = t[1] = Type::optvartop();
3374 rb(env, m, ASTString("is_same"), t, b_is_same);
3375 }
3376 {
3377 std::vector<Type> t(1);
3378 t[0] = Type::optvartop();
3379 rb(env, m, ASTString("fix"), t, b_fix_bool);
3380 rb(env, m, ASTString("fix"), t, b_fix_int);
3381 rb(env, m, ASTString("fix"), t, b_fix_set);
3382 rb(env, m, ASTString("fix"), t, b_fix_float);
3383 }
3384 {
3385 std::vector<Type> t(1);
3386 t[0] = Type::optvartop(1);
3387 rb(env, m, ASTString("fix"), t, b_fix_array);
3388 }
3389 {
3390 std::vector<Type> t(2);
3391 t[0] = Type::optvartop();
3392 t[1] = Type::ann();
3393 rb(env, m, ASTString("has_ann"), t, b_has_ann);
3394 t[0] = Type::varsetint();
3395 rb(env, m, ASTString("has_ann"), t, b_has_ann);
3396 Type setoftop;
3397 setoftop.bt(Type::BT_TOP);
3398 setoftop.st(Type::ST_SET);
3399 setoftop.ti(Type::TI_PAR);
3400 setoftop.ot(Type::OT_PRESENT);
3401 t[0] = setoftop;
3402 rb(env, m, ASTString("has_ann"), t, b_has_ann);
3403 }
3404 {
3405 std::vector<Type> t(2);
3406 t[0] = Type::optvartop();
3407 t[1] = Type::ann();
3408 rb(env, m, ASTString("annotate"), t, b_annotate);
3409 t[0] = Type::varsetint();
3410 rb(env, m, ASTString("annotate"), t, b_annotate);
3411 Type setoftop;
3412 setoftop.bt(Type::BT_TOP);
3413 setoftop.st(Type::ST_SET);
3414 setoftop.ti(Type::TI_PAR);
3415 setoftop.ot(Type::OT_PRESENT);
3416 t[0] = setoftop;
3417 rb(env, m, ASTString("annotate"), t, b_annotate);
3418 }
3419 {
3420 std::vector<Type> t(1);
3421 t[0] = Type::parint();
3422 rb(env, m, ASTString("int2float"), t, b_int2float);
3423 }
3424 {
3425 std::vector<Type> t(1);
3426 t[0] = Type::parfloat();
3427 rb(env, m, ASTString("ceil"), t, b_ceil);
3428 rb(env, m, ASTString("floor"), t, b_floor);
3429 rb(env, m, ASTString("round"), t, b_round);
3430 rb(env, m, ASTString("log10"), t, b_log10);
3431 rb(env, m, ASTString("log2"), t, b_log2);
3432 rb(env, m, ASTString("ln"), t, b_ln);
3433 rb(env, m, ASTString("exp"), t, b_exp);
3434 rb(env, m, ASTString("sqrt"), t, b_sqrt);
3435 t.push_back(Type::parfloat());
3436 rb(env, m, ASTString("log"), t, b_log);
3437 rb(env, m, ASTString("pow"), t, b_pow);
3438 }
3439 {
3440 std::vector<Type> t(1);
3441 t[0] = Type::parfloat(1);
3442 rb(env, m, constants().ids.sum, t, b_sum_float);
3443 rb(env, m, ASTString("product"), t, b_product_float);
3444 }
3445 {
3446 std::vector<Type> t(1);
3447 t[0] = Type::parfloat(1);
3448 rb(env, m, ASTString("min"), t, b_float_min);
3449 rb(env, m, ASTString("max"), t, b_float_max);
3450
3451 t[0] = Type::parfloat();
3452 t.push_back(Type::parfloat());
3453 rb(env, m, ASTString("min"), t, b_float_min);
3454 rb(env, m, ASTString("max"), t, b_float_max);
3455 }
3456 {
3457 std::vector<Type> t(1);
3458 t[0] = Type::parsetint();
3459 rb(env, m, ASTString("set2array"), t, b_set2array);
3460 }
3461 {
3462 std::vector<Type> t(1);
3463 t[0] = Type::parstring();
3464 rb(env, m, ASTString("string_length"), t, b_string_length);
3465 }
3466 { rb(env, m, ASTString("file_path"), std::vector<Type>(), b_file_path); }
3467 {
3468 std::vector<Type> t(1);
3469 t[0] = Type::vartop();
3470 rb(env, m, ASTString("show"), t, b_show);
3471 rb(env, m, ASTString("showJSON"), t, b_show_json);
3472 t[0] = Type::vartop();
3473 t[0].st(Type::ST_SET);
3474 t[0].ot(Type::OT_OPTIONAL);
3475 rb(env, m, ASTString("show"), t, b_show);
3476 rb(env, m, ASTString("showJSON"), t, b_show_json);
3477 t[0] = Type::vartop(-1);
3478 rb(env, m, ASTString("show"), t, b_show);
3479 rb(env, m, ASTString("showJSON"), t, b_show_json);
3480 }
3481 {
3482 std::vector<Type> t(1);
3483 t[0] = Type::parstring();
3484 rb(env, m, ASTString("showDznId"), t, b_show_dzn_id);
3485 }
3486 {
3487 std::vector<Type> t(3);
3488 t[0] = t[1] = Type::parint();
3489 t[2] = Type::vartop();
3490 rb(env, m, ASTString("format"), t, b_format);
3491 t[2] = Type::vartop();
3492 t[2].st(Type::ST_SET);
3493 t[2].ot(Type::OT_OPTIONAL);
3494 rb(env, m, ASTString("format"), t, b_format);
3495 t[2] = Type::vartop(-1);
3496 rb(env, m, ASTString("format"), t, b_format);
3497 }
3498 {
3499 std::vector<Type> t(2);
3500 t[0] = Type::parint();
3501 t[1] = Type::vartop();
3502 rb(env, m, ASTString("format"), t, b_format);
3503 t[1] = Type::vartop();
3504 t[1].st(Type::ST_SET);
3505 t[1].ot(Type::OT_OPTIONAL);
3506 rb(env, m, ASTString("format"), t, b_format);
3507 t[1] = Type::vartop(-1);
3508 rb(env, m, ASTString("format"), t, b_format);
3509 t[1] = Type::parstring();
3510 rb(env, m, ASTString("format_justify_string"), t, b_format_justify_string);
3511 }
3512 {
3513 std::vector<Type> t;
3514 rb(env, m, ASTString("outputJSON"), t, b_output_json);
3515 rb(env, m, ASTString("outputJSONParameters"), t, b_output_json_parameters);
3516 }
3517 {
3518 std::vector<Type> t(2);
3519 t[0] = Type::parint();
3520 t[1] = Type::varint();
3521 rb(env, m, ASTString("show_int"), t, b_show_int);
3522 }
3523 {
3524 std::vector<Type> t(3);
3525 t[0] = Type::parint();
3526 t[1] = Type::parint();
3527 t[2] = Type::varfloat();
3528 rb(env, m, ASTString("show_float"), t, b_show_float);
3529 }
3530 {
3531 std::vector<Type> t(1);
3532 t[0] = Type::parstring(1);
3533 rb(env, m, ASTString("concat"), t, b_concat);
3534 }
3535 {
3536 std::vector<Type> t(2);
3537 t[0] = Type::parstring();
3538 t[1] = Type::parstring(1);
3539 rb(env, m, ASTString("join"), t, b_join);
3540 }
3541 {
3542 std::vector<Type> t(2);
3543 t[0] = Type::varint();
3544 t[1] = Type::varint();
3545 rb(env, m, ASTString("compute_div_bounds"), t, b_compute_div_bounds);
3546 }
3547 {
3548 std::vector<Type> t(1);
3549 t[0] = Type::parsetint(1);
3550 rb(env, m, ASTString("array_intersect"), t, b_array_intersect);
3551 rb(env, m, ASTString("array_union"), t, b_array_union);
3552 }
3553 {
3554 std::vector<Type> t(1);
3555 t[0] = Type::parint();
3556 t[0].ot(Type::OT_OPTIONAL);
3557 t[0].bt(Type::BT_TOP);
3558 rb(env, m, ASTString("occurs"), t, b_occurs);
3559 rb(env, m, ASTString("deopt"), t, b_deopt_expr);
3560 t[0].bt(Type::BT_INT);
3561 rb(env, m, ASTString("deopt"), t, b_deopt_int);
3562 t[0].bt(Type::BT_BOOL);
3563 rb(env, m, ASTString("deopt"), t, b_deopt_bool);
3564 t[0].bt(Type::BT_FLOAT);
3565 rb(env, m, ASTString("deopt"), t, b_deopt_float);
3566 t[0].bt(Type::BT_STRING);
3567 rb(env, m, ASTString("deopt"), t, b_deopt_string);
3568 t[0].bt(Type::BT_INT);
3569 t[0].st(Type::ST_SET);
3570 rb(env, m, ASTString("deopt"), t, b_deopt_intset);
3571 }
3572 {
3573 std::vector<Type> t(2);
3574 t[0] = Type::varbot(1);
3575 t[1] = Type::parint(1);
3576 rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
3577 t[0] = Type::bot(1);
3578 rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
3579 t[0].ot(Type::OT_OPTIONAL);
3580 rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
3581 }
3582 {
3583 std::vector<Type> t(2);
3584 t[0] = Type::varbot(1);
3585 t[1] = Type::parfloat(1);
3586 rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
3587 t[0] = Type::bot(1);
3588 rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
3589 t[0].ot(Type::OT_OPTIONAL);
3590 rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
3591 }
3592 {
3593 std::vector<Type> t(1);
3594 t[0] = Type::parint(1);
3595 rb(env, m, ASTString("sort"), t, b_sort);
3596 rb(env, m, ASTString("arg_min"), t, b_arg_min_int);
3597 rb(env, m, ASTString("arg_max"), t, b_arg_max_int);
3598 t[0] = Type::parbool(1);
3599 rb(env, m, ASTString("sort"), t, b_sort);
3600 rb(env, m, ASTString("arg_min"), t, b_arg_min_bool);
3601 rb(env, m, ASTString("arg_max"), t, b_arg_max_bool);
3602 t[0] = Type::parfloat(1);
3603 rb(env, m, ASTString("sort"), t, b_sort);
3604 rb(env, m, ASTString("arg_min"), t, b_arg_min_float);
3605 rb(env, m, ASTString("arg_max"), t, b_arg_max_float);
3606 }
3607 {
3608 std::vector<Type> t(1);
3609 t[0] = Type::parint(1);
3610 rb(env, m, ASTString("inverse"), t, b_inverse, true);
3611 }
3612 {
3613 std::vector<Type> t(1);
3614 t[0] = Type::parfloat();
3615 rb(env, m, ASTString("atan"), t, b_atan);
3616 }
3617 {
3618 std::vector<Type> t(1);
3619 t[0] = Type::parfloat();
3620 rb(env, m, ASTString("cos"), t, b_cos);
3621 }
3622 {
3623 std::vector<Type> t(1);
3624 t[0] = Type::parfloat();
3625 rb(env, m, ASTString("sin"), t, b_sin);
3626 }
3627 {
3628 std::vector<Type> t(1);
3629 t[0] = Type::parfloat();
3630 rb(env, m, ASTString("asin"), t, b_asin);
3631 }
3632 {
3633 std::vector<Type> t(1);
3634 t[0] = Type::parfloat();
3635 rb(env, m, ASTString("acos"), t, b_acos);
3636 }
3637 {
3638 std::vector<Type> t(1);
3639 t[0] = Type::parfloat();
3640 rb(env, m, ASTString("tan"), t, b_tan);
3641 }
3642 {
3643 std::vector<Type> t(2);
3644 t[0] = Type::parfloat();
3645 t[1] = Type::parfloat();
3646 rb(env, m, ASTString("normal"), t, b_normal_float_float);
3647 t[0] = Type::parint();
3648 rb(env, m, ASTString("normal"), t, b_normal_int_float);
3649 }
3650 {
3651 std::vector<Type> t(2);
3652 t[0] = Type::parfloat();
3653 t[1] = Type::parfloat();
3654 rb(env, m, ASTString("uniform"), t, b_uniform_float);
3655 t[0] = Type::parint();
3656 t[1] = Type::parint();
3657 rb(env, m, ASTString("uniform"), t, b_uniform_int);
3658 }
3659 {
3660 std::vector<Type> t(1);
3661 t[0] = Type::parfloat();
3662 rb(env, m, ASTString("poisson"), t, b_poisson_float);
3663 t[0] = Type::parint();
3664 rb(env, m, ASTString("poisson"), t, b_poisson_int);
3665 }
3666 {
3667 std::vector<Type> t(2);
3668 t[0] = Type::parfloat();
3669 t[1] = Type::parfloat();
3670 rb(env, m, ASTString("gamma"), t, b_gamma_float_float);
3671 t[0] = Type::parint();
3672 rb(env, m, ASTString("gamma"), t, b_gamma_int_float);
3673 }
3674 {
3675 std::vector<Type> t(2);
3676 t[0] = Type::parfloat();
3677 t[1] = Type::parfloat();
3678 rb(env, m, ASTString("weibull"), t, b_weibull_float_float);
3679 t[0] = Type::parint();
3680 rb(env, m, ASTString("weibull"), t, b_weibull_int_float);
3681 }
3682 {
3683 std::vector<Type> t(1);
3684 t[0] = Type::parfloat();
3685 rb(env, m, ASTString("exponential"), t, b_exponential_float);
3686 t[0] = Type::parint();
3687 rb(env, m, ASTString("exponential"), t, b_exponential_int);
3688 }
3689 {
3690 std::vector<Type> t(2);
3691 t[0] = Type::parfloat();
3692 t[1] = Type::parfloat();
3693 rb(env, m, ASTString("lognormal"), t, b_lognormal_float_float);
3694 t[0] = Type::parint();
3695 rb(env, m, ASTString("lognormal"), t, b_lognormal_int_float);
3696 }
3697 {
3698 std::vector<Type> t(1);
3699 t[0] = Type::parfloat();
3700 rb(env, m, ASTString("chisquared"), t, b_chisquared_float);
3701 t[0] = Type::parint();
3702 rb(env, m, ASTString("chisquared"), t, b_chisquared_int);
3703 }
3704 {
3705 std::vector<Type> t(2);
3706 t[0] = Type::parfloat();
3707 t[1] = Type::parfloat();
3708 rb(env, m, ASTString("cauchy"), t, b_cauchy_float_float);
3709 t[0] = Type::parint();
3710 rb(env, m, ASTString("cauchy"), t, b_cauchy_int_float);
3711 }
3712 {
3713 std::vector<Type> t(2);
3714 t[0] = Type::parfloat();
3715 t[1] = Type::parfloat();
3716 rb(env, m, ASTString("fdistribution"), t, b_fdistribution_float_float);
3717 t[0] = Type::parint();
3718 t[1] = Type::parint();
3719 rb(env, m, ASTString("fdistribution"), t, b_fdistribution_int_int);
3720 }
3721 {
3722 std::vector<Type> t(1);
3723 t[0] = Type::parfloat();
3724 rb(env, m, ASTString("tdistribution"), t, b_tdistribution_float);
3725 t[0] = Type::parint();
3726 rb(env, m, ASTString("tdistribution"), t, b_tdistribution_int);
3727 }
3728 {
3729 std::vector<Type> t(1);
3730 t[0] = Type::parint(1);
3731 rb(env, m, ASTString("discrete_distribution"), t, b_discrete_distribution);
3732 }
3733 {
3734 std::vector<Type> t(1);
3735 t[0] = Type::parint();
3736 rb(env, m, ASTString("bernoulli"), t, b_bernoulli);
3737 }
3738 {
3739 std::vector<Type> t(2);
3740 t[0] = Type::parint();
3741 t[1] = Type::parfloat();
3742 rb(env, m, ASTString("binomial"), t, b_binomial);
3743 }
3744 {
3745 std::vector<Type> t(2);
3746 t[0] = Type::parsetint();
3747 t[1] = Type::parint();
3748 rb(env, m, ASTString("to_enum"), t, b_to_enum);
3749 rb(env, m, ASTString("enum_next"), t, b_enum_next);
3750 rb(env, m, ASTString("enum_prev"), t, b_enum_prev);
3751 }
3752 { rb(env, m, ASTString("mzn_compiler_version"), std::vector<Type>(), b_mzn_compiler_version); }
3753 {
3754 std::vector<Type> t(2);
3755 t[0] = Type::varint(1);
3756 t[1] = Type::parstring();
3757 rb(env, m, ASTString("fzn_regular"), t, b_regular_from_string, true);
3758 }
3759 { rb(env, m, ASTString("showCheckerOutput"), {}, b_show_checker_output); }
3760 }
3761
3762 } // namespace MiniZinc
3763