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

Import Fortran Strategies #381

Closed
marcharper opened this issue Oct 23, 2015 · 16 comments
Closed

Import Fortran Strategies #381

marcharper opened this issue Oct 23, 2015 · 16 comments

Comments

@marcharper
Copy link
Member

Given the original Axelrod tournament #2 source code, we should be able to wrap the Fortran using numpy. This would net the 64 strategies from that tournament as is.

To proceed we'll need to (at least):

  • Figure out the numpy interface for pulling in Fortran
  • Map the generated functions to strategy names
  • Create a wrapper or subclass of Player that sends the right information to the Fortran subroutines. The function signature is: FUNCTION K49R(J,M,K,L,R, JA) where
J = JB: opponent's previous play
M = Move: Round number
K = RowGameSc: player's score (cumulative)
L = ColGameSc: opponent's score (cumulative)
R = a RandomNumber (in [0,1])
JA: player's previous play

This is different than what we give players now (the full history, we don't track the cumulative score, etc.)

  • Create tests and check for clashes with already implemented strategies from the list of 64
@langner
Copy link
Member

langner commented Oct 27, 2015

Why not just implement the remaining strategies in Python?

@marcharper
Copy link
Member Author

They range from easily translatable to borderline unintelligible. The lack of comments also makes it difficult to know if we've implemented them correctly.

@meatballs
Copy link
Member

meatballs commented Jul 21, 2017

An extra complication is that all internal variables in the Fortran functions maintain their state between invocations.

This was handled orginally using "a. the -SAVEALL option must be used in the Language Systems Fortran compiler to make the local variables in the rule functions static (ie remembers from one call to the next)."

It's done now within gfortran by passing the -fno-automatic flag to the compiler.

I can't find any material to describe how numpy handles that requirement. My suspicion is that it doesn't.

@drvinceknight
Copy link
Member

My current line of thought is that I'd prefer us not to automatically load in the Fortran code:

  1. Readability. A big strength of the library is that we've tried to emphasise readability of the strategies. Someone new to Python but wanting to use the library and potentially understand it would have to pick up Python and potentially Fortran.
  2. Testability. This is somewhat linked but every strategy is specifically tested and that also a strength. We would need to write tests for each individual strategy if there were to be added in.

I think it's brilliant to have them and have them working but I feel that we should use them to write the corresponding Python/Axelrod class.

One potential option would be to write some sort of wrapper in another library that did translate them AS IS to Python classes that can be used in axelrod with the "disclaimer" that that's what that's doing.

So for example a user could run:

$ pip install axelrod
$ pip install axelrod-fortran

and then:

>>> import axelrod as axl
>>> import axelrod-fortran as axlf
>>> players = [s() for s in axelrod.strategies] + [s() for s in axlf.strategies]
>>> tournament = axl.Tournament(players)

That way we're still claiming that everything in the Axelrod library is written to a high quality and completely tested.

We would theoretically, slowly slowly translate the strategies in axelrod-fortran (or whatever the appropriate name for that is) to Python and potentially no longer have the need for it.

@meatballs
Copy link
Member

I agree with the thoughts above. I'm also not entirely convinced the import is possible because of the issue with persistence of state. (Although that may just be that I haven't yet found how to cope with that).

@marcharper
Copy link
Member Author

I would be in favor of automatic loading (so we have them, or at the user's discretion), translating each to python implementations with sufficient test coverage.

For the state retention issue, could we reload in the reset method?

@drvinceknight
Copy link
Member

sufficient test coverage.

Testing them is one thing, readability and cohesiveness is the other.

at the user's discretion

Would the suggestion of an optional library be ok for this? (Like my suggestion for pip install axelrod-fortran or perhaps axelrod-extra or something like that).

@marcharper
Copy link
Member Author

Would the suggestion of an optional library be ok for this? (Like my suggestion for pip install axelrod-fortran or perhaps axelrod-extra or something like that).

Yes. Do we know if it's even possible to import the Fortran yet?

@meatballs
Copy link
Member

meatballs commented Jul 22, 2017

A little further research:

https://docs.scipy.org/doc/numpy-1.10.1/user/c-info.python-as-glue.html
Talks about there being two methods for consideration: writing extension modules or using the ctypes module.

Extension modules is the method f2py (and now, numpy) uses.

There is some guidance at http://www.fortran90.org/src/best-practices.html#interfacing-with-python for using the ctypes module with Fortran.

Essentially, the extension module approach works with the fortran code directly, whilst the ctypes approach works with the compiled object files.

I don't know how we would handle the state persistence issue using extension modules. It's not clear to me how the compilation stage is handled and how, therefore, I would pass the instruction to keep function variable values between invocations.

My gut feel is that the ctypes approach is the way to go. That way, I can control the compilation of the Fortran code into object files and pass the necessary flag.

@meatballs
Copy link
Member

meatballs commented Jul 22, 2017

So, my thoughts at the moment are to compile the strategy functions that we wish to import into a single shared object file which is then called from within Python using the ctypes module.

As we translate strategies into Python properly, we remove them from the list of those we compile.

Update

And, yes, I think that the suggestion by @drvinceknight to use a separate axelrod-fortran library to do this is the way to go.

@meatballs
Copy link
Member

meatballs commented Jul 22, 2017

Side Note:

Whilst some (many?) of the Fortran strategies are indecipherable, that doesn't mean we can't translate them to Python - we could just do a 'literal' translation line by line.

We'd end up with the most un-pythonic Python code you've ever seen, but it would work.

Writing tests would be almost impossible, because we'd still have little idea of the intention behind the strategy. However, if my idea of using a shared object file and the ctypes module works, it gives us the possibility of at least writing tests to assert that the translated Python strategy behaves in the same way as the original Fortran.

@meatballs
Copy link
Member

Further research:

https://docs.scipy.org/doc/numpy-dev/f2py/usage.html#command-f2py shows that f2py has options to pass flags to the compiler:

--f77flags=

Specify F77 compiler flags

--f90flags=

Specify F90 compiler flags

So, both f2py (numpy) and ctypes look like viable options

@drvinceknight
Copy link
Member

This all sounds great to me. I also understand very little about it though :)

And, yes, I think that the suggestion by @drvinceknight to use a separate axelrod-fortran library to do this is the way to go.

👍

It'll be awesome to have these run if indeed it's possible to do so. Potentially a paper in itself just about reviving the code and running the tournament :)

@marcharper
Copy link
Member Author

Whilst some (many?) of the Fortran strategies are indecipherable, that doesn't mean we can't translate them to Python - we could just do a 'literal' translation line by line.
We'd end up with the most un-pythonic Python code you've ever seen, but it would work.

I think you'd find this difficult, what with all the implicit GOTOs in the compound if statements.

It'll be awesome to have these run if indeed it's possible to do so. Potentially a paper in itself just about reviving the code and running the tournament :)

Indeed! And we can add our ML-strategies to the mix for a nice validity test (since they've never seen most of the original tournament strategies).

@meatballs
Copy link
Member

Can I be so bold as to suggest we can now close this one?!!!

@drvinceknight
Copy link
Member

Yeah I think this can be closed. I'll add a comment to #379 and then we can open up specific individual issues for translating specific strategies 👍

Great work @meatballs!

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

No branches or pull requests

4 participants