1use super::subproblem::{compute_step, Subproblem};
2use crate::kernel::Kernel;
3use crate::problem::DualProblem;
4use crate::status::Status;
5
6pub fn update(
7 problem: &dyn DualProblem,
8 kernel: &mut dyn Kernel,
9 idx_i: usize,
10 idx_j: usize,
11 status: &mut Status,
12 active_set: &Vec<usize>,
13) {
14 let i = active_set[idx_i];
15 let j = active_set[idx_j];
16 kernel.use_rows([i, j].as_slice(), &active_set, &mut |kij: Vec<&[f64]>| {
17 let ki = kij[0];
18 let kj = kij[1];
19 let mut max_tij = f64::min(status.a[i] - problem.lb(i), problem.ub(j) - status.a[j]);
20
21 let max_t_asum = 0.5 * (problem.max_asum() - status.asum);
22 let update_asum = if problem.has_max_asum() {
23 if problem.sign(i) != problem.sign(j) {
24 if max_tij > max_t_asum {
25 max_tij = max_t_asum;
26 }
27 true
28 } else {
29 false
30 }
31 } else {
32 false
33 };
34 let step = compute_step(
35 problem,
36 Subproblem {
37 ij: (i, j),
38 max_t: max_tij,
39 q0: (ki[idx_i] + kj[idx_j] - 2.0 * ki[idx_j]) / problem.lambda(),
40 p0: status.ka[i] - status.ka[j],
41 },
42 &status,
43 );
44
45 let t = step.t;
46 if update_asum {
47 if t == max_t_asum {
48 status.asum = problem.max_asum();
49 } else {
50 status.asum -= 2.0 * t * problem.sign(i);
51 }
52 }
53 status.a[i] -= t;
54 status.a[j] += t;
55 status.value -= step.dvalue;
56 for (idx, &k) in active_set.iter().enumerate() {
57 status.ka[k] += t / problem.lambda() * (kj[idx] - ki[idx]);
58 }
59 });
60}