use crate::algorithm::two_phase::matrix_provider::column::Column;
use crate::algorithm::two_phase::matrix_provider::column::identity::Identity;
use crate::algorithm::two_phase::matrix_provider::MatrixProvider;
use crate::algorithm::two_phase::tableau::inverse_maintenance::{InverseMaintener, ops as im_ops};
use crate::algorithm::two_phase::tableau::kind::artificial::{Artificial, Cost};
use crate::algorithm::two_phase::tableau::kind::Kind;
use crate::algorithm::two_phase::tableau::Tableau;
pub struct Fully<'a, MP: MatrixProvider> {
provider: &'a MP,
}
impl<'provider, MP> Kind for Fully<'provider, MP>
where
MP: MatrixProvider<Column: Column + Identity>,
{
type Column = MP::Column;
type Cost = Cost;
fn initial_cost_value(&self, j: usize) -> Self::Cost {
if j < self.nr_artificial_variables() {
Cost::One
} else {
Cost::Zero
}
}
fn original_column(&self, j: usize) -> Self::Column {
if j < self.nr_rows() {
<Self::Column as Identity>::identity(j, self.nr_rows())
} else {
self.provider.column(j - self.nr_rows())
}
}
fn nr_rows(&self) -> usize {
self.provider.nr_rows()
}
fn nr_columns(&self) -> usize {
self.nr_rows() + self.provider.nr_columns()
}
}
impl<'provider, MP> Artificial for Fully<'provider, MP>
where
MP: MatrixProvider<Column: Identity>,
{
fn nr_artificial_variables(&self) -> usize {
self.nr_rows()
}
fn pivot_row_from_artificial(&self, artificial_index: usize) -> usize {
debug_assert!(artificial_index < self.nr_artificial_variables());
artificial_index
}
}
impl<'provider, IM, MP> Tableau<IM, Fully<'provider, MP>>
where
IM: InverseMaintener<F: im_ops::Rhs<MP::Rhs>>,
MP: MatrixProvider,
{
pub(crate) fn new(provider: &'provider MP) -> Self {
let m = provider.nr_rows();
Tableau {
inverse_maintainer: IM::create_for_fully_artificial(provider.right_hand_side()),
basis_columns: (0..m).collect(),
kind: Fully { provider },
}
}
}