Adjusting implementations of traits for interval sets and resource intervals
This commit is contained in:
parent
9cd2be5255
commit
3031ab8767
+30
-33
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user