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 #include <gecode/search/nogoods.hh>
00035
00036 namespace Gecode { namespace Search {
00037
00039 forceinline NGL*
00040 disposenext(NGL* ngl, Space& home, Propagator& p, bool c) {
00041 NGL* n = ngl->next();
00042 if (c)
00043 ngl->cancel(home,p);
00044 home.rfree(ngl,ngl->dispose(home));
00045 return n;
00046 }
00047
00048 void
00049 NoNGL::subscribe(Space&, Propagator&) {
00050 GECODE_NEVER;
00051 }
00052 void
00053 NoNGL::cancel(Space&, Propagator&) {
00054 GECODE_NEVER;
00055 }
00056 void
00057 NoNGL::reschedule(Space&, Propagator&) {
00058 GECODE_NEVER;
00059 }
00060 NGL::Status
00061 NoNGL::status(const Space&) const {
00062 GECODE_NEVER;
00063 return NGL::NONE;
00064 }
00065 ExecStatus
00066 NoNGL::prune(Space&) {
00067 GECODE_NEVER;
00068 return ES_OK;
00069 }
00070 NGL*
00071 NoNGL::copy(Space&) {
00072 GECODE_NEVER;
00073 return NULL;
00074 }
00075
00076 Actor*
00077 NoGoodsProp::copy(Space& home) {
00078 return new (home) NoGoodsProp(home,*this);
00079 }
00080
00081 PropCost
00082 NoGoodsProp::cost(const Space&, const ModEventDelta&) const {
00083 return PropCost::linear(PropCost::LO,n);
00084 }
00085
00086 void
00087 NoGoodsProp::reschedule(Space& home) {
00088 root->reschedule(home,*this);
00089 NGL* l = root->next();
00090 while ((l != NULL) && l->leaf()) {
00091 l->reschedule(home,*this);
00092 l = l->next();
00093 }
00094 if (l != NULL)
00095 l->reschedule(home,*this);
00096 }
00097
00098
00099 ExecStatus
00100 NoGoodsProp::propagate(Space& home, const ModEventDelta&) {
00101 restart:
00102
00103 switch (root->status(home)) {
00104 case NGL::FAILED:
00105
00106 return home.ES_SUBSUMED(*this);
00107 case NGL::SUBSUMED:
00108 {
00109 NGL* l = disposenext(root,home,*this,true); n--;
00110
00111 while ((l != NULL) && l->leaf()) {
00112 l->cancel(home,*this); n--;
00113 GECODE_ES_CHECK(l->prune(home));
00114 l = disposenext(l,home,*this,false);
00115 }
00116 root = l;
00117
00118 if (l == NULL)
00119 return home.ES_SUBSUMED(*this);
00120
00121 l = l->next();
00122
00123 while ((l != NULL) && l->leaf()) {
00124 l->subscribe(home,*this); n++;
00125 l = l->next();
00126 }
00127
00128 if (l != NULL) {
00129 l->subscribe(home,*this); n++;
00130 }
00131 goto restart;
00132 }
00133 case NGL::NONE:
00134 break;
00135 default: GECODE_NEVER;
00136 }
00137
00138 {
00139 NGL* p = root;
00140 NGL* l = p->next();
00141
00142
00143 while ((l != NULL) && l->leaf()) {
00144 switch (l->status(home)) {
00145 case NGL::SUBSUMED:
00146 l = disposenext(l,home,*this,true); n--;
00147 p->next(l);
00148 GECODE_ES_CHECK(root->prune(home));
00149 if (root->status(home) == NGL::FAILED)
00150 return home.ES_SUBSUMED(*this);
00151 break;
00152 case NGL::FAILED:
00153 l = disposenext(l,home,*this,true); n--;
00154 p->next(l);
00155 break;
00156 case NGL::NONE:
00157 p = l; l = l->next();
00158 break;
00159 default: GECODE_NEVER;
00160 }
00161 }
00162
00163
00164 if (l != NULL) {
00165 switch (l->status(home)) {
00166 case NGL::FAILED:
00167 (void) disposenext(l,home,*this,true); n--;
00168
00169 p->next(NULL);
00170 break;
00171 case NGL::SUBSUMED:
00172 {
00173
00174 l = disposenext(l,home,*this,true); n--;
00175 p->next(l);
00176
00177 while ((l != NULL) && l->leaf()) {
00178 l->subscribe(home,*this); n++;
00179 l = l->next();
00180 }
00181 if (l != NULL) {
00182 l->subscribe(home,*this); n++;
00183 }
00184 }
00185 break;
00186 case NGL::NONE:
00187 break;
00188 default: GECODE_NEVER;
00189 }
00190 }
00191 }
00192 return ES_NOFIX;
00193 }
00194
00195 size_t
00196 NoGoodsProp::dispose(Space& home) {
00197 if (home.failed()) {
00198
00199 NGL* l = root;
00200 while (l != NULL) {
00201 NGL* t = l->next();
00202 (void) l->dispose(home);
00203 l = t;
00204 }
00205 } else if (root != NULL) {
00206
00207 NGL* l = disposenext(root,home,*this,true);
00208 while ((l != NULL) && l->leaf())
00209 l = disposenext(l,home,*this,true);
00210 if (l != NULL)
00211 l = disposenext(l,home,*this,true);
00212 while (l != NULL)
00213 l = disposenext(l,home,*this,false);
00214 }
00215 home.ignore(*this,AP_DISPOSE,true);
00216 (void) Propagator::dispose(home);
00217 return sizeof(*this);
00218 }
00219
00220 }}
00221
00222