rusvm/smo/
update.rs

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}