diff --git a/koka_bench/cpp/CMakeLists.txt b/koka_bench/cpp/CMakeLists.txt index f587560..b4421ef 100644 --- a/koka_bench/cpp/CMakeLists.txt +++ b/koka_bench/cpp/CMakeLists.txt @@ -2,7 +2,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) -foreach (source IN ITEMS rbtree.cpp) +foreach (source IN ITEMS rbtree.cpp nqueens.cpp) get_filename_component(name "${source}" NAME_WE) set(name "cpp-${name}") diff --git a/koka_bench/cpp/nqueens.cpp b/koka_bench/cpp/nqueens.cpp new file mode 100644 index 0000000..37ab3b5 --- /dev/null +++ b/koka_bench/cpp/nqueens.cpp @@ -0,0 +1,94 @@ +// NQueens solution in C++ +// Note: does not free memory as that is difficult to do +// since many subsolutions are shared +#include + +template +class list { +public: + T head; + list* tail; + list(T hd, list* tl) { + head = hd; + tail = tl; + } + ~list() { + delete head; + delete tail; + } +}; + +template +list* Cons( T hd, list* tl ) { + return new list(hd,tl); +} + +template +int len(list* xs) { + int n = 0; + while(xs != NULL) { + n++; + xs = xs->tail; + } + return n; +} + +bool safe( int queen, list* xs ) { + list* cur = xs; + int diag = 1; + while(cur != NULL) { + int q = cur->head; + if (queen == q || queen == (q+diag) || queen == (q-diag)) { + return false; + } + diag++; + cur = cur->tail; + } + return true; +} + +list*>* append_safe( int k, list* soln, list*>* solns ) { + list*>* acc = solns; + int n = k; + while(n > 0) { + if (safe(n,soln)) { + acc = Cons(Cons(n,soln),acc); + } + n--; + } + return acc; +} + +list*>* extend( int n, list*>* solns ) { + list*>* acc = NULL; + list*>* cur = solns; + while(cur != NULL) { + list* soln = cur->head; + acc = append_safe(n,soln,acc); + cur = cur->tail; + } + return acc; +} + +list*>* find_solutions( int n ) { + int k = 0; + list*>* acc = Cons*>(NULL,NULL); + while(k < n) { + acc = extend(n,acc); + k++; + } + return acc; +} + +int nqueens(int n) { + return len(find_solutions(n)); +} + +int main(int argc, char ** argv) { + int n = 13; + if (argc == 2) { + n = atoi(argv[1]); + } + std::cout << nqueens(n) << "\n"; + return 0; +} diff --git a/koka_bench/koka/CMakeLists.txt b/koka_bench/koka/CMakeLists.txt index 495a82d..e06719f 100644 --- a/koka_bench/koka/CMakeLists.txt +++ b/koka_bench/koka/CMakeLists.txt @@ -1,4 +1,4 @@ -set(sources rbtree.kk) +set(sources rbtree.kk nqueens.kk nqueens-int.kk) set(koka koka) diff --git a/koka_bench/koka/nqueens-int.kk b/koka_bench/koka/nqueens-int.kk new file mode 100644 index 0000000..8c8772e --- /dev/null +++ b/koka_bench/koka/nqueens-int.kk @@ -0,0 +1,31 @@ +module nqueens-int +import std/os/env + +alias solution = list +alias solutions = list> + +fun safe( queen : int, diag : int, ^xs : solution ) : bool + match xs + Cons(q,qs) -> (queen != q && queen != q + diag && queen != q - diag && safe(queen,diag + 1,qs)) + _ -> True + +fun append-safe( queen : int, xs : solution, xss : solutions ) : div solutions + if queen <= 0 then xss + elif safe(queen,1,xs) then append-safe( queen - 1, xs, Cons(Cons(queen,xs),xss) ) + else append-safe( queen - 1, xs, xss ) + +fun extend(queen : int, acc : solutions, xss : solutions ) : div solutions + match xss + Cons(xs,rest) -> extend(queen, append-safe(queen,xs,acc), rest) + Nil -> acc + +fun find-solutions( n : int, queen : int ) : div solutions + if queen == 0 + then [[]] + else extend(n,[], find-solutions(n,queen - 1)) + +pub fun queens( n : int ) : div int + find-solutions(n,n).length + +pub fun main() + queens(get-args().head("").parse-int.default(13)).println diff --git a/koka_bench/koka/nqueens.kk b/koka_bench/koka/nqueens.kk new file mode 100644 index 0000000..f3fd7df --- /dev/null +++ b/koka_bench/koka/nqueens.kk @@ -0,0 +1,32 @@ +module nqueens +import std/num/int32 +import std/os/env + +alias solution = list +alias solutions = list> + +fun safe( queen : int32, diag : int32, ^xs : solution ) : bool + match xs + Cons(q,qs) -> (queen != q && queen != (q+diag) && queen != (q - diag) && safe(queen,diag.inc,qs)) + _ -> True + +fun append-safe( queen : int32, xs : solution, xss : solutions ) : div solutions + if queen <= 0.int32 then xss + elif safe(queen,1.int32,xs) then append-safe( queen.dec, xs, Cons(Cons(queen,xs),xss) ) + else append-safe( queen.dec, xs, xss ) + +fun extend( queen : int32, acc : solutions, xss : solutions ) : div solutions + match xss + Cons(xs,rest) -> extend(queen, append-safe(queen,xs,acc), rest) + Nil -> acc + +fun find-solutions( n : int32, queen : int32 ) : div solutions + if queen.is-zero + then [[]] + else extend(n, [], find-solutions(n,queen.dec)) + +pub fun queens( n : int32 ) : div int + find-solutions(n,n).length + +pub fun main() + queens(get-args().head("").parse-int.default(13).int32).println diff --git a/koka_bench/rbnqueens_table.md b/koka_bench/rbnqueens_table.md new file mode 100644 index 0000000..484ffbb --- /dev/null +++ b/koka_bench/rbnqueens_table.md @@ -0,0 +1,6 @@ +| Command | Mean [s] | Min [s] | Max [s] | Relative | +|:---|---:|---:|---:|---:| +| `build/kraken/out/bench/kraken-nqueens 10` | 2.280 ± 0.040 | 2.218 | 2.356 | 493.82 ± 56.59 | +| `build/cpp/cpp-nqueens 10` | 0.006 ± 0.001 | 0.006 | 0.008 | 1.32 ± 0.19 | +| `build/koka/out/bench/kk-nqueens 10` | 0.005 ± 0.001 | 0.004 | 0.006 | 1.00 | +| `build/koka/out/bench/kk-nqueens-int 10` | 0.007 ± 0.001 | 0.006 | 0.009 | 1.46 ± 0.20 | diff --git a/koka_bench/rbtree_table.md b/koka_bench/rbtree_table.md index 76fc576..0cc95e4 100644 --- a/koka_bench/rbtree_table.md +++ b/koka_bench/rbtree_table.md @@ -1,5 +1,6 @@ | Command | Mean [s] | Min [s] | Max [s] | Relative | |:---|---:|---:|---:|---:| -| `build/kraken/out/bench/kraken-rbtree 42000` | 4.116 ± 0.030 | 4.078 | 4.160 | 862.26 ± 110.34 | -| `build/cpp/cpp-rbtree 42000` | 0.006 ± 0.001 | 0.005 | 0.008 | 1.22 ± 0.20 | -| `build/koka/out/bench/kk-rbtree 42000` | 0.005 ± 0.001 | 0.004 | 0.008 | 1.00 | +| `build/kraken/out/bench/kraken-rbtree-opt 42000` | 3.814 ± 0.021 | 3.775 | 3.850 | 865.95 ± 89.32 | +| `build/kraken/out/bench/kraken-rbtree 42000` | 4.133 ± 0.050 | 4.090 | 4.245 | 938.49 ± 97.33 | +| `build/cpp/cpp-rbtree 42000` | 0.006 ± 0.001 | 0.005 | 0.008 | 1.30 ± 0.20 | +| `build/koka/out/bench/kk-rbtree 42000` | 0.004 ± 0.000 | 0.004 | 0.007 | 1.00 | diff --git a/koka_bench/test.sh b/koka_bench/test.sh index 32ddb99..aa1e55f 100755 --- a/koka_bench/test.sh +++ b/koka_bench/test.sh @@ -7,7 +7,10 @@ then pushd build nix develop -i -c bash -c 'cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build .' popd - rm -rf ./build/CMakeFiles || true fi +pushd build +nix develop -i -c bash -c 'make' +popd -nix develop -i -c bash -c 'ulimit -s unlimited && find build -type f -executable -name \*rbtree -printf "\"%p 42000\"\n" | xargs hyperfine --ignore-failure --warmup 2 --export-markdown rbtree_table.md' +nix develop -i -c bash -c 'ulimit -s unlimited && find build -type f -executable -name \*nqueens\* -printf "\"%p 10\"\n" | xargs hyperfine --ignore-failure --warmup 2 --export-markdown rbnqueens_table.md' +nix develop -i -c bash -c 'ulimit -s unlimited && find build -type f -executable -name \*rbtree\* -printf "\"%p 42000\"\n" | xargs hyperfine --ignore-failure --warmup 2 --export-markdown rbtree_table.md'