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 2572df0663 Squashed 'software/gecode_base/' content from commit bbefcea214
git-subtree-dir: software/gecode_base
git-subtree-split: bbefcea214fec798a0f5acc442581984555acd21
2021-07-11 17:26:05 +10:00

919 lines
29 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main author:
* Christian Schulte <schulte@gecode.org>
*
* Copyright:
* Christian Schulte, 2012
*
* This file is part of Gecode, the generic constraint
* development environment:
* http://www.gecode.org
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
namespace Gecode {
/**
* \defgroup TaskBranchViewSel Generic view selection for brancher based on view and value selection
*
* \ingroup TaskBranchViewVal
*/
//@{
/// Abstract class for view selection
template<class View_>
class ViewSel {
public:
/// Define the view type
typedef View_ View;
/// The corresponding variable type
typedef typename View::VarType Var;
/// \name Initialization
//@{
/// Constructor for creation
ViewSel(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSel(Space& home, ViewSel<View>& vs);
//@}
/// \name View selection and tie breaking
//@{
/// Select a view from \a x starting from \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s) = 0;
/// Select a view from \a x starting from \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s,
BrancherFilter<View>& f) = 0;
/// Select a view from \a x starting from \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s,
BrancherNoFilter<View>& f);
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n) = 0;
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f) = 0;
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherNoFilter<View>& f);
/// Break ties in \a x and update to new ties
virtual void brk(Space& home, ViewArray<View>& x,
int* ties, int& n) = 0;
/// Select a view from \a x considering views with positions in \a ties
virtual int select(Space& home, ViewArray<View>& x,
int* ties, int n) = 0;
//@}
/// \name Resource management and cloning
//@{
/// Create copy during cloning
virtual ViewSel<View>* copy(Space& home) = 0;
/// Whether dispose must always be called (that is, notice is needed)
virtual bool notice(void) const;
/// Dispose view selection
virtual void dispose(Space& home);
/// Unused destructor
virtual ~ViewSel(void);
//@}
/// \name Memory management
//@{
/// Allocate memory from space
static void* operator new(size_t s, Space& home);
/// Return memory to space
static void operator delete(void* p, Space& home);
/// Needed for exceptions
static void operator delete(void* p);
//@}
};
/// Select the first unassigned view
template<class View>
class ViewSelNone : public ViewSel<View> {
protected:
typedef typename ViewSel<View>::Var Var;
public:
/// \name Initialization
//@{
/// Constructor for creation
ViewSelNone(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelNone(Space& home, ViewSelNone<View>& vs);
//@}
/// \name View selection and tie breaking
//@{
/// Select a view from \a x starting at \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s);
/// Select a view from \a x starting at \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s,
BrancherFilter<View>& f);
/// Select ties from \a x starting at \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n);
/// Select ties from \a x starting at \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f);
/// Break ties in \a x and update to new ties
virtual void brk(Space& home, ViewArray<View>& x,
int* ties, int& n);
/// Select a view from \a x considering view with positions in \a ties
virtual int select(Space& home, ViewArray<View>& x, int* ties, int n);
//@}
/// \name Resource management and cloning
//@{
/// Create copy during cloning
virtual ViewSel<View>* copy(Space& home);
//@}
};
/// Select a view randomly
template<class View>
class ViewSelRnd : public ViewSel<View> {
protected:
typedef typename ViewSel<View>::Var Var;
/// The random number generator used
Rnd r;
public:
/// \name Initialization
//@{
/// Constructor for creation
ViewSelRnd(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelRnd(Space& home, ViewSelRnd<View>& vs);
//@}
/// \name View selection and tie breaking
//@{
/// Select a view from \a x starting from \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s);
/// Select a view from \a x starting from \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s,
BrancherFilter<View>& f);
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n);
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f);
/// Break ties in \a x and update to new ties
virtual void brk(Space& home, ViewArray<View>& x, int* ties, int& n);
/// Select a view from \a x considering view with positions in \a ties
virtual int select(Space& home, ViewArray<View>& x, int* ties, int n);
//@}
/// \name Resource management and cloning
//@{
/// Create copy during cloning
virtual ViewSel<View>* copy(Space& home);
//@}
};
/// Choose views with smaller merit values
class ChooseMin {
public:
/// Return true if \a a is better than \a b
template<class Val>
bool operator ()(Val a, Val b) const;
};
/// Choose views with larger merit values
class ChooseMax {
public:
/// Return true if \a a is better than \a b
template<class Val>
bool operator ()(Val a, Val b) const;
};
/// Choose view according to merit
template<class Choose, class Merit>
class ViewSelChoose : public ViewSel<typename Merit::View> {
protected:
typedef typename ViewSel<typename Merit::View>::Var Var;
typedef typename ViewSel<typename Merit::View>::View View;
/// Type of merit
typedef typename Merit::Val Val;
/// How to choose
Choose c;
/// The merit object used
Merit m;
public:
/// \name Initialization
//@{
/// Constructor for creation
ViewSelChoose(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelChoose(Space& home, ViewSelChoose<Choose,Merit>& vs);
//@}
/// \name View selection and tie breaking
//@{
/// Select a view from \a x starting from \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s);
/// Select a view from \a x starting from \a s and return its position
virtual int select(Space& home, ViewArray<View>& x, int s,
BrancherFilter<View>& f);
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n);
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f);
/// Break ties in \a x and update to new ties
virtual void brk(Space& home, ViewArray<View>& x, int* ties, int& n);
/// Select a view from \a x considering views with positions in \a ties
virtual int select(Space& home, ViewArray<View>& x, int* ties, int n);
//@}
/// \name Resource management and cloning
//@{
/// Whether dispose must always be called (that is, notice is needed)
virtual bool notice(void) const;
/// Delete view selection
virtual void dispose(Space& home);
//@}
};
/// Choose view according to merit taking tie-break limit into account
template<class Choose, class Merit>
class ViewSelChooseTbl : public ViewSelChoose<Choose,Merit> {
protected:
typedef typename ViewSelChoose<Choose,Merit>::Val Val;
typedef typename ViewSelChoose<Choose,Merit>::View View;
typedef typename ViewSelChoose<Choose,Merit>::Var Var;
using ViewSelChoose<Choose,Merit>::c;
using ViewSelChoose<Choose,Merit>::m;
/// Tie-break limit function
SharedData<BranchTbl> tbl;
public:
/// \name Initialization
//@{
/// Constructor for initialization
ViewSelChooseTbl(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelChooseTbl(Space& home, ViewSelChooseTbl<Choose,Merit>& vs);
//@}
/// \name View selection and tie breaking
//@{
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n);
/// Select ties from \a x starting from \a s
virtual void ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f);
/// Break ties in \a x and update to new ties
virtual void brk(Space& home, ViewArray<View>& x, int* ties, int& n);
//@}
/// \name Resource management and cloning
//@{
/// Whether dispose must always be called (that is, notice is needed)
virtual bool notice(void) const;
/// Delete view selection
virtual void dispose(Space& home);
//@}
};
/// Select view with least merit
template<class Merit>
class ViewSelMin : public ViewSelChoose<ChooseMin,Merit> {
typedef typename ViewSelChoose<ChooseMin,Merit>::View View;
typedef typename ViewSelChoose<ChooseMin,Merit>::Var Var;
public:
/// \name Initialization
//@{
/// Constructor for initialization
ViewSelMin(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelMin(Space& home, ViewSelMin<Merit>& vs);
//@}
/// \name Resource management and cloning
//@{
/// Create copy during cloning
virtual ViewSel<View>* copy(Space& home);
//@}
};
/// Select view with least merit taking tie-break limit into account
template<class Merit>
class ViewSelMinTbl : public ViewSelChooseTbl<ChooseMin,Merit> {
typedef typename ViewSelChooseTbl<ChooseMin,Merit>::View View;
typedef typename ViewSelChooseTbl<ChooseMin,Merit>::Var Var;
public:
/// \name Initialization
//@{
/// Constructor for initialization
ViewSelMinTbl(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelMinTbl(Space& home, ViewSelMinTbl<Merit>& vs);
//@}
/// \name Resource management and cloning
//@{
/// Create copy during cloning
virtual ViewSel<View>* copy(Space& home);
//@}
};
/// Select view with largest merit
template<class Merit>
class ViewSelMax : public ViewSelChoose<ChooseMax,Merit> {
typedef typename ViewSelChoose<ChooseMax,Merit>::View View;
typedef typename ViewSelChoose<ChooseMax,Merit>::Var Var;
public:
/// \name Initialization
//@{
/// Constructor for initialization
ViewSelMax(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelMax(Space& home, ViewSelMax<Merit>& vs);
//@}
/// \name Resource management and cloning
//@{
/// Create copy during cloning
virtual ViewSel<View>* copy(Space& home);
//@}
};
/// Select view with largest merit taking tie-break limit into account
template<class Merit>
class ViewSelMaxTbl : public ViewSelChooseTbl<ChooseMax,Merit> {
typedef typename ViewSelChooseTbl<ChooseMax,Merit>::View View;
typedef typename ViewSelChooseTbl<ChooseMax,Merit>::Var Var;
public:
/// \name Initialization
//@{
/// Constructor for initialization
ViewSelMaxTbl(Space& home, const VarBranch<Var>& vb);
/// Constructor for copying during cloning
ViewSelMaxTbl(Space& home, ViewSelMaxTbl<Merit>& vs);
//@}
/// \name Resource management and cloning
//@{
/// Create copy during cloning
virtual ViewSel<View>* copy(Space& home);
//@}
};
//@}
template<class View>
forceinline
ViewSel<View>::ViewSel(Space&, const VarBranch<Var>&) {}
template<class View>
forceinline
ViewSel<View>::ViewSel(Space&, ViewSel<View>&) {}
template<class View>
int
ViewSel<View>::select(Space&, ViewArray<View>&, int,
BrancherNoFilter<View>&) {
GECODE_NEVER;
return 0;
}
template<class View>
void
ViewSel<View>::ties(Space&, ViewArray<View>&, int,
int*, int&,
BrancherNoFilter<View>&) {
GECODE_NEVER;
}
template<class View>
bool
ViewSel<View>::notice(void) const {
return false;
}
template<class View>
void
ViewSel<View>::dispose(Space&) {}
template<class View>
ViewSel<View>::~ViewSel(void) {}
template<class View>
forceinline void
ViewSel<View>::operator delete(void*) {}
template<class View>
forceinline void
ViewSel<View>::operator delete(void*, Space&) {}
template<class View>
forceinline void*
ViewSel<View>::operator new(size_t s, Space& home) {
return home.ralloc(s);
}
template<class View>
forceinline
ViewSelNone<View>::ViewSelNone(Space& home, const VarBranch<Var>& vb)
: ViewSel<View>(home,vb) {}
template<class View>
forceinline
ViewSelNone<View>::ViewSelNone(Space& home, ViewSelNone<View>& vs)
: ViewSel<View>(home,vs) {}
template<class View>
int
ViewSelNone<View>::select(Space&, ViewArray<View>&, int s) {
return s;
}
template<class View>
int
ViewSelNone<View>::select(Space&, ViewArray<View>&, int s,
BrancherFilter<View>&) {
return s;
}
template<class View>
void
ViewSelNone<View>::ties(Space&, ViewArray<View>& x, int s,
int* ties, int& n) {
int j=0; ties[j++]=s;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned())
ties[j++]=i;
n=j;
assert(n > 0);
}
template<class View>
void
ViewSelNone<View>::ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f) {
int j=0; ties[j++]=s;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned() && f(home,x[i],i))
ties[j++]=i;
n=j;
assert(n > 0);
}
template<class View>
void
ViewSelNone<View>::brk(Space&, ViewArray<View>&, int*, int&) {
// Nothing needs to be done
}
template<class View>
int
ViewSelNone<View>::select(Space&, ViewArray<View>&, int* ties, int) {
return ties[0];
}
template<class View>
ViewSel<View>*
ViewSelNone<View>::copy(Space& home) {
return new (home) ViewSelNone<View>(home,*this);
}
template<class View>
forceinline
ViewSelRnd<View>::ViewSelRnd(Space& home, const VarBranch<Var>& vb)
: ViewSel<View>(home,vb), r(vb.rnd()) {}
template<class View>
forceinline
ViewSelRnd<View>::ViewSelRnd(Space& home, ViewSelRnd<View>& vs)
: ViewSel<View>(home,vs), r(vs.r) {}
template<class View>
int
ViewSelRnd<View>::select(Space&, ViewArray<View>& x, int s) {
unsigned int n=1;
int j=s;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned()) {
n++;
if (r(n) == 0U)
j=i;
}
return j;
}
template<class View>
int
ViewSelRnd<View>::select(Space& home, ViewArray<View>& x, int s,
BrancherFilter<View>& f) {
unsigned int n=1;
int j=s;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned() && f(home,x[i],i)) {
n++;
if (r(n) == 0U)
j=i;
}
return j;
}
template<class View>
void
ViewSelRnd<View>::ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n) {
n=1; ties[0] = select(home,x,s);
}
template<class View>
void
ViewSelRnd<View>::ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>&) {
n=1; ties[0] = select(home,x,s);
}
template<class View>
void
ViewSelRnd<View>::brk(Space&, ViewArray<View>&, int* ties, int& n) {
ties[0] = ties[static_cast<int>(r(static_cast<unsigned int>(n)))];
n=1;
}
template<class View>
int
ViewSelRnd<View>::select(Space&, ViewArray<View>&, int* ties, int n) {
return ties[static_cast<int>(r(static_cast<unsigned int>(n)))];
}
template<class View>
ViewSel<View>*
ViewSelRnd<View>::copy(Space& home) {
return new (home) ViewSelRnd<View>(home,*this);
}
template<class Val>
forceinline bool
ChooseMin::operator ()(Val a, Val b) const {
return a < b;
}
template<class Val>
forceinline bool
ChooseMax::operator ()(Val a, Val b) const {
return a > b;
}
template<class Choose, class Merit>
forceinline
ViewSelChoose<Choose,Merit>::ViewSelChoose(Space& home, const VarBranch<Var>& vb)
: ViewSel<View>(home,vb), m(home,vb) {}
template<class Choose, class Merit>
forceinline
ViewSelChoose<Choose,Merit>::ViewSelChoose(Space& home,
ViewSelChoose<Choose,Merit>& vs)
: ViewSel<View>(home,vs), m(home,vs.m) {}
template<class Choose, class Merit>
int
ViewSelChoose<Choose,Merit>::select(Space& home, ViewArray<View>& x, int s) {
// Consider x[s] as the so-far best view
int b_i = s;
Val b_m = m(home,x[s],s);
// Scan all non-assigned views from s+1 onwards
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned()) {
Val mxi = m(home,x[i],i);
if (c(mxi,b_m)) {
b_i = i; b_m = mxi;
}
}
return b_i;
}
template<class Choose, class Merit>
int
ViewSelChoose<Choose,Merit>::select(Space& home, ViewArray<View>& x, int s,
BrancherFilter<View>& f) {
// Consider x[s] as the so-far best view
int b_i = s;
Val b_m = m(home,x[s],s);
// Scan all non-assigned views from s+1 onwards
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned() && f(home,x[i],i)) {
Val mxi = m(home,x[i],i);
if (c(mxi,b_m)) {
b_i = i; b_m = mxi;
}
}
return b_i;
}
template<class Choose, class Merit>
void
ViewSelChoose<Choose,Merit>::ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n) {
// Consider x[s] as the so-far best view and record as tie
Val b = m(home,x[s],s);
int j=0; ties[j++]=s;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned()) {
Val mxi = m(home,x[i],i);
if (c(mxi,b)) {
// Found a better one, reset all ties and record
j=0; ties[j++]=i; b=mxi;
} else if (mxi == b) {
// Found a tie, record
ties[j++]=i;
}
}
n=j;
// There must be at least one tie, of course!
assert(n > 0);
}
template<class Choose, class Merit>
void
ViewSelChoose<Choose,Merit>::ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f) {
// Consider x[s] as the so-far best view and record as tie
Val b = m(home,x[s],s);
int j=0; ties[j++]=s;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned() && f(home,x[i],i)) {
Val mxi = m(home,x[i],i);
if (c(mxi,b)) {
// Found a better one, reset all ties and record
j=0; ties[j++]=i; b=mxi;
} else if (mxi == b) {
// Found a tie, record
ties[j++]=i;
}
}
n=j;
// There must be at least one tie, of course!
assert(n > 0);
}
template<class Choose, class Merit>
void
ViewSelChoose<Choose,Merit>::brk(Space& home, ViewArray<View>& x,
int* ties, int& n) {
// Keep first tie in place
Val b = m(home,x[ties[0]],ties[0]);
int j=1;
// Scan remaining ties
for (int i=1; i<n; i++) {
Val mxi = m(home,x[ties[i]],ties[i]);
if (c(mxi,b)) {
// Found a better one, reset all ties
b=mxi; j=0; ties[j++]=ties[i];
} else if (mxi == b) {
// Found a tie and record it
ties[j++]=ties[i];
}
}
n=j;
// There must be at least one tie, of course!
assert(n > 0);
}
template<class Choose, class Merit>
int
ViewSelChoose<Choose,Merit>::select(Space& home, ViewArray<View>& x,
int* ties, int n) {
int b_i = ties[0];
Val b_m = m(home,x[ties[0]],ties[0]);
for (int i=1; i<n; i++) {
Val mxi = m(home,x[ties[i]],ties[i]);
if (c(mxi,b_m)) {
b_i = ties[i]; b_m = mxi;
}
}
return b_i;
}
template<class Choose, class Merit>
bool
ViewSelChoose<Choose,Merit>::notice(void) const {
return m.notice();
}
template<class Choose, class Merit>
void
ViewSelChoose<Choose,Merit>::dispose(Space& home) {
m.dispose(home);
}
template<class Choose, class Merit>
forceinline
ViewSelChooseTbl<Choose,Merit>::ViewSelChooseTbl(Space& home,
const VarBranch<Var>& vb)
: ViewSelChoose<Choose,Merit>(home,vb), tbl(vb.tbl()) {
if (!tbl())
throw InvalidFunction("ViewSelChooseTbl::ViewSelChooseTbl");
}
template<class Choose, class Merit>
forceinline
ViewSelChooseTbl<Choose,Merit>::ViewSelChooseTbl
(Space& home, ViewSelChooseTbl<Choose,Merit>& vs)
: ViewSelChoose<Choose,Merit>(home,vs), tbl(vs.tbl) {
}
template<class Choose, class Merit>
void
ViewSelChooseTbl<Choose,Merit>::ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n) {
// Find the worst and best merit value
Val w = m(home,x[s],s);
Val b = w;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned()) {
Val mxi = m(home,x[i],i);
if (c(mxi,b))
b=mxi;
else if (c(w,mxi))
w=mxi;
}
// Compute tie-break limit
GECODE_VALID_FUNCTION(tbl());
double l = tbl()(home,static_cast<double>(w),static_cast<double>(b));
// If the limit is not better than the worst merit, everything is a tie
if (!c(l,static_cast<double>(w))) {
int j=0;
for (int i=s; i<x.size(); i++)
if (!x[i].assigned())
ties[j++]=i;
n=j;
} else {
// The limit is not allowed to better than the best merit value
if (c(l,static_cast<double>(b)))
l = static_cast<double>(b);
// Record all ties that are not worse than the limit merit value
int j=0;
for (int i=s; i<x.size(); i++)
if (!x[i].assigned() && !c(l,static_cast<double>(m(home,x[i],i))))
ties[j++]=i;
n=j;
}
// There will be at least one tie (the best will qualify, of course)
assert(n > 0);
}
template<class Choose, class Merit>
void
ViewSelChooseTbl<Choose,Merit>::ties(Space& home, ViewArray<View>& x, int s,
int* ties, int& n,
BrancherFilter<View>& f) {
// Find the worst and best merit value
assert(f(home,x[s],s));
Val w = m(home,x[s],s);
Val b = w;
for (int i=s+1; i<x.size(); i++)
if (!x[i].assigned() && f(home,x[i],i)) {
Val mxi = m(home,x[i],i);
if (c(mxi,b))
b=mxi;
else if (c(w,mxi))
w=mxi;
}
// Compute tie-break limit
GECODE_VALID_FUNCTION(tbl());
double l = tbl()(home,static_cast<double>(w),static_cast<double>(b));
// If the limit is not better than the worst merit, everything is a tie
if (!c(l,static_cast<double>(w))) {
int j=0;
for (int i=s; i<x.size(); i++)
if (!x[i].assigned() && f(home,x[i],i))
ties[j++]=i;
n=j;
} else {
// The limit is not allowed to better than the best merit value
if (c(l,static_cast<double>(b)))
l = static_cast<double>(b);
// Record all ties that are not worse than the limit merit value
int j=0;
for (int i=s; i<x.size(); i++)
if (!x[i].assigned() && f(home,x[i],i) &&
!c(l,static_cast<double>(m(home,x[i],i))))
ties[j++]=i;
n=j;
}
// There will be at least one tie (the best will qualify, of course)
assert(n > 0);
}
template<class Choose, class Merit>
void
ViewSelChooseTbl<Choose,Merit>::brk(Space& home, ViewArray<View>& x,
int* ties, int& n) {
// Find the worst and best merit value
Val w = m(home,x[ties[0]],ties[0]);
Val b = w;
for (int i=1; i<n; i++) {
Val mxi = m(home,x[ties[i]],ties[i]);
if (c(mxi,b))
b=mxi;
else if (c(w,mxi))
w=mxi;
}
// Compute tie-break limit
GECODE_VALID_FUNCTION(tbl());
double l = tbl()(home,static_cast<double>(w),static_cast<double>(b));
// If the limit is not better than the worst merit, everything is a tie
// and no breaking is required
if (c(l,static_cast<double>(w))) {
// The limit is not allowed to better than the best merit value
if (c(l,static_cast<double>(b)))
l = static_cast<double>(b);
// Keep all ties that are not worse than the limit merit value
int j=0;
for (int i=0; i<n; i++)
if (!c(l,static_cast<double>(m(home,x[ties[i]],ties[i]))))
ties[j++]=ties[i];
n=j;
}
// There will be at least one tie (the best will qualify)
assert(n > 0);
}
template<class Choose, class Merit>
bool
ViewSelChooseTbl<Choose,Merit>::notice(void) const {
return true;
}
template<class Choose, class Merit>
void
ViewSelChooseTbl<Choose,Merit>::dispose(Space&) {
tbl.~SharedData<BranchTbl>();
}
template<class Merit>
forceinline
ViewSelMin<Merit>::ViewSelMin(Space& home, const VarBranch<Var>& vb)
: ViewSelChoose<ChooseMin,Merit>(home,vb) {}
template<class Merit>
forceinline
ViewSelMin<Merit>::ViewSelMin(Space& home, ViewSelMin<Merit>& vs)
: ViewSelChoose<ChooseMin,Merit>(home,vs) {}
template<class Merit>
ViewSel<typename ViewSelMin<Merit>::View>*
ViewSelMin<Merit>::copy(Space& home) {
return new (home) ViewSelMin<Merit>(home,*this);
}
template<class Merit>
forceinline
ViewSelMinTbl<Merit>::ViewSelMinTbl(Space& home, const VarBranch<Var>& vb)
: ViewSelChooseTbl<ChooseMin,Merit>(home,vb) {}
template<class Merit>
forceinline
ViewSelMinTbl<Merit>::ViewSelMinTbl(Space& home, ViewSelMinTbl<Merit>& vs)
: ViewSelChooseTbl<ChooseMin,Merit>(home,vs) {}
template<class Merit>
ViewSel<typename ViewSelMinTbl<Merit>::View>*
ViewSelMinTbl<Merit>::copy(Space& home) {
return new (home) ViewSelMinTbl<Merit>(home,*this);
}
template<class Merit>
forceinline
ViewSelMax<Merit>::ViewSelMax(Space& home, const VarBranch<Var>& vb)
: ViewSelChoose<ChooseMax,Merit>(home,vb) {}
template<class Merit>
forceinline
ViewSelMax<Merit>::ViewSelMax(Space& home, ViewSelMax<Merit>& vs)
: ViewSelChoose<ChooseMax,Merit>(home,vs) {}
template<class Merit>
ViewSel<typename ViewSelMax<Merit>::View>*
ViewSelMax<Merit>::copy(Space& home) {
return new (home) ViewSelMax<Merit>(home,*this);
}
template<class Merit>
forceinline
ViewSelMaxTbl<Merit>::ViewSelMaxTbl(Space& home, const VarBranch<Var>& vb)
: ViewSelChooseTbl<ChooseMax,Merit>(home,vb) {}
template<class Merit>
forceinline
ViewSelMaxTbl<Merit>::ViewSelMaxTbl(Space& home, ViewSelMaxTbl<Merit>& vs)
: ViewSelChooseTbl<ChooseMax,Merit>(home,vs) {}
template<class Merit>
ViewSel<typename ViewSelMaxTbl<Merit>::View>*
ViewSelMaxTbl<Merit>::copy(Space& home) {
return new (home) ViewSelMaxTbl<Merit>(home,*this);
}
}
// STATISTICS: kernel-branch