00001 //---------------------------------------------------------------------------- 00002 /** @file VCList.hpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef VCLIST_HPP 00007 #define VCLIST_HPP 00008 00009 #include "ChangeLog.hpp" 00010 #include "VC.hpp" 00011 00012 _BEGIN_BENZENE_NAMESPACE_ 00013 00014 //---------------------------------------------------------------------- 00015 00016 /** Sorted list of VCs. 00017 00018 The list is sorted by VC carrier size. When VCs are added, only 00019 VCs that are not duplicates or supersets of existing VCs in the 00020 list are considered; any elements currently in the list that are 00021 supersets of the new vc are removed. This means an add operation 00022 will run in linear time. 00023 00024 The soft limit is the number of vcs used in vc calculations. VCs 00025 that appear after the soft limit are not considered in vc 00026 calculations, but may be later on if some vcs are removed. The 00027 idea is to keep around extra vcs that may be important later, but 00028 not at the expense of slower vc calculations now. 00029 */ 00030 class VCList 00031 { 00032 public: 00033 00034 /** Creates a list with given limits. */ 00035 VCList(HexPoint x, HexPoint y, unsigned int soft); 00036 00037 HexPoint getX() const; 00038 00039 HexPoint getY() const; 00040 00041 /** Returns the soft limit. */ 00042 int softlimit() const; 00043 00044 /** See softlimit() */ 00045 void setSoftLimit(int limit); 00046 00047 /** Empties the list and the changelog. */ 00048 void clear(); 00049 00050 /** Returns the number of VCs in this list. */ 00051 std::size_t size() const; 00052 00053 /** Returns true if the list is empty. */ 00054 bool empty() const; 00055 00056 /** Dumps the contents of this list to a string. */ 00057 std::string dump() const; 00058 00059 //---------------------------------------------------------------------- 00060 00061 /** Returns true if bs is superset of connection in list. */ 00062 bool isSupersetOfAny(const bitset_t& vc) const; 00063 00064 /** Returns true if vc is subset of connection in list. */ 00065 bool isSubsetOfAny(const bitset_t& vc) const; 00066 00067 /** Removes any connection whose carrier is a superset of the 00068 given VC's carrier. Returns number of connections 00069 removed. Does not dirty intersections if flag is set to false; 00070 only use this if you are for sure only removing supersets of a 00071 member of this list! 00072 */ 00073 int removeSuperSetsOf(const bitset_t& vc, ChangeLog<VC>* log, 00074 bool dirty_intersections = true); 00075 00076 //---------------------------------------------------------------------- 00077 00078 /** @name Adding connections */ 00079 // @{ 00080 00081 /** Return type for add() methods. */ 00082 typedef enum 00083 { 00084 /** Add did not succeed, list is unchanged. */ 00085 ADD_FAILED = 0, 00086 00087 /** Added connection within the soft limit. */ 00088 ADDED_INSIDE_SOFT_LIMIT = 1, 00089 00090 /** Add connection within the hard limit. */ 00091 ADDED_INSIDE_HARD_LIMIT = 2 00092 00093 } AddResult; 00094 00095 /** Adds vc to the list. 00096 00097 Requires a single pass over the entire list. The add will fail 00098 if vc is a superset of some vc already in the list. Supersets 00099 of this vc that are already in the list are removed. 00100 00101 Operations will be recorded in the log if log is not 0. 00102 00103 @return true if the VC was added, false otherwise. 00104 */ 00105 AddResult add(const VC& vc, ChangeLog<VC>* log); 00106 00107 00108 /** Adds the elements of other to list. Returns number of vcs 00109 added. Vcs are added as unprocessed. 00110 Operations will be recorded in the log if log is not 0. */ 00111 int add(const VCList& other, ChangeLog<VC>* log); 00112 00113 /** 00114 * Force the addition of this vc. Used by VCSet::revert(): 00115 * 00116 * 1) add(vc) can cause a superset to vc to be removed. 00117 * 2) this superset is then added to the log 00118 * 3) when reverting the log, we try to add the superset, 00119 * but the add fails because vc is still in it. 00120 * 4) Ooops! 00121 * 00122 * This method does NO checks. It simply adds vc into the 00123 * proper position according to the ordering on the vcs. 00124 */ 00125 void simple_add(const VC& vc); 00126 00127 // @} 00128 00129 //---------------------------------------------------------------------- 00130 00131 /** @name Iterators */ 00132 // @{ 00133 00134 typedef std::list<VC>::iterator iterator; 00135 00136 typedef std::list<VC>::const_iterator const_iterator; 00137 00138 /** Returns an iterator to the given VC, or end() if vc is not in 00139 the list. Note that these methods are not constant, but as 00140 long as VCs are immutable (except for their processed flags) 00141 then the list cannot be altered by these methods. */ 00142 iterator find(const VC& vc); 00143 iterator find(const VC& vc, const iterator& b, const iterator& e); 00144 00145 /** Returns a constant iterator to the given VC, or end() if vc is 00146 not in the list. */ 00147 const_iterator find(const VC& vc) const; 00148 const_iterator find(const VC& vc, 00149 const const_iterator& b, 00150 const const_iterator& e) const; 00151 00152 00153 /** Removes the element pointed to by i from the list. 00154 @return the next element. */ 00155 iterator remove(iterator i, ChangeLog<VC>* log); 00156 00157 /** Removes the given vc from the list. Does nothing if vc is not 00158 actually in the list. Takes O(n) time. Returns true if vc 00159 was actually removed, false otherwise. */ 00160 bool remove(const VC& vc, ChangeLog<VC>* log); 00161 00162 /** Returns an iterator to the start of the list. */ 00163 iterator begin(); 00164 00165 /** Returns an iterator just past the end of the list. */ 00166 iterator end(); 00167 00168 /** Returns a constant iterator to the start of the list. */ 00169 const_iterator begin() const; 00170 00171 /** Returns a constant iterator just past the end of the list. */ 00172 const_iterator end() const; 00173 00174 // @} 00175 00176 //---------------------------------------------------------------------- 00177 00178 /** Returns the union of all carriers in the list. */ 00179 bitset_t getUnion() const; 00180 00181 /** Returns the union of all carriers in the list. 00182 00183 Only includes carriers of VCs in the union if they shrink the 00184 intersection at each step (considered in the sorted order). 00185 00186 @note Doing this may result in different sets of connections 00187 depending upon the relative order of the vcs in the list. So, 00188 on an empty board, BLACK can have a slightly different 00189 connection set that WHITE. Can also result in different vc 00190 connections between non-rotated and rotated versions of the 00191 board. 00192 */ 00193 bitset_t getGreedyUnion() const; 00194 00195 /** Returns soft-limit intersection. If list is empty, the bitset 00196 will have all of its bits set. */ 00197 bitset_t softIntersection() const; 00198 00199 /** Returns hard-limit intersection. If list is empty, the bitset 00200 will have all of its bits set. */ 00201 bitset_t hardIntersection() const; 00202 00203 //---------------------------------------------------------------------- 00204 00205 /** Removes all VCs that intersect with b. Removed VCs are 00206 appended to out if out---note that the order of the vcs in out 00207 is the same as it was in the original list! Returns number of 00208 vcs removed. */ 00209 int removeAllContaining(HexPoint cell, std::list<VC>& out, 00210 ChangeLog<VC>* log); 00211 00212 int removeAllContaining(const bitset_t& b, std::list<VC>& out, 00213 ChangeLog<VC>* log); 00214 00215 int removeAllContaining(const bitset_t& b, ChangeLog<VC>* log); 00216 00217 /** Performs list equality. */ 00218 bool operator==(const VCList& other) const; 00219 00220 /** Performs list inequality. */ 00221 bool operator!=(const VCList& other) const; 00222 00223 protected: 00224 00225 /** Invalidates the precomputed list unions. */ 00226 void dirty_list_unions(); 00227 00228 /** Invalidates the list intersection. */ 00229 void dirty_list_intersections(); 00230 00231 /** Computes list unions in one pass: normal and greedy. */ 00232 void computeUnions() const; 00233 00234 /** Computes list intersections in one pass: soft and hard. */ 00235 void computeIntersections() const; 00236 00237 HexPoint m_x, m_y; 00238 00239 /** See softlimit() */ 00240 unsigned int m_softlimit; 00241 00242 std::list<VC> m_vcs; 00243 00244 mutable bool m_dirty_intersection; 00245 mutable bitset_t m_soft_intersection; 00246 mutable bitset_t m_hard_intersection; 00247 00248 mutable bool m_dirty_union; 00249 mutable bitset_t m_union; 00250 mutable bitset_t m_greedy_union; 00251 }; 00252 00253 inline HexPoint VCList::getX() const 00254 { 00255 return m_x; 00256 } 00257 00258 inline HexPoint VCList::getY() const 00259 { 00260 return m_y; 00261 } 00262 00263 inline int VCList::softlimit() const 00264 { 00265 return m_softlimit; 00266 } 00267 00268 inline void VCList::setSoftLimit(int limit) 00269 { 00270 if (limit != (int)m_softlimit) 00271 { 00272 m_softlimit = limit; 00273 m_dirty_intersection = true; 00274 } 00275 } 00276 00277 // FIXME: size() is might be O(n) for lists: 00278 // keep track of size on our own? 00279 inline std::size_t VCList::size() const 00280 { 00281 return m_vcs.size(); 00282 } 00283 00284 inline bool VCList::empty() const 00285 { 00286 return m_vcs.empty(); 00287 } 00288 00289 inline void VCList::dirty_list_unions() 00290 { 00291 m_dirty_union = true; 00292 } 00293 00294 inline void VCList::dirty_list_intersections() 00295 { 00296 m_dirty_intersection = true; 00297 } 00298 00299 inline void VCList::clear() 00300 { 00301 m_vcs.clear(); 00302 00303 dirty_list_unions(); 00304 00305 m_dirty_intersection = false; 00306 m_soft_intersection.set(); 00307 m_hard_intersection.set(); 00308 } 00309 00310 inline VCList::iterator VCList::begin() 00311 { 00312 return m_vcs.begin(); 00313 } 00314 00315 inline VCList::iterator VCList::end() 00316 { 00317 return m_vcs.end(); 00318 } 00319 00320 inline VCList::const_iterator VCList::begin() const 00321 { 00322 return m_vcs.begin(); 00323 } 00324 00325 inline VCList::const_iterator VCList::end() const 00326 { 00327 return m_vcs.end(); 00328 } 00329 00330 //---------------------------------------------------------------------------- 00331 00332 _END_BENZENE_NAMESPACE_ 00333 00334 #endif // VCLIST_HPP