diff --git a/src/gui/src/grid_window.cpp b/src/gui/src/grid_window.cpp index 8c681e5..d0a69ef 100644 --- a/src/gui/src/grid_window.cpp +++ b/src/gui/src/grid_window.cpp @@ -17,10 +17,10 @@ #include -GridWindow::LineEvent::LineEvent(picross::ObserverEvent event, const picross::Line* line, unsigned int misc, const ObserverGrid& grid) +GridWindow::LineEvent::LineEvent(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data, const ObserverGrid& grid) : m_event(event) , m_line_id() - , m_misc(misc) + , m_data(data) , m_grid(grid) { if (line) { m_line_id = std::make_optional(*line); } @@ -310,7 +310,7 @@ void GridWindow::reset_solutions() text_buffer->buffer.appendf("Grid %s\n", picross::str_input_grid_size(grid).c_str()); } -void GridWindow::observer_callback(picross::ObserverEvent event, const picross::Line* line, unsigned int, unsigned int misc, const ObserverGrid& l_grid) +void GridWindow::observer_callback(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data, const ObserverGrid& l_grid) { // Filter out events useless to the GUI if (event != picross::ObserverEvent::DELTA_LINE && event != picross::ObserverEvent::SOLVED_GRID && event != picross::ObserverEvent::PROGRESS) @@ -329,7 +329,7 @@ void GridWindow::observer_callback(picross::ObserverEvent event, const picross:: || this->abort_solver_thread(); }); } - line_events.emplace_back(event, line, misc, l_grid); + line_events.emplace_back(event, line, data, l_grid); } unsigned int GridWindow::process_line_events(std::vector& events) @@ -343,7 +343,7 @@ unsigned int GridWindow::process_line_events(std::vector& events) if (event.m_event == picross::ObserverEvent::PROGRESS) { // Only indicative - solver_progress = reinterpret_cast(static_cast(event.m_misc)); + solver_progress = event.m_data.m_misc_f; continue; } assert(event.m_event == picross::ObserverEvent::DELTA_LINE || event.m_event == picross::ObserverEvent::SOLVED_GRID); diff --git a/src/gui/src/grid_window.h b/src/gui/src/grid_window.h index 11ae5a4..3d943a8 100644 --- a/src/gui/src/grid_window.h +++ b/src/gui/src/grid_window.h @@ -23,11 +23,11 @@ class GridWindow : public GridObserver public: struct LineEvent { - LineEvent(picross::ObserverEvent event, const picross::Line* line, unsigned int misc, const ObserverGrid& grid); + LineEvent(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data, const ObserverGrid& grid); picross::ObserverEvent m_event; std::optional m_line_id; - unsigned int m_misc; + picross::ObserverData m_data; ObserverGrid m_grid; }; public: @@ -42,7 +42,7 @@ class GridWindow : public GridObserver private: void reset_solutions(); - void observer_callback(picross::ObserverEvent event, const picross::Line* line, unsigned int, unsigned int, const ObserverGrid& grid) override; + void observer_callback(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data, const ObserverGrid& grid) override; unsigned int process_line_events(std::vector& events); void solve_picross_grid(); void save_grid(); diff --git a/src/picross/include/picross/picross_observer.h b/src/picross/include/picross/picross_observer.h index ab77590..b613a30 100644 --- a/src/picross/include/picross/picross_observer.h +++ b/src/picross/include/picross/picross_observer.h @@ -9,6 +9,7 @@ ******************************************************************************/ #pragma once +#include #include #include #include @@ -20,10 +21,10 @@ namespace picross // // The observer is a function object with the following signature: // -// void observer(Event event, const Line* line, unsigned int depth, unsigned int misc); +// void observer(Event event, const Line* line, { uint32_t depth, uint32_t misc_i, float misc_f }); // -// * event = KNOWN_LINE line = known_line depth is set misc = nb_alternatives (before) -// * event = DELTA_LINE line = delta depth is set misc = nb_alternatives (after) +// * event = KNOWN_LINE line = known_line depth is set misc_i = nb_alternatives (before) +// * event = DELTA_LINE line = delta depth is set misc_i = nb_alternatives (after) // // A line of the output grid has been updated, the delta between the previous value of that line // and the new one is given in event DELTA_LINE. @@ -31,8 +32,8 @@ namespace picross // The number of alternatives before (resp. after) the line solver are given in the event KNOWN_LINE // (resp. DELTA_LINE). // -// * event = BRANCHING line = known_line depth >= 0 misc = nb_alternatives (NODE) -// * event = BRANCHING line = nullptr depth > 0 misc = 0 (EDGE) +// * event = BRANCHING line = known_line depth >= 0 misc_i = nb_alternatives (NODE) +// * event = BRANCHING line = nullptr depth > 0 misc_i = 0 (EDGE) // // This event occurs when the algorithm is branching between several alternative solutions, or // when it is going back to an earlier branch. Upon starting a new branch the depth is increased @@ -43,19 +44,18 @@ namespace picross // branching line and the number of alternatives, and the EDGE event each time an alternative // of the branching line is being tested. // -// * event = SOLVED_GRID line = nullptr depth is set misc = 0 +// * event = SOLVED_GRID line = nullptr depth is set misc_i = 0 // // A solution grid has been found. The sum of all the delta lines up until that stage is the solved grid. // -// * event = INTERNAL_STATE line = nullptr depth is set misc = state +// * event = INTERNAL_STATE line = nullptr depth is set misc_i = internal state // // Internal state of the solver given as an integer // -// * event = PROGRESS line = nullptr deptb is set misc = reinterpret_cast(progress); +// * event = PROGRESS line = nullptr depth is set misc_f = progress_ratio // -// Progress is a float between 0.f and 1.f, whose binary representation is copied in the 'misc' integer. -// -enum class ObserverEvent { +enum class ObserverEvent +{ KNOWN_LINE, DELTA_LINE, BRANCHING, @@ -63,11 +63,17 @@ enum class ObserverEvent { INTERNAL_STATE, PROGRESS }; +struct ObserverData +{ + std::uint32_t m_depth = 0u; + std::uint32_t m_misc_i = 0u; + float m_misc_f = 0.f; +}; class Line; -using Observer = std::function; +using Observer = std::function; std::ostream& operator<<(std::ostream& out, ObserverEvent event); -std::string str_solver_internal_state(unsigned int internal_state); +std::string str_solver_internal_state(std::uint32_t internal_state); } // namespace picross diff --git a/src/picross/src/solver.cpp b/src/picross/src/solver.cpp index e9e8000..b6e9b29 100644 --- a/src/picross/src/solver.cpp +++ b/src/picross/src/solver.cpp @@ -146,7 +146,7 @@ std::ostream& operator<<(std::ostream& out, ObserverEvent event) return out; } -std::string str_solver_internal_state(unsigned int internal_state) +std::string str_solver_internal_state(std::uint32_t internal_state) { std::stringstream ss; ss << static_cast(internal_state); diff --git a/src/picross/src/work_grid.cpp b/src/picross/src/work_grid.cpp index 3307cb9..ade44c2 100644 --- a/src/picross/src/work_grid.cpp +++ b/src/picross/src/work_grid.cpp @@ -66,18 +66,13 @@ void update_line_range(LineRange& range, const std::vector& source) assert(range.m_begin <= range.m_end); } -template -RET_UINT progress_bar(const std::pair& progress_bar, LineAlternatives::NbAlt progress, LineAlternatives::NbAlt nb_alternatives) +float progress_bar(const std::pair& progress_bar, LineAlternatives::NbAlt progress, LineAlternatives::NbAlt nb_alternatives) { - static_assert(std::is_integral_v && std::is_unsigned_v); - static_assert(std::numeric_limits::digits >= std::numeric_limits::digits); assert(progress <= nb_alternatives); - const float ratio_f = static_cast(progress) / static_cast(nb_alternatives); - assert(0.f <= ratio_f && ratio_f <= 1.f); - const auto progress_f = std::make_unique(progress_bar.first + (progress_bar.second - progress_bar.first) * ratio_f); - // reinterpret as integer to go through the observer interface - const std::uint32_t ratio = *reinterpret_cast(progress_f.get()); - return static_cast(ratio); + const float ratio = static_cast(progress) / static_cast(nb_alternatives); + assert(0.f <= ratio && ratio <= 1.f); + const float progress_f = progress_bar.first + (progress_bar.second - progress_bar.first) * ratio; + return progress_f; } std::pair nested_progress_bar(const std::pair& progress_bar, LineAlternatives::NbAlt progress, LineAlternatives::NbAlt nb_alternatives) @@ -323,7 +318,10 @@ Solver::Status WorkGrid::line_solve(const Solver::SolutionFound& s { if (m_observer) { - m_observer(ObserverEvent::INTERNAL_STATE, nullptr, m_branching_depth, static_cast(m_state)); + ObserverData data; + data.m_depth = m_branching_depth; + data.m_misc_i = static_cast(m_state); + m_observer(ObserverEvent::INTERNAL_STATE, nullptr, data); } switch (m_state) @@ -430,7 +428,10 @@ Solver::Status WorkGrid::solve(const Solver::SolutionFound& soluti assert(m_solver_policy.m_branching_allowed); if (m_observer) { - m_observer(ObserverEvent::INTERNAL_STATE, nullptr, m_branching_depth, static_cast(m_state)); + ObserverData data; + data.m_depth = m_branching_depth; + data.m_misc_i = static_cast(m_state); + m_observer(ObserverEvent::INTERNAL_STATE, nullptr, data); } // Make a guess (branch search) @@ -513,15 +514,21 @@ bool WorkGrid::update_line(const LineSpan& line, unsigned int nb_a if (m_observer) { + ObserverData data; + data.m_depth = m_branching_depth; + if (line_changed) { - m_observer(ObserverEvent::KNOWN_LINE, &observer_original_line, m_branching_depth, observer_original_nb_alt); + data.m_misc_i = observer_original_nb_alt; + m_observer(ObserverEvent::KNOWN_LINE, &observer_original_line, data); const Line delta = get_line(line_type, line_index) - observer_original_line; - m_observer(ObserverEvent::DELTA_LINE, &delta, m_branching_depth, nb_alt); + data.m_misc_i = nb_alt; + m_observer(ObserverEvent::DELTA_LINE, &delta, data); } else { - m_observer(ObserverEvent::KNOWN_LINE, &observer_original_line, m_branching_depth, nb_alt); + data.m_misc_i = nb_alt; + m_observer(ObserverEvent::KNOWN_LINE, &observer_original_line, data); } } @@ -764,8 +771,10 @@ typename WorkGrid::PassStatus WorkGrid::full_grid_pa { if (m_observer) { + ObserverData data; + data.m_depth = m_branching_depth; const Line contradictory_line = line_from_line_span(get_line(*it)); - m_observer(ObserverEvent::KNOWN_LINE, &contradictory_line, m_branching_depth, 0); + m_observer(ObserverEvent::KNOWN_LINE, &contradictory_line, data); } break; } @@ -867,7 +876,10 @@ typename WorkGrid::ProbingResult WorkGrid::probe(Lin if (m_observer) { const auto line_known_tiles = line_from_line_span(known_tiles); - m_observer(ObserverEvent::BRANCHING, &line_known_tiles, m_branching_depth, nb_alt); + ObserverData data; + data.m_depth = m_branching_depth; + data.m_misc_i = nb_alt; + m_observer(ObserverEvent::BRANCHING, &line_known_tiles, data); } if (m_grid_stats != nullptr) @@ -891,7 +903,9 @@ typename WorkGrid::ProbingResult WorkGrid::probe(Lin probing_work_grid.configure(nested_solver_policy, WorkGridState::LINEAR_REDUCTION, nested_stats.get(), nested_progress.first, nested_progress.second); if (m_observer) { - m_observer(ObserverEvent::BRANCHING, nullptr, probing_work_grid.m_branching_depth, 0); + ObserverData data; + data.m_depth = probing_work_grid.m_branching_depth; + m_observer(ObserverEvent::BRANCHING, nullptr, data); } // Set one line in the new_grid according to the hypothesis we made. That line is then complete @@ -940,7 +954,10 @@ typename WorkGrid::ProbingResult WorkGrid::probe(Lin if (m_observer) { const auto line_known_tiles = line_from_line_span(known_tiles); - m_observer(ObserverEvent::BRANCHING, &line_known_tiles, m_branching_depth, nb_alt); + ObserverData data; + data.m_depth = m_branching_depth; + data.m_misc_i = nb_alt; + m_observer(ObserverEvent::BRANCHING, &line_known_tiles, data); } if (!reduced_grid) @@ -990,8 +1007,11 @@ Solver::Status WorkGrid::branch(const Solver::SolutionFound& solut if (m_observer) { + ObserverData data; + data.m_depth = m_branching_depth; + data.m_misc_i = nb_alt; const auto line_known_tiles = line_from_line_span(known_tiles); - m_observer(ObserverEvent::BRANCHING, &line_known_tiles, m_branching_depth, nb_alt); + m_observer(ObserverEvent::BRANCHING, &line_known_tiles, data); } if (m_grid_stats != nullptr) @@ -1019,7 +1039,9 @@ Solver::Status WorkGrid::branch(const Solver::SolutionFound& solut branching_work_grid.configure(nested_solver_policy, WorkGridState::LINEAR_REDUCTION, nested_stats.get(), nested_progress.first, nested_progress.second); if (m_observer) { - m_observer(ObserverEvent::BRANCHING, nullptr, branching_work_grid.m_branching_depth, 0); + ObserverData data; + data.m_depth = branching_work_grid.m_branching_depth; + m_observer(ObserverEvent::BRANCHING, nullptr, data); } // Set one line in the new_grid according to the hypothesis we made. That line is then complete @@ -1050,7 +1072,10 @@ Solver::Status WorkGrid::branch(const Solver::SolutionFound& solut progress++; if (m_observer) { - m_observer(ObserverEvent::PROGRESS, nullptr, branching_work_grid.m_branching_depth, progress_bar(m_progress_bar, progress, nb_alt)); + ObserverData data; + data.m_depth = branching_work_grid.m_branching_depth; + data.m_misc_f = progress_bar(m_progress_bar, progress, nb_alt); + m_observer(ObserverEvent::PROGRESS, nullptr, data); } if (status == Solver::Status::ABORTED) @@ -1063,8 +1088,11 @@ Solver::Status WorkGrid::branch(const Solver::SolutionFound& solut // Repeat start branching message if (m_observer) { + ObserverData data; + data.m_depth = m_branching_depth; + data.m_misc_i = nb_alt; const auto line_known_tiles = line_from_line_span(known_tiles); - m_observer(ObserverEvent::BRANCHING, &line_known_tiles, m_branching_depth, nb_alt); + m_observer(ObserverEvent::BRANCHING, &line_known_tiles, data); } return flag_solution_found ? Solver::Status::OK : Solver::Status::CONTRADICTORY_GRID; @@ -1088,7 +1116,12 @@ bool WorkGrid::found_solution(const Solver::SolutionFound& solutio assert(is_valid_solution()); const auto adjusted_branching_depth = m_branching_depth + m_probing_depth_incr; if (m_grid_stats != nullptr) { m_grid_stats->nb_solutions++; } - if (m_observer) { m_observer(ObserverEvent::SOLVED_GRID, nullptr, adjusted_branching_depth, 0); } + if (m_observer) + { + ObserverData data; + data.m_depth = adjusted_branching_depth; + m_observer(ObserverEvent::SOLVED_GRID, nullptr, data); + } // Shallow copy of only the grid data return solution_found(Solver::Solution{ OutputGrid(*this), adjusted_branching_depth, FULL_SOLUTION }); diff --git a/src/utils/include/utils/console_observer.h b/src/utils/include/utils/console_observer.h index ae6be71..e8e3e62 100644 --- a/src/utils/include/utils/console_observer.h +++ b/src/utils/include/utils/console_observer.h @@ -19,7 +19,7 @@ class ConsoleObserver final : public GridObserver void verify_against_goal(const picross::OutputGrid& goal); private: - void observer_callback(picross::ObserverEvent event, const picross::Line* line, unsigned int depth, unsigned int misc, const ObserverGrid& grid) override; + void observer_callback(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data, const ObserverGrid& grid) override; private: std::ostream& m_ostream; diff --git a/src/utils/include/utils/console_progress_observer.h b/src/utils/include/utils/console_progress_observer.h index 88a4ab9..41bae6a 100644 --- a/src/utils/include/utils/console_progress_observer.h +++ b/src/utils/include/utils/console_progress_observer.h @@ -13,7 +13,7 @@ class ConsoleProgressObserver final public: explicit ConsoleProgressObserver(std::ostream& ostream); - void operator()(picross::ObserverEvent event, const picross::Line* line, unsigned int depth, unsigned int misc); + void operator()(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data); private: std::ostream& m_ostream; diff --git a/src/utils/include/utils/grid_observer.h b/src/utils/include/utils/grid_observer.h index a9d926c..adfd66f 100644 --- a/src/utils/include/utils/grid_observer.h +++ b/src/utils/include/utils/grid_observer.h @@ -35,13 +35,13 @@ class GridObserver explicit GridObserver(const picross::InputGrid& grid); virtual ~GridObserver() = default; - void operator()(picross::ObserverEvent event, const picross::Line* line, unsigned int depth, unsigned int misc); + void operator()(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data); protected: void observer_clear(); private: - virtual void observer_callback(picross::ObserverEvent event, const picross::Line* line, unsigned int depth, unsigned int misc, const ObserverGrid& grid) = 0; + virtual void observer_callback(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data, const ObserverGrid& grid) = 0; private: std::vector m_grids; diff --git a/src/utils/src/console_observer.cpp b/src/utils/src/console_observer.cpp index 7b879a8..eebe965 100644 --- a/src/utils/src/console_observer.cpp +++ b/src/utils/src/console_observer.cpp @@ -19,7 +19,7 @@ void ConsoleObserver::verify_against_goal(const picross::OutputGrid& goal) m_goal = goal; } -void ConsoleObserver::observer_callback(picross::ObserverEvent event, const picross::Line* line, unsigned int depth, unsigned int misc, const ObserverGrid& grid) +void ConsoleObserver::observer_callback(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data, const ObserverGrid& grid) { m_ostream << event; switch (event) @@ -29,28 +29,28 @@ void ConsoleObserver::observer_callback(picross::ObserverEvent event, const picr { m_ostream << " NODE"; m_ostream << " known: " << picross::str_line_full(*line); - m_ostream << " depth: " << depth; - m_ostream << " nb_alt: " << misc; + m_ostream << " depth: " << data.m_depth; + m_ostream << " nb_alt: " << data.m_misc_i; } else { m_ostream << " EDGE"; - m_ostream << " depth: " << depth; + m_ostream << " depth: " << data.m_depth; } break; case picross::ObserverEvent::KNOWN_LINE: assert(line); m_ostream << " known: " << picross::str_line_full(*line) - << " depth: " << depth - << " nb_alt: " << misc; + << " depth: " << data.m_depth + << " nb_alt: " << data.m_misc_i; break; case picross::ObserverEvent::DELTA_LINE: assert(line); m_ostream << " delta: " << picross::str_line_full(*line) - << " depth: " << depth - << " nb_alt: " << misc; + << " depth: " << data.m_depth + << " nb_alt: " << data.m_misc_i; break; case picross::ObserverEvent::SOLVED_GRID: @@ -59,16 +59,15 @@ void ConsoleObserver::observer_callback(picross::ObserverEvent event, const picr break; case picross::ObserverEvent::INTERNAL_STATE: - m_ostream << " state: " << picross::str_solver_internal_state(misc) - << " depth: " << depth; + m_ostream << " state: " << picross::str_solver_internal_state(data.m_misc_i) + << " depth: " << data.m_depth; break; case picross::ObserverEvent::PROGRESS: { - const auto progress_i = std::make_unique(static_cast(misc)); - const float progress_f = *reinterpret_cast(progress_i.get()); - m_ostream << " progress: " << progress_f - << " depth: " << depth; + const float& progress = data.m_misc_f; + m_ostream << " progress: " << progress + << " depth: " << data.m_depth; break; } @@ -78,7 +77,7 @@ void ConsoleObserver::observer_callback(picross::ObserverEvent event, const picr m_ostream << std::endl; // Detect discrepancy with set goal - if (m_goal.has_value() && depth == 0 && event == picross::ObserverEvent::DELTA_LINE) + if (m_goal.has_value() && data.m_depth == 0 && event == picross::ObserverEvent::DELTA_LINE) { assert(line); picross::LineId line_id(*line); diff --git a/src/utils/src/console_progress_observer.cpp b/src/utils/src/console_progress_observer.cpp index 138b9dc..e3371f3 100644 --- a/src/utils/src/console_progress_observer.cpp +++ b/src/utils/src/console_progress_observer.cpp @@ -11,7 +11,7 @@ ConsoleProgressObserver::ConsoleProgressObserver(std::ostream& ostream) { } -void ConsoleProgressObserver::operator()(picross::ObserverEvent event, const picross::Line*, unsigned int depth, unsigned int misc) +void ConsoleProgressObserver::operator()(picross::ObserverEvent event, const picross::Line*, const picross::ObserverData& data) { switch (event) { @@ -25,14 +25,13 @@ void ConsoleProgressObserver::operator()(picross::ObserverEvent event, const pic case picross::ObserverEvent::PROGRESS: { - const auto progress_i = std::make_unique(static_cast(misc)); - const float progress_f = *reinterpret_cast(progress_i.get()); - if ((progress_f - m_previous_progress) > 0.001f) + const float& progress = data.m_misc_f; + if ((progress - m_previous_progress) > 0.001f) { - m_ostream << "Progress: " << progress_f - << " (depth: " << depth << ")" + m_ostream << "Progress: " << progress + << " (depth: " << data.m_depth << ")" << std::endl; - m_previous_progress = progress_f; + m_previous_progress = progress; } break; } diff --git a/src/utils/src/grid_observer.cpp b/src/utils/src/grid_observer.cpp index 35e245d..9abb1dc 100644 --- a/src/utils/src/grid_observer.cpp +++ b/src/utils/src/grid_observer.cpp @@ -53,7 +53,7 @@ GridObserver::GridObserver(const picross::InputGrid& grid) { } -void GridObserver::operator()(picross::ObserverEvent event, const picross::Line* line, unsigned int depth, unsigned int misc) +void GridObserver::operator()(picross::ObserverEvent event, const picross::Line* line, const picross::ObserverData& data) { const auto width = m_grids[0].width(); const auto height = m_grids[0].height(); @@ -64,20 +64,20 @@ void GridObserver::operator()(picross::ObserverEvent event, const picross::Line* if (!line) { // BRANCHING EDGE event - assert(depth > 0u); - if (depth > m_current_depth) + assert(data.m_depth > 0u); + if (data.m_depth > m_current_depth) { - assert(depth == m_current_depth + 1u); + assert(data.m_depth == m_current_depth + 1u); const unsigned int start_fill_depth = static_cast(m_grids.size()); - for (unsigned int d = start_fill_depth; d <= depth; d++) + for (unsigned int d = start_fill_depth; d <= data.m_depth; d++) { m_grids.emplace_back(width, height, d); } } - assert(depth < m_grids.size()); - m_grids[depth] = m_grids[depth - 1]; + assert(data.m_depth < m_grids.size()); + m_grids[data.m_depth] = m_grids[data.m_depth - 1]; } - m_current_depth = depth; + m_current_depth = data.m_depth; break; case picross::ObserverEvent::KNOWN_LINE: @@ -85,7 +85,7 @@ void GridObserver::operator()(picross::ObserverEvent event, const picross::Line* case picross::ObserverEvent::DELTA_LINE: { - assert(depth == m_current_depth); + assert(data.m_depth == m_current_depth); const size_t index = line->index(); ObserverGrid& grid = m_grids.at(m_current_depth); if (line->type() == picross::Line::ROW) @@ -122,7 +122,7 @@ void GridObserver::operator()(picross::ObserverEvent event, const picross::Line* } assert(m_current_depth < m_grids.size()); - observer_callback(event, line, depth, misc, m_grids.at(m_current_depth)); + observer_callback(event, line, data, m_grids.at(m_current_depth)); } void GridObserver::observer_clear()