""" Build optimized ONNX model for Task 255. Boundary-anchored rect finding + integral image + cross extensions. Target: ~500 nodes, ~2-3M memory → score ~10-12 → gain +3-5 pts. """ import onnx from onnx import helper, TensorProto, numpy_helper import numpy as np import os, json, sys H, W, C = 30, 30, 10 def build_task255(): nodes, inits, vis = [], [], [] counter = [0] def nm(): counter[0] += 1 return f"t{counter[0]}" def const(name, val, dtype='f'): arr = np.array(val, dtype=np.float32 if dtype == 'f' else np.int64) inits.append(numpy_helper.from_array(arr, name)) def vi(name, shape, dt=TensorProto.FLOAT): vis.append(helper.make_tensor_value_info(name, dt, shape)) def nd(op, ins, outs_shapes, **kwargs): out_names = [] for sd in outs_shapes: if isinstance(sd, tuple): shape, dt = sd else: shape, dt = sd, TensorProto.FLOAT n = nm() vi(n, shape, dt) out_names.append(n) nodes.append(helper.make_node(op, ins, out_names, **kwargs)) return out_names[0] if len(out_names) == 1 else out_names # === CONSTANTS === const('c_half', [0.5]) const('c_one', [1.0]) const('c_two', [2.0]) const('c_three', [3.0]) const('c_30', [30.0]) const('c_neg1000', [-1000.0]) const('c_pos1000', [1000.0]) const('c_zero_s', [0.0]) const('c_2_5', [2.5]) const('shape_30', [30], 'i') const('shape_30x30', [30, 30], 'i') const('shape_1_1_30_30', [1, 1, 30, 30], 'i') const('shape_1_30', [1, 30], 'i') const('shape_30_1', [30, 1], 'i') const('shape_900', [900], 'i') const('axes0', [0], 'i') const('axes1', [1], 'i') const('s_ch1', [0, 1, 0, 0], 'i') const('e_ch1', [1, 10, 30, 30], 'i') const('ax4', [0, 1, 2, 3], 'i') const('row_idx', np.arange(30, dtype=np.float32)) const('col_idx', np.arange(30, dtype=np.float32)) # Thresholds for CumSum-based depth detection row_plus_half = (np.arange(30, dtype=np.float32) + 0.5).reshape(30, 1) const('row_plus_half_col', row_plus_half) bot_thresh = (30.0 - np.arange(30, dtype=np.float32) - 0.5).reshape(30, 1) const('bot_thresh', bot_thresh) col_plus_half = (np.arange(30, dtype=np.float32) + 0.5).reshape(1, 30) const('col_plus_half_row', col_plus_half) right_thresh = (30.0 - np.arange(30, dtype=np.float32) - 0.5).reshape(1, 30) const('right_thresh', right_thresh) # Sparse table constants for rect finding # lower_tri mask and length matrix for [30,30] inf_upper = np.zeros((30, 30), dtype=np.float32) for i in range(30): for j in range(i): inf_upper[i, j] = 1e9 const('inf_upper', inf_upper) length_mat = np.zeros((30, 30), dtype=np.float32) for i in range(30): for j in range(i, 30): length_mat[i, j] = float(j - i + 1) const('length_mat', length_mat) const('ones_30_1', np.ones((30, 1), dtype=np.float32)) const('ones_1_30', np.ones((1, 30), dtype=np.float32)) # Color delta for output color3_delta = np.zeros((1, 10, 1, 1), dtype=np.float32) color3_delta[0, 3, 0, 0] = 1.0 color3_delta[0, 0, 0, 0] = -1.0 const('color3_delta', color3_delta) # === STEP 1: fg_mask [30,30] === ch19 = nd('Slice', ['input', 's_ch1', 'e_ch1', 'ax4'], [[1, 9, 30, 30]]) fg_sum = nd('ReduceSum', [ch19, 'axes1'], [[1, 1, 30, 30]], keepdims=1) fg_bool = nd('Greater', [fg_sum, 'c_half'], [([1, 1, 30, 30], TensorProto.BOOL)]) fg_4d = nd('Cast', [fg_bool], [[1, 1, 30, 30]], to=1) fg = nd('Reshape', [fg_4d, 'shape_30x30'], [[30, 30]]) not_fg = nd('Sub', ['c_one', fg], [[30, 30]]) # === STEP 2: Depth vectors from 4 sides === # TOP: CumSum(not_fg, axis=0). If cum[r,c] > r+0.5 → all empty [0..r] cum_nf_top = nd('CumSum', [not_fg, 'axes0'], [[30, 30]]) lead_top_b = nd('Greater', [cum_nf_top, 'row_plus_half_col'], [([30, 30], TensorProto.BOOL)]) lead_top_f = nd('Cast', [lead_top_b], [[30, 30]], to=1) depth_top_2d = nd('ReduceSum', [lead_top_f, 'axes0'], [[1, 30]], keepdims=1) depth_top = nd('Reshape', [depth_top_2d, 'shape_30'], [[30]]) # BOTTOM: CumSum(not_fg, axis=0, reverse=1) cum_nf_bot = nd('CumSum', [not_fg, 'axes0'], [[30, 30]], reverse=1) lead_bot_b = nd('Greater', [cum_nf_bot, 'bot_thresh'], [([30, 30], TensorProto.BOOL)]) lead_bot_f = nd('Cast', [lead_bot_b], [[30, 30]], to=1) depth_bot_2d = nd('ReduceSum', [lead_bot_f, 'axes0'], [[1, 30]], keepdims=1) depth_bot = nd('Reshape', [depth_bot_2d, 'shape_30'], [[30]]) # LEFT: CumSum(not_fg, axis=1) cum_nf_left = nd('CumSum', [not_fg, 'axes1'], [[30, 30]]) lead_left_b = nd('Greater', [cum_nf_left, 'col_plus_half_row'], [([30, 30], TensorProto.BOOL)]) lead_left_f = nd('Cast', [lead_left_b], [[30, 30]], to=1) depth_left_2d = nd('ReduceSum', [lead_left_f, 'axes1'], [[30, 1]], keepdims=1) depth_left = nd('Reshape', [depth_left_2d, 'shape_30'], [[30]]) # RIGHT: CumSum(not_fg, axis=1, reverse=1) cum_nf_right = nd('CumSum', [not_fg, 'axes1'], [[30, 30]], reverse=1) lead_right_b = nd('Greater', [cum_nf_right, 'right_thresh'], [([30, 30], TensorProto.BOOL)]) lead_right_f = nd('Cast', [lead_right_b], [[30, 30]], to=1) depth_right_2d = nd('ReduceSum', [lead_right_f, 'axes1'], [[30, 1]], keepdims=1) depth_right = nd('Reshape', [depth_right_2d, 'shape_30'], [[30]]) # === STEP 3: Largest rect in histogram for each side === # Sparse table: 5 doubling steps to compute range-min matrix # Then area = min_height * width, find max. def hist_rect(depth_name, label): """Largest rectangle in histogram h[30]. Returns (area, start, width, height) as [1] tensors.""" # Broadcast h to [30,30]: h_mat[i,j] = h[j] for all i h_row = nd('Reshape', [depth_name, 'shape_1_30'], [[1, 30]]) h_mat = nd('MatMul', ['ones_30_1', h_row], [[30, 30]]) # Add inf for upper triangle (j < i): ensures min is only over valid range [i..j] m = nd('Add', [h_mat, 'inf_upper'], [[30, 30]]) # Sparse table doubling: 5 steps with shifts 1, 2, 4, 8, 16 # Shift m RIGHT by `shift` columns (pad left with inf, slice [0:30]) # ONNX Pad format for [30,30]: [dim0_begin, dim1_begin, dim0_end, dim1_end] for step, shift in enumerate([1, 2, 4, 8, 16]): # Pad: add `shift` inf columns on the LEFT of dim 1 pads = np.array([0, shift, 0, 0], dtype=np.int64) const(f'pad_{label}_{step}', pads, 'i') const(f'padval_{label}_{step}', [1e9]) padded = nd('Pad', [m, f'pad_{label}_{step}', f'padval_{label}_{step}'], [[30, 30 + shift]]) # Slice first 30 columns: [0:30, 0:30] const(f'sls_{label}_{step}', [0, 0], 'i') const(f'sle_{label}_{step}', [30, 30], 'i') const(f'sla_{label}_{step}', [0, 1], 'i') m_shifted = nd('Slice', [padded, f'sls_{label}_{step}', f'sle_{label}_{step}', f'sla_{label}_{step}'], [[30, 30]]) m = nd('Min', [m, m_shifted], [[30, 30]]) # Now m[i,j] = min(h[i..j]) for j>=i, large for j 0), remove end at non-boundary (pos < 29) const(f'p0_{label}', np.array([1.0] + [0.0]*29, dtype=np.float32)) const(f'p29_{label}', np.array([0.0]*29 + [1.0], dtype=np.float32)) not_p0 = nd('Sub', ['c_one', f'p0_{label}'], [[30]]) rm_start = nd('Mul', [run_start, not_p0], [[30]]) not_p29 = nd('Sub', ['c_one', f'p29_{label}'], [[30]]) rm_end = nd('Mul', [run_end, not_p29], [[30]]) e1 = nd('Sub', [elig, rm_start], [[30]]) e2 = nd('Sub', [e1, rm_end], [[30]]) # Clip to [0,1] eroded = nd('Clip', [e2, 'c_zero_s', 'c_one'], [[30]]) return eroded # === PHASE 1: RIGHT extension === # Eligible: row in core AND fg_row_max < core_c1 (all fg left of core) fg_lt_cc1 = nd('Less', [fg_row_max, cc1_m_half], [([30], TensorProto.BOOL)]) fg_lt_cc1_f = nd('Cast', [fg_lt_cc1], [[30]], to=1) right_elig = nd('Mul', [row_in, fg_lt_cc1_f], [[30]]) right_eroded = erode_vec(right_elig, 'r1') # Fill: eroded rows, cols > core_c2 col_gt_cc2 = nd('Greater', ['col_idx', cc2_p_half], [([30], TensorProto.BOOL)]) col_gt_cc2_f = nd('Cast', [col_gt_cc2], [[30]], to=1) re_col = nd('Reshape', [right_eroded, 'shape_30_1'], [[30, 1]]) cg_row = nd('Reshape', [col_gt_cc2_f, 'shape_1_30'], [[1, 30]]) right_fill = nd('MatMul', [re_col, cg_row], [[30, 30]]) result = nd('Max', [core_mask, right_fill], [[30, 30]]) # === PHASE 1b: LEFT extension === fg_gt_cc2 = nd('Greater', [fg_row_min, cc2_p_half], [([30], TensorProto.BOOL)]) fg_gt_cc2_f = nd('Cast', [fg_gt_cc2], [[30]], to=1) left_elig = nd('Mul', [row_in, fg_gt_cc2_f], [[30]]) left_eroded = erode_vec(left_elig, 'l1') col_lt_cc1 = nd('Less', ['col_idx', core_c1], [([30], TensorProto.BOOL)]) col_lt_cc1_f = nd('Cast', [col_lt_cc1], [[30]], to=1) le_col = nd('Reshape', [left_eroded, 'shape_30_1'], [[30, 1]]) cl_row = nd('Reshape', [col_lt_cc1_f, 'shape_1_30'], [[1, 30]]) left_fill = nd('MatMul', [le_col, cl_row], [[30, 30]]) result = nd('Max', [result, left_fill], [[30, 30]]) # === PHASE 2: Sub-rect post-processing === # For RIGHT sub-rect: eligible rows where fg_row_max < core_c1 # Within each contiguous run of eligible rows, compute max(fg_row_max) # sub_left = max_fg_in_run + 1. If main_c1 - sub_left >= 4, fill from sub_left+1 (eroded) # Static RIGHT eligibility sr_elig = fg_lt_cc1_f # [30] — already computed in Phase 1 # Propagate max fg_row_max within eligible runs using iterative max # masked_val[r] = fg_row_max[r] if eligible else -1000 sr_not_elig = nd('Sub', ['c_one', sr_elig], [[30]]) const('c_neg1000_sr', [-1000.0]) sr_fg_masked = nd('Mul', [fg_row_max, sr_elig], [[30]]) sr_ne_w = nd('Mul', [sr_not_elig, 'c_neg1000_sr'], [[30]]) sr_vals = nd('Add', [sr_fg_masked, sr_ne_w], [[30]]) # [30] fg_max where eligible, -1000 elsewhere # Reshape to [1,1,30,1] for MaxPool propagation along row dimension const('shape_1_1_30_1', [1, 1, 30, 1], 'i') sr_4d2 = nd('Reshape', [sr_vals, 'shape_1_1_30_1'], [[1, 1, 30, 1]]) # MaxPool with kernel [3,1] propagates max along the row dimension # Do 15 iterations to propagate max across runs of length up to 30 for it in range(15): sr_4d2 = nd('MaxPool', [sr_4d2], [[1, 1, 30, 1]], kernel_shape=[3, 1], pads=[1, 0, 1, 0]) # Re-mask: only keep values in eligible positions sr_elig_4d = nd('Reshape', [sr_elig, 'shape_1_1_30_1'], [[1, 1, 30, 1]]) sr_4d2 = nd('Mul', [sr_4d2, sr_elig_4d], [[1, 1, 30, 1]]) # Add -1000 for non-eligible sr_ne_4d = nd('Reshape', [sr_ne_w, 'shape_1_1_30_1'], [[1, 1, 30, 1]]) sr_4d2 = nd('Add', [sr_4d2, sr_ne_4d], [[1, 1, 30, 1]]) # Now sr_4d2[r] = max(fg_row_max) across the contiguous eligible run containing r sr_run_max = nd('Reshape', [sr_4d2, 'shape_30'], [[30]]) # sub_left per row = sr_run_max + 1 sr_sub_left = nd('Add', [sr_run_max, 'c_two'], [[30]]) # eroded: +2 from max_fg (= sub_lc + 1) # Threshold: lc_val - (sr_run_max + 1) >= 4 (per row) — check before erosion const('c_3_5', [3.5]) sr_sub_left_uneroded = nd('Add', [sr_run_max, 'c_one'], [[30]]) # before col erosion sr_gap = nd('Sub', [lc_val, sr_sub_left_uneroded], [[30]]) sr_thresh_b = nd('Greater', [sr_gap, 'c_3_5'], [([30], TensorProto.BOOL)]) sr_thresh_f = nd('Cast', [sr_thresh_b], [[30]], to=1) # Erode the eligible vector sr_eroded = erode_vec(sr_elig, 'sr') # Active = eroded AND threshold met sr_active = nd('Mul', [sr_eroded, sr_thresh_f], [[30]]) # Fill: for each active row r, fill cols >= sr_sub_left[r] # Build [30,30] mask where mask[r,c] = (c >= sr_sub_left[r]) * sr_active[r] sr_sub_left_col = nd('Reshape', [sr_sub_left, 'shape_30_1'], [[30, 1]]) # [30,1] # col_idx [30] broadcast with sr_sub_left_col [30,1] col_ge_srl = nd('Greater', [col_idx_row, nd('Sub', [sr_sub_left_col, 'c_half'], [[30, 1]])], [([30, 30], TensorProto.BOOL)]) col_ge_srl_f = nd('Cast', [col_ge_srl], [[30, 30]], to=1) sr_act_col = nd('Reshape', [sr_active, 'shape_30_1'], [[30, 1]]) sr_fill = nd('Mul', [nd('MatMul', [sr_act_col, 'ones_1_30'], [[30, 30]]), col_ge_srl_f], [[30, 30]]) result = nd('Max', [result, sr_fill], [[30, 30]]) # For LEFT sub-rect: eligible rows where fg_row_min > core_c2 # Propagate min fg_row_min within eligible runs sl_elig = fg_gt_cc2_f # [30] sl_not_elig = nd('Sub', ['c_one', sl_elig], [[30]]) const('c_pos1000_sl', [1000.0]) sl_fg_masked = nd('Mul', [fg_row_min, sl_elig], [[30]]) sl_ne_w = nd('Mul', [sl_not_elig, 'c_pos1000_sl'], [[30]]) sl_vals = nd('Add', [sl_fg_masked, sl_ne_w], [[30]]) # For min propagation: negate, maxpool, negate sl_neg = nd('Mul', [sl_vals, nd('Sub', ['c_zero_s', 'c_one'], [[1]])], [[30]]) sl_4d = nd('Reshape', [sl_neg, 'shape_1_1_30_1'], [[1, 1, 30, 1]]) for it in range(15): sl_4d = nd('MaxPool', [sl_4d], [[1, 1, 30, 1]], kernel_shape=[3, 1], pads=[1, 0, 1, 0]) sl_elig_4d = nd('Reshape', [sl_elig, 'shape_1_1_30_1'], [[1, 1, 30, 1]]) sl_4d = nd('Mul', [sl_4d, sl_elig_4d], [[1, 1, 30, 1]]) # Non-eligible: add -1000 (since negated, this means +1000 in original = not participating) sl_ne_neg = nd('Reshape', [nd('Mul', [sl_not_elig, 'c_neg1000_sr'], [[30]]), 'shape_1_1_30_1'], [[1, 1, 30, 1]]) sl_4d = nd('Add', [sl_4d, sl_ne_neg], [[1, 1, 30, 1]]) # Negate back to get min sl_run_min_neg = nd('Reshape', [sl_4d, 'shape_30'], [[30]]) sl_run_min = nd('Mul', [sl_run_min_neg, nd('Sub', ['c_zero_s', 'c_one'], [[1]])], [[30]]) # sub_right per row = sl_run_min - 1 sl_sub_right_uneroded = nd('Sub', [sl_run_min, 'c_one'], [[30]]) # before erosion sl_sub_right = nd('Sub', [sl_run_min, 'c_two'], [[30]]) # eroded: -2 from min_fg # Threshold: sl_sub_right_uneroded - main_c2 >= 4 main_c2_val = nd('Sub', [lc_plus_rw, 'c_one'], [[1]]) sl_gap = nd('Sub', [sl_sub_right_uneroded, main_c2_val], [[30]]) sl_thresh_b = nd('Greater', [sl_gap, 'c_3_5'], [([30], TensorProto.BOOL)]) sl_thresh_f = nd('Cast', [sl_thresh_b], [[30]], to=1) sl_eroded = erode_vec(sl_elig, 'sl') sl_active = nd('Mul', [sl_eroded, sl_thresh_f], [[30]]) # Fill cols <= sl_sub_right[r] sl_sub_right_col = nd('Reshape', [sl_sub_right, 'shape_30_1'], [[30, 1]]) col_le_slr = nd('Less', [col_idx_row, nd('Add', [sl_sub_right_col, 'c_half'], [[30, 1]])], [([30, 30], TensorProto.BOOL)]) col_le_slr_f = nd('Cast', [col_le_slr], [[30, 30]], to=1) sl_act_col = nd('Reshape', [sl_active, 'shape_30_1'], [[30, 1]]) sl_fill = nd('Mul', [nd('MatMul', [sl_act_col, 'ones_1_30'], [[30, 30]]), col_le_slr_f], [[30, 30]]) result = nd('Max', [result, sl_fill], [[30, 30]]) # === PHASE 3: DOWN extension === # Eligible: col has result height >= 3 AND all fg in col is above result_top # Compute per-column result height and top # result_col_sum[c] = number of result cells in col c res_col_sum = nd('ReduceSum', [result, 'axes0'], [[1, 30]], keepdims=1) res_col_sum_1d = nd('Reshape', [res_col_sum, 'shape_30'], [[30]]) col_h_ge3 = nd('Greater', [res_col_sum_1d, 'c_2_5'], [([30], TensorProto.BOOL)]) col_h_ge3_f = nd('Cast', [col_h_ge3], [[30]], to=1) # result_top per col: min row with result # Use: result * row_idx + (1-result) * 1000 → ReduceMin along rows not_res_pre = nd('Sub', ['c_one', result], [[30, 30]]) res_row_w = nd('Mul', [result, row_idx_col], [[30, 30]]) nrp_big = nd('Mul', [not_res_pre, 'c_pos1000'], [[30, 30]]) res_top_scored = nd('Add', [res_row_w, nrp_big], [[30, 30]]) res_top_2d = nd('ReduceMin', [res_top_scored, 'axes0'], [[1, 30]], keepdims=1) res_top_1d = nd('Reshape', [res_top_2d, 'shape_30'], [[30]]) # fg_col_max < res_top (all fg above result top in that col) res_top_m_half = nd('Sub', [res_top_1d, 'c_half'], [[30]]) fg_above = nd('Less', [fg_col_max, res_top_m_half], [([30], TensorProto.BOOL)]) fg_above_f = nd('Cast', [fg_above], [[30]], to=1) down_e1 = nd('Mul', [col_h_ge3_f, fg_above_f], [[30]]) # Extend with adjacent no-fg cols de_2d = nd('Reshape', [down_e1, 'shape_1_30'], [[1, 30]]) const('pl_de', [0, 1, 0, 0], 'i') const('pv_de', [0.0]) de_pl = nd('Pad', [de_2d, 'pl_de', 'pv_de'], [[1, 31]]) const('ss_de', [0, 0], 'i') const('se_de', [1, 30], 'i') const('sa_de', [0, 1], 'i') de_prev = nd('Slice', [de_pl, 'ss_de', 'se_de', 'sa_de'], [[1, 30]]) de_prev_1d = nd('Reshape', [de_prev, 'shape_30'], [[30]]) const('pr_de', [0, 0, 0, 1], 'i') de_pr = nd('Pad', [de_2d, 'pr_de', 'pv_de'], [[1, 31]]) const('ss2_de', [0, 1], 'i') const('se2_de', [1, 31], 'i') de_next = nd('Slice', [de_pr, 'ss2_de', 'se2_de', 'sa_de'], [[1, 30]]) de_next_1d = nd('Reshape', [de_next, 'shape_30'], [[30]]) adj_p_d = nd('Mul', [de_prev_1d, no_fg_col], [[30]]) adj_n_d = nd('Mul', [de_next_1d, no_fg_col], [[30]]) down_ext = nd('Max', [down_e1, adj_p_d], [[30]]) down_ext2 = nd('Max', [down_ext, adj_n_d], [[30]]) down_eroded = erode_vec(down_ext2, 'd1') # Fill: for each eligible col, fill rows > result_bottom[c] # result_bottom[c] = max row with result in col c res_bot_scored = nd('Add', [res_row_w, nd('Mul', [not_res_pre, 'c_neg1000'], [[30, 30]])], [[30, 30]]) res_bot_2d = nd('ReduceMax', [res_bot_scored, 'axes0'], [[1, 30]], keepdims=1) res_bot_1d = nd('Reshape', [res_bot_2d, 'shape_30'], [[30]]) # For each col c: fill rows > res_bot_1d[c] # Build [30,30] mask: mask[r,c] = (row_idx[r] > res_bot_1d[c]) * down_eroded[c] res_bot_row = nd('Reshape', [res_bot_1d, 'shape_1_30'], [[1, 30]]) # [1,30] row_gt_rb = nd('Greater', [row_idx_col, res_bot_row], [([30, 30], TensorProto.BOOL)]) # [30,30] row_gt_rb_f = nd('Cast', [row_gt_rb], [[30, 30]], to=1) de_row2 = nd('Reshape', [down_eroded, 'shape_1_30'], [[1, 30]]) down_mask = nd('Mul', [nd('MatMul', ['ones_30_1', de_row2], [[30, 30]]), row_gt_rb_f], [[30, 30]]) result = nd('Max', [result, down_mask], [[30, 30]]) # === PHASE 3b: UP extension === # Eligible: col has result height >= 3 AND all fg below result_bottom # Re-compute result column info after DOWN phase res_col_sum2 = nd('ReduceSum', [result, 'axes0'], [[1, 30]], keepdims=1) res_col_sum2_1d = nd('Reshape', [res_col_sum2, 'shape_30'], [[30]]) col_h_ge3_2 = nd('Greater', [res_col_sum2_1d, 'c_2_5'], [([30], TensorProto.BOOL)]) col_h_ge3_2f = nd('Cast', [col_h_ge3_2], [[30]], to=1) # result_bottom per col (after DOWN) not_res_2 = nd('Sub', ['c_one', result], [[30, 30]]) res_row_w2 = nd('Mul', [result, row_idx_col], [[30, 30]]) nrp_neg2 = nd('Mul', [not_res_2, 'c_neg1000'], [[30, 30]]) res_bot_scored2 = nd('Add', [res_row_w2, nrp_neg2], [[30, 30]]) res_bot_2d2 = nd('ReduceMax', [res_bot_scored2, 'axes0'], [[1, 30]], keepdims=1) res_bot_1d2 = nd('Reshape', [res_bot_2d2, 'shape_30'], [[30]]) # fg_col_min > result_bottom (all fg below result) res_bot_p_half = nd('Add', [res_bot_1d2, 'c_half'], [[30]]) fg_below = nd('Greater', [fg_col_min, res_bot_p_half], [([30], TensorProto.BOOL)]) fg_below_f = nd('Cast', [fg_below], [[30]], to=1) up_e1 = nd('Mul', [col_h_ge3_2f, fg_below_f], [[30]]) ue_2d = nd('Reshape', [up_e1, 'shape_1_30'], [[1, 30]]) const('pl_ue', [0, 1, 0, 0], 'i') const('pv_ue', [0.0]) ue_pl = nd('Pad', [ue_2d, 'pl_ue', 'pv_ue'], [[1, 31]]) const('ss_ue', [0, 0], 'i') const('se_ue', [1, 30], 'i') const('sa_ue', [0, 1], 'i') ue_prev = nd('Slice', [ue_pl, 'ss_ue', 'se_ue', 'sa_ue'], [[1, 30]]) ue_prev_1d = nd('Reshape', [ue_prev, 'shape_30'], [[30]]) const('pr_ue', [0, 0, 0, 1], 'i') ue_pr = nd('Pad', [ue_2d, 'pr_ue', 'pv_ue'], [[1, 31]]) const('ss2_ue', [0, 1], 'i') const('se2_ue', [1, 31], 'i') ue_next = nd('Slice', [ue_pr, 'ss2_ue', 'se2_ue', 'sa_ue'], [[1, 30]]) ue_next_1d = nd('Reshape', [ue_next, 'shape_30'], [[30]]) adj_p_u = nd('Mul', [ue_prev_1d, no_fg_col], [[30]]) adj_n_u = nd('Mul', [ue_next_1d, no_fg_col], [[30]]) up_ext = nd('Max', [up_e1, adj_p_u], [[30]]) up_ext2 = nd('Max', [up_ext, adj_n_u], [[30]]) up_eroded = erode_vec(up_ext2, 'u1') # Fill: for each eligible col, fill rows < result_top[c] # result_top per col (after DOWN fills) nrp_big2 = nd('Mul', [not_res_2, 'c_pos1000'], [[30, 30]]) res_top_scored2 = nd('Add', [res_row_w2, nrp_big2], [[30, 30]]) res_top_2d2 = nd('ReduceMin', [res_top_scored2, 'axes0'], [[1, 30]], keepdims=1) res_top_1d2 = nd('Reshape', [res_top_2d2, 'shape_30'], [[30]]) # mask[r,c] = (row_idx[r] < res_top_1d2[c]) * up_eroded[c] res_top_row2 = nd('Reshape', [res_top_1d2, 'shape_1_30'], [[1, 30]]) row_lt_rt = nd('Less', [row_idx_col, res_top_row2], [([30, 30], TensorProto.BOOL)]) row_lt_rt_f = nd('Cast', [row_lt_rt], [[30, 30]], to=1) ue_row2 = nd('Reshape', [up_eroded, 'shape_1_30'], [[1, 30]]) up_mask = nd('Mul', [nd('MatMul', ['ones_30_1', ue_row2], [[30, 30]]), row_lt_rt_f], [[30, 30]]) result = nd('Max', [result, up_mask], [[30, 30]]) # === PHASE 4: Second RIGHT/LEFT (width>=3) === # result_row info res_row_sum = nd('ReduceSum', [result, 'axes1'], [[30, 1]], keepdims=1) res_row_sum_1d = nd('Reshape', [res_row_sum, 'shape_30'], [[30]]) has_res_b = nd('Greater', [res_row_sum_1d, 'c_half'], [([30], TensorProto.BOOL)]) has_res = nd('Cast', [has_res_b], [[30]], to=1) w_ge3_b = nd('Greater', [res_row_sum_1d, 'c_2_5'], [([30], TensorProto.BOOL)]) w_ge3 = nd('Cast', [w_ge3_b], [[30]], to=1) # result left boundary per row not_res = nd('Sub', ['c_one', result], [[30, 30]]) res_col_w = nd('Mul', [result, col_idx_row], [[30, 30]]) nr_big = nd('Mul', [not_res, 'c_pos1000'], [[30, 30]]) res_min_scored = nd('Add', [res_col_w, nr_big], [[30, 30]]) res_min_2d = nd('ReduceMin', [res_min_scored, 'axes1'], [[30, 1]], keepdims=1) res_min_1d = nd('Reshape', [res_min_2d, 'shape_30'], [[30]]) # result right boundary per row nr_neg = nd('Mul', [not_res, 'c_neg1000'], [[30, 30]]) res_max_scored = nd('Add', [res_col_w, nr_neg], [[30, 30]]) res_max_2d = nd('ReduceMax', [res_max_scored, 'axes1'], [[30, 1]], keepdims=1) res_max_1d = nd('Reshape', [res_max_2d, 'shape_30'], [[30]]) # RIGHT2: fg_row_max < res_min (all fg left of result) res_min_m_half = nd('Sub', [res_min_1d, 'c_half'], [[30]]) fg_lt_res = nd('Less', [fg_row_max, res_min_m_half], [([30], TensorProto.BOOL)]) fg_lt_res_f = nd('Cast', [fg_lt_res], [[30]], to=1) r2_elig = nd('Mul', [has_res, w_ge3], [[30]]) r2_elig2 = nd('Mul', [r2_elig, fg_lt_res_f], [[30]]) r2_eroded = erode_vec(r2_elig2, 'r2') # Fill cols > res_max per row rm_col = nd('Reshape', [res_max_1d, 'shape_30_1'], [[30, 1]]) col_gt_rm = nd('Greater', [col_idx_row, rm_col], [([30, 30], TensorProto.BOOL)]) col_gt_rm_f = nd('Cast', [col_gt_rm], [[30, 30]], to=1) r2e_col = nd('Reshape', [r2_eroded, 'shape_30_1'], [[30, 1]]) r2_mask = nd('MatMul', [r2e_col, 'ones_1_30'], [[30, 30]]) r2_fill = nd('Mul', [r2_mask, col_gt_rm_f], [[30, 30]]) result = nd('Max', [result, r2_fill], [[30, 30]]) # LEFT2: fg_row_min > res_max (all fg right of result) res_max_p_half = nd('Add', [res_max_1d, 'c_half'], [[30]]) fg_gt_res = nd('Greater', [fg_row_min, res_max_p_half], [([30], TensorProto.BOOL)]) fg_gt_res_f = nd('Cast', [fg_gt_res], [[30]], to=1) l2_elig = nd('Mul', [has_res, w_ge3], [[30]]) l2_elig2 = nd('Mul', [l2_elig, fg_gt_res_f], [[30]]) l2_eroded = erode_vec(l2_elig2, 'l2') # Fill cols < res_min per row rm2_col = nd('Reshape', [res_min_1d, 'shape_30_1'], [[30, 1]]) col_lt_rm = nd('Less', [col_idx_row, rm2_col], [([30, 30], TensorProto.BOOL)]) col_lt_rm_f = nd('Cast', [col_lt_rm], [[30, 30]], to=1) l2e_col = nd('Reshape', [l2_eroded, 'shape_30_1'], [[30, 1]]) l2_mask = nd('MatMul', [l2e_col, 'ones_1_30'], [[30, 30]]) l2_fill = nd('Mul', [l2_mask, col_lt_rm_f], [[30, 30]]) result = nd('Max', [result, l2_fill], [[30, 30]]) # === STEP 7: Mask to background + output === final_mask = nd('Mul', [result, not_fg], [[30, 30]]) fm_4d = nd('Reshape', [final_mask, 'shape_1_1_30_30'], [[1, 1, 30, 30]]) delta = nd('Mul', [fm_4d, 'color3_delta'], [[1, 10, 30, 30]]) nodes.append(helper.make_node('Add', ['input', delta], ['output'])) # === Build model === x = helper.make_tensor_value_info('input', TensorProto.FLOAT, [1, C, H, W]) y = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, C, H, W]) graph = helper.make_graph(nodes, 'task255_v2', [x], [y], initializer=inits, value_info=vis) model = helper.make_model(graph, ir_version=10, opset_imports=[helper.make_opsetid('', 18)]) return model if __name__ == '__main__': print("Building Task 255 ONNX model v2...") model = build_task255() os.makedirs('/app/repo/medal-solvers/optimized', exist_ok=True) output_path = '/app/repo/medal-solvers/optimized/task255.onnx' onnx.save(model, output_path) fsize = os.path.getsize(output_path) print(f" Nodes: {len(model.graph.node)}") print(f" File size: {fsize:,} bytes (limit: {int(1.44*1024*1024):,})") # Quick validation import onnxruntime as ort with open('task-data/task255.json') as f: data = json.load(f) sess = ort.InferenceSession(output_path) all_examples = data['train'] + data['test'] + data['arc-gen'] right_count, wrong_count = 0, 0 for i, ex in enumerate(all_examples): inp = np.zeros((1, 10, 30, 30), dtype=np.float32) for r, row in enumerate(ex['input']): for c, v in enumerate(row): if r < 30 and c < 30: inp[0][v][r][c] = 1.0 result = sess.run(['output'], {'input': inp}) out = (result[0] > 0.0).astype(float) exp = np.zeros((1, 10, 30, 30), dtype=np.float32) for r, row in enumerate(ex['output']): for c, v in enumerate(row): if r < 30 and c < 30: exp[0][v][r][c] = 1.0 if np.array_equal(out, exp): right_count += 1 else: wrong_count += 1 if wrong_count <= 3: diff = (out != exp) ch3_pred = set(zip(*np.where(out[0, 3] > 0))) ch3_exp = set(zip(*np.where(exp[0, 3] > 0))) extra = ch3_pred - ch3_exp missing = ch3_exp - ch3_pred print(f" FAIL {i}: ch3 extra={len(extra)}, missing={len(missing)}") print(f"\nResults: {right_count} pass, {wrong_count} fail out of {len(all_examples)}")