Adjusting implementations of traits for interval sets and resource intervals

This commit is contained in:
Kinesin Data Technologies Incorporated
2022-09-29 13:02:39 -03:00
parent 9cd2be5255
commit 3031ab8767
3 changed files with 106 additions and 46 deletions
+30 -33
View File
@@ -1,5 +1,4 @@
use super::*;
use std::convert::From;
use std::ops::{Add, BitAnd, BitOr, Deref, DerefMut, Not, Sub};
/// A coalescing set of intervals
@@ -159,43 +158,41 @@ impl From<&[Interval]> for IntervalSet {
}
}
impl Not for &IntervalSet {
type Output = IntervalSet;
fn not(self) -> Self::Output {
self.complement()
}
}
impl Add for &IntervalSet {
type Output = IntervalSet;
fn add(self, other: &IntervalSet) -> Self::Output {
self.union(other)
}
}
impl Sub for &IntervalSet {
type Output = IntervalSet;
fn sub(self, other: &IntervalSet) -> Self::Output {
self.difference(other)
}
}
impl BitOr for &IntervalSet {
type Output = IntervalSet;
fn bitor(self, other: &IntervalSet) -> Self::Output {
self.union(other)
}
}
impl BitAnd for &IntervalSet {
type Output = IntervalSet;
fn bitand(self, other: &IntervalSet) -> Self::Output {
self.intersection(other)
}
}
impl Not for IntervalSet {
type Output = IntervalSet;
fn not(self) -> Self::Output {
type Output = Self;
fn not(self) -> Self {
self.complement()
}
}
impl Add for IntervalSet {
type Output = Self;
fn add(self, other: Self) -> Self {
self.union(&other)
}
}
impl Sub for IntervalSet {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
self.difference(&other)
}
}
impl BitOr for IntervalSet {
type Output = Self;
fn bitor(self, other: Self) -> Self {
self.union(&other)
}
}
impl BitAnd for IntervalSet {
type Output = Self;
fn bitand(self, other: Self) -> Self {
self.intersection(&other)
}
}
#[cfg(test)]
mod tests {
use super::*;
+75 -12
View File
@@ -5,12 +5,29 @@ use std::ops::{Add, Deref, DerefMut, Sub};
/// represent where a resource is available, or where it's required
/// Resources are independent, so overlaps between the
/// interval sets are possible.
#[derive(Debug, PartialEq)]
pub struct ResourceInterval(HashMap<Resource, IntervalSet>);
impl ResourceInterval {
fn new() -> Self {
pub fn new() -> Self {
ResourceInterval(HashMap::new())
}
pub fn insert(&mut self, other: ResourceInterval) {
for (res, is) in other.iter() {
self.0
.entry(res.clone())
.or_insert(IntervalSet::new())
.merge(is);
}
}
pub fn remove(&mut self, other: ResourceInterval) {
for (res, is) in other.iter() {
let avail = self.0.entry(res.clone()).or_insert(IntervalSet::new());
*avail = avail.difference(is);
}
}
}
impl Deref for ResourceInterval {
@@ -37,9 +54,9 @@ impl From<&HashMap<Resource, IntervalSet>> for ResourceInterval {
}
}
impl Add for &ResourceInterval {
impl Add for ResourceInterval {
type Output = ResourceInterval;
fn add(self, other: &ResourceInterval) -> Self::Output {
fn add(self, other: ResourceInterval) -> Self::Output {
let res: HashMap<Resource, IntervalSet> =
other.0.iter().fold(self.0.clone(), |mut acc, (res, is)| {
acc.entry(res.clone())
@@ -51,16 +68,62 @@ impl Add for &ResourceInterval {
}
}
impl Sub for &ResourceInterval {
impl Sub for ResourceInterval {
type Output = ResourceInterval;
fn sub(self, other: &ResourceInterval) -> Self::Output {
let res: HashMap<Resource, IntervalSet> =
other.0.iter().fold(self.0.clone(), |mut acc, (res, is)| {
acc.entry(res.clone())
.or_insert(IntervalSet::new())
.difference(is);
acc
});
fn sub(self, other: ResourceInterval) -> Self::Output {
let res: HashMap<Resource, IntervalSet> = self
.0
.iter()
.map(|(res, is)| {
(
res.clone(),
is.difference(other.get(res).unwrap_or(&IntervalSet::new())),
)
})
.collect();
ResourceInterval(res)
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! intv {
( $x:literal, $y:literal ) => {
Interval::new(
Utc.ymd(2022, 1, 1).and_hms($x, 0, 0),
Utc.ymd(2022, 1, 1).and_hms($y, 0, 0),
)
};
}
macro_rules! ri {
( $r:literal, $(($x:literal, $y:literal)),* ) => {
ResourceInterval::from(HashMap::from([(
$r.to_owned(),
IntervalSet::from(vec![$(intv!($x, $y)),*]),
)]))
};
}
#[test]
fn test_conversion() {
let ri = ResourceInterval::from(HashMap::from([("alpha".to_owned(), IntervalSet::new())]));
assert_eq!(ri.len(), 1);
}
#[test]
fn test_addition() {
let a = ri!("alpha", (13, 15));
assert_eq!(a + ri!("alpha", (15, 18)), ri!("alpha", (13, 18)));
}
#[test]
fn test_subtraction() {
let a = ri!("alpha", (13, 18));
assert_eq!(a - ri!("alpha", (15, 16)), ri!("alpha", (13, 15), (16, 18)));
}
}
+1 -1
View File
@@ -157,7 +157,7 @@ impl Task {
)]));
self.provides.iter().all(|res| {
if let Some(is) = available.get(res) {
!(&horizon_is - is).is_empty()
!(horizon_is.difference(is)).is_empty()
} else {
false
}