Generated on Mon Aug 25 11:35:43 2008 for Gecode by doxygen 1.5.6

weights.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *     Christian Schulte <schulte@gecode.org>
00006  *     Gabor Szokoli <szokoli@gecode.org>
00007  *
00008  *  Copyright:
00009  *     Guido Tack, 2004
00010  *     Christian Schulte, 2004
00011  *     Gabor Szokoli, 2004
00012  *
00013  *  Last modified:
00014  *     $Date: 2008-01-31 18:29:16 +0100 (Thu, 31 Jan 2008) $ by $Author: tack $
00015  *     $Revision: 6017 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */
00041 
00042 #include "gecode/set.hh"
00043 #include "gecode/int.hh"
00044 
00045 namespace Gecode { namespace Set { namespace Int {
00046 
00048   template <class I>
00049   class OverweightValues {
00050   private:
00052     int threshold;
00054     I iter;
00056     const SharedArray<int> elements;
00058     const SharedArray<int> weights;
00060     int index;
00062     void next(void);
00063   public:
00065 
00066 
00067     OverweightValues(void);
00069     OverweightValues(int t,
00070                      SharedArray<int>& elements0,
00071                      SharedArray<int>& weights0,
00072                      I& i);
00074     void init(int t,
00075               SharedArray<int>& elements0,
00076               SharedArray<int>& weights0,
00077               I& i);
00079 
00081 
00082 
00083     bool operator()(void) const;
00085     void operator++(void);
00087 
00088 
00089 
00090     int  val(void) const;
00092   };
00093 
00094   template <class I>
00095   forceinline void
00096   OverweightValues<I>::next(void) {
00097     while (iter()) {
00098       while (elements[index]<iter.val()) index++;
00099       assert(elements[index]==iter.val());
00100       if (weights[index] > threshold) {
00101         return;
00102       }
00103       ++iter;
00104     }
00105   }
00106 
00107   template <class I>
00108   forceinline
00109   OverweightValues<I>::OverweightValues(void) {}
00110 
00111   template <class I>
00112   forceinline
00113   OverweightValues<I>::OverweightValues(int t,
00114                                         SharedArray<int>& elements0,
00115                                         SharedArray<int>& weights0,
00116                                         I& i) : threshold(t),
00117                                                 iter(i),
00118                                                 elements(elements0),
00119                                                 weights(weights0),
00120                                                 index(0) {
00121     next();
00122   }
00123 
00124   template <class I>
00125   forceinline void
00126   OverweightValues<I>::init(int t,
00127                             SharedArray<int>& elements0,
00128                             SharedArray<int>& weights0,
00129                             I& i) {
00130     threshold = t; iter = i;
00131     elements = elements0; weights = weights0;
00132     index = 0;
00133     next();
00134   }
00135 
00136   template <class I>
00137   forceinline bool
00138   OverweightValues<I>::operator()(void) const { return iter(); }
00139 
00140   template <class I>
00141   forceinline void
00142   OverweightValues<I>::operator++(void) { ++iter; next(); }
00143 
00144   template <class I>
00145   forceinline int
00146   OverweightValues<I>::val(void) const { return elements[index]; }
00147 
00148   template <class View>
00149   forceinline
00150   Weights<View>::Weights(Space* home,
00151                    const IntArgs& elements0, const IntArgs& weights0,
00152                    View x0, Gecode::Int::IntView y0)
00153     : Propagator(home), elements(elements0.size()), weights(weights0.size()),
00154       x(x0), y(y0) {
00155     x.subscribe(home,this, PC_SET_ANY);
00156     y.subscribe(home,this, Gecode::Int::PC_INT_BND);
00157     for (int i=elements0.size(); i--;) {
00158       elements[i] = elements0[i];
00159       weights[i] = weights0[i];
00160     }
00161   }
00162 
00163   template <class View>
00164   forceinline
00165   Weights<View>::Weights(Space* home, bool share, Weights& p)
00166     : Propagator(home,share,p) {
00167     x.update(home,share,p.x);
00168     y.update(home,share,p.y);
00169     elements.update(home,share,p.elements);
00170     weights.update(home,share,p.weights);
00171   }
00172 
00173   template <class View>
00174   inline ExecStatus
00175   Weights<View>::post(Space* home, const IntArgs& elements, const IntArgs& weights,
00176                 View x, Gecode::Int::IntView y) {
00177     if (elements.size() != weights.size())
00178       throw ArgumentSizeMismatch("Weights");
00179     GECODE_AUTOARRAY(int, els_arr, elements.size());
00180     for (int i=elements.size(); i--;)
00181       els_arr[i] = elements[i];
00182     IntSet els(els_arr, elements.size());
00183     IntSetRanges er(els);
00184     GECODE_ME_CHECK(x.intersectI(home, er));
00185     (void) new (home) Weights(home,elements,weights,x,y);
00186     return ES_OK;
00187   }
00188 
00189   template <class View>
00190   PropCost
00191   Weights<View>::cost(ModEventDelta) const {
00192     return PC_LINEAR_LO;
00193   }
00194 
00195   template <class View>
00196   size_t
00197   Weights<View>::dispose(Space* home) {
00198     assert(!home->failed());
00199     x.cancel(home,this, PC_SET_ANY);
00200     y.cancel(home,this, Gecode::Int::PC_INT_BND);
00201     (void) Propagator::dispose(home);
00202     return sizeof(*this);
00203   }
00204 
00205   template <class View>
00206   Actor*
00207   Weights<View>::copy(Space* home, bool share) {
00208     return new (home) Weights(home,share,*this);
00209   }
00210 
00211   enum CostType { POS_COST, NEG_COST, ALL_COST };
00212 
00213   template <class I, CostType c>
00214   forceinline
00215   int weightI(SharedArray<int>& elements,
00216               SharedArray<int>& weights,
00217               I& iter) {
00218     int sum = 0;
00219     int i = 0;
00220     for (Iter::Ranges::ToValues<I> v(iter); v(); ++v) {
00221       // Skip all elements below the current
00222       while (elements[i]<v.val()) i++;
00223       assert(elements[i] == v.val());
00224       switch (c) {
00225       case ALL_COST:
00226         sum += weights[i];
00227         break;
00228       case POS_COST:
00229         if (weights[i] > 0) sum += weights[i];
00230         break;
00231       case NEG_COST:
00232         if (weights[i] < 0) sum += weights[i];
00233         break;
00234       default: GECODE_NEVER;
00235       }
00236     }
00237     return sum;
00238   }
00239 
00240 
00242   class IntLt {
00243   public:
00244     bool operator()(int x, int y);
00245   };
00246 
00247   forceinline bool 
00248   IntLt::operator()(int x, int y) {
00249     return x < y;
00250   }
00251 
00252   template <class View>
00253   ExecStatus
00254   Weights<View>::propagate(Space* home, ModEventDelta) {
00255 
00256     if (x.assigned()) {
00257       GlbRanges<View> glb(x);
00258       int w = 
00259         weightI<GlbRanges<View>,ALL_COST>(elements, weights, glb);
00260       GECODE_ME_CHECK(y.eq(home, w));
00261       return ES_SUBSUMED(this,home);
00262     }
00263 
00264     int lowCost;
00265     int lowestCost;
00266     int highestCost;
00267     int size = elements.size();
00268     {
00269       UnknownRanges<View> ur(x);
00270       Iter::Ranges::ToValues<UnknownRanges<View> > urv(ur);
00271       GECODE_AUTOARRAY(int, currentWeights, size);
00272       for (int i=0; i<size; i++) {
00273         if (!urv() || elements[i]<urv.val()) {
00274           currentWeights[i] = 0;
00275         } else {
00276           assert(elements[i] == urv.val());
00277           currentWeights[i] = weights[i];
00278           ++urv;
00279         }
00280       }
00281 
00282       IntLt ilt;
00283       Support::quicksort<int>(currentWeights, size, ilt);
00284 
00285       GlbRanges<View> glb(x);
00286       lowCost = weightI<GlbRanges<View>,ALL_COST>(elements, weights, glb);
00287       highestCost =
00288         weightI<GlbRanges<View>,ALL_COST>(elements, weights, glb);
00289 
00290       int delta = std::min(x.unknownSize(), x.cardMax() - x.glbSize());
00291 
00292       for (int i=0; i<delta-1; i++) {
00293         if (currentWeights[i] >= 0)
00294           break;
00295         lowCost+=currentWeights[i];
00296       }
00297       lowestCost = lowCost;
00298       if (delta>0 && currentWeights[delta-1]<0)
00299         lowestCost+=currentWeights[delta-1];
00300 
00301       for (int i=0; i<delta; i++) {
00302         if (currentWeights[size-i-1]<=0)
00303           break;
00304         highestCost += currentWeights[size-i-1];
00305       }
00306 
00307     }
00308 
00309     GECODE_ME_CHECK(y.gq(home, lowestCost));
00310     GECODE_ME_CHECK(y.lq(home, highestCost));
00311 
00312     ModEvent me;
00313     {
00314       UnknownRanges<View> ur2(x);
00315       Iter::Ranges::ToValues<UnknownRanges<View> > urv(ur2);
00316       OverweightValues<Iter::Ranges::ToValues<UnknownRanges<View> > >
00317         ov(y.max()-lowCost, elements, weights, urv);
00318       Iter::Values::ToRanges<OverweightValues<
00319         Iter::Ranges::ToValues<UnknownRanges<View> > > > ovr(ov);
00320       me = x.excludeI(home, ovr);
00321       GECODE_ME_CHECK(me);
00322     }
00323 
00324     if (x.assigned()) {
00325       GlbRanges<View> glb(x);
00326       int w = 
00327         weightI<GlbRanges<View>,ALL_COST>(elements, weights, glb);
00328       GECODE_ME_CHECK(y.eq(home, w));
00329       return ES_SUBSUMED(this,home);
00330     }
00331     return me_modified(me) ? ES_NOFIX : ES_FIX;
00332   }
00333 
00334   template <class View>
00335   Support::Symbol
00336   Weights<View>::ati(void) {
00337     return Reflection::mangle<View>("Gecode::Set::Int::Weights");
00338   }
00339 
00340   template <class View>
00341   Reflection::ActorSpec
00342   Weights<View>::spec(const Space* home, Reflection::VarMap& m) const {
00343     Reflection::ActorSpec s(ati());
00344     return s << Reflection::Arg::newIntArray(elements)
00345              << Reflection::Arg::newIntArray(weights)
00346              << x.spec(home, m)
00347              << y.spec(home, m);
00348   }
00349 
00350   template <class View>
00351   void
00352   Weights<View>::post(Space* home, Reflection::VarMap& vars,
00353                       const Reflection::ActorSpec& spec) {
00354     spec.checkArity(4);
00355     Reflection::IntArrayArg* elementsArg = spec[0]->toIntArray();
00356     Reflection::IntArrayArg* weightsArg = spec[1]->toIntArray();
00357     IntArgs elements(elementsArg->size());
00358     IntArgs weights(weightsArg->size());
00359     for (int i=elementsArg->size(); i--;)
00360       elements[i] = (*elementsArg)[i];
00361     for (int i=weightsArg->size(); i--;)
00362       weights[i] = (*weightsArg)[i];
00363     View x0(home, vars, spec[2]);
00364     Gecode::Int::IntView x1(home, vars, spec[3]);
00365     (void) new (home) Weights<View>(home,elements,weights,x0,x1);
00366   }
00367 
00368 }}}
00369 
00370 // STATISTICS: set-prop