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

#884 lookerup and gambler #966

Merged
merged 14 commits into from
Apr 16, 2017

Conversation

eric-s-s
Copy link
Contributor

@eric-s-s eric-s-s commented Apr 8, 2017

#884

I did a rather involved re-write of the re-write to Lookerup.

  1. made keys to LookupTable a namedtuple, ActionKeys (could probably use a renaming)
  2. moved a lot of functionality to new object LookupTable
  3. made create_lookup_table_keys follow API
  4. changed the "paramaters" parameter to require an ActionKeys and not a tuple.
  5. refactored init and created helper functions for readablitiy
  6. made a new function called lookup_table_display() to easily visualize information while writing tests.
  1. ActionKeys.:
    The keys to the lookup table are now the namedtuple, ActionKeys(self_plays, op_plays, op_openings). This will solve problems when moving to Actions(Enum) and even if the move never happens, removes reliance on knowledge of the value of Actions.C, Actions.D

  2. LookupTable class:
    All the functionality for creating a lookup table and getting information from it really was a class different from dictionary. This simplifies a lot of LookerUp init, error checking and strategy. It is also an immutable object (unless you want to muck around in private variables, but that's not my problem).

  3. create_lookup_keys and API:
    Every piece of API, uses (self_plays, op_plays, op_openings), but the original lookup_table keys used (op_openings, self_plays, op_plays). Having functions and inputs that relied on a different ordering for keys made this confusing. So i rewrote ActionKeys, LookupTable and create_lookup_keys to follow the API of everything else, which seemed like a more intuitive way to input information anyways. The nice advantage of a namedtuple and LookupTable obj is that this will now be easy to change, willynilly in the future.

  4. Old data (in case you were wondering what happened to "3" above):
    Once I changed how lookup_table keys were made, I had to change the order of all the set patterns. The original patterns are all hard-coded tested for in the tests. They are currently still in comment lines for ease of undoing the change that I did (and I have the original .csv file saved for easy reversal). Since create_action_keys has the same change, any newly created patterns from the axelrod dojo should work with the new API just fine.

  5. The "parameters" parameter:
    I changed "parameters" to using an ActionKeys instead of a tuple. This forces the explicit naming of each action. since ActionKeys is still treated as a tuple, old code using a tuple CAN be passed in without breaking anything (mypy should complain, but the code will still run)

  6. refactored init:
    the init function has a LOT of different things that needed to happen. It required a lot of comments, and took a while to read, and get the gist of everything it was doing. So i took all that functionality and made it pirvate helper functions. This helped expose some situations where bugs could crop up. Each of these helper functions is explicitly tested for, now. This, hopefully, made the init function easier to read.

  7. lookup_table_display():
    Using a named tuple of tuples for the lookup_table makes the repr hopelessly messy to read (but easy to change). i gathered that the point of changing the order of the inputs (see pt 2) was to make it easy to look up the next action on the lookup table. so i wrote this to make writing my tests easier. I then cleaned it up and wrote tests for it. And now moved it into LookupTable where it belongs. Even if the ActionKeys is renamed or re-ordered, the repr of a LookupTable.dictionary is now hopelessly noisy. the horrible dictionary repr. and the display functionSo this was written to address that disadvantage.

NOTE: lookup_table_display() relies on being able to sort actions. This could be an issue or it might be worthwhile anyways to create Actions.C < Actions.D

I hope these changes improve readability and readiness for change.

@eric-s-s
Copy link
Contributor Author

eric-s-s commented Apr 8, 2017

you all might want to wait a day before looking at this. it occurs to me that this is slightly messy because LookupTable is most definitely a class by itself. i will push up some changes withing 24hrs.

@drvinceknight
Copy link
Member

This has some implications in other places. For example https://github.com/Axelrod-Python/axelrod-dojo has some code that trains strategies so that would need to be adjusted.

Am I correct that the main motivation for this is the potential move to a ("real") class for actions?

i will push up some changes withing 24hrs.

Will wait to review properly :) 👍

@eric-s-s
Copy link
Contributor Author

