1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
Jip J. Dekker 35a3110598 Squashed 'software/chuffed/' content from commit 2ed0c015
git-subtree-dir: software/chuffed
git-subtree-split: 2ed0c01558d2a5c49c1ce57e048d32c17adf92d3
2021-06-18 09:36:35 +10:00

160 lines
3.9 KiB
C++

#include <chuffed/vars/int-var.h>
#include <chuffed/core/sat.h>
#include <chuffed/core/propagator.h>
extern std::map<IntVar*, std::string> intVarString;
IntVarSL::IntVarSL(const IntVar& other, vec<int>& _values)
: IntVar(other), values(_values) {
initVals();
// handle min, max and vals
int l = 0;
while (values[l] < min) if (++l == values.size()) TL_FAIL();
while (!vals[values[l]]) if (++l == values.size()) TL_FAIL();
min = values[l];
// printf("l = %d\n", l);
int u = values.size()-1;
while (values[u] > max) if (u-- == 0) TL_FAIL();
while (!vals[values[u]]) if (u-- == 0) TL_FAIL();
max = values[u];
// printf("u = %d\n", u);
for (int i = min, k = l; i <= max; i++) {
if (i == values[k]) { k++; continue; }
vals[i] = false;
}
for (int i = l; i <= u; i++) values[i-l] = values[i];
values.resize(u-l+1);
// for (int i = 0; i < values.size(); i++) printf("%d ", values[i]);
// printf("\n");
// create the IntVarEL
IntVar *v = newIntVar(0, values.size()-1);
// inherit the name from this SL
intVarString[v] = intVarString[this];
v->specialiseToEL();
el = (IntVarEL*) v;
// rechannel channel info
for (int i = 0; i < values.size(); i++) {
Lit p = el->getLit(i, 0);
sat.c_info[var(p)].cons_id = var_id;
}
for (int i = 0; i <= values.size(); i++) {
Lit p = el->getLit(i, 2);
sat.c_info[var(p)].cons_id = var_id;
}
// transfer pinfo to el
for (int i = 0; i < pinfo.size(); i++) {
el->pinfo.push(pinfo[i]);
}
pinfo.clear(true);
}
void IntVarSL::attach(Propagator *p, int pos, int eflags) {
if (isFixed()) p->wakeup(pos, eflags);
else el->pinfo.push(PropInfo(p, pos, eflags));
}
int IntVarSL::transform(int v, int type) {
int l = 0, u = values.size()-1, m;
while (true) {
m = (l+u)/2;
if (values[m] == v) return m;
else if (values[m] < v) l = m+1;
else u = m-1;
if (u < l) break;
}
switch (type) {
case 0: return u;
case 1: return l;
case 2: return -1;
default: NEVER;
}
}
// t = 0: [x != v], t = 1: [x = v], t = 2: [x >= v], t = 3: [x <= v]
Lit IntVarSL::getLit(int64_t v, int t) {
int u;
switch (t) {
case 0:
u = transform(v, 2);
return (u == -1 ? lit_True : el->getLit(u, 0));
case 1:
u = transform(v, 2);
return (u == -1 ? lit_False : el->getLit(u, 1));
case 2: return el->getLit(transform(v, 1), 2);
case 3: return el->getLit(transform(v, 0), 3);
default: NEVER;
}
}
bool IntVarSL::setMin(int64_t v, Reason r, bool channel) {
assert(setMinNotR(v));
// debug();
// printf("setMin: v = %d, u = %d\n", v, transform(v, 0));
if (!el->setMin(transform(v, 1), r, channel)) return false;
min = values[el->min];
return true;
}
bool IntVarSL::setMax(int64_t v, Reason r, bool channel) {
assert(setMaxNotR(v));
// debug();
// printf("setMax: v = %d, u = %d\n", v, transform(v, 0));
if (!el->setMax(transform(v, 0), r, channel)) return false;
max = values[el->max];
return true;
}
bool IntVarSL::setVal(int64_t v, Reason r, bool channel) {
assert(setValNotR(v));
int u = transform(v, 2);
if (u == -1) {
if (channel) sat.cEnqueue(lit_False, r);
assert(sat.confl);
return false;
}
if (!el->setVal(u, r, channel)) return false;
if (min < v) min = v;
if (max > v) max = v;
return true;
}
bool IntVarSL::remVal(int64_t v, Reason r, bool channel) {
assert(remValNotR(v));
int u = transform(v, 2);
assert(u != -1);
if (!el->remVal(u, r, channel)) return false;
vals[v] = false;
min = values[el->min];
max = values[el->max];
return true;
}
void IntVarSL::channel(int val, int val_type, int sign) {
// fprintf(stderr, "funny channel\n");
int type = val_type * 3 ^ sign;
el->set(val, type, false);
if (type == 0) vals[values[val]] = false;
min = values[el->min];
max = values[el->max];
}
void IntVarSL::debug() {
printf("min = %d, max = %d, el->min = %d, el->max = %d\n", (int) min, (int) max, (int) el->min, (int) el->max);
for (int i = 0; i < values.size(); i++) printf("%d ", values[i]);
printf("\n");
}