c3_lang_linearization/
c3_linearization.rs1use std::fmt::Debug;
2
3use super::{is_subset, C3Error, Sets, C3};
4
5pub fn c3_linearization(mut input: C3) -> Result<C3, C3Error> {
7 let mut output = C3::new();
8 loop {
9 let solved = output.all_classes();
10 let mut found = false;
11 for base in input.all_classes() {
12 let parents = input.path(&base)?;
13 if is_subset(&solved, &parents) {
14 let sets = output.sets_for(parents)?;
15 let solution = merge(&base, sets)?;
16 input.remove(&base)?;
17 output.add(base, solution);
18 found = true;
19 }
20 }
21 if !found {
22 break;
23 }
24 }
25 Ok(output)
26}
27
28pub fn merge<T: Clone + Debug + Eq>(base: &T, mut sets: Sets<T>) -> Result<Vec<T>, C3Error> {
29 let mut solutions = vec![base.clone()];
30 loop {
31 if sets.is_empty() {
32 return Ok(solutions);
33 }
34 let solution = sets.find_solution()?;
35 solutions.push(solution);
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42
43 #[test]
44 fn test_c3() {
45 let mut input = C3::new();
46 input.add_class_str("A", "");
47 input.add_class_str("B", "A");
48 input.add_class_str("C", "A");
49 input.add_class_str("D", "B, C");
50
51 let mut target = C3::new();
52 target.add_class_str("A", "A");
53 target.add_class_str("B", "B, A");
54 target.add_class_str("C", "C, A");
55 target.add_class_str("D", "D, B, C, A");
56
57 assert_eq!(c3_linearization(input).unwrap(), target);
58 }
59
60 #[test]
61 fn test_merge() {
62 let head = "K";
63 let mut sets: Sets<&str> = Sets::new();
64 sets.push(vec!["B", "O"]).unwrap();
65 sets.push(vec!["A", "O"]).unwrap();
66 sets.push(vec!["C", "O"]).unwrap();
67 sets.push(vec!["B", "A", "C"]).unwrap();
68
69 let result = merge(&head, sets).unwrap();
70 assert_eq!(result, vec!["K", "B", "A", "C", "O"]);
71 }
72
73 #[test]
74 fn test_merge_2() {
75 let head = "Z";
76 let mut sets: Sets<&str> = Sets::new();
77 sets.push(vec!["K1", "C", "B", "A", "O"]).unwrap();
78 sets.push(vec!["K3", "A", "D", "O"]).unwrap();
79 sets.push(vec!["K2", "B", "D", "E", "O"]).unwrap();
80 sets.push(vec!["K1", "K3", "K2"]).unwrap();
81
82 let result = merge(&head, sets).unwrap();
83 let expected = vec!["Z", "K1", "C", "K3", "K2", "B", "A", "D", "E", "O"];
84 assert_eq!(result, expected);
85 }
86}