eric-s-s commented Apr 8, 2017

@drvinceknight thanks. good to know about the dojo. at a glance, it seems that this shouldn't affect that too much. it will create the keys in a different order now, but it will create the correct output (just in the new order). i was going to put "create_lookup_table_keys" inside the LookupTable class, but now see why i shouldn't.

@eric-s-s
Copy link
Contributor Author

eric-s-s commented Apr 8, 2017

edited the opening description to reflect the changes i just wrote.

@drvinceknight

Am I correct that the main motivation for this is the potential move to a ("real") class for actions?

That was a big part of the motivation. I also wanted to make this more ready for change of any kind. with the extra classes, different functionality is hidden from different parts and future changes should be easier.

and then, of course, i enjoy sussing out the hidden structure in something to find what it's trying to say. and writing the tests to show that. i teach one of my students some programming for fun, and i'm probably one of the few people to ever utter the sentence, "Today, I'm going to show you something really cool, unit tests!"

@marcharper
Copy link
Member

On a quick look this all looks fine in principle. Since we don't comprehensively test the patterns I'd like to see a full tournament run on this PR for a sanity check comparison on the pattern translation.

The dojo should be fine but the saved patterns from our previous runs won't be valid anymore. (Not a big deal IMO.)

@drvinceknight
Copy link
Member

On a quick look this all looks fine in principle. Since we don't comprehensively test the patterns I'd like to see a full tournament run on this PR for a sanity check comparison on the pattern translation.

Would you be able to do this @eric-s-s or would you like one of us to do it?

Here is the code with the tournament: https://github.com/Axelrod-Python/tournament but I'm happy to grab this branch and run a tournament on our University cluster tomorrow.

The dojo should be fine but the saved patterns from our previous runs won't be valid anymore. (Not a big deal IMO.)

I'm happy with this if you are @marcharper 👍

@eric-s-s
Copy link
Contributor Author

