use super::{calc_and_count, calc_or_count};
use crate::c2d_lexer::TId;
use crate::{Node, NodeType};
use petgraph::algo::is_cyclic_directed;
use petgraph::prelude::DfsPostOrder;
use petgraph::stable_graph::{NodeIndex, StableGraph};
use std::collections::HashMap;
pub type DdnnfGraph = StableGraph<TId, ()>;
pub fn rebuild_graph(
graph: DdnnfGraph,
root: NodeIndex,
) -> (Vec<Node>, HashMap<i32, usize>, Vec<usize>) {
debug_assert!(!is_cyclic_directed(&graph));
let mut dfs = DfsPostOrder::new(&graph, root);
let mut nd_to_usize: HashMap<NodeIndex, usize> = HashMap::new();
let mut parsed_nodes: Vec<Node> = Vec::with_capacity(graph.node_count());
let mut literals: HashMap<i32, usize> = HashMap::new();
let mut true_nodes = Vec::new();
while let Some(nx) = dfs.next(&graph) {
nd_to_usize.insert(nx, parsed_nodes.len());
let neighs = graph
.neighbors(nx)
.map(|n| *nd_to_usize.get(&n).unwrap())
.collect::<Vec<usize>>();
let next: Node = match graph[nx] {
TId::Literal { feature } => Node::new_literal(feature),
TId::And => Node::new_and(calc_and_count(&mut parsed_nodes, &neighs), neighs),
TId::Or => Node::new_or(0, calc_or_count(&mut parsed_nodes, &neighs), neighs),
TId::True => Node::new_bool(true),
TId::False => Node::new_bool(false),
TId::Header => {
panic!("The d4 standard does not include a header!")
}
};
match &next.ntype {
NodeType::And { children } | NodeType::Or { children } => {
let next_indize: usize = parsed_nodes.len();
for &i in children {
parsed_nodes[i].parents.push(next_indize);
}
}
NodeType::Literal { literal } => {
literals.insert(*literal, parsed_nodes.len());
}
NodeType::True => {
true_nodes.push(parsed_nodes.len());
}
_ => (),
}
parsed_nodes.push(next);
}
(parsed_nodes, literals, true_nodes)
}