initial support for 'keep'

This commit is contained in:
Denys Duchier 2011-12-03 23:31:28 +01:00
parent 696e0e91e7
commit 8aa813d342
3 changed files with 242 additions and 61 deletions

View File

@ -41,14 +41,17 @@ namespace generic_gecode
Optimizing(): num(-1), den(-1), what(OPT_NONE), how(OPT_MAX) {} Optimizing(): num(-1), den(-1), what(OPT_NONE), how(OPT_MAX) {}
Optimizing(Optimizing& o) Optimizing(Optimizing& o)
: num(o.num), den(o.den), what(o.what), how(o.how) {} : num(o.num), den(o.den), what(o.what), how(o.how) {}
void check_ok() const
{ if (what!=OPT_NONE)
throw Exception("gecode-python","too many optimization criteria"); }
void maximize(int i) void maximize(int i)
{ what = OPT_INT; how = OPT_MAX; num = i; }; { check_ok(); what = OPT_INT; how = OPT_MAX; num = i; };
void maximize(int i,int j) void maximize(int i,int j)
{ what = OPT_RATIO; how = OPT_MAX; num = i; den = j; }; { check_ok(); what = OPT_RATIO; how = OPT_MAX; num = i; den = j; };
void minimize(int i) void minimize(int i)
{ what = OPT_INT; how = OPT_MIN; num = i; }; { check_ok(); what = OPT_INT; how = OPT_MIN; num = i; };
void minimize(int i,int j) void minimize(int i,int j)
{ what = OPT_RATIO; how = OPT_MIN; num = i; den = j; }; { check_ok(); what = OPT_RATIO; how = OPT_MIN; num = i; den = j; };
}; };
struct GenericSpace; struct GenericSpace;
@ -80,21 +83,106 @@ namespace generic_gecode
virtual GenericSpace* next(void) { return engine.next(); } virtual GenericSpace* next(void) { return engine.next(); }
}; };
struct LoadingDock
{
vector<IntVar> ivars;
vector<BoolVar> bvars;
vector<SetVar> svars;
vector<int> ikeep;
vector<int> bkeep;
vector<int> skeep;
bool keeping_some() const
{
return (ikeep.size() != 0)
|| (bkeep.size() != 0)
|| (skeep.size() != 0);
}
IntVar get_ivar(int i) const { return ivars[i]; }
BoolVar get_bvar(int i) const { return bvars[i]; }
SetVar get_svar(int i) const { return svars[i]; }
int enter_ivar(const IntVar& v)
{ ivars.push_back(v); return static_cast<int>(ivars.size()-1); }
int enter_bvar(const BoolVar& v)
{ bvars.push_back(v); return static_cast<int>(bvars.size()-1); }
int enter_svar(const SetVar& v)
{ svars.push_back(v); return static_cast<int>(svars.size()-1); }
int keep_ivar(int i) { ikeep.push_back(i); return static_cast<int>(ikeep.size()-1); }
int keep_bvar(int i) { bkeep.push_back(i); return static_cast<int>(bkeep.size()-1); }
int keep_svar(int i) { skeep.push_back(i); return static_cast<int>(skeep.size()-1); }
void freeze(Space& home,
IntVarArray& iarr, BoolVarArray& barr, SetVarArray& sarr,
int& num, int& den)
{
if (keeping_some())
{
// make sure that optimization vars (if any) are kept
if (num != -1)
{
const int _num(num);
const int _den(den);
int n = static_cast<int>(ikeep.size());
bool num_found(false);
bool den_found(false);
for (;n--;)
{
const int idx(ikeep[n]);
if (idx==_num)
{ num_found=true; if (den_found) break; }
if (idx==_den)
{ den_found=true; if (num_found) break; }
}
if (!num_found)
{ ikeep.push_back(_num);
num=static_cast<int>(ikeep.size()-1); }
if (_den != -1 && !den_found)
{ ikeep.push_back(_den);
den=static_cast<int>(ikeep.size()-1); }
}
{ int n = static_cast<int>(ikeep.size());
iarr = IntVarArray(home, n);
for (;n--;) iarr[n]=ivars[ikeep[n]]; }
{ int n = static_cast<int>(bkeep.size());
barr = BoolVarArray(home, n);
for (;n--;) barr[n]=bvars[bkeep[n]]; }
{ int n = static_cast<int>(skeep.size());
sarr = SetVarArray(home, n);
for (;n--;) sarr[n]=svars[skeep[n]]; }
}
else
{
{ int n = static_cast<int>(ivars.size());
iarr = IntVarArray(home, n);
for (;n--;) iarr[n]=ivars[n]; }
{ int n = static_cast<int>(bvars.size());
barr = BoolVarArray(home, n);
for (;n--;) barr[n]=bvars[n]; }
{ int n = static_cast<int>(svars.size());
sarr = SetVarArray(home, n);
for (;n--;) sarr[n]=svars[n]; }
}
}
};
struct GenericSpace: Space struct GenericSpace: Space
{ {
Optimizing optim; Optimizing optim;
IntVarArray ivars; IntVarArray ivars;
BoolVarArray bvars; BoolVarArray bvars;
SetVarArray svars; SetVarArray svars;
vector<IntVar>* _ivars; LoadingDock* dock;
vector<BoolVar>* _bvars; bool keeping_some; // iff only SOME of the vars are kept
vector<SetVar>* _svars;
Space* space() { return this; } Space* space() { return this; }
GenericSpace(bool share, GenericSpace& s) GenericSpace(bool share, GenericSpace& s)
: Space(share, s), optim(s.optim), : Space(share, s), optim(s.optim), dock(NULL), keeping_some(s.keeping_some)
_ivars(NULL), _bvars(NULL), _svars(NULL)
{ {
ivars.update(*this, share, s.ivars); ivars.update(*this, share, s.ivars);
bvars.update(*this, share, s.bvars); bvars.update(*this, share, s.bvars);
@ -104,45 +192,53 @@ namespace generic_gecode
Space* copy(bool share) Space* copy(bool share)
{ freeze(); return new GenericSpace(share, *this); } { freeze(); return new GenericSpace(share, *this); }
GenericSpace() : _ivars(NULL), _bvars(NULL), _svars(NULL) {} GenericSpace() : dock(new LoadingDock()), keeping_some(false) {}
~GenericSpace() { delete dock; }
// throw some C++ exception on behalf of glue code
void kaboom(const char* s)
{ throw Exception("gecode-python", s); }
int ikaboom(const char* s)
{ kaboom(s); return 0; }
// freeze the space before handing it off to a search engine // freeze the space before handing it off to a search engine
void freeze() void freeze()
{ {
if (_ivars) if (dock)
{ {
int n = _ivars->size(); keeping_some = dock->keeping_some();
ivars = IntVarArray(*this, n); dock->freeze(*this, ivars, bvars, svars, optim.num, optim.den);
vector<IntVar>& v(*_ivars); delete dock;
for (; n--;) ivars[n] = v[n]; dock = NULL;
delete _ivars;
_ivars = NULL;
}
if (_bvars)
{
int n = _bvars->size();
bvars = BoolVarArray(*this, n);
vector<BoolVar>& v(*_bvars);
for (; n--;) bvars[n] = v[n];
delete _bvars;
_bvars = NULL;
}
if (_svars)
{
int n = _svars->size();
svars = SetVarArray(*this, n);
vector<SetVar>& v(*_svars);
for (; n--;) svars[n] = v[n];
delete _svars;
_svars = NULL;
} }
} }
IntVar get_ivar(int i) const { return (_ivars) ? (*_ivars)[i] : ivars[i]; } IntVar get_ivar(int i) const { return (dock)?dock->get_ivar(i):ivars[i]; }
BoolVar get_bvar(int i) const { return (_bvars) ? (*_bvars)[i] : bvars[i]; } BoolVar get_bvar(int i) const { return (dock)?dock->get_bvar(i):bvars[i]; }
SetVar get_svar(int i) const { return (_svars) ? (*_svars)[i] : svars[i]; } SetVar get_svar(int i) const { return (dock)?dock->get_svar(i):svars[i]; }
int keep_ivar(int i)
{
if (dock) return dock->keep_ivar(i);
else return ikaboom("too late to keep");
}
int keep_bvar(int i)
{
if (dock) return dock->keep_bvar(i);
else return ikaboom("too late to keep");
}
int keep_svar(int i)
{
if (dock) return dock->keep_svar(i);
else return ikaboom("too late to keep");
}
bool frozen() const { return dock==NULL; }
bool has_keepers() const { return keeping_some; }
// when frozen and has_keepers: which is just has_keepers actually
bool use_keep_index() const { return has_keepers(); }
GenericEngine* new_engine(bool restart, Search::Options& opt) GenericEngine* new_engine(bool restart, Search::Options& opt)
{ {
@ -156,10 +252,8 @@ namespace generic_gecode
int _new_ivar(IntVar& v) int _new_ivar(IntVar& v)
{ {
if (!_ivars) _ivars = new vector<IntVar>; if (dock) return dock->enter_ivar(v);
int i = _ivars->size(); else return ikaboom("too late to create vars");
_ivars->push_back(v);
return i;
} }
int new_ivar(int lo, int hi) int new_ivar(int lo, int hi)
@ -176,10 +270,8 @@ namespace generic_gecode
int _new_bvar(BoolVar& v) int _new_bvar(BoolVar& v)
{ {
if (!_bvars) _bvars = new vector<BoolVar>; if (dock) return dock->enter_bvar(v);
int i = _bvars->size(); else return ikaboom("too late to create vars");
_bvars->push_back(v);
return i;
} }
int new_bvar() int new_bvar()
@ -190,10 +282,8 @@ namespace generic_gecode
int _new_svar(SetVar& v) int _new_svar(SetVar& v)
{ {
if (!_svars) _svars = new vector<SetVar>; if (dock) return dock->enter_svar(v);
int i = _svars->size(); else return ikaboom("too late to create vars");
_svars->push_back(v);
return i;
} }
int new_svar(int glbMin, int glbMax, int lubMin, int lubMax, int new_svar(int glbMin, int glbMax, int lubMin, int lubMax,

View File

@ -651,6 +651,48 @@ extern "C"
cerr << "this should never happen" << endl; exit(1); cerr << "this should never happen" << endl; exit(1);
} }
static int gecode_space_use_keep_index(void)
{
YAP_Term arg1 = YAP_ARG1;
YAP_Term arg2 = YAP_ARG2;
GenericSpace* space = gecode_Space_from_term(arg1);
return YAP_Unify(arg2,(space->use_keep_index()
?gecode_TRUE:gecode_FALSE));
}
static int gecode_intvar_keep(void)
{
YAP_Term arg1 = YAP_ARG1;
YAP_Term arg2 = YAP_ARG2;
YAP_Term arg3 = YAP_ARG3;
GenericSpace* space = gecode_Space_from_term(arg1);
int idx = YAP_IntOfTerm(arg2);
int kidx = space->keep_ivar(idx);
return YAP_Unify(arg3,YAP_MkIntTerm(kidx));
}
static int gecode_boolvar_keep(void)
{
YAP_Term arg1 = YAP_ARG1;
YAP_Term arg2 = YAP_ARG2;
YAP_Term arg3 = YAP_ARG3;
GenericSpace* space = gecode_Space_from_term(arg1);
int idx = YAP_IntOfTerm(arg2);
int kidx = space->keep_bvar(idx);
return YAP_Unify(arg3,YAP_MkIntTerm(kidx));
}
static int gecode_setvar_keep(void)
{
YAP_Term arg1 = YAP_ARG1;
YAP_Term arg2 = YAP_ARG2;
YAP_Term arg3 = YAP_ARG3;
GenericSpace* space = gecode_Space_from_term(arg1);
int idx = YAP_IntOfTerm(arg2);
int kidx = space->keep_svar(idx);
return YAP_Unify(arg3,YAP_MkIntTerm(kidx));
}
// INFO ON INTVARS // INFO ON INTVARS
static int gecode_intvar_assigned(void) static int gecode_intvar_assigned(void)
{ {
@ -1133,5 +1175,9 @@ extern "C"
YAP_UserCPredicate("gecode_setvar_glb_values", gecode_setvar_glb_values, 3); YAP_UserCPredicate("gecode_setvar_glb_values", gecode_setvar_glb_values, 3);
YAP_UserCPredicate("gecode_setvar_lub_values", gecode_setvar_lub_values, 3); YAP_UserCPredicate("gecode_setvar_lub_values", gecode_setvar_lub_values, 3);
YAP_UserCPredicate("gecode_setvar_unknown_values", gecode_setvar_unknown_values, 3); YAP_UserCPredicate("gecode_setvar_unknown_values", gecode_setvar_unknown_values, 3);
YAP_UserCPredicate("gecode_space_use_keep_index", gecode_space_use_keep_index, 2);
YAP_UserCPredicate("gecode_intvar_keep", gecode_intvar_keep, 3);
YAP_UserCPredicate("gecode_boolvar_keep", gecode_boolvar_keep, 3);
YAP_UserCPredicate("gecode_setvar_keep", gecode_setvar_keep, 3);
} }
} }

View File

@ -31,9 +31,21 @@ is_bool_(false,false).
is_bool(X,Y) :- nonvar(X), Y=X. is_bool(X,Y) :- nonvar(X), Y=X.
is_bool(X) :- is_bool(X,_). is_bool(X) :- is_bool(X,_).
is_IntVar_('IntVar'(I),I) :- integer(I). is_IntVar_('IntVar'(I,K),N) :-
is_BoolVar_('BoolVar'(I),I) :- integer(I). integer(I),
is_SetVar_('SetVar'(I),I) :- integer(I). integer(K),
nb_getval(gecode_space_use_keep_index,B),
(B=true -> N=K ; N=I).
is_BoolVar_('BoolVar'(I,K),N) :-
integer(I),
integer(K),
nb_getval(gecode_space_use_keep_index,B),
(B=true -> N=K ; N=I).
is_SetVar_('SetVar'(I,K),N) :-
integer(I),
integer(K),
nb_getval(gecode_space_use_keep_index,B),
(B=true -> N=K ; N=I).
is_IntVar(X,I) :- nonvar(X), is_IntVar_(X,I). is_IntVar(X,I) :- nonvar(X), is_IntVar_(X,I).
is_BoolVar(X,I) :- nonvar(X), is_BoolVar_(X,I). is_BoolVar(X,I) :- nonvar(X), is_BoolVar_(X,I).
@ -142,7 +154,18 @@ new_space(Space) :-
gecode_new_space(Space_), gecode_new_space(Space_),
Space='Space'(Space_). Space='Space'(Space_).
is_Space_('Space'(X),X). %% checking that an argument is a space sets a global variable
%% indicating whether variables need to be translated to their
%% original index or to their "keep" index.
%%
%% these bindings are going to take advantage of the fact that,
%% when a space is involved, it is checked first, thus setting
%% this global variable. subsequent accesses to variables are
%% then correctly translated.
is_Space_('Space'(X),X) :-
gecode_space_use_keep_index(X,B),
nb_setval(gecode_space_use_keep_index,B).
is_Space(X,Y) :- nonvar(X), is_Space_(X,Y). is_Space(X,Y) :- nonvar(X), is_Space_(X,Y).
is_Space(X) :- is_Space(X,_). is_Space(X) :- is_Space(X,_).
@ -198,19 +221,19 @@ new_intvar(IVar, Space, Lo, Hi) :- !,
assert_integer(Lo), assert_integer(Lo),
assert_integer(Hi), assert_integer(Hi),
gecode_new_intvar_from_bounds(Idx,Space_,Lo,Hi), gecode_new_intvar_from_bounds(Idx,Space_,Lo,Hi),
IVar='IntVar'(Idx). IVar='IntVar'(Idx,-1).
new_intvar(IVar, Space, IntSet) :- !, new_intvar(IVar, Space, IntSet) :- !,
assert_var(IVar), assert_var(IVar),
assert_is_Space_or_Clause(Space,Space_), assert_is_Space_or_Clause(Space,Space_),
assert_is_IntSet(IntSet, L), assert_is_IntSet(IntSet, L),
gecode_new_intvar_from_intset(Idx,Space_,L), gecode_new_intvar_from_intset(Idx,Space_,L),
IVar='IntVar'(Idx). IVar='IntVar'(Idx,-1).
new_boolvar(BVar, Space) :- !, new_boolvar(BVar, Space) :- !,
assert_var(BVar), assert_var(BVar),
assert_is_Space_or_Clause(Space,Space_), assert_is_Space_or_Clause(Space,Space_),
gecode_new_boolvar(Idx,Space_), gecode_new_boolvar(Idx,Space_),
BVar='BoolVar'(Idx). BVar='BoolVar'(Idx,-1).
%% (GlbMin,GlbMax,LubMin,LubMax,CardMin,CardMax) 6 new_setvar_1 %% (GlbMin,GlbMax,LubMin,LubMax,CardMin,CardMax) 6 new_setvar_1
%% (GlbMin,GlbMax,LubMin,LubMax,CardMin) 5 new_setvar_2 %% (GlbMin,GlbMax,LubMin,LubMax,CardMin) 5 new_setvar_2
@ -237,7 +260,7 @@ new_setvar(SVar, Space, GlbMin, GlbMax, LubMin, LubMax, CardMin, CardMax) :-
assert_integer(CardMin), assert_integer(CardMin),
assert_integer(CardMax), assert_integer(CardMax),
gecode_new_setvar(Idx, Space_, GlbMin, GlbMax, LubMib, LubMax, CardMin, CardMax), gecode_new_setvar(Idx, Space_, GlbMin, GlbMax, LubMib, LubMax, CardMin, CardMax),
SVar='SetVar'(Idx). SVar='SetVar'(Idx,-1).
%% 5 arguments %% 5 arguments
%% (GlbMin,GlbMax,LubMin,LubMax,CardMin) 5 new_setvar_2 %% (GlbMin,GlbMax,LubMin,LubMax,CardMin) 5 new_setvar_2
@ -593,7 +616,9 @@ new_clause(X, Disj) :-
gecode_new_clause(C, Disj_), gecode_new_clause(C, Disj_),
X='Clause'(C). X='Clause'(C).
is_Clause_('Clause'(C),C). is_Clause_('Clause'(C),C) :-
gecode_space_use_keep_index(C,B),
nb_setval(gecode_space_use_keep_index,B).
is_Clause(X,Y) :- nonvar(X), is_Clause_(X,Y). is_Clause(X,Y) :- nonvar(X), is_Clause_(X,Y).
is_Clause(X) :- is_Clause(X,_). is_Clause(X) :- is_Clause(X,_).
@ -636,6 +661,24 @@ new_setvars_(L,Space,N,X1,X2,X3,X4) :- length(L,N), new_setvars(L,Space,X1,X2,X3
new_setvars_(L,Space,N,X1,X2,X3) :- length(L,N), new_setvars(L,Space,X1,X2,X3). new_setvars_(L,Space,N,X1,X2,X3) :- length(L,N), new_setvars(L,Space,X1,X2,X3).
new_setvars_(L,Space,N,X1,X2) :- length(L,N), new_setvars(L,Space,X1,X2). new_setvars_(L,Space,N,X1,X2) :- length(L,N), new_setvars(L,Space,X1,X2).
keep_(Space, Var) :-
(Var = 'IntVar'(I,J)
-> (J = -1 -> (gecode_intvar_keep(Space,I,K),setarg(2,Var,K))
; throw(gecode_error(variable_already_kept(Var))))
; (Var = 'BoolVar'(I,J)
-> (J = -1 -> (gecode_boolvar_keep(Space,I,K),setarg(2,Var,K))
; throw(gecode_error(variable_already_kept(Var))))
; (Var = 'SetVar'(I,J)
-> (J = -1 -> (gecode_setvar_keep(Space,I,K),setarg(2,Var,K))
; throw(gecode_error(variable_already_kept(Var))))
; keep_list_(Space,Var)))).
keep_list_(Space, []) :- !.
keep_list_(Space, [H|T]) :- !,
keep_(Space,H), keep_list_(Space,T).
keep_list_(_, X) :-
throw(gecode_error(not_a_variable(X))).
%% more concise interface: %% more concise interface:
(X := Y) :- var(Y), !, throw(gecode_error((X := Y))). (X := Y) :- var(Y), !, throw(gecode_error((X := Y))).
(X := intset(I,J)) :- !, new_intset(X,I,J). (X := intset(I,J)) :- !, new_intset(X,I,J).
@ -801,3 +844,5 @@ new_setvars_(L,Space,N,X1,X2) :- length(L,N), new_setvars(L,Space,X1,X2).
(Space += maximize(X)) :- !, maximize(Space,X). (Space += maximize(X)) :- !, maximize(Space,X).
(Space += minimize(X,Y)) :- !, minimize(Space,X,Y). (Space += minimize(X,Y)) :- !, minimize(Space,X,Y).
(Space += maximize(X,Y)) :- !, maximize(Space,X,Y). (Space += maximize(X,Y)) :- !, maximize(Space,X,Y).
(Space += keep(X)) :- !, keep_(Space,X).