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