-
Notifications
You must be signed in to change notification settings - Fork 479
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
Showing
4 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
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,26 @@ | ||
module Main (main) where | ||
|
||
{- | ||
import Criterion.Main (bench, defaultMain) | ||
import PlutusBenchmark.Common (benchProgramCek, mkMostRecentEvalCtx) | ||
import PlutusBenchmark.NQueens (nqueens) | ||
import PlutusTx.Code (CompiledCode, getPlcNoAnn) | ||
import PlutusTx.TH (compile) | ||
-} | ||
|
||
main :: IO () | ||
main = print "Pending" | ||
|
||
{- Currently not able to run, due to problems with writeBits compiling under PlutusTx | ||
main :: IO () | ||
main = defaultMain [ | ||
bench "8-queens" . benchProgramCek mkMostRecentEvalCtx . getPlcNoAnn $ nqueensCompiled | ||
] | ||
-- Helpers | ||
nqueensCompiled :: CompiledCode [(Integer, Integer)] | ||
nqueensCompiled = $$(compile [||nqueens 8||]) | ||
-} |
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,79 @@ | ||
-- editorconfig-checker-disable-file | ||
{-# LANGUAGE MultiWayIf #-} | ||
{-# LANGUAGE NoImplicitPrelude #-} | ||
{-# LANGUAGE TypeApplications #-} | ||
|
||
module PlutusBenchmark.NQueens (nqueens) where | ||
|
||
import PlutusTx.Builtins (complementByteString, findFirstSetBit, orByteString, replicateByte, | ||
shiftByteString, writeBits) | ||
import PlutusTx.Prelude | ||
|
||
-- Based on Qiu, Zongyan (February 2002). "Bit-vector encoding of n-queen problem". ACM SIGPLAN Notices. 37 (2): 68–70 | ||
-- For simplicity, this only accepts multiples of 8 for the dimension (so 8, 16, | ||
-- 24, etc): in all other cases it will return an empty list. Results are (row, | ||
-- column) pairs. | ||
{-# INLINE nqueens #-} | ||
nqueens :: Integer -> [(Integer, Integer)] | ||
nqueens dim | ||
| dim < 8 = [] | ||
| dim `remainder` 8 /= 0 = [] | ||
| otherwise = | ||
let down = replicateByte bytesNeeded 0x00 | ||
left = replicateByte bytesNeeded 0x00 | ||
right = replicateByte bytesNeeded 0x00 | ||
in go 0 0 down left right (replicateByte bytesNeeded 0xFF) | ||
where | ||
bytesNeeded :: Integer | ||
bytesNeeded = dim `quotient` 8 | ||
go :: | ||
Integer -> | ||
Integer -> | ||
BuiltinByteString -> | ||
BuiltinByteString -> | ||
BuiltinByteString -> | ||
BuiltinByteString -> | ||
[(Integer, Integer)] | ||
go selectIx row down left right control | ||
| selectIx == dim = [] | ||
| otherwise = | ||
-- In the original writeup, 0 in a position meant 'occupied'. However, | ||
-- this makes updates to the control vectors very annoying, because | ||
-- now we have to 'shift in' 1 bits, which costs us an extra two | ||
-- copies. We can reduce this by one by instead treating 0 as 'free'. | ||
-- Ideally, we would eliminate one more redundant copy, but this | ||
-- requires a select0 operation, which can't be implemented | ||
-- efficiently. However, given that these copies are per recursive | ||
-- call, we can save ourselves considerable effort by avoiding them. | ||
let available = selectByteString selectIx control | ||
in if | ||
| available == (-1) -> [] | ||
| row == lastRow -> [(row, available)] | ||
| otherwise -> | ||
let newDown = writeBit down available True | ||
newLeft = shiftByteString (writeBit left available True) 1 | ||
newRight = shiftByteString (writeBit right available True) (-1) | ||
newRow = row + 1 | ||
-- We 'hoist' the control vector as a parameter rather | ||
-- than recomputing it every time we modify selectIx. | ||
newControl = complementByteString . orByteString False newDown . orByteString False newLeft $ newRight | ||
in case go 0 newRow newDown newLeft newRight newControl of | ||
[] -> go (selectIx + 1) row down left right control | ||
next -> (row, available) : next | ||
lastRow :: Integer | ||
lastRow = dim - 1 | ||
|
||
-- Helpers | ||
|
||
{-# INLINE selectByteString #-} | ||
selectByteString :: Integer -> BuiltinByteString -> Integer | ||
selectByteString which bs | ||
| which <= 0 = findFirstSetBit bs | ||
| otherwise = let i = selectByteString (which - 1) bs | ||
in if i == (-1) | ||
then (-1) | ||
else i + 1 + findFirstSetBit (shiftByteString bs $ negate (i + 1)) | ||
|
||
{-# INLINE writeBit #-} | ||
writeBit :: BuiltinByteString -> Integer -> Bool -> BuiltinByteString | ||
writeBit bs i b = writeBits bs . toBuiltin @[(Integer, Bool)] $ [(i, b)] |
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,12 @@ | ||
module Main (main) where | ||
|
||
import PlutusBenchmark.NQueens (nqueens) | ||
import Test.Tasty (defaultMain, testGroup) | ||
import Test.Tasty.HUnit (assertEqual, testCase) | ||
|
||
main :: IO () | ||
main = defaultMain . testGroup "nqueens" $ [ | ||
testCase "solves for 8 queens" $ assertEqual "" | ||
[(0,0), (1,4), (2,7), (3,5), (4,2), (5,6), (6,1), (7,3)] | ||
(nqueens 8) | ||
] |
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