use crate::algorithm::{OptimizationResult, SolveRelaxation};
use crate::algorithm::two_phase::matrix_provider::column::{Column, ColumnNumber};
use crate::algorithm::two_phase::matrix_provider::column::identity::Identity;
use crate::algorithm::two_phase::matrix_provider::filter::generic_wrapper::{IntoFilteredColumn, RemoveRows};
use crate::algorithm::two_phase::matrix_provider::MatrixProvider;
use crate::algorithm::two_phase::phase_one::{FeasibilityComputeTrait, FullInitialBasis, Rank, RankedFeasibilityResult};
use crate::algorithm::two_phase::strategy::pivot_rule::SteepestDescentAlongObjective;
use crate::algorithm::two_phase::tableau::inverse_maintenance::{InverseMaintainer, ops as im_ops};
use crate::algorithm::two_phase::tableau::kind::artificial::Cost as ArtificialCost;
use crate::algorithm::two_phase::tableau::kind::non_artificial::NonArtificial;
use crate::algorithm::two_phase::tableau::Tableau;
pub mod phase_one;
pub mod phase_two;
pub mod tableau;
pub mod matrix_provider;
pub mod strategy;
impl<MP> SolveRelaxation for MP
where
MP: MatrixProvider<Column: Identity + IntoFilteredColumn>,
{
default fn solve_relaxation<'provider, IM>(&'provider self) -> OptimizationResult<IM::F>
where
IM: InverseMaintainer<F:
im_ops::FieldHR +
im_ops::Column<<<Self as MatrixProvider>::Column as Column>::F> +
im_ops::Cost<ArtificialCost> +
im_ops::Cost<MP::Cost<'provider>> +
im_ops::Rhs<MP::Rhs> +
>,
{
match self.compute_bfs_giving_im::<IM>() {
RankedFeasibilityResult::Feasible {
rank,
nr_artificial_variables,
basis,
inverse_maintainer,
} => match rank {
Rank::Deficient(rows_to_remove) if !rows_to_remove.is_empty() => {
let rows_removed = RemoveRows::new(self, rows_to_remove);
let mut non_artificial = Tableau::<_, NonArtificial<_>>::from_artificial_removing_rows(
inverse_maintainer,
nr_artificial_variables,
basis,
&rows_removed,
);
phase_two::primal::<_, _, SteepestDescentAlongObjective<_>>(&mut non_artificial)
},
_ => {
let mut non_artificial_tableau = Tableau::<_, NonArtificial<_>>::from_artificial(
inverse_maintainer,
nr_artificial_variables,
basis,
self,
);
phase_two::primal::<_, _, SteepestDescentAlongObjective<_>>(&mut non_artificial_tableau)
},
},
RankedFeasibilityResult::Infeasible => OptimizationResult::Infeasible,
}
}
}
impl<MP: FullInitialBasis> SolveRelaxation for MP
where
MP: MatrixProvider<Column: Identity + IntoFilteredColumn>,
MP::Rhs: 'static + ColumnNumber,
{
fn solve_relaxation<'provider, IM>(&'provider self) -> OptimizationResult<IM::F>
where
IM: InverseMaintainer<F:
im_ops::FieldHR +
im_ops::Column<<<Self as MatrixProvider>::Column as Column>::F> +
im_ops::Cost<MP::Cost<'provider>> +
im_ops::Rhs<Self::Rhs> +
im_ops::Column<Self::Rhs> +
>,
{
let basis_indices = self.pivot_element_indices();
let inverse_maintainer = IM::from_basis_pivots(&basis_indices, self);
let basis_indices = basis_indices.into_iter().map(|(_row, column)| column).collect();
let mut tableau = Tableau::<_, NonArtificial<_>>::new_with_inverse_maintainer(
self, inverse_maintainer, basis_indices,
);
phase_two::primal::<_, _, SteepestDescentAlongObjective<_>>(&mut tableau)
}
}
#[cfg(test)]
mod test;