1use super::functions::*;
6use std::collections::HashSet;
7
8#[allow(dead_code)]
10#[derive(Debug, Clone)]
11pub struct Relation<A: Clone + Eq + std::hash::Hash> {
12 pub domain: Vec<A>,
13 pub pairs: std::collections::HashSet<(usize, usize)>,
14}
15#[allow(dead_code)]
16impl<A: Clone + Eq + std::hash::Hash> Relation<A> {
17 pub fn new(domain: Vec<A>) -> Self {
18 Relation {
19 domain,
20 pairs: std::collections::HashSet::new(),
21 }
22 }
23 pub fn add_pair(&mut self, a: &A, b: &A) {
24 let i = self.domain.iter().position(|x| x == a);
25 let j = self.domain.iter().position(|x| x == b);
26 if let (Some(i), Some(j)) = (i, j) {
27 self.pairs.insert((i, j));
28 }
29 }
30 pub fn contains(&self, a: &A, b: &A) -> bool {
31 let i = self.domain.iter().position(|x| x == a);
32 let j = self.domain.iter().position(|x| x == b);
33 match (i, j) {
34 (Some(i), Some(j)) => self.pairs.contains(&(i, j)),
35 _ => false,
36 }
37 }
38 pub fn is_reflexive(&self) -> bool {
39 (0..self.domain.len()).all(|i| self.pairs.contains(&(i, i)))
40 }
41 pub fn is_symmetric(&self) -> bool {
42 self.pairs
43 .iter()
44 .all(|&(i, j)| self.pairs.contains(&(j, i)))
45 }
46 pub fn is_transitive(&self) -> bool {
47 let n = self.domain.len();
48 for i in 0..n {
49 for j in 0..n {
50 if self.pairs.contains(&(i, j)) {
51 for k in 0..n {
52 if self.pairs.contains(&(j, k)) && !self.pairs.contains(&(i, k)) {
53 return false;
54 }
55 }
56 }
57 }
58 }
59 true
60 }
61 pub fn is_equivalence(&self) -> bool {
62 self.is_reflexive() && self.is_symmetric() && self.is_transitive()
63 }
64 pub fn is_antisymmetric(&self) -> bool {
65 self.pairs
66 .iter()
67 .all(|&(i, j)| i == j || !self.pairs.contains(&(j, i)))
68 }
69 pub fn is_partial_order(&self) -> bool {
70 self.is_reflexive() && self.is_antisymmetric() && self.is_transitive()
71 }
72 pub fn equivalence_class(&self, a: &A) -> Vec<A> {
73 let i = self.domain.iter().position(|x| x == a);
74 match i {
75 None => Vec::new(),
76 Some(i) => self
77 .pairs
78 .iter()
79 .filter(|&&(x, _)| x == i)
80 .map(|&(_, j)| self.domain[j].clone())
81 .collect(),
82 }
83 }
84}
85#[allow(dead_code)]
87#[derive(Debug, Clone)]
88pub struct SetPartition {
89 pub n: usize,
90 pub blocks: Vec<std::collections::HashSet<usize>>,
91}
92#[allow(dead_code)]
93impl SetPartition {
94 pub fn discrete(n: usize) -> Self {
95 SetPartition {
96 n,
97 blocks: (0..n)
98 .map(|i| {
99 let mut s = std::collections::HashSet::new();
100 s.insert(i);
101 s
102 })
103 .collect(),
104 }
105 }
106 pub fn trivial(n: usize) -> Self {
107 let mut block = std::collections::HashSet::new();
108 for i in 0..n {
109 block.insert(i);
110 }
111 SetPartition {
112 n,
113 blocks: vec![block],
114 }
115 }
116 pub fn n_blocks(&self) -> usize {
117 self.blocks.len()
118 }
119 pub fn block_of(&self, element: usize) -> Option<usize> {
120 self.blocks.iter().position(|b| b.contains(&element))
121 }
122 pub fn merge_blocks(&mut self, i: usize, j: usize) {
123 if i == j || i >= self.blocks.len() || j >= self.blocks.len() {
124 return;
125 }
126 let block_j = self.blocks[j].clone();
127 let block_i = &mut self.blocks[i];
128 for x in block_j {
129 block_i.insert(x);
130 }
131 self.blocks.remove(j);
132 }
133 pub fn is_valid(&self) -> bool {
134 let mut covered = vec![false; self.n];
135 for block in &self.blocks {
136 if block.is_empty() {
137 return false;
138 }
139 for &x in block {
140 if x >= self.n || covered[x] {
141 return false;
142 }
143 covered[x] = true;
144 }
145 }
146 covered.iter().all(|&c| c)
147 }
148}
149#[allow(dead_code)]
151#[derive(Debug, Clone, PartialEq, Eq)]
152pub struct OrderedPair<A: Clone + Eq, B: Clone + Eq> {
153 pub fst: A,
154 pub snd: B,
155}
156#[allow(dead_code)]
157impl<A: Clone + Eq, B: Clone + Eq> OrderedPair<A, B> {
158 pub fn new(a: A, b: B) -> Self {
159 OrderedPair { fst: a, snd: b }
160 }
161 pub fn swap(self) -> OrderedPair<B, A> {
162 OrderedPair {
163 fst: self.snd,
164 snd: self.fst,
165 }
166 }
167}