scirs2_vision/registration/
optimization.rs1use crate::error::Result;
4use scirs2_core::ndarray::Array1;
5
6#[derive(Debug, Clone)]
8pub struct OptimizationResult {
9 pub parameters: Array1<f64>,
11 pub final_cost: f64,
13 pub iterations: usize,
15 pub converged: bool,
17}
18
19#[allow(dead_code)]
21pub fn gradient_descent_optimize(
22 initialparams: &Array1<f64>,
23 cost_function: &dyn Fn(&Array1<f64>) -> Result<f64>,
24 gradient_function: &dyn Fn(&Array1<f64>) -> Result<Array1<f64>>,
25 learning_rate: f64,
26 maxiterations: usize,
27 tolerance: f64,
28) -> Result<OptimizationResult> {
29 use scirs2_core::ndarray::Zip;
30
31 let mut params = initialparams.clone();
32 let mut prev_cost = cost_function(¶ms)?;
33 let mut converged = false;
34 let mut iterations = 0;
35
36 for i in 0..maxiterations {
37 iterations = i + 1;
38
39 let gradient = gradient_function(¶ms)?;
41
42 Zip::from(&mut params)
44 .and(&gradient)
45 .for_each(|p, &g| *p -= learning_rate * g);
46
47 let current_cost = cost_function(¶ms)?;
49
50 if (prev_cost - current_cost).abs() < tolerance {
52 converged = true;
53 break;
54 }
55
56 if current_cost > prev_cost {
58 }
61
62 prev_cost = current_cost;
63 }
64
65 Ok(OptimizationResult {
66 parameters: params,
67 final_cost: prev_cost,
68 iterations,
69 converged,
70 })
71}
72
73#[allow(dead_code)]
75pub fn powell_optimize(
76 initialparams: &Array1<f64>,
77 cost_function: &dyn Fn(&Array1<f64>) -> Result<f64>,
78 maxiterations: usize,
79 tolerance: f64,
80) -> Result<OptimizationResult> {
81 let n = initialparams.len();
82 let mut params = initialparams.clone();
83 let mut directions = scirs2_core::ndarray::Array2::eye(n);
84 let mut converged = false;
85 let mut iterations = 0;
86 let mut prev_cost = cost_function(¶ms)?;
87
88 for iter in 0..maxiterations {
89 iterations = iter + 1;
90 let startparams = params.clone();
91 let mut biggest_decrease = 0.0;
92 let mut biggest_decrease_idx = 0;
93
94 for i in 0..n {
96 let old_cost = cost_function(¶ms)?;
97 let direction = directions.row(i).to_owned();
98
99 let (newparams, new_cost) = line_search(¶ms, &direction, cost_function, 1e-6)?;
101 params = newparams;
102
103 let decrease = old_cost - new_cost;
104 if decrease > biggest_decrease {
105 biggest_decrease = decrease;
106 biggest_decrease_idx = i;
107 }
108 }
109
110 let current_cost = cost_function(¶ms)?;
112 if (prev_cost - current_cost).abs() < tolerance {
113 converged = true;
114 break;
115 }
116
117 if iter > 0 && iter % n == 0 {
119 let new_direction = ¶ms - &startparams;
121 let new_dir_norm = new_direction.dot(&new_direction).sqrt();
122
123 if new_dir_norm > 1e-10 {
124 let normalized_dir = &new_direction / new_dir_norm;
126 directions
127 .row_mut(biggest_decrease_idx)
128 .assign(&normalized_dir);
129
130 let (newparams_, _) = line_search(¶ms, &normalized_dir, cost_function, 1e-6)?;
132 params = newparams_;
133 }
134 }
135
136 prev_cost = current_cost;
137 }
138
139 Ok(OptimizationResult {
140 parameters: params,
141 final_cost: prev_cost,
142 iterations,
143 converged,
144 })
145}
146
147#[allow(dead_code)]
149fn line_search(
150 start_point: &Array1<f64>,
151 direction: &Array1<f64>,
152 cost_function: &dyn Fn(&Array1<f64>) -> Result<f64>,
153 tolerance: f64,
154) -> Result<(Array1<f64>, f64)> {
155 const GOLDEN_RATIO: f64 = 0.618033988749895;
157
158 let mut a = 0.0;
160 let mut b = 1.0;
161 let mut c = a + GOLDEN_RATIO * (b - a);
162 let mut d = b - GOLDEN_RATIO * (b - a);
163
164 let mut fc = cost_function(&(start_point + c * direction))?;
166 let mut fd = cost_function(&(start_point + d * direction))?;
167
168 while (b - a).abs() > tolerance {
170 if fc < fd {
171 b = d;
172 d = c;
173 fd = fc;
174 c = a + GOLDEN_RATIO * (b - a);
175 fc = cost_function(&(start_point + c * direction))?;
176 } else {
177 a = c;
178 c = d;
179 fc = fd;
180 d = b - GOLDEN_RATIO * (b - a);
181 fd = cost_function(&(start_point + d * direction))?;
182 }
183 }
184
185 let alpha = (a + b) / 2.0;
187 let optimal_point = start_point + alpha * direction;
188 let optimal_cost = cost_function(&optimal_point)?;
189
190 Ok((optimal_point, optimal_cost))
191}