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

Add game tree visiting logic? #15

Open
bkushigian opened this issue Dec 23, 2022 · 4 comments
Open

Add game tree visiting logic? #15

bkushigian opened this issue Dec 23, 2022 · 4 comments

Comments

@bkushigian
Copy link
Contributor

bkushigian commented Dec 23, 2022

There are various reasons why we might want to traverse a game tree after a solve. My present usecase (mentioned in #14) is to build a strategy simplifier by pruning low-utility branches. Another use case would bet to serialize the game tree efficiently (rather than dumping to memory, we could serialize relevant pre-river state), and if mutability was allowed we could even modify trees during a visit.

Would this be something you'd want to support? I'd maybe be willing to take a stab at the implementation though I can't guarantee quality.

Edit: I over-edited the above to the point of being nonsense: I want some isolated logic to make traversing a game tree dead simple, something that does all the traversal logic and lets me hook into the right spots with lamdas or whatever.

@b-inary
Copy link
Owner

b-inary commented Dec 23, 2022

I am not sure I grasp your intent. The game tree can be traversed after solving by calling the play() method of the PostFlopGame struct. The children nodes can also be obtained by the available_actions() method.

It is hard to make the game tree mutable after it is solved. This is because the strategy and EV data are stored in a single global buffer.

Also, although the implementation will probably wait a month or two, there is a plan to implement the ability to save the data without post-river information.

@bkushigian
Copy link
Contributor Author

Yeah, I wrote a traverser and it works but it took some time and the logic was a little subtle. I'm sure I didn't find the nicest implementation, but I guess that's the point: it took me most of the day to build a traverser and I ran into a few dead ends/etc, and I thought it would be a good piece of logic to abstract out.

I'm coming at this from a "I want to perform analyses on game trees" perspective, so I'll be writing lots of traversals and I'll probably be abstracting this logic out anyway. It may be too niche for the main repo, but I think there's some definite value added to have an interface that makes traversals easy.

Here is an example that builds a traverser that identifies low-frequency actions and stores them for removal later.

let removed_lines: Vec
let traverser = GameTreeTraverserFactory::new()
  .breadth_first()                                                 // do a breadth-first traversal
  .with_skip_actions(|action, history| action.frequency() < 0.01)  // skip low-frequency action
  .with_action_processor(                                          // store low-frequency actions
    |action, history| 
      if node.frequency() < 0.01 {
        let mut line = history.clone();
        line.push(action);
        removed_lines.push(line);
      })
  .build();
traverser.traverse();

Obviously the interface would need to be a bit more complicated than this (I'd want to pass a &PostFlopGame reference into the lambdas), but this is the basic idea.

@bkushigian
Copy link
Contributor Author

Another use case would be turn aggregation reports, river aggregation reports, etc. If you've ever messed with compilers I'm basically looking for something that does the same thing as the Visitor Pattern.

Anyway, I'll try to hack something together on my fork and if it looks not horrible I'll send a PR along.

@b-inary
Copy link
Owner

b-inary commented Dec 23, 2022

I got it. Such a feature could be useful, but it would also require a bit of effort. If you could work on it in your forked repository, I would appreciate it. PRs are always welcome!

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

2 participants