use super::*;
pub struct ValueRange {
variable: VariableId,
min: RawValue,
max: RawValue,
}
impl ValueRange {
pub fn new<T: ValueSchema>(variable: Variable<T>, min: Value<T>, max: Value<T>) -> Self {
ValueRange {
variable: variable.index,
min: min.raw,
max: max.raw,
}
}
}
pub fn value_range<T: ValueSchema>(
variable: Variable<T>,
min: Value<T>,
max: Value<T>,
) -> ValueRange {
ValueRange::new(variable, min, max)
}
impl<'a> Constraint<'a> for ValueRange {
fn variables(&self) -> VariableSet {
VariableSet::new_singleton(self.variable)
}
fn estimate(&self, variable: VariableId, _binding: &Binding) -> Option<usize> {
if self.variable == variable {
Some(usize::MAX)
} else {
None
}
}
fn propose(&self, _variable: VariableId, _binding: &Binding, _proposals: &mut Vec<RawValue>) {
}
fn confirm(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
if self.variable == variable {
proposals.retain(|v| *v >= self.min && *v <= self.max);
}
}
fn satisfied(&self, binding: &Binding) -> bool {
match binding.get(self.variable) {
Some(v) => *v >= self.min && *v <= self.max,
None => true,
}
}
}
#[cfg(test)]
mod tests {
use crate::prelude::valueschemas::R256;
use crate::prelude::*;
attributes! {
"AA00000000000000AA00000000000000" as test_score: R256;
}
#[test]
fn value_range_filters_correctly() {
let e1 = ufoid();
let e2 = ufoid();
let e3 = ufoid();
let v10: Value<R256> = 10i128.to_value();
let v50: Value<R256> = 50i128.to_value();
let v90: Value<R256> = 90i128.to_value();
let mut data = TribleSet::new();
data += entity! { &e1 @ test_score: v10 };
data += entity! { &e2 @ test_score: v50 };
data += entity! { &e3 @ test_score: v90 };
let all: Vec<Value<R256>> = find!(
v: Value<R256>,
pattern!(&data, [{ test_score: ?v }])
)
.collect();
assert_eq!(all.len(), 3);
let min: Value<R256> = 20i128.to_value();
let max: Value<R256> = 80i128.to_value();
let filtered: Vec<Value<R256>> = find!(
v: Value<R256>,
and!(
pattern!(&data, [{ test_score: ?v }]),
value_range(v, min, max),
)
)
.collect();
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0], v50);
}
}