Skip to content

Commit ff95fd3

Browse files
committed
Move logging to module level for easier user control of amount of information given (#10)
1 parent 3b65e18 commit ff95fd3

File tree

4 files changed

+49
-40
lines changed

4 files changed

+49
-40
lines changed

pybobyqa/controller.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
'EXIT_INPUT_ERROR', 'EXIT_TR_INCREASE_ERROR', 'EXIT_LINALG_ERROR', 'EXIT_FALSE_SUCCESS_WARNING',
4444
'EXIT_AUTO_DETECT_RESTART_WARNING']
4545

46+
module_logger = logging.getLogger(__name__)
47+
4648
EXIT_AUTO_DETECT_RESTART_WARNING = 4 # warning, auto-detected restart criteria
4749
EXIT_FALSE_SUCCESS_WARNING = 3 # warning, maximum fake successful steps reached
4850
EXIT_SLOW_WARNING = 2 # warning, maximum number of slow (successful) iterations reached
@@ -131,7 +133,7 @@ def npt(self):
131133

132134
def initialise_coordinate_directions(self, number_of_samples, num_directions, params):
133135
if self.do_logging:
134-
logging.debug("Initialising with coordinate directions")
136+
module_logger.debug("Initialising with coordinate directions")
135137
# self.model already has x0 evaluated, so only need to initialise the other points
136138
# num_directions = params("growing.ndirs_initial")
137139
assert self.model.num_pts <= (self.n() + 1) * (self.n() + 2) // 2, "prelim: must have npt <= (n+1)(n+2)/2"
@@ -205,7 +207,7 @@ def initialise_coordinate_directions(self, number_of_samples, num_directions, pa
205207

206208
def initialise_random_directions(self, number_of_samples, num_directions, params):
207209
if self.do_logging:
208-
logging.debug("Initialising with random orthogonal directions")
210+
module_logger.debug("Initialising with random orthogonal directions")
209211
# self.model already has x0 evaluated, so only need to initialise the other points
210212
# num_directions = params("growing.ndirs_initial")
211213
assert 1 <= num_directions < self.model.num_pts, "Initialisation: must have 1 <= ndirs_initial < npt"
@@ -282,7 +284,7 @@ def trust_region_step(self):
282284

283285
def geometry_step(self, knew, adelt, number_of_samples, params):
284286
if self.do_logging:
285-
logging.debug("Running geometry-fixing step")
287+
module_logger.debug("Running geometry-fixing step")
286288
try:
287289
c, g, H = self.model.lagrange_polynomial(knew) # based at xopt
288290
# Solve problem: bounds are sl <= xnew <= su, and ||xnew-xopt|| <= adelt
@@ -467,12 +469,12 @@ def terminate_from_slow_iterations(self, current_iter, params):
467469
if this_iter_slow:
468470
self.num_slow_iters += 1
469471
if self.do_logging:
470-
logging.info("Slow iteration (%g consecutive so far, max allowed %g)"
472+
module_logger.info("Slow iteration (%g consecutive so far, max allowed %g)"
471473
% (self.num_slow_iters, params("slow.max_slow_iters")))
472474
else:
473475
self.num_slow_iters = 0
474476
if self.do_logging:
475-
logging.debug("Non-slow iteration")
477+
module_logger.debug("Non-slow iteration")
476478
return this_iter_slow, self.num_slow_iters >= params("slow.max_slow_iters")
477479

478480
def soft_restart(self, number_of_samples, nruns_so_far, params, x_in_abs_coords_to_save=None, f_to_save=None,
@@ -507,7 +509,7 @@ def soft_restart(self, number_of_samples, nruns_so_far, params, x_in_abs_coords_
507509
self.model.nsamples[self.model.kopt], x_in_abs_coords=True)
508510

509511
if self.do_logging:
510-
logging.info("Soft restart [currently, f = %g after %g function evals]" % (self.model.fopt(), self.nf))
512+
module_logger.info("Soft restart [currently, f = %g after %g function evals]" % (self.model.fopt(), self.nf))
511513
# Resetting method: reset delta and rho, then move the closest 'num_steps' points to xk to improve geometry
512514
# Note: closest points because we are suddenly increasing delta & rho, so we want to encourage spreading out points
513515
self.delta = self.rhobeg

pybobyqa/model.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
__all__ = ['Model']
4242

4343

44+
module_logger = logging.getLogger(__name__)
45+
46+
4447
class Model(object):
4548
def __init__(self, npt, x0, f0, xl, xu, f0_nsamples, n=None, abs_tol=-1e20, precondition=True, do_logging=True):
4649
if n is None:
@@ -260,7 +263,7 @@ def solve_system(self, rhs):
260263
return col_scale(LA.lu_solve((self.lu, self.piv), col_scale(rhs, self.left_scaling)), self.right_scaling)
261264
else:
262265
if self.do_logging:
263-
logging.warning("model.solve_system not using factorisation")
266+
module_logger.warning("model.solve_system not using factorisation")
264267
A, left_scaling, right_scaling = self.interpolation_matrix()
265268
return col_scale(LA.solve(A, col_scale(rhs, left_scaling)), right_scaling)
266269

pybobyqa/solver.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
__all__ = ['solve']
4444

45+
module_logger = logging.getLogger(__name__)
46+
4547

4648
# A container for the results of the optimization routine
4749
class OptimResults(object):
@@ -149,11 +151,11 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
149151
num_directions = npt - 1
150152
if params("init.random_initial_directions"):
151153
if do_logging:
152-
logging.info("Initialising (random directions)")
154+
module_logger.info("Initialising (random directions)")
153155
exit_info = control.initialise_random_directions(number_of_samples, num_directions, params)
154156
else:
155157
if do_logging:
156-
logging.info("Initialising (coordinate directions)")
158+
module_logger.info("Initialising (coordinate directions)")
157159
exit_info = control.initialise_coordinate_directions(number_of_samples, num_directions, params)
158160
if exit_info is not None:
159161
x, f, gradmin, hessmin, nsamples = control.model.get_final_results()
@@ -174,7 +176,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
174176
# ------------------------------------------
175177
current_iter = -1
176178
if do_logging:
177-
logging.info("Beginning main loop")
179+
module_logger.info("Beginning main loop")
178180
if print_progress:
179181
print("{:^5}{:^7}{:^10}{:^10}{:^10}{:^10}{:^7}".format("Run", "Iter", "Obj", "Grad", "Delta", "rho", "Evals"))
180182
while True:
@@ -231,7 +233,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
231233
# Trust region step
232234
d, gopt, H, gnew, crvmin = control.trust_region_step()
233235
if do_logging:
234-
logging.debug("Trust region step is d = " + str(d))
236+
module_logger.debug("Trust region step is d = " + str(d))
235237
xnew = control.model.xopt() + d
236238
dnorm = min(LA.norm(d), control.delta)
237239

@@ -250,7 +252,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
250252
if dnorm < params("general.safety_step_thresh") * control.rho:
251253
# (start safety step)
252254
if do_logging:
253-
logging.debug("Safety step (main phase)")
255+
module_logger.debug("Safety step (main phase)")
254256

255257
if params("logging.save_diagnostic_info"):
256258
diagnostic_info.update_ratio(np.nan)
@@ -295,12 +297,12 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
295297
# Reduce rho
296298
control.reduce_rho(current_iter, params)
297299
if do_logging:
298-
logging.info("New rho = %g after %i function evaluations" % (control.rho, control.nf))
300+
module_logger.info("New rho = %g after %i function evaluations" % (control.rho, control.nf))
299301
if control.n() < params("logging.n_to_print_whole_x_vector"):
300-
logging.debug("Best so far: f = %.15g at x = " % (control.model.fopt())
302+
module_logger.debug("Best so far: f = %.15g at x = " % (control.model.fopt())
301303
+ str(control.model.xopt(abs_coordinates=True)))
302304
else:
303-
logging.debug("Best so far: f = %.15g at x = [...]" % (control.model.fopt()))
305+
module_logger.debug("Best so far: f = %.15g at x = [...]" % (control.model.fopt()))
304306
continue # next iteration
305307
else:
306308
# Quit on rho=rhoend
@@ -340,7 +342,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
340342
else:
341343
# (start trust region step)
342344
if do_logging:
343-
logging.debug("Standard trust region step")
345+
module_logger.debug("Standard trust region step")
344346

345347
# Add chgJ and delta to restart auto-detect set
346348
if params("restarts.use_restarts") and params("restarts.auto_detect"):
@@ -420,26 +422,26 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
420422

421423
# Update delta
422424
if do_logging:
423-
logging.debug("Ratio = %g" % ratio)
425+
module_logger.debug("Ratio = %g" % ratio)
424426
if params("logging.save_diagnostic_info"):
425427
diagnostic_info.update_ratio(ratio)
426428
diagnostic_info.update_slow_iter(-1) # n/a, unless otherwise update
427429
if ratio < params("tr_radius.eta1"): # ratio < 0.1
428430
control.delta = min(params("tr_radius.gamma_dec") * control.delta, dnorm)
429431
if params("logging.save_diagnostic_info"):
430-
# logging.info("Last eval was for unsuccessful step (ratio = %g)" % ratio)
432+
# module_logger.info("Last eval was for unsuccessful step (ratio = %g)" % ratio)
431433
diagnostic_info.update_iter_type(ITER_ACCEPTABLE_NO_GEOM if ratio > 0.0
432434
else ITER_UNSUCCESSFUL_NO_GEOM) # we flag geom update below
433435
elif ratio <= params("tr_radius.eta2"): # 0.1 <= ratio <= 0.7
434436
control.delta = max(params("tr_radius.gamma_dec") * control.delta, dnorm)
435437
if params("logging.save_diagnostic_info"):
436-
# logging.info("Last eval was for acceptable step (ratio = %g)" % ratio)
438+
# module_logger.info("Last eval was for acceptable step (ratio = %g)" % ratio)
437439
diagnostic_info.update_iter_type(ITER_SUCCESSFUL)
438440
else: # (ratio > eta2 = 0.7)
439441
control.delta = min(max(params("tr_radius.gamma_inc") * control.delta,
440442
params("tr_radius.gamma_inc_overline") * dnorm), 1.0e10)
441443
if params("logging.save_diagnostic_info"):
442-
# logging.info("Last eval was for successful step (ratio = %g)" % ratio)
444+
# module_logger.info("Last eval was for successful step (ratio = %g)" % ratio)
443445
diagnostic_info.update_iter_type(ITER_VERY_SUCCESSFUL)
444446
if control.delta <= 1.5 * control.rho: # cap trust region radius at rho
445447
control.delta = control.rho
@@ -472,7 +474,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
472474

473475
# Update point
474476
if do_logging:
475-
logging.debug("Updating with knew = %i" % knew)
477+
module_logger.debug("Updating with knew = %i" % knew)
476478
control.model.change_point(knew, xnew, f_list[0]) # expect step, not absolute x
477479
for i in range(1, num_samples_run):
478480
control.model.add_new_sample(knew, f_extra=f_list[i])
@@ -484,7 +486,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
484486
diagnostic_info.update_slow_iter(1 if this_iter_slow else 0)
485487
if should_terminate:
486488
if do_logging:
487-
logging.info("Slow iteration - terminating/restarting")
489+
module_logger.info("Slow iteration - terminating/restarting")
488490
if params("restarts.use_restarts") and params("restarts.use_soft_restarts"):
489491
number_of_samples = max(nsamples(control.delta, control.rho, current_iter, nruns_so_far), 1)
490492
exit_info = control.soft_restart(number_of_samples, nruns_so_far, params,
@@ -539,7 +541,7 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
539541
slope2, intercept2, r_value2, p_value2, std_err2 = slope, intercept, r_value, p_value, std_err
540542

541543
if do_logging:
542-
logging.debug("Iter %g: (slope, intercept, r_value) = (%g, %g, %g)" % (current_iter, slope, intercept, r_value))
544+
module_logger.debug("Iter %g: (slope, intercept, r_value) = (%g, %g, %g)" % (current_iter, slope, intercept, r_value))
543545
if min(slope, slope2) > params("restarts.auto_detect.min_chg_model_slope") \
544546
and min(r_value, r_value2) > params("restarts.auto_detect.min_correl"):
545547
# increasing trend, with at least some positive correlation
@@ -549,10 +551,10 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
549551

550552
if do_restart and params("restarts.use_soft_restarts"):
551553
if do_logging:
552-
logging.info("Auto detection: need to do a restart")
553-
logging.debug("delta history = %s" % str(restart_auto_detect_delta))
554-
logging.debug("chg_grad history = %s" % str(restart_auto_detect_chg_grad))
555-
logging.debug("chg_hess history = %s" % str(restart_auto_detect_chg_hess))
554+
module_logger.info("Auto detection: need to do a restart")
555+
module_logger.debug("delta history = %s" % str(restart_auto_detect_delta))
556+
module_logger.debug("chg_grad history = %s" % str(restart_auto_detect_chg_grad))
557+
module_logger.debug("chg_hess history = %s" % str(restart_auto_detect_chg_hess))
556558
number_of_samples = max(nsamples(control.delta, control.rho, current_iter, nruns_so_far), 1)
557559
exit_info = control.soft_restart(number_of_samples, nruns_so_far, params,
558560
x_in_abs_coords_to_save=None, f_to_save=None,
@@ -570,15 +572,15 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
570572
continue # next iteration
571573
elif do_restart:
572574
if do_logging:
573-
logging.info("Auto detection: need to do a restart")
575+
module_logger.info("Auto detection: need to do a restart")
574576
exit_info = ExitInformation(EXIT_AUTO_DETECT_RESTART_WARNING, "Auto-detected restart")
575577
nruns_so_far += 1
576578
break # quit
577579
# If not doing restart, just continue as below (geom steps, etc.)
578580

579581
# Otherwise (ratio < eta1 = 0.1), check & fix geometry
580582
if do_logging:
581-
logging.debug("Checking and possibly improving geometry (unsuccessful step)")
583+
module_logger.debug("Checking and possibly improving geometry (unsuccessful step)")
582584
distsq = max((2.0 * control.delta) ** 2, (10.0 * control.rho) ** 2)
583585
update_delta = False
584586
number_of_samples = max(nsamples(control.delta, control.rho, current_iter, nruns_so_far), 1)
@@ -624,12 +626,12 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
624626
# Reduce rho
625627
control.reduce_rho(current_iter, params)
626628
if do_logging:
627-
logging.info("New rho = %g after %i function evaluations" % (control.rho, control.nf))
629+
module_logger.info("New rho = %g after %i function evaluations" % (control.rho, control.nf))
628630
if control.n() < params("logging.n_to_print_whole_x_vector"):
629-
logging.debug("Best so far: f = %.15g at x = " % (control.model.fopt())
631+
module_logger.debug("Best so far: f = %.15g at x = " % (control.model.fopt())
630632
+ str(control.model.xopt(abs_coordinates=True)))
631633
else:
632-
logging.debug("Best so far: f = %.15g at x = [...]" % (control.model.fopt()))
634+
module_logger.debug("Best so far: f = %.15g at x = [...]" % (control.model.fopt()))
633635
continue # next iteration
634636
else:
635637
# Quit on rho=rhoend
@@ -658,8 +660,8 @@ def solve_main(objfun, x0, args, xl, xu, npt, rhobeg, rhoend, maxfun, nruns_so_f
658660
# Quit & return the important information
659661
x, f, gradmin, hessmin, nsamples = control.model.get_final_results()
660662
if do_logging:
661-
logging.debug("At return from solver, number of function evals = %i" % nf)
662-
logging.debug("Smallest objective value = %.15g at x = " % f + str(x))
663+
module_logger.debug("At return from solver, number of function evals = %i" % nf)
664+
module_logger.debug("Smallest objective value = %.15g at x = " % f + str(x))
663665
return x, f, gradmin, hessmin, nsamples, control.nf, control.nx, nruns_so_far, exit_info, diagnostic_info
664666

665667

@@ -823,7 +825,7 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8,
823825
if not reduction_last_run:
824826
_rhobeg = _rhobeg * params("restarts.rhobeg_scale_after_unsuccessful_restart")
825827

826-
logging.info("Restarting from finish point (f = %g) after %g function evals; using rhobeg = %g and rhoend = %g"
828+
module_logger.info("Restarting from finish point (f = %g) after %g function evals; using rhobeg = %g and rhoend = %g"
827829
% (fmin, nf, _rhobeg, _rhoend))
828830
if params("restarts.hard.use_old_fk"):
829831
xmin2, fmin2, gradmin2, hessmin2, nsamples2, nf, nx, nruns, exit_info, diagnostic_info = \
@@ -835,7 +837,7 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8,
835837
diagnostic_info, scaling_changes, do_logging=do_logging, print_progress=print_progress)
836838

837839
if fmin2 < fmin or np.isnan(fmin):
838-
logging.info("Successful run with new f = %s compared to old f = %s" % (fmin2, fmin))
840+
module_logger.info("Successful run with new f = %s compared to old f = %s" % (fmin2, fmin))
839841
last_successful_run = nruns
840842
(xmin, fmin, nsamples_min) = (xmin2, fmin2, nsamples2)
841843
if gradmin2 is not None: # may be None if finished during setup phase, in which case just use old gradient
@@ -844,7 +846,7 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8,
844846
hessmin = hessmin2
845847
reduction_last_run = True
846848
else:
847-
logging.info("Unsuccessful run with new f = %s compared to old f = %s" % (fmin2, fmin))
849+
module_logger.info("Unsuccessful run with new f = %s compared to old f = %s" % (fmin2, fmin))
848850
reduction_last_run = False
849851
total_unsuccessful_restarts += 1
850852

@@ -868,7 +870,7 @@ def solve(objfun, x0, args=(), bounds=None, npt=None, rhobeg=None, rhoend=1e-8,
868870
results.diagnostic_info = df
869871

870872
if do_logging:
871-
logging.info("Did a total of %g run(s)" % nruns)
873+
module_logger.info("Did a total of %g run(s)" % nruns)
872874

873875
return results
874876

pybobyqa/util.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
__all__ = ['sumsq', 'eval_objective', 'model_value', 'random_orthog_directions_within_bounds',
3434
'random_directions_within_bounds', 'apply_scaling', 'remove_scaling']
3535

36+
module_logger = logging.getLogger(__name__)
37+
3638

3739
def sumsq(x):
3840
# There are several ways to calculate sum of squares of a vector:
@@ -56,9 +58,9 @@ def eval_objective(objfun, x, args=(), verbose=True, eval_num=0, pt_num=0, full_
5658

5759
if verbose:
5860
if len(x) < full_x_thresh:
59-
logging.info("Function eval %i at point %i has f = %.15g at x = " % (eval_num, pt_num, f) + str(x))
61+
module_logger.info("Function eval %i at point %i has f = %.15g at x = " % (eval_num, pt_num, f) + str(x))
6062
else:
61-
logging.info("Function eval %i at point %i has f = %.15g at x = [...]" % (eval_num, pt_num, f))
63+
module_logger.info("Function eval %i at point %i has f = %.15g at x = [...]" % (eval_num, pt_num, f))
6264

6365
return f
6466

0 commit comments

Comments
 (0)