Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions experiments/convert_to_pdf.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

# Define the input and output files
input_file="parametric_expressivity.md"
output_file="parametric_expressivity.pdf"

# Check if the input file exists
if [ -f "$input_file" ]; then
echo "Converting $input_file to PDF..."
pandoc "$input_file" -o "$output_file" --pdf-engine=pdflatex
echo "Conversion complete: $output_file created."
else
echo "Error: $input_file not found."
exit 1
fi
23 changes: 23 additions & 0 deletions experiments/grid_xform_spec_10.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# type: ignore

"""
Describe this transformation from grids to grids (ARC challenge).
"""


class GridTransformSpec:
colors = ["blue", "red", "green" "yellow"]

def Pre(self):
Objs = self.find_objects()
assert all(obj.getColor() == "grey" for obj in Objs1)
Objs1 = sorted(Objs, key=lambda obj: obj.height)
return Objs

def Post(self):
Objs = self.Pre()

def obj_func(obj, index):
color = colors[index]
return obj.copy().setColor(color)
return Grid.from_objects(Objs, obj_func=obj_func)
39 changes: 39 additions & 0 deletions experiments/grid_xform_spec_5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# type: ignore

"""
Describe this transformation from grids to grids (ARC challenge).
Notice that transformations are described as predicates `Pre --> Post` where `Pre` describes the grid before the transformation, and `Post` the grid after the transformation.
To connect different predicates, `&&` is used for conjunction.
For example ` Obj1.getColor() == Obj2.getColor && Obj1.getSize() = (3,3)`.

Note that NestedGrid(origin, size) return a new nested grid, where there is a sub-grid of size `size` at each coordinate `(x,y)`. At coordinate `(0,0)`, the nested grid contains the grid of size `size` at position `origin` in the initial grid.
All operations are immutable. In particular setXXX returns a copy of the receives with some property set as in the argument.
"""


class GridTransformSpec:
def Pre(self):
Objs = self.find_objects()
Obj = Objs.max()
Origin = Obj.getOrigin()
Size = Obj.getSize()
NestedGrid = self.grid_to_subgrids(subgrid_size=Size, origin=Origin)
return [NestedGrid, Obj]

def Post():
NG0, Obj0 = self.Pre()

def clamp(p):
return [max(min(p[0], 1), -1), max(min(p[1], 1), -1)]

def is_cardinal_or_diagonal(p):
return p[0] == 0 or p[1] == 0 or abs(p[0]) == abs(p[1])

def new_color(p):
Obj = NG0[clamp(p)]
return Obj.getColor() if is_cardinal_or_diagonal(p): else 0
NG1 = create_grid_of_objects(subgrid_size=Size,
subgrid_func=lambda p: Obj.copy().setColor(get_color(p)))
Grid1 = NG1.flatten()
Grid1 = Grid1.shift(Origin)
return Grid1
78 changes: 78 additions & 0 deletions experiments/parametric_expressivity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@


### Introduction

In the ARC challenge DSL, transformations (xforms) map one grid to another. To formalize these transformations, we use **shape types** to describe the sets of grids that a transformation can operate on. This allows us to distinguish between non-parametric and parametric transformations, depending on whether the transformations are specific to particular grid types or generalized using type variables.

### Shape Types

A **shape type** $S$ denotes a set of grids. This can capture structure such as dimensions, content patterns, or other properties. For example:

- $S$ could represent all grids of a certain size, like all $3 \times 3$ grids.
- $S$ could also represent grids with a specific pattern, such as grids where all cells along the diagonal are the same.

Shape types include singleton types, denoting specific grids, and type variables `X` of kind `Grid` (for now).

### Transformations

A **transformation** $\text{xf}$ is a total function $Grid \rightarrow Grid$.

### Specs
A **spec** $[S,T]$ denotes the set of transformations $\text{xf}$ such that $\forall G \in Grid. G \in S \Rightarrow \text{xf}(G) \in T$

In addition, $[S1,T1] \wedge [S2,T2] \wedge [S3,T3]$ is also a spec, denoting the intersection.

### Matching
A **spec** $[S,T]$ matches an example $(I,O)$ if

1. $I \in S$
2. $\forall \text{xf}. \text{xf} \in [S,T] \Rightarrow \text{xf}(I) = O$

Intuitively, matching means that the spec admits the input $I$, and exactly specifies the behaviour on it.

### Non-Parametric Matching

Given examples $I_i \rightarrow O_i$ for $i = 1..3$, the following spec matches all of them:

$$[I1,O1] \wedge [I2,O2] \wedge [I3,O3]$$

where we write `I` as the singleton shape type denoting exactly `I`.

Here's an example

```python
def flip_2x2(grid):
# Assumes grid is 2x2
return [[grid[0][1], grid[0][0]],
[grid[1][1], grid[1][0]]]
```

This transformation, `flip_2x2`, is specifically designed to work only for $2 \times 2$ grids. It does not generalize to other grid sizes.


### Parametric Spec

Consider this example

```python
def flip_grid(grid):
# Flip any grid horizontally
return [row[::-1] for row in grid]
```

This transformation, `flip_grid`, works for grids of any size by flipping each row horizontally.

In addition to the non-parametric spec above, this transformation satisfies spec $[X, Flip(X)]$ where:

- $X$ represents any grid.
- $\text{Flip}(X)$ denotes the grid $X$ flipped horizontally.

### Genericity of Specs

A spec $\text{spec1}$ is more specific than $\text{spec2}$ if it is a strict subset.
In the examples above, the non-parametric spec is more specific than the parametric one.

### Genericity of Transformation

A transformation $\text{xf1}$ is more generic than $\text{xf2}$ if it satisfies more generic specs.
In the examples above, `flip_grid` is more generic than `flip_2x2`.
Binary file added experiments/parametric_expressivity.pdf
Binary file not shown.