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 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