problemreductions/models/graph/
kernel.rs1use crate::registry::{FieldInfo, ProblemSchemaEntry, VariantDimension};
9use crate::topology::DirectedGraph;
10use crate::traits::Problem;
11use serde::{Deserialize, Serialize};
12
13inventory::submit! {
14 ProblemSchemaEntry {
15 name: "Kernel",
16 display_name: "Kernel",
17 aliases: &[],
18 dimensions: &[
19 VariantDimension::new("graph", "DirectedGraph", &["DirectedGraph"]),
20 ],
21 module_path: module_path!(),
22 description: "Does the directed graph contain a kernel (independent and absorbing vertex subset)?",
23 fields: &[
24 FieldInfo { name: "graph", type_name: "DirectedGraph", description: "The directed graph G=(V,A)" },
25 ],
26 }
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct Kernel {
59 graph: DirectedGraph,
60}
61
62impl Kernel {
63 pub fn new(graph: DirectedGraph) -> Self {
65 Self { graph }
66 }
67
68 pub fn graph(&self) -> &DirectedGraph {
70 &self.graph
71 }
72
73 pub fn num_vertices(&self) -> usize {
75 self.graph.num_vertices()
76 }
77
78 pub fn num_arcs(&self) -> usize {
80 self.graph.num_arcs()
81 }
82}
83
84impl Problem for Kernel {
85 const NAME: &'static str = "Kernel";
86 type Value = crate::types::Or;
87
88 fn variant() -> Vec<(&'static str, &'static str)> {
89 crate::variant_params![]
90 }
91
92 fn dims(&self) -> Vec<usize> {
93 vec![2; self.graph.num_vertices()]
94 }
95
96 fn evaluate(&self, config: &[usize]) -> crate::types::Or {
97 let n = self.graph.num_vertices();
98
99 let selected: Vec<bool> = config.iter().map(|&c| c == 1).collect();
101
102 for u in 0..n {
104 if !selected[u] {
105 continue;
106 }
107 for &v in &self.graph.successors(u) {
109 if selected[v] {
110 return crate::types::Or(false);
111 }
112 }
113 }
114
115 for u in 0..n {
117 if selected[u] {
118 continue;
119 }
120 let has_arc_to_selected = self.graph.successors(u).iter().any(|&v| selected[v]);
121 if !has_arc_to_selected {
122 return crate::types::Or(false);
123 }
124 }
125
126 crate::types::Or(true)
127 }
128}
129
130#[cfg(feature = "example-db")]
131pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::ModelExampleSpec> {
132 let graph = DirectedGraph::new(
135 5,
136 vec![(0, 1), (0, 2), (1, 3), (2, 3), (3, 4), (4, 0), (4, 1)],
137 );
138 let optimal_config = vec![1, 0, 0, 1, 0];
139 vec![crate::example_db::specs::ModelExampleSpec {
140 id: "kernel",
141 instance: Box::new(Kernel::new(graph)),
142 optimal_config,
143 optimal_value: serde_json::json!(true),
144 }]
145}
146
147crate::declare_variants! {
148 default Kernel => "2^num_vertices",
149}
150
151#[cfg(test)]
152#[path = "../../unit_tests/models/graph/kernel.rs"]
153mod tests;