use std::collections::HashSet;
use crate::algorithm::two_phase::matrix_provider::column::{Column, ColumnNumber};
use crate::algorithm::two_phase::matrix_provider::filter::Filtered;
use crate::algorithm::two_phase::matrix_provider::MatrixProvider;
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;
#[derive(Eq, PartialEq, Debug)]
pub struct NonArtificial<'a, MP> {
provider: &'a MP,
}
impl<'provider, MP> Kind for NonArtificial<'provider, MP>
where
MP: MatrixProvider,
{
type Column = MP::Column;
type Cost = MP::Cost<'provider>;
fn initial_cost_value(&self, j: usize) -> Self::Cost {
debug_assert!(j < self.provider.nr_columns());
self.provider.cost_value(j)
}
fn original_column(&self, j: usize) -> Self::Column {
debug_assert!(j < self.provider.nr_columns());
self.provider.column(j)
}
fn nr_rows(&self) -> usize {
self.provider.nr_rows()
}
fn nr_columns(&self) -> usize {
self.provider.nr_columns()
}
}
impl<'provider, IM, MP> Tableau<IM, NonArtificial<'provider, MP>>
where
IM: InverseMaintainer<F:
im_ops::FieldHR +
im_ops::Column<<MP::Column as Column>::F> +
im_ops::Cost<MP::Cost<'provider>> +
>,
MP: MatrixProvider,
{
pub fn new_with_inverse_maintainer(
provider: &'provider MP,
inverse_maintainer: IM,
basis_columns: HashSet<usize>,
) -> Self {
Tableau {
inverse_maintainer,
basis_columns,
kind: NonArtificial {
provider,
},
}
}
pub(crate) fn new_with_basis(
provider: &'provider MP,
basis: &HashSet<usize>,
) -> Self
where
IM::F: im_ops::Column<MP::Rhs>,
MP::Rhs: 'static,
{
let arbitrary_order = basis.iter().copied().collect::<Vec<_>>();
Tableau {
inverse_maintainer: IM::from_basis(&arbitrary_order, provider),
basis_columns: basis.clone(),
kind: NonArtificial {
provider,
},
}
}
pub fn from_artificial(
inverse_maintainer: IM,
nr_artificial: usize,
basis_indices: HashSet<usize>,
provider: &'provider MP,
) -> Self {
Tableau {
inverse_maintainer: IM::from_artificial(
inverse_maintainer,
provider,
nr_artificial,
),
basis_columns: basis_indices.into_iter()
.map(|column| column - nr_artificial)
.collect(),
kind: NonArtificial {
provider,
},
}
}
}
impl<'provider, IM, MP> Tableau<IM, NonArtificial<'provider, MP>>
where
IM: InverseMaintainer<F: im_ops::FieldHR + im_ops::Column<<MP::Column as Column>::F> + im_ops::Cost<MP::Cost<'provider>>>,
MP: Filtered,
{
pub fn from_artificial_removing_rows(
inverse_maintainer: IM,
nr_artificial: usize,
mut basis: HashSet<usize>,
provider: &'provider MP,
) -> Self {
debug_assert!(
basis.iter().all(|&v| v >= nr_artificial || provider.filtered_rows().iter()
.any(|&row| inverse_maintainer.basis_column_index_for_row(row) == v)
),
);
for &row in provider.filtered_rows() {
let column = inverse_maintainer.basis_column_index_for_row(row);
let was_there = basis.remove(&column);
debug_assert!(was_there);
}
let basis_columns = basis.into_iter().map(|j| j - nr_artificial).collect();
let inverse_maintainer = IM::from_artificial_remove_rows(
inverse_maintainer,
provider,
nr_artificial,
);
Tableau {
inverse_maintainer,
basis_columns,
kind: NonArtificial {
provider,
},
}
}
}