column_range/
column_range.rs1use num_traits::Zero;
21use relp_num::RationalBig;
22use relp_num::RB;
23
24use relp::algorithm::OptimizationResult;
25use relp::algorithm::two_phase::matrix_provider::matrix_data::MatrixData;
26use relp::algorithm::two_phase::matrix_provider::MatrixProvider;
27use relp::algorithm::two_phase::phase_two;
28use relp::algorithm::two_phase::strategy::pivot_rule::FirstProfitable;
29use relp::algorithm::two_phase::tableau::inverse_maintenance::carry::basis_inverse_rows::BasisInverseRows;
30use relp::algorithm::two_phase::tableau::inverse_maintenance::carry::Carry;
31use relp::algorithm::two_phase::tableau::inverse_maintenance::InverseMaintainer;
32use relp::algorithm::two_phase::tableau::kind::non_artificial::NonArtificial;
33use relp::algorithm::two_phase::tableau::Tableau;
34use relp::data::linear_algebra::matrix::{ColumnMajor, MatrixOrder};
35use relp::data::linear_algebra::vector::{DenseVector, Vector};
36use relp::data::linear_program::elements::VariableType;
37use relp::data::linear_program::general_form::Variable;
38
39fn main() {
40 let input_matrix = [
44 [Some(3), Some(3), Some(3)],
45 [None, Some(3), Some(3)],
46 [Some(1), Some(2), Some(3)],
47 ];
48
49 let m = input_matrix.len();
50 let n = input_matrix[0].len();
51
52 let column_extreme = |f: fn(_) -> Option<i32>| (0..n)
53 .map(|j| f((0..m).filter_map(move |i| input_matrix[i][j])).unwrap())
54 .collect::<Vec<_>>();
55 let column_min = column_extreme(Iterator::min);
56 let column_max = column_extreme(Iterator::max);
57
58 let subtraction_amount = (0..m).map(|_| Variable {
60 variable_type: VariableType::Continuous,
61 cost: RB!(0),
62 lower_bound: Some(RB!(0)),
63 upper_bound: None,
64 shift: RB!(0),
65 flipped: false,
66 })
67 .collect::<Vec<_>>();
68 let column_minimum = (0..n).map(|_| Variable {
69 variable_type: VariableType::Continuous,
70 cost: RB!(-1),
72 lower_bound: Some(RB!(0)),
73 upper_bound: None,
74 shift: RB!(0),
75 flipped: false,
76 })
77 .collect::<Vec<_>>();
78 let column_maximum = (0..n).map(|_| Variable {
79 variable_type: VariableType::Continuous,
80 cost: RB!(1),
81 lower_bound: Some(RB!(0)),
82 upper_bound: None,
83 shift: RB!(0),
84 flipped: false,
85 })
86 .collect::<Vec<_>>();
87 let variables = [subtraction_amount, column_minimum, column_maximum].concat();
89
90 let mut row_major_constraints = Vec::new();
93 let mut b = Vec::new();
94 let mut basis_columns = Vec::new();
96
97 let mut nr_upper_bounded_constraints = 0;
99 let mut had_a_min = vec![false; n];
103 for j in 0..n {
106 for i in 0..m {
107 if let Some(value) = input_matrix[i][j] {
108 row_major_constraints.push(vec![
110 (i, RB!(1)), (m + j, RB!(1)), ]);
114 b.push(RB!(value));
115 basis_columns.push(if value == column_min[j] {
116 if had_a_min[j] {
119 m + 2 * n + nr_upper_bounded_constraints
122 } else {
123 had_a_min[j] = true;
124 m + j
127 }
128 } else {
129 m + 2 * n + nr_upper_bounded_constraints
130 });
131 nr_upper_bounded_constraints += 1;
132 }
133 }
134 }
135
136 let mut nr_lower_bounded_constraints = 0;
138 let mut had_a_max = vec![false; n];
139 for j in 0..n {
140 for i in 0..m {
141 if let Some(value) = input_matrix[i][j] {
142 row_major_constraints.push(vec![(i, RB!(1)), (m + n + j, RB!(1))]);
143 b.push(RB!(value));
144 basis_columns.push(if value == column_max[j] {
145 if had_a_max[j] {
146 m + 2 * n + nr_upper_bounded_constraints + nr_lower_bounded_constraints
147 } else {
148 had_a_max[j] = true;
149 m + n + j
150 }
151 } else {
152 m + 2 * n + nr_upper_bounded_constraints + nr_lower_bounded_constraints
153 });
154 nr_lower_bounded_constraints += 1;
155 }
156 }
157 }
158
159 let mut constraints = vec![vec![]; m + 2 * n];
161 for (row_index, row) in row_major_constraints.into_iter().enumerate() {
162 for (column_index, value) in row {
163 constraints[column_index].push((row_index, value));
164 }
165 }
166 let constraints = ColumnMajor::new(constraints, nr_upper_bounded_constraints + nr_lower_bounded_constraints, m + 2 * n);
167 let b = DenseVector::new(b, nr_upper_bounded_constraints + nr_lower_bounded_constraints);
168
169 let matrix = MatrixData::new(
171 &constraints,
172 &b,
173 Vec::with_capacity(0),
174 0, 0, nr_upper_bounded_constraints, nr_lower_bounded_constraints,
175 &variables,
176 );
177
178 type IM = Carry<RationalBig, BasisInverseRows<RationalBig>>;
180 let inverse_maintainer = IM::from_basis(&basis_columns, &matrix);
181
182 let mut tableau = Tableau::<_, NonArtificial<_>>::new_with_inverse_maintainer(
185 &matrix, inverse_maintainer, basis_columns.into_iter().collect(),
186 );
187
188 let result = phase_two::primal::<_, _, FirstProfitable>(&mut tableau);
190 match result {
191 OptimizationResult::FiniteOptimum(vector) => {
192 let solution = matrix.reconstruct_solution(vector);
193 let shifts = (0..m)
194 .map(|i| match solution.get(i) {
195 None => Zero::zero(),
196 Some(value) => value.clone(),
197 })
198 .collect::<Vec<_>>();
199 println!("{:?}", shifts);
200 },
201 _ => panic!("We started with a feasible solution, and has at least value 0."),
202 }
203}