weights.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "gecode/set/int.hh"
00031
00032 #include "gecode/iter.hh"
00033
00034 using namespace Gecode::Int;
00035
00036 namespace Gecode { namespace Set { namespace Int {
00037
00038 PropCost
00039 Weights::cost(void) const {
00040 return PC_LINEAR_LO;
00041 }
00042
00043 size_t
00044 Weights::dispose(Space* home) {
00045 assert(!home->failed());
00046 x.cancel(home,this, PC_SET_ANY);
00047 y.cancel(home,this, Gecode::Int::PC_INT_BND);
00048 (void) Propagator::dispose(home);
00049 return sizeof(*this);
00050 }
00051
00052 Actor*
00053 Weights::copy(Space* home, bool share) {
00054 return new (home) Weights(home,share,*this);
00055 }
00056
00057 enum CostType { POS_COST, NEG_COST, ALL_COST };
00058
00059 template <class I, CostType c>
00060 forceinline
00061 int weightI(Support::SharedArray<int>& elements,
00062 Support::SharedArray<int>& weights,
00063 I& iter) {
00064 int sum = 0;
00065 int i = 0;
00066 for (Iter::Ranges::ToValues<I> v(iter); v(); ++v) {
00067
00068 while (elements[i]<v.val()) i++;
00069 assert(elements[i] == v.val());
00070 switch (c) {
00071 case ALL_COST:
00072 sum += weights[i];
00073 break;
00074 case POS_COST:
00075 if (weights[i] > 0) sum += weights[i];
00076 break;
00077 case NEG_COST:
00078 if (weights[i] < 0) sum += weights[i];
00079 break;
00080 default: GECODE_NEVER;
00081 }
00082 }
00083 return sum;
00084 }
00085
00086
00088 class IntLt {
00089 public:
00090 bool operator()(int x, int y);
00091 };
00092
00093 forceinline bool
00094 IntLt::operator()(int x, int y) {
00095 return x < y;
00096 }
00097
00098 ExecStatus
00099 Weights::propagate(Space* home) {
00100
00101 if (x.assigned()) {
00102 GlbRanges<SetView> glb(x);
00103 int w =
00104 weightI<GlbRanges<SetView>,ALL_COST>(elements, weights, glb);
00105 GECODE_ME_CHECK(y.eq(home, w));
00106 return ES_SUBSUMED;
00107 }
00108
00109 int lowCost;
00110 int lowestCost;
00111 int highestCost;
00112 int size = elements.size();
00113 {
00114 UnknownRanges<SetView> ur(x);
00115 Iter::Ranges::ToValues<UnknownRanges<SetView> > urv(ur);
00116 GECODE_AUTOARRAY(int, currentWeights, size);
00117 for (int i=0; i<size; i++) {
00118 if (!urv() || elements[i]<urv.val()) {
00119 currentWeights[i] = 0;
00120 } else {
00121 assert(elements[i] == urv.val());
00122 currentWeights[i] = weights[i];
00123 ++urv;
00124 }
00125 }
00126
00127 IntLt ilt;
00128 Support::quicksort<int>(currentWeights, size, ilt);
00129
00130 GlbRanges<SetView> glb(x);
00131 lowCost = weightI<GlbRanges<SetView>,ALL_COST>(elements, weights, glb);
00132 highestCost =
00133 weightI<GlbRanges<SetView>,ALL_COST>(elements, weights, glb);
00134
00135 int delta = std::min(x.unknownSize(), x.cardMax() - x.glbSize());
00136
00137 for (int i=0; i<delta-1; i++) {
00138 if (currentWeights[i] >= 0)
00139 break;
00140 lowCost+=currentWeights[i];
00141 }
00142 lowestCost = lowCost;
00143 if (delta>0 && currentWeights[delta-1]<0)
00144 lowestCost+=currentWeights[delta-1];
00145
00146 for (int i=0; i<delta; i++) {
00147 if (currentWeights[size-i-1]<=0)
00148 break;
00149 highestCost += currentWeights[size-i-1];
00150 }
00151
00152 }
00153
00154 GECODE_ME_CHECK(y.gq(home, lowestCost));
00155 GECODE_ME_CHECK(y.lq(home, highestCost));
00156
00157 ModEvent me;
00158 {
00159 UnknownRanges<SetView> ur2(x);
00160 Iter::Ranges::ToValues<UnknownRanges<SetView> > urv(ur2);
00161 OverweightValues<Iter::Ranges::ToValues<UnknownRanges<SetView> > >
00162 ov(y.max()-lowCost, elements, weights, urv);
00163 Iter::Values::ToRanges<OverweightValues<
00164 Iter::Ranges::ToValues<UnknownRanges<SetView> > > > ovr(ov);
00165 me = x.excludeI(home, ovr);
00166 GECODE_ME_CHECK(me);
00167 }
00168
00169 if (x.assigned()) {
00170 GlbRanges<SetView> glb(x);
00171 int w =
00172 weightI<GlbRanges<SetView>,ALL_COST>(elements, weights, glb);
00173 GECODE_ME_CHECK(y.eq(home, w));
00174 return ES_SUBSUMED;
00175 }
00176 return me_modified(me) ? ES_NOFIX : ES_FIX;
00177 }
00178
00179
00180 }}}
00181
00182