-
Notifications
You must be signed in to change notification settings - Fork 22
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
Add compatibility wrapper for DeepMind Melting Pot #39
Conversation
…ight errors and comment consistency
Could you fix pre-commit and tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM, aside from some minor comments. @pseudo-rnd-thoughts may want to have a second look as he tends to be more detail oriented and may have preferences over certain aspects.
tests/test_meltingpot.py
Outdated
|
||
@pytest.mark.parametrize("substrate_name", SUBSTRATES) | ||
def test_seeding(substrate_name): | ||
"""Tests the seeding of the openspiel conversion wrapper.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in this docstring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch
tests/test_meltingpot.py
Outdated
@@ -0,0 +1,57 @@ | |||
"""Tests the functionality of the MeltingPotCompatibility wrapper on meltingpot substrates.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests look good to me, but perhaps @pseudo-rnd-thoughts may want to have a second look.
@@ -0,0 +1,61 @@ | |||
"""Shared utils for meltingpot.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks rather similar to the dm_env utils, do you think the two could be merged, especially the spec_to_space functionality? Or perhaps rename the timestep_to_observations into multiagent_timestep_to_observations to make it more verbose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call I’ll look into that
shimmy/meltingpot_compatibility.py
Outdated
self.player_roles = substrate.get_config(self.substrate_name).default_player_roles | ||
self.max_cycles = max_cycles | ||
self.env_config = {"substrate": self.substrate_name, "roles": self.player_roles} | ||
EzPickle.__init__(self, self.render_mode, self.env_config, self.max_cycles) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the ezpickle be moved up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move to be the first line of the function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The EzPickle init line takes a few arguments which need to be extracted from the environment (env config, which contains player_roles) so it can't be done on the first line.
shimmy/meltingpot_compatibility.py
Outdated
self.player_roles = substrate.get_config(self.substrate_name).default_player_roles | ||
self.max_cycles = max_cycles | ||
self.env_config = {"substrate": self.substrate_name, "roles": self.player_roles} | ||
EzPickle.__init__(self, self.render_mode, self.env_config, self.max_cycles) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move to be the first line of the function
shimmy/meltingpot_compatibility.py
Outdated
self._env.observation_spec()[0]['WORLD.RGB']) # type: ignore | ||
|
||
# Set agents | ||
self._num_players = len(self._env.observation_spec()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this include the "WORLD.RGB"? Should it not be len() - 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was code from their previous pettingzoo code and the number of players stayed consistent with the observation and such, but I’ll check again to see if it might be an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What it an issue ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WORLD.RGB is just one entry in each observation, self._env.observation_spec() just has a dict for each agent so is of length(num_players)
shimmy/meltingpot_compatibility.py
Outdated
|
||
state_space = utils.spec_to_space( | ||
self._env.observation_spec()[0]['WORLD.RGB']) | ||
return state_space |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we not using self.state_space
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean to make it in the init constructor rather than a separate method? I had it that way originally but saw the action space and observation space in most other examples were separate methods so thought it might be more readable that way. Although those are functions with agent id as input, whereas this is independent of agent. Wasn’t sure if it was necessary at all because a lot of examples don’t have state space included.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is just confusing as the observation-spec
doesn't change and you already define self.state_space
which is equivalent to this function. So just use the variable that already exists or remove the variable
shimmy/meltingpot_compatibility.py
Outdated
) -> Tuple[ | ||
ObsDict, Dict[str, float], Dict[str, bool], Dict[str, bool], Dict[str, dict] | ||
]: | ||
"""step. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update docstring
shimmy/meltingpot_compatibility.py
Outdated
""" | ||
rgb_arr = self.state()[0]['WORLD.RGB'] | ||
if self.render_mode == 'human': | ||
plt.cla() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jjshoots Do we care that we are using matplotlib for rendering
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, I think we should avoid import matplotlib if possible. I'm not sure how it's done in meltingpot, but if it's not possible to not use matplotlib, I think that's still fine. We can simply make it a dependency for meltingpot only.
@elliottower is it possible to use PIL instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not familiar with PIL but from some googling looks doable. https://stackoverflow.com/questions/57316491/how-to-convert-matplotlib-figure-to-pil-image-object-without-saving-image
Something like this? Or do you mean to avoid matplotlib entirely? Is it because plt is slow? And I’ve on seen pettingzoo games use pygame not PIL, is there a consensus on one or the other?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We generally try to avoid imports of large libraries, especially if we're not using their main functionality. Since we only want to display images, MPL is a bit overkill. That said, PIL is also a bit of a large library, and so is PyGame. I think the consensus for one over the other has thus far just been 'most of the other libraries tend not to use MPL, so let's not use that'. There may be other reasons that I don't know of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, will look into it today.
shimmy/utils/meltingpot.py
Outdated
}) | ||
|
||
|
||
def spec_to_space(spec: tree.Structure[dm_env.specs.Array]) -> spaces.Space: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As jet mentioned, remove and replace with the existing dm spec to space
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the existing spec to space is actually less general than this one, and is a bit less clear (imo) so I’ve actually replaced the existing one with this and adapted the functionality to work with both cases. Will commit the changes later today.
@jjshoots As meltingpot requires DMLab2D is it possible for test this in the CI? |
…for meltingpot env seeding
Addressed these comments (including the minor openspiel changes), cleaned up docstrings and swapped the rendering from plt to pygame. I also added a test for pygame rendering as it's different from how the underlying env does rendering by default, although it may not be necessary. Problem is now that the seeding seems to be broken and I'm not sure how to go about fixing it. @jjshoots @pseudo-rnd-thoughts |
@elliottower, seeding for meltingpot? It may be the case that meltingpot just has very bad seeding techniques that doesn't actually make it deterministic. This would not be the first time. Our solution to this was to set |
Oh okay that’s good to know. I asked how hard it would be to supply a seed and they said it wouldn’t be easy and recommended something similar to disable seeding. |
…o from parallel envs
…for meltingpot import
I found this in the CI
However, I don't seem to be able to replicate the issue locally. |
…stency across farama repos
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM, some minor questions which I think once solved get my greenlight for merging.
#!/bin/sh | ||
set -eu | ||
|
||
if [[ "$(uname -s)" == 'Linux' ]]; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nitpick, could we name /bin
to /scripts
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a good idea, do you agree @pseudo-rnd-thoughts ?
# "dm_control/compatibility-env-v0", env=wrapped_env, disable_env_checker=True | ||
# ) | ||
# check_env(env.unwrapped, skip_render_check=True) | ||
# env.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies if I missed out the discussion on this, but is there a reason this entire file is commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this is definitely a mistake from my part, I thought for some reason when I synced with master that this changed but now looking at master that file hasn’t changed for a month. Will clean it up.
|
||
Print the current game state. | ||
""" | ||
print(self.game_state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kinda weird since some openspiel environments actually have a render function, but I guess c'est la vie.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn’t actually aware of that, the current code just ignores rendering and says it’s not implemented but I could check if the env has a render function and if not just print the state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO, this PR has become several different PRs: adding meltingpot support, documentation updates and possibly more given the number of files edited.
Therefore, I would propose closing this PR and opening new PRs for each of the problems addressed. This should make reviewing and understanding the PRs later if necessary
@pseudo-rnd-thoughts Actually I think that's a bit counter productive. I mean for us it makes sense, but for Elliot it will be a whole lot of work |
It’s all good, it’s best practice so I’m happy to practice it now and spend the extra day splitting things up and organizing. Looks messy to do a single PR commit with all these changes (although committing directly to master I feel like the sequential changes would be fine, it’s just that PRs get condensed into one commit afaik) |
@elliottower I would recommend not using main for prs as it can cause issues if you need to revert commits etc |
I meant like if you had made some of these changes directly to main because you have access, without doing a PR, as separate commits, then it would probably be fine. Definitely agree about PRs though there’s a reason separate branches are used. Anyways I’m going to refactor and clean things up today and reopen some PRs here and on pettingzoo. |
See: google-deepmind/meltingpot#117
Pytest and pre-commit hooks passing.
Also fixed misc.pyrght errors (e.g., step() argument action of type int incompatible with int64 -> action: ActionType (from pettingzoo.utils.env) and made comments a bit more consistent (using the same language to describe the wrappers ,etc).