use crate::algorithms::online::Memory;
use crate::algorithms::online::{OnlineAlgorithm, Step};
use crate::algorithms::Options;
use crate::config::Config;
use crate::model::{ModelOutputFailure, ModelOutputSuccess};
use crate::problem::{Online, Problem};
use crate::result::{Failure, Result};
use crate::schedule::Schedule;
use crate::utils::assert;
use crate::value::Value;
impl<'a, P> Online<P> {
pub fn stream<T, M, O, C, D>(
&mut self,
alg: &impl OnlineAlgorithm<'a, T, P, M, O, C, D>,
update: impl Fn(&mut Online<P>, &Schedule<T>) -> bool,
options: O,
) -> Result<(Schedule<T>, Option<M>)>
where
T: Value<'a>,
P: Problem<T, C, D> + 'a,
M: Memory<'a, T, P, C, D>,
O: Options<T, P, C, D>,
C: ModelOutputSuccess,
D: ModelOutputFailure,
{
let mut xs = Schedule::empty();
let m = self.stream_from(alg, update, options, &mut xs, None)?;
Ok((xs, m))
}
pub fn stream_from<T, M, O, C, D>(
&mut self,
alg: &impl OnlineAlgorithm<'a, T, P, M, O, C, D>,
update: impl Fn(&mut Online<P>, &Schedule<T>) -> bool,
options: O,
xs: &mut Schedule<T>,
mut prev_m: Option<M>,
) -> Result<Option<M>>
where
T: Value<'a>,
P: Problem<T, C, D> + 'a,
M: Memory<'a, T, P, C, D>,
O: Options<T, P, C, D>,
C: ModelOutputSuccess,
D: ModelOutputFailure,
{
loop {
prev_m = self.next(alg, options.clone(), xs, prev_m)?.1;
if !update(self, xs) {
break;
};
self.verify()?;
}
Ok(prev_m)
}
pub fn next<T, M, O, C, D>(
&self,
alg: &impl OnlineAlgorithm<'a, T, P, M, O, C, D>,
options: O,
xs: &mut Schedule<T>,
prev_m: Option<M>,
) -> Result<(Config<T>, Option<M>)>
where
T: Value<'a>,
P: Problem<T, C, D> + 'a,
M: Memory<'a, T, P, C, D>,
O: Options<T, P, C, D>,
C: ModelOutputSuccess,
D: ModelOutputFailure,
{
assert(
xs.t_end() + 1 == self.p.t_end(),
Failure::OnlineInconsistentCurrentTimeSlot {
previous_time_slots: xs.t_end(),
current_time_slot: self.p.t_end(),
},
)?;
let Step(x, m) = alg.next(self.clone(), xs, prev_m, options)?;
xs.push(x.clone());
Ok((x, m))
}
pub fn offline_stream<T, M, O, C, D>(
&mut self,
alg: &impl OnlineAlgorithm<'a, T, P, M, O, C, D>,
t_end: i32,
options: O,
) -> Result<(Schedule<T>, Option<M>)>
where
T: Value<'a>,
P: Problem<T, C, D> + 'a,
M: Memory<'a, T, P, C, D>,
O: Options<T, P, C, D>,
C: ModelOutputSuccess,
D: ModelOutputFailure,
{
self.stream(
alg,
|o, _| {
if o.p.t_end() < t_end - o.w {
o.p.inc_t_end();
true
} else {
false
}
},
options,
)
}
pub fn offline_stream_from<T, M, O, C, D>(
&'a mut self,
alg: &impl OnlineAlgorithm<'a, T, P, M, O, C, D>,
t_end: i32,
options: O,
xs: &mut Schedule<T>,
prev_m: Option<M>,
) -> Result<Option<M>>
where
T: Value<'a>,
P: Problem<T, C, D>,
M: Memory<'a, T, P, C, D>,
O: Options<T, P, C, D>,
C: ModelOutputSuccess,
D: ModelOutputFailure,
{
self.stream_from(
alg,
|o, _| {
if o.p.t_end() < t_end - o.w {
o.p.inc_t_end();
true
} else {
false
}
},
options,
xs,
prev_m,
)
}
}