forked from tudo-seal/cls-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
54d5b35
commit 1602d78
Showing
5 changed files
with
556 additions
and
0 deletions.
There are no files selected for viewing
130 changes: 130 additions & 0 deletions
130
tests/benchmarks/benchmark_maze_loopfree_generate_and_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
from functools import partial, cache | ||
|
||
from collections.abc import Callable, Mapping | ||
import timeit | ||
from itertools import product | ||
from typing import Any, cast | ||
from clsp.dsl import DSL | ||
from clsp.enumeration import Tree, enumerate_terms, interpret_term | ||
from clsp.fcl import FiniteCombinatoryLogic | ||
|
||
from clsp.types import Constructor, Literal, Param, LVar, Type | ||
|
||
|
||
@cache | ||
def visited(path: Tree[Any]) -> list[tuple[int, int]]: | ||
if path.root == "START": | ||
return [] | ||
return [cast(tuple[int, int], path.parameters["a"].root)] + visited(path.parameters["pos"]) | ||
|
||
|
||
def loopfree(term: Tree[Any]) -> bool: | ||
visited_positions = visited(term) | ||
return len(visited_positions) == len(set(visited_positions)) | ||
|
||
|
||
def is_free(size: int, pos: tuple[int, int]) -> bool: | ||
""" | ||
Create a maze in the form: | ||
XXX...XXX | ||
X X | ||
X X...X X | ||
. ..... . | ||
X X...X X | ||
X X | ||
X X...XXX | ||
X X | ||
XXX...XXX | ||
""" | ||
|
||
col, row = pos | ||
if row in [0, size - 1, size - 3]: | ||
return True | ||
else: | ||
if row == size - 2 and col == size - 1: | ||
return False | ||
if col in [0, size - 1]: | ||
return True | ||
return False | ||
|
||
|
||
def main(SIZE: int = 10, output: bool = True) -> float: | ||
visited.cache_clear() | ||
U: Callable[[int, int, str], str] = lambda b, _, p: f"{p} => UP({b})" | ||
D: Callable[[int, int, str], str] = lambda b, _, p: f"{p} => DOWN({b})" | ||
L: Callable[[int, int, str], str] = lambda b, _, p: f"{p} => LEFT({b})" | ||
R: Callable[[int, int, str], str] = lambda b, _, p: f"{p} => RIGHT({b})" | ||
|
||
pos: Callable[[str], Type] = lambda ab: Constructor("pos", (LVar(ab))) | ||
|
||
repo: Mapping[ | ||
Callable[[int, int, str], str] | str, | ||
Param | Type, | ||
] = { | ||
U: DSL() | ||
.Use("b", "int2") | ||
.Use("a", "int2") | ||
.As(lambda b: (b[0], b[1] + 1)) | ||
.Use("pos", pos("a")) | ||
# .With(lambda b, pos: b not in visited(pos)) | ||
.In(pos("b")), | ||
D: DSL() | ||
.Use("b", "int2") | ||
.Use("a", "int2") | ||
.As(lambda b: (b[0], b[1] - 1)) | ||
.Use("pos", pos("a")) | ||
# .With(lambda b, pos: b not in visited(pos)) | ||
.In(pos("b")), | ||
L: DSL() | ||
.Use("b", "int2") | ||
.Use("a", "int2") | ||
.As(lambda b: (b[0] + 1, b[1])) | ||
.Use("pos", pos("a")) | ||
# .With(lambda b, pos: b not in visited(pos)) | ||
.In(pos("b")), | ||
R: DSL() | ||
.Use("b", "int2") | ||
.Use("a", "int2") | ||
.As(lambda b: (b[0] - 1, b[1])) | ||
.Use("pos", pos("a")) | ||
# .With(lambda b, pos: b not in visited(pos)) | ||
.In(pos("b")), | ||
"START": "pos" @ (Literal((0, 0), "int2")), | ||
} | ||
|
||
# literals = {"int": list(range(SIZE))} | ||
literals = {"int2": list(filter(partial(is_free, SIZE), product(range(SIZE), range(SIZE))))} | ||
|
||
if output: | ||
for row in range(SIZE): | ||
for col in range(SIZE): | ||
if is_free(SIZE, (col, row)): | ||
print("-", end="") | ||
else: | ||
print("#", end="") | ||
print("") | ||
|
||
fin = "pos" @ (Literal((SIZE - 1, SIZE - 1), "int2")) | ||
|
||
fcl: FiniteCombinatoryLogic[Callable[[int, int, str], str] | str] = FiniteCombinatoryLogic( | ||
repo, literals=literals | ||
) | ||
|
||
start = timeit.default_timer() | ||
grammar = fcl.inhabit(fin) | ||
|
||
num_terms = 0 | ||
for term in enumerate_terms(fin, grammar): | ||
if loopfree(term): | ||
t = interpret_term(term) | ||
if output: | ||
print(t) | ||
num_terms += 1 | ||
if num_terms == 2: | ||
break | ||
|
||
return timeit.default_timer() - start | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
114 changes: 114 additions & 0 deletions
114
tests/benchmarks/benchmark_maze_posparams_onlytermparam.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
from collections.abc import Callable, Mapping | ||
from functools import cache | ||
import timeit | ||
from typing import Optional | ||
from clsp.dsl import DSL | ||
from clsp.enumeration import Tree, enumerate_terms, interpret_term | ||
from clsp.fcl import FiniteCombinatoryLogic | ||
|
||
from clsp.types import Constructor, Literal, Param, Type | ||
|
||
|
||
def plus_one(a: str) -> Callable[[Mapping[str, Literal]], int]: | ||
def _inner(vars: Mapping[str, Literal]) -> int: | ||
return int(1 + vars[a].value) | ||
|
||
return _inner | ||
|
||
|
||
@cache | ||
def current_position(pos: Tree[str]) -> tuple[int, int]: | ||
curr_pos = (0, 0) | ||
while pos.root != "START": | ||
if pos.root == "D": | ||
curr_pos = (curr_pos[0], curr_pos[1] + 1) | ||
elif pos.root == "U": | ||
curr_pos = (curr_pos[0], curr_pos[1] - 1) | ||
elif pos.root == "L": | ||
curr_pos = (curr_pos[0] - 1, curr_pos[1]) | ||
elif pos.root == "R": | ||
curr_pos = (curr_pos[0] + 1, curr_pos[1]) | ||
pos = pos.parameters["pos"] | ||
return curr_pos | ||
|
||
|
||
@cache | ||
def is_free(pos: tuple[int, int], SIZE: int, next_step: Optional[tuple[int, int]] = None) -> bool: | ||
col, row = pos | ||
if next_step is not None: | ||
col = col + next_step[0] | ||
row = row + next_step[1] | ||
if col < 0 or row < 0 or col >= SIZE or row >= SIZE: | ||
return False | ||
SEED = 0 | ||
if row == col: | ||
return True | ||
else: | ||
return pow(11, (row + col + SEED) * (row + col + SEED) + col + 7, 1000003) % 5 > 0 | ||
|
||
|
||
def main(SIZE: int = 5, output: bool = True) -> float: | ||
repo: Mapping[ | ||
str, | ||
Param | Type, | ||
] = { | ||
"U": DSL() | ||
.Use("pos", Constructor("pos")) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(0, -1))) | ||
.In(Constructor("pos")), | ||
"D": DSL() | ||
.Use("pos", Constructor("pos")) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(0, 1))) | ||
.In(Constructor("pos")), | ||
"L": DSL() | ||
.Use("pos", Constructor("pos")) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(-1, 0))) | ||
.In(Constructor("pos")), | ||
"R": DSL() | ||
.Use("pos", Constructor("pos")) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(1, 0))) | ||
.In(Constructor("pos")), | ||
"START": "pos" @ (Literal((0, 0), "int2")), | ||
"END": DSL() | ||
.Use("pos", Constructor("pos")) | ||
.With(lambda pos: current_position(pos) == (SIZE - 1, SIZE - 1)) | ||
.In(Constructor("end")), | ||
} | ||
|
||
# literals = {"int": list(range(SIZE))} | ||
# literals = {"int2": list(filter(is_free, product(range(SIZE), range(SIZE))))} | ||
|
||
if output: | ||
for row in range(SIZE): | ||
for col in range(SIZE): | ||
if is_free((col, row), SIZE): | ||
print("-", end="") | ||
else: | ||
print("#", end="") | ||
print("") | ||
|
||
fin = Constructor("end") | ||
|
||
fcl: FiniteCombinatoryLogic[str] = FiniteCombinatoryLogic(repo) | ||
|
||
start = timeit.default_timer() | ||
grammar = fcl.inhabit(fin) | ||
|
||
interpretation = { | ||
"U": lambda pos: f"{pos} => UP", | ||
"D": lambda pos: f"{pos} => DOWN", | ||
"L": lambda pos: f"{pos} => LEFT", | ||
"R": lambda pos: f"{pos} => RIGHT", | ||
"END": lambda pos: f"{pos} => END", | ||
} | ||
|
||
for term in enumerate_terms(fin, grammar, 10): | ||
t = interpret_term(term, interpretation) | ||
if output: | ||
print(t) | ||
|
||
return timeit.default_timer() - start | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
128 changes: 128 additions & 0 deletions
128
tests/benchmarks/benchmark_maze_posparams_onlytermparam_stratified.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
from collections.abc import Callable, Mapping | ||
from functools import cache | ||
import timeit | ||
from typing import Optional | ||
from clsp.dsl import DSL | ||
from clsp.enumeration import Tree, enumerate_terms, interpret_term | ||
from clsp.fcl import FiniteCombinatoryLogic | ||
|
||
from clsp.types import Constructor, Literal, Param, LVar, Type | ||
|
||
|
||
def plus_one(a: str) -> Callable[[Mapping[str, Literal]], int]: | ||
def _inner(vars: Mapping[str, Literal]) -> int: | ||
return int(1 + vars[a].value) | ||
|
||
return _inner | ||
|
||
|
||
@cache | ||
def current_position(pos: Tree[str]) -> tuple[int, int]: | ||
curr_pos = (0, 0) | ||
while pos.root != "START": | ||
if pos.root == "D": | ||
curr_pos = (curr_pos[0], curr_pos[1] + 1) | ||
elif pos.root == "U": | ||
curr_pos = (curr_pos[0], curr_pos[1] - 1) | ||
elif pos.root == "L": | ||
curr_pos = (curr_pos[0] - 1, curr_pos[1]) | ||
elif pos.root == "R": | ||
curr_pos = (curr_pos[0] + 1, curr_pos[1]) | ||
pos = pos.parameters["pos"] | ||
return curr_pos | ||
|
||
|
||
@cache | ||
def is_free(pos: tuple[int, int], SIZE: int, next_step: Optional[tuple[int, int]] = None) -> bool: | ||
col, row = pos | ||
if next_step is not None: | ||
col = col + next_step[0] | ||
row = row + next_step[1] | ||
if col < 0 or row < 0 or col >= SIZE or row >= SIZE: | ||
return False | ||
SEED = 0 | ||
if row == col: | ||
return True | ||
else: | ||
return pow(11, (row + col + SEED) * (row + col + SEED) + col + 7, 1000003) % 5 > 0 | ||
|
||
|
||
def main(SIZE: int = 9, output: bool = True) -> float: | ||
repo: Mapping[ | ||
str, | ||
Param | Type, | ||
] = { | ||
"U": DSL() | ||
.Use("new_size", "int") | ||
.Use("size", "int") | ||
.As(lambda new_size: new_size - 1) | ||
.Use("pos", Constructor("pos", LVar("size"))) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(0, -1))) | ||
.In(Constructor("pos", LVar("new_size"))), | ||
"D": DSL() | ||
.Use("new_size", "int") | ||
.Use("size", "int") | ||
.As(lambda new_size: new_size - 1) | ||
.Use("pos", Constructor("pos", LVar("size"))) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(0, 1))) | ||
.In(Constructor("pos", LVar("new_size"))), | ||
"L": DSL() | ||
.Use("new_size", "int") | ||
.Use("size", "int") | ||
.As(lambda new_size: new_size - 1) | ||
.Use("pos", Constructor("pos", LVar("size"))) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(-1, 0))) | ||
.In(Constructor("pos", LVar("new_size"))), | ||
"R": DSL() | ||
.Use("new_size", "int") | ||
.Use("size", "int") | ||
.As(lambda new_size: new_size - 1) | ||
.Use("pos", Constructor("pos", LVar("size"))) | ||
.With(lambda pos: is_free(current_position(pos), SIZE, next_step=(1, 0))) | ||
.In(Constructor("pos", LVar("new_size"))), | ||
"START": "pos" @ (Literal(0, "int")), | ||
"END": DSL() | ||
.Use("size", "int") | ||
.Use("pos", Constructor("pos", LVar("size"))) | ||
.With(lambda pos: current_position(pos) == (SIZE - 1, SIZE - 1)) | ||
.In(Constructor("end")), | ||
} | ||
|
||
literals = {"int": set(range(SIZE * SIZE))} | ||
# literals = {"int2": list(filter(is_free, product(range(SIZE), range(SIZE))))} | ||
|
||
if output: | ||
for row in range(SIZE): | ||
for col in range(SIZE): | ||
if is_free((col, row), SIZE): | ||
print("-", end="") | ||
else: | ||
print("#", end="") | ||
print("") | ||
|
||
fin = Constructor("pos", Literal(4, "int")) | ||
fin = Constructor("end") | ||
|
||
fcl: FiniteCombinatoryLogic[str] = FiniteCombinatoryLogic(repo, literals=literals) | ||
|
||
start = timeit.default_timer() | ||
grammar = fcl.inhabit(fin) | ||
|
||
interpretation = { | ||
"U": lambda new_size, size, pos: f"{pos} => UP", | ||
"D": lambda new_size, size, pos: f"{pos} => DOWN", | ||
"L": lambda new_size, size, pos: f"{pos} => LEFT", | ||
"R": lambda new_size, size, pos: f"{pos} => RIGHT", | ||
"END": lambda size, pos: f"{pos} => END", | ||
} | ||
|
||
for term in enumerate_terms(fin, grammar, 10): | ||
t = interpret_term(term, interpretation) | ||
if output: | ||
print(t) | ||
|
||
return timeit.default_timer() - start | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.