robopoker/mccfr/
info.rs

1use crate::mccfr::edge::Edge;
2use crate::mccfr::node::Node;
3use petgraph::graph::DiGraph;
4use petgraph::graph::NodeIndex;
5use std::ptr::NonNull;
6
7#[derive(Debug, Clone)]
8pub struct Info {
9    roots: Vec<NodeIndex>,
10    graph: NonNull<DiGraph<Node, Edge>>,
11}
12
13impl From<(NodeIndex, NonNull<DiGraph<Node, Edge>>)> for Info {
14    fn from((index, graph): (NodeIndex, NonNull<DiGraph<Node, Edge>>)) -> Self {
15        let roots = vec![index];
16        Self { roots, graph }
17    }
18}
19
20impl Info {
21    pub fn add(&mut self, index: NodeIndex) {
22        self.roots.push(index)
23    }
24    pub fn heads(&self) -> Vec<&Node> {
25        self.roots
26            .iter()
27            .copied()
28            .map(|i| self.graph_ref().node_weight(i).expect("valid node index"))
29            .collect()
30    }
31    pub fn node(&self) -> &Node {
32        self.roots
33            .iter()
34            .next()
35            .copied()
36            .map(|i| self.graph_ref().node_weight(i).expect("valid node index"))
37            .expect("non-empty infoset")
38    }
39    /// SAFETY:
40    /// we have logical assurance that lifetimes work out effectively:
41    /// 'info: 'node: 'tree
42    /// Info is created from a Node
43    /// Node is created from a Tree
44    /// Tree owns its Graph
45    fn graph_ref(&self) -> &DiGraph<Node, Edge> {
46        unsafe { self.graph.as_ref() }
47    }
48}