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 981be2067e Squashed 'software/gecode_on_replay/' content from commit 8051d92b9
git-subtree-dir: software/gecode_on_replay
git-subtree-split: 8051d92b9c89e49cccfbd1c201371580d7703ab4
2021-06-16 14:04:29 +10:00

984 lines
32 KiB
C++
Executable File

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Christian Schulte <schulte@gecode.org>
*
* Copyright:
* Christian Schulte, 2004
*
* 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.
*
*/
#include <climits>
#include <algorithm>
namespace Gecode { namespace Int { namespace Extensional {
/**
* \brief Traits class for variables
*
* Each variable must specialize this traits class and add a \code
* typedef \endcode for the view \a View corresponding to this variable.
*/
template<class Var>
class VarTraits {};
/**
* \brief Traits class for variables
*
* This class specializes the VarTraits for integer variables.
*/
template<>
class VarTraits<IntVar> {
public:
/// The variable type of an IntView
typedef Int::IntView View;
};
/**
* \brief Traits class for variables
*
* This class specializes the VarTraits for Boolean variables.
*/
template<>
class VarTraits<BoolVar> {
public:
/// The variable type of an IntView
typedef Int::BoolView View;
};
/*
* States
*/
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::State::init(void) {
i_deg=o_deg=0;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline typename LayeredGraph<View,Val,Degree,StateIdx>::State&
LayeredGraph<View,Val,Degree,StateIdx>::i_state(int i, StateIdx is) {
return layers[i].states[is];
}
template<class View, class Val, class Degree, class StateIdx>
forceinline typename LayeredGraph<View,Val,Degree,StateIdx>::State&
LayeredGraph<View,Val,Degree,StateIdx>::i_state
(int i, const typename LayeredGraph<View,Val,Degree,StateIdx>::Edge& e) {
return i_state(i,e.i_state);
}
template<class View, class Val, class Degree, class StateIdx>
forceinline bool
LayeredGraph<View,Val,Degree,StateIdx>::i_dec
(int i, const typename LayeredGraph<View,Val,Degree,StateIdx>::Edge& e) {
return --i_state(i,e).o_deg == 0;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline typename LayeredGraph<View,Val,Degree,StateIdx>::State&
LayeredGraph<View,Val,Degree,StateIdx>::o_state(int i, StateIdx os) {
return layers[i+1].states[os];
}
template<class View, class Val, class Degree, class StateIdx>
forceinline typename LayeredGraph<View,Val,Degree,StateIdx>::State&
LayeredGraph<View,Val,Degree,StateIdx>::o_state
(int i, const typename LayeredGraph<View,Val,Degree,StateIdx>::Edge& e) {
return o_state(i,e.o_state);
}
template<class View, class Val, class Degree, class StateIdx>
forceinline bool
LayeredGraph<View,Val,Degree,StateIdx>::o_dec
(int i, const typename LayeredGraph<View,Val,Degree,StateIdx>::Edge& e) {
return --o_state(i,e).i_deg == 0;
}
/*
* Value iterator
*/
template<class View, class Val, class Degree, class StateIdx>
forceinline
LayeredGraph<View,Val,Degree,StateIdx>::LayerValues::LayerValues(void) {}
template<class View, class Val, class Degree, class StateIdx>
forceinline
LayeredGraph<View,Val,Degree,StateIdx>::LayerValues
::LayerValues(const Layer& l)
: s1(l.support), s2(l.support+l.size) {}
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::LayerValues::init(const Layer& l) {
s1=l.support; s2=l.support+l.size;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline bool
LayeredGraph<View,Val,Degree,StateIdx>::LayerValues
::operator ()(void) const {
return s1<s2;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::LayerValues::operator ++(void) {
s1++;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline int
LayeredGraph<View,Val,Degree,StateIdx>::LayerValues::val(void) const {
return s1->val;
}
/*
* Index advisors
*
*/
template<class View, class Val, class Degree, class StateIdx>
forceinline
LayeredGraph<View,Val,Degree,StateIdx>::Index::Index(Space& home, Propagator& p,
Council<Index>& c,
int i0)
: Advisor(home,p,c), i(i0) {}
template<class View, class Val, class Degree, class StateIdx>
forceinline
LayeredGraph<View,Val,Degree,StateIdx>::Index::Index(Space& home, Index& a)
: Advisor(home,a), i(a.i) {}
/*
* Index ranges
*
*/
template<class View, class Val, class Degree, class StateIdx>
forceinline
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::IndexRange(void)
: _fst(INT_MAX), _lst(INT_MIN) {}
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::reset(void) {
_fst=INT_MAX; _lst=INT_MIN;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::add(int i) {
_fst=std::min(_fst,i); _lst=std::max(_lst,i);
}
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::add
(const typename LayeredGraph<View,Val,Degree,StateIdx>::IndexRange& ir) {
_fst=std::min(_fst,ir._fst); _lst=std::max(_lst,ir._lst);
}
template<class View, class Val, class Degree, class StateIdx>
forceinline bool
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::empty(void) const {
return _fst>_lst;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::lshift(int n) {
if (empty())
return;
if (n > _lst) {
reset();
} else {
_fst = std::max(0,_fst-n);
_lst -= n;
}
}
template<class View, class Val, class Degree, class StateIdx>
forceinline int
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::fst(void) const {
return _fst;
}
template<class View, class Val, class Degree, class StateIdx>
forceinline int
LayeredGraph<View,Val,Degree,StateIdx>::IndexRange::lst(void) const {
return _lst;
}
/*
* The layered graph
*
*/
template<class View, class Val, class Degree, class StateIdx>
template<class Var>
forceinline
LayeredGraph<View,Val,Degree,StateIdx>::LayeredGraph(Home home,
const VarArgArray<Var>& x,
const DFA& dfa)
: Propagator(home), c(home), n(x.size()),
max_states(static_cast<StateIdx>(dfa.n_states())) {
assert(n > 0);
}
template<class View, class Val, class Degree, class StateIdx>
forceinline void
LayeredGraph<View,Val,Degree,StateIdx>::audit(void) {
#ifdef GECODE_AUDIT
// Check states and edge information to be consistent
unsigned int n_e = 0; // Number of edges
unsigned int n_s = 0; // Number of states
StateIdx m_s = 0; // Maximal number of states per layer
for (int i=n; i--; ) {
n_s += layers[i].n_states;
m_s = std::max(m_s,layers[i].n_states);
for (ValSize j=layers[i].size; j--; )
n_e += layers[i].support[j].n_edges;
}
n_s += layers[n].n_states;
m_s = std::max(m_s,layers[n].n_states);
assert(n_e == n_edges);
assert(n_s <= n_states);
assert(m_s <= max_states);
#endif
}
template<class View, class Val, class Degree, class StateIdx>
template<class Var>
forceinline ExecStatus
LayeredGraph<View,Val,Degree,StateIdx>::initialize(Space& home,
const VarArgArray<Var>& x,
const DFA& dfa) {
Region r;
// Allocate memory for layers
layers = home.alloc<Layer>(n+1);
// Allocate temporary memory for all possible states
State* states = r.alloc<State>(max_states*(n+1));
for (int i=0; i<static_cast<int>(max_states)*(n+1); i++)
states[i].init();
for (int i=0; i<n+1; i++)
layers[i].states = states + i*max_states;
// Allocate temporary memory for edges
Edge* edges = r.alloc<Edge>(dfa.max_degree());
// Mark initial state as being reachable
i_state(0,0).i_deg = 1;
// Forward pass: add transitions
for (int i=0; i<n; i++) {
layers[i].x = x[i];
layers[i].support = home.alloc<Support>(layers[i].x.size());
ValSize j=0;
// Enter links leaving reachable states (indegree != 0)
for (ViewValues<View> nx(layers[i].x); nx(); ++nx) {
Degree n_edges=0;
for (DFA::Transitions t(dfa,nx.val()); t(); ++t)
if (i_state(i,static_cast<StateIdx>(t.i_state())).i_deg != 0) {
i_state(i,static_cast<StateIdx>(t.i_state())).o_deg++;
o_state(i,static_cast<StateIdx>(t.o_state())).i_deg++;
edges[n_edges].i_state = static_cast<StateIdx>(t.i_state());
edges[n_edges].o_state = static_cast<StateIdx>(t.o_state());
n_edges++;
}
assert(n_edges <= dfa.max_degree());
// Found support for value
if (n_edges > 0) {
Support& s = layers[i].support[j];
s.val = static_cast<Val>(nx.val());
s.n_edges = n_edges;
s.edges = Heap::copy(home.alloc<Edge>(n_edges),edges,n_edges);
j++;
}
}
if ((layers[i].size = j) == 0)
return ES_FAILED;
}
// Mark final states as reachable
for (int s=dfa.final_fst(); s<dfa.final_lst(); s++)
if (o_state(n-1,static_cast<StateIdx>(s)).i_deg != 0)
o_state(n-1,static_cast<StateIdx>(s)).o_deg = 1;
// Backward pass: prune all transitions that do not lead to final state
for (int i=n; i--; ) {
ValSize k=0;
for (ValSize j=0; j<layers[i].size; j++) {
Support& s = layers[i].support[j];
for (Degree d=s.n_edges; d--; )
if (o_state(i,s.edges[d]).o_deg == 0) {
// Adapt states
i_dec(i,s.edges[d]); o_dec(i,s.edges[d]);
// Prune edge
s.edges[d] = s.edges[--s.n_edges];
}
// Value has support, copy the support information
if (s.n_edges > 0)
layers[i].support[k++]=s;
}
if ((layers[i].size = k) == 0)
return ES_FAILED;
LayerValues lv(layers[i]);
GECODE_ME_CHECK(layers[i].x.narrow_v(home,lv,false));
if (!layers[i].x.assigned())
layers[i].x.subscribe(home, *new (home) Index(home,*this,c,i));
}
// Copy and compress states, setup other information
{
// State map for in-states
StateIdx* i_map = r.alloc<StateIdx>(max_states);
// State map for out-states
StateIdx* o_map = r.alloc<StateIdx>(max_states);
// Number of in-states
StateIdx i_n = 0;
// Initialize map for in-states (special for last layer)
// Degree for single final state
unsigned int d = 0;
for (StateIdx j=0; j<max_states; j++)
d += static_cast<unsigned int>(layers[n].states[j].i_deg);
// Check whether all final states can be joined to a single state
if (d >
static_cast<unsigned int>
(Gecode::Support::IntTypeTraits<Degree>::max)) {
// Initialize map for in-states
for (StateIdx j=max_states; j--; )
if ((layers[n].states[j].o_deg != 0) ||
(layers[n].states[j].i_deg != 0))
i_map[j]=i_n++;
} else {
i_n = 1;
for (StateIdx j=max_states; j--; ) {
layers[n].states[j].init();
i_map[j] = 0;
}
layers[n].states[0].i_deg = static_cast<Degree>(d);
layers[n].states[0].o_deg = 1;
}
layers[n].n_states = i_n;
// Total number of states
n_states = i_n;
// Total number of edges
n_edges = 0;
// New maximal number of states
StateIdx max_s = i_n;
for (int i=n; i--; ) {
// In-states become out-states
std::swap(o_map,i_map); i_n=0;
// Initialize map for in-states
for (StateIdx j=max_states; j--; )
if ((layers[i].states[j].o_deg != 0) ||
(layers[i].states[j].i_deg != 0))
i_map[j]=i_n++;
layers[i].n_states = i_n;
n_states += i_n;
max_s = std::max(max_s,i_n);
// Update states in edges
for (ValSize j=layers[i].size; j--; ) {
Support& ls = layers[i].support[j];
n_edges += ls.n_edges;
for (Degree deg=ls.n_edges; deg--; ) {
ls.edges[deg].i_state = i_map[ls.edges[deg].i_state];
ls.edges[deg].o_state = o_map[ls.edges[deg].o_state];
}
}
}
// Allocate and copy states
State* a_states = home.alloc<State>(n_states);
for (int i=n+1; i--; ) {
StateIdx k=0;
for (StateIdx j=max_states; j--; )
if ((layers[i].states[j].o_deg != 0) ||
(layers[i].states[j].i_deg != 0))
a_states[k++] = layers[i].states[j];
assert(k == layers[i].n_states);
layers[i].states = a_states;
a_states += layers[i].n_states;
}
// Update maximal number of states
max_states = max_s;
}
// Schedule if subsumption is needed
if (c.empty())
View::schedule(home,*this,ME_INT_VAL);
audit();
return ES_OK;
}
template<class View, class Val, class Degree, class StateIdx>
ExecStatus
LayeredGraph<View,Val,Degree,StateIdx>::advise(Space& home,
Advisor& _a, const Delta& d) {
// Check whether state information has already been created
if (layers[0].states == nullptr) {
State* states = home.alloc<State>(n_states);
for (unsigned int i=0; i<n_states; i++)
states[i].init();
layers[n].states = states;
states += layers[n].n_states;
for (int i=n; i--; ) {
layers[i].states = states;
states += layers[i].n_states;
for (ValSize j=layers[i].size; j--; ) {
Support& s = layers[i].support[j];
for (Degree deg=s.n_edges; deg--; ) {
i_state(i,s.edges[deg]).o_deg++;
o_state(i,s.edges[deg]).i_deg++;
}
}
}
}
Index& a = static_cast<Index&>(_a);
const int i = a.i;
if (layers[i].size <= layers[i].x.size()) {
// Propagator has already done everything
if (View::modevent(d) == ME_INT_VAL) {
a.dispose(home,c);
return c.empty() ? ES_NOFIX : ES_FIX;
} else {
return ES_FIX;
}
}
bool i_mod = false;
bool o_mod = false;
if (View::modevent(d) == ME_INT_VAL) {
Val n = static_cast<Val>(layers[i].x.val());
ValSize j=0;
for (; layers[i].support[j].val < n; j++) {
Support& s = layers[i].support[j];
n_edges -= s.n_edges;
// Supported value not any longer in view
for (Degree deg=s.n_edges; deg--; ) {
// Adapt states
o_mod |= i_dec(i,s.edges[deg]);
i_mod |= o_dec(i,s.edges[deg]);
}
}
assert(layers[i].support[j].val == n);
layers[i].support[0] = layers[i].support[j++];
ValSize s=layers[i].size;
layers[i].size = 1;
for (; j<s; j++) {
Support& ls = layers[i].support[j];
n_edges -= ls.n_edges;
for (Degree deg=ls.n_edges; deg--; ) {
// Adapt states
o_mod |= i_dec(i,ls.edges[deg]);
i_mod |= o_dec(i,ls.edges[deg]);
}
}
} else if (layers[i].x.any(d)) {
ValSize j=0;
ValSize k=0;
ValSize s=layers[i].size;
for (ViewRanges<View> rx(layers[i].x); rx() && (j<s);) {
Support& ls = layers[i].support[j];
if (ls.val < static_cast<Val>(rx.min())) {
// Supported value not any longer in view
n_edges -= ls.n_edges;
for (Degree deg=ls.n_edges; deg--; ) {
// Adapt states
o_mod |= i_dec(i,ls.edges[deg]);
i_mod |= o_dec(i,ls.edges[deg]);
}
++j;
} else if (ls.val > static_cast<Val>(rx.max())) {
++rx;
} else {
layers[i].support[k++]=ls;
++j;
}
}
assert(k > 0);
layers[i].size = k;
// Remove remaining values
for (; j<s; j++) {
Support& ls=layers[i].support[j];
n_edges -= ls.n_edges;
for (Degree deg=ls.n_edges; deg--; ) {
// Adapt states
o_mod |= i_dec(i,ls.edges[deg]);
i_mod |= o_dec(i,ls.edges[deg]);
}
}
} else {
Val min = static_cast<Val>(layers[i].x.min(d));
ValSize j=0;
// Skip values smaller than min (to keep)
for (; layers[i].support[j].val < min; j++) {}
Val max = static_cast<Val>(layers[i].x.max(d));
ValSize k=j;
ValSize s=layers[i].size;
// Remove pruned values
for (; (j<s) && (layers[i].support[j].val <= max); j++) {
Support& ls=layers[i].support[j];
n_edges -= ls.n_edges;
for (Degree deg=ls.n_edges; deg--; ) {
// Adapt states
o_mod |= i_dec(i,ls.edges[deg]);
i_mod |= o_dec(i,ls.edges[deg]);
}
}
// Keep remaining values
while (j<s)
layers[i].support[k++]=layers[i].support[j++];
layers[i].size=k;
assert(k > 0);
}
audit();
bool fix = true;
if (o_mod && (i > 0)) {
o_ch.add(i-1); fix = false;
}
if (i_mod && (i+1 < n)) {
i_ch.add(i+1); fix = false;
}
if (fix) {
if (View::modevent(d) == ME_INT_VAL) {
a.dispose(home,c);
return c.empty() ? ES_NOFIX : ES_FIX;
}
return ES_FIX;
} else {
return (View::modevent(d) == ME_INT_VAL)
? home.ES_NOFIX_DISPOSE(c,a) : ES_NOFIX;
}
}
template<class View, class Val, class Degree, class StateIdx>
forceinline size_t
LayeredGraph<View,Val,Degree,StateIdx>::dispose(Space& home) {
c.dispose(home);
(void) Propagator::dispose(home);
return sizeof(*this);
}
template<class View, class Val, class Degree, class StateIdx>
void
LayeredGraph<View,Val,Degree,StateIdx>::reschedule(Space& home) {
View::schedule(home,*this,c.empty() ? ME_INT_VAL : ME_INT_DOM);
}
template<class View, class Val, class Degree, class StateIdx>
ExecStatus
LayeredGraph<View,Val,Degree,StateIdx>::propagate(Space& home,
const ModEventDelta&) {
// Forward pass
for (int i=i_ch.fst(); i<=i_ch.lst(); i++) {
bool i_mod = false;
bool o_mod = false;
ValSize j=0;
ValSize k=0;
ValSize ls=layers[i].size;
do {
Support& s=layers[i].support[j];
n_edges -= s.n_edges;
for (Degree d=s.n_edges; d--; )
if (i_state(i,s.edges[d]).i_deg == 0) {
// Adapt states
o_mod |= i_dec(i,s.edges[d]);
i_mod |= o_dec(i,s.edges[d]);
// Remove edge
s.edges[d] = s.edges[--s.n_edges];
}
n_edges += s.n_edges;
// Check whether value is still supported
if (s.n_edges == 0) {
layers[i].size--;
GECODE_ME_CHECK(layers[i].x.nq(home,s.val));
} else {
layers[i].support[k++]=s;
}
} while (++j<ls);
assert(k > 0);
// Update modification information
if (o_mod && (i > 0))
o_ch.add(i-1);
if (i_mod && (i+1 < n))
i_ch.add(i+1);
}
// Backward pass
for (int i=o_ch.lst(); i>=o_ch.fst(); i--) {
bool o_mod = false;
ValSize j=0;
ValSize k=0;
ValSize ls=layers[i].size;
do {
Support& s=layers[i].support[j];
n_edges -= s.n_edges;
for (Degree d=s.n_edges; d--; )
if (o_state(i,s.edges[d]).o_deg == 0) {
// Adapt states
o_mod |= i_dec(i,s.edges[d]);
(void) o_dec(i,s.edges[d]);
// Remove edge
s.edges[d] = s.edges[--s.n_edges];
}
n_edges += s.n_edges;
// Check whether value is still supported
if (s.n_edges == 0) {
layers[i].size--;
GECODE_ME_CHECK(layers[i].x.nq(home,s.val));
} else {
layers[i].support[k++]=s;
}
} while (++j<ls);
assert(k > 0);
// Update modification information
if (o_mod && (i > 0))
o_ch.add(i-1);
}
a_ch.add(i_ch); i_ch.reset();
a_ch.add(o_ch); o_ch.reset();
audit();
// Check subsumption
if (c.empty())
return home.ES_SUBSUMED(*this);
else
return ES_FIX;
}
template<class View, class Val, class Degree, class StateIdx>
template<class Var>
ExecStatus
LayeredGraph<View,Val,Degree,StateIdx>::post(Home home,
const VarArgArray<Var>& x,
const DFA& dfa) {
if (x.size() == 0) {
// Check whether the start state 0 is also a final state
if ((dfa.final_fst() <= 0) && (dfa.final_lst() >= 0))
return ES_OK;
return ES_FAILED;
}
assert(x.size() > 0);
for (int i=0; i<x.size(); i++) {
DFA::Symbols s(dfa);
typename VarTraits<Var>::View xi(x[i]);
GECODE_ME_CHECK(xi.inter_v(home,s,false));
}
LayeredGraph<View,Val,Degree,StateIdx>* p =
new (home) LayeredGraph<View,Val,Degree,StateIdx>(home,x,dfa);
return p->initialize(home,x,dfa);
}
template<class View, class Val, class Degree, class StateIdx>
forceinline
LayeredGraph<View,Val,Degree,StateIdx>
::LayeredGraph(Space& home, LayeredGraph<View,Val,Degree,StateIdx>& p)
: Propagator(home,p),
n(p.n), layers(home.alloc<Layer>(n+1)),
max_states(p.max_states), n_states(p.n_states), n_edges(p.n_edges) {
c.update(home,p.c);
// Do not allocate states, postpone to advise!
layers[n].n_states = p.layers[n].n_states;
layers[n].states = nullptr;
// Allocate memory for edges
Edge* edges = home.alloc<Edge>(n_edges);
// Copy layers
for (int i=0; i<n; i++) {
layers[i].x.update(home,p.layers[i].x);
assert(layers[i].x.size() == p.layers[i].size);
layers[i].size = p.layers[i].size;
layers[i].support = home.alloc<Support>(layers[i].size);
for (ValSize j=0; j<layers[i].size; j++) {
layers[i].support[j].val = p.layers[i].support[j].val;
layers[i].support[j].n_edges = p.layers[i].support[j].n_edges;
assert(layers[i].support[j].n_edges > 0);
layers[i].support[j].edges =
Heap::copy(edges,p.layers[i].support[j].edges,
layers[i].support[j].n_edges);
edges += layers[i].support[j].n_edges;
}
layers[i].n_states = p.layers[i].n_states;
layers[i].states = nullptr;
}
audit();
}
template<class View, class Val, class Degree, class StateIdx>
PropCost
LayeredGraph<View,Val,Degree,StateIdx>::cost(const Space&,
const ModEventDelta&) const {
return PropCost::linear(PropCost::HI,n);
}
template<class View, class Val, class Degree, class StateIdx>
Actor*
LayeredGraph<View,Val,Degree,StateIdx>::copy(Space& home) {
// Eliminate an assigned prefix
{
int k=0;
while (layers[k].size == 1) {
assert(layers[k].support[0].n_edges == 1);
n_states -= layers[k].n_states;
k++;
}
if (k > 0) {
/*
* The state information is always available: either the propagator
* has been created (hence, also the state information has been
* created), or the first variable become assigned and hence
* an advisor must have been run (which then has created the state
* information).
*/
// Eliminate assigned layers
n -= k; layers += k;
// Eliminate edges
n_edges -= static_cast<unsigned int>(k);
// Update advisor indices
for (Advisors<Index> as(c); as(); ++as)
as.advisor().i -= k;
// Update all change information
a_ch.lshift(k);
}
}
audit();
// Compress states
if (!a_ch.empty()) {
int f = a_ch.fst();
int l = a_ch.lst();
assert((f >= 0) && (l <= n));
Region r;
// State map for in-states
StateIdx* i_map = r.alloc<StateIdx>(max_states);
// State map for out-states
StateIdx* o_map = r.alloc<StateIdx>(max_states);
// Number of in-states
StateIdx i_n = 0;
n_states -= layers[l].n_states;
// Initialize map for in-states and compress
for (StateIdx j=0; j<layers[l].n_states; j++)
if ((layers[l].states[j].i_deg != 0) ||
(layers[l].states[j].o_deg != 0)) {
layers[l].states[i_n]=layers[l].states[j];
i_map[j]=i_n++;
}
layers[l].n_states = i_n;
n_states += layers[l].n_states;
assert(i_n > 0);
// Update in-states in edges for last layer, if any
if (l < n)
for (ValSize j=layers[l].size; j--; ) {
Support& s = layers[l].support[j];
for (Degree d=s.n_edges; d--; )
s.edges[d].i_state = i_map[s.edges[d].i_state];
}
// Update all changed layers
for (int i=l-1; i>=f; i--) {
// In-states become out-states
std::swap(o_map,i_map); i_n=0;
// Initialize map for in-states and compress
n_states -= layers[i].n_states;
for (StateIdx j=0; j<layers[i].n_states; j++)
if ((layers[i].states[j].o_deg != 0) ||
(layers[i].states[j].i_deg != 0)) {
layers[i].states[i_n]=layers[i].states[j];
i_map[j]=i_n++;
}
layers[i].n_states = i_n;
n_states += layers[i].n_states;
assert(i_n > 0);
// Update states in edges
for (ValSize j=layers[i].size; j--; ) {
Support& s = layers[i].support[j];
for (Degree d=s.n_edges; d--; ) {
s.edges[d].i_state = i_map[s.edges[d].i_state];
s.edges[d].o_state = o_map[s.edges[d].o_state];
}
}
}
// Update out-states in edges for previous layer, if any
if (f > 0)
for (ValSize j=layers[f-1].size; j--; ) {
Support& s = layers[f-1].support[j];
for (Degree d=s.n_edges; d--; )
s.edges[d].o_state = i_map[s.edges[d].o_state];
}
a_ch.reset();
}
audit();
return new (home) LayeredGraph<View,Val,Degree,StateIdx>(home,*this);
}
/// Select small types for the layered graph propagator
template<class Var>
forceinline ExecStatus
post_lgp(Home home, const VarArgArray<Var>& x, const DFA& dfa) {
Gecode::Support::IntType t_state_idx =
Gecode::Support::u_type(static_cast<unsigned int>(dfa.n_states()));
Gecode::Support::IntType t_degree =
Gecode::Support::u_type(dfa.max_degree());
Gecode::Support::IntType t_val =
std::max(Support::s_type(dfa.symbol_min()),
Support::s_type(dfa.symbol_max()));
switch (t_val) {
case Gecode::Support::IT_CHAR:
// fall through
case Gecode::Support::IT_SHRT:
switch (t_state_idx) {
case Gecode::Support::IT_CHAR:
switch (t_degree) {
case Gecode::Support::IT_CHAR:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned char,unsigned char>
::post(home,x,dfa);
case Gecode::Support::IT_SHRT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned short int,unsigned char>
::post(home,x,dfa);
case Gecode::Support::IT_INT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned int,unsigned char>
::post(home,x,dfa);
default: GECODE_NEVER;
}
break;
case Gecode::Support::IT_SHRT:
switch (t_degree) {
case Gecode::Support::IT_CHAR:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned char,unsigned short int>
::post(home,x,dfa);
case Gecode::Support::IT_SHRT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned short int,unsigned short int>
::post(home,x,dfa);
case Gecode::Support::IT_INT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned int,unsigned short int>
::post(home,x,dfa);
default: GECODE_NEVER;
}
break;
case Gecode::Support::IT_INT:
switch (t_degree) {
case Gecode::Support::IT_CHAR:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned char,unsigned int>
::post(home,x,dfa);
case Gecode::Support::IT_SHRT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned short int,unsigned int>
::post(home,x,dfa);
case Gecode::Support::IT_INT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,short int,unsigned int,unsigned int>
::post(home,x,dfa);
default: GECODE_NEVER;
}
break;
default: GECODE_NEVER;
}
break;
case Gecode::Support::IT_INT:
switch (t_state_idx) {
case Gecode::Support::IT_CHAR:
switch (t_degree) {
case Gecode::Support::IT_CHAR:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned char,unsigned char>
::post(home,x,dfa);
case Gecode::Support::IT_SHRT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned short int,unsigned char>
::post(home,x,dfa);
case Gecode::Support::IT_INT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned int,unsigned char>
::post(home,x,dfa);
default: GECODE_NEVER;
}
break;
case Gecode::Support::IT_SHRT:
switch (t_degree) {
case Gecode::Support::IT_CHAR:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned char,unsigned short int>
::post(home,x,dfa);
case Gecode::Support::IT_SHRT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned short int,unsigned short int>
::post(home,x,dfa);
case Gecode::Support::IT_INT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned int,unsigned short int>
::post(home,x,dfa);
default: GECODE_NEVER;
}
break;
case Gecode::Support::IT_INT:
switch (t_degree) {
case Gecode::Support::IT_CHAR:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned char,unsigned int>
::post(home,x,dfa);
case Gecode::Support::IT_SHRT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned short int,unsigned int>
::post(home,x,dfa);
case Gecode::Support::IT_INT:
return Extensional::LayeredGraph
<typename VarTraits<Var>::View,int,unsigned int,unsigned int>
::post(home,x,dfa);
default: GECODE_NEVER;
}
break;
default: GECODE_NEVER;
}
default: GECODE_NEVER;
}
return ES_OK;
}
}}}
// STATISTICS: int-prop