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

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