Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
991f048
add simple.py
cristianoc Sep 10, 2024
e03e7ba
Implement symmetry detection and inpainting transformation
cristianoc Sep 11, 2024
4fe25c0
Update symmetry.py
cristianoc Sep 11, 2024
75a1a74
refactor
cristianoc Sep 11, 2024
131824b
Enhance symmetry detection and grid filling
cristianoc Sep 11, 2024
7c89ddc
anti-diagonal
cristianoc Sep 11, 2024
3d6d8e6
Add anti-diagonal symmetry support
cristianoc Sep 11, 2024
b5d47dd
Refactor symmetry handling and improve periodic symmetry detection
cristianoc Sep 11, 2024
decb7ab
format
cristianoc Sep 11, 2024
fd019f1
Refactor symmetry detection and implement non-periodic symmetry
cristianoc Sep 11, 2024
64d3b7d
Refactor inpainting transform and symmetry handling
cristianoc Sep 11, 2024
df81fa5
Refine inpainting transform and symmetry detection
cristianoc Sep 11, 2024
9748dd5
restore normal operations
cristianoc Sep 11, 2024
77688f6
open to all examples
cristianoc Sep 11, 2024
e9c4294
solve function does not need to take the state
cristianoc Sep 11, 2024
59983cb
Refactor type annotations and simplify State type
cristianoc Sep 11, 2024
815b3f0
clean up printing
cristianoc Sep 11, 2024
a80e16f
refactor
cristianoc Sep 11, 2024
41ac6b1
Refactor inpainting_xform and improve symmetry handling
cristianoc Sep 11, 2024
550d76d
Enhance xform logging and add display flag for inpainting task
cristianoc Sep 11, 2024
600839d
add equality modulo offset
cristianoc Sep 11, 2024
73e87b2
update tests
cristianoc Sep 12, 2024
e817a75
comment
cristianoc Sep 12, 2024
4c20fdc
Update symmetry.py
cristianoc Sep 12, 2024
fb54de8
Improve symmetry detection and handling in inpainting
cristianoc Sep 12, 2024
7484ed3
Adjust symmetry detection
cristianoc Sep 12, 2024
7528354
cleanup
cristianoc Sep 12, 2024
5ea50a4
more cleanup
cristianoc Sep 12, 2024
b9b6028
more cleanup
cristianoc Sep 12, 2024
665d839
mooore cleanup
cristianoc Sep 12, 2024
6d4d826
fix coherence
cristianoc Sep 12, 2024
2fed9cb
undo breaking
cristianoc Sep 12, 2024
de94bcc
half fix diagonal
cristianoc Sep 12, 2024
3775b8a
fix diagonal
cristianoc Sep 12, 2024
bf7edfa
fix anti-diagonal
cristianoc Sep 12, 2024
0d8573f
Fix symmetry calculations and add mathematical derivations
cristianoc Sep 12, 2024
383e29c
comments
cristianoc Sep 12, 2024
cfada6e
only do in-painting puzzles
cristianoc Sep 13, 2024
bd31e0c
Generate random in-painting puzzles.
cristianoc Sep 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion simple.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"training_data":50.0,"evaluation_data":0.0}
{"training_data":75.0,"evaluation_data":60.0}
12 changes: 7 additions & 5 deletions src/grid_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
# Direction vectors for 8 directions (N, NE, E, SE, S, SW, W, NW)
DIRECTIONS8 = [(0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1)]

# Symmetries: horizontal, vertical, diagonal, anti-diagonal w.r.t. the origin
class Symmetry(Enum):
HORIZONTAL = auto()
VERTICAL = auto()
DIAGONAL = auto() # x == y
ANTI_DIAGONAL = auto() # x == -y

from enum import Enum, auto
from typing import NamedTuple

Expand Down Expand Up @@ -104,11 +111,6 @@ class Rotation(str, Enum):
CLOCKWISE = "Clockwise"
COUNTERCLOCKWISE = "CounterClockwise"


class Axis(str, Enum):
HORIZONTAL = "Horizontal"
VERTICAL = "Vertical"

Color = NewType("Color", int)

