pub mod multi_dimensional;
pub mod uni_dimensional;
mod graph_search;
pub use graph_search::{Cache, CachedPath};
use crate::algorithms::Options;
use crate::model::{ModelOutputFailure, ModelOutputSuccess};
use crate::problem::Problem;
use crate::result::Result;
use crate::schedule::Schedule;
use pyo3::prelude::*;
pub trait OfflineAlgorithm<T, R, P, O, C, D>:
Fn(P, O, OfflineOptions) -> Result<R>
where
R: OfflineResult<T>,
P: Problem<T, C, D>,
O: Options<T, P, C, D>,
C: ModelOutputSuccess,
D: ModelOutputFailure,
{
fn solve(
&self,
p: P,
options: O,
offline_options: OfflineOptions,
) -> Result<R> {
self(p, options, offline_options)
}
fn solve_with_default_options(
&self,
p: P,
offline_options: OfflineOptions,
) -> Result<R> {
let options = O::default(&p);
self.solve(p, options, offline_options)
}
}
impl<T, R, P, O, C, D, F> OfflineAlgorithm<T, R, P, O, C, D> for F
where
R: OfflineResult<T>,
P: Problem<T, C, D>,
O: Options<T, P, C, D>,
C: ModelOutputSuccess,
D: ModelOutputFailure,
F: Fn(P, O, OfflineOptions) -> Result<R>,
{
}
#[pyclass]
#[derive(Clone, Debug)]
pub struct OfflineOptions {
#[pyo3(get, set)]
pub inverted: bool,
#[pyo3(get, set)]
pub alpha: f64,
#[pyo3(get, set)]
pub l: Option<f64>,
}
impl Default for OfflineOptions {
fn default() -> Self {
OfflineOptions {
inverted: false,
alpha: 1.,
l: None,
}
}
}
impl OfflineOptions {
pub fn inverted() -> Self {
Self {
inverted: true,
..Self::default()
}
}
pub fn alpha_unfair(alpha: f64) -> Self {
Self {
alpha,
..Self::default()
}
}
pub fn l_constrained(l: f64) -> Self {
Self {
l: Some(l),
..Self::default()
}
}
}
#[pymethods]
impl OfflineOptions {
#[new]
pub fn new(inverted: bool, alpha: f64, l: Option<f64>) -> Self {
OfflineOptions { inverted, alpha, l }
}
}
pub trait OfflineResult<T> {
fn xs(self) -> Schedule<T>;
}
pub struct PureOfflineResult<T> {
pub xs: Schedule<T>,
}
impl<T> OfflineResult<T> for PureOfflineResult<T> {
fn xs(self) -> Schedule<T> {
self.xs
}
}