2026-04-23 02:25:50 +01:00
# Tile-Graph Algorithm Map
2026-04-23 04:59:15 +01:00
## Why this map exists
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
The tile-graph path is trying to do one simple, stubborn thing:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Take a fake-pixel mural, cut it into honest one-cell tiles that really belong to the source image, learn which tiles naturally sit beside which, and then lay those tiles back down on a clean output lattice.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
That is the dream.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
When the output looks wrong, this map is here to answer one question:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Where, exactly, did the machine start lying?
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## One-sentence machine
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
The current tile-graph machine is:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
`source image -> edge scout -> atomic opaque regions -> one-cell tile cuts -> per-cell candidate buckets -> learned tile adjacency -> local discrete assignment`
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Or in more visual language:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- the source image is the mural
- connected components are the paint islands
- extracted tiles are the stones we chip out of that mural
- candidate buckets are the bins beside each slot in the final mosaic
- the solver is the mason choosing which chipped stone goes in each slot while trying to keep neighboring stones compatible
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## What was cut away
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
The machine used to carry several ideas that did not belong:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- subsampling the mural before extraction with `source_region_stride`
- ranking region candidates by resemblance to a lattice portrait (`sharp_rgba` , `edge_rgba` )
- papering over missing foreground tiles by injecting `sharp_pixel` or `edge_pixel`
- pretending a learned tile graph existed while actually using sampled color deltas from one cell away in source space
- building and hauling a dedicated tile-graph source-reference object through the core loop
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Those are gone.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
That matters because they were smuggling continuous-solver assumptions back into a path that is supposed to be source-owned and discrete.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## The living machine
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
### Stage 0: Pipeline chooses a lattice
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `run_pipeline(...)` in `src/repixelizer/pipeline.py`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Inputs:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `source_rgba`
- chosen `InferenceResult`
- `target_width`
- `target_height`
- `phase_x`
- `phase_y`
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
The pipeline chooses the grid we are going to commit to. This is not the tile-graph solver yet. This is just choosing the size of the chessboard before we decide which pieces go on it.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Important truth:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- if the lattice is wrong, every later step is forced to cut the mural against the wrong ruler
- but once the lattice is pinned, the tile-graph path now runs directly on that lattice without phase-rerank probes or hybrid sidecars
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
### Stage 1: Edge scout
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 04:18:24 +01:00
2026-04-23 04:59:15 +01:00
- `analyze_tile_graph_source(...)` in `src/repixelizer/analysis.py`
2026-04-23 04:18:24 +01:00
2026-04-23 04:59:15 +01:00
Output:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `TileGraphSourceAnalysis.edge_map`
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
This stage is the scout walking over the mural with a lantern, marking where the sharp cliffs are. It is not deciding colors. It is only pointing out where the paint changes abruptly.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Important variable:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `edge_map[y, x]`
- a per-source-pixel edge strength in `[0, 1]`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Why it exists:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- region extraction needs to know where a component has its sharpest internal detail
- candidate budgeting uses edge strength to give difficult cells more room
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 2: Source pixels are projected onto the output lattice
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `build_tile_graph_model(...)` in `src/repixelizer/tile_graph.py`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Key variables:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- `cell_w`
- `cell_h`
- `projected_coord_x`
- `projected_coord_y`
- `projected_flat_index`
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Every source pixel is asked:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
"If this final grid is the one we believe in, which output cell do you live under?"
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
This is like dropping a transparent graph-paper sheet over the mural and writing the output cell index on every source pixel.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Derived summaries:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `cell_counts_flat`
- how many source pixels fall into each output cell
- `cell_mean_rgba_flat`
- the average source color already living under that cell
- `cell_alpha_support_flat`
- the strongest alpha seen in that cell
- `cell_alpha_mean_flat`
- the average alpha in that cell
- `cell_edge_strength_flat`
- the strongest edge signal seen in that cell
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
These summaries are not a tile portrait from a separate source-reference system. They are direct summaries of the actual source pixels already assigned to that output cell under the chosen lattice.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 3: Atomic opaque regions
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- `_segment_atomic_source_regions(...)`
- CPU path: `_segment_atomic_source_regions_cpu(...)`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Inputs:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- full-resolution `source_rgba`
- full-resolution `edge_map`
- alpha/color join thresholds
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Now the mural is split into paint islands.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Pixels join the same island only if:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- they are opaque enough
- their premultiplied colors are similar enough
- their alpha is similar enough
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
This is not a "cluster by vibes" step. It is literal connected-component labeling over the full-resolution mural.
2026-04-23 02:25:50 +01:00
Important consequence:
2026-04-23 04:59:15 +01:00
- every opaque source pixel belongs to some component
- if an occupied output cell later ends up with no real extracted tile, that is not normal; it is a bug or a failure in cutting/projection logic
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 4: Cut one-cell tiles out of each component
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `_extract_source_region_tiles(...)`
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Inputs:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- `components`
- `flat_rgba`
- `flat_edge`
- `flat_x`
- `flat_y`
- lattice geometry: `cell_w` , `cell_h` , `phase_x` , `phase_y`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
This is the quarry.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
For each paint island, we try to chip out cell-sized stones.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
There are two modes:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- ordinary components:
- start from the centroid and edge peak
- accept a one-cell window if it contains enough of the component
- march outward one cell at a time
- elongated stroke-like components:
- estimate the component’ s principal axis
- seed along that axis
- cut tiles in bands so a long stroke is not immediately turned into a rectangular blob
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Important variables inside each extracted tile:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `rep_linear`
- the literal source pixel index chosen to represent the tile
- `rep_rgba`
- the tile color
- `area_ratio`
- how much component area the tile owns relative to one output cell
- `coverage`
- `area_ratio` clipped to `[0, 1]`
- `edge_peak`
- strongest edge value inside that tile footprint
- `source_center_x` , `source_center_y`
- where this tile lives in source space
- `coord_x` , `coord_y` , `flat_index`
- which output cell this tile projects into
- `component_id`
- which paint island it came from
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Natural-language picture:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
The component is a strip of stained glass. We are cutting out little panes, each about one output cell wide, and tagging where each pane came from.
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
### Stage 5: Fill empty occupied cells honestly
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Still inside:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `_extract_source_region_tiles(...)`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
After the first pass of tile cutting, some output cells may still have no tile in their bucket even though component pixels really do overlap them.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
To fix that, the builder does an overlap-based empty-cell fill:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- for each component, look at every output cell it physically overlaps
- if that bucket is still empty, add one overlap tile there
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
This matters because:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- a foreground cell is allowed to have multiple candidates
- a foreground cell is not allowed to have zero real extracted candidates
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Background-only cells are different:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- they have no opaque source ownership
- they get a transparent candidate later in model building
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 6: Learn adjacency from extracted tiles
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Still inside:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `_extract_source_region_tiles(...)`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Each extracted tile now looks one cell away in all four directions and asks:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
"Among the tiles that actually landed in that neighboring output slot, which one looks like my real neighbor back in source space?"
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
For each direction, we search the neighboring bucket and choose the best observed neighbor by:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- source-center displacement closeness
- same-component tie preference
- area fit
- coverage
- edge strength
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Stored per tile:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `neighbor_rgba[4, 4]`
- `neighbor_mask[4]`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
This is the first honest adjacency graph the tile-graph path has had.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
It is not:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- sampled one-cell-away colors from the source image
- a lattice portrait
- a guessed delta field
2026-04-23 02:25:50 +01:00
It is:
2026-04-23 04:59:15 +01:00
- "this extracted stone most naturally sat beside that extracted stone"
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 7: Build per-cell candidate buckets
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `build_tile_graph_model(...)`
- helper: `_select_source_region_candidates(...)`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Each output cell gets a bucket of legal stones.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Candidate selection now keeps only tile-owned signals:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- area fit
- coverage
- edge peak
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
It does not use:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `sharp_rgba` similarity
- `edge_rgba` similarity
- injected sharp/edge fallback pixels
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Important rule:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- if a cell has real source-owned region tiles, those are the truth
- if a cell has no opaque source support, it gets a transparent candidate
- if a cell has opaque source support but no extracted region candidate, the build fails loudly
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
That last rule is deliberate. The old machine would quietly make something up. The new one would rather stop the line than lie.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Additional background option:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- if `cell_alpha_mean_flat < 0.98` , a transparent candidate is also added
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
This lets the solver choose "leave this slot empty" in partially occupied or fringe cells instead of being forced to place an opaque stone just because a tiny sliver of source detail touched the slot.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 8: The solver model
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Dataclass:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `TileGraphModel`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Current essential fields:
2026-04-23 02:25:50 +01:00
- `candidate_rgba`
- `candidate_area_ratio`
- `candidate_coverage`
2026-04-23 04:59:15 +01:00
- `candidate_edge_peak`
- `candidate_neighbor_rgba`
- `candidate_neighbor_mask`
- `cell_candidate_offsets`
- `cell_candidate_indices`
- `cell_mean_rgba`
- `cell_alpha_mean`
- `cell_edge_strength`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
This is the parts tray beside the machine.
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- the first block describes the legal stones
- the second block says which stones belong to which output slot
- the last block is the local source evidence already living under each slot
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
### Stage 9: Unary cost
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 03:11:56 +01:00
2026-04-23 02:25:50 +01:00
- `_tile_graph_unary_cost_torch(...)`
2026-04-23 04:59:15 +01:00
Current unary terms:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `color_error`
- how far the candidate color is from the actual mean source color already under that output cell
- `area_error`
- how far the candidate footprint is from one cell
- `alpha_error`
- how far the candidate alpha is from the actual mean alpha under that cell
- `coverage_error`
- how incomplete the candidate’ s source ownership is
- `edge_error`
- how far the candidate’ s edge peak is from the strongest edge already under that cell
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Natural-language picture:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
This is the bouncer at each slot saying:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
"Does this stone even look like it belongs in the patch of mural that sits under this square?"
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Important difference from the old machine:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- this is local source support
- not a separate lattice portrait pretending to know the answer in advance
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 10: Pairwise adjacency cost
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Functions:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `_pair_penalty_selected_torch(...)`
- `_pair_penalty_option_right_torch(...)`
- `_pair_penalty_option_left_torch(...)`
- `_pair_penalty_option_down_torch(...)`
- `_pair_penalty_option_up_torch(...)`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it means:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Now the mason cares about seams.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
If tile A says it naturally expects tile B to the right, then choosing a very different right neighbor should cost something.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
The current pairwise cost compares:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- the actually chosen neighbor color
- against the neighbor color learned from extracted tiles
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
This is now a real observed compatibility signal.
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
It is no longer:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- "the source image one cell away from this center happened to look like X, so maybe that is the right delta"
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### Stage 11: Checkerboard parity refinement
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Function:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- `optimize_tile_graph(...)`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What it does:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
1. build the model
2. compute unary cost
3. choose an initial argmin candidate per cell
4. alternate parity updates over the grid
5. keep the initial assignment if the refinement step makes source-lattice fidelity worse
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Natural-language picture:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
The mason lays down a first draft, then alternates black squares and white squares of the chessboard, trying to improve local seam compatibility without moving everything at once.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Important truth:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- this is still a local greedy/discrete smoother
- it is not a global optimal graph solver
- if the initial candidate buckets are wrong, parity updates will not save the image
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## Data dictionary
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `flat_rgba_np`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- full-resolution source pixels flattened into `[pixel, rgba]`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `projected_flat_index`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- for each source pixel, which output cell it belongs to under the chosen lattice
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `components`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- connected opaque paint islands in the source
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `region_buckets[flat_index]`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- all extracted real tiles currently legal for one output cell
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `candidate_rgba`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- literal colors the solver is allowed to place
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `candidate_neighbor_rgba`
2026-04-23 03:00:51 +01:00
2026-04-23 04:59:15 +01:00
- per-candidate remembered neighbor colors from real extracted-tile adjacency
2026-04-23 03:00:51 +01:00
2026-04-23 04:59:15 +01:00
### `cell_mean_rgba`
2026-04-23 03:00:51 +01:00
2026-04-23 04:59:15 +01:00
- actual average source color already living under each output cell
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `cell_alpha_mean`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- actual average source alpha already living under each output cell
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
### `cell_edge_strength`
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- strongest edge signal already living under each output cell
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## What this machine is trying to maximize
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
In plain language:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- choose only real, source-owned stones
- prefer stones that genuinely fit the patch of mural beneath the slot
- prefer neighboring stones that were actually observed beside each other
- never silently hallucinate a foreground tile just because the lattice wanted one
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## What would make the machine lie now
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
If the output is still wrong after this pass, the likely failure points are no longer the old ones.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
The remaining likely lies are:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- region cutting still slices a component into the wrong one-cell panes
- candidate truncation still throws away the only good tile for a difficult slot
- learned adjacency still chooses the wrong observed neighbor when multiple neighbors are plausible
- the parity solver is still too local and can settle into a bad arrangement even with legal tiles
- the lattice itself is wrong, which means the whole quarry is being cut against the wrong ruler
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## Current reality check
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Pinned cleaned badge run:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- target: `126x126`
- phase: `(0.0, -0.2)`
- mode: `tile-graph`
- phase rerank: off
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
Current result after the latest cut:
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
- initial source-fidelity: `0.1814`
- final source-fidelity: `0.1814`
- the solver kept the initial assignment because refinement did not improve it
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
That is still not good enough, but it is dramatically more honest than the earlier architectural-collapse run around `0.5055` .
2026-04-23 03:11:56 +01:00
2026-04-23 04:59:15 +01:00
In other words:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
- the machine is no longer babbling nonsense
- it is still not carving the right stones often enough
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
## Big-picture judgment
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Does the current machine make sense?
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
Yes, much more than before.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
The data now flows in one believable direction:
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
1. observe the mural
2. find real paint islands
3. cut one-cell stones out of those islands
4. learn which stones really sat beside which
5. choose among those stones for each output slot
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
That is a coherent mental model.
2026-04-23 02:25:50 +01:00
2026-04-23 04:59:15 +01:00
What is still missing is not conceptual honesty.
2026-04-23 03:00:51 +01:00
2026-04-23 04:59:15 +01:00
What is still missing is quality in the stone cutting and compatibility choice.