Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate normal_form_game.py #576

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Annotate normal_form_game.py #576

wants to merge 1 commit into from

Conversation

rht
Copy link
Contributor

@rht rht commented Apr 16, 2021

  • np.ndarray is a catch-all type for all ndarrays regardless of its dtype, and so, is unfortunately less specific than the docstring that specifies ndarray.
  • I'm unsure of the type of action_profile since the functions using it are not documented.
  • I found this bug: normal_form_game.py:921: error: Missing return statement in . There is a case where the function returns None instead of int when the if condition is never satisfied.

@pep8speaks
Copy link

Hello @rht! Thanks for opening this PR. We checked the lines you've touched for PEP 8 issues, and found:

Line 204:80: E501 line too long (82 > 79 characters)
Line 259:80: E501 line too long (92 > 79 characters)
Line 525:9: E125 continuation line with same indent as next logical line
Line 525:80: E501 line too long (86 > 79 characters)
Line 732:80: E501 line too long (94 > 79 characters)
Line 759:80: E501 line too long (86 > 79 characters)
Line 817:80: E501 line too long (90 > 79 characters)
Line 922:80: E501 line too long (83 > 79 characters)

@rht
Copy link
Contributor Author

rht commented Apr 16, 2021

Will fix the line too long issues later.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.003%) to 94.338% when pulling b2a8f98 on rht:master into 6ffbe57 on QuantEcon:master.

@rht
Copy link
Contributor Author

rht commented Apr 16, 2021

There is a case where the function returns None instead of int when the if condition is never satisfied.

There is never such case, from the way payoff_max is specified, but Mypy isn't aware of this. Just ignore the error?

@mmcky
Copy link
Contributor

mmcky commented Apr 16, 2021

Just ignore the error?

In Mypy is there a way to add an ignore such as # noqa for coveralls?

@oyamad
Copy link
Member

oyamad commented Apr 16, 2021

There is a case where the function returns None instead of int when the if condition is never satisfied.

Yes, it happens when tol < 0. (tol is supposed to be nonnegative, but it is just implicit.)

There are two options:

  1. Just return -1 when the if condition is never satisfied (which happens if and only if tol < 0).
  2. Let tol = 0 if tol < 0.

Maybe option 1?

@rht
Copy link
Contributor Author

rht commented Apr 16, 2021

There is a type: ignore for a single line, but the error appears exactly at the def best_response_2p(...) line. If this line is disabled, the entire function signature's type checking will also be disabled.

@rht
Copy link
Contributor Author

rht commented Apr 16, 2021

Just return -1 when the if condition is never satisfied (which happens if and only if tol < 0).

Maybe it is safer to tell the user there is a problem instead of -1? I tried raising an Exception at the end and Mypy no longer complains about missing a return. What should the exception message be?

@@ -233,7 +240,7 @@ def delete_action(self, action, player_idx=0):
payoff_array_new = np.delete(self.payoff_array, action, player_idx)
return Player(payoff_array_new)

def payoff_vector(self, opponents_actions):
def payoff_vector(self, opponents_actions: npt.ArrayLike) -> np.ndarray:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opponents_actions should have been IntOrArray, which is Union[int, npt.ArrayLike].
But doing so will cause problem in

reduce_last_player(payoff_vector, opponents_actions[i])
. A Union[int, ...] type generally can't be indexed. Alternative solution to my current version is to use cast() before the indexing to cast opponents_actions into an indexable.

Note that int is also part of npt.ArrayLike, since np.array(1) works.

@mmcky
Copy link
Contributor

mmcky commented Apr 30, 2021

Just return -1 when the if condition is never satisfied (which happens if and only if tol < 0).

Maybe it is safer to tell the user there is a problem instead of -1? I tried raising an Exception at the end and Mypy no longer complains about missing a return. What should the exception message be?

thanks @rht sorry for my slow response.

tol is supposed to be nonnegative, but it is just implicit

@oyamad should we add an exception if tol is negative instead and then the return is bounded.

@oyamad
Copy link
Member

oyamad commented Apr 30, 2021

should we add an exception if tol is negative instead

Actually, this function best_response_2p is for internal use. Negative tol should be handled by the outer function that calls best_response_2p. Let's just return some int, say -1, and write in the docstring, something like "Return -1 if there is no best response action, which occurs when tol < 0".

@oyamad
Copy link
Member

oyamad commented Apr 30, 2021

I'm unsure of the type of action_profile since the functions using it are not documented.

  • action_profile in __getitem__ and __setitem__ is int if N=1 and array_like if N>=2.
  • action_profile in is_nash is array_like.

So your annotations are correct.

@rht
Copy link
Contributor Author

rht commented May 1, 2021

should we add an exception if tol is negative instead

Actually, this function best_response_2p is for internal use. Negative tol should be handled by the outer function that calls best_response_2p. Let's just return some int, say -1, and write in the docstring, something like "Return -1 if there is no best response action, which occurs when tol < 0".

best_response_2p is currently exported as an external function (

from .normal_form_game import pure2mixed, best_response_2p
) and is not used internally anywhere in the module.

@mmcky
Copy link
Contributor

mmcky commented Apr 5, 2022

@oyamad are you happy with these annotations?

@oyamad oyamad self-assigned this Apr 5, 2022
@rht
Copy link
Contributor Author

rht commented Apr 5, 2022

I think it is safe to replace all of IntOrArrayT with npt.ArrayLike? The code selection part that checks whether actions is a scalar or array happens in

if isinstance(action, numbers.Integral): # pure action
return payoff_array.take(action, axis=-1)
else: # mixed action
return payoff_array.dot(action)
.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants