Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

InferiorCells.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file InferiorCells.cpp
00003 
00004     @todo Handle a sink in the dominated component graph being
00005     partially outside the mustplay -- in this case, no representative
00006     of the sink need be chosen (they are all losing).
00007 
00008     @note The set of dominated cells must be recomputed each time the
00009     domination graph or the vulnerable or reversible info is changed.
00010     Dominated() does this computation lazily when required.
00011 */
00012 //----------------------------------------------------------------------------
00013 
00014 #include "BitsetIterator.hpp"
00015 #include "InferiorCells.hpp"
00016 
00017 using namespace benzene;
00018 
00019 //----------------------------------------------------------------------------
00020 
00021 InferiorCells::InferiorCells()
00022     : m_dominated_computed(false)
00023 {
00024 }
00025 
00026 //----------------------------------------------------------------------------
00027 
00028 bitset_t InferiorCells::Dominated() const
00029 {
00030     if (!m_dominated_computed) {
00031         
00032         // remove vulnerable and reversible cells from graph
00033         Digraph<HexPoint> g(m_dom_graph);
00034         for (BitsetIterator p(Vulnerable()); p; ++p) {
00035             g.RemoveVertex(*p);
00036         }
00037         for (BitsetIterator p(Reversible()); p; ++p) {
00038             g.RemoveVertex(*p);
00039         }
00040 
00041         bitset_t captains = InferiorCellsUtil::FindDominationCaptains(g);
00042         bitset_t vertices = BitsetUtil::SetToBitset(g.Vertices());
00043         m_dominated = vertices - captains;
00044         m_dominated_computed = true;
00045 
00046         /// @todo ensure m_dominated is disjoint from all others.
00047         HexAssert((m_dominated & Vulnerable()).none());
00048         HexAssert((m_dominated & Reversible()).none());
00049     }
00050     return m_dominated;
00051 }
00052 
00053 
00054 bitset_t InferiorCells::All() const
00055 {
00056     return Dead()
00057         | Vulnerable() | Reversible() | Dominated()
00058         | Captured(BLACK) | Captured(WHITE) 
00059         | PermInf(BLACK) | PermInf(WHITE)
00060         | MutualFillin(BLACK) | MutualFillin(WHITE);
00061 }
00062 
00063 bitset_t InferiorCells::Fillin(HexColor color) const
00064 {
00065     bitset_t ret = Captured(color) | PermInf(color) | MutualFillin(color);
00066     if (color == DEAD_COLOR) ret |= Dead();
00067     return ret;
00068 }
00069 
00070 //----------------------------------------------------------------------------
00071 
00072 void InferiorCells::AddDead(HexPoint dead)
00073 {
00074     bitset_t b;
00075     b.set(dead);
00076     AddDead(b);
00077 }
00078 
00079 void InferiorCells::AddDead(const bitset_t& dead)
00080 {
00081     m_dead |= dead;
00082     
00083     RemoveVulnerable(dead);
00084     RemoveReversible(dead);
00085     RemoveDominated(dead);
00086 
00087     AssertPairwiseDisjoint();
00088 }
00089 
00090 void InferiorCells::AddCaptured(HexColor color, HexPoint captured)
00091 {
00092     bitset_t b;
00093     b.set(captured);
00094     AddCaptured(color, b);
00095 }
00096 
00097 void InferiorCells::AddCaptured(HexColor color, const bitset_t& captured)
00098 {
00099     m_captured[color] |= captured;
00100 
00101     RemoveVulnerable(captured);
00102     RemoveReversible(captured);
00103     RemoveDominated(captured);
00104 
00105     AssertPairwiseDisjoint();
00106 }
00107 
00108 void InferiorCells::AddPermInf(HexColor color, 
00109                                const bitset_t& cells, 
00110                                const bitset_t& carrier)
00111 {
00112     m_perm_inf[color] |= cells;
00113     m_perm_inf_carrier[color] |= carrier;
00114 
00115     RemoveVulnerable(cells);
00116     RemoveReversible(cells);
00117     RemoveDominated(cells);
00118 
00119     AssertPairwiseDisjoint();
00120 }
00121 
00122 void InferiorCells::AddPermInf(HexColor color, HexPoint cell, 
00123                                const bitset_t& carrier)
00124 {
00125     bitset_t b;
00126     b.set(cell);
00127     AddPermInf(color, b, carrier);
00128 }
00129 
00130 void InferiorCells::AddMutualFillin(HexColor color, 
00131                                     const bitset_t& cells, 
00132                                     const bitset_t& carrier)
00133 {
00134     m_mutual_fillin[color] |= cells;
00135     m_mutual_fillin_carrier[color] |= carrier;
00136 
00137     RemoveVulnerable(cells);
00138     RemoveReversible(cells);
00139     RemoveDominated(cells);
00140 
00141     AssertPairwiseDisjoint();
00142 }
00143 
00144 void InferiorCells::AddMutualFillin(HexColor color, HexPoint cell, 
00145                                     const bitset_t& carrier)
00146 {
00147     bitset_t b;
00148     b.set(cell);
00149     AddMutualFillin(color, b, carrier);
00150 }
00151 
00152 void InferiorCells::AddDominated(HexPoint cell, const std::set<HexPoint>& dom)
00153 {
00154     m_dom_graph.AddEdges(cell, dom);
00155     m_dominated_computed = false;
00156 
00157     //AssertPairwiseDisjoint();
00158 }
00159 
00160 void InferiorCells::AddDominated(HexPoint cell, HexPoint dominator)
00161 {
00162     m_dom_graph.AddEdge(cell, dominator);
00163     m_dominated_computed = false;
00164 
00165     //AssertPairwiseDisjoint();
00166 }
00167 
00168 void InferiorCells::AddVulnerable(HexPoint cell, 
00169                                   const std::set<HexPoint>& killers)
00170 {
00171     m_vulnerable.set(cell);
00172 
00173     // add each killer with an empty carrier
00174     std::set<HexPoint>::iterator it = killers.begin();
00175     for (; it != killers.end(); ++it) {
00176         m_killers[cell].insert(VulnerableKiller(*it));
00177     }
00178 
00179     // update reversible and dominated
00180     RemoveReversible(cell);
00181     m_dominated_computed = false;
00182 
00183     AssertPairwiseDisjoint();
00184 }
00185 
00186 void InferiorCells::AddVulnerable(HexPoint cell, 
00187                                   const std::set<VulnerableKiller>& killers)
00188 {
00189     m_vulnerable.set(cell);
00190     m_killers[cell].insert(killers.begin(), killers.end());
00191     RemoveReversible(cell);
00192     m_dominated_computed = false;
00193 
00194     AssertPairwiseDisjoint();
00195 }
00196 
00197 void InferiorCells::AddVulnerable(HexPoint cell, HexPoint killer)
00198 {
00199     m_vulnerable.set(cell);
00200     m_killers[cell].insert(VulnerableKiller(killer));
00201     RemoveReversible(cell);
00202     m_dominated_computed = false;
00203 
00204     AssertPairwiseDisjoint();
00205 }
00206 
00207 void InferiorCells::AddVulnerable(HexPoint cell, const VulnerableKiller& killer)
00208 {
00209     m_vulnerable.set(cell);
00210     m_killers[cell].insert(killer);
00211     RemoveReversible(cell);
00212     m_dominated_computed = false;
00213 
00214     AssertPairwiseDisjoint();
00215 }
00216 
00217 void InferiorCells::AddReversible(HexPoint cell, bitset_t carrier,
00218                                   HexPoint reverser)
00219 {
00220     // Cell and carrier have equivalent roles, so just merge
00221     bitset_t reversibleCandidates = carrier;
00222     reversibleCandidates.set(cell);
00223 
00224     // Cannot add any if not independent of previous reversible cells
00225     if (m_allReversibleCarriers.test(reverser)) return;
00226     if ((m_allReversers & reversibleCandidates).any()) return;
00227     if (reversibleCandidates.test(reverser)) return;
00228 
00229     // Independent, so mark all (non-vulnerable) candidates as reversible
00230     bool noAdditions = true;
00231     for (BitsetIterator it(reversibleCandidates); it; ++it)
00232     {
00233         if (m_vulnerable.test(*it)) continue;
00234         noAdditions = false;
00235         m_reversible.set(*it);
00236         m_reversers[*it].insert(reverser);
00237     }
00238     if (noAdditions) return;
00239     m_allReversibleCarriers |= reversibleCandidates;
00240     m_allReversers.set(reverser);
00241 
00242     m_dominated_computed = false;
00243     AssertPairwiseDisjoint();
00244 }
00245 
00246 void InferiorCells::AddReversible(HexPoint cell, bitset_t carrier,
00247                                   const std::set<HexPoint>& reversers)
00248 {
00249     // Cell and carrier have equivalent roles, so just merge
00250     bitset_t reversibleCandidates = carrier;
00251     reversibleCandidates.set(cell);
00252     // Merge all reversers into one big pot (all or nothing :)
00253     bitset_t reverserCandidates;
00254     for (std::set<HexPoint>::iterator it = reversers.begin();
00255          it != reversers.end(); ++it)
00256     {
00257         reverserCandidates.set(*it);
00258     }
00259 
00260     // Cannot add any if not independent of previous reversible cells
00261     if ((m_allReversibleCarriers & reverserCandidates).any()) return;
00262     if ((m_allReversers & reversibleCandidates).any()) return;
00263     if ((reverserCandidates & reversibleCandidates).any()) return;
00264 
00265     // Independent, so mark all (non-vulnerable) candidates as reversible
00266     bool noAdditions = true;
00267     for (BitsetIterator it(reversibleCandidates); it; ++it)
00268     {
00269         if (m_vulnerable.test(*it)) continue;
00270         noAdditions = false;
00271         m_reversible.set(*it);
00272         m_reversers[*it].insert(reversers.begin(), reversers.end());
00273     }
00274     if (noAdditions) return;
00275     m_allReversibleCarriers |= reversibleCandidates;
00276     m_allReversers |= reverserCandidates;
00277 
00278     m_dominated_computed = false;
00279     AssertPairwiseDisjoint();
00280 }
00281 
00282 //----------------------------------------------------------------------------
00283 
00284 void InferiorCells::AddDominatedFrom(const InferiorCells& other)
00285 {
00286     bitset_t vertices=BitsetUtil::SetToBitset(other.m_dom_graph.Vertices());
00287     for (BitsetIterator p(vertices); p; ++p) {
00288         AddDominated(*p, other.m_dom_graph.OutSet(*p));
00289     }
00290     //AssertPairwiseDisjoint();
00291 }
00292 
00293 void InferiorCells::AddVulnerableFrom(const InferiorCells& other)
00294 {
00295     for (BitsetIterator p(other.Vulnerable()); p; ++p) {
00296         AddVulnerable(*p, other.m_killers[*p]);
00297     }
00298     AssertPairwiseDisjoint();
00299 }
00300 
00301 void InferiorCells::AddReversibleFrom(const InferiorCells& other)
00302 {
00303     for (BitsetIterator p(other.Reversible()); p; ++p) {
00304         AddReversible(*p, EMPTY_BITSET, other.m_reversers[*p]);
00305     }
00306     m_allReversibleCarriers |= other.AllReversibleCarriers();
00307     m_allReversers |= other.AllReversers();
00308     AssertPairwiseDisjoint();
00309 }
00310 
00311 void InferiorCells::AddPermInfFrom(HexColor color, const InferiorCells& other)
00312 {
00313     m_perm_inf[color] |= other.m_perm_inf[color];
00314     m_perm_inf_carrier[color] |= other.m_perm_inf_carrier[color];
00315     AssertPairwiseDisjoint();
00316 }
00317 
00318 void InferiorCells::AddMutualFillinFrom(HexColor color,
00319                                         const InferiorCells& other)
00320 {
00321     m_mutual_fillin[color] |= other.m_mutual_fillin[color];
00322     m_mutual_fillin_carrier[color] |= other.m_mutual_fillin_carrier[color];
00323     AssertPairwiseDisjoint();
00324 }
00325 
00326 //----------------------------------------------------------------------------
00327 
00328 void InferiorCells::Clear()
00329 {
00330     ClearDead();
00331     ClearVulnerable();
00332     ClearReversible();
00333     for (BWIterator c; c; ++c) {
00334         ClearCaptured(*c);
00335         ClearPermInf(*c);
00336         ClearMutualFillin(*c);
00337     }
00338     ClearDominated();
00339 }
00340 
00341 void InferiorCells::ClearDead()
00342 {
00343     m_dead.reset();
00344 }
00345 
00346 void InferiorCells::ClearCaptured(HexColor color)
00347 {
00348     m_captured[color].reset();
00349 }
00350 
00351 void InferiorCells::ClearPermInf(HexColor color)
00352 {
00353     m_perm_inf[color].reset();
00354     m_perm_inf_carrier[color].reset();
00355 }
00356 
00357 void InferiorCells::ClearMutualFillin(HexColor color)
00358 {
00359     m_mutual_fillin[color].reset();
00360     m_mutual_fillin_carrier[color].reset();
00361 }
00362 
00363 void InferiorCells::ClearVulnerable()
00364 {
00365     RemoveVulnerable(m_vulnerable);
00366     m_dominated_computed = false;
00367 }
00368 
00369 void InferiorCells::ClearReversible()
00370 {
00371     RemoveReversible(m_reversible);
00372     m_allReversibleCarriers.reset();
00373     m_allReversers.reset();
00374     m_dominated_computed = false;
00375 }
00376 
00377 void InferiorCells::ClearDominated()
00378 {
00379     m_dom_graph.Clear();
00380     m_dominated_computed = false;
00381 }
00382 
00383 //----------------------------------------------------------------------------
00384 
00385 void InferiorCells::RemoveDominated(const bitset_t& dominated)
00386 {
00387     bitset_t vertices = BitsetUtil::SetToBitset(m_dom_graph.Vertices());
00388     for (BitsetIterator p(vertices & dominated); p; ++p) {
00389         m_dom_graph.RemoveVertex(*p);
00390     }
00391     m_dominated_computed = false;
00392 }
00393 
00394 void InferiorCells::RemoveVulnerable(const bitset_t& vulnerable)
00395 {
00396     for (BitsetIterator p(vulnerable & m_vulnerable); p; ++p) {
00397         m_killers[*p].clear();
00398     }
00399     m_vulnerable = m_vulnerable - vulnerable;
00400     m_dominated_computed = false;
00401 }
00402 
00403 void InferiorCells::RemoveReversible(const bitset_t& reversible)
00404 {
00405     for (BitsetIterator p(reversible & m_reversible); p; ++p) {
00406         m_reversers[*p].clear();
00407     }
00408     m_reversible = m_reversible - reversible;
00409     m_dominated_computed = false;
00410 }
00411 
00412 void InferiorCells::RemoveReversible(HexPoint reversible)
00413 {
00414     if (m_reversible.test(reversible)) {
00415         m_reversers[reversible].clear();
00416         m_reversible.reset(reversible);
00417         m_dominated_computed = false;
00418     }
00419 }
00420 
00421 //----------------------------------------------------------------------------
00422 
00423 void InferiorCells::AssertPairwiseDisjoint() const
00424 {
00425     HexAssert((m_dead & m_vulnerable).none());
00426     HexAssert((m_dead & m_reversible).none());
00427     HexAssert((m_reversible & m_vulnerable).none());
00428     HexAssert((m_allReversibleCarriers & m_allReversers).none());
00429     HexAssert((m_reversible & m_allReversibleCarriers) == m_reversible);
00430     HexAssert(!m_dominated_computed || (m_dead & m_dominated).none());
00431     HexAssert(!m_dominated_computed || (m_vulnerable & m_dominated).none());
00432     HexAssert(!m_dominated_computed || (m_reversible & m_dominated).none());
00433 
00434     for (BWIterator c; c; ++c) {
00435         HexAssert((m_captured[*c] & m_dead).none());
00436         HexAssert(!m_dominated_computed
00437                   || (m_captured[*c] & m_dominated).none());
00438         HexAssert((m_captured[*c] & m_vulnerable).none());
00439         HexAssert((m_captured[*c] & m_reversible).none());
00440         HexAssert((m_captured[*c] & m_captured[!*c]).none());
00441         
00442         HexAssert((m_perm_inf[*c] & m_dead).none());
00443         HexAssert(!m_dominated_computed
00444                   || (m_perm_inf[*c] & m_dominated).none());
00445         HexAssert((m_perm_inf[*c] & m_vulnerable).none());
00446         HexAssert((m_perm_inf[*c] & m_reversible).none());
00447 
00448         HexAssert((m_captured[*c] & m_perm_inf[*c]).none());
00449         HexAssert((m_captured[*c] & m_perm_inf[!*c]).none());
00450 
00451         HexAssert((m_mutual_fillin[*c] & m_dead).none());
00452         HexAssert(!m_dominated_computed
00453                   || (m_mutual_fillin[*c] & m_dominated).none());
00454         HexAssert((m_mutual_fillin[*c] & m_vulnerable).none());
00455         HexAssert((m_mutual_fillin[*c] & m_reversible).none());
00456 
00457         HexAssert((m_mutual_fillin[*c] & m_captured[*c]).none());
00458         HexAssert((m_mutual_fillin[*c] & m_captured[!*c]).none());
00459         HexAssert((m_mutual_fillin[*c] & m_perm_inf[*c]).none());
00460         HexAssert((m_mutual_fillin[*c] & m_perm_inf[!*c]).none());
00461     }
00462 }
00463 
00464 //----------------------------------------------------------------------------
00465 
00466 bitset_t InferiorCells::FindPresimplicialPairs() const
00467 {
00468     bitset_t fillin;
00469     std::set<VulnerableKiller>::iterator k1, k2;
00470 
00471     /** @todo Handle vulnerable cycles larger than length 2? If they
00472         occur, they are extrememly rare, so it is probably not worth
00473         it. */
00474 
00475     for (BitsetIterator x(m_vulnerable); x; ++x) {
00476         if (fillin.test(*x)) continue;
00477 
00478         for (k1 = m_killers[*x].begin(); k1 != m_killers[*x].end(); ++k1) {
00479             HexPoint y = k1->killer();
00480             if (fillin.test(y)) continue;
00481             if ((k1->carrier() & fillin).any()) continue;
00482 
00483             bool success = false;
00484             for (k2 = m_killers[y].begin(); k2 != m_killers[y].end(); ++k2) {
00485                 HexPoint z = k2->killer();
00486                 if (z != *x) continue;
00487                 if (fillin.test(z)) continue;
00488                 if ((k2->carrier() & fillin).any()) continue;
00489 
00490                 // if x kills y and y kills x and the carriers do not
00491                 // intersect, fill them in along with their carriers. 
00492                 if ((k1->carrier() & k2->carrier()).none()) {
00493                     bitset_t both = k1->carrier() | k2->carrier();
00494                     if ((both & fillin).none()) {
00495                         fillin |= both;
00496                         fillin.set(y);
00497                         fillin.set(*x);
00498                         success = true;
00499                         break;
00500                     }
00501                 }
00502             }
00503 
00504             // if x and a killer of x have been filled in, there is no
00505             // point checking the remaining killers of x. 
00506             if (success) break;
00507         }
00508     }
00509 
00510     return fillin;
00511 }
00512 
00513 bitset_t InferiorCells::DeductionSet(HexColor color) const
00514 {
00515     bitset_t deductionSet;
00516     deductionSet = Captured(color);
00517     deductionSet |= PermInf(color);
00518     deductionSet |= PermInfCarrier(color);
00519     deductionSet |= MutualFillin(color);
00520     deductionSet |= MutualFillinCarrier(color);
00521     return deductionSet;
00522 }
00523 
00524 //----------------------------------------------------------------------------
00525 
00526 std::string InferiorCells::GuiOutput() const
00527 {
00528     std::size_t c = 0;
00529     std::ostringstream out;
00530     for (int i = 0; i < FIRST_INVALID; ++i) 
00531     {
00532         HexPoint p = static_cast<HexPoint>(i);
00533         std::ostringstream os;
00534         
00535         os << " " << p << " ";
00536         if (Dead().test(i)) 
00537         {
00538             os << "fd";
00539             os << ((DEAD_COLOR == BLACK) ? "b" : "w");
00540         }
00541         else if (Captured(BLACK).test(i))
00542             os << "fcb";
00543         else if (Captured(WHITE).test(i))
00544             os << "fcw";
00545         else if (PermInf(BLACK).test(i))
00546             os << "fpb";
00547         else if (PermInf(WHITE).test(i))
00548             os << "fpw";
00549         else if (MutualFillin(BLACK).test(i))
00550             os << "fub";
00551         else if (MutualFillin(WHITE).test(i))
00552             os << "fuw";
00553         else if (Vulnerable().test(i)) 
00554         {
00555             os << "iv[";
00556             bool first=true;
00557             std::set<VulnerableKiller>::const_iterator i;
00558             for (i = m_killers[p].begin(); i != m_killers[p].end(); ++i) 
00559             {
00560                 if (!first) os << "-";
00561                 os << i->killer();
00562                 first = false;
00563             }
00564             os << "]";
00565         }
00566         else if (Reversible().test(i)) 
00567         {
00568             os << "ir[";
00569             bool first=true;
00570             std::set<HexPoint>::const_iterator i;
00571             for (i = m_reversers[p].begin(); i != m_reversers[p].end(); ++i) 
00572             {
00573                 if (!first) os << "-";
00574                 os << *i;
00575                 first = false;
00576             }
00577             os << "]";
00578         }
00579         else if (Dominated().test(i)) 
00580         {
00581             os << "id[";
00582             bool first=true;
00583             std::set<HexPoint>::iterator i;
00584             for (i=m_dom_graph.out_begin(p); i!=m_dom_graph.out_end(p); ++i) 
00585             {
00586                 // PHIL IS CONFUSED: CAN THIS HAPPEN??
00587                 if (Vulnerable().test(*i))
00588                     continue;
00589                 if (!first) os << "-";
00590                 os << *i;
00591                 first = false;
00592             }
00593             os << "]";
00594         }
00595         else 
00596             continue;
00597 
00598         std::string str = os.str();
00599         std::size_t t = str.size();
00600         if (c + t > 40) 
00601         {
00602             out << '\n';
00603             c = t;
00604         } 
00605         else 
00606             c += t;
00607 
00608         out << str;
00609     }
00610     return out.str();
00611 }
00612 
00613 //----------------------------------------------------------------------------
00614 
00615 bitset_t 
00616 InferiorCellsUtil::FindDominationCaptains(const Digraph<HexPoint>& graph)
00617 {
00618     bitset_t captains;
00619 
00620     // Find the strongly connected components of the domination graph.
00621     std::vector<HexPointSet> comp;
00622     graph.FindStronglyConnectedComponents(comp);
00623 
00624     // Find the sinks in the component graph
00625     for (std::size_t i=0; i < comp.size(); ++i) {
00626 
00627         std::set<HexPoint> out;
00628         graph.OutSet(comp[i], out);
00629 
00630         // remove members of the component from the outset since
00631         // we are only concerned with edges leaving the component
00632         std::set<HexPoint>::iterator it;
00633         for (it = comp[i].begin(); it != comp[i].end(); ++it) 
00634             out.erase(*it);
00635         
00636         // if a sink, pick a representative for the component
00637         if (out.empty()) {
00638             captains.set(*comp[i].begin());
00639         }
00640     }
00641     
00642     return captains;
00643 }
00644 
00645 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3