A helper class that prints relevant solver progress information to the console, if desired. Parameters ---------- should_print Whether to print information to the console. When ``False``, nothing is printed. display_interval Time (in seconds) between
| 36 | |
| 37 | |
| 38 | class ProgressPrinter: |
| 39 | """ |
| 40 | A helper class that prints relevant solver progress information to the |
| 41 | console, if desired. |
| 42 | |
| 43 | Parameters |
| 44 | ---------- |
| 45 | should_print |
| 46 | Whether to print information to the console. When ``False``, nothing is |
| 47 | printed. |
| 48 | display_interval |
| 49 | Time (in seconds) between iteration logs. |
| 50 | """ |
| 51 | |
| 52 | def __init__(self, should_print: bool, display_interval: float): |
| 53 | if display_interval < 0: |
| 54 | raise ValueError("Expected display_interval >= 0.") |
| 55 | |
| 56 | self._print = should_print |
| 57 | self._display_interval = display_interval |
| 58 | self._last_print_time = perf_counter() |
| 59 | self._best_cost = float("inf") |
| 60 | |
| 61 | def iteration(self, stats: Statistics): |
| 62 | """ |
| 63 | Outputs relevant information every few seconds. The output contains |
| 64 | information about the (penalised) cost and feasibility of the current, |
| 65 | candidate, and best solutions, as well as the search duration. |
| 66 | """ |
| 67 | curr_time = perf_counter() |
| 68 | interval = curr_time - self._last_print_time |
| 69 | should_print = ( |
| 70 | self._print |
| 71 | and stats.is_collecting() |
| 72 | and interval >= self._display_interval |
| 73 | ) |
| 74 | |
| 75 | if not should_print: |
| 76 | return |
| 77 | |
| 78 | datum = stats.data[-1] |
| 79 | new_best = datum.best_feas and datum.best_cost < self._best_cost |
| 80 | msg = _ITERATION.format( |
| 81 | special="H" if new_best else " ", |
| 82 | iters=stats.num_iterations, |
| 83 | elapsed=round(sum(stats.runtimes)), |
| 84 | curr=datum.current_cost, |
| 85 | curr_feas="Y" if datum.current_feas else "N", |
| 86 | cand=datum.candidate_cost, |
| 87 | cand_feas="Y" if datum.candidate_feas else "N", |
| 88 | best=datum.best_cost, |
| 89 | best_feas="Y" if datum.best_feas else "N", |
| 90 | ) |
| 91 | |
| 92 | logger.info(msg) |
| 93 | |
| 94 | self._last_print_time = curr_time |
| 95 | if new_best: |
no outgoing calls