cbs.hpp
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
00031
00032
00033
00034 #ifdef GECODE_HAS_CBS
00035
00036 #include <limits>
00037 #include <algorithm>
00038
00039 namespace Gecode { namespace Int { namespace Distinct {
00040
00048 const int MAX_MINC_FACTORS = 400;
00049 extern const double mincFactors[MAX_MINC_FACTORS];
00050
00051 forceinline double
00052 getMincFactor(int domSize) {
00053 return mincFactors[domSize - 1];
00054 }
00055
00063 const int WIDTH_LIANG_BAI_FACTORS = 400;
00064 extern const double liangBaiFactors[WIDTH_LIANG_BAI_FACTORS * WIDTH_LIANG_BAI_FACTORS];
00065
00066 forceinline double
00067 getLiangBaiFactor(int index, int domSize) {
00068 return liangBaiFactors[index*WIDTH_LIANG_BAI_FACTORS + domSize - 1];
00069 }
00070
00075 class ValToUpdate {
00076 private:
00078 const int minVal;
00080 double* mincUpdate;
00082 double* liangUpdate;
00083 public:
00084 template<class View>
00085 ValToUpdate(const ViewArray<View>& x,
00086 int minDomVal, int maxDomVal, Region& r);
00092 double getMincUpdate(int val, unsigned int varSize) const;
00099 double getLiangUpdate(int val, unsigned int idx, unsigned int varSize) const;
00100 };
00101
00102 template<class View>
00103 forceinline
00104 ValToUpdate::ValToUpdate(const ViewArray<View>& x,
00105 int minDomVal, int maxDomVal, Region& r)
00106 : minVal(minDomVal) {
00107 unsigned int width = maxDomVal - minDomVal + 1;
00108 mincUpdate = r.alloc<double>(width);
00109 std::fill(mincUpdate, mincUpdate + width, 1);
00110 liangUpdate = r.alloc<double>(width);
00111 std::fill(liangUpdate, liangUpdate + width, 1);
00112
00113 for (int i=0; i<x.size(); i++) {
00114 if (x[i].assigned()) continue;
00115 size_t s = x[i].size();
00116 for (ViewValues<View> val(x[i]); val(); ++val) {
00117 int idx = val.val() - minVal;
00118 mincUpdate[idx] *= getMincFactor(s-1) / getMincFactor(s);
00119 liangUpdate[idx] *= getLiangBaiFactor(i, s-1) / getLiangBaiFactor(i, s);
00120 }
00121 }
00122 }
00123
00124 forceinline double
00125 ValToUpdate::getMincUpdate(int val, unsigned int varSize) const {
00126 return mincUpdate[val-minVal] / getMincFactor(varSize-1);
00127 }
00128
00129 forceinline double
00130 ValToUpdate::getLiangUpdate(int val, unsigned int idx,
00131 unsigned int varSize) const {
00132 return liangUpdate[val-minVal] / getLiangBaiFactor(idx, varSize-1);
00133 }
00134
00135
00136 template<class View>
00137 void cbsdistinct(Space&, unsigned int prop_id, const ViewArray<View>& x,
00138 Propagator::SendMarginal send) {
00139
00140
00141 struct UB {
00142 double minc;
00143 double liangBai;
00144 };
00145
00146 UB ub{1,1};
00147 for (int i=0; i<x.size(); i++) {
00148 unsigned int s = x[i].size();
00149 if ((s >= MAX_MINC_FACTORS) || (s >= WIDTH_LIANG_BAI_FACTORS))
00150 throw Gecode::Exception("Int::Distinct::cbsdistinct",
00151 "Variable cardinality too big for using counting-based"
00152 "search with distinct constraints");
00153 ub.minc *= getMincFactor(s);
00154 ub.liangBai *= getLiangBaiFactor(i, s);
00155 }
00156
00157
00158 int minVal = std::numeric_limits<int>::max();
00159 int maxVal = std::numeric_limits<int>::min();
00160 for (const auto& v : x) {
00161 if (v.assigned()) continue;
00162 minVal = std::min(v.min(), minVal);
00163 maxVal = std::max(v.max(), maxVal);
00164 }
00165
00166
00167
00168 Region r;
00169 ValToUpdate valToUpdate(x, minVal, maxVal, r);
00170
00171
00172
00173 double* solCounts = r.alloc<double>(maxVal - minVal + 1);
00174
00175 for (int i=0; i<x.size(); i++) {
00176 if (x[i].assigned()) continue;
00177
00178
00179 double normalization = 0;
00180
00181 for (ViewValues<View> val(x[i]); val(); ++val) {
00182 UB localUB = ub;
00183 int v = val.val();
00184 unsigned int s = x[i].size();
00185
00186
00187
00188 localUB.minc *= valToUpdate.getMincUpdate(v, s);
00189 localUB.liangBai *= valToUpdate.getLiangUpdate(v, i, s);
00190
00191
00192 double lowerUB = std::min(localUB.minc, ::sqrt(localUB.liangBai));
00193 solCounts[val.val() - minVal] = lowerUB;
00194 normalization += lowerUB;
00195 }
00196
00197
00198
00199 for (ViewValues<View> val(x[i]); val(); ++val) {
00200
00201
00202
00203
00204
00205 send(prop_id,
00206 x[i].id(),
00207 x[i].baseval(val.val()),
00208 solCounts[val.val() - minVal] / normalization);
00209 }
00210 }
00211 }
00212
00213 template<class View>
00214 void cbssize(const ViewArray<View>& x, Propagator::InDecision in,
00215 unsigned int& size, unsigned int& size_b) {
00216 size = 0;
00217 size_b = 0;
00218 for (const auto& v : x) {
00219 if (!v.assigned()) {
00220 size += v.size();
00221 if (in(v.id()))
00222 size_b += v.size();
00223 }
00224 }
00225 }
00226
00227 }}}
00228
00229 #endif
00230
00231
00232