/Users/jamian/qecode-1.1/qecode/implicative.cc

Go to the documentation of this file.
00001 /*************************************************************[implicative.cc]
00002 Copyright (c) 2007, Universite d'Orleans - Jeremie Vautard, Marco Benedetti,
00003 Arnaud Lallouet.
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 *****************************************************************************/
00023 #include "implicative.hh"
00024 #include "myDom.cc"
00025 
00026 Implicative::Implicative(int ns,bool firstQ,int* nv, int prop) : QSpace(1) {
00027     n=0;
00028     for (int i=0;i<ns;i++) {
00029         n += nv[i];
00030     }
00031     nbSpaces=ns;
00032     v=IntVarArgs(n);
00033     q=new bool[n];
00034     whichSpaceOwns=new int[n];
00035     nbVarBySpace=new int[nbSpaces];
00036     rules=new MySpace*[ns];
00037     ruleDefined=new bool[n];
00038     nbVarBySpace[0]=nv[0];
00039     rules[0]=new MySpace(nbVarBySpace[0]);
00040     ruleDefined[0] = true;
00041     for (int i=1;i<nbSpaces;i++) {
00042         nbVarBySpace[i]=nbVarBySpace[i-1]+nv[i];
00043         rules[i]=new MySpace(nbVarBySpace[i]);
00044         ruleDefined[i]=true;
00045     }
00046     goal=new MySpace(n);
00047     goalDefined=true;
00048     for(int i=0;i<n;i++) {
00049         int lespace=0;
00050         while (nbVarBySpace[lespace]<=i) lespace++;
00051         whichSpaceOwns[i]=lespace;
00052         q[i] = ((lespace%2 == 0) ? firstQ : !firstQ);
00053     }
00054     
00055     varInitialised=new bool[n];
00056     for (int i=0;i<n;i++) varInitialised[i]=false;
00057     currentDeclareSpace=0;
00058     prop_power=prop;
00059 }
00060 
00061 
00062 Implicative::Implicative(Implicative& qc) : QSpace(qc) {
00063     
00064     unsigned long int rien;
00065     q=qc.q;
00066     nbSpaces=qc.nbSpaces;          //  | Shared among every descendants of Implicatives
00067     nbVarBySpace=qc.nbVarBySpace;  //  |
00068     whichSpaceOwns=qc.whichSpaceOwns;//|
00069         varInitialised=qc.varInitialised;//|
00070             rules = new MySpace*[n];
00071             ruleDefined=new bool[n];
00072             w=qc.w;
00073             w->update(this);
00074             prop_power=qc.prop_power;
00075             
00076             for (int i=0;i<nbSpaces;i++) {
00077                 if (!qc.ruleDefined[i]) {
00078                     ruleDefined[i]=false;
00079                 }
00080                 else if (qc.rules[i]->status(rien) == SS_FAILED) {
00081                     ruleDefined[i]=false;
00082                 }
00083                 else {
00084                     rules[i]=static_cast<MySpace*>(qc.rules[i]->clone());
00085                     ruleDefined[i]=true;
00086                 }
00087             }
00088             if (!qc.goalDefined) {
00089                 goalDefined=false;
00090             }
00091             else if (qc.goal->status(rien) == SS_FAILED) {
00092                 goalDefined=false;
00093             }
00094             else {
00095                 goal=static_cast<MySpace*>(qc.goal->clone());
00096                 goalDefined=true;
00097             }
00098             
00099             for (int i=0;i<n;i++) {
00100                 if (ruleDefined[whichSpaceOwns[i]]) {
00101                     v[i] = (rules[whichSpaceOwns[i]]->v[i]);
00102                 }
00103             }
00104             
00105             
00106 }
00107 
00108 
00109 Implicative::~Implicative() {
00110     for (int i=0;i<nbSpaces;i++) {
00111         if (ruleDefined[i])
00112             delete rules[i];
00113     }    
00114     
00115     if (goalDefined) 
00116         delete goal;
00117     delete rules;
00118     delete ruleDefined;
00119 }
00120 
00121 
00122 int Implicative::spaces() {
00123     return nbSpaces;
00124 }
00125 
00126 
00127 void Implicative::QIntVar(int var,int min,int max) {
00128     if (varInitialised[var]) {
00129         cout<<"Variable "<<var<<"  Already created !!"<<endl;
00130         abort();
00131     }
00132     
00133     for (int i=whichSpaceOwns[var];i<nbSpaces;i++) {
00134         rules[i]->v[var] = IntVar(rules[i],min,max);
00135     }
00136     goal->v[var] = IntVar(goal,min,max);
00137     varInitialised[var]=true;
00138 }
00139 
00140 
00141 void Implicative::QBoolVar(int var,int min,int max) {
00142     if (varInitialised[var]) {
00143         cout<<"Variable "<<var<<" Already created !!"<<endl;
00144         abort();
00145     }
00146     
00147     for (int i=whichSpaceOwns[var];i<nbSpaces;i++) {
00148         rules[i]->v[var] = BoolVar(rules[i],min,max);
00149     }
00150     goal->v[var] = BoolVar(goal,min,max);
00151     varInitialised[var]=true;
00152 }
00153 
00154 
00155 void Implicative::QIntVar(int var,IntSet dom) {
00156     if (varInitialised[var]) {
00157         cout<<"Variable "<<var<<" Already created !!"<<endl;
00158         abort();
00159     }
00160     
00161     for (int i=whichSpaceOwns[var];i<nbSpaces;i++) {
00162         rules[i]->v[var] = IntVar(rules[i],dom);
00163     }
00164     goal->v[var] = IntVar(goal,dom);
00165     varInitialised[var]=true;
00166 }
00167 
00168 
00169 MySpace* Implicative::space() {
00170     if (currentDeclareSpace<nbSpaces)
00171         return rules[currentDeclareSpace];
00172     if (currentDeclareSpace==nbSpaces)
00173         return goal;
00174     return NULL;
00175 }
00176 
00177 
00178 IntVar Implicative::var(int n) {
00179     return space()->v[n];
00180 }
00181 
00182 
00183 BoolVar Implicative::bvar(int n) {
00184     return static_cast<BoolVar>(space()->v[n]);
00185 }
00186 
00187 
00188 int Implicative::nextScope() {
00189     if (currentDeclareSpace == -1) return -1;
00190     currentDeclareSpace++;
00191     if (currentDeclareSpace>nbSpaces) return -1;
00192     return currentDeclareSpace;
00193 }
00194 
00195 
00196 MySpace* Implicative::getRuleSpace(int sp) {
00197     bool var=true;
00198     for(int i=0;i<n;i++) {
00199         var = var && varInitialised[i];
00200     }
00201     if (!var) return NULL;
00202     if ( sp >= nbSpaces ) return NULL;
00203     return rules[sp];
00204 }
00205 
00206 
00207 MySpace* Implicative::getGoalSpace() {
00208     bool var=true;
00209     for(int i=0;i<n;i++) {
00210         var = var && varInitialised[i];
00211     }
00212     if (!var) return NULL;
00213     return goal;
00214 }
00215 
00216 
00217 void Implicative::makeStructure() {
00218     bool varInit=true;
00219     for (int i=0;i<n;i++) {
00220         if (varInitialised[i] == false) {
00221             cout<<"Can't make structure : variable "<<i<<" not initialised"<<endl;
00222             abort();
00223         }
00224     }
00225     
00226     for (int i=0;i<n;i++) {
00227         v[i] = rules[whichSpaceOwns[i]]->v[i];
00228     }
00229     w=new Warner(this);
00230     for(int i=0;i<n;i++) {
00231         WarningProp::warning(rules[whichSpaceOwns[i]],i,rules[whichSpaceOwns[i]]->v[i],w);
00232     } 
00233 }
00234 
00235 
00236 bool Implicative::quantification(int v) {
00237     return q[v];
00238 }
00239 
00240 // Returns the number of the first failed space (number of rule space, nbSpaces if goal, nbSpaces+1 if there is no failed space)
00241 int Implicative::cascade(int firstSpace, unsigned long int& propsteps) {
00242     int curSpace = firstSpace;
00243     
00244     while(curSpace < nbSpaces) {
00245         MySpace* nextSpace = (curSpace==nbSpaces-1)?goal:rules[curSpace+1];
00246         bool* nextDefined  = (curSpace==nbSpaces-1)?&goalDefined:&(ruleDefined[curSpace+1]);
00247         
00248         if (!ruleDefined[curSpace]) {
00249             return curSpace;
00250         }
00251         if (rules[curSpace]->status(propsteps) == SS_FAILED) {
00252             return curSpace;
00253         }
00254         if (*nextDefined) {
00255             if (nextSpace->status(propsteps) != SS_FAILED) {
00256                 for (int i=0;i<nbVarBySpace[curSpace];i++) {
00257                     IntView dest(nextSpace->v[i]);
00258                     IntView src(rules[curSpace]->v[i]);
00259                     ViewRanges<IntView> rg(src);
00260                     if (dest.inter(nextSpace,rg) == ME_GEN_FAILED) {
00261                         nextSpace->fail();
00262                     }
00263                 }
00264             }
00265         }
00266         curSpace++;
00267     }
00268     
00269     if (!goalDefined) {
00270         return nbSpaces;
00271     }
00272     if (goal->status(propsteps) == SS_FAILED) {
00273         return nbSpaces;
00274     }
00275     
00276     return nbSpaces+1;
00277 }
00278 
00279 
00280 int Implicative::status(int var, unsigned long int& propsteps) {
00281     int currentSpace=whichSpaceOwns[var];
00282     currentSpace--;
00283     if (currentSpace<0) currentSpace=0;
00284     
00285     // First case : Strong propagation : ///////////////////////////////////////////
00286     // First, call cascade propagation. ////////////////////////////////////////////
00287     // We fail the spaces after the first failed one (so they are not //////////////
00288     // copied anymore)//////////////////////////////////////////////////////////////
00289     if (prop_power == 2) {                                                        //
00290         int firstFailed=cascade(currentSpace,propsteps);                          //
00291         for (int i=firstFailed;i<nbSpaces;i++) {                                  //
00292             if (ruleDefined[i]) rules[i]->fail();                                 //
00293         }                                                                         //
00294         if (firstFailed <= nbSpaces) {                                            //
00295             if (goalDefined)                                                      //
00296                 goal->fail();                                                     //
00297         }                                                                         //
00298                                                                                   //
00299         if (firstFailed==currentSpace) {                                          //
00300             return (quantification(var)?1:0);                                     //
00301         }                                                                         //
00302                                                                                   //
00303         return -1;                                                                //
00304     }                                                                             //
00306     
00307     /*
00308      // Step 3, third case : ////////////////////////////////////////////////////////
00309      // If the trick is used, cascade propagation is performed, then ////////////////
00310      // a little check is done about the ability of the problem to be solved ////////
00311      // with the trick. Finally, the answer is given. ///////////////////////////////
00312      else if (prop_power == 3) {                                                   //
00313          int firstFailed=cascade(currentSpace,propsteps);                            //
00314                                                                                      //   cout<<"Firstfailed = "<<firstFailed<<endl;                                //
00315          if (firstFailed < nbSpaces) {                                               //
00316              cout<<"This problem doesn't resolve with the trick.";                     //
00317              cout<<"Retry with a smaller propagation strength"<<endl;                  //
00318              abort();                                                                  //
00319          }                                                                           //
00320          if (firstFailed == nbSpaces)                                                //
00321              return 0;                                                                 //
00322          return -1;                                                                  //
00323      }                                                                             //
00325      */
00326     else {
00327         cout<<"Propagation "<<prop_power<<" is not supported in this version of Qecode."<<endl;
00328         abort();
00329     }
00330 }
00331 
00332 
00333 int Implicative::finalStatus(unsigned long int& propsteps) {
00334     
00335     // Step 1 : we check every rule space in the order. If one of them is failed, //
00336     // we can answer. //////////////////////////////////////////////////////////////
00337     for (int i=0;i<nbSpaces;i++) {                                                //
00338         if (!ruleDefined[i])                                                        //
00339             return q[ nbVarBySpace[i]-1 ] ? 1 : 0;                                    //
00340         if (rules[i]->status(propsteps) == SS_FAILED)                               //
00341             return q[ nbVarBySpace[i]-1 ] ? 1 : 0;                                    //
00342     }                                                                             //
00344     
00345     // Step 2 : if we are here, then the rules were not violated. So, we check /////
00346     // the goal. ///////////////////////////////////////////////////////////////////
00347     if (!goalDefined)                                                             //
00348         return 0;                                                                   //
00349     if (goal->status(propsteps) == SS_FAILED)                                     //
00350         return 0;                                                                   //
00352     
00353     // Step 3 : if we are here, then the rules were respected, and the goal ////////
00354     // is also true. So, the whole problem is true. ////////////////////////////////
00355     return 1;                                                                     //
00357 }
00358 
00359 bool Implicative::subsumed(int var) {
00360     
00361     int varSpace=whichSpaceOwns[var];
00362     if (!ruleDefined[varSpace])
00363         return true;
00364     int varSize=rules[varSpace]->v[var].size();
00365     
00366     if (rules[varSpace]->v[var].size() < 2)
00367         return true;
00368     
00369     if (rules[varSpace]->v[var].degree() > 1) 
00370         return false;
00371     
00372     
00373     for (int i=varSpace+1;i<nbSpaces;i++) {
00374         if (!ruleDefined[i])
00375             return true;
00376         if (rules[i]->v[var].degree() > 0)
00377             return false;
00378         if (rules[i]->v[var].size() < varSize)
00379             return false;
00380     }
00381     
00382     if (!goalDefined)
00383         return true;
00384     if (goal->v[var].degree() >0)
00385         return false;
00386     if (goal->v[var].size() < varSize)
00387         return false;
00388     
00389     
00390     return true;
00391 }
00392 
00393 
00394 Implicative* Implicative::clone() {
00395     Implicative* resultat=new Implicative(*this);
00396     return resultat;
00397 }
00398 
00399 
00400 void Implicative::assign(int var,int** vals,int nbVals) {
00401     int varspace = whichSpaceOwns[var];
00402     for (int i=varspace;i<nbSpaces;i++) {
00403         if (ruleDefined[i]) {
00404             MySpace* s = rules[i];
00405             post(s,s->v[var] >= vals[0][0]);
00406             for (int j=1;j<nbVals;j++) {
00407                 IntSet rg(vals[1][j-1]+1,vals[0][j]-1);
00408                 antidom(s,s->v[var],rg,ICL_DOM);
00409             }
00410             post(s,s->v[var] <= vals[1][nbVals-1]);
00411         }
00412     }
00413 }
00414 
00415 
00416 void Implicative::remove(int var,int** vals,int nbVals) {
00417     int varspace = whichSpaceOwns[var];
00418     for (int i=varspace;i<nbSpaces;i++) {
00419         if (ruleDefined[i]) {
00420             MySpace* s = rules[i];
00421             for (int j=0;j<nbVals;j++) {
00422                 IntSet rg(vals[0][j],vals[1][j]);
00423                 antidom(s,s->v[var],rg,ICL_DOM);
00424             }
00425         }
00426     }
00427 }
00428 
00429 
00430 void Implicative::backtrack() {
00431     w->update(this);
00432 }
00433 
00434 
00435 void Implicative::indicateBranchingHeuristic(BranchingHeuristic* bh) {
00436     w->setBH(bh);
00437 }
00438 
00439 void Implicative::print() {
00440     for (int i=0;i<nv();i++)
00441         cout<<(q[i]?"A":"E");
00442     cout<<endl;
00443     for (int i=0;i<nbSpaces;i++) {
00444         if (ruleDefined[i]) {
00445             for (int j=0;j<nbVarBySpace[i];j++)
00446                 cout<<rules[i]->v[j]<<" ";
00447             cout<<endl;
00448         }
00449         else cout<<"Undefined"<<endl;
00450     }
00451     if (goalDefined) {
00452         for (int j=0;j<nv();j++)
00453             cout<<goal->v[j]<<" ";
00454         cout<<endl;
00455     }
00456     else cout<<"Undefined"<<endl;
00457     cout<<endl<<endl;
00458 }

Generated on Fri Sep 21 16:36:36 2007 for qecode by  doxygen 1.5.2