Generated on Fri Mar 20 15:56:04 2015 for Gecode by doxygen 1.6.3

argmax.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2015
00008  *
00009  *  Last modified:
00010  *     $Date: 2015-03-20 15:37:34 +0100 (Fri, 20 Mar 2015) $ by $Author: schulte $
00011  *     $Revision: 14471 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/int/rel.hh>
00039 
00040 namespace Gecode { namespace Int { namespace Arithmetic {
00041 
00042   template<class VA, class VB, bool tiebreak>
00043   forceinline
00044   ArgMax<VA,VB,tiebreak>::ArgMax(Home home, IdxViewArray<VA>& x0, VB y0)
00045     : Propagator(home), x(x0), y(y0) {
00046     x.subscribe(home,*this,PC_INT_BND);
00047     y.subscribe(home,*this,PC_INT_DOM);
00048   }
00049 
00050   template<class VA, class VB, bool tiebreak>
00051   ExecStatus
00052   ArgMax<VA,VB,tiebreak>::post(Home home, IdxViewArray<VA>& x, VB y) {
00053     assert(x.size() > 0);
00054     if (x.size() == 1) {
00055       GECODE_ME_CHECK(y.eq(home,x[0].idx));
00056     } else if (y.assigned()) {
00057       int max=0;
00058       while (x[max].idx < y.val())
00059         max++;
00060       assert(x[max].idx == y.val());
00061       if (tiebreak)
00062         for (int i=0; i<max; i++)
00063           GECODE_ES_CHECK(Rel::Le<VA>::post(home,
00064                                             x[i].view,x[max].view));
00065       else
00066         for (int i=0; i<max; i++)
00067           GECODE_ES_CHECK(Rel::Lq<VA>::post(home,
00068                                             x[i].view,x[max].view));
00069       for (int i=max+1; i<x.size(); i++)
00070         GECODE_ES_CHECK(Rel::Lq<VA>::post(home,
00071                                           x[i].view,x[max].view));
00072     } else {
00073       (void) new (home) ArgMax<VA,VB,tiebreak>(home,x,y);
00074     }
00075     return ES_OK;
00076   }
00077 
00078   template<class VA, class VB, bool tiebreak>
00079   forceinline
00080   ArgMax<VA,VB,tiebreak>::ArgMax(Space& home, bool share, 
00081                                         ArgMax<VA,VB,tiebreak>& p)
00082     : Propagator(home,share,p) {
00083     x.update(home,share,p.x);
00084     y.update(home,share,p.y);
00085   }
00086 
00087   template<class VA, class VB, bool tiebreak>
00088   Actor*
00089   ArgMax<VA,VB,tiebreak>::copy(Space& home, bool share) {
00090     return new (home) ArgMax<VA,VB,tiebreak>(home,share,*this);
00091   }
00092 
00093   template<class VA, class VB, bool tiebreak>
00094   PropCost
00095   ArgMax<VA,VB,tiebreak>::cost(const Space&, 
00096                                       const ModEventDelta&) const {
00097     return PropCost::linear(PropCost::LO,x.size()+1);
00098   }
00099 
00100   template<class VA, class VB, bool tiebreak>
00101   ExecStatus
00102   ArgMax<VA,VB,tiebreak>::propagate(Space& home, const ModEventDelta&) {
00103     /*
00104      * A key invariant is as follows: for each value i in the domain
00105      * of y there is an index-value pair with index i in x.
00106      */
00107 
00108     // Compute lower and upper bounds for the maximum and its first position.
00109     int p = x[0].idx;
00110     int l = x[0].view.min();
00111     int u = x[0].view.max();
00112     for (int i=1; i<x.size(); i++) {
00113       if (l < x[i].view.min()) {
00114         p = x[i].idx; l = x[i].view.min();
00115       }
00116       if (u < x[i].view.max())
00117         u = x[i].view.max();
00118     }
00119       
00120     // Eliminate elements from x and y that are too small
00121     {
00122       Region r(home);
00123    
00124       // Values to delete from y
00125       int* d=r.alloc<int>(y.size());
00126       // Number of values to delete
00127       int  n = 0;
00128 
00129       int i=0, j=0;
00130       ViewValues<VB> iy(y);
00131 
00132       while ((i < x.size()) && iy()) {
00133         if (x[i].idx == iy.val()) {
00134           if (x[i].view.max() < l) {
00135             x[i].view.cancel(home,*this,PC_INT_BND); 
00136             d[n++]=x[i].idx;
00137           } else {
00138             x[j++]=x[i];
00139           }
00140           ++iy;
00141         } else {
00142           assert(x[i].idx < iy.val());
00143           if (x[i].view.max() < l) {
00144             x[i].view.cancel(home,*this,PC_INT_BND);
00145           } else {
00146             x[j++]=x[i];
00147           }
00148         }
00149         i++;
00150       }
00151       while (i < x.size())
00152         if (x[i].view.max() < l) {
00153           x[i].view.cancel(home,*this,PC_INT_BND); i++;
00154         } else {
00155           x[j++]=x[i++];
00156         }
00157       x.size(j);
00158 
00159       if (static_cast<unsigned int>(n) == y.size())
00160         return ES_FAILED;
00161       Iter::Values::Array id(d,n);
00162       GECODE_ME_CHECK(y.minus_v(home,id,false));
00163     }
00164 
00165     /*
00166      * Now the following invariant holds:
00167      * - for all q in y: u >= x(q).max() >= l
00168      * - if l==u, then exists q in y: x(q).max = u
00169      */
00170 
00171     if (tiebreak && (l == u))
00172       GECODE_ME_CHECK(y.lq(home,p));
00173 
00174     if (y.assigned()) {
00175       int max=0;
00176       while (x[max].idx < y.val())
00177         max++;
00178       assert(x[max].idx == y.val());
00179       if (tiebreak)
00180         for (int i=0; i<max; i++)
00181           GECODE_ES_CHECK(Rel::Le<VA>::post(home(*this),
00182                                             x[i].view,x[max].view));
00183       else
00184         for (int i=0; i<max; i++)
00185           GECODE_ES_CHECK(Rel::Lq<VA>::post(home(*this),
00186                                             x[i].view,x[max].view));
00187       for (int i=max+1; i<x.size(); i++)
00188         GECODE_ES_CHECK(Rel::Lq<VA>::post(home(*this),
00189                                           x[i].view,x[max].view));
00190       return home.ES_SUBSUMED(*this);
00191     }
00192 
00193     // Recompute the upper bound for elements in y
00194     {
00195       ViewValues<VB> iy(y);
00196       int i=0;
00197       // Skip smaller elements
00198       while (x[i].idx < y.min())
00199         i++;
00200       u=x[i].view.max();
00201       // Skip the minimal element
00202       i++; ++iy;
00203       while (iy()) {
00204         if (x[i].idx == iy.val()) {
00205           u = std::max(u,x[i].view.max());
00206           ++iy;
00207         } else {
00208           assert(x[i].idx < iy.val());
00209         }
00210         i++;
00211       }
00212     }
00213 
00214     // Constrain elements in x but not in y
00215     {
00216       int i = 0;
00217       // Elements which must be smaller (for tiebreaking)
00218       if (tiebreak)
00219         while ((i < x.size()) && (x[i].idx < y.min())) {
00220           GECODE_ME_CHECK(x[i].view.le(home,u));
00221           i++;
00222         }
00223       else
00224         while ((i < x.size()) && (x[i].idx < y.min())) {
00225           GECODE_ME_CHECK(x[i].view.lq(home,u));
00226           i++;
00227         }
00228       assert(x[i].idx == y.min());
00229 
00230       // Elements which cannot be larger
00231       ViewValues<VB> iy(y);
00232       // Skip the minimal element
00233       i++; ++iy;
00234       while ((i < x.size()) && iy()) {
00235         if (x[i].idx == iy.val()) {
00236           ++iy;
00237         } else {
00238           assert(x[i].idx < iy.val());
00239           GECODE_ME_CHECK(x[i].view.lq(home,u));
00240         }
00241         i++;
00242       }
00243       while (i < x.size()) {
00244         assert(x[i].idx > y.max());
00245         GECODE_ME_CHECK(x[i].view.lq(home,u));
00246         i++;
00247       }
00248     }
00249     return tiebreak ? ES_NOFIX : ES_FIX;
00250   }
00251 
00252   template<class VA, class VB, bool tiebreak>
00253   forceinline size_t
00254   ArgMax<VA,VB,tiebreak>::dispose(Space& home) {
00255     x.cancel(home,*this,PC_INT_BND);
00256     y.cancel(home,*this,PC_INT_DOM);
00257     (void) Propagator::dispose(home);
00258     return sizeof(*this);
00259   }
00260 
00261 }}}
00262 
00263 // STATISTICS: int-prop
00264