tensorlogic_adapters/
constraint.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
7pub enum PredicateProperty {
8 Symmetric,
10 Transitive,
12 Reflexive,
14 Irreflexive,
16 Antisymmetric,
18 Functional,
20 InverseFunctional,
22}
23
24#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
26pub struct ValueRange {
27 pub min: Option<f64>,
28 pub max: Option<f64>,
29 pub inclusive_min: bool,
30 pub inclusive_max: bool,
31}
32
33impl ValueRange {
34 pub fn new() -> Self {
35 Self {
36 min: None,
37 max: None,
38 inclusive_min: true,
39 inclusive_max: true,
40 }
41 }
42
43 pub fn with_min(mut self, min: f64, inclusive: bool) -> Self {
44 self.min = Some(min);
45 self.inclusive_min = inclusive;
46 self
47 }
48
49 pub fn with_max(mut self, max: f64, inclusive: bool) -> Self {
50 self.max = Some(max);
51 self.inclusive_max = inclusive;
52 self
53 }
54
55 pub fn contains(&self, value: f64) -> bool {
56 if let Some(min) = self.min {
57 if self.inclusive_min {
58 if value < min {
59 return false;
60 }
61 } else if value <= min {
62 return false;
63 }
64 }
65
66 if let Some(max) = self.max {
67 if self.inclusive_max {
68 if value > max {
69 return false;
70 }
71 } else if value >= max {
72 return false;
73 }
74 }
75
76 true
77 }
78}
79
80impl Default for ValueRange {
81 fn default() -> Self {
82 Self::new()
83 }
84}
85
86#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
88pub struct FunctionalDependency {
89 pub determinants: Vec<usize>,
91 pub dependents: Vec<usize>,
93}
94
95impl FunctionalDependency {
96 pub fn new(determinants: Vec<usize>, dependents: Vec<usize>) -> Self {
97 Self {
98 determinants,
99 dependents,
100 }
101 }
102}
103
104#[derive(Clone, Debug, Default, Serialize, Deserialize)]
106pub struct PredicateConstraints {
107 pub properties: Vec<PredicateProperty>,
109 pub value_ranges: Vec<Option<ValueRange>>,
111 pub functional_dependencies: Vec<FunctionalDependency>,
113}
114
115impl PredicateConstraints {
116 pub fn new() -> Self {
117 Self::default()
118 }
119
120 pub fn with_property(mut self, property: PredicateProperty) -> Self {
121 self.properties.push(property);
122 self
123 }
124
125 pub fn with_value_range(mut self, arg_index: usize, range: ValueRange) -> Self {
126 while self.value_ranges.len() <= arg_index {
127 self.value_ranges.push(None);
128 }
129 self.value_ranges[arg_index] = Some(range);
130 self
131 }
132
133 pub fn with_functional_dependency(mut self, dependency: FunctionalDependency) -> Self {
134 self.functional_dependencies.push(dependency);
135 self
136 }
137
138 pub fn has_property(&self, property: &PredicateProperty) -> bool {
139 self.properties.contains(property)
140 }
141
142 pub fn is_symmetric(&self) -> bool {
143 self.has_property(&PredicateProperty::Symmetric)
144 }
145
146 pub fn is_transitive(&self) -> bool {
147 self.has_property(&PredicateProperty::Transitive)
148 }
149
150 pub fn is_reflexive(&self) -> bool {
151 self.has_property(&PredicateProperty::Reflexive)
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_value_range() {
161 let range = ValueRange::new().with_min(0.0, true).with_max(1.0, true);
162
163 assert!(range.contains(0.0));
164 assert!(range.contains(0.5));
165 assert!(range.contains(1.0));
166 assert!(!range.contains(-0.1));
167 assert!(!range.contains(1.1));
168 }
169
170 #[test]
171 fn test_value_range_exclusive() {
172 let range = ValueRange::new().with_min(0.0, false).with_max(1.0, false);
173
174 assert!(!range.contains(0.0));
175 assert!(range.contains(0.5));
176 assert!(!range.contains(1.0));
177 }
178
179 #[test]
180 fn test_predicate_properties() {
181 let constraints = PredicateConstraints::new()
182 .with_property(PredicateProperty::Symmetric)
183 .with_property(PredicateProperty::Transitive);
184
185 assert!(constraints.is_symmetric());
186 assert!(constraints.is_transitive());
187 assert!(!constraints.is_reflexive());
188 }
189
190 #[test]
191 fn test_functional_dependency() {
192 let fd = FunctionalDependency::new(vec![0], vec![1, 2]);
193
194 assert_eq!(fd.determinants, vec![0]);
195 assert_eq!(fd.dependents, vec![1, 2]);
196 }
197}