this repo has no description
at develop 23 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3/* 4 * Main authors: 5 * Jip J. Dekker <jip.dekker@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#pragma clang diagnostic push 13#pragma ide diagnostic ignored "cppcoreguidelines-pro-type-static-cast-downcast" 14 15#include <minizinc/solvers/geas/geas_constraints.hh> 16#include <minizinc/solvers/geas_solverinstance.hh> 17 18#include <geas/constraints/builtins.h> 19#include <geas/constraints/flow/flow.h> 20 21namespace MiniZinc { 22namespace GeasConstraints { 23 24#define SI (static_cast<GeasSolverInstance&>(s)) 25#define SD SI.solverData() 26#define SOL SI.solver() 27#define EXPR(X) call->arg(X) 28#define BOOL(X) SI.asBool(EXPR(X)) 29#define BOOLARRAY(X) SI.asBool(ARRAY(X)) 30#define BOOLVAR(X) SI.asBoolVar(EXPR(X)) 31#define BOOLVARARRAY(X) SI.asBoolVar(ARRAY(X)) 32#define INT(X) SI.asInt(EXPR(X)) 33#define INTARRAY(X) SI.asInt(ARRAY(X)) 34#define INTVAR(X) SI.asIntVar(EXPR(X)) 35#define INTVARARRAY(X) SI.asIntVar(ARRAY(X)) 36#define PAR(X) call->arg(X)->type().isPar() 37#define ARRAY(X) eval_array_lit(s.env().envi(), call->arg(X)) 38 39void p_int_eq(SolverInstanceBase& s, const Call* call) { geas::int_eq(SD, INTVAR(0), INTVAR(1)); } 40 41void p_int_ne(SolverInstanceBase& s, const Call* call) { geas::int_ne(SD, INTVAR(0), INTVAR(1)); } 42 43void p_int_le(SolverInstanceBase& s, const Call* call) { 44 geas::int_le(SD, INTVAR(0), INTVAR(1), 0); 45} 46 47void p_int_lt(SolverInstanceBase& s, const Call* call) { 48 geas::int_le(SD, INTVAR(0), INTVAR(1), -1); 49} 50 51void p_int_eq_imp(SolverInstanceBase& s, const Call* call) { 52 if (PAR(2)) { 53 if (BOOL(2)) { 54 p_int_eq(s, call); 55 } 56 } else { 57 geas::int_eq(SD, INTVAR(0), INTVAR(1), BOOLVAR(2)); 58 } 59} 60 61void p_int_ne_imp(SolverInstanceBase& s, const Call* call) { 62 if (PAR(2)) { 63 if (BOOL(2)) { 64 p_int_ne(s, call); 65 } 66 } else { 67 geas::int_ne(SD, INTVAR(0), INTVAR(1), BOOLVAR(2)); 68 } 69} 70 71void p_int_le_imp(SolverInstanceBase& s, const Call* call) { 72 if (PAR(2)) { 73 if (BOOL(2)) { 74 p_int_le(s, call); 75 } 76 } else { 77 geas::int_le(SD, INTVAR(0), INTVAR(1), 0, BOOLVAR(2)); 78 } 79} 80 81void p_int_lt_imp(SolverInstanceBase& s, const Call* call) { 82 if (PAR(2)) { 83 if (BOOL(2)) { 84 p_int_lt(s, call); 85 } 86 } else { 87 geas::int_le(SD, INTVAR(0), INTVAR(1), -1, BOOLVAR(2)); 88 } 89} 90 91void p_int_eq_reif(SolverInstanceBase& s, const Call* call) { 92 if (PAR(2)) { 93 if (BOOL(2)) { 94 p_int_eq(s, call); 95 } else { 96 p_int_ne(s, call); 97 } 98 } else { 99 geas::int_eq(SD, INTVAR(0), INTVAR(1), BOOLVAR(2)); 100 geas::int_ne(SD, INTVAR(0), INTVAR(1), ~BOOLVAR(2)); 101 } 102} 103 104void p_int_ne_reif(SolverInstanceBase& s, const Call* call) { 105 if (PAR(2)) { 106 if (BOOL(2)) { 107 p_int_ne(s, call); 108 } else { 109 p_int_eq(s, call); 110 } 111 } else { 112 geas::int_ne(SD, INTVAR(0), INTVAR(1), BOOLVAR(2)); 113 geas::int_eq(SD, INTVAR(0), INTVAR(1), ~BOOLVAR(2)); 114 } 115} 116 117void p_int_le_reif(SolverInstanceBase& s, const Call* call) { 118 if (PAR(2)) { 119 if (BOOL(2)) { 120 p_int_le(s, call); 121 } else { 122 auto* nc = new Call(Location().introduce(), call->id(), {call->arg(1), call->arg(0)}); 123 p_int_lt(s, nc); 124 } 125 } else { 126 geas::int_le(SD, INTVAR(0), INTVAR(1), 0, BOOLVAR(2)); 127 geas::int_le(SD, INTVAR(1), INTVAR(0), -1, ~BOOLVAR(2)); 128 } 129} 130 131void p_int_lt_reif(SolverInstanceBase& s, const Call* call) { 132 if (PAR(2)) { 133 if (BOOL(2)) { 134 p_int_lt(s, call); 135 } else { 136 auto* nc = new Call(Location().introduce(), call->id(), {call->arg(1), call->arg(0)}); 137 p_int_le(s, nc); 138 } 139 } else { 140 geas::int_le(SD, INTVAR(0), INTVAR(1), -1, BOOLVAR(2)); 141 geas::int_le(SD, INTVAR(1), INTVAR(0), 0, ~BOOLVAR(2)); 142 } 143} 144 145void p_int_abs(SolverInstanceBase& s, const Call* call) { geas::int_abs(SD, INTVAR(1), INTVAR(0)); } 146 147void p_int_times(SolverInstanceBase& s, const Call* call) { 148 geas::int_mul(SD, INTVAR(2), INTVAR(0), INTVAR(1)); 149} 150 151void p_int_div(SolverInstanceBase& s, const Call* call) { 152 geas::int_div(SD, INTVAR(2), INTVAR(0), INTVAR(1)); 153} 154 155void p_int_max(SolverInstanceBase& s, const Call* call) { 156 vec<geas::intvar> vars = {INTVAR(0), INTVAR(1)}; 157 geas::int_max(SD, INTVAR(2), vars); 158} 159 160void p_int_min(SolverInstanceBase& s, const Call* call) { 161 vec<geas::intvar> vars = {-INTVAR(0), -INTVAR(1)}; 162 geas::int_max(SD, -INTVAR(2), vars); 163} 164 165void p_int_lin_eq(SolverInstanceBase& s, const Call* call) { 166 vec<int> pos = INTARRAY(0); 167 vec<int> neg(pos.size()); 168 for (int i = 0; i < neg.size(); ++i) { 169 neg[i] = -pos[i]; 170 } 171 vec<geas::intvar> vars = INTVARARRAY(1); 172 // TODO: Rewrite using MiniZinc Library?? 173 geas::linear_le(SD, pos, vars, INT(2)); 174 geas::linear_le(SD, neg, vars, -INT(2)); 175} 176 177void p_int_lin_ne(SolverInstanceBase& s, const Call* call) { 178 vec<int> cons = INTARRAY(0); 179 vec<geas::intvar> vars = INTVARARRAY(1); 180 geas::linear_ne(SD, cons, vars, INT(2)); 181} 182 183void p_int_lin_le(SolverInstanceBase& s, const Call* call) { 184 vec<int> cons = INTARRAY(0); 185 vec<geas::intvar> vars = INTVARARRAY(1); 186 geas::linear_le(SD, cons, vars, INT(2)); 187} 188 189void p_int_lin_eq_imp(SolverInstanceBase& s, const Call* call) { 190 vec<int> pos = INTARRAY(0); 191 vec<int> neg(pos.size()); 192 for (int i = 0; i < neg.size(); ++i) { 193 neg[i] = -pos[i]; 194 } 195 vec<geas::intvar> vars = INTVARARRAY(1); 196 // TODO: Rewrite using MiniZinc Library?? 197 geas::linear_le(SD, pos, vars, INT(2), BOOLVAR(3)); 198 geas::linear_le(SD, neg, vars, -INT(2), BOOLVAR(3)); 199} 200 201void p_int_lin_ne_imp(SolverInstanceBase& s, const Call* call) { 202 vec<int> cons = INTARRAY(0); 203 vec<geas::intvar> vars = INTVARARRAY(1); 204 geas::linear_ne(SD, cons, vars, INT(2), BOOLVAR(3)); 205} 206 207void p_int_lin_le_imp(SolverInstanceBase& s, const Call* call) { 208 vec<int> cons = INTARRAY(0); 209 vec<geas::intvar> vars = INTVARARRAY(1); 210 geas::linear_le(SD, cons, vars, INT(2), BOOLVAR(3)); 211} 212 213void p_int_lin_eq_reif(SolverInstanceBase& s, const Call* call) { 214 vec<int> pos = INTARRAY(0); 215 vec<int> neg(pos.size()); 216 for (int i = 0; i < neg.size(); ++i) { 217 neg[i] = -pos[i]; 218 } 219 vec<geas::intvar> vars = INTVARARRAY(1); 220 // TODO: Rewrite using MiniZinc Library?? 221 geas::linear_le(SD, pos, vars, INT(2), BOOLVAR(3)); 222 geas::linear_le(SD, neg, vars, -INT(2), BOOLVAR(3)); 223 geas::linear_ne(SD, pos, vars, INT(2), ~BOOLVAR(3)); 224} 225 226void p_int_lin_ne_reif(SolverInstanceBase& s, const Call* call) { 227 vec<int> pos = INTARRAY(0); 228 vec<int> neg(pos.size()); 229 for (int i = 0; i < neg.size(); ++i) { 230 neg[i] = -pos[i]; 231 } 232 vec<geas::intvar> vars = INTVARARRAY(1); 233 // TODO: Rewrite using MiniZinc Library?? 234 geas::linear_ne(SD, pos, vars, INT(2), BOOLVAR(3)); 235 geas::linear_le(SD, pos, vars, INT(2), ~BOOLVAR(3)); 236 geas::linear_le(SD, neg, vars, -INT(2), ~BOOLVAR(3)); 237} 238 239void p_int_lin_le_reif(SolverInstanceBase& s, const Call* call) { 240 vec<int> pos = INTARRAY(0); 241 vec<int> neg(pos.size()); 242 for (int i = 0; i < neg.size(); ++i) { 243 neg[i] = -pos[i]; 244 } 245 vec<geas::intvar> vars = INTVARARRAY(1); 246 geas::linear_le(SD, pos, vars, INT(2), BOOLVAR(3)); 247 geas::linear_le(SD, neg, vars, -INT(2) - 1, ~BOOLVAR(3)); 248} 249 250void p_bool_eq(SolverInstanceBase& s, const Call* call) { 251 if (PAR(0)) { 252 SOL.post(BOOL(0) ? BOOLVAR(1) : ~BOOLVAR(1)); 253 } else if (PAR(2)) { 254 SOL.post(BOOL(1) ? BOOLVAR(0) : ~BOOLVAR(0)); 255 } else { 256 geas::add_clause(SD, BOOLVAR(0), ~BOOLVAR(1)); 257 geas::add_clause(SD, ~BOOLVAR(0), BOOLVAR(1)); 258 } 259} 260 261void p_bool_ne(SolverInstanceBase& s, const Call* call) { 262 if (PAR(0)) { 263 SOL.post(BOOL(0) ? ~BOOLVAR(1) : BOOLVAR(1)); 264 } else if (PAR(1)) { 265 SOL.post(BOOL(1) ? ~BOOLVAR(0) : BOOLVAR(0)); 266 } else { 267 geas::add_clause(SD, BOOLVAR(0), BOOLVAR(1)); 268 geas::add_clause(SD, ~BOOLVAR(0), ~BOOLVAR(1)); 269 } 270} 271 272void p_bool_le(SolverInstanceBase& s, const Call* call) { 273 if (PAR(0)) { 274 if (BOOL(0)) { 275 SOL.post(BOOLVAR(1)); 276 } 277 } else if (PAR(1)) { 278 if (!BOOL(1)) { 279 SOL.post(~BOOLVAR(0)); 280 } 281 } else { 282 geas::add_clause(SD, ~BOOLVAR(0), BOOLVAR(1)); 283 } 284} 285 286void p_bool_lt(SolverInstanceBase& s, const Call* call) { 287 SOL.post(~BOOLVAR(0)); 288 SOL.post(BOOLVAR(1)); 289} 290 291void p_bool_eq_imp(SolverInstanceBase& s, const Call* call) { 292 if (PAR(2)) { 293 if (BOOL(2)) { 294 p_bool_eq(s, call); 295 } 296 } else { 297 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0), BOOLVAR(1)); 298 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0), ~BOOLVAR(1)); 299 } 300} 301 302void p_bool_ne_imp(SolverInstanceBase& s, const Call* call) { 303 if (PAR(2)) { 304 if (BOOL(2)) { 305 p_bool_ne(s, call); 306 } 307 } else { 308 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0), BOOLVAR(1)); 309 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0), ~BOOLVAR(1)); 310 } 311} 312 313void p_bool_le_imp(SolverInstanceBase& s, const Call* call) { 314 if (PAR(2)) { 315 if (BOOL(2)) { 316 p_bool_le(s, call); 317 } 318 } else { 319 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0), BOOLVAR(1)); 320 } 321} 322 323void p_bool_lt_imp(SolverInstanceBase& s, const Call* call) { 324 if (PAR(2)) { 325 if (BOOL(2)) { 326 p_bool_lt(s, call); 327 } 328 } else { 329 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0)); 330 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(1)); 331 } 332} 333 334void p_bool_eq_reif(SolverInstanceBase& s, const Call* call) { 335 if (PAR(2)) { 336 if (BOOL(2)) { 337 p_bool_eq(s, call); 338 } else { 339 p_bool_ne(s, call); 340 } 341 } else { 342 geas::add_clause(SD, BOOLVAR(2), BOOLVAR(0), BOOLVAR(1)); 343 geas::add_clause(SD, BOOLVAR(2), ~BOOLVAR(0), ~BOOLVAR(1)); 344 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0), BOOLVAR(1)); 345 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0), ~BOOLVAR(1)); 346 } 347} 348 349void p_bool_ne_reif(SolverInstanceBase& s, const Call* call) { 350 if (PAR(2)) { 351 if (BOOL(2)) { 352 p_bool_ne(s, call); 353 } else { 354 p_bool_eq(s, call); 355 } 356 } else { 357 geas::add_clause(SD, BOOLVAR(2), ~BOOLVAR(0), BOOLVAR(1)); 358 geas::add_clause(SD, BOOLVAR(2), BOOLVAR(0), ~BOOLVAR(1)); 359 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0), BOOLVAR(1)); 360 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0), ~BOOLVAR(1)); 361 } 362} 363 364void p_bool_le_reif(SolverInstanceBase& s, const Call* call) { 365 if (PAR(2)) { 366 if (BOOL(2)) { 367 p_bool_le(s, call); 368 } else { 369 auto* nc = new Call(Location().introduce(), call->id(), {call->arg(1), call->arg(0)}); 370 p_bool_lt(s, nc); 371 } 372 } else { 373 geas::add_clause(SD, BOOLVAR(2), ~BOOLVAR(1)); 374 geas::add_clause(SD, BOOLVAR(2), BOOLVAR(0)); 375 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0), BOOLVAR(1)); 376 } 377} 378 379void p_bool_lt_reif(SolverInstanceBase& s, const Call* call) { 380 if (PAR(2)) { 381 if (BOOL(2)) { 382 p_int_lt(s, call); 383 } else { 384 auto* nc = new Call(Location().introduce(), call->id(), {call->arg(1), call->arg(0)}); 385 p_int_le(s, nc); 386 } 387 } else { 388 geas::add_clause(SD, ~BOOLVAR(2), ~BOOLVAR(0)); 389 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(1)); 390 geas::add_clause(SD, BOOLVAR(2), BOOLVAR(0), ~BOOLVAR(1)); 391 } 392} 393 394void p_bool_or(SolverInstanceBase& s, const Call* call) { 395 geas::add_clause(SD, BOOLVAR(2), ~BOOLVAR(0)); 396 geas::add_clause(SD, BOOLVAR(2), ~BOOLVAR(1)); 397 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0), BOOLVAR(1)); 398} 399 400void p_bool_and(SolverInstanceBase& s, const Call* call) { 401 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0)); 402 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(1)); 403 geas::add_clause(SD, BOOLVAR(2), ~BOOLVAR(0), ~BOOLVAR(1)); 404} 405 406void p_bool_xor(SolverInstanceBase& s, const Call* call) { 407 if (call->argCount() == 2) { 408 p_bool_ne(s, call); 409 } else { 410 p_bool_ne_reif(s, call); 411 } 412} 413 414void p_bool_not(SolverInstanceBase& s, const Call* call) { p_bool_ne(s, call); } 415 416void p_bool_or_imp(SolverInstanceBase& s, const Call* call) { 417 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0), BOOLVAR(1)); 418} 419 420void p_bool_and_imp(SolverInstanceBase& s, const Call* call) { 421 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(0)); 422 geas::add_clause(SD, ~BOOLVAR(2), BOOLVAR(1)); 423} 424 425void p_bool_xor_imp(SolverInstanceBase& s, const Call* call) { p_bool_ne_imp(s, call); } 426 427void p_bool_clause(SolverInstanceBase& s, const Call* call) { 428 auto& gi = static_cast<GeasSolverInstance&>(s); 429 auto* pos = ARRAY(0); 430 auto* neg = ARRAY(1); 431 vec<geas::clause_elt> clause; 432 for (int i = 0; i < pos->size(); ++i) { 433 clause.push(SI.asBoolVar((*pos)[i])); 434 } 435 for (int j = 0; j < neg->size(); ++j) { 436 clause.push(~SI.asBoolVar((*neg)[j])); 437 } 438 geas::add_clause(*SD, clause); 439} 440 441void p_array_bool_or(SolverInstanceBase& s, const Call* call) { 442 auto* arr = ARRAY(0); 443 vec<geas::clause_elt> clause; 444 clause.push(~BOOLVAR(1)); 445 for (int i = 0; i < arr->size(); ++i) { 446 geas::patom_t elem = SI.asBoolVar((*arr)[i]); 447 geas::add_clause(SD, BOOLVAR(1), ~elem); 448 clause.push(elem); 449 } 450 geas::add_clause(*SD, clause); 451} 452 453void p_array_bool_and(SolverInstanceBase& s, const Call* call) { 454 auto* arr = ARRAY(0); 455 vec<geas::clause_elt> clause; 456 clause.push(BOOLVAR(1)); 457 for (int i = 0; i < arr->size(); ++i) { 458 geas::patom_t elem = SI.asBoolVar((*arr)[i]); 459 geas::add_clause(SD, ~BOOLVAR(1), elem); 460 clause.push(~elem); 461 } 462 geas::add_clause(*SD, clause); 463} 464 465void p_bool_clause_imp(SolverInstanceBase& s, const Call* call) { 466 auto* pos = ARRAY(0); 467 auto* neg = ARRAY(1); 468 vec<geas::clause_elt> clause; 469 clause.push(~BOOLVAR(2)); 470 for (int i = 0; i < pos->size(); ++i) { 471 clause.push(SI.asBoolVar((*pos)[i])); 472 } 473 for (int j = 0; j < neg->size(); ++j) { 474 clause.push(~SI.asBoolVar((*neg)[j])); 475 } 476 geas::add_clause(*SD, clause); 477} 478 479void p_array_bool_or_imp(SolverInstanceBase& s, const Call* call) { 480 auto* arr = ARRAY(0); 481 vec<geas::clause_elt> clause; 482 clause.push(~BOOLVAR(1)); 483 for (int i = 0; i < arr->size(); ++i) { 484 geas::patom_t elem = SI.asBoolVar((*arr)[i]); 485 clause.push(elem); 486 } 487 geas::add_clause(*SD, clause); 488} 489 490void p_array_bool_and_imp(SolverInstanceBase& s, const Call* call) { 491 auto* arr = ARRAY(0); 492 for (int i = 0; i < arr->size(); ++i) { 493 geas::add_clause(SD, ~BOOLVAR(1), SI.asBoolVar((*arr)[i])); 494 } 495} 496 497void p_bool_clause_reif(SolverInstanceBase& s, const Call* call) { 498 auto* pos = ARRAY(0); 499 auto* neg = ARRAY(1); 500 vec<geas::clause_elt> clause; 501 clause.push(~BOOLVAR(2)); 502 for (int i = 0; i < pos->size(); ++i) { 503 geas::patom_t elem = SI.asBoolVar((*pos)[i]); 504 geas::add_clause(SD, BOOLVAR(2), ~elem); 505 clause.push(elem); 506 } 507 for (int j = 0; j < neg->size(); ++j) { 508 geas::patom_t elem = SI.asBoolVar((*neg)[j]); 509 geas::add_clause(SD, BOOLVAR(2), elem); 510 clause.push(~elem); 511 } 512 geas::add_clause(*SD, clause); 513} 514 515void p_bool_lin_eq(SolverInstanceBase& s, const Call* call) { 516 vec<int> cons = INTARRAY(0); 517 vec<geas::patom_t> vars = BOOLVARARRAY(1); 518 // TODO: Rewrite using MiniZinc Library?? 519 geas::bool_linear_le(SD, geas::at_True, SI.zero, cons, vars, -INT(2)); 520 geas::bool_linear_ge(SD, geas::at_True, SI.zero, cons, vars, -INT(2)); 521} 522 523void p_bool_lin_ne(SolverInstanceBase& s, const Call* call) { 524 vec<int> cons = INTARRAY(0); 525 vec<geas::patom_t> vars = BOOLVARARRAY(1); 526 geas::bool_linear_ne(SD, cons, vars, INT(2)); 527} 528 529void p_bool_lin_le(SolverInstanceBase& s, const Call* call) { 530 vec<int> cons = INTARRAY(0); 531 vec<geas::patom_t> vars = BOOLVARARRAY(1); 532 geas::bool_linear_ge(SD, geas::at_True, SI.zero, cons, vars, -INT(2)); 533} 534 535void p_bool_lin_eq_imp(SolverInstanceBase& s, const Call* call) { 536 vec<int> cons = INTARRAY(0); 537 vec<geas::patom_t> vars = BOOLVARARRAY(1); 538 // TODO: Rewrite using MiniZinc Library?? 539 geas::bool_linear_le(SD, BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 540 geas::bool_linear_ge(SD, BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 541} 542 543void p_bool_lin_ne_imp(SolverInstanceBase& s, const Call* call) { 544 vec<int> cons = INTARRAY(0); 545 vec<geas::patom_t> vars = BOOLVARARRAY(1); 546 geas::bool_linear_ne(SD, cons, vars, INT(2), BOOLVAR(3)); 547} 548 549void p_bool_lin_le_imp(SolverInstanceBase& s, const Call* call) { 550 vec<int> cons = INTARRAY(0); 551 vec<geas::patom_t> vars = BOOLVARARRAY(1); 552 geas::bool_linear_ge(SD, BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 553} 554 555void p_bool_lin_eq_reif(SolverInstanceBase& s, const Call* call) { 556 vec<int> cons = INTARRAY(0); 557 vec<geas::patom_t> vars = BOOLVARARRAY(1); 558 // TODO: Rewrite using MiniZinc Library?? 559 geas::bool_linear_le(SD, BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 560 geas::bool_linear_ge(SD, BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 561 geas::bool_linear_ne(SD, cons, vars, INT(2), ~BOOLVAR(3)); 562} 563 564void p_bool_lin_ne_reif(SolverInstanceBase& s, const Call* call) { 565 vec<int> cons = INTARRAY(0); 566 vec<geas::patom_t> vars = BOOLVARARRAY(1); 567 // TODO: Rewrite using MiniZinc Library?? 568 geas::bool_linear_ne(SD, cons, vars, INT(2), BOOLVAR(3)); 569 geas::bool_linear_le(SD, ~BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 570 geas::bool_linear_ge(SD, ~BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 571} 572 573void p_bool_lin_le_reif(SolverInstanceBase& s, const Call* call) { 574 vec<int> cons = INTARRAY(0); 575 vec<geas::patom_t> vars = BOOLVARARRAY(1); 576 // TODO: Rewrite using MiniZinc Library?? 577 geas::bool_linear_ge(SD, BOOLVAR(3), SI.zero, cons, vars, -INT(2)); 578 geas::bool_linear_le(SD, ~BOOLVAR(3), SI.zero, cons, vars, -INT(2) - 1); 579} 580 581void p_bool2int(SolverInstanceBase& s, const Call* call) { 582 geas::add_clause(SD, BOOLVAR(0), INTVAR(1) <= 0); 583 geas::add_clause(SD, ~BOOLVAR(0), INTVAR(1) >= 1); 584} 585 586void p_array_int_element(SolverInstanceBase& s, const Call* call) { 587 assert(ARRAY(1)->min(0) == 1 && ARRAY(1)->max(0) == ARRAY(1)->size() + 1); 588 vec<int> vals = INTARRAY(1); 589 if (PAR(0)) { 590 SOL.post(INTVAR(2) == vals[INT(0) - 1]); 591 } else if (PAR(2)) { 592 for (int j = 0; j < vals.size(); ++j) { 593 if (vals[j] != INT(2)) { 594 SOL.post(INTVAR(0) != j + 1); 595 } 596 } 597 } else { 598 geas::int_element(SD, INTVAR(2), INTVAR(0), vals); 599 } 600} 601 602void p_array_bool_element(SolverInstanceBase& s, const Call* call) { 603 assert(ARRAY(1)->min(0) == 1 && ARRAY(1)->max(0) == ARRAY(1)->size() + 1); 604 vec<bool> vals = BOOLARRAY(1); 605 if (PAR(0)) { 606 SOL.post(vals[INT(0) - 1] ? BOOLVAR(2) : ~BOOLVAR(2)); 607 } else if (PAR(2)) { 608 for (int j = 0; j < vals.size(); ++j) { 609 if (static_cast<int>(vals[j]) != BOOL(2)) { 610 SOL.post(INTVAR(0) != j + 1); 611 } 612 } 613 } else { 614 for (int j = 0; j < vals.size(); ++j) { 615 geas::add_clause(SD, INTVAR(0) != j + 1, vals[j] ? BOOLVAR(2) : ~BOOLVAR(2)); 616 } 617 } 618} 619 620void p_array_var_int_element(SolverInstanceBase& s, const Call* call) { 621 assert(ARRAY(1)->min(0) == 1 && ARRAY(1)->max(0) == ARRAY(1)->size() + 1); 622 if (PAR(1)) { 623 return p_array_int_element(s, call); 624 } 625 if (PAR(0) && PAR(2)) { 626 SOL.post(SI.asIntVar((*ARRAY(1))[INT(0) - 1]) == INT(2)); 627 } else if (PAR(0)) { 628 Expression* elem = (*ARRAY(1))[INT(0) - 1]; 629 if (elem->type().isPar()) { 630 return p_array_int_element(s, call); 631 } 632 geas::int_eq(SD, SI.asIntVar(elem), INTVAR(2)); 633 634 } else if (PAR(2)) { 635 for (int j = 0; j < ARRAY(1)->size(); ++j) { 636 Expression* elem = (*ARRAY(1))[j]; 637 if (elem->type().isvar()) { 638 geas::add_clause(SD, INTVAR(0) != j + 1, SI.asIntVar(elem) == INT(2)); 639 } else { 640 if (SI.asInt(elem) != INT(2)) { 641 SOL.post(INTVAR(0) != j + 1); 642 } 643 } 644 } 645 } else { 646 vec<geas::intvar> vals = INTVARARRAY(1); 647 geas::var_int_element(SD, INTVAR(2), INTVAR(0), vals); 648 } 649} 650 651void p_array_var_bool_element(SolverInstanceBase& s, const Call* call) { 652 assert(ARRAY(1)->min(0) == 1 && ARRAY(1)->max(0) == ARRAY(1)->size() + 1); 653 if (PAR(1)) { 654 return p_array_bool_element(s, call); 655 } 656 if (PAR(0) && PAR(2)) { 657 SOL.post(BOOL(2) ? SI.asBoolVar((*ARRAY(1))[INT(0) - 1]) 658 : ~SI.asBoolVar((*ARRAY(1))[INT(0) - 1])); 659 } else if (PAR(0)) { 660 Expression* elem = (*ARRAY(1))[INT(0) - 1]; 661 if (elem->type().isPar()) { 662 return p_array_bool_element(s, call); 663 } 664 geas::add_clause(SD, BOOLVAR(2), ~SI.asBoolVar(elem)); 665 geas::add_clause(SD, ~BOOLVAR(2), SI.asBoolVar(elem)); 666 667 } else if (PAR(2)) { 668 for (int j = 0; j < ARRAY(1)->size(); ++j) { 669 Expression* elem = (*ARRAY(1))[j]; 670 if (elem->type().isvar()) { 671 geas::add_clause(SD, INTVAR(0) != j + 1, INT(2) ? SI.asBoolVar(elem) : ~SI.asBoolVar(elem)); 672 } else { 673 if (SI.asBool(elem) != INT(2)) { 674 SOL.post(INTVAR(0) != j + 1); 675 } 676 } 677 } 678 } else { 679 auto vars = BOOLVARARRAY(1); 680 for (int j = 0; j < vars.size(); ++j) { 681 geas::add_clause(SD, INTVAR(0) != j + 1, ~vars[j], BOOLVAR(2)); 682 geas::add_clause(SD, INTVAR(0) != j + 1, vars[j], ~BOOLVAR(2)); 683 } 684 } 685} 686 687void p_all_different(SolverInstanceBase& s, const Call* call) { 688 vec<geas::intvar> vars = INTVARARRAY(0); 689 geas::all_different_int(SD, vars); 690} 691 692void p_all_different_except_0(SolverInstanceBase& s, const Call* call) { 693 vec<geas::intvar> vars = INTVARARRAY(0); 694 geas::all_different_except_0(SD, vars); 695} 696 697void p_at_most(SolverInstanceBase& s, const Call* call) { 698 vec<geas::intvar> ivars = INTVARARRAY(1); 699 vec<geas::patom_t> bvars; 700 for (auto& ivar : ivars) { 701 bvars.push(ivar == INT(2)); 702 } 703 704 if (INT(0) == 1) { 705 geas::atmost_1(SD, bvars); 706 } else { 707 geas::atmost_k(SD, bvars, INT(0)); 708 } 709} 710 711void p_at_most1(SolverInstanceBase& s, const Call* call) { 712 vec<geas::intvar> ivars = INTVARARRAY(0); 713 vec<geas::patom_t> bvars; 714 for (auto& ivar : ivars) { 715 bvars.push(ivar == INT(1)); 716 } 717 geas::atmost_1(SD, bvars); 718} 719 720void p_cumulative(SolverInstanceBase& s, const Call* call) { 721 vec<geas::intvar> st = INTVARARRAY(0); 722 if (PAR(1) && PAR(2) && PAR(3)) { 723 vec<int> d = INTARRAY(1); 724 vec<int> r = INTARRAY(2); 725 geas::cumulative(SD, st, d, r, INT(3)); 726 } else { 727 vec<geas::intvar> d = INTVARARRAY(1); 728 vec<geas::intvar> r = INTVARARRAY(2); 729 geas::cumulative_var(SD, st, d, r, INTVAR(3)); 730 } 731} 732 733void p_disjunctive(SolverInstanceBase& s, const Call* call) { 734 vec<geas::intvar> st = INTVARARRAY(0); 735 if (PAR(1)) { 736 vec<int> d = INTARRAY(1); 737 geas::disjunctive_int(SD, st, d); 738 } else { 739 vec<geas::intvar> d = INTVARARRAY(1); 740 geas::disjunctive_var(SD, st, d); 741 } 742} 743 744void p_global_cardinality(SolverInstanceBase& s, const Call* call) { 745 vec<geas::intvar> x = INTVARARRAY(0); 746 vec<int> cover = INTARRAY(1); 747 vec<int> count = INTARRAY(2); 748 749 vec<int> srcs(x.size(), 1); 750 vec<geas::bflow> flows; 751 for (int i = 0; i < x.size(); ++i) { 752 for (int j = 0; j < cover.size(); ++j) { 753 if (x[i].lb(SD) <= cover[j] && cover[j] <= x[i].ub(SD)) { 754 flows.push({i, j, x[i] == cover[j]}); 755 } 756 } 757 } 758 geas::bipartite_flow(SD, srcs, count, flows); 759} 760 761void p_table_int(SolverInstanceBase& s, const Call* call) { 762 auto& gi = static_cast<GeasSolverInstance&>(s); 763 vec<geas::intvar> vars = INTVARARRAY(0); 764 vec<int> tmp = INTARRAY(1); 765 assert(tmp.size() % vars.size() == 0); 766 vec<vec<int>> table(tmp.size() == 0 ? 0 : tmp.size() / vars.size()); 767 for (int i = 0; i < table.size(); ++i) { 768 table[i].growTo(vars.size()); 769 for (int j = 0; j < vars.size(); ++j) { 770 table[i][j] = tmp[i * vars.size() + j]; 771 } 772 } 773 geas::table_id id = geas::table::build(SD, table); 774 // TODO: Annotations for table versions 775 geas::table::post(SD, id, vars); 776} 777 778} // namespace GeasConstraints 779} // namespace MiniZinc 780 781#pragma clang diagnostic pop