feat(cdcl): add activity-ordered variable heap
This commit is contained in:
1 parent
81664ccad0
commit
9795316136
1 file changed
+120
@@ -0,0 +1,120 @@
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
module Sift.Cdcl.Heap
|
||||
( VarHeap
|
||||
, newHeap
|
||||
, heapInsert
|
||||
, heapIncrease
|
||||
, heapRemoveMax
|
||||
, heapInHeap
|
||||
, heapIsEmpty
|
||||
) where
|
||||
|
||||
import Control.Monad (when)
|
||||
import Control.Monad.ST (ST)
|
||||
import Data.STRef
|
||||
import Data.Array.ST
|
||||
|
||||
data VarHeap s = VarHeap
|
||||
{ hArr :: STUArray s Int Int
|
||||
, hPos :: STUArray s Int Int
|
||||
, hSize :: STRef s Int
|
||||
, hAct :: STUArray s Int Double
|
||||
}
|
||||
|
||||
newHeap :: Int -> STUArray s Int Double -> ST s (VarHeap s)
|
||||
newHeap n act = do
|
||||
arr <- newArray (0, n - 1) 0
|
||||
pos <- newArray (0, n - 1) (-1)
|
||||
size <- newSTRef 0
|
||||
pure (VarHeap arr pos size act)
|
||||
|
||||
heapInHeap :: VarHeap s -> Int -> ST s Bool
|
||||
heapInHeap h v = do
|
||||
p <- readArray (hPos h) v
|
||||
pure (p >= 0)
|
||||
|
||||
heapIsEmpty :: VarHeap s -> ST s Bool
|
||||
heapIsEmpty h = do
|
||||
n <- readSTRef (hSize h)
|
||||
pure (n == 0)
|
||||
|
||||
heapInsert :: VarHeap s -> Int -> ST s ()
|
||||
heapInsert h v = do
|
||||
present <- heapInHeap h v
|
||||
when (not present) $ do
|
||||
n <- readSTRef (hSize h)
|
||||
writeArray (hArr h) n v
|
||||
writeArray (hPos h) v n
|
||||
writeSTRef (hSize h) (n + 1)
|
||||
siftUp h n
|
||||
|
||||
heapIncrease :: VarHeap s -> Int -> ST s ()
|
||||
heapIncrease h v = do
|
||||
p <- readArray (hPos h) v
|
||||
when (p >= 0) $ siftUp h p
|
||||
|
||||
heapRemoveMax :: VarHeap s -> ST s Int
|
||||
heapRemoveMax h = do
|
||||
n <- readSTRef (hSize h)
|
||||
top <- readArray (hArr h) 0
|
||||
lastV <- readArray (hArr h) (n - 1)
|
||||
writeArray (hArr h) 0 lastV
|
||||
writeArray (hPos h) lastV 0
|
||||
writeArray (hPos h) top (-1)
|
||||
writeSTRef (hSize h) (n - 1)
|
||||
when (n - 1 > 0) $ siftDown h 0
|
||||
pure top
|
||||
|
||||
siftUp :: VarHeap s -> Int -> ST s ()
|
||||
siftUp h start = do
|
||||
x <- readArray (hArr h) start
|
||||
ax <- readArray (hAct h) x
|
||||
let go j
|
||||
| j <= 0 = finish j
|
||||
| otherwise = do
|
||||
let parent = (j - 1) `div` 2
|
||||
yp <- readArray (hArr h) parent
|
||||
ay <- readArray (hAct h) yp
|
||||
if ax > ay
|
||||
then do
|
||||
writeArray (hArr h) j yp
|
||||
writeArray (hPos h) yp j
|
||||
go parent
|
||||
else finish j
|
||||
finish j = do
|
||||
writeArray (hArr h) j x
|
||||
writeArray (hPos h) x j
|
||||
go start
|
||||
|
||||
siftDown :: VarHeap s -> Int -> ST s ()
|
||||
siftDown h start = do
|
||||
n <- readSTRef (hSize h)
|
||||
x <- readArray (hArr h) start
|
||||
ax <- readArray (hAct h) x
|
||||
let go j = do
|
||||
let l = 2 * j + 1
|
||||
if l >= n
|
||||
then finish j
|
||||
else do
|
||||
let r = l + 1
|
||||
cl <- readArray (hArr h) l
|
||||
acl <- readArray (hAct h) cl
|
||||
(childIdx, childVar, childAct) <-
|
||||
if r < n
|
||||
then do
|
||||
cr <- readArray (hArr h) r
|
||||
acr <- readArray (hAct h) cr
|
||||
if acr > acl
|
||||
then pure (r, cr, acr)
|
||||
else pure (l, cl, acl)
|
||||
else pure (l, cl, acl)
|
||||
if childAct > ax
|
||||
then do
|
||||
writeArray (hArr h) j childVar
|
||||
writeArray (hPos h) childVar j
|
||||
go childIdx
|
||||
else finish j
|
||||
finish j = do
|
||||
writeArray (hArr h) j x
|
||||
writeArray (hPos h) x j
|
||||
go start
|
||||
Reference in new issue
Block a user