powerset.h

00001 /*
00002  * All of the documentation and software included in the
00003  * Alchemy Software is copyrighted by Stanley Kok, Parag
00004  * Singla, Matthew Richardson, Pedro Domingos, Marc
00005  * Sumner and Hoifung Poon.
00006  * 
00007  * Copyright [2004-07] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00009  * Poon. All rights reserved.
00010  * 
00011  * Contact: Pedro Domingos, University of Washington
00012  * (pedrod@cs.washington.edu).
00013  * 
00014  * Redistribution and use in source and binary forms, with
00015  * or without modification, are permitted provided that
00016  * the following conditions are met:
00017  * 
00018  * 1. Redistributions of source code must retain the above
00019  * copyright notice, this list of conditions and the
00020  * following disclaimer.
00021  * 
00022  * 2. Redistributions in binary form must reproduce the
00023  * above copyright notice, this list of conditions and the
00024  * following disclaimer in the documentation and/or other
00025  * materials provided with the distribution.
00026  * 
00027  * 3. All advertising materials mentioning features or use
00028  * of this software must display the following
00029  * acknowledgment: "This product includes software
00030  * developed by Stanley Kok, Parag Singla, Matthew
00031  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00032  * Poon in the Department of Computer Science and
00033  * Engineering at the University of Washington".
00034  * 
00035  * 4. Your publications acknowledge the use or
00036  * contribution made by the Software to your research
00037  * using the following citation(s): 
00038  * Stanley Kok, Parag Singla, Matthew Richardson and
00039  * Pedro Domingos (2005). "The Alchemy System for
00040  * Statistical Relational AI", Technical Report,
00041  * Department of Computer Science and Engineering,
00042  * University of Washington, Seattle, WA.
00043  * http://www.cs.washington.edu/ai/alchemy.
00044  * 
00045  * 5. Neither the name of the University of Washington nor
00046  * the names of its contributors may be used to endorse or
00047  * promote products derived from this software without
00048  * specific prior written permission.
00049  * 
00050  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
00051  * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00052  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00053  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00054  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
00055  * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00056  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00057  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00058  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00059  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00060  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00061  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00062  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00063  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00064  * 
00065  */
00066 #ifndef POWERSET_H_SEP_6_2005
00067 #define POWERSET_H_SEP_6_2005
00068 
00069 #include "array.h"
00070 
00071   //maximum number of elements from which subsets are composed
00072 const int MAX_SIZE_TO_STORE = 10;
00073 
00074 
00075 struct PowerSetInstanceVars
00076 {
00077   int tempMaxSize;
00078   int sizeIdx;
00079   int lastNumIdx;
00080   int combIdx;  
00081   bool smallSizeFirst;
00082 };
00083 
00084 
00085 class PowerSet
00086 {
00087   //private:
00088  public:
00089   PowerSet() : setSizeArr_(new Array<Array<Array<Array<int>*>*>*>)
00090   {
00091     instanceVars_.tempMaxSize = 0;
00092     instanceVars_.sizeIdx = 1;
00093     instanceVars_.lastNumIdx = 0;
00094     instanceVars_.combIdx = 0;
00095   }
00096 
00097 
00098  public:
00099   static PowerSet* getPowerSet() 
00100   { 
00101     if (ps_ == NULL) ps_ = new PowerSet; 
00102     return ps_;
00103   }
00104 
00105   static void deletePowerSet() { if (ps_) delete ps_; }
00106 
00107 
00108   ~PowerSet()
00109   {
00110     for (int i = 0; i < setSizeArr_->size(); i++)
00111     {
00112       if ((*setSizeArr_)[i] == NULL) continue;
00113       for (int j = 0; j < (*setSizeArr_)[i]->size(); j++)
00114       {
00115         if ((*(*setSizeArr_)[i])[j] == NULL) continue;
00116         for (int k = 0; k < (*(*setSizeArr_)[i])[j]->size(); k++)
00117           delete (*(*(*setSizeArr_)[i])[j])[k];
00118         delete (*(*setSizeArr_)[i])[j];
00119       }
00120       delete (*setSizeArr_)[i];
00121     }
00122     delete setSizeArr_;
00123   }
00124 
00125 
00126   void create(const int& maxSize)
00127   {
00128     int curMaxSize = setSizeArr_->size()-1;
00129     //commented out because user can choose not to delete the power set
00130     //assert(curMaxSize <= MAX_SIZE_TO_STORE);
00131     if (maxSize <= curMaxSize) return;
00132     setSizeArr_->growToSize(maxSize+1, NULL);
00133 
00134       // if there are no combinations with only one item, then create them
00135     if (curMaxSize < 0) (*setSizeArr_)[1] = new Array<Array<Array<int>*>*>;
00136     Array<Array<Array<int>*>*>* unitCombs = (*setSizeArr_)[1];
00137     unitCombs->growToSize(maxSize,NULL);
00138     for (int i = (curMaxSize<0)?0:curMaxSize; i < maxSize; i++)
00139     {
00140       Array<Array<int>*>* unitComb = new Array<Array<int>*>;
00141       unitComb->append(new Array<int>);
00142       unitComb->lastItem()->append(i);
00143       unitComb->lastItem()->compress();
00144       unitComb->compress();
00145       (*unitCombs)[i] = unitComb;
00146     }
00147     if (curMaxSize < 0) curMaxSize = 1;
00148 
00149       // create combinations with more than one item
00150     for (int s = 2; s <= maxSize; s++)
00151     {
00152       int remainingSize = s-1;
00153       Array<Array<Array<int>*>*>* combs = (*setSizeArr_)[remainingSize];
00154 
00155         // for each index that can be appended to an existing combination
00156       for (int i = curMaxSize; i < maxSize; i++)
00157       {
00158         for (int j = 0; j < i; j++)
00159         {
00160           Array<Array<int>*>* combsEndInJ = (*combs)[j];
00161             // if there are no combinations ending in j
00162           if (combsEndInJ == NULL) continue;
00163           for (int k = 0; k < combsEndInJ->size(); k++)
00164           {
00165             Array<int>* comb = (*combsEndInJ)[k];
00166             assert (comb->lastItem() == j);
00167             assert (comb->lastItem() < i);
00168             Array<int>* newComb = new Array<int>(*comb);
00169             newComb->append(i);
00170             newComb->compress();
00171             assert(newComb->size() == s);
00172             if ((*setSizeArr_)[s] == NULL) 
00173               (*setSizeArr_)[s] = new Array<Array<Array<int>*>*>;              
00174             if ((*setSizeArr_)[s]->size() < maxSize)
00175               (*setSizeArr_)[s]->growToSize(maxSize,NULL);            
00176             if ((*(*setSizeArr_)[s])[i] == NULL)
00177               (*(*setSizeArr_)[s])[i] = new Array<Array<int>*>;
00178             (*(*setSizeArr_)[s])[i]->append(newComb);
00179           }
00180           (*(*setSizeArr_)[s])[i]->compress();
00181         }
00182       } //for each index that can be appended to an existing combination
00183     } //create combinations with more than one item
00184   }
00185 
00186 
00187   void destroy()
00188   {
00189     if (setSizeArr_->size()-1 <= MAX_SIZE_TO_STORE) return;
00190 
00191     for (int i = 0; i < setSizeArr_->size(); i++)
00192     {
00193       if ((*setSizeArr_)[i] == NULL) continue;
00194 
00195       if (i <= MAX_SIZE_TO_STORE)
00196       {
00197         for (int j = MAX_SIZE_TO_STORE; j < (*setSizeArr_)[i]->size(); j++)
00198         {
00199           if ((*(*setSizeArr_)[i])[j] == NULL) continue;
00200           for (int k = 0; k < (*(*setSizeArr_)[i])[j]->size(); k++)
00201             delete (*(*(*setSizeArr_)[i])[j])[k];
00202           delete (*(*setSizeArr_)[i])[j];
00203         }
00204         (*setSizeArr_)[i]->shrinkToSize(MAX_SIZE_TO_STORE);
00205       }
00206       else
00207       {
00208         for (int j = 0; j < (*setSizeArr_)[i]->size(); j++)
00209         {
00210           if ((*(*setSizeArr_)[i])[j] == NULL) continue;
00211           for (int k = 0; k < (*(*setSizeArr_)[i])[j]->size(); k++)
00212             delete (*(*(*setSizeArr_)[i])[j])[k];
00213           delete (*(*setSizeArr_)[i])[j];
00214         }
00215         delete (*setSizeArr_)[i];
00216       }
00217     }
00218     setSizeArr_->shrinkToSize(MAX_SIZE_TO_STORE+1);
00219   }
00220 
00221 
00222   void prepareAccess(const int& tempMaxSize, PowerSetInstanceVars& instVars,
00223                      const bool& smallSizeFirst=true)
00224   {
00225     if (tempMaxSize > setSizeArr_->size()-1)
00226       create(tempMaxSize);
00227 
00228     instVars.tempMaxSize = tempMaxSize;
00229     instVars.sizeIdx = (smallSizeFirst) ? 1 : tempMaxSize;
00230     instVars.lastNumIdx = instVars.sizeIdx - 1;
00231     instVars.combIdx = -1;
00232     instVars.smallSizeFirst = smallSizeFirst;
00233   }
00234 
00235 
00236   void prepareAccess(const int& tempMaxSize, const bool& smallSizeFirst=true)
00237   { prepareAccess(tempMaxSize, instanceVars_, smallSizeFirst); }
00238 
00239 
00240   bool getNextSet(const Array<int>*& set, PowerSetInstanceVars& instVars)
00241   {
00242     int& tempMaxSize = instVars.tempMaxSize;
00243     int& sizeIdx = instVars.sizeIdx;
00244     int& lastNumIdx = instVars.lastNumIdx;
00245     int& combIdx = instVars.combIdx;
00246     bool& smallSizeFirst = instVars.smallSizeFirst;
00247 
00248     if (++combIdx >= (*(*setSizeArr_)[sizeIdx])[lastNumIdx]->size())
00249     {
00250       combIdx = 0;
00251       ++lastNumIdx;
00252       while (lastNumIdx == tempMaxSize || 
00253              (lastNumIdx < tempMaxSize && 
00254               (*(*setSizeArr_)[sizeIdx])[lastNumIdx] == NULL ))
00255       {
00256         ++lastNumIdx;
00257         if (lastNumIdx >= tempMaxSize)
00258         {
00259           if (smallSizeFirst)
00260           {
00261             lastNumIdx = sizeIdx - 1;
00262             while (++sizeIdx <= tempMaxSize && (*setSizeArr_)[sizeIdx]==NULL);
00263             if (sizeIdx > tempMaxSize) return false;
00264           }
00265           else
00266           {
00267             lastNumIdx = sizeIdx - 2;
00268             while (--sizeIdx >= 1 && (*setSizeArr_)[sizeIdx]==NULL);
00269             if (sizeIdx < 1) return false;
00270           }
00271         }
00272         if ((*(*setSizeArr_)[sizeIdx])[lastNumIdx] != NULL) break;
00273       }
00274     }
00275     set = (*(*(*setSizeArr_)[sizeIdx])[lastNumIdx])[combIdx];
00276     return true;
00277   }
00278 
00279 
00280   bool getNextSet(const Array<int>*& set) 
00281   { return getNextSet(set, instanceVars_); }
00282 
00283 
00284   Array<Array<Array<Array<int>*>*>*>* getSetSizeArr() const  
00285   { return setSizeArr_; }
00286 
00287 
00288   ostream& print(ostream& out) const
00289   {
00290     int n = 0;
00291     for (int i = 0; i < setSizeArr_->size(); i++)
00292     {
00293       if ((*setSizeArr_)[i] == NULL) continue;
00294       for (int j = 0; j < (*setSizeArr_)[i]->size(); j++)
00295       {
00296         if ((*(*setSizeArr_)[i])[j] != NULL) 
00297         {
00298           for (int k = 0; k < (*(*setSizeArr_)[i])[j]->size(); k++)
00299           {
00300             cout << n++ << ": ";
00301             for (int l = 0; l < (*(*(*setSizeArr_)[i])[j])[k]->size(); l++)
00302               cout << (*(*(*(*setSizeArr_)[i])[j])[k])[l] << " ";
00303             cout << endl;
00304           }
00305         }
00306       }
00307     }
00308     return out;
00309   }
00310 
00311 
00312  private:
00313   static PowerSet* ps_; //singleton
00314 
00315     //setSizeArr_[i][j] are the subsets of size i that ends with index j
00316   Array<Array<Array<Array<int>*>*>*>* setSizeArr_;
00317   
00318   PowerSetInstanceVars instanceVars_;
00319 };
00320 
00321 
00322 inline
00323 ostream& operator<<(ostream& out, const PowerSet& p) { return p.print(out); }
00324 
00325 
00326 #endif

Generated on Tue Jan 16 05:30:05 2007 for Alchemy by  doxygen 1.5.1