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