Skip to content

Commit 0cf29c7

Browse files
committed
Revert "Optimize entropy selection with bucket-based data structure"
This reverts commit 644b332.
1 parent 25c4376 commit 0cf29c7

File tree

1 file changed

+18
-69
lines changed

1 file changed

+18
-69
lines changed

lib/wave_function_collapse/model.rb

Lines changed: 18 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ def initialize(tiles, width, height)
2929
@height.times { |y| @width.times { |x| @cells << Cell.new(x, y, @tiles.shuffle) } }
3030
@uncollapsed_cells = Set.new(@cells.reject(&:collapsed))
3131
@max_entropy = @tiles.length
32-
33-
# Initialize entropy buckets for O(1) minimum entropy lookup
34-
@entropy_buckets = Hash.new { |h, k| h[k] = Set.new }
35-
@min_entropy = @max_entropy
36-
@uncollapsed_cells.each { |cell| @entropy_buckets[cell.entropy].add(cell) }
3732
end
3833

3934
def build_tile_adjacencies
@@ -62,45 +57,6 @@ def build_tile_adjacencies
6257
end
6358
end
6459

65-
# Update entropy bucket when a cell's entropy changes
66-
def update_cell_entropy(cell, old_entropy, new_entropy)
67-
return if old_entropy == new_entropy
68-
69-
# Remove from old bucket
70-
@entropy_buckets[old_entropy].delete(cell)
71-
@entropy_buckets.delete(old_entropy) if @entropy_buckets[old_entropy].empty?
72-
73-
# Add to new bucket (unless collapsed)
74-
if new_entropy > 1
75-
@entropy_buckets[new_entropy].add(cell)
76-
end
77-
78-
# Update minimum entropy if needed
79-
update_min_entropy
80-
end
81-
82-
# Remove cell from entropy tracking (when collapsed or removed)
83-
def remove_from_entropy_buckets(cell)
84-
# Cell might be in any bucket, so search all buckets to remove it
85-
# This is still O(1) amortized since we only check a few entropy levels
86-
@entropy_buckets.each do |entropy, bucket|
87-
if bucket.delete(cell)
88-
@entropy_buckets.delete(entropy) if bucket.empty?
89-
break
90-
end
91-
end
92-
update_min_entropy
93-
end
94-
95-
# Find the current minimum entropy value
96-
def update_min_entropy
97-
if @entropy_buckets.empty?
98-
@min_entropy = nil
99-
else
100-
@min_entropy = @entropy_buckets.keys.min
101-
end
102-
end
103-
10460
def cell_at(x, y)
10561
@cells[@width * y + x]
10662
end
@@ -137,10 +93,8 @@ def prepend_empty_row
13793
new_cell = Cell.new(x, @height - 1, @tiles)
13894
@cells << new_cell
13995
@uncollapsed_cells.add(new_cell)
140-
@entropy_buckets[new_cell.entropy].add(new_cell)
14196
x = x.succ
14297
end
143-
update_min_entropy
14498
@width.times { |x|
14599
evaluate_neighbor(cell_at(x, @height - 2), :up)
146100
}
@@ -169,13 +123,8 @@ def generate_grid
169123
end
170124

171125
def process_cell(cell)
172-
old_entropy = cell.entropy
173126
cell.collapse
174127
@uncollapsed_cells.delete(cell)
175-
# Remove from the bucket it was in before collapsing
176-
@entropy_buckets[old_entropy]&.delete(cell)
177-
@entropy_buckets.delete(old_entropy) if @entropy_buckets[old_entropy]&.empty?
178-
update_min_entropy
179128
return if @uncollapsed_cells.empty?
180129

181130
propagate(cell)
@@ -222,32 +171,32 @@ def evaluate_neighbor(source_cell, evaluation_direction)
222171
new_tiles << neighbor_tile if valid_tile_ids[neighbor_tile.__id__]
223172
end
224173

225-
unless new_tiles.empty?
226-
old_entropy = neighbor_cell.entropy
227-
neighbor_cell.tiles = new_tiles
228-
new_entropy = neighbor_cell.entropy
229-
230-
# Update entropy buckets if entropy changed
231-
# update_cell_entropy handles removal from buckets when cell collapses (entropy=1)
232-
update_cell_entropy(neighbor_cell, old_entropy, new_entropy) if old_entropy != new_entropy
233-
234-
# Remove from uncollapsed set if collapsed
235-
@uncollapsed_cells.delete(neighbor_cell) if neighbor_cell.collapsed
236-
end
174+
neighbor_cell.tiles = new_tiles unless new_tiles.empty?
175+
@uncollapsed_cells.delete(neighbor_cell) if neighbor_cell.collapsed
237176

238177
# if the number of tiles changed, we need to evaluate current cell's neighbors now
239178
propagate(neighbor_cell) if neighbor_cell.tiles.length != original_tile_count
240179
end
241180

242181
def find_lowest_entropy
243-
return nil if @min_entropy.nil?
182+
return nil if @uncollapsed_cells.empty?
183+
184+
min_e = nil
185+
acc = []
186+
187+
@uncollapsed_cells.each do |cell|
188+
ce = cell.entropy
244189

245-
# Get cells with minimum entropy from bucket (O(1) instead of O(n))
246-
min_entropy_cells = @entropy_buckets[@min_entropy]
247-
return nil if min_entropy_cells.nil? || min_entropy_cells.empty?
190+
if min_e.nil? || ce < min_e
191+
min_e = ce
192+
acc.clear
193+
acc << cell
194+
elsif ce == min_e
195+
acc << cell
196+
end
197+
end
248198

249-
# Sample randomly from cells with same minimum entropy
250-
min_entropy_cells.to_a.sample
199+
acc.sample
251200
end
252201
end
253202
end

0 commit comments

Comments
 (0)