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.

495 lines
14 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* David Rijsman <David.Rijsman@quintiq.com>
*
* Contributing authors:
* Christian Schulte <schulte@gecode.org>
*
* Copyright:
* David Rijsman, 2009
* Christian Schulte, 2009
*
* 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 { namespace Int { namespace Sequence {
/**
* \brief Class for advising the propagator
*/
template<class View>
class SupportAdvisor : public Advisor {
public:
/// Index position
int i;
/// Initialize
SupportAdvisor(Space& home, Propagator& p, Council<SupportAdvisor>& c,
int i0);
/// Copy during cloning
SupportAdvisor(Space& home, SupportAdvisor& a);
/// Dispose advisor
void dispose(Space& home, Council<SupportAdvisor>& c);
};
template<class View>
forceinline
SupportAdvisor<View>::SupportAdvisor(Space& home, Propagator& p,
Council<SupportAdvisor>& c,int i0)
: Advisor(home,p,c), i(i0) {
}
template<class View>
forceinline
SupportAdvisor<View>::SupportAdvisor(Space& home, SupportAdvisor& a)
: Advisor(home,a), i(a.i) {
}
template<class View>
forceinline void
SupportAdvisor<View>::dispose(Space& home, Council<SupportAdvisor>& c) {
Advisor::dispose(home,c);
}
/**
* \brief Class for view value support structure
*/
template<class View, class Val, bool iss>
class ViewValSupport {
public:
/// Initialize
void init(Space& home, ViewArray<View>& x,Val s, int i, int q);
/// Update
void update(Space& home, ViewValSupport<View,Val,iss>& vvs, int n0);
/// Advise
ExecStatus advise(Space& home,ViewArray<View>& a,Val s,int i,int q, int j,const Delta& d);
/// Propagate
ExecStatus propagate(Space& home,ViewArray<View>& a,Val s,int i,int q,int l,int u);
/// Return true if sequence j has been violated
bool violated(int j, int q, int l, int u) const;
/// Check if retired
bool retired(void) const;
/// Allocate an instance
static ViewValSupport* allocate(Space&,int);
private:
/// Schedules the invoking support to be concluded (to be shaved)
ExecStatus schedule_conclusion(ViewArray<View>& a,Val s,int i);
/// Returns true if a conclusion to be made has been scheduled
bool conlusion_scheduled(void) const;
/// Retires invoking instance
void retire(void);
/// Return number of forced to s elements in sequence j
int values(int j, int q) const;
/// Checks if x[i] has been shaved
bool shaved(const View& x, Val s, int i) const;
/// Push up the cumulative array
bool pushup(ViewArray<View>& a,Val s,int i,int q,int idx, int v);
/// Make conclusion
ExecStatus conclude(Space& home,ViewArray<View>& a,Val s,int i);
/// Returns true if a[idx]=s not possible taking into account a[i]=s if iss or a[i]!=s if ! iss
bool s_not_possible(ViewArray<View>& a, Val s, int i, int idx) const;
/// Returns true if a[idx] can be not s taking into account a[i]=s if iss or a[i]!=s if ! iss
bool alternative_not_possible(ViewArray<View>& a,Val s,int i, int idx) const;
/// Returns true if there are potential violations marked
bool has_potential_violation(void) const;
/// Returns next potential violation and removes it
int next_potential_violation(void);
/// Adds potential violation i
void potential_violation(int i);
// Sets element idx of cumulative array to v
void set(int idx, int v, int q, int n);
/// Adds potential violations for location idx in cumulative array
void potential_violation(int idx, int q, int n);
/// Cumulative array
int* y;
/// Potential violation set
Violations v;
};
template<class View, class Val, bool iss>
forceinline ViewValSupport<View,Val,iss>*
ViewValSupport<View,Val,iss>::allocate(Space& home, int n) {
return home.alloc<ViewValSupport<View,Val,iss> >(n);
}
template<class View, class Val, bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::has_potential_violation(void) const {
return !v.empty();
}
template<class View, class Val, bool iss>
forceinline int
ViewValSupport<View,Val,iss>::next_potential_violation(void) {
return static_cast<int>(v.get());
}
template<class View, class Val, bool iss>
forceinline void
ViewValSupport<View,Val,iss>::potential_violation(int k) {
v.add(static_cast<unsigned int>(k));
}
template<class View, class Val, bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::retired(void) const {
return nullptr == y;
}
template<class View, class Val, bool iss>
forceinline void
ViewValSupport<View,Val,iss>::retire(void) {
y = nullptr;
}
template<class View,class Val, bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::alternative_not_possible
(ViewArray<View>& a, Val s, int i, int idx) const {
(void) i;
return includes(a[idx-1],s) || (iss && (idx-1 == i));
}
template<class View, class Val, bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::s_not_possible
(ViewArray<View>& a, Val s, int i, int idx) const {
(void) i;
return excludes(a[idx-1],s) || (!iss && (i == idx-1));
}
template<class View, class Val, bool iss>
forceinline void
ViewValSupport<View,Val,iss>::init(Space& home, ViewArray<View>& a, Val s,
int i, int q) {
y = home.alloc<int>(a.size()+1);
v.init(home,static_cast<unsigned int>(a.size()));
y[0] = 0;
for ( int l=0; l<a.size(); l++ ) {
if ( alternative_not_possible(a,s,i,l+1) ) {
y[l+1] = y[l] + 1;
} else {
y[l+1] = y[l];
}
if ( l+1 >= q ) {
potential_violation(l+1-q);
}
if ( l <= a.size() - q ) {
potential_violation(l);
}
}
}
template<class View, class Val, bool iss>
forceinline void
ViewValSupport<View,Val,iss>::update(Space& home,
ViewValSupport<View,Val,iss>& vvs,
int n0) {
y = nullptr;
if ( !vvs.retired() ) {
y = home.alloc<int>(n0);
for ( int l=0; l<n0; l++ ) {
y[l] = vvs.y[l];
}
v.update(home,vvs.v);
// = &home.construct<S>(S::key_compare(),S::allocator_type(home));
}
}
template<class View,class Val, bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::shaved(const View& x, Val s, int) const {
if (iss)
return excludes(x,s);
else
return includes(x,s);
}
template<class View,class Val, bool iss>
forceinline ExecStatus
ViewValSupport<View,Val,iss>::schedule_conclusion(ViewArray<View>& a, Val s,
int i) {
if (!retired()) {
if ((iss && includes(a[i],s)) || (!iss && excludes(a[i],s)))
return ES_FAILED;
y[0] = 1;
potential_violation(0);
}
return ES_OK;
}
template<class View,class Val, bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::conlusion_scheduled(void) const {
return !retired() && y[0] > 0;
}
template<class View,class Val, bool iss>
forceinline int
ViewValSupport<View,Val,iss>::values(int j, int q) const {
return y[j+q]-y[j];
}
template<class View,class Val,bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::violated(int j, int q, int l, int u) const {
return values(j,q) < l || values(j,q) > u;
}
template<class View,class Val,bool iss>
forceinline ExecStatus
ViewValSupport<View,Val,iss>::conclude(Space& home,ViewArray<View>& a,
Val s, int i) {
if ( iss ) {
GECODE_ME_CHECK(exclude(home,a[i],s));
} else {
GECODE_ME_CHECK(include(home,a[i],s));
}
retire();
return ES_OK;
}
template<class View,class Val,bool iss>
forceinline void
ViewValSupport<View,Val,iss>::potential_violation(int idx, int q, int n) {
if ( idx >= q ) {
potential_violation(idx-q);
}
if ( idx <= n - q - 1) {
potential_violation(idx);
}
}
template<class View,class Val,bool iss>
forceinline void
ViewValSupport<View,Val,iss>::set(int idx, int v, int q, int n) {
assert(y[idx]<=v);
if ( y[idx] < v ) {
y[idx] = v;
potential_violation(idx,q,n);
}
}
template<class View,class Val,bool iss>
forceinline bool
ViewValSupport<View,Val,iss>::pushup(ViewArray<View>& a,Val s,int i,int q,int idx, int v) {
if ( !retired() ) {
int n = a.size() + 1;
set(idx,y[idx]+v,q,n);
if ( y[idx] > idx ) {
return false;
}
int t = idx;
// repair y on the left
while ( idx > 0 && ((y[idx]-y[idx-1]>1) || ((y[idx]-y[idx-1]==1 && s_not_possible(a,s,i,idx)))) ) {
if ( s_not_possible(a,s,i,idx) ) {
set(idx-1,y[idx],q,n);
} else {
set(idx-1,y[idx]-1,q,n);
}
if ( y[idx-1]>idx-1 ) {
return false;
}
idx -= 1;
}
idx = t;
// repair y on the right
while ( idx < a.size() && ((y[idx]-y[idx+1]>0) || ((y[idx]-y[idx+1]==0) && alternative_not_possible(a,s,i,idx+1))) ) {
if ( alternative_not_possible(a,s,i,idx+1) ) {
set(idx+1,y[idx]+1,q,n);
} else {
set(idx+1,y[idx],q,n);
}
idx += 1;
}
}
return true;
}
template<class View,class Val,bool iss>
forceinline ExecStatus
ViewValSupport<View,Val,iss>::advise(Space&, ViewArray<View>& a,
Val s,int i,int q, int j,
const Delta&) {
ExecStatus status = ES_FIX;
if (!retired()) {
if ((j == i) && shaved(a[j],s,j)) {
retire();
} else {
switch (takes(a[j],s)) {
case TS_YES:
if (y[j+1]-y[j] == 0) {
if (!pushup(a,s,i,q,j+1,1)) {
GECODE_ES_CHECK(schedule_conclusion(a,s,i));
}
}
break;
case TS_NO:
if (y[j+1]-y[j] > 0) {
if (!pushup(a,s,i,q,j,y[j+1]-y[j])) {
GECODE_ES_CHECK(schedule_conclusion(a,s,i));
}
}
break;
case TS_MAYBE:
break;
default:
GECODE_NEVER;
}
if ( has_potential_violation() )
status = ES_NOFIX;
}
}
return status;
}
template<class View,class Val,bool iss>
forceinline ExecStatus
ViewValSupport<View,Val,iss>::propagate(Space& home,ViewArray<View>& a,Val s,int i,int q,int l,int u) {
if ( !retired() ) {
if ( conlusion_scheduled() ) {
return conclude(home,a,s,i);
}
while (has_potential_violation()) {
int j = next_potential_violation();
if (violated(j,q,l,u)) {
int forced_to_s = values(j,q);
if (forced_to_s < l) {
if (!pushup(a,s,i,q,j+q,l-forced_to_s))
return conclude(home,a,s,i);
} else {
if (!pushup(a,s,i,q,j,forced_to_s-u))
return conclude(home,a,s,i);
}
if (violated(j,q,l,u))
return conclude(home,a,s,i);
}
}
}
return ES_OK;
}
template<class View,class Val,bool iss>
ViewValSupportArray<View,Val,iss>::ViewValSupportArray(void) : xs(nullptr), n(0) {
}
template<class View,class Val,bool iss>
ViewValSupportArray<View,Val,iss>::ViewValSupportArray(const ViewValSupportArray<View,Val,iss>& a) {
n = a.n; xs = a.xs;
}
template<class View,class Val,bool iss>
ViewValSupportArray<View,Val,iss>::ViewValSupportArray(Space& home,ViewArray<View>& x, Val s, int q) : xs(nullptr) {
n = x.size();
if ( n > 0 ) {
xs = ViewValSupport<View,Val,iss>::allocate(home,n);
for (int i = n; i--; ) {
xs[i].init(home,x,s,i,q);
}
}
}
template<class View,class Val,bool iss>
ViewValSupportArray<View,Val,iss>::ViewValSupportArray(Space& home, int n0) : xs(nullptr) {
n = n0;
if (n>0) {
xs = ViewValSupport<View,Val,iss>::allocate(home,n);
}
}
template<class View,class Val,bool iss>
forceinline int
ViewValSupportArray<View,Val,iss>::size(void) const {
return n;
}
template<class View,class Val,bool iss>
forceinline ViewValSupport<View,Val,iss>&
ViewValSupportArray<View,Val,iss>::operator [](int i) {
assert((i >= 0) && (i < size()));
return xs[i];
}
template<class View,class Val,bool iss>
forceinline const ViewValSupport<View,Val,iss>&
ViewValSupportArray<View,Val,iss>::operator [](int i) const {
assert((i >= 0) && (i < size()));
return xs[i];
}
template<class View,class Val,bool iss>
void
ViewValSupportArray<View,Val,iss>::update(Space& home, ViewValSupportArray<View,Val,iss>& a) {
n = a.size();
if (n>0) {
xs = ViewValSupport<View,Val,iss>::allocate(home,n);
for (int i=n; i--; ) {
xs[i].update(home,a[i],n+1);
}
}
}
template<class View,class Val,bool iss>
ExecStatus
ViewValSupportArray<View,Val,iss>::propagate(Space& home,ViewArray<View>& a,Val s,int q,int l,int u) {
for (int i=n; i--; ) {
GECODE_ES_CHECK(xs[i].propagate(home,a,s,i,q,l,u));
}
return ES_OK;
}
template<class View,class Val,bool iss>
ExecStatus
ViewValSupportArray<View,Val,iss>::advise(Space& home,ViewArray<View>& a,Val s,int q,int j,const Delta& d) {
ExecStatus status = ES_FIX;
for (int i=n; i--; ) {
if ( ES_NOFIX == xs[i].advise(home,a,s,i,q,j,d) )
status = ES_NOFIX;
}
return status;
}
}}}
// STATISTICS: int-prop