base.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
00035
00036
00037
00038 namespace Gecode { namespace Int { namespace Circuit {
00039
00040 template<class View, class Offset>
00041 forceinline
00042 Base<View,Offset>::Base(Home home, ViewArray<View>& x, Offset& o0)
00043 : NaryPropagator<View,Int::PC_INT_DOM>(home,x),
00044 start(0), y(home,x), o(o0) {
00045 home.notice(*this,AP_WEAKLY);
00046 }
00047
00048 template<class View, class Offset>
00049 forceinline
00050 Base<View,Offset>::Base(Space& home, bool share, Base<View,Offset>& p)
00051 : NaryPropagator<View,Int::PC_INT_DOM>(home,share,p), start(p.start) {
00052 o.update(p.o);
00053 y.update(home,share,p.y);
00054 }
00055
00057 template<class View>
00058 class NodeInfo {
00059 public:
00060 int min, low, pre;
00061 Int::ViewValues<View> v;
00062 };
00063
00065 template<class View>
00066 class TellInfo {
00067 public:
00068 View x; int n;
00069 };
00070
00071 template<class View, class Offset>
00072 ExecStatus
00073 Base<View,Offset>::connected(Space& home) {
00074 int n = x.size();
00075
00077 {
00078 int v = start;
00080 int m = n;
00081 while (x[v].assigned()) {
00082 m--;
00083 v = o(x[v]).val();
00084
00085 if (start == v)
00086 return (m == 0) ? home.ES_SUBSUMED(*this) : ES_FAILED;
00087 }
00088 start = v;
00089 }
00090
00092 Region r(home);
00093 typedef typename Offset::ViewType OView;
00094 NodeInfo<OView>* si = r.alloc<NodeInfo<OView> >(n);
00095 unsigned int n_edges = 0;
00096 for (int i=n; i--; ) {
00097 n_edges += x[i].size();
00098 si[i].pre=-1;
00099 }
00100
00101
00102 Support::StaticStack<int,Region> next(r,n);
00103
00104
00105 TellInfo<OView>* eq = r.alloc<TellInfo<OView> >(n);
00106 int n_eq = 0;
00107
00108
00109 TellInfo<OView>* nq = r.alloc<TellInfo<OView> >(n_edges);
00110 int n_nq = 0;
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 {
00136
00137 int i = start;
00138
00139 int cnt = 0;
00140
00141 int subtree_min = 0;
00142
00143 int subtree_max = 0;
00144
00145 int back = 0;
00146 start:
00147 si[i].min = si[i].pre = si[i].low = cnt++;
00148 si[i].v.init(o(x[i]));
00149 do {
00150 if (si[si[i].v.val()].pre < 0) {
00151 next.push(i);
00152 i=si[i].v.val();
00153 goto start;
00154 } else if ((subtree_min <= si[si[i].v.val()].pre) &&
00155 (si[si[i].v.val()].pre <= subtree_max)) {
00156 back++;
00157 eq[n_eq].x = o(x[i]);
00158 eq[n_eq].n = si[i].v.val();
00159 } else if (si[si[i].v.val()].pre < subtree_min) {
00160 nq[n_nq].x = o(x[i]);
00161 nq[n_nq].n = si[i].v.val();
00162 n_nq++;
00163 }
00164 cont:
00165 if (si[si[i].v.val()].low < si[i].min)
00166 si[i].min = si[si[i].v.val()].low;
00167 ++si[i].v;
00168 } while (si[i].v());
00169 if (si[i].min < si[i].low) {
00170 si[i].low = si[i].min;
00171 } else if (i != start) {
00172
00173 return ES_FAILED;
00174 }
00175 if (!next.empty()) {
00176 i=next.pop();
00177 if (i == start) {
00178
00179 if (back == 0)
00180 return ES_FAILED;
00181
00182 if (back == 1)
00183 n_eq++;
00184 back = 0;
00185 subtree_min = subtree_max+1;
00186 subtree_max = cnt-1;
00187 }
00188 goto cont;
00189 }
00190
00191
00192 if (cnt != n)
00193 return ES_FAILED;
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 if (subtree_min > 1) {
00204 for (Int::ViewValues<OView> v(o(x[start])); v(); ++v)
00205 if (si[v.val()].pre < subtree_min) {
00206 nq[n_nq].x = o(x[v.val()]);
00207 nq[n_nq].n = v.val();
00208 n_nq++;
00209 }
00210 }
00211
00212 ExecStatus es = ES_FIX;
00213
00214 while (n_eq-- > 0) {
00215 ModEvent me = eq[n_eq].x.eq(home,eq[n_eq].n);
00216 if (me_failed(me))
00217 return ES_FAILED;
00218 if (me_modified(me))
00219 es = ES_NOFIX;
00220 }
00221
00222
00223 while (n_nq-- > 0) {
00224 ModEvent me = nq[n_nq].x.nq(home,nq[n_nq].n);
00225 if (me_failed(me))
00226 return ES_FAILED;
00227 if (me_modified(me))
00228 es = ES_NOFIX;
00229 }
00230
00231
00232 start = o(x[start]).min();
00233
00234 return es;
00235 }
00236 }
00237
00238 template<class View, class Offset>
00239 ExecStatus
00240 Base<View,Offset>::path(Space& home) {
00241
00242
00243 int n=x.size();
00244
00245 Region r(home);
00246
00247
00248
00249 int* end = r.alloc<int>(n);
00250 for (int i=n; i--; )
00251 end[i]=-1;
00252
00253
00254 Support::StaticStack<int,Region> tell(r,n);
00255
00256 typedef typename Offset::ViewType OView;
00257 for (int i=y.size(); i--; ) {
00258 assert(!y[i].assigned());
00259
00260 Int::ViewValues<OView> v(o(y[i]));
00261
00262 do {
00263 int j0=v.val();
00264
00265 if (x[j0].assigned() && (end[j0] < 0)) {
00266
00267
00268
00269
00270 int j = j0;
00271 do {
00272 j=o(x[j]).val();
00273 } while (x[j].assigned());
00274
00275
00276
00277 end[j0]=j; tell.push(j0);
00278 }
00279 ++v;
00280 } while (v());
00281 }
00282
00283
00284 while (!tell.empty()) {
00285 int i = tell.pop();
00286 assert(end[i] >= 0);
00287 GECODE_ME_CHECK(o(x[end[i]]).nq(home,i));
00288 }
00289 return ES_NOFIX;
00290 }
00291
00292 template<class View, class Offset>
00293 forceinline size_t
00294 Base<View,Offset>::dispose(Space& home) {
00295 home.ignore(*this,AP_WEAKLY);
00296 (void) NaryPropagator<View,Int::PC_INT_DOM>::dispose(home);
00297 return sizeof(*this);
00298 }
00299
00300 }}}
00301
00302
00303