47 #include <Eigen/Dense>
48 #include <glog/logging.h>
138 nmiPiano(
const std::function<
float(
const Eigen::MatrixXf&)> f,
139 const std::function<
void(
const Eigen::MatrixXf&, Eigen::MatrixXf&)> df,
140 std::function<
float(
const Eigen::MatrixXf&)> g,
141 const std::function<
void(
const Eigen::MatrixXf&, Eigen::MatrixXf&,
float alpha)> prox_g,
143 const std::function<
void(
const Iteration&)> callback = [](
const Iteration &iteration) ->
void { });
152 void optimize(Eigen::MatrixXf &x_star,
float &f_x_star);
161 float estimateL(
const Iteration &iteration);
168 void iterate(Iteration &iteration,
float beta, Eigen::MatrixXf &x_np1);
175 bool checkLipschitz(
const Iteration& iteration,
const Eigen::MatrixXf &x_np1);
178 std::function<float(const Eigen::MatrixXf&)>
f_;
180 std::function<void(const Eigen::MatrixXf&, Eigen::MatrixXf&)>
df_;
182 std::function<float(const Eigen::MatrixXf&)>
g_;
184 std::function<void(const Eigen::MatrixXf&, Eigen::MatrixXf&, float)>
prox_g_;
206 if (iteration.
n%n == 0)
208 std::cout <<
"[" << iteration.
n <<
"] "
210 <<
" (Delta_n = " << iteration.
Delta_n <<
"; L_n = " << iteration.
L_n
211 <<
"; alpha_n = " << iteration.
alpha_n <<
")"
222 if (iteration.
n%n == 0)
224 std::cout <<
"[" << iteration.
n <<
"] "
226 <<
" (Delta_n = " << iteration.
Delta_n <<
")"
238 out.open(file, std::ios_base::app);
239 out <<
"iteration = " << iteration.
n <<
"; f_x_n = " << iteration.
f_x_n
240 <<
"; g_x_n = " << iteration.
g_x_n <<
"; alpha_n = " << iteration.
alpha_n
241 <<
"; L_n = " << iteration.
L_n
242 <<
"; |df_x_n| = " << std::sqrt(iteration.
df_x_n.squaredNorm())
243 <<
"; Delta_n = " << iteration.
Delta_n << std::endl;
254 out.open(file, std::ios_base::app);
255 out << iteration.
n <<
"," << iteration.
f_x_n + iteration.
g_x_n
256 <<
"," << iteration.
f_x_n <<
"," << iteration.
g_x_n
257 <<
"," << iteration.
alpha_n <<
"," << iteration.
L_n
258 <<
"," << iteration.
Delta_n << std::endl;
267 const std::function<
void(
const Eigen::MatrixXf&,Eigen::MatrixXf&)> df,
268 std::function<
float(
const Eigen::MatrixXf &)> g,
269 const std::function<
void(
const Eigen::MatrixXf&, Eigen::MatrixXf&,
float alpha)> prox_g,
300 Eigen::MatrixXf x_np1;
307 float L_nm1 = estimateL(iteration);
312 LOG_IF(INFO, !
options_.
BOUND_L_N) <<
"Could not get starting value for local Lipschitz constant, using L_nm1 instead (L_n = " << L_nm1 <<
")";
313 L_nm1 = iteration.
L_n;
316 bool condition =
false;
323 LOG_IF(FATAL, std::isinf(iteration.
L_n) || std::isnan(iteration.
L_n))
324 <<
"Could not find the local Lipschitz constant - L_n = "
325 << iteration.
L_n << std::endl;
326 LOG_IF(INFO, l > 0 && l%1000 == 0)
327 <<
"Having a hard time finding the local Lipschitz constant (L_n = " << iteration.
L_n
328 <<
"; L_nm1 = " << L_nm1 <<
"; eta = " <<
options_.
eta <<
"; l = " << l <<
")" << std::endl;
331 LOG_IF(FATAL, iteration.
alpha_n < 0)
332 <<
"Cannot choose alpha_n - it does not exist: alpha_n = "
333 << iteration.
alpha_n <<
" (L_n = " << iteration.
L_n <<
")!";
346 iteration.
x_n = x_np1;
353 LOG_IF(FATAL, iteration.
x_n.rows() != iteration.
df_x_n.rows()
354 || iteration.
x_n.cols() != iteration.
df_x_n.cols()) <<
"Output dimensions of df invalid.";
365 x_star = iteration.
x_n;
366 f_x_star = iteration.
f_x_n;
383 LOG_IF(FATAL, iteration.
x_n.rows() != iteration.
df_x_n.rows()
384 || iteration.
x_n.cols() != iteration.
df_x_n.cols()) <<
"Output dimensions of df invalid.";
395 if (iteration.
df_x_n.squaredNorm() > 0.001)
397 iteration.
L_n = std::max(iteration.
L_n, estimateL(iteration));
405 Eigen::MatrixXf x_tilde = iteration.
x_n - iteration.
alpha_n*iteration.
df_x_n;
407 Eigen::MatrixXf df_x_tilde;
408 df_(x_tilde, df_x_tilde);
410 Eigen::MatrixXf delta_df_x = iteration.
df_x_n - df_x_tilde;
411 Eigen::MatrixXf delta_x = iteration.
x_n - x_tilde;
413 float L_n = std::sqrt(delta_df_x.squaredNorm())/std::sqrt(delta_x.squaredNorm ());
432 LOG_IF(FATAL, iteration.
x_n.rows() != x_np1.rows()
433 || iteration.
x_n.cols() != x_np1.cols()) <<
"Output dimensions of prox_g invalid.";
435 Eigen::MatrixXf Delta_n = iteration.
x_n - x_np1;
436 iteration.
Delta_n = std::sqrt(Delta_n.squaredNorm());
445 float f_x_np1 =
f_(x_np1);
447 Eigen::MatrixXf residual = x_np1 - iteration.
x_n;
448 Eigen::MatrixXf product = iteration.
df_x_n.array()*residual.array();
449 float threshold = iteration.
f_x_n + product.squaredNorm() + iteration.
L_n/2.f * residual.squaredNorm();
451 return (f_x_np1 <= threshold);
float L_n
L_n of current iterate (within iterations, this is also used to estimate L_np1 via backtracking)...
Definition: nmipiano.h:98
std::function< float(const Eigen::MatrixXf &)> g_
Convex, nonsmooth part of objective.
Definition: nmipiano.h:182
float f_x_n
Smooth objective function at current iterate.
Definition: nmipiano.h:92
Eigen::MatrixXf Delta_x_n
Update: x_np1 = x_n + Delta_x_n.
Definition: nmipiano.h:88
~nmiPiano()
Destructor.
Definition: nmipiano.h:285
void optimize(Eigen::MatrixXf &x_star, float &f_x_star)
Optimize the given objective using the nmiPiano algorithm.
Definition: nmipiano.h:294
Implementation of nmiPiano (algorithm 4) as proposed in [1]: [1] P. Ochs, Y. Chen, T. Brox, T. Pock. iPiano: Inertial Proximal Algorithm for Nonconvex Optimization. SIAM J. Imaging Sciences, vol. 7, no. 2, 2014.
Definition: nmipiano.h:56
int n
Current iteration.
Definition: nmipiano.h:102
void initialize(Iteration &iteration)
Initialize the iteration structure (i.e. set iteration 0):
Definition: nmipiano.h:373
float epsilon
Termination criterion; stop if Delta_n smaller than epsilon.
Definition: nmipiano.h:76
Eigen::MatrixXf df_x_n
Derivative of smooth objective at current iterate.
Definition: nmipiano.h:94
static void file_callback(const Iteration &iteration, const std::string &file)
File callback, used to write all information to the specified file.
Definition: nmipiano.h:235
float eta
Fixed eta for backtracking the local lipschitz constant.
Definition: nmipiano.h:70
std::function< void(const Eigen::MatrixXf &, Eigen::MatrixXf &)> df_
Gradient of smooth part of the objective function (i.e. derivative).
Definition: nmipiano.h:180
static void brief_callback(const Iteration &iteration, int n=10)
Brief callback to use with nmiPiano.
Definition: nmipiano.h:220
static void default_callback(const Iteration &iteration, int n=10)
Default callback to use with nmiPiano.
Definition: nmipiano.h:204
static void plot_callback(const Iteration &iteration, const std::string &file)
File callback for plotting, writes CSV output of format: iteration,f,g,alpha_n,L_n,Delta_n.
Definition: nmipiano.h:251
float beta
Fixed beta in [0, 1).
Definition: nmipiano.h:68
void iterate(Iteration &iteration, float beta, Eigen::MatrixXf &x_np1)
Do an iteration, i.e. compute x_np1.
Definition: nmipiano.h:425
static void silent_callback(const Iteration &iteration)
Silent callback to use with nmiPiano.
Definition: nmipiano.h:195
Eigen::MatrixXf x_nm1
Last iterate.
Definition: nmipiano.h:86
std::function< void(const Eigen::MatrixXf &, Eigen::MatrixXf &, float)> prox_g_
Proximal map for g, i.e. (I + alpha_n*g)^(-1).
Definition: nmipiano.h:184
float alpha_n
alpha_n of current iterate (within iterations, this is also used to estimate alpha_np1).
Definition: nmipiano.h:100
bool checkLipschitz(const Iteration &iteration, const Eigen::MatrixXf &x_np1)
Check the lipschitz condition for backtracking.
Definition: nmipiano.h:443
float g_x_n
Definition: nmipiano.h:96
Eigen::MatrixXf x_0
Initial iterate.
Definition: nmipiano.h:64
unsigned int max_iter
Maximum number of iterations.
Definition: nmipiano.h:66
Options options_
Options.
Definition: nmipiano.h:188
std::function< float(const Eigen::MatrixXf &)> f_
The smooth part of the objective function.
Definition: nmipiano.h:178
float Delta_n
Difference between two iterates.
Definition: nmipiano.h:90
std::function< void(const Iteration &)> callback_
Callback, can e.g. be sued to monitor process using the provided information in the Iteration structu...
Definition: nmipiano.h:186
Options of algorithm.
Definition: nmipiano.h:61
Eigen::MatrixXf x_n
Current iterate.
Definition: nmipiano.h:84
float L_0m1
Initialization of loca Lipschitz.
Definition: nmipiano.h:72
bool BOUND_L_N
Whether to bound estimated Lipschitz constant below by the given L_n.
Definition: nmipiano.h:74
nmiPiano(const std::function< float(const Eigen::MatrixXf &)> f, const std::function< void(const Eigen::MatrixXf &, Eigen::MatrixXf &)> df, std::function< float(const Eigen::MatrixXf &)> g, const std::function< void(const Eigen::MatrixXf &, Eigen::MatrixXf &, float alpha)> prox_g, Options options, const std::function< void(const Iteration &)> callback=[](const Iteration &iteration) -> void{})
Constructor.
Definition: nmipiano.h:266
Structure representing an iteration, passed as is to a callback function to be able to monitor proces...
Definition: nmipiano.h:81