parentiter.h

00001 #ifndef PARENTITER_H
00002 #define PARENTITER_H
00003 
00004 #include "array.h"
00005 #include "permutation.h"
00006 #include "arraysaccessor.h"
00007 
00008 class ParentIter
00009 {
00010 public:
00011     ParentIter()
00012     {
00013         /* NOP */
00014     }
00015 
00016     ~ParentIter()
00017     {
00018         // Default destructor should work...
00019     }
00020 
00021     ParentIter(const ParentIter& other)
00022         : size_(other.size_), fillerValues_(other.fillerValues_),
00023           reqValues_(other.reqValues_), reqGround_(other.reqGround_),
00024           fillerGround_(), firstTime_(other.firstTime_)
00025     {
00026         setupFillerIter();
00027         while (fillerGround_.getCombinationIndex() <
00028                 other.fillerGround_.getCombinationIndex()) {
00029             fillerGround_.next();
00030         }
00031     }
00032 
00033     // TODO: expand this to allow for objects of different types
00034     ParentIter(const Array<int>& required, const Array<int>* filler, int size)
00035         : size_(size), fillerValues_(*filler), reqValues_(required),
00036           reqGround_(), firstTime_(true)
00037     {
00038         Array<int> requiredWithSpaces(required);
00039         for (int i = required.size(); i < size; i++) {
00040             requiredWithSpaces.append(-2);
00041         }
00042         reqGround_.setValues(requiredWithSpaces);
00043         setupFillerIter();
00044     }
00045 
00046     void reset()
00047     {
00048         reqGround_.reset();
00049         setupFillerIter();
00050         firstTime_ = true;
00051     }
00052 
00053     bool hasNextGrounding() {
00054         return fillerGround_.hasNextCombination() || reqGround_.hasNext();
00055     }
00056 
00057 
00058     bool getNextGrounding(Array<int>& grounding)
00059     {
00060         grounding.clear();
00061         grounding.growToSize(size_);
00062 
00063         if (firstTime_ || !fillerGround_.hasNextCombination()) {
00064             reqGround_.next();
00065             setupFillerIter();
00066         }
00067         firstTime_ = false;
00068 
00069         // Advance to next grounding
00070         Array<int> fillerGrounding;
00071         fillerGround_.getNextCombination(fillerGrounding);
00072 
00073         // Copy to the passed-in array
00074         int fillerIndex = 0;
00075         for (int i = 0; i < size_; i++) {
00076             if (reqGround_[i] < 0) {
00077                 grounding[i] = fillerGrounding[fillerIndex++];
00078             } else {
00079                 grounding[i] = reqGround_[i];
00080             }
00081         }
00082 
00083         return hasNextGrounding();
00084     }
00085 
00086 
00087 protected:
00088     void setupFillerIter()
00089     {
00090         // There's some trickiness in here to avoid duplicate groundings.
00091         // Consider a parent grounding that must have variable A,
00092         // but also has one free variable that can be anaything.  If we
00093         // considerthe permutations (A,?) and (?,A), we must be careful
00094         // not to double-count (A,A) when iterating through all values of
00095         // the wildcard, '?'.  Therefore, this code ensures that all
00096         // wildcards that take on a specific value must *precede* all
00097         // non-wildcards of that value.  This makes groundings unique.
00098         Array<int> seenSoFar;
00099         fillerGround_.deleteArraysAndClear();
00100         for (int i = 0; i < size_; i++) {
00101             if (reqGround_[i] >= 0) {
00102                 seenSoFar.append(reqGround_[i]);
00103             } else {
00104                 Array<int>* valList = new Array<int>;
00105                 for (int fi = 0; fi < fillerValues_.size(); fi++) {
00106                     bool seen = false;
00107                     for (int si = 0; si < seenSoFar.size(); si++) {
00108                         if (seenSoFar[si] == fillerValues_[fi]) {
00109                             seen = true;
00110                             break;
00111                         }
00112                     }
00113                     if (!seen) {
00114                         valList->append(fillerValues_[fi]);
00115                     }
00116                 }
00117 
00118                 fillerGround_.appendArray(valList);
00119             }
00120         }
00121     }
00122 
00123 
00124 private:
00125     int size_;
00126     Array<int> fillerValues_;
00127     Array<int> reqValues_;
00128     Permutation<int> reqGround_;
00129     ArraysAccessor<int> fillerGround_;
00130     bool firstTime_;
00131 };
00132 
00133 #endif // ndef PARENTITER_H

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