From 75edb76681b8482486b44f9129c1df358875f86e Mon Sep 17 00:00:00 2001 From: Mitchell Hansen Date: Wed, 6 May 2026 21:18:09 -0700 Subject: [PATCH] brush-paint-opt: tighten axis bounds to prevent smear-basin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wider ranges let the optimizer find a degenerate local minimum: brush_radius_factor=0.43 + pen_lift_penalty=50 + min_score_factor=0.046 + polish_search_factor=1.95. This config covered every letter but at ~8× repaint per pixel — visually a fuzzy halo'd mess. Bounds now: brush_radius_factor 0.40-1.50 → 0.70-1.20 (close to original guess) brush_radius_percentile 0.70-1.00 → 0.85-1.00 pen_lift_penalty 0-200 → 0-25 (cap repaint aggression) pen_lift_reach 0.5-16 → 1.0-6.0 min_score_factor 0.0-0.30 → 0.05-0.30 (walker must demand progress) polish_search_factor 0.10-4.0 → 0.30-1.20 (polish stays brush-local) polish_iters 0-12 → 0-4 lookahead_steps 1-12 → 2-6 --- src/brush_paint_opt.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/brush_paint_opt.rs b/src/brush_paint_opt.rs index 587f8d76..f169e278 100644 --- a/src/brush_paint_opt.rs +++ b/src/brush_paint_opt.rs @@ -35,16 +35,21 @@ pub struct Axis { } pub fn default_axes() -> Vec { + // Bounds tightened to keep the search inside a sane neighbourhood + // around the original brush-sizing guess. Wider ranges let the + // optimizer find a "smear" basin (tiny brush + huge pen-lift + + // low score gate) that covers the corpus by repainting every + // pixel 7-8× — visually awful even though all metrics pass. vec![ - Axis { name: "brush_radius_factor", lo: 0.40, hi: 1.50, is_int: false, + Axis { name: "brush_radius_factor", lo: 0.70, hi: 1.20, is_int: false, set: |p, v| p.brush_radius_factor = v, get: |p| p.brush_radius_factor }, - Axis { name: "brush_radius_percentile", lo: 0.70, hi: 1.00, is_int: false, + Axis { name: "brush_radius_percentile", lo: 0.85, hi: 1.00, is_int: false, set: |p, v| p.brush_radius_percentile = v, get: |p| p.brush_radius_percentile }, Axis { name: "brush_radius_offset_px", lo: 0.0, hi: 1.0, is_int: false, set: |p, v| p.brush_radius_offset_px = v, get: |p| p.brush_radius_offset_px }, - Axis { name: "polish_iters", lo: 0.0, hi: 12.0, is_int: true, + Axis { name: "polish_iters", lo: 0.0, hi: 4.0, is_int: true, set: |p, v| p.polish_iters = v as u32, get: |p| p.polish_iters as f32 }, - Axis { name: "polish_search_factor", lo: 0.10, hi: 4.0, is_int: false, + Axis { name: "polish_search_factor", lo: 0.30, hi: 1.20, is_int: false, set: |p, v| p.polish_search_factor = v, get: |p| p.polish_search_factor }, Axis { name: "bg_penalty", lo: 0.0, hi: 20.0, is_int: false, set: |p, v| p.bg_penalty = v, get: |p| p.bg_penalty }, @@ -54,21 +59,21 @@ pub fn default_axes() -> Vec { set: |p, v| p.overpaint_penalty = v, get: |p| p.overpaint_penalty }, Axis { name: "step_size_factor", lo: 0.20, hi: 0.90, is_int: false, set: |p, v| p.step_size_factor = v, get: |p| p.step_size_factor }, - Axis { name: "lookahead_steps", lo: 1.0, hi: 12.0, is_int: true, + Axis { name: "lookahead_steps", lo: 2.0, hi: 6.0, is_int: true, set: |p, v| p.lookahead_steps = v as usize, get: |p| p.lookahead_steps as f32 }, Axis { name: "n_directions", lo: 8.0, hi: 64.0, is_int: true, set: |p, v| p.n_directions = v as usize, get: |p| p.n_directions as f32 }, Axis { name: "momentum_weight", lo: 0.0, hi: 2.0, is_int: false, set: |p, v| p.momentum_weight = v, get: |p| p.momentum_weight }, - Axis { name: "min_score_factor", lo: 0.0, hi: 0.30, is_int: false, + Axis { name: "min_score_factor", lo: 0.05, hi: 0.30, is_int: false, set: |p, v| p.min_score_factor = v, get: |p| p.min_score_factor }, Axis { name: "back_dir_cutoff", lo: -0.95, hi: -0.3, is_int: false, set: |p, v| p.back_dir_cutoff = v, get: |p| p.back_dir_cutoff }, Axis { name: "min_component_factor", lo: 0.10, hi: 1.50, is_int: false, set: |p, v| p.min_component_factor = v, get: |p| p.min_component_factor }, - Axis { name: "pen_lift_penalty", lo: 0.0, hi: 200.0, is_int: false, + Axis { name: "pen_lift_penalty", lo: 0.0, hi: 25.0, is_int: false, set: |p, v| p.pen_lift_penalty = v, get: |p| p.pen_lift_penalty }, - Axis { name: "pen_lift_reach", lo: 0.5, hi: 16.0, is_int: false, + Axis { name: "pen_lift_reach", lo: 1.0, hi: 6.0, is_int: false, set: |p, v| p.pen_lift_reach = v, get: |p| p.pen_lift_reach }, Axis { name: "output_rdp_eps", lo: 0.0, hi: 2.0, is_int: false, set: |p, v| p.output_rdp_eps = v, get: |p| p.output_rdp_eps },