xlog_logic/hypergraph/
explain.rs1use super::eligibility::{Boundary, Eligibility};
28use super::ir::HypergraphRule;
29use super::var_order::VariableOrder;
30use std::fmt::Write;
31
32pub fn explain(hg: &HypergraphRule, eligibility: &Eligibility, vo: &dyn VariableOrder) -> String {
36 let mut out = String::new();
37
38 writeln!(out, "rule head={}", hg.head_predicate).unwrap();
39
40 if hg.vertices.is_empty() {
42 writeln!(out, " vertices: []").unwrap();
43 } else {
44 let names: Vec<&str> = hg.vertices.iter().map(|v| v.name.as_str()).collect();
45 writeln!(out, " vertices: [{}]", names.join(" ")).unwrap();
46 }
47
48 if hg.hyperedges.is_empty() {
50 writeln!(out, " hyperedges: <none>").unwrap();
51 } else {
52 writeln!(out, " hyperedges:").unwrap();
53 for edge in &hg.hyperedges {
54 let args: Vec<String> = edge
55 .vertex_positions
56 .iter()
57 .map(|p| match p {
58 Some(vid) => format!("?{}", hg.vertex(*vid).name),
59 None => "_".to_string(),
60 })
61 .collect();
62 writeln!(out, " {}({})", edge.predicate, args.join(", ")).unwrap();
63 }
64 }
65
66 writeln!(out, " filters: {}", hg.comparison_count).unwrap();
68
69 match eligibility {
71 Eligibility::Eligible => {
72 writeln!(out, " eligibility: Eligible").unwrap();
73 }
74 Eligibility::Ineligible(boundaries) => {
75 writeln!(out, " eligibility: Ineligible").unwrap();
76 for b in boundaries {
77 writeln!(out, " {}", format_boundary(b)).unwrap();
78 }
79 }
80 }
81
82 let order = vo.order(hg);
84 let order_names: Vec<&str> = order
85 .iter()
86 .map(|vid| hg.vertex(*vid).name.as_str())
87 .collect();
88 writeln!(
89 out,
90 " variable-order({}): [{}]",
91 vo.name(),
92 order_names.join(" ")
93 )
94 .unwrap();
95
96 out
97}
98
99fn format_boundary(b: &Boundary) -> String {
100 match b {
101 Boundary::GroundFact => "GroundFact".to_string(),
102 Boundary::HeadAggregation => "HeadAggregation".to_string(),
103 Boundary::BodyNegation => "BodyNegation".to_string(),
104 Boundary::BodyIsExpr => "BodyIsExpr".to_string(),
105 Boundary::InsufficientPositiveAtoms { positive_count } => {
106 format!("InsufficientPositiveAtoms(positive_count={positive_count})")
107 }
108 Boundary::JoinKeysExceedBinaryFallbackLimit {
109 context,
110 count,
111 limit,
112 } => {
113 format!(
114 "JoinKeysExceedBinaryFallbackLimit(context={context:?}, count={count}, limit={limit})"
115 )
116 }
117 Boundary::UnsupportedKeyType { var, ty } => {
118 format!("UnsupportedKeyType(var={var}, ty={ty:?})")
119 }
120 }
121}