44
55#include < spdlog/spdlog.h>
66
7- #include < cfenv>
8-
97namespace polysolve ::nonlinear::line_search
108{
119
@@ -20,58 +18,68 @@ namespace polysolve::nonlinear::line_search
2018 Problem &objFunc,
2119 const bool use_grad_norm,
2220 const double old_energy,
21+ const TVector &old_grad,
2322 const double starting_step_size)
2423 {
2524 double step_size = starting_step_size;
2625
27- TVector grad (x. rows () );
26+ init_compute_descent_step_size (delta_x, old_grad );
2827
29- // Find step that reduces the energy
30- double cur_energy = std::nan (" " );
31- bool is_step_valid = false ;
32- while (step_size > current_min_step_size () && cur_iter < current_max_step_size_iter ())
28+ for (; step_size > current_min_step_size () && cur_iter < current_max_step_size_iter (); step_size *= step_ratio, ++cur_iter)
3329 {
34- TVector new_x = x + step_size * delta_x;
30+ const TVector new_x = x + step_size * delta_x;
3531
3632 try
3733 {
38- POLYSOLVE_SCOPED_STOPWATCH (" solution changed - constraint set update in LS" , this -> constraint_set_update_time , m_logger);
34+ POLYSOLVE_SCOPED_STOPWATCH (" solution changed - constraint set update in LS" , constraint_set_update_time, m_logger);
3935 objFunc.solution_changed (new_x);
4036 }
4137 catch (const std::runtime_error &e)
4238 {
4339 m_logger.warn (" Failed to take step due to \" {}\" , reduce step size..." , e.what ());
44-
45- step_size *= step_ratio;
46- this ->cur_iter ++;
4740 continue ;
4841 }
4942
50- if (use_grad_norm )
43+ if (!objFunc. is_step_valid (x, new_x) )
5144 {
52- objFunc.gradient (new_x, grad);
53- cur_energy = grad.squaredNorm ();
45+ continue ;
5446 }
55- else
56- cur_energy = objFunc.value (new_x);
5747
58- is_step_valid = objFunc.is_step_valid (x, new_x);
48+ const double new_energy = objFunc.value ( new_x);
5949
60- m_logger.trace (" ls it: {} delta: {} invalid: {} " , this ->cur_iter , (cur_energy - old_energy), !is_step_valid);
61-
62- if (!std::isfinite (cur_energy) || cur_energy >= old_energy || !is_step_valid)
50+ if (!std::isfinite (new_energy))
6351 {
64- step_size *= step_ratio;
65- // max_step_size should return a collision free step
66- // assert(objFunc.is_step_collision_free(x, new_x));
52+ continue ;
6753 }
68- else
54+
55+ m_logger.trace (" ls it: {} ΔE: {}" , cur_iter, new_energy - old_energy);
56+
57+ if (criteria (delta_x, objFunc, use_grad_norm, old_energy, old_grad, new_x, new_energy, step_size))
6958 {
70- break ;
59+ break ; // found a good step size
7160 }
72- this ->cur_iter ++;
7361 }
7462
7563 return step_size;
7664 }
65+
66+ bool Backtracking::criteria (
67+ const TVector &delta_x,
68+ Problem &objFunc,
69+ const bool use_grad_norm,
70+ const double old_energy,
71+ const TVector &old_grad,
72+ const TVector &new_x,
73+ const double new_energy,
74+ const double step_size) const
75+ {
76+ if (use_grad_norm)
77+ {
78+ TVector new_grad;
79+ objFunc.gradient (new_x, new_grad);
80+ return new_grad.norm () < old_grad.norm (); // TODO: cache old_grad.norm()
81+ }
82+ return new_energy < old_energy;
83+ }
84+
7785} // namespace polysolve::nonlinear::line_search
0 commit comments