array.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, Hoifung Poon, and Daniel Lowd.
00006  * 
00007  * Copyright [2004-07] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner, Hoifung
00009  * Poon, and Daniel Lowd. 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, Hoifung
00032  * Poon, and Daniel Lowd 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 ARRAY_H_JUN_21_2005
00067 #define ARRAY_H_JUN_21_2005
00068 
00069 #include <stdlib.h>
00070 #include <assert.h>
00071 #include <iostream>
00072 #include "random.h"
00073 using namespace std;
00074 
00075 
00076 template <typename Type> 
00077 class Array
00078 {
00079  public:
00080   Array(const int& initSize=0)
00081   {
00082     items_    = NULL;
00083     maxItems_ = 0;
00084     numItems_ = 0;
00085     if (initSize > 0) allocateMemory(initSize);
00086   }
00087 
00088   Array(const int& initSize, const Type& fill)
00089   {
00090     items_    = NULL;
00091     maxItems_ = 0;
00092     numItems_ = 0;
00093     growToSize(initSize, fill);
00094   }
00095   
00096   
00097     // creates an array which points to this data
00098     // Array owns the data
00099   Array(Type* data, int numdata) 
00100   {
00101     items_    = data;
00102     maxItems_ = numdata;
00103     numItems_ = numdata;
00104   }
00105 
00106   
00107   Array(const Array<Type>& x)
00108   { 
00109     if (x.numItems_ == 0) 
00110     {
00111       items_    = NULL;
00112       maxItems_ = 0;
00113       numItems_ = 0;
00114       allocateMemory(0);
00115       return;
00116     }
00117     items_ = new Type[x.numItems_];
00118     //commented out: Type may not be a basic type and thus need deep copying
00119     //memcpy(items_, x.items_, x.numItems_*sizeof(Type));
00120     for (int i = 0; i < x.numItems_; i++) items_[i] = x.items_[i];
00121     numItems_ = x.numItems_;
00122     maxItems_ = numItems_;
00123   }
00124 
00125 
00126   Array<Type>& operator=(const Array<Type>& x)
00127   { 
00128     if (items_ == x.items_) {
00129       return *this;
00130     }
00131 
00132     if (items_) {
00133       delete [] items_;
00134     }
00135 
00136     // The below code is mostly copied from the copy constructor.
00137     if (x.numItems_ == 0) 
00138     {
00139       items_    = NULL;
00140       maxItems_ = 0;
00141       numItems_ = 0;
00142       allocateMemory(0);
00143       return *this;
00144     }
00145     items_ = new Type[x.numItems_];
00146     //commented out: Type may not be a basic type and thus need deep copying
00147     //memcpy(items_, x.items_, x.numItems_*sizeof(Type));
00148     for (int i = 0; i < x.numItems_; i++) items_[i] = x.items_[i];
00149     numItems_ = x.numItems_;
00150     maxItems_ = numItems_;
00151 
00152     return *this;
00153   }
00154 
00155 
00156     // does not delete each individual item
00157   ~Array() { if (items_) delete [] items_; }
00158 
00159 
00160     // returns index of appended item
00161   int append(Type item)
00162   {
00163     if (numItems_ == maxItems_)
00164       allocateMemory(maxItems_*2+1);
00165     items_[numItems_++] = item;
00166     return numItems_-1;
00167   }
00168 
00169 
00170   void append(const Array<Type>& newItems)
00171   {
00172     int origSize = numItems_;
00173     int newItemsSize = newItems.numItems_;
00174     growToSize(origSize+newItemsSize);
00175     //commented out: Type may not be a basic type and thus need deep copying
00176     //memcpy(items_+origSize, newItems.items_, newItemsSize*sizeof(Type));
00177     for (int i = 0; i<newItemsSize;i++) items_[origSize+i] = newItems.items_[i];
00178 
00179   }
00180 
00181 
00182   void append(const Array<Type>* const & items)  { append(*items); }
00183 
00184  
00185   void copyFrom(const Array<Type>& items) { clear(); append(items); }
00186 
00187 
00188   bool growToSize(const int& newSize)
00189   {
00190     if (newSize <= numItems_) return false;
00191     
00192     if (newSize <= maxItems_)
00193       numItems_ = newSize;
00194     else
00195     {
00196       allocateMemory(newSize);
00197       numItems_ = newSize;
00198     }
00199     return true;
00200   }
00201 
00202 
00203   bool growToSize(const int& newSize, Type fill)
00204   {
00205     if (newSize <= numItems_) return false;
00206     int origNumItems = numItems_;
00207     growToSize(newSize);
00208     for (int i = origNumItems; i < numItems_; i++)
00209       items_[i] = fill;
00210     return true;
00211   }
00212 
00213   
00214   bool shrinkToSize(const int& newSize)
00215   {
00216     if (newSize >= numItems_) return false;
00217     allocateMemory(newSize);
00218     numItems_ = newSize;
00219     return true;
00220   }
00221   
00222 
00223   void clear()  { numItems_ = 0; }
00224   void clearAndCompress()  { numItems_ = 0; compress(); }
00225 
00226 
00227     // delete the contents of items_ array and set numItems = 0;
00228     // items_ is not deleted,and maxItems_ stay the same
00229   void deleteItemsAndClear()
00230   {
00231     for (int i = 0; i < numItems_; i++)
00232       if (items_[i]) delete items_[i];
00233     clear();
00234   }
00235 
00236 
00237     // delete the contents of items_ array and set numItems = 0;
00238     // items_ is not deleted,and maxItems_ stay the same
00239   void deleteItemsAndClearCompress() 
00240   { 
00241     for (int i = 0; i < numItems_; i++)
00242       if (items_[i]) delete items_[i];
00243     clear();
00244     compress();
00245   }
00246 
00247 
00248   int size() const { return numItems_; }
00249 
00250   int maxItems() const { return maxItems_; }
00251 
00252   bool empty() const { return size()==0; } 
00253 
00254 
00255   Type& item(const int& index) const 
00256   {
00257     assert(index < numItems_);
00258     return items_[index];
00259   }
00260 
00261 
00262   Type& operator[](const int& index) const { return item(index); } 
00263 
00264 
00265   Type& lastItem() const { return items_[numItems_-1]; }
00266 
00267 
00268     // caller should not delete the returned pointer nor modify the object
00269   const Type* getItems() const { return items_; }
00270 
00271   
00272   //comment out: randomOneOf no longer a static function
00273   //Type& randomItem() const 
00274   //{
00275   //  assert(numItems_>0); 
00276   //  return items_[Random::randomOneOf(numItems_)];
00277   //}
00278 
00279 
00280     // linear search
00281   int find(Type const & item) const
00282   {
00283     for (int i = 0; i < numItems_; i++)
00284       if (items_[i] == item) return i;
00285     return -1;
00286   }
00287   
00288 
00289     // linear search
00290   bool contains(Type const & item) const { return find(item) >= 0;}
00291 
00292 
00293     // Appends item only if it is not already in the array 
00294     // (by checking item1 == item2). Involves slow linear search.
00295     // Returns true of items is unique and inserted.
00296   bool appendUnique(Type item)
00297   {
00298     if (!contains(item))
00299     {
00300       append(item);
00301       return true;
00302     }
00303     return false;
00304   }
00305 
00306 
00307   void appendUnique(Array<Type>& items)
00308   {
00309     for (int i = 0; i < items.size(); i++)
00310       appendUnique(items.item(i));
00311   }
00312 
00313 
00314   void appendUnique(Array<Type>* items) { appendUnique(*items); }
00315 
00316 
00317   void removeAllNull()
00318   {
00319       // remove all entries with value NULL, and reindex so they're contiguous  
00320       // (e.g. [3 4 7 NULL 3 6 NULL] becomes [3 4 7 3 6]
00321     int currentIndex = 0;
00322     for (int i = 0; i < numItems_; i++)
00323     {
00324       if (item(i) != NULL)
00325         item(currentIndex++) = item(i);
00326     }
00327     numItems_ = currentIndex;
00328   }
00329   
00330 
00331   Type removeItem(const int& index)
00332   {
00333     Type removedItem = item(index);
00334     for (int i = index+1; i < numItems_; i++) items_[i-1] = items_[i];
00335     numItems_--;
00336     return removedItem;
00337 
00338     //commented out: Type may not be a basic type and thus need deep copying
00339       // move everything past the item back
00340     //int numItemsToMove = numItems_ - index - 1;
00341     //if (numItemsToMove > 0)
00342     //  memmove(&items_[index], &items_[index+1], numItemsToMove*sizeof(Type));
00343     //numItems_--;
00344   }
00345 
00346 
00347   Type removeLastItem() { return removeItem(numItems_-1); }
00348 
00349 
00350     // removes the item, but does not leave the array in the same order as 
00351     // before
00352   Type removeItemFastDisorder(const int& index) 
00353   {
00354     Type removedItem = item(index);
00355     item(index) = item(numItems_-1);
00356     numItems_--;
00357     return removedItem;
00358   }
00359 
00360 
00361     // resizes the array to be exactly the number of elements in it
00362   void compress()  { if (maxItems_ > numItems_)  allocateMemory(numItems_); }
00363 
00364 
00365     // reorder randomly
00366   void shuffle() 
00367   {
00368     for (int i = 0; i < numItems_; i++) 
00369     {
00370         // swap item i with a random item
00371       int swapwith = Random::randomOneOf(numItems_);
00372       Type tmp;
00373       tmp = items_[i];
00374       items_[i] = items_[swapwith];
00375       items_[swapwith] = tmp;
00376     }
00377   }
00378 
00379 
00380     // returns the index of largest item
00381   int getMaxIndex() 
00382   {
00383     assert(numItems_ > 0);
00384     int max = 0;
00385     for (int i = 1; i < numItems_; i++) 
00386     {
00387       if (items_[i] > items_[max])
00388         max = i;
00389     }
00390     return max;
00391   }
00392 
00393 
00394     // returns the value of largest item
00395   Type getMaxValue() 
00396   {
00397     assert(numItems_ > 0);
00398     Type max = items_[0];
00399     for (int i = 1; i < numItems_; i++) 
00400     {
00401       if (items_[i] > max)
00402         max = items_[i];
00403     }
00404     return max;
00405   }    
00406 
00407 
00408     // sort in increasing order
00409   void quicksort()  { quicksort(0,numItems_-1); }
00410 
00411     // sort in decreasing order
00412   void rquicksort() { rquicksort(0,numItems_-1); }
00413   
00414     // sort in increasing order
00415   void bubbleSort()
00416   {
00417     Type tempItem;
00418     for (int i = 0; i < numItems_; i++)
00419       for (int j = i+1; j < numItems_; j++)
00420         if (items_[i] > items_[j])
00421         {
00422           tempItem = items_[i];
00423           items_[i] = items_[j];
00424           items_[j] = tempItem;
00425         }
00426   }
00427 
00428 
00429     // sort in increasing order
00430   void rbubbleSort()
00431   {
00432     Type tempItem;
00433     for (int i = 0; i < numItems_; i++)
00434       for (int j = i+1; j < numItems_; j++)
00435         if (items_[i] < items_[j])
00436         {
00437           tempItem = items_[i];
00438           items_[i] = items_[j];
00439           items_[j] = tempItem;
00440         }
00441   }
00442 
00443 
00444 
00445  private:
00446   void truncate(const int& newNumItems) 
00447   {
00448     assert(newNumItems <= numItems_);
00449     numItems_ = newNumItems;
00450   }
00451 
00452 
00453     // if newSize < numItems, numItems will be shrunk to newSize
00454   void allocateMemory(const int& newSize)
00455   {
00456     if (newSize > 0)
00457     {
00458       if (newSize >= numItems_)
00459       {
00460         Type* tempItems = new Type[newSize];
00461         if (numItems_ > 0) 
00462         {
00463           //commented out: Type may not be a basic type & thus need deep copying
00464           //memcpy(tempItems, items_, numItems_*sizeof(Type));
00465           for (int i = 0; i < numItems_; i++) tempItems[i] = items_[i];
00466         }
00467         if (items_) delete [] items_;
00468         items_ = tempItems;
00469         maxItems_ = newSize;
00470       }
00471       else  // newSize < numItems_
00472       {
00473         Type* tempItems = new Type[newSize];
00474         if (numItems_ > 0) 
00475         {
00476           //commented out: Type may not be a basic type & thus need deep copying
00477           //memcpy(tempItems, items_, newSize*sizeof(Type));
00478           for (int i = 0; i < newSize; i++) tempItems[i] = items_[i];
00479         }
00480         if (items_) delete [] items_;
00481         items_ = tempItems;
00482         maxItems_ = newSize;
00483         numItems_ = newSize;
00484       }
00485     }
00486     else // newSize==0
00487     {
00488       if (items_) delete [] items_;
00489       items_ = NULL;
00490       maxItems_ = 0;
00491       numItems_ = 0;
00492     }
00493   }
00494 
00495 
00496   void quicksort(const int& l, const int& r)
00497   {
00498     if (l >= r) return;
00499     Type tmp = items_[l];
00500     items_[l] = items_[(l+r)/2];
00501     items_[(l+r)/2] = tmp;
00502 
00503     int last = l;
00504     for (int i = l+1; i <= r; i++)
00505       if (items_[i] < items_[l])
00506       {
00507         ++last;
00508         tmp = items_[last];
00509         items_[last] = items_[i];
00510         items_[i] = tmp;
00511       }
00512     
00513     tmp = items_[l];
00514     items_[l] = items_[last];
00515     items_[last] = tmp;
00516     quicksort(l, last-1);
00517     quicksort(last+1, r);  
00518   }
00519 
00520 
00521   void rquicksort(const int& l, const int& r)
00522   {
00523     if (l >= r) return;
00524     Type tmp = items_[l];
00525     items_[l] = items_[(l+r)/2];
00526     items_[(l+r)/2] = tmp;
00527 
00528     int last = l;
00529     for (int i = l+1; i <= r; i++)
00530       if (items_[i] > items_[l])
00531       {
00532         ++last;
00533         Type tmp = items_[last];
00534         items_[last] = items_[i];
00535         items_[i] = tmp;
00536       }
00537     
00538     tmp = items_[l];
00539     items_[l] = items_[last];
00540     items_[last] = tmp;
00541     rquicksort(l, last-1);
00542     rquicksort(last+1, r);  
00543   }
00544 
00545      
00546  private:
00547   Type* items_;
00548   int maxItems_;
00549   int numItems_;
00550 };
00551 
00552 
00553 // Useful functions
00554 
00555   // between is the filler string to be used between items
00556 template<typename T> 
00557 void writeArray(const Array<T*>& array, ostream& out, char* between, 
00558                 const char& delimiter)
00559 {
00560   out << array.size() << delimiter;
00561   for (int i = 0; i < array.size(); i++)
00562   {
00563     array.item(i)->save(out);
00564     if (between) out << between;
00565   }
00566 }
00567 
00568 
00569 template<typename T> 
00570 void writeArray(const Array<T*>& array, ostream& out, char* between=NULL)
00571 { writeArray(array, out, between, '\n'); }
00572 
00573 
00574 template<typename T> 
00575 void readArray(Array<T*>& array, istream& in)
00576 {
00577   int numItems;
00578   in >> numItems;
00579   for (int i = 0; i < numItems && in.good(); i++)
00580   {
00581     T* x = new T;
00582     x->load(in);
00583     array.append(x);
00584   }
00585 }
00586 
00587 
00588 template<typename T> 
00589 void writeArray(const Array<T>& array, ostream& out, char* between, 
00590                 const char& delimiter)
00591 {
00592   out << array.Size() << delimiter;
00593   for (int i = 0; i < array.Size(); i++)  
00594   {
00595     array.item(i).save(out);
00596     if (between) out << between;
00597   }  
00598 }
00599 
00600 
00601 template<typename T> 
00602 void writeArray(const Array<T>& array, ostream& out, char* between=NULL)
00603 { writeArray(array, out, between, '\n'); }
00604 
00605 
00606 template<typename T> 
00607 void readArray(Array<T>& array, istream& in) 
00608 {
00609   int numItems;
00610   in >> numItems;
00611   for (int i = 0; i < numItems && in.good(); i++) 
00612   {
00613     T x;
00614     x.load(in);
00615     array.append(x);
00616   }
00617 }
00618 
00619 
00620 template<typename T> 
00621 void writeBasicArray(const Array<T>& array, ostream& out, char* between,
00622                      const char& delimiter)
00623 {
00624   out << array.Size() << delimiter;
00625   for (int i = 0; i < array.Size(); i++)
00626   {
00627     out << array.item(i) << " ";
00628     if (between) out << between;
00629   }
00630 }
00631 
00632 
00633 template<typename T> 
00634 void writeBasicArray(const Array<T>& array, ostream& out, char* between=NULL)
00635 { writeBasicArray(array, out, between, '\n'); }
00636 
00637 
00638 template<typename T> 
00639 void readBasicArray(Array<T>& array, istream& in)
00640 {
00641   int numItems=0;
00642   in >> numItems;
00643   for (int i = 0; i < numItems && in.good(); i++)
00644   {
00645     T x;
00646     in >> x;
00647     array.append(x);
00648   }
00649   if (!in.good())
00650     cout << "ERROR: readBasicArray(). Input not good." << endl;
00651 }
00652 
00653   //Print the array
00654 template <typename type>
00655 ostream& printArray(const Array<type>& array, ostream& out)
00656 {
00657   return printArray(array, 0, out);
00658 }
00659 
00660   //Print the array
00661 template <typename type>
00662 ostream& printArray(const Array<type>& array, int beginIndex, ostream& out)
00663 {
00664   char delimiter = ' ';
00665   for (int i = beginIndex; i < array.size(); i++)
00666   {
00667     out << array[i] << delimiter;
00668   }
00669   return out;
00670 }
00671 
00672   //get the total number of elements in the array of arrays
00673 template <typename type> 
00674 int getNumArrayArrayElements(const Array<Array<type>*> & elementsArr)
00675 {
00676   int numElements = 0;
00677   for (int i = 0; i < elementsArr.size(); i++)
00678   {
00679     numElements += elementsArr[i]->size();
00680   }
00681   return numElements;
00682 }
00683 
00684 
00685 #endif

Generated on Sun Jun 7 11:55:21 2009 for Alchemy by  doxygen 1.5.1