From f2ff9a2ee356959f889897ed272cccba6b3a11b9 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Tue, 16 Jul 2024 14:46:36 +0200 Subject: [PATCH] Review knights benchmark and update dependencies. --- examples/benchmarks/aiken.lock | 4 +- examples/benchmarks/aiken.toml | 2 +- examples/benchmarks/lib/benchmarks/knights.ak | 554 +++++++++++++++++- .../lib/benchmarks/knights/chess_set.ak | 62 +- .../lib/benchmarks/knights/heuristic.ak | 22 +- .../lib/benchmarks/knights/types.ak | 2 +- examples/benchmarks/lib/benchmarks/queue.ak | 29 +- examples/hello_world/aiken.toml | 2 +- examples/hello_world/plutus.json | 2 +- 9 files changed, 555 insertions(+), 124 deletions(-) diff --git a/examples/benchmarks/aiken.lock b/examples/benchmarks/aiken.lock index 0a72eb3c..62f2265a 100644 --- a/examples/benchmarks/aiken.lock +++ b/examples/benchmarks/aiken.lock @@ -3,12 +3,12 @@ [[requirements]] name = "aiken-lang/stdlib" -version = "1.7.0" +version = "1.9.0" source = "github" [[packages]] name = "aiken-lang/stdlib" -version = "1.7.0" +version = "1.9.0" requirements = [] source = "github" diff --git a/examples/benchmarks/aiken.toml b/examples/benchmarks/aiken.toml index 7223d60f..b246c981 100644 --- a/examples/benchmarks/aiken.toml +++ b/examples/benchmarks/aiken.toml @@ -10,5 +10,5 @@ platform = "github" [[dependencies]] name = "aiken-lang/stdlib" -version = "1.7.0" +version = "1.9.0" source = "github" diff --git a/examples/benchmarks/lib/benchmarks/knights.ak b/examples/benchmarks/lib/benchmarks/knights.ak index f6d01146..23926aa5 100644 --- a/examples/benchmarks/lib/benchmarks/knights.ak +++ b/examples/benchmarks/lib/benchmarks/knights.ak @@ -1,42 +1,47 @@ use aiken/list -use benchmarks/knights/heuristic.{descendants, finished_tour, start_tour} +use benchmarks/knights/heuristic.{descendants, start_tour, tour_finished} use benchmarks/knights/types.{ChessSet, Solution} -use benchmarks/queue.{ - Queue, append_all_front, append_front, create_queue, head, is_empty, - remove_front, to_list, +use benchmarks/queue.{Queue} + +// ------------------------------------------------------------------ Benchmarks + +test bench_knights_100_4x4() { + run_knights(100, 4) == [] } -test run_knights0() { - run_knights(100, 0) == [] +test bench_knights_100_6x6() { + run_knights(100, 6) == solution_100_6x6() } -test run_knights1() { - run_knights(100, 2) == [] +test bench_knights_100_8x8() { + run_knights(100, 8) == solution_100_8x8() } +// ----------------------------------------------------------------------- Setup + fn run_knights(depth: Int, board_size: Int) -> Solution { - depth_search(depth, root(board_size), grow, is_fin) |> to_list + depth_search(depth, root(board_size), grow, done) |> queue.to_list } fn depth_search( depth: Int, - queue: Queue, - grow_fn: fn(a) -> List, - fin_fn: fn(a) -> Bool, + xs: Queue, + grow: fn(a) -> List, + done: fn(a) -> Bool, ) -> Queue { - if depth == 0 || is_empty(queue) { - create_queue() - } else if fin_fn(head(queue)) { - depth_search(depth - 1, remove_front(queue), grow_fn, fin_fn) - |> append_front(head(queue)) + if depth == 0 || queue.is_empty(xs) { + queue.new() + } else if done(queue.head(xs)) { + depth_search(depth - 1, queue.remove_front(xs), grow, done) + |> queue.append_front(queue.head(xs)) } else { - append_all_front(remove_front(queue), grow_fn(head(queue))) - |> depth_search(depth - 1, _, grow_fn, fin_fn) + queue.append_all_front(queue.remove_front(xs), grow(queue.head(xs))) + |> depth_search(depth - 1, _, grow, done) } } -fn root(sze: Int) -> Queue<(Int, ChessSet)> { - append_all_front(create_queue(), mk_starts(sze)) +fn root(size: Int) -> Queue<(Int, ChessSet)> { + queue.append_all_front(queue.new(), mk_starts(size)) } fn mk_starts(sze: Int) -> List<(Int, ChessSet)> { @@ -59,13 +64,506 @@ fn interval(a: Int, b: Int) -> List { fn grow(item: (Int, ChessSet)) -> List<(Int, ChessSet)> { let (x, y) = item - - let const_item = x + 1 - descendants(y) |> list.map(fn(list_item) { (const_item, list_item) }) + descendants(y) |> list.map(fn(list_item) { (x + 1, list_item) }) } -fn is_fin(item: (Int, ChessSet)) -> Bool { - let (_, y) = item - - finished_tour(y) +fn done(item: (Int, ChessSet)) -> Bool { + tour_finished(item.2nd) +} + +// ------------------------------------------------------------------ Fixtures + +fn solution_100_6x6() { + [ + ( + 0, + ChessSet { + size: 6, + move_number: 36, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (6, 1), + (4, 2), + (3, 4), + (2, 6), + (4, 5), + (6, 6), + (5, 4), + (6, 2), + (4, 1), + (2, 2), + (1, 4), + (3, 3), + (2, 1), + (1, 3), + (2, 5), + (4, 6), + (6, 5), + (4, 4), + (5, 2), + (6, 4), + (5, 6), + (3, 5), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (4, 3), + (5, 1), + (6, 3), + (5, 5), + (3, 6), + (1, 5), + (2, 3), + (1, 1), + ], + }, + ), + ( + 0, + ChessSet { + size: 6, + move_number: 36, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (6, 1), + (4, 2), + (3, 4), + (2, 2), + (4, 1), + (6, 2), + (5, 4), + (6, 6), + (4, 5), + (2, 6), + (1, 4), + (3, 3), + (2, 1), + (1, 3), + (2, 5), + (4, 6), + (6, 5), + (4, 4), + (5, 2), + (6, 4), + (5, 6), + (3, 5), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (4, 3), + (5, 1), + (6, 3), + (5, 5), + (3, 6), + (1, 5), + (2, 3), + (1, 1), + ], + }, + ), + ( + 0, + ChessSet { + size: 6, + move_number: 36, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (6, 1), + (4, 2), + (3, 4), + (2, 2), + (1, 4), + (2, 6), + (4, 5), + (6, 6), + (5, 4), + (6, 2), + (4, 1), + (3, 3), + (2, 1), + (1, 3), + (2, 5), + (4, 6), + (6, 5), + (4, 4), + (5, 2), + (6, 4), + (5, 6), + (3, 5), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (4, 3), + (5, 1), + (6, 3), + (5, 5), + (3, 6), + (1, 5), + (2, 3), + (1, 1), + ], + }, + ), + ( + 0, + ChessSet { + size: 6, + move_number: 36, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (6, 1), + (4, 2), + (3, 4), + (2, 6), + (1, 4), + (2, 2), + (4, 1), + (6, 2), + (5, 4), + (6, 6), + (4, 5), + (3, 3), + (2, 1), + (1, 3), + (2, 5), + (4, 6), + (6, 5), + (4, 4), + (5, 2), + (6, 4), + (5, 6), + (3, 5), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (4, 3), + (5, 1), + (6, 3), + (5, 5), + (3, 6), + (1, 5), + (2, 3), + (1, 1), + ], + }, + ), + ] +} + +fn solution_100_8x8() { + [ + ( + 0, + ChessSet { + size: 8, + move_number: 64, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (4, 5), + (5, 7), + (7, 6), + (8, 8), + (6, 7), + (5, 5), + (3, 4), + (1, 5), + (2, 7), + (4, 8), + (3, 6), + (1, 7), + (3, 8), + (4, 6), + (6, 5), + (4, 4), + (5, 6), + (6, 4), + (7, 2), + (8, 4), + (6, 3), + (5, 1), + (4, 3), + (3, 5), + (5, 4), + (3, 3), + (2, 5), + (1, 3), + (2, 1), + (4, 2), + (6, 1), + (8, 2), + (7, 4), + (8, 6), + (7, 8), + (6, 6), + (8, 5), + (7, 7), + (5, 8), + (3, 7), + (1, 8), + (2, 6), + (1, 4), + (2, 2), + (4, 1), + (6, 2), + (8, 1), + (7, 3), + (5, 2), + (7, 1), + (8, 3), + (7, 5), + (8, 7), + (6, 8), + (4, 7), + (2, 8), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (2, 3), + (1, 1), + ], + }, + ), + ( + 0, + ChessSet { + size: 8, + move_number: 64, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (4, 5), + (5, 7), + (7, 6), + (8, 8), + (6, 7), + (4, 8), + (2, 7), + (1, 5), + (3, 4), + (5, 5), + (3, 6), + (1, 7), + (3, 8), + (4, 6), + (6, 5), + (4, 4), + (5, 6), + (6, 4), + (7, 2), + (8, 4), + (6, 3), + (5, 1), + (4, 3), + (3, 5), + (5, 4), + (3, 3), + (2, 5), + (1, 3), + (2, 1), + (4, 2), + (6, 1), + (8, 2), + (7, 4), + (8, 6), + (7, 8), + (6, 6), + (8, 5), + (7, 7), + (5, 8), + (3, 7), + (1, 8), + (2, 6), + (1, 4), + (2, 2), + (4, 1), + (6, 2), + (8, 1), + (7, 3), + (5, 2), + (7, 1), + (8, 3), + (7, 5), + (8, 7), + (6, 8), + (4, 7), + (2, 8), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (2, 3), + (1, 1), + ], + }, + ), + ] +} + +fn solution_80_8x8() { + [ + ( + 0, + ChessSet { + size: 8, + move_number: 64, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (4, 5), + (5, 7), + (7, 6), + (8, 8), + (6, 7), + (5, 5), + (3, 4), + (1, 5), + (2, 7), + (4, 8), + (3, 6), + (1, 7), + (3, 8), + (4, 6), + (6, 5), + (4, 4), + (5, 6), + (6, 4), + (7, 2), + (8, 4), + (6, 3), + (5, 1), + (4, 3), + (3, 5), + (5, 4), + (3, 3), + (2, 5), + (1, 3), + (2, 1), + (4, 2), + (6, 1), + (8, 2), + (7, 4), + (8, 6), + (7, 8), + (6, 6), + (8, 5), + (7, 7), + (5, 8), + (3, 7), + (1, 8), + (2, 6), + (1, 4), + (2, 2), + (4, 1), + (6, 2), + (8, 1), + (7, 3), + (5, 2), + (7, 1), + (8, 3), + (7, 5), + (8, 7), + (6, 8), + (4, 7), + (2, 8), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (2, 3), + (1, 1), + ], + }, + ), + ( + 0, + ChessSet { + size: 8, + move_number: 64, + start: Some((1, 1)), + visited: [ + (3, 2), + (5, 3), + (4, 5), + (5, 7), + (7, 6), + (8, 8), + (6, 7), + (4, 8), + (2, 7), + (1, 5), + (3, 4), + (5, 5), + (3, 6), + (1, 7), + (3, 8), + (4, 6), + (6, 5), + (4, 4), + (5, 6), + (6, 4), + (7, 2), + (8, 4), + (6, 3), + (5, 1), + (4, 3), + (3, 5), + (5, 4), + (3, 3), + (2, 5), + (1, 3), + (2, 1), + (4, 2), + (6, 1), + (8, 2), + (7, 4), + (8, 6), + (7, 8), + (6, 6), + (8, 5), + (7, 7), + (5, 8), + (3, 7), + (1, 8), + (2, 6), + (1, 4), + (2, 2), + (4, 1), + (6, 2), + (8, 1), + (7, 3), + (5, 2), + (7, 1), + (8, 3), + (7, 5), + (8, 7), + (6, 8), + (4, 7), + (2, 8), + (1, 6), + (2, 4), + (1, 2), + (3, 1), + (2, 3), + (1, 1), + ], + }, + ), + ] } diff --git a/examples/benchmarks/lib/benchmarks/knights/chess_set.ak b/examples/benchmarks/lib/benchmarks/knights/chess_set.ak index 8d9454b1..30f78440 100644 --- a/examples/benchmarks/lib/benchmarks/knights/chess_set.ak +++ b/examples/benchmarks/lib/benchmarks/knights/chess_set.ak @@ -1,4 +1,3 @@ -use aiken/builtin use aiken/list use benchmarks/knights/types.{ChessSet, Tile} @@ -12,7 +11,6 @@ pub fn create_board(size: Int, init_square: Tile) -> ChessSet { } pub fn add_piece(board: ChessSet, tile: Tile) -> ChessSet { - // record update ChessSet { ..board, move_number: board.move_number + 1, @@ -25,11 +23,6 @@ pub fn first_piece(board: ChessSet) -> Tile { tile } -// {-# INLINABLE lastPiece #-} -// lastPiece :: ChessSet -> Tile -// lastPiece (Board _ _ _ (t:_)) = t -// lastPiece _ = Tx.error () - pub fn last_piece(board: ChessSet) -> Tile { when board.visited is { [] -> fail @@ -70,58 +63,5 @@ fn second_last(visited: List) -> Option { } pub fn is_square_free(board: ChessSet, tile: Tile) -> Bool { - not_in(board.visited, tile) + !list.has(board.visited, tile) } - -pub fn not_in(tiles: List, tile: a) -> Bool { - !list.has(tiles, tile) -} -// {-# INLINABLE positionPiece #-} -// positionPiece :: Integer -> ChessSet -> Tile -// positionPiece x (Board _ n _ ts) = ts Tx.!! (n - x) - -// {-# INLINABLE pieceAtTile #-} -// pieceAtTile :: Tile -> ChessSet -> Integer -// pieceAtTile x0 (Board _ _ _ ts) -// = findPiece x0 ts -// where -// findPiece _ [] = Tx.error () -// findPiece x (y:xs) -// | x == y = 1 + Tx.length xs -// | otherwise = findPiece x xs - -// -- % Everything below here is only needed for printing boards. -// -- % This is useful for debugging. - -// instance Haskell.Show ChessSet where -// showsPrec _ (Board sze n _ ts) -// = Haskell.showString (printBoard sze sortedTrail 1) -// where sortedTrail = quickSort (assignMoveNo ts sze n) - -// assignMoveNo :: [Tile] -> Integer -> Integer -> [Tile] -// assignMoveNo [] _ _ -// = [] -// assignMoveNo ((x,y):t) size z -// = (((y-1)*size)+x,z):assignMoveNo t size (z-1) - -// printBoard :: Integer -> [Tile] -> Integer -> Haskell.String -// printBoard s [] n -// | (n > (s*s)) = "" -// | ((n `Haskell.mod` s) /=0)= "*"++(spaces (s*s) 1) ++(printBoard s [] (n+1)) -// | ((n `Haskell.mod` s) ==0)= "*\n" ++(printBoard s [] (n+1)) -// printBoard s trail@((i,j):xs) n -// | (i==n) && -// ((n `Haskell.mod` s) ==0) = (Haskell.show j)++"\n"++(printBoard s xs (n+1)) -// | (i==n) && -// ((n `Haskell.mod` s) /=0)= (Haskell.show j)++(spaces (s*s) j)++(printBoard s xs (n+1)) -// | ((n `Haskell.mod` s) /=0)= "*" ++(spaces (s*s) 1)++(printBoard s trail (n+1)) -// | ((n `Haskell.mod` s) ==0)= "*\n" ++(printBoard s trail (n+1)) -// printBoard _ _ _ = "?" - -// spaces :: Integer -> Integer -> Haskell.String -// spaces s y = -// take' ((logTen s) - (logTen y) + 1) [' ',' '..] -// where -// logTen :: Integer -> Integer -// logTen 0 = 0 -// logTen x = 1 + logTen (x `Haskell.div` 10) diff --git a/examples/benchmarks/lib/benchmarks/knights/heuristic.ak b/examples/benchmarks/lib/benchmarks/knights/heuristic.ak index 9099b24a..e89b5968 100644 --- a/examples/benchmarks/lib/benchmarks/knights/heuristic.ak +++ b/examples/benchmarks/lib/benchmarks/knights/heuristic.ak @@ -1,9 +1,10 @@ use aiken/builtin +use aiken/int use aiken/list use benchmarks/knights/chess_set.{ add_piece, create_board, delete_first, first_piece, is_square_free, last_piece, } -use benchmarks/knights/sort.{quick_sort} +use benchmarks/knights/sort.{quicksort} use benchmarks/knights/types.{ChessSet, Tile} type Direction { @@ -23,7 +24,6 @@ fn direction_list() { fn move(direction: Direction, tile: Tile) -> Tile { let (x, y) = tile - when direction is { UL -> (x - 1, y - 2) UR -> (x + 1, y - 2) @@ -38,13 +38,11 @@ fn move(direction: Direction, tile: Tile) -> Tile { pub fn start_tour(st: Tile, size: Int) -> ChessSet { expect 0 = builtin.remainder_integer(size, 2) - create_board(size, st) } -pub fn finished_tour(board: ChessSet) -> Bool { +pub fn tour_finished(board: ChessSet) -> Bool { let ChessSet { move_number, size, .. } = board - move_number == size * size && can_jump_first(board) } @@ -78,9 +76,8 @@ pub fn dead_end(board: ChessSet) -> Bool { } pub fn single_descend(board: ChessSet) -> List { - let descendants_and_moves = desc_and_no(board) list.filter_map( - descendants_and_moves, + desc_and_no(board), fn(item) { let (moves, board) = item if moves == 1 { @@ -96,16 +93,15 @@ pub fn desc_and_no(board: ChessSet) -> List<(Int, ChessSet)> { board |> all_descend |> list.map( - fn(item) { - (item |> delete_first |> possible_moves |> list.length, item) - }, - ) + fn(item) { + (item |> delete_first |> possible_moves |> list.length, item) + }, + ) } pub fn can_move_to(board: ChessSet, tile: Tile) -> Bool { let (x, y) = tile let size = board.size - and { x >= 1, x <= size, @@ -122,7 +118,7 @@ fn can_move(board: ChessSet, direction: Direction) -> Bool { pub fn all_descend(board: ChessSet) -> List { board |> possible_moves - |> list.map(fn(direction) { move_knight(board, direction) }) + |> list.map(move_knight(board, _)) } fn move_knight(board: ChessSet, direction: Direction) -> ChessSet { diff --git a/examples/benchmarks/lib/benchmarks/knights/types.ak b/examples/benchmarks/lib/benchmarks/knights/types.ak index fc293456..16b50c6d 100644 --- a/examples/benchmarks/lib/benchmarks/knights/types.ak +++ b/examples/benchmarks/lib/benchmarks/knights/types.ak @@ -4,8 +4,8 @@ pub type Tile = pub type ChessSet { size: Int, move_number: Int, - visited: List, start: Option, + visited: List, } pub type Solution = diff --git a/examples/benchmarks/lib/benchmarks/queue.ak b/examples/benchmarks/lib/benchmarks/queue.ak index 9a5fbb06..0abd9c76 100644 --- a/examples/benchmarks/lib/benchmarks/queue.ak +++ b/examples/benchmarks/lib/benchmarks/queue.ak @@ -4,38 +4,35 @@ pub opaque type Queue { inner: List, } -pub fn create_queue() -> Queue { +pub fn new() -> Queue { [] |> Queue } -pub fn to_list(queue: Queue) -> List { - queue.inner +pub fn to_list(self: Queue) -> List { + self.inner } -pub fn is_empty(queue: Queue) -> Bool { - when queue.inner is { +pub fn is_empty(self: Queue) -> Bool { + when self.inner is { [] -> True _ -> False } } -pub fn append_front(queue: Queue, item: a) -> Queue { - list.push(queue.inner, item) |> Queue +pub fn append_front(self: Queue, item: a) -> Queue { + list.push(self.inner, item) |> Queue } -/// Add all items from the list to the front of the queue -pub fn append_all_front(queue: Queue, items: List) -> Queue { - list.concat(items, queue.inner) |> Queue +pub fn append_all_front(self: Queue, items: List) -> Queue { + list.concat(items, self.inner) |> Queue } -pub fn remove_front(queue: Queue) -> Queue { - expect [_, ..rest] = queue.inner - +pub fn remove_front(self: Queue) -> Queue { + expect [_, ..rest] = self.inner rest |> Queue } -pub fn head(queue: Queue) -> a { - expect [q, ..] = queue.inner - +pub fn head(self: Queue) -> a { + expect [q, ..] = self.inner q } diff --git a/examples/hello_world/aiken.toml b/examples/hello_world/aiken.toml index 1e530f11..3b523f22 100644 --- a/examples/hello_world/aiken.toml +++ b/examples/hello_world/aiken.toml @@ -5,5 +5,5 @@ description = "Aiken contracts for project 'aiken-lang/hello_world'" [[dependencies]] name = "aiken-lang/stdlib" -version = "1.7.0" +version = "main" source = "github" diff --git a/examples/hello_world/plutus.json b/examples/hello_world/plutus.json index 5b6e3cc0..a0fab843 100644 --- a/examples/hello_world/plutus.json +++ b/examples/hello_world/plutus.json @@ -6,7 +6,7 @@ "plutusVersion": "v2", "compiler": { "name": "Aiken", - "version": "v1.0.21-alpha+4b04517" + "version": "v1.0.19-alpha+d56d518" } }, "validators": [