@drvinceknight thank you for that offer. I would very much appreciate you running this on your university cluster. A single repetition of each took about 12 minutes on the family computer. This means about 20hrs of whirring CPU fan that would drive me up the wall (it's a loud fan.)

@drvinceknight
Copy link
Member

drvinceknight commented Apr 10, 2017

I would very much appreciate you running this on your university cluster.

I'll get that running later today 👍

In the meantime here are two Ashlock fingerprints for EvolvedLookerUp_2_2_2:

download

download 1

Looks good to me (but will grab the full tournament run too).

@marcharper
Copy link
Member

Is there a standard difference measure for the fingerprints? maybe mean squared difference on the pixel values?

@drvinceknight
Copy link
Member

Is there a standard difference measure for the fingerprints? maybe mean squared difference on the pixel values?

We have the underlying data in the fingerprint class so yeah, we can just compare those. I'll do that and post back here later. 👍

@eric-s-s
Copy link
Contributor Author

@drvinceknight that fingerprint module is pretty cool. i noticed some stuff as i was reading through. any objections to my taking a crack at some refactoring?

@drvinceknight
Copy link
Member

i noticed some stuff as i was reading through. any objections to my taking a crack at some refactoring?

No objections, if it can be cleared up/improved that's always good. Feel free to open an issue if you're thinking of big changes in case it's worth discussing before you spend a lot of time on things.

@drvinceknight
Copy link
Member

Sorry for taking a while to get this done but I've run the following on both master and this branch:

import axelrod as axl
import csv

def write_data_to_file(fp, filename):
    """
    Write the fingerprint data to a file.
    """
    columns = ['x', 'y', 'score']

    with open(filename, 'w') as f:
        w = csv.writer(f)
        w.writerow(columns)
        for key, value in fp.data.items():
            w.writerow([key.x, key.y, value])

lookerups = [axl.EvolvedLookerUp1_1_1, axl.EvolvedLookerUp2_2_2, 
             axl.Winner12, axl.Winner21]

axl.seed(0)
for lookerup in lookerups:
    af = axl.AshlockFingerprint(strategy=lookerup)
    _ = af.fingerprint()
    write_data_to_file(fp=af, filename="{}.csv".format(lookerup))

that generated the data available in the following tar file:

Comparing Lookerups.tar.gz

I then ran:

def make_dict(filename):
    """Make a dictionary from a data file"""

    with open(filename, "r") as f:
        reader = csv.reader(f)
        return {(x, y): score for x, y, score in reader}  

for lookerup in lookerups:
    fingerprint_on_master = make_dict("master/{}.csv".format(lookerup))
    fingerprint_on_884 = make_dict("884/{}.csv".format(lookerup))
    print(fingerprint_on_master == fingerprint_on_884)

The output is:

True
True
True
True

So I think we're ok to merge this in.

@drvinceknight
Copy link
Member

So I think we're ok to merge this in.

If perhaps someone else could run the above to confirm (because of the branch change there's a manual step that I could have messed up). It doesn't take long.

@eric-s-s
Copy link
Contributor Author

@drvinceknight i'll do those tests today.

@eric-s-s
Copy link
Contributor Author

eric-s-s commented Apr 12, 2017

i've confirmed your fingerprint results, and i also included all the PSOGambler classes. they checked out too.

@drvinceknight
Copy link
Member

On a quick look this all looks fine in principle. Since we don't comprehensively test the patterns I'd like to see a full tournament run on this PR for a sanity check comparison on the pattern translation.

Great. I think this is good to go @marcharper?

@marcharper
Copy link
Member

How are the dictionaries equal? The plots are slightly different.

@drvinceknight
Copy link
Member

drvinceknight commented Apr 13, 2017 via email

parameters=Plays(self_plays=player_depth: int,
op_plays=op_depth: int,
op_openings=op_openings_depth: int).
| LookerUp can also be instantiated with pattern=str/tuple of actions, and
Copy link
Member

Choose a reason for hiding this comment

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

What's the pipe for here?

Copy link
Contributor Author

@eric-s-s eric-s-s Apr 13, 2017

Choose a reason for hiding this comment

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

what is a pipe? you mean like in bash?

the docstrings use rst notation, correct? I thought it would be useful to preserve the line-breaks there. so i used the rst "| " notation. without the "hey rst! preserve linebreaks"-notation, it threw an error with one of the auto checks for having naughty indentation. should i change to "::" notation?

while i think of it, can i go ahead and delete all the commented-out original data?

Copy link
Member

Choose a reason for hiding this comment

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

I hadn't seen the | in rst before. I'm not sure it looks like it should though. Here's what the docs build looks like on this branch:

screenshot from 2017-04-13 09-46-20

Is that what you were going for?

This tweak:

  235                                                                                                                                                 
~ 236     LookerUp can also be instantiated with :code:`pattern=str/tuple` of actions                                                                 
~ 237     , and::                                                                                                                                     
~ 238                                                                                                                                                 
~ 239         parameters=Plays(                                                                                                                       
~ 240             self_plays=player_depth: int,                                                                                                       
+ 241             op_plays=op_depth: int,                                                                                                             
+ 242             op_openings=op_openings_depth: int).                                                                                                
  243                                                                                                                                                 
  244     It will create keys of len=2 ** (sum(parameters)) and map the pattern to                                                                    
  245     the keys.   

looks like:

screenshot from 2017-04-13 09-50-35

while i think of it, can i go ahead and delete all the commented-out original data?

Sounds good to me. 👍

@drvinceknight
Copy link
Member

Here are the plots with the same seed:

This branch:

884

Current master:

master

@meatballs
Copy link
Member

If perhaps someone else could run the above to confirm (because of the branch change there's a manual step that I could have messed up). It doesn't take long.

I've repeated this and can confirm the result

Copy link
Member

@drvinceknight drvinceknight left a comment

Choose a reason for hiding this comment

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

I think we're all happy? Marking this as good to go. :) Thanks @eric-s-s!

@eric-s-s
Copy link
Contributor Author

eric-s-s commented Apr 14, 2017

@drvinceknight

Thanks @eric-s-s!

:)

@meatballs meatballs merged commit 263a60f into Axelrod-Python:master Apr 16, 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

4 participants