initial support for 'keep'
This commit is contained in:
parent
696e0e91e7
commit
8aa813d342
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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).
|
||||
|
Reference in New Issue
Block a user