this repo has no description
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/flatten_internal.hh>
20#include <minizinc/output.hh>
21#include <minizinc/prettyprinter.hh>
22#include <minizinc/support/regex.hh>
23
24#include <climits>
25#include <cmath>
26#include <iomanip>
27#include <random>
28
29namespace MiniZinc {
30
31void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
32 FunctionI::builtin_e b, bool fromGlobals = false) {
33 FunctionI* fi = m->matchFn(env, id, t, false);
34 if (fi) {
35 fi->_builtins.e = b;
36 } else if (!fromGlobals) {
37 throw InternalError("no definition found for builtin " + id.str());
38 }
39}
40void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
41 FunctionI::builtin_f b, bool fromGlobals = false) {
42 FunctionI* fi = m->matchFn(env, id, t, false);
43 if (fi) {
44 fi->_builtins.f = b;
45 } else if (!fromGlobals) {
46 throw InternalError("no definition found for builtin " + id.str());
47 }
48}
49void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
50 FunctionI::builtin_i b, bool fromGlobals = false) {
51 FunctionI* fi = m->matchFn(env, id, t, false);
52 if (fi) {
53 fi->_builtins.i = b;
54 } else if (!fromGlobals) {
55 throw InternalError("no definition found for builtin " + id.str());
56 }
57}
58void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
59 FunctionI::builtin_b b, bool fromGlobals = false) {
60 FunctionI* fi = m->matchFn(env, id, t, false);
61 if (fi) {
62 fi->_builtins.b = b;
63 } else if (!fromGlobals) {
64 throw InternalError("no definition found for builtin " + id.str());
65 }
66}
67void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
68 FunctionI::builtin_s b, bool fromGlobals = false) {
69 FunctionI* fi = m->matchFn(env, id, t, false);
70 if (fi) {
71 fi->_builtins.s = b;
72 } else if (!fromGlobals) {
73 throw InternalError("no definition found for builtin " + id.str());
74 }
75}
76void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t,
77 FunctionI::builtin_str b, bool fromGlobals = false) {
78 FunctionI* fi = m->matchFn(env, id, t, false);
79 if (fi) {
80 fi->_builtins.str = b;
81 } else if (!fromGlobals) {
82 throw InternalError("no definition found for builtin " + id.str());
83 }
84}
85
86IntVal b_int_min(EnvI& env, Call* call) {
87 switch (call->n_args()) {
88 case 1:
89 if (call->arg(0)->type().is_set()) {
90 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
91 } else {
92 GCLock lock;
93 ArrayLit* al = eval_array_lit(env, call->arg(0));
94 if (al->size() == 0)
95 throw ResultUndefinedError(env, al->loc(), "minimum of empty array is undefined");
96 IntVal m = eval_int(env, (*al)[0]);
97 for (unsigned int i = 1; i < al->size(); i++) m = std::min(m, eval_int(env, (*al)[i]));
98 return m;
99 }
100 case 2: {
101 return std::min(eval_int(env, call->arg(0)), eval_int(env, call->arg(1)));
102 }
103 default:
104 throw EvalError(env, Location(), "dynamic type error");
105 }
106}
107
108IntVal b_int_max(EnvI& env, Call* call) {
109 switch (call->n_args()) {
110 case 1:
111 if (call->arg(0)->type().is_set()) {
112 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
113 } else {
114 GCLock lock;
115 ArrayLit* al = eval_array_lit(env, call->arg(0));
116 if (al->size() == 0)
117 throw ResultUndefinedError(env, al->loc(), "maximum of empty array is undefined");
118 IntVal m = eval_int(env, (*al)[0]);
119 for (unsigned int i = 1; i < al->size(); i++) m = std::max(m, eval_int(env, (*al)[i]));
120 return m;
121 }
122 case 2: {
123 return std::max(eval_int(env, call->arg(0)), eval_int(env, call->arg(1)));
124 }
125 default:
126 throw EvalError(env, Location(), "dynamic type error");
127 }
128}
129
130IntVal b_arg_min_int(EnvI& env, Call* call) {
131 GCLock lock;
132 ArrayLit* al = eval_array_lit(env, call->arg(0));
133 if (al->size() == 0)
134 throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined");
135 IntVal m = eval_int(env, (*al)[0]);
136 int m_idx = 0;
137 for (unsigned int i = 1; i < al->size(); i++) {
138 IntVal mi = eval_int(env, (*al)[i]);
139 if (mi < m) {
140 m = mi;
141 m_idx = i;
142 }
143 }
144 return m_idx + 1;
145}
146IntVal b_arg_max_int(EnvI& env, Call* call) {
147 GCLock lock;
148 ArrayLit* al = eval_array_lit(env, call->arg(0));
149 if (al->size() == 0)
150 throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined");
151 IntVal m = eval_int(env, (*al)[0]);
152 int m_idx = 0;
153 for (unsigned int i = 1; i < al->size(); i++) {
154 IntVal mi = eval_int(env, (*al)[i]);
155 if (mi > m) {
156 m = mi;
157 m_idx = i;
158 }
159 }
160 return m_idx + 1;
161}
162IntVal b_arg_min_float(EnvI& env, Call* call) {
163 GCLock lock;
164 ArrayLit* al = eval_array_lit(env, call->arg(0));
165 if (al->size() == 0)
166 throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined");
167 FloatVal m = eval_float(env, (*al)[0]);
168 int m_idx = 0;
169 for (unsigned int i = 1; i < al->size(); i++) {
170 FloatVal mi = eval_float(env, (*al)[i]);
171 if (mi < m) {
172 m = mi;
173 m_idx = i;
174 }
175 }
176 return m_idx + 1;
177}
178IntVal b_arg_max_float(EnvI& env, Call* call) {
179 GCLock lock;
180 ArrayLit* al = eval_array_lit(env, call->arg(0));
181 if (al->size() == 0)
182 throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined");
183 FloatVal m = eval_float(env, (*al)[0]);
184 int m_idx = 0;
185 for (unsigned int i = 1; i < al->size(); i++) {
186 FloatVal mi = eval_float(env, (*al)[i]);
187 if (mi > m) {
188 m = mi;
189 m_idx = i;
190 }
191 }
192 return m_idx + 1;
193}
194
195IntVal b_abs_int(EnvI& env, Call* call) {
196 assert(call->n_args() == 1);
197 return std::abs(eval_int(env, call->arg(0)));
198}
199
200FloatVal b_abs_float(EnvI& env, Call* call) {
201 assert(call->n_args() == 1);
202 return std::abs(eval_float(env, call->arg(0)));
203}
204
205bool b_has_bounds_int(EnvI& env, Call* call) {
206 if (call->n_args() != 1) throw EvalError(env, Location(), "dynamic type error");
207 IntBounds ib = compute_int_bounds(env, call->arg(0));
208 return ib.valid && ib.l.isFinite() && ib.u.isFinite();
209}
210bool b_has_bounds_float(EnvI& env, Call* call) {
211 if (call->n_args() != 1) throw EvalError(env, Location(), "dynamic type error");
212 FloatBounds fb = compute_float_bounds(env, call->arg(0));
213 return fb.valid;
214}
215
216IntVal lb_varoptint(EnvI& env, Expression* e) {
217 IntBounds b = compute_int_bounds(env, e);
218 if (b.valid)
219 return b.l;
220 else
221 return -IntVal::infinity();
222}
223IntVal b_lb_varoptint(EnvI& env, Call* call) {
224 if (call->n_args() != 1) throw EvalError(env, Location(), "dynamic type error");
225 return lb_varoptint(env, call->arg(0));
226}
227
228bool b_occurs(EnvI& env, Call* call) {
229 GCLock lock;
230 return eval_par(env, call->arg(0)) != constants().absent;
231}
232
233IntVal b_deopt_int(EnvI& env, Call* call) {
234 GCLock lock;
235 Expression* e = eval_par(env, call->arg(0));
236 if (e == constants().absent)
237 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
238 return eval_int(env, e);
239}
240
241bool b_deopt_bool(EnvI& env, Call* call) {
242 GCLock lock;
243 Expression* e = eval_par(env, call->arg(0));
244 if (e == constants().absent)
245 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
246 return eval_bool(env, e);
247}
248
249FloatVal b_deopt_float(EnvI& env, Call* call) {
250 GCLock lock;
251 Expression* e = eval_par(env, call->arg(0));
252 if (e == constants().absent)
253 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
254 return eval_float(env, e);
255}
256
257IntSetVal* b_deopt_intset(EnvI& env, Call* call) {
258 GCLock lock;
259 Expression* e = eval_par(env, call->arg(0));
260 if (e == constants().absent)
261 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
262 return eval_intset(env, e);
263}
264
265std::string b_deopt_string(EnvI& env, Call* call) {
266 GCLock lock;
267 Expression* e = eval_par(env, call->arg(0));
268 if (e == constants().absent)
269 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
270 return eval_string(env, e);
271}
272
273Expression* b_deopt_expr(EnvI& env, Call* call) {
274 GCLock lock;
275 Expression* e = eval_par(env, call->arg(0));
276 if (e == constants().absent)
277 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value");
278 return e;
279};
280
281IntVal b_array_lb_int(EnvI& env, Call* call) {
282 assert(call->n_args() == 1);
283 Expression* e = follow_id_to_decl(call->arg(0));
284
285 bool foundMin = false;
286 IntVal array_lb = -IntVal::infinity();
287
288 if (VarDecl* vd = e->dyn_cast<VarDecl>()) {
289 if (vd->ti()->domain()) {
290 GCLock lock;
291 IntSetVal* isv = eval_intset(env, vd->ti()->domain());
292 if (isv->size() != 0) {
293 array_lb = isv->min();
294 foundMin = true;
295 }
296 }
297 e = vd->e();
298 }
299
300 if (e != NULL) {
301 GCLock lock;
302 ArrayLit* al = eval_array_lit(env, e);
303 if (al->size() == 0) throw EvalError(env, Location(), "lower bound of empty array undefined");
304 IntVal min = IntVal::infinity();
305 for (unsigned int i = 0; i < al->size(); i++) {
306 IntBounds ib = compute_int_bounds(env, (*al)[i]);
307 if (!ib.valid) goto b_array_lb_int_done;
308 min = std::min(min, ib.l);
309 }
310 if (foundMin)
311 array_lb = std::max(array_lb, min);
312 else
313 array_lb = min;
314 foundMin = true;
315 }
316b_array_lb_int_done:
317 if (foundMin) {
318 return array_lb;
319 } else {
320 return -IntVal::infinity();
321 }
322}
323
324IntVal ub_varoptint(EnvI& env, Expression* e) {
325 IntBounds b = compute_int_bounds(env, e);
326 if (b.valid)
327 return b.u;
328 else
329 return IntVal::infinity();
330}
331IntVal b_ub_varoptint(EnvI& env, Call* call) {
332 if (call->n_args() != 1) throw EvalError(env, Location(), "dynamic type error");
333 return ub_varoptint(env, call->arg(0));
334}
335
336IntVal b_array_ub_int(EnvI& env, Call* call) {
337 assert(call->n_args() == 1);
338 Expression* e = follow_id_to_decl(call->arg(0));
339
340 bool foundMax = false;
341 IntVal array_ub = IntVal::infinity();
342
343 if (VarDecl* vd = e->dyn_cast<VarDecl>()) {
344 if (vd->ti()->domain()) {
345 GCLock lock;
346 IntSetVal* isv = eval_intset(env, vd->ti()->domain());
347 if (isv->size() != 0) {
348 array_ub = isv->max();
349 foundMax = true;
350 }
351 }
352 e = vd->e();
353 }
354
355 if (e != NULL) {
356 GCLock lock;
357 ArrayLit* al = eval_array_lit(env, e);
358 if (al->size() == 0) throw EvalError(env, Location(), "upper bound of empty array undefined");
359 IntVal max = -IntVal::infinity();
360 for (unsigned int i = 0; i < al->size(); i++) {
361 IntBounds ib = compute_int_bounds(env, (*al)[i]);
362 if (!ib.valid) goto b_array_ub_int_done;
363 max = std::max(max, ib.u);
364 }
365 if (foundMax)
366 array_ub = std::min(array_ub, max);
367 else
368 array_ub = max;
369 foundMax = true;
370 }
371b_array_ub_int_done:
372 if (foundMax) {
373 return array_ub;
374 } else {
375 return IntVal::infinity();
376 }
377}
378
379IntVal b_sum_int(EnvI& env, Call* call) {
380 assert(call->n_args() == 1);
381 GCLock lock;
382 ArrayLit* al = eval_array_lit(env, call->arg(0));
383 if (al->size() == 0) return 0;
384 IntVal m = 0;
385 for (unsigned int i = 0; i < al->size(); i++) m += eval_int(env, (*al)[i]);
386 return m;
387}
388
389IntVal b_product_int(EnvI& env, Call* call) {
390 assert(call->n_args() == 1);
391 GCLock lock;
392 ArrayLit* al = eval_array_lit(env, call->arg(0));
393 if (al->size() == 0) return 1;
394 IntVal m = 1;
395 for (unsigned int i = 0; i < al->size(); i++) m *= eval_int(env, (*al)[i]);
396 return m;
397}
398
399FloatVal b_product_float(EnvI& env, Call* call) {
400 assert(call->n_args() == 1);
401 GCLock lock;
402 ArrayLit* al = eval_array_lit(env, call->arg(0));
403 if (al->size() == 0) return 1;
404 FloatVal m = 1.0;
405 for (unsigned int i = 0; i < al->size(); i++) m *= eval_float(env, (*al)[i]);
406 return m;
407}
408
409FloatVal lb_varoptfloat(EnvI& env, Expression* e) {
410 FloatBounds b = compute_float_bounds(env, e);
411 if (b.valid)
412 return b.l;
413 else
414 throw EvalError(env, e->loc(), "cannot determine bounds");
415}
416FloatVal ub_varoptfloat(EnvI& env, Expression* e) {
417 FloatBounds b = compute_float_bounds(env, e);
418 if (b.valid)
419 return b.u;
420 else
421 throw EvalError(env, e->loc(), "cannot determine bounds");
422}
423
424FloatVal b_lb_varoptfloat(EnvI& env, Call* call) {
425 if (call->n_args() != 1) throw EvalError(env, Location(), "dynamic type error");
426 return lb_varoptfloat(env, call->arg(0));
427}
428FloatVal b_ub_varoptfloat(EnvI& env, Call* call) {
429 if (call->n_args() != 1) throw EvalError(env, Location(), "dynamic type error");
430 return ub_varoptfloat(env, call->arg(0));
431}
432
433FloatVal b_array_lb_float(EnvI& env, Call* call) {
434 assert(call->n_args() == 1);
435 Expression* e = follow_id_to_decl(call->arg(0));
436
437 bool foundMin = false;
438 FloatVal array_lb = 0.0;
439
440 if (VarDecl* vd = e->dyn_cast<VarDecl>()) {
441 if (vd->ti()->domain()) {
442 FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain());
443 array_lb = fsv->min();
444 foundMin = true;
445 }
446 e = vd->e();
447 }
448
449 if (e != NULL) {
450 GCLock lock;
451 ArrayLit* al = eval_array_lit(env, e);
452 if (al->size() == 0) throw EvalError(env, Location(), "lower bound of empty array undefined");
453 bool min_valid = false;
454 FloatVal min = 0.0;
455 for (unsigned int i = 0; i < al->size(); i++) {
456 FloatBounds fb = compute_float_bounds(env, (*al)[i]);
457 if (!fb.valid) goto b_array_lb_float_done;
458 if (min_valid) {
459 min = std::min(min, fb.l);
460 } else {
461 min_valid = true;
462 min = fb.l;
463 }
464 }
465 assert(min_valid);
466 if (foundMin)
467 array_lb = std::max(array_lb, min);
468 else
469 array_lb = min;
470 foundMin = true;
471 }
472b_array_lb_float_done:
473 if (foundMin) {
474 return array_lb;
475 } else {
476 throw EvalError(env, e->loc(), "cannot determine lower bound");
477 }
478}
479
480FloatVal b_array_ub_float(EnvI& env, Call* call) {
481 assert(call->n_args() == 1);
482 Expression* e = follow_id_to_decl(call->arg(0));
483
484 bool foundMax = false;
485 FloatVal array_ub = 0.0;
486
487 if (VarDecl* vd = e->dyn_cast<VarDecl>()) {
488 if (vd->ti()->domain()) {
489 FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain());
490 array_ub = fsv->max();
491 foundMax = true;
492 }
493 e = vd->e();
494 }
495
496 if (e != NULL) {
497 GCLock lock;
498 ArrayLit* al = eval_array_lit(env, e);
499 if (al->size() == 0) throw EvalError(env, Location(), "upper bound of empty array undefined");
500 bool max_valid = false;
501 FloatVal max = 0.0;
502 for (unsigned int i = 0; i < al->size(); i++) {
503 FloatBounds fb = compute_float_bounds(env, (*al)[i]);
504 if (!fb.valid) goto b_array_ub_float_done;
505 if (max_valid) {
506 max = std::max(max, fb.u);
507 } else {
508 max_valid = true;
509 max = fb.u;
510 }
511 }
512 assert(max_valid);
513 if (foundMax)
514 array_ub = std::min(array_ub, max);
515 else
516 array_ub = max;
517 foundMax = true;
518 }
519b_array_ub_float_done:
520 if (foundMax) {
521 return array_ub;
522 } else {
523 throw EvalError(env, e->loc(), "cannot determine upper bound");
524 }
525}
526
527FloatVal b_sum_float(EnvI& env, Call* call) {
528 assert(call->n_args() == 1);
529 GCLock lock;
530 ArrayLit* al = eval_array_lit(env, call->arg(0));
531 if (al->size() == 0) return 0;
532 FloatVal m = 0;
533 for (unsigned int i = 0; i < al->size(); i++) m += eval_float(env, (*al)[i]);
534 return m;
535}
536
537FloatVal b_float_min(EnvI& env, Call* call) {
538 switch (call->n_args()) {
539 case 1:
540 if (call->arg(0)->type().is_set()) {
541 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
542 } else {
543 GCLock lock;
544 ArrayLit* al = eval_array_lit(env, call->arg(0));
545 if (al->size() == 0) throw EvalError(env, al->loc(), "min on empty array undefined");
546 FloatVal m = eval_float(env, (*al)[0]);
547 for (unsigned int i = 1; i < al->size(); i++) m = std::min(m, eval_float(env, (*al)[i]));
548 return m;
549 }
550 case 2: {
551 return std::min(eval_float(env, call->arg(0)), eval_float(env, call->arg(1)));
552 }
553 default:
554 throw EvalError(env, Location(), "dynamic type error");
555 }
556}
557
558FloatVal b_float_max(EnvI& env, Call* call) {
559 switch (call->n_args()) {
560 case 1:
561 if (call->arg(0)->type().is_set()) {
562 throw EvalError(env, call->arg(0)->loc(), "sets not supported");
563 } else {
564 GCLock lock;
565 ArrayLit* al = eval_array_lit(env, call->arg(0));
566 if (al->size() == 0) throw EvalError(env, al->loc(), "max on empty array undefined");
567 FloatVal m = eval_float(env, (*al)[0]);
568 for (unsigned int i = 1; i < al->size(); i++) m = std::max(m, eval_float(env, (*al)[i]));
569 return m;
570 }
571 case 2: {
572 return std::max(eval_float(env, call->arg(0)), eval_float(env, call->arg(1)));
573 }
574 default:
575 throw EvalError(env, Location(), "dynamic type error");
576 }
577}
578
579IntSetVal* b_index_set(EnvI& env, Expression* e, int i) {
580 if (e->eid() != Expression::E_ID) {
581 GCLock lock;
582 ArrayLit* al = eval_array_lit(env, e);
583 if (al->dims() < i) throw EvalError(env, e->loc(), "index_set: wrong dimension");
584 return IntSetVal::a(al->min(i - 1), al->max(i - 1));
585 }
586 Id* id = e->cast<Id>();
587 if (id->decl() == NULL) throw EvalError(env, id->loc(), "undefined identifier");
588 if ((id->decl()->ti()->ranges().size() == 1 && id->decl()->ti()->ranges()[0]->domain() != NULL &&
589 id->decl()->ti()->ranges()[0]->domain()->isa<TIId>()) ||
590 (static_cast<int>(id->decl()->ti()->ranges().size()) >= i &&
591 (id->decl()->ti()->ranges()[i - 1]->domain() == NULL ||
592 id->decl()->ti()->ranges()[i - 1]->domain()->isa<TIId>()))) {
593 GCLock lock;
594 ArrayLit* al = eval_array_lit(env, id);
595 if (al->dims() < i) throw EvalError(env, id->loc(), "index_set: wrong dimension");
596 return IntSetVal::a(al->min(i - 1), al->max(i - 1));
597 }
598 if (static_cast<int>(id->decl()->ti()->ranges().size()) < i)
599 throw EvalError(env, id->loc(), "index_set: wrong dimension");
600 return eval_intset(env, id->decl()->ti()->ranges()[i - 1]->domain());
601}
602bool b_index_sets_agree(EnvI& env, Call* call) {
603 if (call->n_args() != 2)
604 throw EvalError(env, Location(), "index_sets_agree needs exactly two arguments");
605 GCLock lock;
606 ArrayLit* al0 = eval_array_lit(env, call->arg(0));
607 ArrayLit* al1 = eval_array_lit(env, call->arg(1));
608 if (al0->type().dim() != al1->type().dim()) return false;
609 for (int i = 1; i <= al0->type().dim(); i++) {
610 IntSetVal* index0 = b_index_set(env, al0, i);
611 IntSetVal* index1 = b_index_set(env, al1, i);
612 if (!index0->equal(index1)) return false;
613 }
614 return true;
615}
616IntSetVal* b_index_set1(EnvI& env, Call* call) {
617 if (call->n_args() != 1) throw EvalError(env, Location(), "index_set needs exactly one argument");
618 return b_index_set(env, call->arg(0), 1);
619}
620IntSetVal* b_index_set2(EnvI& env, Call* call) {
621 if (call->n_args() != 1) throw EvalError(env, Location(), "index_set needs exactly one argument");
622 return b_index_set(env, call->arg(0), 2);
623}
624IntSetVal* b_index_set3(EnvI& env, Call* call) {
625 if (call->n_args() != 1) throw EvalError(env, Location(), "index_set needs exactly one argument");
626 return b_index_set(env, call->arg(0), 3);
627}
628IntSetVal* b_index_set4(EnvI& env, Call* call) {
629 if (call->n_args() != 1) throw EvalError(env, Location(), "index_set needs exactly one argument");
630 return b_index_set(env, call->arg(0), 4);
631}
632IntSetVal* b_index_set5(EnvI& env, Call* call) {
633 if (call->n_args() != 1) throw EvalError(env, Location(), "index_set needs exactly one argument");
634 return b_index_set(env, call->arg(0), 5);
635}
636IntSetVal* b_index_set6(EnvI& env, Call* call) {
637 if (call->n_args() != 1) throw EvalError(env, Location(), "index_set needs exactly one argument");
638 return b_index_set(env, call->arg(0), 6);
639}
640
641IntVal b_min_parsetint(EnvI& env, Call* call) {
642 assert(call->n_args() == 1);
643 IntSetVal* isv = eval_intset(env, call->arg(0));
644 return isv->min();
645}
646IntVal b_max_parsetint(EnvI& env, Call* call) {
647 assert(call->n_args() == 1);
648 IntSetVal* isv = eval_intset(env, call->arg(0));
649 return isv->max();
650}
651IntSetVal* b_lb_set(EnvI& env, Call* e) {
652 Expression* ee = eval_par(env, e->arg(0));
653 if (ee->type().ispar()) {
654 return eval_intset(env, ee);
655 }
656 return IntSetVal::a();
657}
658IntSetVal* b_ub_set(EnvI& env, Expression* e) {
659 IntSetVal* isv = compute_intset_bounds(env, e);
660 if (isv) return isv;
661 throw EvalError(env, e->loc(), "cannot determine bounds of set expression");
662}
663IntSetVal* b_ub_set(EnvI& env, Call* call) {
664 assert(call->n_args() == 1);
665 return b_ub_set(env, call->arg(0));
666}
667bool b_has_ub_set(EnvI& env, Call* call) {
668 Expression* e = call->arg(0);
669 for (;;) {
670 switch (e->eid()) {
671 case Expression::E_SETLIT:
672 return true;
673 case Expression::E_ID: {
674 Id* id = e->cast<Id>();
675 if (id->decl() == NULL) throw EvalError(env, id->loc(), "undefined identifier");
676 if (id->decl()->e() == NULL)
677 return id->decl()->ti()->domain() != NULL;
678 else
679 e = id->decl()->e();
680 } break;
681 default:
682 throw EvalError(env, e->loc(), "invalid argument to has_ub_set");
683 }
684 }
685}
686
687IntSetVal* b_array_ub_set(EnvI& env, Call* call) {
688 assert(call->n_args() == 1);
689 GCLock lock;
690 ArrayLit* al = eval_array_lit(env, call->arg(0));
691 if (al->size() == 0) throw EvalError(env, Location(), "upper bound of empty array undefined");
692 IntSetVal* ub = b_ub_set(env, (*al)[0]);
693 for (unsigned int i = 1; i < al->size(); i++) {
694 IntSetRanges isr(ub);
695 IntSetRanges r(b_ub_set(env, (*al)[i]));
696 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
697 ub = IntSetVal::ai(u);
698 }
699 return ub;
700}
701
702IntSetVal* b_dom_varint(EnvI& env, Expression* e) {
703 Id* lastid = NULL;
704 Expression* cur = e;
705 for (;;) {
706 if (cur == NULL) {
707 if (lastid == NULL || lastid->decl()->ti()->domain() == NULL) {
708 IntBounds b = compute_int_bounds(env, e);
709 if (b.valid)
710 return IntSetVal::a(b.l, b.u);
711 else
712 return IntSetVal::a(-IntVal::infinity(), IntVal::infinity());
713 } else {
714 return eval_intset(env, lastid->decl()->ti()->domain());
715 }
716 }
717 switch (cur->eid()) {
718 case Expression::E_INTLIT: {
719 IntVal v = cur->cast<IntLit>()->v();
720 return IntSetVal::a(v, v);
721 }
722 case Expression::E_ID: {
723 lastid = cur->cast<Id>();
724 if (lastid->decl() == NULL) throw EvalError(env, lastid->loc(), "undefined identifier");
725 cur = lastid->decl()->e();
726 } break;
727 case Expression::E_ARRAYACCESS: {
728 bool success;
729 cur = eval_arrayaccess(env, cur->cast<ArrayAccess>(), success);
730 if (!success) {
731 cur = NULL;
732 }
733 } break;
734 default:
735 cur = NULL;
736 break;
737 }
738 }
739}
740IntSetVal* b_dom_varint(EnvI& env, Call* call) {
741 assert(call->n_args() == 1);
742 return b_dom_varint(env, call->arg(0));
743}
744
745IntSetVal* b_dom_bounds_array(EnvI& env, Call* call) {
746 assert(call->n_args() == 1);
747 Expression* arg_e = call->arg(0);
748 Expression* e = follow_id_to_decl(arg_e);
749
750 bool foundBounds = false;
751 IntVal array_lb = -IntVal::infinity();
752 IntVal array_ub = IntVal::infinity();
753
754 if (VarDecl* vd = e->dyn_cast<VarDecl>()) {
755 if (vd->ti()->domain()) {
756 GCLock lock;
757 IntSetVal* isv = eval_intset(env, vd->ti()->domain());
758 if (isv->size() != 0) {
759 array_lb = isv->min();
760 array_ub = isv->max();
761 foundBounds = true;
762 }
763 }
764 e = vd->e();
765 if (e == NULL) e = vd->flat()->e();
766 }
767
768 if (foundBounds) {
769 return IntSetVal::a(array_lb, array_ub);
770 }
771
772 if (e != NULL) {
773 GCLock lock;
774 ArrayLit* al = eval_array_lit(env, e);
775 if (al->size() == 0) throw EvalError(env, Location(), "lower bound of empty array undefined");
776 IntVal min = IntVal::infinity();
777 IntVal max = -IntVal::infinity();
778 for (unsigned int i = 0; i < al->size(); i++) {
779 IntBounds ib = compute_int_bounds(env, (*al)[i]);
780 if (!ib.valid) goto b_array_lb_int_done;
781 min = std::min(min, ib.l);
782 max = std::max(max, ib.u);
783 }
784 array_lb = std::max(array_lb, min);
785 array_ub = std::min(array_ub, max);
786 foundBounds = true;
787 }
788b_array_lb_int_done:
789 if (foundBounds) {
790 return IntSetVal::a(array_lb, array_ub);
791 } else {
792 throw EvalError(env, e->loc(), "cannot determine lower bound");
793 }
794}
795
796IntSetVal* b_dom_array(EnvI& env, Call* call) {
797 assert(call->n_args() == 1);
798 Expression* ae = call->arg(0);
799 ArrayLit* al = NULL;
800 while (al == NULL) {
801 switch (ae->eid()) {
802 case Expression::E_ARRAYLIT:
803 al = ae->cast<ArrayLit>();
804 break;
805 case Expression::E_ID: {
806 Id* id = ae->cast<Id>();
807 if (id->decl() == NULL) throw EvalError(env, id->loc(), "undefined identifier");
808 if (id->decl()->e() == NULL) {
809 if (id->decl()->flat() == NULL) {
810 throw EvalError(env, id->loc(), "array without initialiser");
811 } else {
812 if (id->decl()->flat()->e() == NULL) {
813 throw EvalError(env, id->loc(), "array without initialiser");
814 }
815 ae = id->decl()->flat()->e();
816 }
817 } else {
818 ae = id->decl()->e();
819 }
820 } break;
821 default:
822 throw EvalError(env, ae->loc(), "invalid argument to dom");
823 }
824 }
825 if (al->size() == 0) return IntSetVal::a();
826 IntSetVal* isv = b_dom_varint(env, (*al)[0]);
827 for (unsigned int i = 1; i < al->size(); i++) {
828 IntSetRanges isr(isv);
829 IntSetRanges r(b_dom_varint(env, (*al)[i]));
830 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
831 isv = IntSetVal::ai(u);
832 }
833 return isv;
834}
835IntSetVal* b_compute_div_bounds(EnvI& env, Call* call) {
836 assert(call->n_args() == 2);
837 IntBounds bx = compute_int_bounds(env, call->arg(0));
838 if (!bx.valid) throw EvalError(env, call->arg(0)->loc(), "cannot determine bounds");
839 /// TODO: better bounds if only some input bounds are infinite
840 if (!bx.l.isFinite() || !bx.u.isFinite()) return constants().infinity->isv();
841 IntBounds by = compute_int_bounds(env, call->arg(1));
842 if (!by.valid) throw EvalError(env, call->arg(1)->loc(), "cannot determine bounds");
843 if (!by.l.isFinite() || !by.u.isFinite()) return constants().infinity->isv();
844 Ranges::Const<IntVal> byr(by.l, by.u);
845 Ranges::Const<IntVal> by0(0, 0);
846 Ranges::Diff<IntVal, Ranges::Const<IntVal>, Ranges::Const<IntVal>> byr0(byr, by0);
847
848 IntVal min = IntVal::maxint();
849 IntVal max = IntVal::minint();
850 if (byr0()) {
851 min = std::min(min, bx.l / byr0.min());
852 min = std::min(min, bx.l / byr0.max());
853 min = std::min(min, bx.u / byr0.min());
854 min = std::min(min, bx.u / byr0.max());
855 max = std::max(max, bx.l / byr0.min());
856 max = std::max(max, bx.l / byr0.max());
857 max = std::max(max, bx.u / byr0.min());
858 max = std::max(max, bx.u / byr0.max());
859 ++byr0;
860 if (byr0()) {
861 min = std::min(min, bx.l / byr0.min());
862 min = std::min(min, bx.l / byr0.max());
863 min = std::min(min, bx.u / byr0.min());
864 min = std::min(min, bx.u / byr0.max());
865 max = std::max(max, bx.l / byr0.min());
866 max = std::max(max, bx.l / byr0.max());
867 max = std::max(max, bx.u / byr0.min());
868 max = std::max(max, bx.u / byr0.max());
869 }
870 }
871 return IntSetVal::a(min, max);
872}
873
874ArrayLit* b_arrayXd(EnvI& env, Call* call, int d) {
875 GCLock lock;
876 ArrayLit* al = eval_array_lit(env, call->arg(d));
877 std::vector<std::pair<int, int>> dims(d);
878 unsigned int dim1d = 1;
879 for (int i = 0; i < d; i++) {
880 IntSetVal* di = eval_intset(env, call->arg(i));
881 if (di->size() == 0) {
882 dims[i] = std::pair<int, int>(1, 0);
883 dim1d = 0;
884 } else if (di->size() != 1) {
885 throw EvalError(env, call->arg(i)->loc(), "arrayXd only defined for ranges");
886 } else {
887 dims[i] = std::pair<int, int>(static_cast<int>(di->min(0).toInt()),
888 static_cast<int>(di->max(0).toInt()));
889 dim1d *= dims[i].second - dims[i].first + 1;
890 }
891 }
892 if (dim1d != al->size()) throw EvalError(env, al->loc(), "mismatch in array dimensions");
893 ArrayLit* ret = new ArrayLit(al->loc(), *al, dims);
894 Type t = al->type();
895 t.dim(d);
896 ret->type(t);
897 ret->flat(al->flat());
898 return ret;
899}
900Expression* b_array1d_list(EnvI& env, Call* call) {
901 GCLock lock;
902 ArrayLit* al = eval_array_lit(env, call->arg(0));
903 if (al->dims() == 1 && al->min(0) == 1) {
904 return call->arg(0)->isa<Id>() ? call->arg(0) : al;
905 }
906 ArrayLit* ret = new ArrayLit(al->loc(), *al);
907 Type t = al->type();
908 t.dim(1);
909 ret->type(t);
910 ret->flat(al->flat());
911 return ret;
912}
913Expression* b_array1d(EnvI& env, Call* call) { return b_arrayXd(env, call, 1); }
914Expression* b_array2d(EnvI& env, Call* call) { return b_arrayXd(env, call, 2); }
915Expression* b_array3d(EnvI& env, Call* call) { return b_arrayXd(env, call, 3); }
916Expression* b_array4d(EnvI& env, Call* call) { return b_arrayXd(env, call, 4); }
917Expression* b_array5d(EnvI& env, Call* call) { return b_arrayXd(env, call, 5); }
918Expression* b_array6d(EnvI& env, Call* call) { return b_arrayXd(env, call, 6); }
919
920Expression* b_arrayXd(EnvI& env, Call* call) {
921 GCLock lock;
922 ArrayLit* al0 = eval_array_lit(env, call->arg(0));
923 ArrayLit* al1 = eval_array_lit(env, call->arg(1));
924 if (al0->dims() == al1->dims()) {
925 bool sameDims = true;
926 for (unsigned int i = al0->dims(); i--;) {
927 if (al0->min(i) != al1->min(i) || al0->max(i) != al1->max(i)) {
928 sameDims = false;
929 break;
930 }
931 }
932 if (sameDims) return call->arg(1)->isa<Id>() ? call->arg(1) : al1;
933 }
934 std::vector<std::pair<int, int>> dims(al0->dims());
935 for (unsigned int i = al0->dims(); i--;) {
936 dims[i] = std::make_pair(al0->min(i), al0->max(i));
937 }
938 ArrayLit* ret = new ArrayLit(al1->loc(), *al1, dims);
939 Type t = al1->type();
940 t.dim(static_cast<int>(dims.size()));
941 ret->type(t);
942 ret->flat(al1->flat());
943 return ret;
944}
945
946IntVal b_length(EnvI& env, Call* call) {
947 GCLock lock;
948 ArrayLit* al = eval_array_lit(env, call->arg(0));
949 return al->size();
950}
951
952IntVal b_bool2int(EnvI& env, Call* call) { return eval_bool(env, call->arg(0)) ? 1 : 0; }
953
954bool b_forall_par(EnvI& env, Call* call) {
955 if (call->n_args() != 1) throw EvalError(env, Location(), "forall needs exactly one argument");
956 GCLock lock;
957 ArrayLit* al = eval_array_lit(env, call->arg(0));
958 for (unsigned int i = al->size(); i--;)
959 if (!eval_bool(env, (*al)[i])) return false;
960 return true;
961}
962bool b_exists_par(EnvI& env, Call* call) {
963 if (call->n_args() != 1) throw EvalError(env, Location(), "exists needs exactly one argument");
964 GCLock lock;
965 ArrayLit* al = eval_array_lit(env, call->arg(0));
966 for (unsigned int i = al->size(); i--;)
967 if (eval_bool(env, (*al)[i])) return true;
968 return false;
969}
970bool b_clause_par(EnvI& env, Call* call) {
971 if (call->n_args() != 2) throw EvalError(env, Location(), "clause needs exactly two arguments");
972 GCLock lock;
973 ArrayLit* al = eval_array_lit(env, call->arg(0));
974 for (unsigned int i = al->size(); i--;)
975 if (eval_bool(env, (*al)[i])) return true;
976 al = eval_array_lit(env, call->arg(1));
977 for (unsigned int i = al->size(); i--;)
978 if (!eval_bool(env, (*al)[i])) return true;
979 return false;
980}
981bool b_xorall_par(EnvI& env, Call* call) {
982 if (call->n_args() != 1) throw EvalError(env, Location(), "xorall needs exactly one argument");
983 GCLock lock;
984 int count = 0;
985 ArrayLit* al = eval_array_lit(env, call->arg(0));
986 for (unsigned int i = al->size(); i--;) count += eval_bool(env, (*al)[i]);
987 return count % 2 == 1;
988}
989bool b_iffall_par(EnvI& env, Call* call) {
990 if (call->n_args() != 1) throw EvalError(env, Location(), "xorall needs exactly one argument");
991 GCLock lock;
992 int count = 0;
993 ArrayLit* al = eval_array_lit(env, call->arg(0));
994 for (unsigned int i = al->size(); i--;) count += eval_bool(env, (*al)[i]);
995 return count % 2 == 0;
996}
997
998IntVal b_card(EnvI& env, Call* call) {
999 if (call->n_args() != 1) throw EvalError(env, Location(), "card needs exactly one argument");
1000 IntSetVal* isv = eval_intset(env, call->arg(0));
1001 IntSetRanges isr(isv);
1002 return Ranges::cardinality(isr);
1003}
1004
1005Expression* exp_is_fixed(EnvI& env, Expression* e) {
1006 GCLock lock;
1007 Expression* cur = eval_par(env, e);
1008 for (;;) {
1009 if (cur == NULL) return NULL;
1010 if (cur->type().ispar()) return cur;
1011 switch (cur->eid()) {
1012 case Expression::E_ID:
1013 cur = cur->cast<Id>()->decl();
1014 break;
1015 case Expression::E_VARDECL:
1016 if (cur->type().st() != Type::ST_SET) {
1017 Expression* dom = cur->cast<VarDecl>()->ti()->domain();
1018 if (dom && (dom->isa<IntLit>() || dom->isa<BoolLit>() || dom->isa<FloatLit>()))
1019 return dom;
1020 }
1021 cur = cur->cast<VarDecl>()->e();
1022 break;
1023 default:
1024 return NULL;
1025 }
1026 }
1027}
1028
1029bool b_is_fixed(EnvI& env, Call* call) {
1030 assert(call->n_args() == 1);
1031 return exp_is_fixed(env, call->arg(0)) != NULL;
1032}
1033
1034bool b_is_fixed_array(EnvI& env, Call* call) {
1035 assert(call->n_args() == 1);
1036 GCLock lock;
1037 ArrayLit* al = eval_array_lit(env, call->arg(0));
1038 if (al->size() == 0) return true;
1039 for (unsigned int i = 0; i < al->size(); i++) {
1040 if (exp_is_fixed(env, (*al)[i]) == NULL) return false;
1041 }
1042 return true;
1043}
1044
1045Expression* b_fix(EnvI& env, Call* call) {
1046 assert(call->n_args() == 1);
1047 Expression* ret = exp_is_fixed(env, call->arg(0));
1048 if (ret == NULL) throw EvalError(env, call->arg(0)->loc(), "expression is not fixed");
1049 return ret;
1050}
1051
1052IntVal b_fix_int(EnvI& env, Call* call) { return eval_int(env, b_fix(env, call)); }
1053bool b_fix_bool(EnvI& env, Call* call) { return eval_bool(env, b_fix(env, call)); }
1054FloatVal b_fix_float(EnvI& env, Call* call) { return eval_float(env, b_fix(env, call)); }
1055IntSetVal* b_fix_set(EnvI& env, Call* call) { return eval_intset(env, b_fix(env, call)); }
1056
1057Expression* b_fix_array(EnvI& env, Call* call) {
1058 assert(call->n_args() == 1);
1059 GCLock lock;
1060 ArrayLit* al = eval_array_lit(env, call->arg(0));
1061 std::vector<Expression*> fixed(al->size());
1062 for (unsigned int i = 0; i < fixed.size(); i++) {
1063 fixed[i] = exp_is_fixed(env, (*al)[i]);
1064 if (fixed[i] == NULL) throw EvalError(env, (*al)[i]->loc(), "expression is not fixed");
1065 }
1066 ArrayLit* ret = new ArrayLit(Location(), fixed);
1067 Type tt = al->type();
1068 tt.ti(Type::TI_PAR);
1069 ret->type(tt);
1070 return ret;
1071}
1072
1073FloatVal b_int2float(EnvI& env, Call* call) { return eval_int(env, call->arg(0)); }
1074IntVal b_ceil(EnvI& env, Call* call) {
1075 return static_cast<IntVal>(std::ceil(eval_float(env, call->arg(0))));
1076}
1077IntVal b_floor(EnvI& env, Call* call) {
1078 return static_cast<IntVal>(std::floor(eval_float(env, call->arg(0))));
1079}
1080IntVal b_round(EnvI& env, Call* call) {
1081 FloatVal v(eval_float(env, call->arg(0)));
1082 return v < 0 ? static_cast<IntVal>(v - 0.5) : static_cast<IntVal>(v + 0.5);
1083 // return static_cast<IntVal>(eval_float(env,call->arg(0))+0.5);
1084}
1085FloatVal b_log10(EnvI& env, Call* call) {
1086 return std::log10(eval_float(env, call->arg(0)).toDouble());
1087}
1088FloatVal b_log2(EnvI& env, Call* call) {
1089 return std::log(eval_float(env, call->arg(0)).toDouble()) / std::log(2.0);
1090}
1091FloatVal b_ln(EnvI& env, Call* call) { return std::log(eval_float(env, call->arg(0)).toDouble()); }
1092FloatVal b_log(EnvI& env, Call* call) {
1093 return std::log(eval_float(env, call->arg(1)).toDouble()) /
1094 std::log(eval_float(env, call->arg(0)).toDouble());
1095}
1096FloatVal b_exp(EnvI& env, Call* call) { return std::exp(eval_float(env, call->arg(0)).toDouble()); }
1097FloatVal b_pow(EnvI& env, Call* call) {
1098 return std::pow(eval_float(env, call->arg(0)).toDouble(),
1099 eval_float(env, call->arg(1)).toDouble());
1100}
1101IntVal b_pow_int(EnvI& env, Call* call) {
1102 IntVal p = eval_int(env, call->arg(0));
1103 IntVal r = 1;
1104 long long int e = eval_int(env, call->arg(1)).toInt();
1105 if (e < 0) throw EvalError(env, call->arg(1)->loc(), "Cannot raise integer to a negative power");
1106 for (long long int i = e; i--;) r = r * p;
1107 return r;
1108}
1109FloatVal b_sqrt(EnvI& env, Call* call) {
1110 return std::sqrt(eval_float(env, call->arg(0)).toDouble());
1111}
1112
1113bool b_assert_bool(EnvI& env, Call* call) {
1114 assert(call->n_args() == 2);
1115 GCLock lock;
1116 if (eval_bool(env, call->arg(0))) return true;
1117 StringLit* err = eval_par(env, call->arg(1))->cast<StringLit>();
1118 throw EvalError(env, call->arg(0)->loc(), "Assertion failed: " + err->v().str());
1119}
1120
1121Expression* b_assert(EnvI& env, Call* call) {
1122 assert(call->n_args() == 3);
1123 GCLock lock;
1124 if (eval_bool(env, call->arg(0))) return call->arg(2);
1125 StringLit* err = eval_par(env, call->arg(1))->cast<StringLit>();
1126 throw EvalError(env, call->arg(0)->loc(), "Assertion failed: " + err->v().str());
1127}
1128
1129bool b_abort(EnvI& env, Call* call) {
1130 GCLock lock;
1131 StringLit* err = eval_par(env, call->arg(0))->cast<StringLit>();
1132 throw EvalError(env, call->arg(0)->loc(), "Abort: " + err->v().str());
1133}
1134
1135Expression* b_trace(EnvI& env, Call* call) {
1136 GCLock lock;
1137 StringLit* msg = eval_par(env, call->arg(0))->cast<StringLit>();
1138 env.errstream << msg->v();
1139 return call->n_args() == 1 ? constants().lit_true : call->arg(1);
1140}
1141
1142Expression* b_trace_stdout(EnvI& env, Call* call) {
1143 GCLock lock;
1144 StringLit* msg = eval_par(env, call->arg(0))->cast<StringLit>();
1145 env.outstream << msg->v();
1146 return call->n_args() == 1 ? constants().lit_true : call->arg(1);
1147}
1148
1149bool b_in_redundant_constraint(EnvI& env, Call*) { return env.in_redundant_constraint > 0; }
1150
1151Expression* b_set2array(EnvI& env, Call* call) {
1152 assert(call->n_args() == 1);
1153 GCLock lock;
1154 IntSetVal* isv = eval_intset(env, call->arg(0));
1155 std::vector<Expression*> elems;
1156 IntSetRanges isr(isv);
1157 for (Ranges::ToValues<IntSetRanges> isr_v(isr); isr_v(); ++isr_v)
1158 elems.push_back(IntLit::a(isr_v.val()));
1159 ArrayLit* al = new ArrayLit(call->arg(0)->loc(), elems);
1160 al->type(Type::parint(1));
1161 return al;
1162}
1163
1164IntVal b_string_length(EnvI& env, Call* call) {
1165 GCLock lock;
1166 std::string s = eval_string(env, call->arg(0));
1167 return s.size();
1168}
1169
1170std::string show(EnvI& env, Expression* exp) {
1171 std::ostringstream oss;
1172 GCLock lock;
1173 Printer p(oss, 0, false);
1174 Expression* e = eval_par(env, exp);
1175 if (e->type().isvar()) {
1176 p.print(e);
1177 } else {
1178 e = eval_par(env, e);
1179 if (ArrayLit* al = e->dyn_cast<ArrayLit>()) {
1180 oss << "[";
1181 for (unsigned int i = 0; i < al->size(); i++) {
1182 p.print((*al)[i]);
1183 if (i < al->size() - 1) oss << ", ";
1184 }
1185 oss << "]";
1186 } else {
1187 p.print(e);
1188 }
1189 }
1190 return oss.str();
1191}
1192std::string b_show(EnvI& env, Call* call) { return show(env, call->arg(0)); }
1193std::string b_showDznId(EnvI& env, Call* call) {
1194 GCLock lock;
1195 std::string s = eval_string(env, call->arg(0));
1196 size_t nonIdChar =
1197 s.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
1198 size_t nonIdBegin = s.find_first_of("0123456789_");
1199 if (nonIdChar != std::string::npos || nonIdBegin == 0) {
1200 s = "'" + s + "'";
1201 }
1202 return s;
1203}
1204
1205std::string b_show_json_basic(EnvI& env, Expression* e) {
1206 std::ostringstream oss;
1207 Printer p(oss, 0, false);
1208 if (SetLit* sl = e->dyn_cast<SetLit>()) {
1209 oss << "{ \"set\" : [";
1210 if (IntSetVal* isv = sl->isv()) {
1211 bool first = true;
1212 for (IntSetRanges isr(isv); isr(); ++isr) {
1213 if (first) {
1214 first = false;
1215 } else {
1216 oss << ",";
1217 }
1218 if (isr.min() == isr.max()) {
1219 oss << isr.min();
1220 } else {
1221 oss << "[" << isr.min() << "," << isr.max() << "]";
1222 }
1223 }
1224 } else if (FloatSetVal* fsv = sl->fsv()) {
1225 bool first = true;
1226 for (FloatSetRanges fsr(fsv); fsr(); ++fsr) {
1227 if (first) {
1228 first = false;
1229 } else {
1230 oss << ",";
1231 }
1232 if (fsr.min() == fsr.max()) {
1233 ppFloatVal(oss, fsr.min());
1234 } else {
1235 oss << "[";
1236 ppFloatVal(oss, fsr.min());
1237 oss << ",";
1238 ppFloatVal(oss, fsr.max());
1239 oss << "]";
1240 }
1241 }
1242 } else {
1243 for (unsigned int i = 0; i < sl->v().size(); i++) {
1244 p.print(sl->v()[i]);
1245 if (i < sl->v().size() - 1) oss << ",";
1246 }
1247 }
1248 oss << "]}";
1249 } else if (e == constants().absent) {
1250 oss << "null";
1251 } else {
1252 p.print(e);
1253 }
1254 return oss.str();
1255}
1256
1257std::string b_show_json(EnvI& env, Call* call) {
1258 Expression* exp = call->arg(0);
1259 GCLock lock;
1260 Expression* e = eval_par(env, exp);
1261 if (e->type().isvar()) {
1262 std::ostringstream oss;
1263 Printer p(oss, 0, false);
1264 p.print(e);
1265 return oss.str();
1266 } else {
1267 if (ArrayLit* al = e->dyn_cast<ArrayLit>()) {
1268 std::vector<unsigned int> dims(al->dims() - 1);
1269 if (dims.size() != 0) {
1270 dims[0] = al->max(al->dims() - 1) - al->min(al->dims() - 1) + 1;
1271 }
1272
1273 for (int i = 1; i < al->dims() - 1; i++) {
1274 dims[i] = dims[i - 1] * (al->max(al->dims() - 1 - i) - al->min(al->dims() - 1 - i) + 1);
1275 }
1276
1277 std::ostringstream oss;
1278 oss << "[";
1279 for (unsigned int i = 0; i < al->size(); i++) {
1280 for (unsigned int j = 0; j < dims.size(); j++) {
1281 if (i % dims[j] == 0) {
1282 oss << "[";
1283 }
1284 }
1285 oss << b_show_json_basic(env, (*al)[i]);
1286 for (unsigned int j = 0; j < dims.size(); j++) {
1287 if (i % dims[j] == dims[j] - 1) {
1288 oss << "]";
1289 }
1290 }
1291
1292 if (i < al->size() - 1) oss << ", ";
1293 }
1294 oss << "]";
1295
1296 return oss.str();
1297 } else {
1298 return b_show_json_basic(env, e);
1299 }
1300 }
1301}
1302
1303Expression* b_outputJSON(EnvI& env, Call* call) { return createJSONOutput(env, false, false); }
1304Expression* b_outputJSONParameters(EnvI& env, Call* call) {
1305 std::vector<Expression*> outputVars;
1306 outputVars.push_back(new StringLit(Location().introduce(), "{\n"));
1307
1308 class JSONParVisitor : public ItemVisitor {
1309 protected:
1310 EnvI& e;
1311 std::vector<Expression*>& outputVars;
1312 bool first_var;
1313
1314 public:
1315 JSONParVisitor(EnvI& e0, std::vector<Expression*>& outputVars0)
1316 : e(e0), outputVars(outputVars0), first_var(true) {}
1317 void vVarDeclI(VarDeclI* vdi) {
1318 VarDecl* vd = vdi->e();
1319 if (vd->ann().contains(constants().ann.rhs_from_assignment)) {
1320 std::ostringstream s;
1321 if (first_var) {
1322 first_var = false;
1323 } else {
1324 s << ",\n";
1325 }
1326 s << " \"" << vd->id()->str().str() << "\""
1327 << " : ";
1328 StringLit* sl = new StringLit(Location().introduce(), s.str());
1329 outputVars.push_back(sl);
1330
1331 std::vector<Expression*> showArgs(1);
1332 showArgs[0] = vd->id();
1333 Call* show = new Call(Location().introduce(), "showJSON", showArgs);
1334 show->type(Type::parstring());
1335 FunctionI* fi = e.model->matchFn(e, show, false);
1336 assert(fi);
1337 show->decl(fi);
1338 outputVars.push_back(show);
1339 }
1340 }
1341 } jsonov(env, outputVars);
1342
1343 iterItems(jsonov, env.model);
1344 outputVars.push_back(new StringLit(Location().introduce(), "\n}\n"));
1345 return new ArrayLit(Location().introduce(), outputVars);
1346}
1347
1348std::string b_format(EnvI& env, Call* call) {
1349 int width = 0;
1350 int prec = -1;
1351 GCLock lock;
1352 Expression* e;
1353 if (call->n_args() > 1) {
1354 width = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1355 if (call->n_args() == 2) {
1356 e = eval_par(env, call->arg(1));
1357 } else {
1358 assert(call->n_args() == 3);
1359 prec = static_cast<int>(eval_int(env, call->arg(1)).toInt());
1360 if (prec < 0)
1361 throw EvalError(env, call->arg(1)->loc(), "output precision cannot be negative");
1362 e = eval_par(env, call->arg(2));
1363 }
1364 } else {
1365 e = eval_par(env, call->arg(0));
1366 }
1367 if (e->type() == Type::parint()) {
1368 long long int i = eval_int(env, e).toInt();
1369 std::ostringstream formatted;
1370 if (width > 0) {
1371 formatted.width(width);
1372 } else if (width < 0) {
1373 formatted.width(-width);
1374 formatted.flags(std::ios::left);
1375 }
1376 if (prec != -1) formatted.precision(prec);
1377 formatted << i;
1378 return formatted.str();
1379 } else if (e->type() == Type::parfloat()) {
1380 FloatVal i = eval_float(env, e);
1381 std::ostringstream formatted;
1382 if (width > 0) {
1383 formatted.width(width);
1384 } else if (width < 0) {
1385 formatted.width(-width);
1386 formatted.flags(std::ios::left);
1387 }
1388 formatted.setf(std::ios::fixed);
1389 formatted.precision(std::numeric_limits<double>::digits10 + 2);
1390 if (prec != -1) formatted.precision(prec);
1391 formatted << i;
1392 return formatted.str();
1393 } else {
1394 std::string s = show(env, e);
1395 if (prec >= 0 && prec < s.size()) s = s.substr(0, prec);
1396 std::ostringstream oss;
1397 if (s.size() < std::abs(width)) {
1398 int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size()));
1399 if (addLeft < 0) addLeft = 0;
1400 int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0;
1401 if (addRight < 0) addRight = 0;
1402 for (int i = addLeft; i--;) oss << " ";
1403 oss << s;
1404 for (int i = addRight; i--;) oss << " ";
1405 return oss.str();
1406 } else {
1407 return s;
1408 }
1409 }
1410}
1411
1412std::string b_format_justify_string(EnvI& env, Call* call) {
1413 int width = 0;
1414 GCLock lock;
1415 Expression* e;
1416 width = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1417 e = eval_par(env, call->arg(1));
1418 std::string s = eval_string(env, e);
1419 std::ostringstream oss;
1420 if (s.size() < std::abs(width)) {
1421 int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size()));
1422 if (addLeft < 0) addLeft = 0;
1423 int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0;
1424 if (addRight < 0) addRight = 0;
1425 for (int i = addLeft; i--;) oss << " ";
1426 oss << s;
1427 for (int i = addRight; i--;) oss << " ";
1428 return oss.str();
1429 } else {
1430 return s;
1431 }
1432}
1433
1434std::string b_show_int(EnvI& env, Call* call) {
1435 assert(call->n_args() == 2);
1436 GCLock lock;
1437 Expression* e = eval_par(env, call->arg(1));
1438 std::ostringstream oss;
1439 if (IntLit* iv = e->dyn_cast<IntLit>()) {
1440 int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1441 std::ostringstream oss_length;
1442 oss_length << iv->v();
1443 int iv_length = static_cast<int>(oss_length.str().size());
1444 int addLeft = justify < 0 ? 0 : (justify - iv_length);
1445 if (addLeft < 0) addLeft = 0;
1446 int addRight = justify < 0 ? (-justify - iv_length) : 0;
1447 if (addRight < 0) addRight = 0;
1448 for (int i = addLeft; i--;) oss << " ";
1449 oss << iv->v();
1450 for (int i = addRight; i--;) oss << " ";
1451 } else {
1452 Printer p(oss, 0, false);
1453 p.print(e);
1454 }
1455 return oss.str();
1456}
1457
1458std::string b_show_float(EnvI& env, Call* call) {
1459 assert(call->n_args() == 3);
1460 GCLock lock;
1461 Expression* e = eval_par(env, call->arg(2));
1462 std::ostringstream oss;
1463 if (FloatLit* fv = e->dyn_cast<FloatLit>()) {
1464 int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt());
1465 int prec = static_cast<int>(eval_int(env, call->arg(1)).toInt());
1466 if (prec < 0)
1467 throw EvalError(env, call->arg(1)->loc(),
1468 "number of digits in show_float cannot be negative");
1469 std::ostringstream oss_length;
1470 oss_length << std::setprecision(prec) << std::fixed << fv->v();
1471 int fv_length = static_cast<int>(oss_length.str().size());
1472 int addLeft = justify < 0 ? 0 : (justify - fv_length);
1473 if (addLeft < 0) addLeft = 0;
1474 int addRight = justify < 0 ? (-justify - fv_length) : 0;
1475 if (addRight < 0) addRight = 0;
1476 for (int i = addLeft; i--;) oss << " ";
1477 oss << std::setprecision(prec) << std::fixed << fv->v();
1478 for (int i = addRight; i--;) oss << " ";
1479 } else {
1480 Printer p(oss, 0, false);
1481 p.print(e);
1482 }
1483 return oss.str();
1484}
1485
1486std::string b_file_path(EnvI&, Call* call) {
1487 return FileUtils::file_path(call->loc().filename().str());
1488}
1489
1490std::string b_concat(EnvI& env, Call* call) {
1491 assert(call->n_args() == 1);
1492 GCLock lock;
1493 ArrayLit* al = eval_array_lit(env, call->arg(0));
1494 std::ostringstream oss;
1495 for (unsigned int i = 0; i < al->size(); i++) {
1496 oss << eval_string(env, (*al)[i]);
1497 }
1498 return oss.str();
1499}
1500
1501std::string b_join(EnvI& env, Call* call) {
1502 assert(call->n_args() == 2);
1503 std::string sep = eval_string(env, call->arg(0));
1504 GCLock lock;
1505 ArrayLit* al = eval_array_lit(env, call->arg(1));
1506 std::ostringstream oss;
1507 for (unsigned int i = 0; i < al->size(); i++) {
1508 oss << eval_string(env, (*al)[i]);
1509 if (i < al->size() - 1) oss << sep;
1510 }
1511 return oss.str();
1512}
1513
1514IntSetVal* b_array_union(EnvI& env, Call* call) {
1515 assert(call->n_args() == 1);
1516 ArrayLit* al = eval_array_lit(env, call->arg(0));
1517 if (al->size() == 0) return IntSetVal::a();
1518 IntSetVal* isv = eval_intset(env, (*al)[0]);
1519 for (unsigned int i = 0; i < al->size(); i++) {
1520 IntSetRanges i0(isv);
1521 IntSetRanges i1(eval_intset(env, (*al)[i]));
1522 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(i0, i1);
1523 isv = IntSetVal::ai(u);
1524 }
1525 return isv;
1526}
1527
1528IntSetVal* b_array_intersect(EnvI& env, Call* call) {
1529 assert(call->n_args() == 1);
1530 ArrayLit* al = eval_array_lit(env, call->arg(0));
1531 std::vector<IntSetVal::Range> ranges;
1532 if (al->size() > 0) {
1533 IntSetVal* i0 = eval_intset(env, (*al)[0]);
1534 if (i0->size() > 0) {
1535 IntSetRanges i0r(i0);
1536 IntVal min = i0r.min();
1537 while (i0r()) {
1538 // Initialize with last interval
1539 IntVal max = i0r.max();
1540 // Intersect with all other intervals
1541 restart:
1542 for (int j = al->size(); j--;) {
1543 IntSetRanges ij(eval_intset(env, (*al)[j]));
1544 // Skip intervals that are too small
1545 while (ij() && (ij.max() < min)) ++ij;
1546 if (!ij()) goto done;
1547 if (ij.min() > max) {
1548 min = ij.min();
1549 max = ij.max();
1550 goto restart;
1551 }
1552 // Now the intervals overlap
1553 if (min < ij.min()) min = ij.min();
1554 if (max > ij.max()) max = ij.max();
1555 }
1556 ranges.push_back(IntSetVal::Range(min, max));
1557 // The next interval must be at least two elements away
1558 min = max + 2;
1559 }
1560 done:
1561 return IntSetVal::a(ranges);
1562 } else {
1563 return IntSetVal::a();
1564 }
1565 } else {
1566 return IntSetVal::a();
1567 }
1568}
1569
1570Expression* b_sort_by_int(EnvI& env, Call* call) {
1571 assert(call->n_args() == 2);
1572 ArrayLit* al = eval_array_lit(env, call->arg(0));
1573 ArrayLit* order_e = eval_array_lit(env, call->arg(1));
1574 std::vector<IntVal> order(order_e->size());
1575 std::vector<int> a(order_e->size());
1576 for (unsigned int i = 0; i < order.size(); i++) {
1577 a[i] = i;
1578 order[i] = eval_int(env, (*order_e)[i]);
1579 }
1580 struct Ord {
1581 std::vector<IntVal>& order;
1582 Ord(std::vector<IntVal>& order0) : order(order0) {}
1583 bool operator()(int i, int j) { return order[i] < order[j]; }
1584 } _ord(order);
1585 std::stable_sort(a.begin(), a.end(), _ord);
1586 std::vector<Expression*> sorted(a.size());
1587 for (unsigned int i = static_cast<unsigned int>(sorted.size()); i--;) sorted[i] = (*al)[a[i]];
1588 ArrayLit* al_sorted = new ArrayLit(al->loc(), sorted);
1589 al_sorted->type(al->type());
1590 return al_sorted;
1591}
1592
1593Expression* b_sort_by_float(EnvI& env, Call* call) {
1594 assert(call->n_args() == 2);
1595 ArrayLit* al = eval_array_lit(env, call->arg(0));
1596 ArrayLit* order_e = eval_array_lit(env, call->arg(1));
1597 std::vector<FloatVal> order(order_e->size());
1598 std::vector<int> a(order_e->size());
1599 for (unsigned int i = 0; i < order.size(); i++) {
1600 a[i] = i;
1601 order[i] = eval_float(env, (*order_e)[i]);
1602 }
1603 struct Ord {
1604 std::vector<FloatVal>& order;
1605 Ord(std::vector<FloatVal>& order0) : order(order0) {}
1606 bool operator()(int i, int j) { return order[i] < order[j]; }
1607 } _ord(order);
1608 std::stable_sort(a.begin(), a.end(), _ord);
1609 std::vector<Expression*> sorted(a.size());
1610 for (unsigned int i = static_cast<unsigned int>(sorted.size()); i--;) sorted[i] = (*al)[a[i]];
1611 ArrayLit* al_sorted = new ArrayLit(al->loc(), sorted);
1612 al_sorted->type(al->type());
1613 return al_sorted;
1614}
1615
1616Expression* b_sort(EnvI& env, Call* call) {
1617 assert(call->n_args() == 1);
1618 ArrayLit* al = eval_array_lit(env, call->arg(0));
1619 std::vector<Expression*> sorted(al->size());
1620 for (unsigned int i = static_cast<unsigned int>(sorted.size()); i--;) sorted[i] = (*al)[i];
1621 struct Ord {
1622 EnvI& env;
1623 Ord(EnvI& env0) : env(env0) {}
1624 bool operator()(Expression* e0, Expression* e1) {
1625 switch (e0->type().bt()) {
1626 case Type::BT_INT:
1627 return eval_int(env, e0) < eval_int(env, e1);
1628 case Type::BT_BOOL:
1629 return eval_bool(env, e0) < eval_bool(env, e1);
1630 case Type::BT_FLOAT:
1631 return eval_float(env, e0) < eval_float(env, e1);
1632 default:
1633 throw EvalError(env, e0->loc(), "unsupported type for sorting");
1634 }
1635 }
1636 } _ord(env);
1637 std::sort(sorted.begin(), sorted.end(), _ord);
1638 ArrayLit* al_sorted = new ArrayLit(al->loc(), sorted);
1639 al_sorted->type(al->type());
1640 return al_sorted;
1641}
1642
1643std::default_random_engine& rnd_generator(void) {
1644 // TODO: initiate with seed if given as annotation/in command line
1645 static std::default_random_engine g;
1646 return g;
1647}
1648
1649FloatVal b_normal_float_float(EnvI& env, Call* call) {
1650 assert(call->n_args() == 2);
1651 const double mean = eval_float(env, call->arg(0)).toDouble();
1652 const double stdv = eval_float(env, call->arg(1)).toDouble();
1653 std::normal_distribution<double> distribution(mean, stdv);
1654 // return a sample from the distribution
1655 return distribution(rnd_generator());
1656}
1657
1658FloatVal b_normal_int_float(EnvI& env, Call* call) {
1659 assert(call->n_args() == 2);
1660 const double mean = double(eval_int(env, call->arg(0)).toInt());
1661 const double stdv = eval_float(env, call->arg(1)).toDouble();
1662 std::normal_distribution<double> distribution(mean, stdv);
1663 // return a sample from the distribution
1664 return distribution(rnd_generator());
1665}
1666
1667FloatVal b_uniform_float(EnvI& env, Call* call) {
1668 assert(call->n_args() == 2);
1669 const double lb = eval_float(env, call->arg(0)).toDouble();
1670 const double ub = eval_float(env, call->arg(1)).toDouble();
1671 if (lb > ub) {
1672 std::stringstream ssm;
1673 ssm << "lowerbound of uniform distribution \"" << lb
1674 << "\" is higher than its upperbound: " << ub;
1675 throw EvalError(env, call->arg(0)->loc(), ssm.str());
1676 }
1677 std::uniform_real_distribution<double> distribution(lb, ub);
1678 // return a sample from the distribution
1679 return distribution(rnd_generator());
1680}
1681
1682IntVal b_uniform_int(EnvI& env, Call* call) {
1683 assert(call->n_args() == 2);
1684 const long long int lb = eval_int(env, call->arg(0)).toInt();
1685 const long long int ub = eval_int(env, call->arg(1)).toInt();
1686 if (lb > ub) {
1687 std::stringstream ssm;
1688 ssm << "lowerbound of uniform distribution \"" << lb
1689 << "\" is higher than its upperbound: " << ub;
1690 throw EvalError(env, call->arg(0)->loc(), ssm.str());
1691 }
1692 std::uniform_int_distribution<long long int> distribution(lb, ub);
1693 // return a sample from the distribution
1694 return IntVal(distribution(rnd_generator()));
1695}
1696
1697IntVal b_poisson_int(EnvI& env, Call* call) {
1698 assert(call->n_args() == 1);
1699 long long int mean = eval_int(env, call->arg(0)).toInt();
1700 std::poisson_distribution<long long int> distribution(mean);
1701 // return a sample from the distribution
1702 return IntVal(distribution(rnd_generator()));
1703}
1704
1705IntVal b_poisson_float(EnvI& env, Call* call) {
1706 assert(call->n_args() == 1);
1707 double mean = eval_float(env, call->arg(0)).toDouble();
1708 std::poisson_distribution<long long int> distribution(mean);
1709 // return a sample from the distribution
1710 return IntVal(distribution(rnd_generator()));
1711}
1712
1713FloatVal b_gamma_float_float(EnvI& env, Call* call) {
1714 assert(call->n_args() == 2);
1715 const double alpha = eval_float(env, call->arg(0)).toDouble();
1716 const double beta = eval_float(env, call->arg(1)).toDouble();
1717 std::gamma_distribution<double> distribution(alpha, beta);
1718 // return a sample from the distribution
1719 return distribution(rnd_generator());
1720}
1721
1722FloatVal b_gamma_int_float(EnvI& env, Call* call) {
1723 assert(call->n_args() == 2);
1724 const double alpha = eval_float(env, call->arg(0)).toDouble();
1725 const double beta = eval_float(env, call->arg(1)).toDouble();
1726 std::gamma_distribution<double> distribution(alpha, beta);
1727 // return a sample from the distribution
1728 return distribution(rnd_generator());
1729}
1730
1731FloatVal b_weibull_int_float(EnvI& env, Call* call) {
1732 assert(call->n_args() == 2);
1733 const double shape = double(eval_int(env, call->arg(0)).toInt());
1734 if (shape < 0) {
1735 std::stringstream ssm;
1736 ssm << "The shape factor for the weibull distribution \"" << shape
1737 << "\" has to be greater than zero.";
1738 throw EvalError(env, call->arg(0)->loc(), ssm.str());
1739 }
1740 const double scale = eval_float(env, call->arg(1)).toDouble();
1741 if (scale < 0) {
1742 std::stringstream ssm;
1743 ssm << "The scale factor for the weibull distribution \"" << scale
1744 << "\" has to be greater than zero.";
1745 throw EvalError(env, call->arg(1)->loc(), ssm.str());
1746 }
1747 std::weibull_distribution<double> distribution(shape, scale);
1748 // return a sample from the distribution
1749 return distribution(rnd_generator());
1750}
1751
1752FloatVal b_weibull_float_float(EnvI& env, Call* call) {
1753 assert(call->n_args() == 2);
1754 const double shape = eval_float(env, call->arg(0)).toDouble();
1755 if (shape < 0) {
1756 std::stringstream ssm;
1757 ssm << "The shape factor for the weibull distribution \"" << shape
1758 << "\" has to be greater than zero.";
1759 throw EvalError(env, call->arg(0)->loc(), ssm.str());
1760 }
1761 const double scale = eval_float(env, call->arg(1)).toDouble();
1762 if (scale < 0) {
1763 std::stringstream ssm;
1764 ssm << "The scale factor for the weibull distribution \"" << scale
1765 << "\" has to be greater than zero.";
1766 throw EvalError(env, call->arg(1)->loc(), ssm.str());
1767 }
1768 std::weibull_distribution<double> distribution(shape, scale);
1769 // return a sample from the distribution
1770 return distribution(rnd_generator());
1771}
1772
1773FloatVal b_exponential_float(EnvI& env, Call* call) {
1774 assert(call->n_args() == 1);
1775 const double lambda = eval_float(env, call->arg(0)).toDouble();
1776 if (lambda < 0) {
1777 std::stringstream ssm;
1778 ssm << "The lambda-parameter for the exponential distribution function \"" << lambda
1779 << "\" has to be greater than zero.";
1780 throw EvalError(env, call->arg(0)->loc(), ssm.str());
1781 }
1782 std::exponential_distribution<double> distribution(lambda);
1783 // return a sample from the distribution
1784 return distribution(rnd_generator());
1785}
1786
1787FloatVal b_exponential_int(EnvI& env, Call* call) {
1788 assert(call->n_args() == 1);
1789 const double lambda = double(eval_int(env, call->arg(0)).toInt());
1790 if (lambda < 0) {
1791 std::stringstream ssm;
1792 ssm << "The lambda-parameter for the exponential distribution function \"" << lambda
1793 << "\" has to be greater than zero.";
1794 throw EvalError(env, call->arg(0)->loc(), ssm.str());
1795 }
1796 std::exponential_distribution<double> distribution(lambda);
1797 // return a sample from the distribution
1798 return distribution(rnd_generator());
1799}
1800
1801FloatVal b_lognormal_float_float(EnvI& env, Call* call) {
1802 assert(call->n_args() == 2);
1803 const double mean = eval_float(env, call->arg(0)).toDouble();
1804 const double stdv = eval_float(env, call->arg(1)).toDouble();
1805 std::lognormal_distribution<double> distribution(mean, stdv);
1806 // return a sample from the distribution
1807 return distribution(rnd_generator());
1808}
1809
1810FloatVal b_lognormal_int_float(EnvI& env, Call* call) {
1811 assert(call->n_args() == 2);
1812 const double mean = double(eval_int(env, call->arg(0)).toInt());
1813 const double stdv = eval_float(env, call->arg(1)).toDouble();
1814 std::lognormal_distribution<double> distribution(mean, stdv);
1815 // return a sample from the distribution
1816 return distribution(rnd_generator());
1817}
1818
1819FloatVal b_chisquared_float(EnvI& env, Call* call) {
1820 assert(call->n_args() == 1);
1821 const double lambda = eval_float(env, call->arg(0)).toDouble();
1822 std::exponential_distribution<double> distribution(lambda);
1823 // return a sample from the distribution
1824 return distribution(rnd_generator());
1825}
1826
1827FloatVal b_chisquared_int(EnvI& env, Call* call) {
1828 assert(call->n_args() == 1);
1829 const double lambda = double(eval_int(env, call->arg(0)).toInt());
1830 std::exponential_distribution<double> distribution(lambda);
1831 // return a sample from the distribution
1832 return distribution(rnd_generator());
1833}
1834
1835FloatVal b_cauchy_float_float(EnvI& env, Call* call) {
1836 assert(call->n_args() == 2);
1837 const double mean = eval_float(env, call->arg(0)).toDouble();
1838 const double scale = eval_float(env, call->arg(1)).toDouble();
1839 std::cauchy_distribution<double> distribution(mean, scale);
1840 // return a sample from the distribution
1841 return distribution(rnd_generator());
1842}
1843
1844FloatVal b_cauchy_int_float(EnvI& env, Call* call) {
1845 assert(call->n_args() == 2);
1846 const double mean = double(eval_int(env, call->arg(0)).toInt());
1847 const double scale = eval_float(env, call->arg(1)).toDouble();
1848 std::cauchy_distribution<double> distribution(mean, scale);
1849 // return a sample from the distribution
1850 return distribution(rnd_generator());
1851}
1852
1853FloatVal b_fdistribution_float_float(EnvI& env, Call* call) {
1854 assert(call->n_args() == 2);
1855 const double d1 = eval_float(env, call->arg(0)).toDouble();
1856 const double d2 = eval_float(env, call->arg(1)).toDouble();
1857 std::fisher_f_distribution<double> distribution(d1, d2);
1858 // return a sample from the distribution
1859 return distribution(rnd_generator());
1860}
1861
1862FloatVal b_fdistribution_int_int(EnvI& env, Call* call) {
1863 assert(call->n_args() == 2);
1864 const double d1 = double(eval_int(env, call->arg(0)).toInt());
1865 const double d2 = double(eval_int(env, call->arg(1)).toInt());
1866 std::fisher_f_distribution<double> distribution(d1, d2);
1867 // return a sample from the distribution
1868 return distribution(rnd_generator());
1869}
1870
1871FloatVal b_tdistribution_float(EnvI& env, Call* call) {
1872 assert(call->n_args() == 1);
1873 const double sampleSize = eval_float(env, call->arg(0)).toDouble();
1874 std::student_t_distribution<double> distribution(sampleSize);
1875 // return a sample from the distribution
1876 return distribution(rnd_generator());
1877}
1878
1879FloatVal b_tdistribution_int(EnvI& env, Call* call) {
1880 assert(call->n_args() == 1);
1881 const double sampleSize = double(eval_int(env, call->arg(0)).toInt());
1882 std::student_t_distribution<double> distribution(sampleSize);
1883 // return a sample from the distribution
1884 return distribution(rnd_generator());
1885}
1886
1887IntVal b_discrete_distribution(EnvI& env, Call* call) {
1888 assert(call->n_args() == 1);
1889 GCLock lock;
1890 ArrayLit* al = eval_array_lit(env, call->arg(0));
1891 if (al->dims() != 1) {
1892 std::stringstream ssm;
1893 ssm << "expecting 1-dimensional array of weights for discrete distribution instead of: " << *al
1894 << std::endl;
1895 throw EvalError(env, al->loc(), ssm.str());
1896 }
1897 std::vector<long long int> weights(al->size());
1898 for (unsigned int i = 0; i < al->size(); i++) {
1899 weights[i] = eval_int(env, (*al)[i]).toInt();
1900 }
1901#ifdef _MSC_VER
1902 std::size_t i(0);
1903 std::discrete_distribution<long long int> distribution(
1904 weights.size(), 0.0, 1.0, [&weights, &i](double) { return weights[i++]; });
1905#else
1906 std::discrete_distribution<long long int> distribution(weights.begin(), weights.end());
1907#endif
1908 // return a sample from the distribution
1909 IntVal iv = IntVal(distribution(rnd_generator()));
1910 return iv;
1911}
1912
1913bool b_bernoulli(EnvI& env, Call* call) {
1914 assert(call->n_args() == 1);
1915 const double p = eval_float(env, call->arg(0)).toDouble();
1916 std::bernoulli_distribution distribution(p);
1917 // return a sample from the distribution
1918 return distribution(rnd_generator());
1919}
1920
1921IntVal b_binomial(EnvI& env, Call* call) {
1922 assert(call->n_args() == 2);
1923 double t = double(eval_int(env, call->arg(0)).toInt());
1924 double p = eval_float(env, call->arg(1)).toDouble();
1925 std::binomial_distribution<long long int> distribution(t, p);
1926 // return a sample from the distribution
1927 return IntVal(distribution(rnd_generator()));
1928}
1929
1930FloatVal b_atan(EnvI& env, Call* call) {
1931 assert(call->n_args() == 1);
1932 GCLock lock;
1933 FloatVal f = eval_float(env, call->arg(0));
1934 return std::atan(f.toDouble());
1935}
1936
1937FloatVal b_cos(EnvI& env, Call* call) {
1938 assert(call->n_args() == 1);
1939 GCLock lock;
1940 FloatVal f = eval_float(env, call->arg(0));
1941 return std::cos(f.toDouble());
1942}
1943
1944FloatVal b_sin(EnvI& env, Call* call) {
1945 assert(call->n_args() == 1);
1946 GCLock lock;
1947 FloatVal f = eval_float(env, call->arg(0));
1948 return std::sin(f.toDouble());
1949}
1950
1951FloatVal b_asin(EnvI& env, Call* call) {
1952 assert(call->n_args() == 1);
1953 GCLock lock;
1954 FloatVal f = eval_float(env, call->arg(0));
1955 return std::asin(f.toDouble());
1956}
1957
1958FloatVal b_acos(EnvI& env, Call* call) {
1959 assert(call->n_args() == 1);
1960 GCLock lock;
1961 FloatVal f = eval_float(env, call->arg(0));
1962 return std::acos(f.toDouble());
1963}
1964
1965FloatVal b_tan(EnvI& env, Call* call) {
1966 assert(call->n_args() == 1);
1967 GCLock lock;
1968 FloatVal f = eval_float(env, call->arg(0));
1969 return std::tan(f.toDouble());
1970}
1971
1972IntVal b_to_enum(EnvI& env, Call* call) {
1973 assert(call->n_args() == 2);
1974 IntSetVal* isv = eval_intset(env, call->arg(0));
1975 IntVal v = eval_int(env, call->arg(1));
1976 if (!isv->contains(v))
1977 throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
1978 return v;
1979}
1980
1981IntVal b_enum_next(EnvI& env, Call* call) {
1982 IntSetVal* isv = eval_intset(env, call->arg(0));
1983 IntVal v = eval_int(env, call->arg(1));
1984 if (!isv->contains(v + 1))
1985 throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
1986 return v + 1;
1987}
1988
1989IntVal b_enum_prev(EnvI& env, Call* call) {
1990 IntSetVal* isv = eval_intset(env, call->arg(0));
1991 IntVal v = eval_int(env, call->arg(1));
1992 if (!isv->contains(v - 1))
1993 throw ResultUndefinedError(env, call->loc(), "value outside of enum range");
1994 return v - 1;
1995}
1996
1997IntVal b_mzn_compiler_version(EnvI&, Call*) {
1998 return atoi(MZN_VERSION_MAJOR) * 10000 + atoi(MZN_VERSION_MINOR) * 1000 + atoi(MZN_VERSION_PATCH);
1999}
2000
2001Expression* b_slice(EnvI& env, Call* call) {
2002 ArrayLit* al = eval_array_lit(env, call->arg(0));
2003
2004 ArrayLit* slice = eval_array_lit(env, call->arg(1));
2005 std::vector<std::pair<int, int>> newSlice(slice->size());
2006 for (unsigned int i = 0; i < slice->size(); i++) {
2007 IntSetVal* isv = eval_intset(env, (*slice)[i]);
2008 if (isv->size() == 0) {
2009 newSlice[i] = std::pair<int, int>(1, 0);
2010 } else {
2011 if (isv->size() > 1)
2012 throw ResultUndefinedError(env, call->loc(), "array slice must be contiguous");
2013 int sl_min = isv->min().isFinite() ? static_cast<int>(isv->min().toInt()) : al->min(i);
2014 int sl_max = isv->max().isFinite() ? static_cast<int>(isv->max().toInt()) : al->max(i);
2015 if (sl_min < al->min(i) || sl_max > al->max(i))
2016 throw ResultUndefinedError(env, call->loc(), "array slice out of bounds");
2017 newSlice[i] = std::pair<int, int>(sl_min, sl_max);
2018 }
2019 }
2020
2021 std::vector<std::pair<int, int>> newDims(call->n_args() - 2);
2022 for (unsigned int i = 0; i < newDims.size(); i++) {
2023 IntSetVal* isv = eval_intset(env, call->arg(2 + i));
2024 if (isv->size() == 0) {
2025 newDims[i] = std::pair<int, int>(1, 0);
2026 } else {
2027 newDims[i] = std::pair<int, int>(static_cast<int>(isv->min().toInt()),
2028 static_cast<int>(isv->max().toInt()));
2029 }
2030 }
2031 ArrayLit* ret = new ArrayLit(al->loc(), al, newDims, newSlice);
2032 ret->type(call->type());
2033 return ret;
2034}
2035
2036Expression* b_regular_from_string(EnvI& env, Call* call) {
2037#ifdef HAS_GECODE
2038 using namespace Gecode;
2039 ArrayLit* vars = eval_array_lit(env, call->arg(0));
2040 std::string expr = eval_string(env, call->arg(1));
2041
2042 IntSetVal* dom;
2043 if (vars->size() == 0) {
2044 dom = IntSetVal::a();
2045 } else {
2046 dom = b_dom_varint(env, (*vars)[0]);
2047 for (unsigned int i = 1; i < vars->size(); i++) {
2048 IntSetRanges isr(dom);
2049 IntSetRanges r(b_dom_varint(env, (*vars)[i]));
2050 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r);
2051 dom = IntSetVal::ai(u);
2052 }
2053 }
2054 int card = dom->max().toInt() - dom->min().toInt() + 1;
2055 int offset = 1 - dom->min().toInt();
2056
2057 std::unique_ptr<REG> regex;
2058 try {
2059 regex = regex_from_string(expr, *dom, env.reverseEnum);
2060 } catch (const std::exception& e) {
2061 throw SyntaxError(call->arg(1)->loc(), e.what());
2062 }
2063 DFA dfa = DFA(*regex);
2064
2065 std::vector<std::vector<Expression*>> reg_trans(
2066 dfa.n_states(), std::vector<Expression*>(card, IntLit::a(IntVal(0))));
2067
2068 DFA::Transitions trans(dfa);
2069 while (trans()) {
2070 // std::cerr << trans.i_state() + 1 << " -- " << trans.symbol() << " --> " <<
2071 // trans.o_state() + 1 << "\n";
2072 if (trans.symbol() >= dom->min().toInt() && trans.symbol() <= dom->max().toInt()) {
2073 reg_trans[trans.i_state()][trans.symbol() + offset - 1] =
2074 IntLit::a(IntVal(trans.o_state() + 1));
2075 }
2076 ++trans;
2077 }
2078
2079 std::vector<Expression*> args(6);
2080 if (offset == 0) {
2081 args[0] = vars; // x
2082 } else {
2083 std::vector<Expression*> nvars(vars->size());
2084 IntLit* loffset = IntLit::a(IntVal(offset));
2085 for (int i = 0; i < nvars.size(); ++i) {
2086 nvars[i] = new BinOp(call->loc().introduce(), (*vars)[i], BOT_PLUS, loffset);
2087 nvars[i]->type(Type::varint());
2088 }
2089 args[0] = new ArrayLit(call->loc().introduce(), nvars); // x
2090 args[0]->type(Type::varint(1));
2091 }
2092 args[1] = IntLit::a(IntVal(dfa.n_states())); // Q
2093 args[1]->type(Type::parint());
2094 args[2] = IntLit::a(IntVal(card)); // S
2095 args[2]->type(Type::parint());
2096 args[3] = new ArrayLit(call->loc().introduce(), reg_trans); // d
2097 args[3]->type(Type::parint(2));
2098 args[4] = IntLit::a(IntVal(1)); // q0
2099 args[4]->type(Type::parint());
2100 args[5] = new SetLit(call->loc().introduce(),
2101 IntSetVal::a(IntVal(dfa.final_fst() + 1), IntVal(dfa.final_lst()))); // F
2102 args[5]->type(Type::parsetint());
2103
2104 auto nc = new Call(call->loc().introduce(), "regular", args);
2105 nc->type(Type::varbool());
2106
2107 return nc;
2108#else
2109 throw FlatteningError(
2110 env, call->loc(),
2111 "MiniZinc was compiled without built-in Gecode, cannot parse regular expression");
2112#endif
2113}
2114
2115void registerBuiltins(Env& e) {
2116 EnvI& env = e.envi();
2117 Model* m = env.model;
2118
2119 std::vector<Type> t_intint(2);
2120 t_intint[0] = Type::parint();
2121 t_intint[1] = Type::parint();
2122
2123 std::vector<Type> t_intarray(1);
2124 t_intarray[0] = Type::parint(-1);
2125
2126 GCLock lock;
2127
2128 rb(env, m, ASTString("min"), t_intint, b_int_min);
2129 rb(env, m, ASTString("min"), t_intarray, b_int_min);
2130 rb(env, m, ASTString("max"), t_intint, b_int_max);
2131 rb(env, m, ASTString("max"), t_intarray, b_int_max);
2132 rb(env, m, constants().ids.sum, t_intarray, b_sum_int);
2133 rb(env, m, ASTString("product"), t_intarray, b_product_int);
2134 rb(env, m, ASTString("pow"), t_intint, b_pow_int);
2135
2136 {
2137 std::vector<Type> t(2);
2138 t[0] = Type::top(-1);
2139 t[1] = Type::top(-1);
2140 rb(env, m, ASTString("index_sets_agree"), t, b_index_sets_agree);
2141 }
2142 {
2143 std::vector<Type> t_anyarray1(1);
2144 t_anyarray1[0] = Type::optvartop(1);
2145 rb(env, m, ASTString("index_set"), t_anyarray1, b_index_set1);
2146 }
2147 {
2148 std::vector<Type> t_anyarray2(1);
2149 t_anyarray2[0] = Type::optvartop(2);
2150 rb(env, m, ASTString("index_set_1of2"), t_anyarray2, b_index_set1);
2151 rb(env, m, ASTString("index_set_2of2"), t_anyarray2, b_index_set2);
2152 }
2153 {
2154 std::vector<Type> t_anyarray3(1);
2155 t_anyarray3[0] = Type::optvartop(3);
2156 rb(env, m, ASTString("index_set_1of3"), t_anyarray3, b_index_set1);
2157 rb(env, m, ASTString("index_set_2of3"), t_anyarray3, b_index_set2);
2158 rb(env, m, ASTString("index_set_3of3"), t_anyarray3, b_index_set3);
2159 }
2160 {
2161 std::vector<Type> t_anyarray4(1);
2162 t_anyarray4[0] = Type::optvartop(4);
2163 rb(env, m, ASTString("index_set_1of4"), t_anyarray4, b_index_set1);
2164 rb(env, m, ASTString("index_set_2of4"), t_anyarray4, b_index_set2);
2165 rb(env, m, ASTString("index_set_3of4"), t_anyarray4, b_index_set3);
2166 rb(env, m, ASTString("index_set_4of4"), t_anyarray4, b_index_set4);
2167 }
2168 {
2169 std::vector<Type> t_anyarray5(1);
2170 t_anyarray5[0] = Type::optvartop(5);
2171 rb(env, m, ASTString("index_set_1of5"), t_anyarray5, b_index_set1);
2172 rb(env, m, ASTString("index_set_2of5"), t_anyarray5, b_index_set2);
2173 rb(env, m, ASTString("index_set_3of5"), t_anyarray5, b_index_set3);
2174 rb(env, m, ASTString("index_set_4of5"), t_anyarray5, b_index_set4);
2175 rb(env, m, ASTString("index_set_5of5"), t_anyarray5, b_index_set5);
2176 }
2177 {
2178 std::vector<Type> t_anyarray6(1);
2179 t_anyarray6[0] = Type::optvartop(6);
2180 rb(env, m, ASTString("index_set_1of6"), t_anyarray6, b_index_set1);
2181 rb(env, m, ASTString("index_set_2of6"), t_anyarray6, b_index_set2);
2182 rb(env, m, ASTString("index_set_3of6"), t_anyarray6, b_index_set3);
2183 rb(env, m, ASTString("index_set_4of6"), t_anyarray6, b_index_set4);
2184 rb(env, m, ASTString("index_set_5of6"), t_anyarray6, b_index_set5);
2185 rb(env, m, ASTString("index_set_6of6"), t_anyarray6, b_index_set6);
2186 }
2187 {
2188 std::vector<Type> t_arrayXd(1);
2189 t_arrayXd[0] = Type::top(-1);
2190 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2191 t_arrayXd[0].ot(Type::OT_OPTIONAL);
2192 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2193 t_arrayXd[0] = Type::vartop(-1);
2194 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2195 t_arrayXd[0] = Type::optvartop(-1);
2196 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list);
2197 }
2198 {
2199 std::vector<Type> t_arrayXd(2);
2200 t_arrayXd[0] = Type::parsetint();
2201 t_arrayXd[1] = Type::top(-1);
2202 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2203 t_arrayXd[1].ot(Type::OT_OPTIONAL);
2204 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2205 t_arrayXd[1] = Type::vartop(-1);
2206 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2207 t_arrayXd[1] = Type::optvartop(-1);
2208 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d);
2209 }
2210 {
2211 std::vector<Type> t_arrayXd(2);
2212 t_arrayXd[0] = Type::optvartop(-1);
2213 t_arrayXd[1] = Type::top(-1);
2214 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2215 t_arrayXd[1].ot(Type::OT_OPTIONAL);
2216 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2217 t_arrayXd[1] = Type::vartop(-1);
2218 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2219 t_arrayXd[1] = Type::optvartop(-1);
2220 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd);
2221 }
2222 {
2223 std::vector<Type> t_arrayXd(3);
2224 t_arrayXd[0] = Type::parsetint();
2225 t_arrayXd[1] = Type::parsetint();
2226 t_arrayXd[2] = Type::top(-1);
2227 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2228 t_arrayXd[2].ot(Type::OT_OPTIONAL);
2229 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2230 t_arrayXd[2] = Type::vartop(-1);
2231 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2232 t_arrayXd[2] = Type::optvartop(-1);
2233 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d);
2234 }
2235 {
2236 std::vector<Type> t_arrayXd(4);
2237 t_arrayXd[0] = Type::parsetint();
2238 t_arrayXd[1] = Type::parsetint();
2239 t_arrayXd[2] = Type::parsetint();
2240 t_arrayXd[3] = Type::top(-1);
2241 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2242 t_arrayXd[3].ot(Type::OT_OPTIONAL);
2243 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2244 t_arrayXd[3] = Type::vartop(-1);
2245 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2246 t_arrayXd[3] = Type::optvartop(-1);
2247 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d);
2248 }
2249 {
2250 std::vector<Type> t_arrayXd(5);
2251 t_arrayXd[0] = Type::parsetint();
2252 t_arrayXd[1] = Type::parsetint();
2253 t_arrayXd[2] = Type::parsetint();
2254 t_arrayXd[3] = Type::parsetint();
2255 t_arrayXd[4] = Type::top(-1);
2256 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2257 t_arrayXd[4].ot(Type::OT_OPTIONAL);
2258 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2259 t_arrayXd[4] = Type::vartop(-1);
2260 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2261 t_arrayXd[4] = Type::optvartop(-1);
2262 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d);
2263 }
2264 {
2265 std::vector<Type> t_arrayXd(6);
2266 t_arrayXd[0] = Type::parsetint();
2267 t_arrayXd[1] = Type::parsetint();
2268 t_arrayXd[2] = Type::parsetint();
2269 t_arrayXd[3] = Type::parsetint();
2270 t_arrayXd[4] = Type::parsetint();
2271 t_arrayXd[5] = Type::top(-1);
2272 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2273 t_arrayXd[5].ot(Type::OT_OPTIONAL);
2274 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2275 t_arrayXd[5] = Type::vartop(-1);
2276 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2277 t_arrayXd[5] = Type::optvartop(-1);
2278 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d);
2279 }
2280 {
2281 std::vector<Type> t_arrayXd(7);
2282 t_arrayXd[0] = Type::parsetint();
2283 t_arrayXd[1] = Type::parsetint();
2284 t_arrayXd[2] = Type::parsetint();
2285 t_arrayXd[3] = Type::parsetint();
2286 t_arrayXd[4] = Type::parsetint();
2287 t_arrayXd[5] = Type::parsetint();
2288 t_arrayXd[6] = Type::top(-1);
2289 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
2290 t_arrayXd[6].ot(Type::OT_OPTIONAL);
2291 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
2292 t_arrayXd[6] = Type::vartop(-1);
2293 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
2294 t_arrayXd[6] = Type::optvartop(-1);
2295 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d);
2296 }
2297 {
2298 std::vector<Type> stv(3);
2299 stv[0] = Type::partop(-1);
2300 stv[1] = Type::parsetint(1);
2301 stv[2] = Type::parsetint();
2302 rb(env, m, ASTString("slice_1d"), stv, b_slice);
2303 stv[0] = Type::vartop(-1);
2304 rb(env, m, ASTString("slice_1d"), stv, b_slice);
2305 stv[0] = Type::optvartop(-1);
2306 rb(env, m, ASTString("slice_1d"), stv, b_slice);
2307 stv[0] = Type::optpartop(-1);
2308 rb(env, m, ASTString("slice_1d"), stv, b_slice);
2309
2310 stv.push_back(Type::parsetint());
2311 stv[0] = Type::partop(-1);
2312 rb(env, m, ASTString("slice_2d"), stv, b_slice);
2313 stv[0] = Type::vartop(-1);
2314 rb(env, m, ASTString("slice_2d"), stv, b_slice);
2315 stv[0] = Type::optvartop(-1);
2316 rb(env, m, ASTString("slice_2d"), stv, b_slice);
2317 stv[0] = Type::optpartop(-1);
2318 rb(env, m, ASTString("slice_2d"), stv, b_slice);
2319
2320 stv.push_back(Type::parsetint());
2321 stv[0] = Type::partop(-1);
2322 rb(env, m, ASTString("slice_3d"), stv, b_slice);
2323 stv[0] = Type::vartop(-1);
2324 rb(env, m, ASTString("slice_3d"), stv, b_slice);
2325 stv[0] = Type::optvartop(-1);
2326 rb(env, m, ASTString("slice_3d"), stv, b_slice);
2327 stv[0] = Type::optpartop(-1);
2328 rb(env, m, ASTString("slice_3d"), stv, b_slice);
2329
2330 stv.push_back(Type::parsetint());
2331 stv[0] = Type::partop(-1);
2332 rb(env, m, ASTString("slice_4d"), stv, b_slice);
2333 stv[0] = Type::vartop(-1);
2334 rb(env, m, ASTString("slice_4d"), stv, b_slice);
2335 stv[0] = Type::optvartop(-1);
2336 rb(env, m, ASTString("slice_4d"), stv, b_slice);
2337 stv[0] = Type::optpartop(-1);
2338 rb(env, m, ASTString("slice_4d"), stv, b_slice);
2339
2340 stv.push_back(Type::parsetint());
2341 stv[0] = Type::partop(-1);
2342 rb(env, m, ASTString("slice_5d"), stv, b_slice);
2343 stv[0] = Type::vartop(-1);
2344 rb(env, m, ASTString("slice_5d"), stv, b_slice);
2345 stv[0] = Type::optvartop(-1);
2346 rb(env, m, ASTString("slice_5d"), stv, b_slice);
2347 stv[0] = Type::optpartop(-1);
2348 rb(env, m, ASTString("slice_5d"), stv, b_slice);
2349
2350 stv.push_back(Type::parsetint());
2351 stv[0] = Type::partop(-1);
2352 rb(env, m, ASTString("slice_6d"), stv, b_slice);
2353 stv[0] = Type::vartop(-1);
2354 rb(env, m, ASTString("slice_6d"), stv, b_slice);
2355 stv[0] = Type::optvartop(-1);
2356 rb(env, m, ASTString("slice_6d"), stv, b_slice);
2357 stv[0] = Type::optpartop(-1);
2358 rb(env, m, ASTString("slice_6d"), stv, b_slice);
2359 }
2360 {
2361 std::vector<Type> t(2);
2362 t[0] = Type::parbool();
2363 t[1] = Type::parstring();
2364 rb(env, m, constants().ids.assert, t, b_assert_bool);
2365 }
2366 {
2367 std::vector<Type> t(3);
2368 t[0] = Type::parbool();
2369 t[1] = Type::parstring();
2370 t[2] = Type::top();
2371 rb(env, m, constants().ids.assert, t, b_assert);
2372 t[2] = Type::vartop();
2373 rb(env, m, constants().ids.assert, t, b_assert);
2374 t[2] = Type::optvartop();
2375 rb(env, m, constants().ids.assert, t, b_assert);
2376 t[2] = Type::top(-1);
2377 rb(env, m, constants().ids.assert, t, b_assert);
2378 t[2] = Type::vartop(-1);
2379 rb(env, m, constants().ids.assert, t, b_assert);
2380 t[2] = Type::optvartop(-1);
2381 rb(env, m, constants().ids.assert, t, b_assert);
2382 }
2383 {
2384 std::vector<Type> t(1);
2385 t[0] = Type::parstring();
2386 rb(env, m, ASTString("abort"), t, b_abort);
2387 rb(env, m, constants().ids.trace, t, b_trace);
2388 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
2389 }
2390 {
2391 std::vector<Type> t(2);
2392 t[0] = Type::parstring();
2393 t[1] = Type::top();
2394 rb(env, m, constants().ids.trace, t, b_trace);
2395 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
2396 t[1] = Type::vartop();
2397 rb(env, m, constants().ids.trace, t, b_trace);
2398 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
2399 t[1] = Type::optvartop();
2400 rb(env, m, constants().ids.trace, t, b_trace);
2401 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout);
2402 }
2403 {
2404 rb(env, m, ASTString("mzn_in_redundant_constraint"), std::vector<Type>(),
2405 b_in_redundant_constraint);
2406 }
2407 {
2408 std::vector<Type> t_length(1);
2409 t_length[0] = Type::optvartop(-1);
2410 rb(env, m, ASTString("length"), t_length, b_length);
2411 }
2412 {
2413 std::vector<Type> t(1);
2414 t[0] = Type::parbool();
2415 rb(env, m, constants().ids.bool2int, t, b_bool2int);
2416 }
2417 {
2418 std::vector<Type> t(1);
2419 t[0] = Type::parbool(-1);
2420 rb(env, m, constants().ids.forall, t, b_forall_par);
2421 rb(env, m, constants().ids.exists, t, b_exists_par);
2422 rb(env, m, ASTString("xorall"), t, b_xorall_par);
2423 rb(env, m, ASTString("iffall"), t, b_iffall_par);
2424 }
2425 {
2426 std::vector<Type> t(2);
2427 t[0] = Type::parbool(-1);
2428 t[1] = Type::parbool(-1);
2429 rb(env, m, constants().ids.clause, t, b_clause_par);
2430 }
2431 {
2432 std::vector<Type> t(1);
2433 t[0] = Type::varsetint();
2434 rb(env, m, ASTString("ub"), t, b_ub_set);
2435 rb(env, m, ASTString("lb"), t, b_lb_set);
2436 }
2437 {
2438 std::vector<Type> t(1);
2439 t[0] = Type::varsetint(1);
2440 rb(env, m, ASTString("ub_array"), t, b_array_ub_set);
2441 }
2442 {
2443 std::vector<Type> t(1);
2444 t[0] = Type::varint();
2445 rb(env, m, ASTString("dom"), t, b_dom_varint);
2446 }
2447 {
2448 std::vector<Type> t(1);
2449 t[0] = Type::varint(-1);
2450 rb(env, m, ASTString("dom_array"), t, b_dom_array);
2451 rb(env, m, ASTString("dom_bounds_array"), t, b_dom_bounds_array);
2452 }
2453 {
2454 std::vector<Type> t(1);
2455 t[0] = Type::parsetint();
2456 rb(env, m, ASTString("min"), t, b_min_parsetint);
2457 }
2458 {
2459 std::vector<Type> t(1);
2460 t[0] = Type::parsetint();
2461 rb(env, m, ASTString("max"), t, b_max_parsetint);
2462 }
2463 {
2464 std::vector<Type> t(1);
2465 t[0] = Type::varint();
2466 t[0].ot(Type::OT_OPTIONAL);
2467 rb(env, m, ASTString("lb"), t, b_lb_varoptint);
2468 }
2469 {
2470 std::vector<Type> t(1);
2471 t[0] = Type::varint();
2472 t[0].ot(Type::OT_OPTIONAL);
2473 rb(env, m, ASTString("ub"), t, b_ub_varoptint);
2474 }
2475 {
2476 std::vector<Type> t(1);
2477 t[0] = Type::varint();
2478 rb(env, m, ASTString("lb"), t, b_lb_varoptint);
2479 }
2480 {
2481 std::vector<Type> t(1);
2482 t[0] = Type::varint();
2483 rb(env, m, ASTString("ub"), t, b_ub_varoptint);
2484 }
2485 {
2486 std::vector<Type> t(1);
2487 t[0] = Type::varint(-1);
2488 t[0].ot(Type::OT_OPTIONAL);
2489 rb(env, m, ASTString("lb_array"), t, b_array_lb_int);
2490 }
2491 {
2492 std::vector<Type> t(1);
2493 t[0] = Type::varint(-1);
2494 t[0].ot(Type::OT_OPTIONAL);
2495 rb(env, m, ASTString("ub_array"), t, b_array_ub_int);
2496 }
2497 {
2498 std::vector<Type> t(1);
2499 t[0] = Type::varfloat();
2500 rb(env, m, ASTString("lb"), t, b_lb_varoptfloat);
2501 }
2502 {
2503 std::vector<Type> t(1);
2504 t[0] = Type::varfloat();
2505 rb(env, m, ASTString("ub"), t, b_ub_varoptfloat);
2506 }
2507 {
2508 std::vector<Type> t(1);
2509 t[0] = Type::varfloat(-1);
2510 rb(env, m, ASTString("lb_array"), t, b_array_lb_float);
2511 }
2512 {
2513 std::vector<Type> t(1);
2514 t[0] = Type::varfloat(-1);
2515 rb(env, m, ASTString("ub_array"), t, b_array_ub_float);
2516 }
2517 {
2518 std::vector<Type> t(1);
2519 t[0] = Type::parsetint();
2520 rb(env, m, ASTString("card"), t, b_card);
2521 }
2522 {
2523 std::vector<Type> t(1);
2524 t[0] = Type::parint();
2525 rb(env, m, ASTString("abs"), t, b_abs_int);
2526 t[0] = Type::parfloat();
2527 rb(env, m, ASTString("abs"), t, b_abs_float);
2528 }
2529 {
2530 std::vector<Type> t(1);
2531 t[0] = Type::varint();
2532 rb(env, m, ASTString("has_bounds"), t, b_has_bounds_int);
2533 }
2534 {
2535 std::vector<Type> t(1);
2536 t[0] = Type::varfloat();
2537 rb(env, m, ASTString("has_bounds"), t, b_has_bounds_float);
2538 }
2539 {
2540 std::vector<Type> t(1);
2541 t[0] = Type::varsetint();
2542 rb(env, m, ASTString("has_ub_set"), t, b_has_ub_set);
2543 }
2544 {
2545 std::vector<Type> t(1);
2546 t[0] = Type::optvartop();
2547 rb(env, m, ASTString("is_fixed"), t, b_is_fixed);
2548 }
2549 {
2550 std::vector<Type> t(1);
2551 t[0] = Type::optvartop(-1);
2552 rb(env, m, ASTString("is_fixed"), t, b_is_fixed_array);
2553 }
2554 {
2555 std::vector<Type> t(1);
2556 t[0] = Type::optvartop();
2557 rb(env, m, ASTString("fix"), t, b_fix_bool);
2558 rb(env, m, ASTString("fix"), t, b_fix_int);
2559 rb(env, m, ASTString("fix"), t, b_fix_set);
2560 rb(env, m, ASTString("fix"), t, b_fix_float);
2561 }
2562 {
2563 std::vector<Type> t(1);
2564 t[0] = Type::optvartop(1);
2565 rb(env, m, ASTString("fix"), t, b_fix_array);
2566 }
2567 {
2568 std::vector<Type> t(1);
2569 t[0] = Type::parint();
2570 rb(env, m, ASTString("int2float"), t, b_int2float);
2571 }
2572 {
2573 std::vector<Type> t(1);
2574 t[0] = Type::parfloat();
2575 rb(env, m, ASTString("ceil"), t, b_ceil);
2576 rb(env, m, ASTString("floor"), t, b_floor);
2577 rb(env, m, ASTString("round"), t, b_round);
2578 rb(env, m, ASTString("log10"), t, b_log10);
2579 rb(env, m, ASTString("log2"), t, b_log2);
2580 rb(env, m, ASTString("ln"), t, b_ln);
2581 rb(env, m, ASTString("exp"), t, b_exp);
2582 rb(env, m, ASTString("sqrt"), t, b_sqrt);
2583 t.push_back(Type::parfloat());
2584 rb(env, m, ASTString("log"), t, b_log);
2585 rb(env, m, ASTString("pow"), t, b_pow);
2586 }
2587 {
2588 std::vector<Type> t(1);
2589 t[0] = Type::parfloat(1);
2590 rb(env, m, constants().ids.sum, t, b_sum_float);
2591 rb(env, m, ASTString("product"), t, b_product_float);
2592 }
2593 {
2594 std::vector<Type> t(1);
2595 t[0] = Type::parfloat(1);
2596 rb(env, m, ASTString("min"), t, b_float_min);
2597 rb(env, m, ASTString("max"), t, b_float_max);
2598
2599 t[0] = Type::parfloat();
2600 t.push_back(Type::parfloat());
2601 rb(env, m, ASTString("min"), t, b_float_min);
2602 rb(env, m, ASTString("max"), t, b_float_max);
2603 }
2604 {
2605 std::vector<Type> t(1);
2606 t[0] = Type::parsetint();
2607 rb(env, m, ASTString("set2array"), t, b_set2array);
2608 }
2609 {
2610 std::vector<Type> t(1);
2611 t[0] = Type::parstring();
2612 rb(env, m, ASTString("string_length"), t, b_string_length);
2613 }
2614 { rb(env, m, ASTString("file_path"), std::vector<Type>(), b_file_path); }
2615 {
2616 std::vector<Type> t(1);
2617 t[0] = Type::vartop();
2618 rb(env, m, ASTString("show"), t, b_show);
2619 rb(env, m, ASTString("showJSON"), t, b_show_json);
2620 t[0] = Type::vartop();
2621 t[0].st(Type::ST_SET);
2622 t[0].ot(Type::OT_OPTIONAL);
2623 rb(env, m, ASTString("show"), t, b_show);
2624 rb(env, m, ASTString("showJSON"), t, b_show_json);
2625 t[0] = Type::vartop(-1);
2626 rb(env, m, ASTString("show"), t, b_show);
2627 rb(env, m, ASTString("showJSON"), t, b_show_json);
2628 }
2629 {
2630 std::vector<Type> t(1);
2631 t[0] = Type::parstring();
2632 rb(env, m, ASTString("showDznId"), t, b_showDznId);
2633 }
2634 {
2635 std::vector<Type> t(3);
2636 t[0] = t[1] = Type::parint();
2637 t[2] = Type::vartop();
2638 rb(env, m, ASTString("format"), t, b_format);
2639 t[2] = Type::vartop();
2640 t[2].st(Type::ST_SET);
2641 t[2].ot(Type::OT_OPTIONAL);
2642 rb(env, m, ASTString("format"), t, b_format);
2643 t[2] = Type::vartop(-1);
2644 rb(env, m, ASTString("format"), t, b_format);
2645 }
2646 {
2647 std::vector<Type> t(2);
2648 t[0] = Type::parint();
2649 t[1] = Type::vartop();
2650 rb(env, m, ASTString("format"), t, b_format);
2651 t[1] = Type::vartop();
2652 t[1].st(Type::ST_SET);
2653 t[1].ot(Type::OT_OPTIONAL);
2654 rb(env, m, ASTString("format"), t, b_format);
2655 t[1] = Type::vartop(-1);
2656 rb(env, m, ASTString("format"), t, b_format);
2657 t[1] = Type::parstring();
2658 rb(env, m, ASTString("format_justify_string"), t, b_format_justify_string);
2659 }
2660 {
2661 std::vector<Type> t;
2662 rb(env, m, ASTString("outputJSON"), t, b_outputJSON);
2663 rb(env, m, ASTString("outputJSONParameters"), t, b_outputJSONParameters);
2664 }
2665 {
2666 std::vector<Type> t(2);
2667 t[0] = Type::parint();
2668 t[1] = Type::varint();
2669 rb(env, m, ASTString("show_int"), t, b_show_int);
2670 }
2671 {
2672 std::vector<Type> t(3);
2673 t[0] = Type::parint();
2674 t[1] = Type::parint();
2675 t[2] = Type::varfloat();
2676 rb(env, m, ASTString("show_float"), t, b_show_float);
2677 }
2678 {
2679 std::vector<Type> t(1);
2680 t[0] = Type::parstring(1);
2681 rb(env, m, ASTString("concat"), t, b_concat);
2682 }
2683 {
2684 std::vector<Type> t(2);
2685 t[0] = Type::parstring();
2686 t[1] = Type::parstring(1);
2687 rb(env, m, ASTString("join"), t, b_join);
2688 }
2689 {
2690 std::vector<Type> t(2);
2691 t[0] = Type::varint();
2692 t[1] = Type::varint();
2693 rb(env, m, ASTString("compute_div_bounds"), t, b_compute_div_bounds);
2694 }
2695 {
2696 std::vector<Type> t(1);
2697 t[0] = Type::parsetint(1);
2698 rb(env, m, ASTString("array_intersect"), t, b_array_intersect);
2699 rb(env, m, ASTString("array_union"), t, b_array_union);
2700 }
2701 {
2702 std::vector<Type> t(1);
2703 t[0] = Type::parint();
2704 t[0].ot(Type::OT_OPTIONAL);
2705 t[0].bt(Type::BT_TOP);
2706 rb(env, m, ASTString("occurs"), t, b_occurs);
2707 rb(env, m, ASTString("deopt"), t, b_deopt_expr);
2708 t[0].bt(Type::BT_INT);
2709 rb(env, m, ASTString("deopt"), t, b_deopt_int);
2710 t[0].bt(Type::BT_BOOL);
2711 rb(env, m, ASTString("deopt"), t, b_deopt_bool);
2712 t[0].bt(Type::BT_FLOAT);
2713 rb(env, m, ASTString("deopt"), t, b_deopt_float);
2714 t[0].bt(Type::BT_STRING);
2715 rb(env, m, ASTString("deopt"), t, b_deopt_string);
2716 t[0].bt(Type::BT_INT);
2717 t[0].st(Type::ST_SET);
2718 rb(env, m, ASTString("deopt"), t, b_deopt_intset);
2719 }
2720 {
2721 std::vector<Type> t(2);
2722 t[0] = Type::varbot(1);
2723 t[1] = Type::parint(1);
2724 rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
2725 t[0] = Type::bot(1);
2726 rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
2727 t[0].ot(Type::OT_OPTIONAL);
2728 rb(env, m, ASTString("sort_by"), t, b_sort_by_int);
2729 }
2730 {
2731 std::vector<Type> t(2);
2732 t[0] = Type::varbot(1);
2733 t[1] = Type::parfloat(1);
2734 rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
2735 t[0] = Type::bot(1);
2736 rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
2737 t[0].ot(Type::OT_OPTIONAL);
2738 rb(env, m, ASTString("sort_by"), t, b_sort_by_float);
2739 }
2740 {
2741 std::vector<Type> t(1);
2742 t[0] = Type::parint(1);
2743 rb(env, m, ASTString("sort"), t, b_sort);
2744 rb(env, m, ASTString("arg_min"), t, b_arg_min_int);
2745 rb(env, m, ASTString("arg_max"), t, b_arg_max_int);
2746 t[0] = Type::parbool(1);
2747 rb(env, m, ASTString("sort"), t, b_sort);
2748 t[0] = Type::parfloat(1);
2749 rb(env, m, ASTString("sort"), t, b_sort);
2750 rb(env, m, ASTString("arg_min"), t, b_arg_min_float);
2751 rb(env, m, ASTString("arg_max"), t, b_arg_max_float);
2752 }
2753 {
2754 std::vector<Type> t(1);
2755 t[0] = Type::parfloat();
2756 rb(env, m, ASTString("atan"), t, b_atan);
2757 }
2758 {
2759 std::vector<Type> t(1);
2760 t[0] = Type::parfloat();
2761 rb(env, m, ASTString("cos"), t, b_cos);
2762 }
2763 {
2764 std::vector<Type> t(1);
2765 t[0] = Type::parfloat();
2766 rb(env, m, ASTString("sin"), t, b_sin);
2767 }
2768 {
2769 std::vector<Type> t(1);
2770 t[0] = Type::parfloat();
2771 rb(env, m, ASTString("asin"), t, b_asin);
2772 }
2773 {
2774 std::vector<Type> t(1);
2775 t[0] = Type::parfloat();
2776 rb(env, m, ASTString("acos"), t, b_acos);
2777 }
2778 {
2779 std::vector<Type> t(1);
2780 t[0] = Type::parfloat();
2781 rb(env, m, ASTString("tan"), t, b_tan);
2782 }
2783 {
2784 std::vector<Type> t(2);
2785 t[0] = Type::parfloat();
2786 t[1] = Type::parfloat();
2787 rb(env, m, ASTString("normal"), t, b_normal_float_float);
2788 t[0] = Type::parint();
2789 rb(env, m, ASTString("normal"), t, b_normal_int_float);
2790 }
2791 {
2792 std::vector<Type> t(2);
2793 t[0] = Type::parfloat();
2794 t[1] = Type::parfloat();
2795 rb(env, m, ASTString("uniform"), t, b_uniform_float);
2796 t[0] = Type::parint();
2797 t[1] = Type::parint();
2798 rb(env, m, ASTString("uniform"), t, b_uniform_int);
2799 }
2800 {
2801 std::vector<Type> t(1);
2802 t[0] = Type::parfloat();
2803 rb(env, m, ASTString("poisson"), t, b_poisson_float);
2804 t[0] = Type::parint();
2805 rb(env, m, ASTString("poisson"), t, b_poisson_int);
2806 }
2807 {
2808 std::vector<Type> t(2);
2809 t[0] = Type::parfloat();
2810 t[1] = Type::parfloat();
2811 rb(env, m, ASTString("gamma"), t, b_gamma_float_float);
2812 t[0] = Type::parint();
2813 rb(env, m, ASTString("gamma"), t, b_gamma_int_float);
2814 }
2815 {
2816 std::vector<Type> t(2);
2817 t[0] = Type::parfloat();
2818 t[1] = Type::parfloat();
2819 rb(env, m, ASTString("weibull"), t, b_weibull_float_float);
2820 t[0] = Type::parint();
2821 rb(env, m, ASTString("weibull"), t, b_weibull_int_float);
2822 }
2823 {
2824 std::vector<Type> t(1);
2825 t[0] = Type::parfloat();
2826 rb(env, m, ASTString("exponential"), t, b_exponential_float);
2827 t[0] = Type::parint();
2828 rb(env, m, ASTString("exponential"), t, b_exponential_int);
2829 }
2830 {
2831 std::vector<Type> t(2);
2832 t[0] = Type::parfloat();
2833 t[1] = Type::parfloat();
2834 rb(env, m, ASTString("lognormal"), t, b_lognormal_float_float);
2835 t[0] = Type::parint();
2836 rb(env, m, ASTString("lognormal"), t, b_lognormal_int_float);
2837 }
2838 {
2839 std::vector<Type> t(1);
2840 t[0] = Type::parfloat();
2841 rb(env, m, ASTString("chisquared"), t, b_chisquared_float);
2842 t[0] = Type::parint();
2843 rb(env, m, ASTString("chisquared"), t, b_chisquared_int);
2844 }
2845 {
2846 std::vector<Type> t(2);
2847 t[0] = Type::parfloat();
2848 t[1] = Type::parfloat();
2849 rb(env, m, ASTString("cauchy"), t, b_cauchy_float_float);
2850 t[0] = Type::parint();
2851 rb(env, m, ASTString("cauchy"), t, b_cauchy_int_float);
2852 }
2853 {
2854 std::vector<Type> t(2);
2855 t[0] = Type::parfloat();
2856 t[1] = Type::parfloat();
2857 rb(env, m, ASTString("fdistribution"), t, b_fdistribution_float_float);
2858 t[0] = Type::parint();
2859 t[1] = Type::parint();
2860 rb(env, m, ASTString("fdistribution"), t, b_fdistribution_int_int);
2861 }
2862 {
2863 std::vector<Type> t(1);
2864 t[0] = Type::parfloat();
2865 rb(env, m, ASTString("tdistribution"), t, b_tdistribution_float);
2866 t[0] = Type::parint();
2867 rb(env, m, ASTString("tdistribution"), t, b_tdistribution_int);
2868 }
2869 {
2870 std::vector<Type> t(1);
2871 t[0] = Type::parint(1);
2872 rb(env, m, ASTString("discrete_distribution"), t, b_discrete_distribution);
2873 }
2874 {
2875 std::vector<Type> t(1);
2876 t[0] = Type::parint();
2877 rb(env, m, ASTString("bernoulli"), t, b_bernoulli);
2878 }
2879 {
2880 std::vector<Type> t(2);
2881 t[0] = Type::parint();
2882 t[1] = Type::parfloat();
2883 rb(env, m, ASTString("binomial"), t, b_binomial);
2884 }
2885 {
2886 std::vector<Type> t(2);
2887 t[0] = Type::parsetint();
2888 t[1] = Type::parint();
2889 rb(env, m, ASTString("to_enum"), t, b_to_enum);
2890 rb(env, m, ASTString("enum_next"), t, b_enum_next);
2891 rb(env, m, ASTString("enum_prev"), t, b_enum_prev);
2892 }
2893 { rb(env, m, ASTString("mzn_compiler_version"), std::vector<Type>(), b_mzn_compiler_version); }
2894 {
2895 std::vector<Type> t(2);
2896 t[0] = Type::varint(1);
2897 t[1] = Type::parstring();
2898 rb(env, m, ASTString("fzn_regular"), t, b_regular_from_string, true);
2899 }
2900}
2901
2902} // namespace MiniZinc