@@ -736,61 +736,21 @@ bool GameTreeRep::IsConstSum() const
736736
737737bool GameTreeRep::IsPerfectRecall () const
738738{
739- using ChildIterator = GameNodeRep::Children::iterator;
740- using ActionIterator = GameInfosetRep::Actions::iterator;
741-
742- std::map<GamePlayer, std::stack<GameAction>> prior_actions;
743- std::map<GameInfoset, std::vector<GameAction>> infoset_parents;
744- std::stack<std::tuple<GameNode, ChildIterator, ActionIterator>> position;
745-
746- for (auto player : GetPlayers ()) {
747- prior_actions[player].emplace (nullptr );
739+ if (m_infosetParents.empty () && !GetRoot ()->IsTerminal ()) {
740+ const_cast <GameTreeRep *>(this )->BuildInfosetParents ();
748741 }
749- prior_actions[GetChance ()].emplace (nullptr );
750- prior_actions[GetRoot ()->GetPlayer ()].emplace (nullptr );
751742
752743 if (GetRoot ()->IsTerminal ()) {
753744 return true ;
754745 }
755746
756- position.emplace (GetRoot (), GetRoot ()->GetChildren ().begin (),
757- GetRoot ()->GetInfoset ()->GetActions ().begin ());
758-
759- infoset_parents[GetRoot ()->GetInfoset ()].emplace_back (nullptr );
760-
761- while (!position.empty ()) {
762- auto &[parent, child_it, action_it] = position.top ();
763-
764- if (child_it != parent->GetChildren ().end ()) {
765- const GameNode child = *child_it;
766- const GameAction action = *action_it;
767-
768- prior_actions[parent->GetPlayer ()].top () = action;
769-
770- if (!child->IsTerminal ()) {
771- infoset_parents[child->GetInfoset ()].push_back (prior_actions[child->GetPlayer ()].top ());
772- position.emplace (child, child->GetChildren ().begin (),
773- child->GetInfoset ()->GetActions ().begin ());
774- prior_actions[child->GetPlayer ()].emplace (nullptr );
775- }
776- ++child_it;
777- ++action_it;
778- }
779-
780- else {
781- prior_actions[parent->GetPlayer ()].pop ();
782- position.pop ();
783- }
784- }
785-
786- for (const auto &[infoset, parent_action_options] : infoset_parents) {
747+ for (const auto &[infoset, parent_action_options] : m_infosetParents) {
787748 const std::set<GameAction> unique_parents (parent_action_options.begin (),
788749 parent_action_options.end ());
789750 if (unique_parents.size () > 1 ) {
790751 return false ;
791752 }
792753 }
793-
794754 return true ;
795755}
796756
@@ -867,6 +827,7 @@ void GameTreeRep::ClearComputedValues() const
867827 player->m_strategies .clear ();
868828 }
869829 const_cast <GameTreeRep *>(this )->m_nodePlays .clear ();
830+ const_cast <GameTreeRep *>(this )->m_infosetParents .clear ();
870831 m_computedValues = false ;
871832}
872833
@@ -905,6 +866,43 @@ std::vector<GameNodeRep *> GameTreeRep::BuildConsistentPlaysRecursiveImpl(GameNo
905866 return consistent_plays;
906867}
907868
869+ void GameTreeRep::BuildInfosetParents ()
870+ {
871+ std::map<GamePlayer, std::stack<GameAction>> prior_actions;
872+ std::stack<ActionsIterator> position;
873+
874+ for (auto player : GetPlayers ()) {
875+ prior_actions[player].emplace (nullptr );
876+ }
877+ prior_actions[GetChance ()].emplace (nullptr );
878+ prior_actions[GetRoot ()->GetPlayer ()].emplace (nullptr );
879+
880+ position.emplace (GetRoot ()->GetActions ().begin ());
881+ m_infosetParents[GetRoot ()->GetInfoset ()].emplace_back (nullptr );
882+
883+ while (!position.empty ()) {
884+ ActionsIterator ¤t_it = position.top ();
885+ const GameNode parent = current_it.GetOwner ();
886+
887+ if (current_it != parent->GetActions ().end ()) {
888+ auto [action, child] = *current_it;
889+
890+ prior_actions[parent->GetPlayer ()].top () = action;
891+
892+ if (!child->IsTerminal ()) {
893+ m_infosetParents[child->GetInfoset ()].push_back (prior_actions[child->GetPlayer ()].top ());
894+ position.emplace (child->GetActions ().begin ());
895+ prior_actions[child->GetPlayer ()].emplace (nullptr );
896+ }
897+ ++current_it;
898+ }
899+ else {
900+ prior_actions[parent->GetPlayer ()].pop ();
901+ position.pop ();
902+ }
903+ }
904+ }
905+
908906// ------------------------------------------------------------------------
909907// GameTreeRep: Writing data files
910908// ------------------------------------------------------------------------
0 commit comments