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(Optimizing& o)
: 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)
{ what = OPT_INT; how = OPT_MAX; num = i; };
{ check_ok(); what = OPT_INT; how = OPT_MAX; num = i; };
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)
{ what = OPT_INT; how = OPT_MIN; num = i; };
{ check_ok(); what = OPT_INT; how = OPT_MIN; num = i; };
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;
@ -80,21 +83,106 @@ namespace generic_gecode
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
{
Optimizing optim;
IntVarArray ivars;
BoolVarArray bvars;
SetVarArray svars;
vector<IntVar>* _ivars;
vector<BoolVar>* _bvars;
vector<SetVar>* _svars;
LoadingDock* dock;
bool keeping_some; // iff only SOME of the vars are kept
Space* space() { return this; }
GenericSpace(bool share, GenericSpace& s)
: Space(share, s), optim(s.optim),
_ivars(NULL), _bvars(NULL), _svars(NULL)
: Space(share, s), optim(s.optim), dock(NULL), keeping_some(s.keeping_some)
{
ivars.update(*this, share, s.ivars);
bvars.update(*this, share, s.bvars);
@ -104,45 +192,53 @@ namespace generic_gecode
Space* copy(bool share)
{ 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
void freeze()
{
if (_ivars)
if (dock)
{
int n = _ivars->size();
ivars = IntVarArray(*this, n);
vector<IntVar>& v(*_ivars);
for (; n--;) ivars[n] = v[n];
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;
keeping_some = dock->keeping_some();
dock->freeze(*this, ivars, bvars, svars, optim.num, optim.den);
delete dock;
dock = NULL;
}
}
IntVar get_ivar(int i) const { return (_ivars) ? (*_ivars)[i] : ivars[i]; }
BoolVar get_bvar(int i) const { return (_bvars) ? (*_bvars)[i] : bvars[i]; }
SetVar get_svar(int i) const { return (_svars) ? (*_svars)[i] : svars[i]; }
IntVar get_ivar(int i) const { return (dock)?dock->get_ivar(i):ivars[i]; }
BoolVar get_bvar(int i) const { return (dock)?dock->get_bvar(i):bvars[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)
{
@ -156,10 +252,8 @@ namespace generic_gecode
int _new_ivar(IntVar& v)
{
if (!_ivars) _ivars = new vector<IntVar>;
int i = _ivars->size();
_ivars->push_back(v);
return i;
if (dock) return dock->enter_ivar(v);
else return ikaboom("too late to create vars");
}
int new_ivar(int lo, int hi)
@ -176,10 +270,8 @@ namespace generic_gecode
int _new_bvar(BoolVar& v)
{
if (!_bvars) _bvars = new vector<BoolVar>;
int i = _bvars->size();
_bvars->push_back(v);
return i;
if (dock) return dock->enter_bvar(v);
else return ikaboom("too late to create vars");
}
int new_bvar()
@ -190,10 +282,8 @@ namespace generic_gecode
int _new_svar(SetVar& v)
{
if (!_svars) _svars = new vector<SetVar>;
int i = _svars->size();
_svars->push_back(v);
return i;
if (dock) return dock->enter_svar(v);
else return ikaboom("too late to create vars");
}
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);
}
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
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_lub_values", gecode_setvar_lub_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) :- is_bool(X,_).
is_IntVar_('IntVar'(I),I) :- integer(I).
is_BoolVar_('BoolVar'(I),I) :- integer(I).
is_SetVar_('SetVar'(I),I) :- integer(I).
is_IntVar_('IntVar'(I,K),N) :-
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_BoolVar(X,I) :- nonvar(X), is_BoolVar_(X,I).
@ -142,7 +154,18 @@ new_space(Space) :-
gecode_new_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) :- is_Space(X,_).
@ -198,19 +221,19 @@ new_intvar(IVar, Space, Lo, Hi) :- !,
assert_integer(Lo),
assert_integer(Hi),
gecode_new_intvar_from_bounds(Idx,Space_,Lo,Hi),
IVar='IntVar'(Idx).
IVar='IntVar'(Idx,-1).
new_intvar(IVar, Space, IntSet) :- !,
assert_var(IVar),
assert_is_Space_or_Clause(Space,Space_),
assert_is_IntSet(IntSet, L),
gecode_new_intvar_from_intset(Idx,Space_,L),
IVar='IntVar'(Idx).
IVar='IntVar'(Idx,-1).
new_boolvar(BVar, Space) :- !,
assert_var(BVar),
assert_is_Space_or_Clause(Space,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) 5 new_setvar_2
@ -237,7 +260,7 @@ new_setvar(SVar, Space, GlbMin, GlbMax, LubMin, LubMax, CardMin, CardMax) :-
assert_integer(CardMin),
assert_integer(CardMax),
gecode_new_setvar(Idx, Space_, GlbMin, GlbMax, LubMib, LubMax, CardMin, CardMax),
SVar='SetVar'(Idx).
SVar='SetVar'(Idx,-1).
%% 5 arguments
%% (GlbMin,GlbMax,LubMin,LubMax,CardMin) 5 new_setvar_2
@ -593,7 +616,9 @@ new_clause(X, Disj) :-
gecode_new_clause(C, Disj_),
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) :- 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) :- 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:
(X := Y) :- var(Y), !, throw(gecode_error((X := Y))).
(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 += minimize(X,Y)) :- !, minimize(Space,X,Y).
(Space += maximize(X,Y)) :- !, maximize(Space,X,Y).
(Space += keep(X)) :- !, keep_(Space,X).