| 58 | // is passed as an argument. |
| 59 | template <class FunctionType, class StateType> |
| 60 | auto PrintProgressCallback(std::ostream& output_stream) { |
| 61 | return [&output_stream](const FunctionType& function, const StateType& state, |
| 62 | const Progress<FunctionType, StateType>& progress) { |
| 63 | const int label_width = 18; // Width for labels like "Value:", "X Delta:" |
| 64 | const int num_width = 15; // Width for numeric values |
| 65 | const int precision = 6; // Decimal places for floating-point numbers |
| 66 | |
| 67 | output_stream << std::fixed << std::setprecision(precision); |
| 68 | |
| 69 | // --- Iteration Header --- |
| 70 | output_stream << "--- Iteration: " << std::setw(5) << std::right |
| 71 | << progress.num_iterations << " ---\n"; |
| 72 | |
| 73 | // --- Function & State Information --- |
| 74 | // Read the cached value/gradient from the populated FunctionState. |
| 75 | // Fall back to one `function()` call only if the state isn't populated |
| 76 | // (e.g. first iteration with a user-supplied state that didn't go |
| 77 | // through `Solver::Minimize`'s initial evaluating constructor). |
| 78 | if constexpr (IsFunctionState<StateType>::value) { |
| 79 | const auto value = (state.gradient.size() == state.x.size()) |
| 80 | ? state.value |
| 81 | : function(state.x); |
| 82 | output_stream << std::left << std::setw(label_width) |
| 83 | << " Value:" << std::right << std::setw(num_width) << value |
| 84 | << "\n"; |
| 85 | } else { |
| 86 | output_stream << std::left << std::setw(label_width) |
| 87 | << " Value:" << std::right << std::setw(num_width) |
| 88 | << function(state.x) << "\n"; |
| 89 | } |
| 90 | |
| 91 | // Format vector/matrix output using a stringstream to avoid messing up |
| 92 | // widths easily |
| 93 | std::stringstream ss_x; |
| 94 | ss_x << state.x.transpose(); |
| 95 | |
| 96 | output_stream << std::left << std::setw(label_width) << " X:" |
| 97 | << " " << ss_x.str() << "\n"; |
| 98 | |
| 99 | // --- Gradient (Conditional) --- |
| 100 | if constexpr (FunctionType::Differentiability >= |
| 101 | cppoptlib::function::DifferentiabilityMode::First) { |
| 102 | typename FunctionType::VectorType gradient; |
| 103 | if constexpr (IsFunctionState<StateType>::value) { |
| 104 | if (state.gradient.size() == state.x.size()) { |
| 105 | gradient = state.gradient; |
| 106 | } else { |
| 107 | gradient.resize(state.x.size()); |
| 108 | function(state.x, &gradient); |
| 109 | } |
| 110 | } else { |
| 111 | gradient.resize(state.x.size()); |
| 112 | function(state.x, &gradient); |
| 113 | } |
| 114 | std::stringstream ss_grad; |
| 115 | ss_grad << gradient.transpose(); |
| 116 | output_stream << std::left << std::setw(label_width) << " Gradient:" |
| 117 | << " " << ss_grad.str() << "\n"; |
nothing calls this directly
no outgoing calls
no test coverage detected