sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.41k stars 475 forks source link

Game Theory: Build capacity to solve matching games in to Sage. #16331

Closed drvinceknight closed 9 years ago

drvinceknight commented 10 years ago

Include class for matching games as well as implementations of the Gale-Shapley algorithm.

Should be efficient to code in pure python/cython. Various methods to include possibility to give suitor/reviewer optimal matchings. Also, make use of graph plotting to represent game.

Possible extensions could include variations of matching games (indifference etc...).

Component: game theory

Keywords: Matching Games

Author: Vince Knight, James Campbell

Branch/Commit: f9388c7

Reviewer: Karl-Dieter Crisman, Travis Scrimshaw

Issue created by migration from https://trac.sagemath.org/ticket/16331

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 31fc554 to e9edce6

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

0c19d87Added another doc test to the player class
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from e9edce6 to 0c19d87

drvinceknight commented 10 years ago
comment:49

Replying to @kcrisman:

Comments I could reconstruct:

  • Should it be a game of 2n players or size n? Is there a standard terminology?
  • Since the matching $M$ is bijective and the algorithm is not symmetric, should the solution really have each match twice?
        sage: m.solve()
        {'A': ['J'],
         'C': ['K'],
         'B': ['M'],
         'D': ['L'],
         'K': ['C'],
         'J': ['A'],
         'M': ['B'],
         'L': ['D']}

