/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2003 * * Last modified: * $Date: 2008-07-11 09:33:32 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $ * $Revision: 7290 $ * * 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 Rel { template inline Lex::Lex(Space* home, ViewArray& x0, ViewArray& y0, bool s) : Propagator(home), x(x0), y(y0), strict(s) { x.subscribe(home, this, PC_INT_BND); y.subscribe(home, this, PC_INT_BND); } template forceinline Lex::Lex(Space* home, bool share, Lex& p) : Propagator(home,share,p), strict(p.strict) { x.update(home,share,p.x); y.update(home,share,p.y); } template Actor* Lex::copy(Space* home, bool share) { return new (home) Lex(home,share,*this); } template inline Support::Symbol Lex::ati(void) { return Reflection::mangle("Gecode::Int::Rel::Lex"); } template Reflection::ActorSpec Lex::spec(const Space* home, Reflection::VarMap& m) const { Reflection::ActorSpec s(ati()); return s << x.spec(home,m) << y.spec(home,m) << strict; } template void Lex::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(3); ViewArray x(home, vars, spec[0]); ViewArray y(home, vars, spec[1]); bool s = spec[2]->toInt(); (void) new (home) Lex(home,x,y,s); } template PropCost Lex::cost(ModEventDelta) const { return cost_lo(x.size(), PC_LINEAR_LO); } template ExecStatus Lex::propagate(Space* home, ModEventDelta) { /* * State 1 * */ { int i = 0; int n = x.size(); while ((i < n) && (x[i].min() == y[i].max())) { // case: =, >= GECODE_ME_CHECK(x[i].lq(home,y[i].max())); GECODE_ME_CHECK(y[i].gq(home,x[i].min())); i++; } if (i == n) // case: $ return strict ? ES_FAILED : ES_SUBSUMED(this,sizeof(*this)); // Possible cases left: <, <=, > (yields failure), ? GECODE_ME_CHECK(x[i].lq(home,y[i].max())); GECODE_ME_CHECK(y[i].gq(home,x[i].min())); if (x[i].max() < y[i].min()) // case: < (after tell) return ES_SUBSUMED(this,home); // x[i] can never be equal to y[i] (otherwise: >=) assert(!(x[i].assigned() && y[i].assigned() && x[i].val() == y[i].val())); // Remove all elements between 0...i-1 as they are assigned and equal x.drop_fst(i); y.drop_fst(i); // After this, execution continues at [1] } /* * State 2 * prefix: (?|<=) * */ { int i = 1; int n = x.size(); while ((i < n) && (x[i].min() == y[i].max()) && (x[i].max() == y[i].min())) { // case: = assert(x[i].assigned() && y[i].assigned() && (x[i].val() == y[i].val())); i++; } if (i == n) { // case: $ if (strict) goto rewrite_le; else goto rewrite_lq; } if (x[i].max() < y[i].min()) // case: < goto rewrite_lq; if (x[i].min() > y[i].max()) // case: > goto rewrite_le; if (i > 1) { // Remove equal elements [1...i-1], keep element [0] x[i-1]=x[0]; x.drop_fst(i-1); y[i-1]=y[0]; y.drop_fst(i-1); } } if (x[1].max() <= y[1].min()) { // case: <= (invariant: not =, <) /* * State 3 * prefix: (?|<=),<= * */ int i = 2; int n = x.size(); while ((i < n) && (x[i].max() == y[i].min())) // case: <=, = i++; if (i == n) { // case: $ if (strict) return ES_FIX; else goto rewrite_lq; } if (x[i].max() < y[i].min()) // case: < goto rewrite_lq; if (x[i].min() > y[i].max()) { // case: > // Eliminate [i]...[n-1] for (int j=i; j= y[1].max()) { // case: >= (invariant: not =, >) /* * State 4 * prefix: (?|<=) >= * */ int i = 2; int n = x.size(); while ((i < n) && (x[i].min() == y[i].max())) // case: >=, = i++; if (i == n) { // case: $ if (strict) goto rewrite_le; else return ES_FIX; } if (x[i].min() > y[i].max()) // case: > goto rewrite_le; if (x[i].max() < y[i].min()) { // case: < // Eliminate [i]...[n-1] for (int j=i; j::post(home,x[0],y[0])); rewrite_lq: GECODE_REWRITE(this,Lq::post(home,x[0],y[0])); } template ExecStatus Lex::post(Space* home, ViewArray& x, ViewArray& y, bool strict){ if (x.size() == 0) return strict ? ES_FAILED : ES_OK; if (x.size() == 1) { if (strict) return Le::post(home,x[0],y[0]); else return Lq::post(home,x[0],y[0]); } (void) new (home) Lex(home,x,y,strict); return ES_OK; } template size_t Lex::dispose(Space* home) { assert(!home->failed()); x.cancel(home,this,PC_INT_BND); y.cancel(home,this,PC_INT_BND); (void) Propagator::dispose(home); return sizeof(*this); } }}} // STATISTICS: int-prop