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

Remove dynamic classes and tidy imports #852

Merged
merged 14 commits into from
Feb 10, 2017
Merged

Remove dynamic classes and tidy imports #852

merged 14 commits into from
Feb 10, 2017

Conversation

drvinceknight
Copy link
Member

@drvinceknight drvinceknight commented Feb 5, 2017

This gets rid of the dynamic lookerup classes.

I also tided a number of things in our imports to make type checking happier:

This is the remaining output of running mypy on the full library:

Axelrod(845) ✗: mypy --ignore-missing-imports --follow-imports skip axelrod
axelrod/player.py:92: error: Need type annotation for variable
axelrod/strategies/meta.py:388: error: Invalid type "axelrod.strategies.meta.NiceMetaWinnerEnsemble"
axelrod/strategies/meta.py:388: error: Invalid base class
axelrod/strategies/meta.py:400: error: Invalid type "axelrod.strategies.meta.NiceMetaWinnerEnsemble"
axelrod/strategies/meta.py:400: error: Invalid base class
axelrod/strategies/meta.py:411: error: Invalid type "axelrod.strategies.meta.NiceMetaWinnerEnsemble"
axelrod/strategies/meta.py:411: error: Invalid base class
axelrod/strategies/meta.py:422: error: Invalid type "axelrod.strategies.meta.NiceMetaWinnerEnsemble"
axelrod/strategies/meta.py:422: error: Invalid base class
axelrod/strategies/meta.py:433: error: Invalid type "axelrod.strategies.meta.NiceMetaWinnerEnsemble"
axelrod/strategies/meta.py:433: error: Invalid base class
axelrod/__init__.py:19: error: Name 'strategies' already defined
axelrod/tests/unit/test_windows_detection.py:9: error: 'overload' decorator expected
axelrod/tests/unit/test_windows_detection.py:15: error: 'overload' decorator expected
axelrod/tests/unit/test_player.py:170: error: Need type annotation for variable
axelrod/tests/unit/test_interaction_utils.py:26: error: List item 0 has incompatible type "Tuple[Tuple[str, str], float]"
axelrod/tests/unit/test_interaction_utils.py:26: error: List item 1 has incompatible type "Tuple[Tuple[str, str], float]"
axelrod/tests/unit/test_interaction_utils.py:27: error: List item 0 has incompatible type "Tuple[Tuple[str, str], float]"
axelrod/tests/unit/test_interaction_utils.py:28: error: List item 0 has incompatible type "Tuple[Tuple[str, str], float]"
axelrod/tests/unit/test_interaction_utils.py:28: error: List item 1 has incompatible type "Tuple[Tuple[str, str], float]"

I suggest that once this PR is merged we take that list and open another issue aiming to get rid of those lasting items.

@marcharper
Copy link
Member

Can this be fixed without removing strategy transformers?

axelrod/strategies/meta.py:388: error: Invalid type "axelrod.strategies.meta.NiceMetaWinnerEnsemble"
axelrod/strategies/meta.py:388: error: Invalid base class

@drvinceknight
Copy link
Member Author

Can this be fixed without removing strategy transformers?

I have no idea.

It took me quite a while to get this far so I suggest that gets looked in to after this PR. Either way we're not going to remove strategy transformers right?

@@ -21,8 +22,7 @@ class AverageCopier(Player):
'manipulates_state': False
}

@staticmethod
def strategy(opponent: Player) -> Action:
Copy link
Member

Choose a reason for hiding this comment

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

because of the random?

Copy link
Member Author

Choose a reason for hiding this comment

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

This was being pointed out as an error by mypy something to do with the method not being in line with the parent class.

# Add the generated class to the module dictionary so it can be
# imported into other modules
setattr(module, class_name, new_class)
class EvolvedLookerUp0_0_1(LookerUp):
Copy link
Member

Choose a reason for hiding this comment

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

I don't know that we actually want to add all of these to the library. I only included a few in the axelrod.strategies list -- maybe just add those? Some of the small ones shadow strategies in the library already, and the ones with larger parameters don't seem to outperform 2_2_2 for the most part.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, you only include 1-1-1 and 2-2-2 in the whole list. Should we go ahead and just include those?

@marcharper
Copy link
Member

It took me quite a while to get this far so I suggest that gets looked in to after this PR. Either way we're not going to remove strategy transformers right?

I don't know? If not then why are we removing the dynamic class generation for LookerUp? For readability? I'm not opposed per se I'm just not sure what problem it solves.

@drvinceknight
Copy link
Member Author

drvinceknight commented Feb 5, 2017

I don't know?

We certainly should not remove the strategy transformers.

If not then why are we removing the dynamic class generation for LookerUp? For readability? I'm not opposed per se I'm just not sure what problem it solves.

Readability would be a big reason for me, I'd almost turn this around the other way, going back to my original question on #845: what problem does having dynamically generated classes solve?

I actually found this quite hard to untangle working on this PR so would be strongly in favour of verbose class definitions (in line with the rest of the library). I'd also suggest that if we are only going to have 1-1-1 and 2-2-2 (which I'm fine with) then we could get rid of the data file for lookerups.

