use std::borrow::Borrow;
use std::convert::TryInto;
use std::ops::RangeBounds;
use std::os::raw::c_int;
use crate::{Integrality, Problem};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Row(pub(crate) c_int);
#[derive(Debug, Clone, PartialEq, Default)]
pub struct ColMatrix {
pub(crate) astart: Vec<c_int>,
pub(crate) aindex: Vec<c_int>,
pub(crate) avalue: Vec<f64>,
}
impl Problem<ColMatrix> {
pub fn add_row<N: Into<f64> + Copy, B: RangeBounds<N>>(&mut self, bounds: B) -> Row {
self.add_row_inner(bounds)
}
pub fn add_column<
N: Into<f64> + Copy,
B: RangeBounds<N>,
ITEM: Borrow<(Row, f64)>,
I: IntoIterator<Item = ITEM>,
>(
&mut self,
col_factor: f64,
bounds: B,
row_factors: I,
) {
self.add_column_with_integrality(col_factor, bounds, row_factors, false);
}
pub fn add_integer_column<
N: Into<f64> + Copy,
B: RangeBounds<N>,
ITEM: Borrow<(Row, f64)>,
I: IntoIterator<Item = ITEM>,
>(
&mut self,
col_factor: f64,
bounds: B,
row_factors: I,
) {
self.add_column_with_integrality(col_factor, bounds, row_factors, true);
}
#[inline]
pub fn add_column_with_integrality<
N: Into<f64> + Copy,
B: RangeBounds<N>,
ITEM: Borrow<(Row, f64)>,
I: IntoIterator<Item = ITEM>,
>(
&mut self,
col_factor: f64,
bounds: B,
row_factors: I,
is_integer: bool,
) {
self.add_column_with_integrality_kind(col_factor, bounds, row_factors, is_integer.into());
}
#[inline]
pub fn add_column_with_integrality_kind<
N: Into<f64> + Copy,
B: RangeBounds<N>,
ITEM: Borrow<(Row, f64)>,
I: IntoIterator<Item = ITEM>,
>(
&mut self,
col_factor: f64,
bounds: B,
row_factors: I,
integrality: Integrality,
) {
self.matrix
.astart
.push(self.matrix.aindex.len().try_into().unwrap());
let iter = row_factors.into_iter();
let (size, _) = iter.size_hint();
self.matrix.aindex.reserve(size);
self.matrix.avalue.reserve(size);
for r in iter {
let &(row, factor) = r.borrow();
self.matrix.aindex.push(row.0);
self.matrix.avalue.push(factor);
}
self.add_column_inner(col_factor, bounds, integrality);
}
pub fn add_semi_continuous_column<
N: Into<f64> + Copy,
B: RangeBounds<N>,
ITEM: Borrow<(Row, f64)>,
I: IntoIterator<Item = ITEM>,
>(
&mut self,
col_factor: f64,
bounds: B,
row_factors: I,
) {
self.add_column_with_integrality_kind(
col_factor,
bounds,
row_factors,
Integrality::SemiContinuous,
);
}
pub fn add_semi_integer_column<
N: Into<f64> + Copy,
B: RangeBounds<N>,
ITEM: Borrow<(Row, f64)>,
I: IntoIterator<Item = ITEM>,
>(
&mut self,
col_factor: f64,
bounds: B,
row_factors: I,
) {
self.add_column_with_integrality_kind(
col_factor,
bounds,
row_factors,
Integrality::SemiInteger,
);
}
}