use std::collections::HashSet;
use relp_num::Binary;
use crate::algorithm::two_phase::matrix_provider::column::Column;
use crate::algorithm::two_phase::matrix_provider::column::identity::Identity;
use crate::algorithm::two_phase::tableau::inverse_maintenance::{InverseMaintainer, ops as im_ops};
use crate::algorithm::two_phase::tableau::kind::Kind;
use crate::algorithm::two_phase::tableau::Tableau;
pub mod fully;
pub mod partially;
pub type Cost = Binary;
pub trait Artificial: Kind<Column: Identity, Cost=Cost> {
fn nr_artificial_variables(&self) -> usize;
fn pivot_row_from_artificial(&self, artificial_index: usize) -> usize;
}
impl<'provider, IM, A> Tableau<IM, A>
where
IM: InverseMaintainer<F: im_ops::Column<<A::Column as Column>::F> + im_ops::Cost<A::Cost>>,
A: Artificial,
{
pub fn has_artificial_in_basis(&self) -> bool {
self.basis_columns.iter().any(|&c| c < self.nr_artificial_variables())
}
pub fn artificial_basis_columns(&self) -> Vec<(usize, usize)> {
(0..self.nr_rows())
.map(|i| (i, self.inverse_maintainer.basis_column_index_for_row(i)))
.filter(|&(_, j)| j < self.nr_artificial_variables())
.collect()
}
pub fn pivot_row_from_artificial(&self, artificial_index: usize) -> usize {
debug_assert!(artificial_index < self.nr_artificial_variables());
debug_assert!(self.is_in_basis(artificial_index));
self.kind.pivot_row_from_artificial(artificial_index)
}
pub fn into_basis(self) -> (IM, usize, HashSet<usize>) {
let nr_artificial = self.nr_artificial_variables();
(self.inverse_maintainer, nr_artificial, self.basis_columns)
}
}
impl<'provider, IM, A> Tableau<IM, A>
where
A: Artificial,
{
pub fn nr_artificial_variables(&self) -> usize {
self.kind.nr_artificial_variables()
}
}