# Define the custom color scheme as a list of colors
Expand Down
81 changes: 73 additions & 8 deletions src/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Cell,
GridData,
Rotation,
Axis,
Symmetry,
BLACK,
Color,
RigidTransformation,
Expand All @@ -22,7 +22,6 @@
GREEN,
RED,
YELLOW,
Axis,
Rotation,
color_scheme,
)
Expand Down Expand Up @@ -192,7 +191,10 @@ def create_object(
return Object(origin=(min_x, min_y), data=data._data)

connected_components = find_connected_components(
grid=self, diagonals=diagonals, allow_black=allow_black, multicolor=multicolor
grid=self,
diagonals=diagonals,
allow_black=allow_black,
multicolor=multicolor,
)
detected_objects = [
create_object(self, component, background_color)
Expand All @@ -212,6 +214,14 @@ def flipud(self) -> "Object":
x: np.ndarray = np.flipud(self._data.copy())
return Object(origin=self.origin, data=x)

def flip_diagonal(self) -> "Object":
x: np.ndarray = self._data.copy().T
return Object(origin=self.origin, data=x)

def flip_anti_diagonal(self) -> "Object":
x: np.ndarray = np.flipud(np.fliplr(self._data.copy()))
return Object(origin=self.origin, data=x)

def invert(self) -> "Object":
x: np.ndarray = 1 - self._data.copy()
return Object(origin=self.origin, data=x)
Expand All @@ -227,11 +237,17 @@ def translate_in_place(self, dx: int, dy: int) -> None:
new_origin = (self.origin[0] + dx, self.origin[1] + dy)
self.origin = new_origin

def flip(self, axis: Axis) -> "Object":
if axis == Axis.HORIZONTAL:
def flip(self, symmetry: Symmetry) -> "Object":
if symmetry == Symmetry.HORIZONTAL:
return self.fliplr()
else:
elif symmetry == Symmetry.VERTICAL:
return self.flipud()
elif symmetry == Symmetry.DIAGONAL:
return self.flip_diagonal()
elif symmetry == Symmetry.ANTI_DIAGONAL:
return self.flip_anti_diagonal()
else:
raise ValueError(f"Unknown symmetry type: {symmetry}")

def num_cells(self, color: Optional[int]) -> int:
if color is None:
Expand Down Expand Up @@ -418,6 +434,55 @@ def detect_colored_objects(
"""
return visual_cortex.find_colored_objects(self, background_color)

def is_symmetric(self, symmetry: Symmetry) -> bool:
"""
Check if the object is symmetric with respect to the given symmetry type.

Args:
symmetry (Symmetry): The type of symmetry to check for.

Returns:
bool: True if the object is symmetric, False otherwise.
"""
data = self._data
width, height = self.size

if symmetry == Symmetry.HORIZONTAL: # (x, y) == (w-x-1, y)
return np.array_equal(data, np.fliplr(data))

elif symmetry == Symmetry.VERTICAL: # (x, y) == (x, h-y-1)
return np.array_equal(data, np.flipud(data))

elif symmetry == Symmetry.DIAGONAL: # (x, y) == (y, x)
if height != width:
return False
return np.array_equal(data, data.T) # Transpose for diagonal symmetry

elif symmetry == Symmetry.ANTI_DIAGONAL: # (x, y) == (w-x-1, h-y-1)
if height != width:
return False
# fliplr:
# then fliplr:
return np.array_equal(data, np.fliplr(data.T))

else:
raise ValueError(f"Unknown symmetry type: {symmetry}")

def find_symmetries(self) -> List[Symmetry]:
"""
Find all symmetries of the object.
"""
symmetries = []
if self.is_symmetric(Symmetry.HORIZONTAL):
symmetries.append(Symmetry.HORIZONTAL)
if self.is_symmetric(Symmetry.VERTICAL):
symmetries.append(Symmetry.VERTICAL)
if self.is_symmetric(Symmetry.DIAGONAL):
symmetries.append(Symmetry.DIAGONAL)
if self.is_symmetric(Symmetry.ANTI_DIAGONAL):
symmetries.append(Symmetry.ANTI_DIAGONAL)
return symmetries


def display(
input: Object, output: Object = Object(np.array([[0]])), title: Optional[str] = None
Expand Down Expand Up @@ -522,12 +587,12 @@ def test_rotate():

def test_flip():
grid = Object(np.array([[1, 2], [3, 4]]))
flipped_grid = grid.flip(Axis.HORIZONTAL)
flipped_grid = grid.flip(Symmetry.HORIZONTAL)
assert flipped_grid == Object(
np.array([[2, 1], [4, 3]])
), f"Expected [[2, 1], [4, 3]], but got {flipped_grid}"

flipped_grid = grid.flip(Axis.VERTICAL)
flipped_grid = grid.flip(Symmetry.VERTICAL)
assert flipped_grid == Object(
np.array([[3, 4], [1, 2]])
), f"Expected [[3, 4], [1, 2]], but got {flipped_grid}"
Expand Down
Loading