permutation.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 PERMUTATION_H
00067 #define PERMUTATION_H
00068 #include "array.h"
00069 #include "arraysaccessor.h"
00070 
00071 /* The Permutation class iterates through all permutations of a set of
00072  * objects.  In order to avoid equivalent permutations, equality must be
00073  * defined among the objects.
00074  */
00075 template<typename Type>
00076 class Permutation
00077 {
00078 public:
00079     Permutation()
00080         : hasNext_(false)
00081     { /* NOP */ }
00082 
00083     Permutation(const Array<Type>& vals) 
00084     { setValues(vals); }
00085 
00086 
00087     void setValues(const Array<Type>& vals) 
00088     {
00089         values_ = vals;
00090 
00091         perm_.clear();
00092         perm_.growToSize(values_.size());
00093         filled_.clear();
00094         filled_.growToSize(values_.size());
00095 
00096         // Keep track of duplicates.  We don't want to double-count
00097         // equivalent permutations.
00098         prevDuplicate_.clear();
00099         numLaterDuplicates_.clear();
00100         for (int i = 0; i < values_.size(); i++) {
00101             int prevDuplicate = -1;
00102             for (int j = 0; j < i; j++) {
00103                 if (values_[j] == values_[i]) {
00104                     prevDuplicate = j;
00105                     numLaterDuplicates_[j]++;
00106                 }
00107             }
00108             prevDuplicate_.append(prevDuplicate);
00109             numLaterDuplicates_.append(0);
00110         }
00111 
00112         reset();
00113     }
00114 
00115     void reset()
00116     {
00117         skips_.clear();
00118         skips_.growToSize(values_.size());
00119 
00120         // Return to first permutation
00121         for (int i = 0; i < skips_.size(); i++) { 
00122             skips_[i] = 0;
00123         }
00124 
00125         for (int i = 0; i < values_.size(); i++) {
00126             perm_[i] = values_[i];
00127         }
00128 
00129         // NOTE: this could be wrong if we have 0 values.  Boundary case.
00130         hasNext_ = true;
00131     }
00132 
00133     ~Permutation() { /* NOP */ }
00134 
00135     int size() {
00136         return values_.size();
00137     }
00138 
00139     bool hasNext() {
00140         return hasNext_;
00141     }
00142 
00143     // Advance to the next permutation.
00144     void next() {
00145 
00146         // Advance to next permutation
00147         hasNext_ = false;
00148         for (int i = size() - 2; i >= 0; i--) {
00149             skips_[i]++;
00150             int numSkips = skips_[i];
00151             // Add up all previous skips
00152             int prevIndex = i;
00153             while (prevDuplicate_[prevIndex] >= 0) {
00154                 numSkips += skips_[prevDuplicate_[prevIndex]];
00155                 prevIndex = prevDuplicate_[prevIndex];
00156             }
00157             if (numSkips < size() - i - numLaterDuplicates_[i]) {
00158                 hasNext_ = true;
00159                 break;
00160             } else {
00161                 skips_[i] = 0;
00162             }
00163         }
00164 
00165         // Mark all slots as empty
00166         for (int i = 0; i < size(); i++) {
00167             filled_[i] = false;
00168         }
00169 
00170         for (int i = 0; i < size(); i++) {
00171             int numSkips = skips_[i];
00172             if (prevDuplicate_[i] >= 0) {
00173                 numSkips += skips_[prevDuplicate_[i]];
00174             }
00175             int currIndex = 0;
00176             while (numSkips > 0 || filled_[currIndex]) {
00177                 if (!filled_[currIndex]) {
00178                     numSkips--;
00179                 }
00180                 currIndex++;
00181                 assert (currIndex < size()); 
00182             }
00183             perm_[currIndex] = values_[i];
00184             filled_[currIndex] = true;
00185         }
00186     }
00187 
00188     Type operator[](int idx) {
00189         return perm_[idx];
00190     }
00191 
00192 
00193 private:
00194     bool hasNext_;
00195     Array<int> skips_;
00196     Array<Type> values_;
00197     Array<bool> filled_;
00198     Array<Type> perm_;
00199     Array<int> prevDuplicate_;
00200     Array<int> numLaterDuplicates_;
00201 };
00202 #endif // ndef PERMUTATION_H

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