I'd actually suggest that the whole reading in of data from the external source doesn't help with readability. For example in this particular case there was an error in the header which caused me a 5 minute labyrinth run around but that's perhaps a discussion for another PR.

@marcharper
Copy link
Member

Ok, I understand. The reason I did it the way it currently is was so that if someone else wants to play with the other variants they can easily, and they wouldn't be tempted to add new variants that had already been created. It was also easy to add a bunch of variants to the library by just adding new lines in the data file rather than write new classes each time, which is pretty tedious and involves a lot of repeated boilerplate that's easy to mess up -- class name, data, player name, parent class... it was much easier to just comment out a line in the data file and add a new one. The dynamic code is ~20 lines, all the individuals classes written out are ~300.

I also didn't want to remove all the variants, but I didn't want to add 15 very similar strategies to the standard tournament -- we already have a number of players that are quite similar, like the gobymajorities and retaliators.

So I don't think there is a great solution, but if we want to say readability takes precedent then I'll go along with that.

Regardless I think it's better no having large static data chunks in the strategy classes themselves, so I would prefer to keep the data loading as is.

@drvinceknight
Copy link
Member Author

The dynamic code is ~20 lines, all the individuals classes written out are ~300.

As I said, I'm not sure it's self evident that that's a good thing.

So I don't think there is a great solution, but if we want to say readability takes precedent then I'll go along with that.

Yes my vote goes to readability. It would be a minor refactor to handle all this with inheritance which would appease your previous concern (and keep in line with the rest of the library with other such cases).

Regardless I think it's better no having large static data chunks in the strategy classes themselves, so I would prefer to keep the data loading as is.

I would personally suggest keeping things in one spot where it's not tedious to do is better with the argument of removing complexity (I went on a bit of a merrygoround ride when working on this).

I've just pushed removing the various ones that were not added to the list, so only have 2_2_2 and 1_1_1. I have removed the data loading for this case as it was in essence there for reading two short strings which felt silly.

@drvinceknight
Copy link
Member Author

drvinceknight commented Feb 5, 2017

09daa29 refactors the code a bit more so that it makes use of inheritance.

@drvinceknight
Copy link
Member Author

Regardless I think it's better no having large static data chunks in the strategy classes themselves, so I would prefer to keep the data loading as is.

I've also just pushed some changes that removed unused code (mainly relevant to reading in the two patterns). None of my main changes (including the inheritance) are incompatible with reading in the data if we really want that to stay.



class Winner12(LookerUp):
Copy link
Member

@marcharper marcharper Feb 5, 2017

Choose a reason for hiding this comment

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

I prefer inheriting from LookerUp to reduce the number of inherited classes. It seems odd to me that Winner12 would derive from EvolvedLookerUp1_1_1 (same for the others that derive from it).

Perhaps we can assume that the lookup table is specified by a pattern.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've gone with an intermediate class. Let me know what you think.

@@ -1,19 +0,0 @@
# Name (string), plays (int), opp_plays(int), starting_plays(int), pattern (str)
Copy link
Member

Choose a reason for hiding this comment

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

Can we find somewhere else to save this data? (the evolver repository, perhaps)

Copy link
Member Author

Choose a reason for hiding this comment

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

A 1_1_1 Lookerup trained with an evolutionary algorithm.

Names:
- Evolved Lookerup 1 1 1: Original name by Marc Harper
Copy link
Member

Choose a reason for hiding this comment

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

The names are inconsistent -- let's pick underscores or no underscores.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍

@marcharper
Copy link
Member

I think kwarg arguments for the pattern make more sense then the intermediate class having member variables. If I wanted to instantiate a new lookerup (say a 4, 4, 2) I have to make a derived classed; with arguments I could just use the existing abstract base class.

Otherwise I'm happy with the PR.

@drvinceknight
Copy link
Member Author

I think kwarg arguments for the pattern make more sense then the intermediate class having member variables. If I wanted to instantiate a new lookerup (say a 4, 4, 2) I have to make a derived classed; with arguments I could just use the existing abstract base class.

I'm not sure I understand. Are you talking about using kwargs in the init method?

@drvinceknight
Copy link
Member Author

I'm not sure I understand. Are you talking about using kwargs in the init method?

I might have it, just working on a commit now :)

@drvinceknight
Copy link
Member Author

Let me know if e7b02d6 is what you had in mind.

@marcharper
Copy link
Member

Thanks, that's what I wanted :) I approved the changes, looks like we need a rebase and then we're good.

@drvinceknight
Copy link
Member Author

Thanks, that's what I wanted :) I approved the changes, looks like we need a rebase and then we're good.

Cool, just pushed that :) I also added another test for the pattern init.

@marcharper
Copy link
Member

@drvinceknight can you rebase/merge?

@drvinceknight
Copy link
Member Author

@drvinceknight can you rebase/merge?

Just seen this :) Will have dinner and do it after.

@drvinceknight
Copy link
Member Author

@drvinceknight can you rebase/merge?

Done. 👍

@meatballs meatballs merged commit c2dba09 into master Feb 10, 2017
@meatballs meatballs deleted the 845 branch February 10, 2017 09:32
This was referenced Feb 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants