#![allow(dead_code, missing_docs)]
#[allow(unused_imports)]
use crate::prelude::*;
use num_rational::BigRational;
use num_traits::{One, Zero};
pub type VarId = usize;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ParametricType {
Objective,
Rhs,
}
#[derive(Debug, Clone)]
pub struct Breakpoint {
pub lambda: BigRational,
pub optimal_value: BigRational,
pub basis: Vec<VarId>,
}
#[derive(Debug, Clone)]
pub struct ParametricInterval {
pub lambda_min: BigRational,
pub lambda_max: BigRational,
pub value_slope: BigRational,
pub value_intercept: BigRational,
pub basis: Vec<VarId>,
}
#[derive(Debug, Clone)]
pub struct ParametricSimplexConfig {
pub param_type: ParametricType,
pub max_breakpoints: usize,
pub lambda_min: BigRational,
pub lambda_max: BigRational,
}
impl Default for ParametricSimplexConfig {
fn default() -> Self {
Self {
param_type: ParametricType::Objective,
max_breakpoints: 1000,
lambda_min: BigRational::zero(),
lambda_max: BigRational::from_integer(100.into()),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ParametricSimplexStats {
pub breakpoints: u64,
pub intervals: u64,
pub iterations: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParametricSimplexResult {
Success,
Infeasible,
Unbounded,
BreakpointLimit,
}
#[derive(Debug)]
pub struct ParametricSimplexSolver {
config: ParametricSimplexConfig,
parametric_coeffs: FxHashMap<usize, BigRational>,
breakpoints: Vec<Breakpoint>,
intervals: Vec<ParametricInterval>,
stats: ParametricSimplexStats,
}
impl ParametricSimplexSolver {
pub fn new(config: ParametricSimplexConfig) -> Self {
Self {
config,
parametric_coeffs: FxHashMap::default(),
breakpoints: Vec::new(),
intervals: Vec::new(),
stats: ParametricSimplexStats::default(),
}
}
pub fn default_config() -> Self {
Self::new(ParametricSimplexConfig::default())
}
pub fn set_parametric_coeff(&mut self, id: usize, coeff: BigRational) {
self.parametric_coeffs.insert(id, coeff);
}
pub fn solve(&mut self) -> ParametricSimplexResult {
let _current_lambda = self.config.lambda_min.clone();
ParametricSimplexResult::Infeasible
}
fn update_simplex_at_lambda(&mut self, _lambda: &BigRational) {
}
fn compute_next_breakpoint(&self, current_lambda: &BigRational) -> BigRational {
current_lambda.clone() + BigRational::one()
}
fn get_current_basis(&self) -> Vec<VarId> {
Vec::new()
}
fn create_interval(
&self,
lambda_min: BigRational,
lambda_max: BigRational,
basis: &[VarId],
) -> ParametricInterval {
let slope = BigRational::zero();
let intercept = BigRational::zero();
ParametricInterval {
lambda_min,
lambda_max,
value_slope: slope,
value_intercept: intercept,
basis: basis.to_vec(),
}
}
pub fn breakpoints(&self) -> &[Breakpoint] {
&self.breakpoints
}
pub fn intervals(&self) -> &[ParametricInterval] {
&self.intervals
}
pub fn evaluate(&self, lambda: &BigRational) -> Option<BigRational> {
for interval in &self.intervals {
if lambda >= &interval.lambda_min && lambda < &interval.lambda_max {
let value = interval.value_intercept.clone() + &interval.value_slope * lambda;
return Some(value);
}
}
None
}
pub fn stats(&self) -> &ParametricSimplexStats {
&self.stats
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parametric_creation() {
let solver = ParametricSimplexSolver::default_config();
assert_eq!(solver.breakpoints().len(), 0);
}
#[test]
fn test_set_parametric_coeff() {
let mut solver = ParametricSimplexSolver::default_config();
solver.set_parametric_coeff(0, BigRational::new(2.into(), 1.into()));
assert!(solver.parametric_coeffs.contains_key(&0));
}
}