maybe instead

        sage: m.solve()
        {'A': ['J'],
         'C': ['K'],
         'B': ['M'],
         'D': ['L'],

and then it will be easy to tell if it's inverted...

I have made this change but this has been done in conjunction with other changes: in particular _sol_dict_ is now an attribute that includes the same dictionary as before (so that it can be used for the bi-partite graph method for example) but solve only returns the required output (as you suggest).

  • _repr_ really shouldn't have it possible to have something other than $2n$. I'm not asking to check the _is_complete at that point, but at least they should be same number can be checked.
  • latex - I'm not sure this is standard notation. 4=\{(1, 0)\} equals sign?

These both have been fixed.

  • in game_to_dict I just don't know whether one should have "undicted" the game in the first place. It seems like a lot of trouble to redictify the game. Maybe the data should be stored differently in any event. Constructing a whole _Player for each player seems like a lot of overhead. They have no external existence.

The only reason to undict the game is because the players are not passed to the instance so no dictionary with player instances as keys was constructed until the game_to_dict method was called. This has now been changed: upon initialisation the input dictionaries are used to create new dictionaries with player instances as keys.

The reason for keeping the player instance is that it allows for an easier and more readable coding of the algorithm itself (so I'm quite keen to keep it).

  • Is it possible for someone to access all the partners and pref and such in such a way as to mess with _is_solved? It just seems odd that those things might be directly accessible.

I actually think this is worth keeping as it could be possible that someone would want to access and change partners (I can't think of why but I can imagine that it would be a shame to take that possibility away).

  • I think another word than 'complete' is needed in checking completeness, because if {3: (0, 2, 1) was changed to {3: (0, 2) it would still raise the error but seem "complete" in some sense...

I'm not sure I actually understand this one. {3:(0,2) would not be complete as 2 is not a valid player? Maybe I'm missing something. Very happy to change vocabulary.

  • What if the automatically added suitor name is already in use? (Say, we already have names 3, 'Fred' and now want to automatically add a third one.) I don't know the right answer here.

I have added an error for this.

  • Any rationale for the autoprefs?

Not really... Do you think they should be something else?

  • I wonder if sol_dict should be an attribute and not a method. Especially since you're not really supposed to access it publicly.

Completely agree: done, see earlier comment re solve.

  • And of course, if you REALLY want to use the _Player class, needs doctests :)

I think this has been done. Note that I need to import the _Player class in the tests themselves: I hope that's ok.

Thanks again for being so thorough: very much appreciated.

kcrisman commented 10 years ago
comment:50

Thanks for these changes.

I have made this change but this has been done in conjunction with other changes: in particular _sol_dict_ is now an attribute that includes the same dictionary as before (so that it can be used for the bi-partite graph method for example) but solve only returns the required output (as you suggest).

I'm glad we agree this is a somewhat better solution, and I think it simplifies the code in the long run as well.

  • I think another word than 'complete' is needed in checking completeness, because if {3: (0, 2, 1) was changed to {3: (0, 2) it would still raise the error but seem "complete" in some sense...

I'm not sure I actually understand this one. {3:(0,2) would not be complete as 2 is not a valid player? Maybe I'm missing something. Very happy to change vocabulary.

My point is that "(0,2,1)" is sort of "overcomplete", too many prefs, while "(0,2)" has the "right" number but the wrong guys. But I don't know what the standard vocabulary is here, that was my main point.

  • Any rationale for the autoprefs?

Not really... Do you think they should be something else?

I think that at least they should be explained clearly so people know how to use them.

  • And of course, if you REALLY want to use the _Player class, needs doctests :)

I think this has been done. Note that I need to import the _Player class in the tests themselves: I hope that's ok.

Yes, that is standard practice in such cases.

Thanks again for being so thorough: very much appreciated.

Not at all.

kcrisman commented 10 years ago
comment:51

I'm still not exactly sure what commit 0a8aea0 is doing and there is still all this gambit stuff in the commits I see... it would be really good to base only the changes for this ticket on whatever the latest beta is (which should already have cooperative games in it, right?) so that it's very obvious what is changing. But maybe that's not possible.

kcrisman commented 10 years ago
comment:52

I'm still not exactly sure what commit 0a8aea0 is doing and there is still all this gambit stuff in the commits I see... it would be really

Oh, I see, there is src/sage/gametheory and src/sage/game_theory. Ugh.

kcrisman commented 10 years ago
comment:53
  • Any rationale for the autoprefs?

Not really... Do you think they should be something else?

I think that at least they should be explained clearly so people know how to use them.

In fact, I can't really figure them out! I guess instead of a tuple/list you just have a bunch of the number -1? (Which isn't even a player?) That does seem confusing. Why bother? It really does confuse me. If people have to populate it anyway...

  • And of course, if you REALLY want to use the _Player class, needs doctests :)

I think this has been done. Note that I need to import the _Player class in the tests themselves: I hope that's ok.

Ahem. __repr__ and __eq__ still are missing doctests, as is the solve method. Naturally, they don't have to be very exciting - do an edge case or copy one from elsewhere. Ideally, they'd be slightly different or test some unusual case (e.g. empty game).

kcrisman commented 10 years ago
comment:54

Another possible (minor) point:

while len([s for s in suitors if s.partner is False]) != 0:

maybe it would be easier to use not any() for that instead of doing a couple comparisons?

kcrisman commented 10 years ago
comment:55

On the plus side, the algorithm is right, as expected!

drvinceknight commented 10 years ago
comment:56

Thanks for all this Karl. I'm getting going on them now!

tscrim commented 10 years ago
comment:57

Replying to @kcrisman:

Another possible (minor) point:

while len([s for s in suitors if s.partner is False]) != 0:

maybe it would be easier to use not any() for that instead of doing a couple comparisons?

Or an all(). This or not any() will be faster to fail because it will short circuit out, whereas building the list (which takes time too) will do the full iteration over all suitors.

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

c0663e1Using any statement instead of length test in algorithm
f48a36eHave added doctests to eq, repr and solve
ceb3802Got rid of -1 auto preferences in new players
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 0c19d87 to ceb3802

drvinceknight commented 10 years ago
comment:59

Thanks both, I've made the following changes:

With regards to is_complete, I don't think there's any standard term (as it simply isn't well defined). This leads me to suggest is_well_defined or is_coherent. I personally prefer is_well_defined. Does that sound ok?

tscrim commented 10 years ago
comment:60

Some notes on the recent commits. Please remove the list brackets in the all statement so it doesn't build the full list, so:

while not all(s.partner for s in suitors):

Note in these timings, there is a failure at the first entry:

sage: L = range(10000)
sage: %timeit all([x for x in L])
1000 loops, best of 3: 758 µs per loop
sage: %timeit all(x for x in L)
100000 loops, best of 3: 3.02 µs per loop

The added doctests are formatted wrong. The tests themselves need one more level of indentation and it shoulds be TESTS:: (mainly 2 colons).

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from ceb3802 to 7eaff65

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

7eaff65Removing brackets for any and indenting docs
drvinceknight commented 10 years ago
comment:62

Replying to @tscrim:

Some notes on the recent commits. Please remove the list brackets in the all statement so it doesn't build the full list, so:

while not all(s.partner for s in suitors):

Note in these timings, there is a failure at the first entry:

sage: L = range(10000)
sage: %timeit all([x for x in L])
1000 loops, best of 3: 758 µs per loop
sage: %timeit all(x for x in L)
100000 loops, best of 3: 3.02 µs per loop

Learn something new every day: thanks. Have updated.

The added doctests are formatted wrong. The tests themselves need one more level of indentation and it shoulds be TESTS:: (mainly 2 colons).

Have made your suggested modifications. Seem to be having issues building the docs though (this seems to be temperamental so might be something locally for me so going to go take a look at that now).

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 7eaff65 to f07b29f

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

f07b29fDocs now build
tscrim commented 10 years ago
comment:64

You should revert the last change and instead remove the second colon from the EXAMPLES:: since 2 colons tells sphinx to go into code/literal format. So things are like:

EXAMPLES::

    sage: into_doctests_directly()

Some text::

    sage: more_doctests()

or

EXAMPLES:

Some explanation::

    sage: a_doctest()

Some more details::

    sage: another_test()
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from f07b29f to cf09cbb

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

cf09cbbdocs now build properly
drvinceknight commented 10 years ago
comment:66

Replying to @tscrim:

You should revert the last change and instead remove the second colon from the EXAMPLES:: since 2 colons tells sphinx to go into code/literal format. So things are like:

EXAMPLES::

    sage: into_doctests_directly()

Some text::

    sage: more_doctests()

or

EXAMPLES:

Some explanation::

    sage: a_doctest()

Some more details::

    sage: another_test()

Thanks Travis, that explanation is super appreciated, after reverting and changing I had to push -f hopefully that hasn't broken absolutely everything git wise...

tscrim commented 10 years ago
comment:67

Here's some more things that come from a more detailed look:

-``name`` - Can be a string or a number. If left blank will automatically
            generate an integer.

should be

- ``name`` -- a string or a number; if left blank will automatically
  generate an integer

Note the punctuation, spacing, and alignment. Also change : :: into :: (this was noted by Karl on another ticket I believe).

I'll take another look once all of this is done.

A category-type question: Does it make sense to talk about the set of all games on a fixed set of players? If so, is there some notion of a morphism? I did some searching and came across this article describing a category for a particular class of games. So perhaps (on a future ticket) we reorganize everything into using the category framework. This is more food for thought.

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

c0cea94deleting gametheory folder
4a2ac20moved _dict_game to `__init__` to make testing more straightforward
fc036e9Removing junk line from init.py
9b90c52renaming bi_partite to bipartite
b4a7a6fMaking Player object a SageObject
ded192dTweak of doc formatting
fe75fa6Tweak of doc formatting
22469f5fixed : :: issue
47c7d0aChanging short doc descriptions to affirmative
197c9aeChanging _Player to Player
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from cf09cbb to 197c9ae

drvinceknight commented 10 years ago
comment:69

Replying to @tscrim:

Here's some more things that come from a more detailed look:

  • You've created another folder for the game theory called gametheory whereas the existing folder game_theory should be used (also it is the better name IMO).

That shouldn't be there: have deleted.

  • Is gambit (#16466) necessary for this ticket?

No, this has nothing to do with #16466, is it looking like it does?

  • Never have mutable attributes public (with no leading underscore _, ex. suitors and reviewers). It's also good practice to not expose internal-use attributes.

I mentioned to Karl that at times it might be nice to be able to access these. Kind of like in lines 147 onwards of the docs: sage: from itertools import permutations .... Happy to remove if you guys don't think that's a good idea.

  • Bipartite is one word, so change bi_partite to bipartite.

Easy fix: done.

  • _dict_game doesn't have a doctest.

Testing this was rather tricky as it was 'just something' that works in __init__ so I've moved it to __init__ which makes it easier to doc-test (I added another doc test there).

  • For the __eq__ method of _Player, I think you're better comparing name. In particular, this would guarantee hash correctness (if x == y, then we must have hash(x) == hash(y)).

By using .__repr__() this allows us to test equality not only against another player instance but also against a name of player which is the values in the dictionaries... Changing this would require a re-write of the dictionary that holds the preferences... This isn't necessarily impossible but just checking if it's really necessary?

  • Remove the leading underscore of _Player so it gets included in the doc (at least, I think it won't get included as is), and it's the proper convention for classes. See the following note too.

Done, although just confirming that we want Player to appear in the docs? This is only meant to be used internally really.

  • In the all.py, it's not good practice to import everything in a particular module (file) as it makes it harder to import things into the global namespace.

This shouldn't be there. Maybe it was in gametheory...

  • In the __init__.py, you don't need to import all (usually these files are left blank).

Done.

  • Make _Player inherit from object since new-style classes are recommended by python (or at least remove those parentheses). Same for Coop_Game.

Coop_Game must have been in gametheory, have made _Player inherit from SageObject.

  • Rename Coop_Game to CoopGame; the latter is the proper naming convention for classes.

Coop_Game doesn't exist (anymore). (Or shouldn't if it does).

  • Actually, more generally in your code you've mixed the python conventions: classes follow CamelCase and functions/attributes/variables use underscore_names.

I believe to have caught these now.

  • cooperativegames.py (which probably should be renamed as cooperative_games.py for easier reading) is lacking doctests. Actually, is this redundant from game_theory/cooperative_game.py?

Yes it's redundant (have removed gametheory). Sorry...

  • Doc formatting:
-``name`` - Can be a string or a number. If left blank will automatically
            generate an integer.

should be

- ``name`` -- a string or a number; if left blank will automatically
  generate an integer

Done.

Note the punctuation, spacing, and alignment. Also change : :: into :: (this was noted by Karl on another ticket I believe).

Done.

  • More on the docs, please make the short description into the affirmative (I think this is the right word). So Raises to Raise, Constructs to Construct, etc. It's a python convention.

I think I've caught all these.

I'll take another look once all of this is done.

A category-type question: Does it make sense to talk about the set of all games on a fixed set of players? If so, is there some notion of a morphism? I did some searching and came across this article describing a category for a particular class of games. So perhaps (on a future ticket) we reorganize everything into using the category framework. This is more food for thought.

Great question, probably not enough in my area of expertise to be able answer straight away but will think about it.

tscrim commented 10 years ago
comment:70

I asked about the gambit stuff because the spkg data is a part of the branch.

For the __eq__ of Player, I would rewrite this as

if isinstance(other, Player):
    return self.name == other.name
return self.name == other

This is faster in general if name is some "horrible" object with a (relatively) hard to compute repr but easy equality testing (most Sage parents fall into this category due to EqualityById). It should be on the same order of speed and is less fragile (I believe there are objects in Sage with the same string repr but different hashes).

The import all was in gametheory (although it is in the game_theory/__init__.py because I didn't check there when looking at the initial ticket).

It's probably overkill to have Player inherit from SageObject; just the python object should be sufficient.

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

d99b5a5Fixed eq to not use repr
126315eMaking player inherit from python object
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 197c9ae to 126315e

drvinceknight commented 10 years ago
comment:72

Replying to @tscrim:

I asked about the gambit stuff because the spkg data is a part of the branch.

Oh no... Does this create a mess? Is the easiest thing for me to do to branch from develop and simply include the code?

For the __eq__ of Player, I would rewrite this as

if isinstance(other, Player):
    return self.name == other.name
return self.name == other

This is faster in general if name is some "horrible" object with a (relatively) hard to compute repr but easy equality testing (most Sage parents fall into this category due to EqualityById). It should be on the same order of speed and is less fragile (I believe there are objects in Sage with the same string repr but different hashes).

This is done now, it looks much nicer as well.

The import all was in gametheory (although it is in the game_theory/__init__.py because I didn't check there when looking at the initial ticket).

I don't believe it's in game_theory/__init__.py anymore...

It's probably overkill to have Player inherit from SageObject; just the python object should be sufficient.

Done. Thanks a lot again for taking the time and explaining all this to me. Really appreciated.

drvinceknight commented 10 years ago
comment:73

Replying to @drvinceknight:

Replying to @tscrim:

I asked about the gambit stuff because the spkg data is a part of the branch.

Oh no... Does this create a mess? Is the easiest thing for me to do to branch from develop and simply include the code?

Or can I just find the 'spkg data' (not sure where that is as James was the one who put that together - but I'm sure I can figure it out) and remove it?

tscrim commented 10 years ago
comment:74

I'd just delete them and check (on a new temp branch) that once you merge in #16466, the spkg files are there (which I believe it should be okay from looking at the commit history).

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

aae25ceRemoving spkg files for gambit which should not have been here
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 126315e to aae25ce

drvinceknight commented 10 years ago
comment:76

Replying to @tscrim:

I'd just delete them and check (on a new temp branch) that once you merge in #16466, the spkg files are there (which I believe it should be okay from looking at the commit history).

Cool, thanks, I've deleted the files and pushed. Sadly when I merged #16466 into a temp branch I got some merge conflicts (saying that the files were deleted in one branch).

If things are 'ok' in this branch I'd be tempted to leave it as is and worry about #16466 which we should probably just re-branch from develop? If I'm misunderstanding a future mess that might appear please let me know and I can just 're-branch' from develop for #16331...

tscrim commented 10 years ago
comment:77

Replying to @drvinceknight:

Replying to @tscrim:

I'd just delete them and check (on a new temp branch) that once you merge in #16466, the spkg files are there (which I believe it should be okay from looking at the commit history).

Cool, thanks, I've deleted the files and pushed. Sadly when I merged #16466 into a temp branch I got some merge conflicts (saying that the files were deleted in one branch).

If things are 'ok' in this branch I'd be tempted to leave it as is and worry about #16466 which we should probably just re-branch from develop? If I'm misunderstanding a future mess that might appear please let me know and I can just 're-branch' from develop for #16331...

Well, at least it doesn't do it silently. So if we forget about it, the merge will remind us (and the conflict is easy enough to handle). I'll make another look-through today.

tscrim commented 10 years ago

Changed commit from aae25ce to 8b106a2

tscrim commented 10 years ago
comment:78

I've made the following reviewer changes:

FYI - I also experimented with removing the Player class, but it didn't sit right with me.

I'm thinking we should rename bipartite to the more explicit bipartite_graph. Do you agree?

Karl, is there anything that you can see that needs to be addressed?


New commits:

600c4dbMerge branch 'u/vinceknight/game_theory__build_capacity_to_solve_matching_games_in_to_sage_' of trac.sagemath.org:sage into public/game_theory/solve_matching_games-16331
f366ff3Formatting and doctest changes. Changed latex output.
6bd64caSome cleanup and making all tests pass.
69c0e61Some more changes and improvements.
8b106a2Reverted change `__repr__` to _repr_.
tscrim commented 10 years ago

Changed branch from u/vinceknight/game_theory__build_capacity_to_solve_matching_games_in_tosage to public/game_theory/solve_matching_games-16331

kcrisman commented 10 years ago
comment:79

Not yet, but I have not had time to try anything in Sage out the last few days (travel). I would definitely like to retain prerogative to try looking at the most recent branch from scratch again, to make sure I didn't miss anything and it works properly, as well as to look at Travis' changes. I might be able to get to that closer to the end of the week. But scanning most of the changes as described in the comments it seems good, other than the idea to put game theory in the category framework - that is really very far away from nearly 100% of game theorists' thoughts, I can assure you, and would be an unneeded step to take at this time.

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Branch pushed to git repo; I updated commit sha1. New commits:

508d819replaced bipartite with bipartite_graph
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 10 years ago

Changed commit from 8b106a2 to 508d819

drvinceknight commented 10 years ago
comment:81

Replying to @tscrim:

I've made the following reviewer changes:

  • Speed/memory improvements to solve.
  • Output of solve doesn't wrap the players in a list.
  • Input to MatchingGame can be 2 arguments.
  • Added __eq__ to MatchingGame so it pickles.
  • Made MatchingGame unhashable because it's mutable.
  • Made attributes of MatchingGame private.
  • Added a suitors() and reviewers() methods which return tuples.
  • Changed input to Player because they were unused.
  • Latex output.
  • Doc formatting.

These all look awesome: thanks!

FYI - I also experimented with removing the Player class, but it didn't sit right with me.

I'm thinking we should rename bipartite to the more explicit bipartite_graph. Do you agree?

I went ahead and changed this as I thought it sounded way better.

Thanks a lot Travis (very much appreciated). Karl, thanks again for finding the time, please let me know if there's anything I can help with (I should be pushing to #16954 hopefully by end of tomorrow if not tonight).

(By the way I am completely confused as to how to push to trac using git push trac...I seem to try a bunch of combinations of HEAD:u/[stuff], some times it doesn't go, sometimes it seems to push to something but who knows where and sometimes it gets here... I've read the docs on this multiple times but that doesn't seem to clarify things for me... Any tips? <- This is probably not a question for trac).

kcrisman commented 10 years ago
comment:82

I can't even see the whole diff now on the branch link. Huh? And the list of commits is not so useful because of the very fine granularity and the many dependencies.

Edit: https://github.com/sagemath/sagetrac-mirror/commits/develop?after=508d8193ea3d99dda90515bced36c8cd8e747224+0&branch=develop&path%5B%5D=src&path%5B%5D=sage&path%5B%5D=game_theory&path%5B%5D=matching_game.py&qualified_name=refs%2Fheads%2Fdevelop seems to work best for this, and then https://github.com/sagemath/sagetrac-mirror/blob/develop/src/sage/game_theory/matching_game.py?h=508d8193ea3d99dda90515bced36c8cd8e747224 for the actual file.

tscrim commented 10 years ago
comment:83

I also get the same thing. However if you want to see the diff, assuming you merged with develop, is to run git diff develop in the branch or git diff develop your/local/name_of_branch in any branch. If you haven't merged with develop, you can replace that with 6.4.beta3 or whatever beta version this is currently based off of (maybe 6.4.beta4?).

In related news, ah crap, I've forgotten about what's left to do on all of the game theory tickets...will need to re-read things...

kcrisman commented 10 years ago
comment:84

In related news, ah crap, I've forgotten about what's left to do on all of the game theory tickets...will need to re-read things...

No, no, I'm on top of it today/next week. Plus, I actually work in this area ;-) You go do some Lie algebras or job applications or thesis or something! Thanks for your definite help on getting this in shape, I've already looked at things and the branch is in pretty good shape, it's just a matter of checking the math and such now, no more crazy branch worries like before.

tscrim commented 10 years ago
comment:85

Replying to @kcrisman:

No, no, I'm on top of it today/next week. Plus, I actually work in this area ;-) You go do some Lie algebras or job applications or thesis or something!

Haha, thanks! I'm doing all of the above in fact (something = teaching).

Thanks for your definite help on getting this in shape, I've already looked at things and the branch is in pretty good shape, it's just a matter of checking the math and such now, no more crazy branch worries like before.

Let me know if there's anything else I can do.