@@ -587,10 +587,13 @@ class MixedBehaviorProfile:
587587 self._check_validity()
588588 return self._is_defined_at(self.game._resolve_infoset(infoset , "is_defined_at"))
589589
590- def belief(self , node: NodeReference ) -> ProfileDType:
590+ def belief(self , node: NodeReference ) -> ProfileDType | None :
591591 """Returns the conditional probability that a node is reached , given that
592592 its information set is reached.
593593
594+ If the information set is not reachable , the belief is not well-defined.
595+ In this case , the function returns `None`.
596+
594597 Parameters
595598 ----------
596599 node
@@ -630,10 +633,13 @@ class MixedBehaviorProfile:
630633 return self._payoff(resolved_player )
631634
632635 def node_value(self , player: PlayerReference ,
633- node: NodeReference ) -> ProfileDType:
636+ node: NodeReference ) -> ProfileDType | None :
634637 """Returns the expected payoff to `player` conditional on play reaching `node`,
635638 if all players play according to the profile.
636639
640+ If the node's information set is not reachable , in general the node value
641+ is not well-defined. In this case , the function returns `None`.
642+
637643 Parameters
638644 ----------
639645 player : Player or str
@@ -661,10 +667,13 @@ class MixedBehaviorProfile:
661667 raise ValueError("node_value() is not defined for the chance player")
662668 return self._node_value(resolved_player , resolved_node )
663669
664- def infoset_value(self , infoset: InfosetReference ) -> ProfileDType:
670+ def infoset_value(self , infoset: InfosetReference ) -> ProfileDType | None :
665671 """Returns the expected payoff to the player conditional on reaching an information set ,
666672 if all players play according to the profile.
667673
674+ If the information set is not reachable , the expected payoff is not well-defined.
675+ In this case , the function returns `None`.
676+
668677 Parameters
669678 ----------
670679 infoset : Infoset or str
@@ -686,10 +695,13 @@ class MixedBehaviorProfile:
686695 raise ValueError("infoset_value() is not defined for the chance player")
687696 return self._infoset_value(resolved_infoset )
688697
689- def action_value(self , action: ActionReference ) -> ProfileDType:
698+ def action_value(self , action: ActionReference ) -> ProfileDType | None :
690699 """Returns the expected payoff to the player of playing an action conditional on reaching
691700 its information set , if all players play according to the profile.
692701
702+ If the information set is not reachable , the expected payoff is not well-defined.
703+ In this case , the function returns `None`.
704+
693705 Parameters
694706 ----------
695707 action : Action or str
@@ -704,6 +716,10 @@ class MixedBehaviorProfile:
704716 If `action` is a string and no action in the game has that label.
705717 ValueError
706718 If `action` resolves to an action that belongs to the chance player
719+
720+ See also
721+ --------
722+ MixedBehaviorProfile.infoset_prob
707723 """
708724 self._check_validity()
709725 resolved_action = self .game._resolve_action(action, " action_value" )
@@ -945,22 +961,34 @@ class MixedBehaviorProfileDouble(MixedBehaviorProfile):
945961 return deref(self.profile ).GetPayoff(player.player )
946962
947963 def _belief(self , node: Node ) -> float:
948- return deref(self.profile ).GetBeliefProb(node.node )
964+ cdef optional[double] value = deref(self .profile).GetBeliefProb(node.node)
965+ if value.has_value():
966+ return value.value()
967+ return None
949968
950969 def _realiz_prob (self , node: Node ) -> float:
951970 return deref(self.profile ).GetRealizProb(node.node )
952971
953972 def _infoset_prob(self , infoset: Infoset ) -> float:
954973 return deref(self.profile ).GetInfosetProb(infoset.infoset )
955974
956- def _infoset_value(self , infoset: Infoset ) -> float:
957- return deref(self.profile ).GetPayoff(infoset.infoset )
975+ def _infoset_value(self , infoset: Infoset ) -> float | None:
976+ cdef optional[double] value = deref(self .profile).GetPayoff(infoset.infoset)
977+ if value.has_value():
978+ return value.value()
979+ return None
958980
959- def _node_value(self , player: Player , node: Node ) -> float:
960- return deref(self.profile ).GetPayoff(player.player , node.node )
981+ def _node_value (self , player: Player , node: Node ) -> float | None:
982+ cdef optional[double] value = deref(self .profile).GetPayoff(player.player, node.node)
983+ if value.has_value():
984+ return value.value()
985+ return None
961986
962- def _action_value(self , action: Action ) -> float:
963- return deref(self.profile ).GetPayoff(action.action )
987+ def _action_value (self , action: Action ) -> float | None:
988+ cdef optional[double] value = deref(self .profile).GetPayoff(action.action)
989+ if value.has_value():
990+ return value.value()
991+ return None
964992
965993 def _action_regret (self , action: Action ) -> float:
966994 return deref(self.profile ).GetRegret(action.action )
@@ -1047,22 +1075,34 @@ class MixedBehaviorProfileRational(MixedBehaviorProfile):
10471075 return rat_to_py(deref(self.profile ).GetPayoff(player.player ))
10481076
10491077 def _belief(self , node: Node ) -> Rational:
1050- return rat_to_py(deref(self.profile ).GetBeliefProb(node.node ))
1078+ cdef optional[c_Rational] value = deref(self .profile).GetBeliefProb(node.node)
1079+ if value.has_value():
1080+ return rat_to_py(value.value())
1081+ return None
10511082
10521083 def _realiz_prob (self , node: Node ) -> Rational:
10531084 return rat_to_py(deref(self.profile ).GetRealizProb(node.node ))
10541085
10551086 def _infoset_prob(self , infoset: Infoset ) -> Rational:
10561087 return rat_to_py(deref(self.profile ).GetInfosetProb(infoset.infoset ))
10571088
1058- def _infoset_value(self , infoset: Infoset ) -> Rational:
1059- return rat_to_py(deref(self.profile ).GetPayoff(infoset.infoset ))
1060-
1061- def _node_value(self , player: Player , node: Node ) -> Rational:
1062- return rat_to_py(deref(self.profile ).GetPayoff(player.player , node.node ))
1063-
1064- def _action_value(self , action: Action ) -> Rational:
1065- return rat_to_py(deref(self.profile ).GetPayoff(action.action ))
1089+ def _infoset_value(self , infoset: Infoset ) -> Rational | None:
1090+ cdef optional[c_Rational] value = deref(self .profile).GetPayoff(infoset.infoset)
1091+ if value.has_value():
1092+ return rat_to_py(value.value())
1093+ return None
1094+
1095+ def _node_value (self , player: Player , node: Node ) -> Rational | None:
1096+ cdef optional[c_Rational] value = deref(self .profile).GetPayoff(player.player, node.node)
1097+ if value.has_value():
1098+ return rat_to_py(value.value())
1099+ return None
1100+
1101+ def _action_value (self , action: Action ) -> Rational | None:
1102+ cdef optional[c_Rational] value = deref(self .profile).GetPayoff(action.action)
1103+ if value.has_value():
1104+ return rat_to_py(value.value())
1105+ return None
10661106
10671107 def _action_regret (self , action: Action ) -> Rational:
10681108 return rat_to_py(deref(self.profile ).GetRegret(action.action ))
0 commit comments