-
-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] Powell's algorithm #234
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use crate::core::{ | ||
ArgminFloat, CostFunction, DeserializeOwnedAlias, Executor, IterState, LineSearch, | ||
OptimizationResult, SerializeAlias, Solver, State, | ||
}; | ||
use argmin_math::{ArgminAdd, ArgminDot, ArgminSub, ArgminZeroLike}; | ||
#[cfg(feature = "serde1")] | ||
use serde::{Deserialize, Serialize}; | ||
use std::mem; | ||
|
||
#[derive(Clone)] | ||
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] | ||
pub struct PowellLineSearch<P, L> { | ||
search_vectors: Vec<P>, | ||
linesearch: L, | ||
} | ||
|
||
impl<P, L> PowellLineSearch<P, L> { | ||
pub fn new(initial_search_vectors: Vec<P>, linesearch: L) -> Self { | ||
PowellLineSearch { | ||
search_vectors: initial_search_vectors, | ||
linesearch, | ||
} | ||
} | ||
} | ||
|
||
impl<O, P, F, L> Solver<O, IterState<P, (), (), (), F>> for PowellLineSearch<P, L> | ||
where | ||
O: CostFunction<Param = P, Output = F>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the problem is passed to a line search as well, you'll probably also require There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe one of the advantages of Powell's method is that it doesn't need gradients. I thought that as long as the linesearch method is given a direction to search along it doesn't need gradients to be computed, i.e. the calculation of gradients should be independent from the linesearch algorith, which only searches along a provided search direction. However, I could be wrong, but I can just write tests and see if it works. I will also implement a version of this using golden section search and brent's method. |
||
P: Clone | ||
+ SerializeAlias | ||
+ DeserializeOwnedAlias | ||
+ ArgminAdd<P, P> | ||
+ ArgminZeroLike | ||
+ ArgminSub<P, P> | ||
+ ArgminDot<P, F>, | ||
F: ArgminFloat, | ||
L: Clone + LineSearch<P, F> + Solver<O, IterState<P, (), (), (), F>>, | ||
{ | ||
const NAME: &'static str = "Powell-LS"; | ||
|
||
fn next_iter( | ||
&mut self, | ||
problem: &mut crate::core::Problem<O>, | ||
mut state: IterState<P, (), (), (), F>, | ||
) -> Result<(IterState<P, (), (), (), F>, Option<crate::core::KV>), anyhow::Error> { | ||
Trombach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let param = state | ||
.take_param() | ||
.ok_or_else(argmin_error_closure!(NotInitialized, "not initialized"))?; // TODO add Error message | ||
|
||
// new displacement vector created from displacement vectors of line searches | ||
let new_displacement = param.zero_like(); | ||
let mut best_direction: (usize, F) = (0, float!(0.0)); | ||
|
||
// init line search | ||
let (ls_state, _) = self.linesearch.init(problem, state.clone())?; | ||
Trombach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Loop over all search vectors and perform line optimization along each search direction | ||
for (i, search_vector) in self.search_vectors.iter().enumerate() { | ||
self.linesearch.search_direction(search_vector.clone()); | ||
|
||
let line_cost = ls_state.get_cost(); | ||
Trombach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Run solver | ||
let OptimizationResult { | ||
problem: _sub_problem, | ||
state: sub_state, | ||
.. | ||
} = Executor::new(problem.take_problem().unwrap(), self.linesearch.clone()) | ||
Trombach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.configure(|state| state.param(param.clone()).cost(line_cost)) | ||
.ctrlc(false) | ||
.run()?; | ||
|
||
// update new displacement vector | ||
let displacement = &sub_state.get_best_param().unwrap().sub(¶m); | ||
let displacement_magnitude = displacement.dot(&displacement).sqrt(); | ||
new_displacement.add(displacement); | ||
Trombach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
//store index of lowest cost displacement vector | ||
if best_direction.1 < displacement_magnitude { | ||
best_direction.0 = i; | ||
best_direction.1 = displacement_magnitude; | ||
} | ||
} | ||
|
||
// replace best performing search direction with new search direction | ||
let _ = mem::replace( | ||
&mut self.search_vectors[best_direction.0], | ||
new_displacement.clone(), | ||
); | ||
|
||
// set new parameters | ||
let param = param.add(&new_displacement); | ||
let cost = problem.cost(¶m); | ||
|
||
Ok((state.param(param).cost(cost?), None)) | ||
Trombach marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Copyright notice is missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks will add this before the PR is final. Leaving this unresolved as a reminder for myself :)