feat(encode): add hamiltonian cycle encoding
This commit is contained in:
1 parent
a3b16797a2
commit
8af1fa439a
1 file changed
+82
@@ -0,0 +1,82 @@
|
||||
module Sift.Encode.Hamiltonian
|
||||
( hamCell
|
||||
, hamiltonianPath
|
||||
, hamiltonianCycle
|
||||
, decodeHamiltonian
|
||||
, validHamiltonianPath
|
||||
, validHamiltonianCycle
|
||||
) where
|
||||
|
||||
import Sift.Types
|
||||
import Sift.Encode.Cardinality
|
||||
import Sift.Encode.Coloring (Graph(..))
|
||||
import Data.List (sortOn)
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as Set
|
||||
import qualified Data.Map.Strict as Map
|
||||
|
||||
hamCell :: Int -> Int -> Int -> Var
|
||||
hamCell n vertex position = Var ((vertex - 1) * n + position)
|
||||
|
||||
adjacency :: Graph -> Set (Int, Int)
|
||||
adjacency (Graph _ edges) =
|
||||
Set.fromList (concat [ [(u, w), (w, u)] | (u, w) <- edges ])
|
||||
|
||||
positionConstraints :: Int -> [Clause]
|
||||
positionConstraints n =
|
||||
concat [ exactlyOne [ posLit (hamCell n vertex position) | vertex <- [1 .. n] ]
|
||||
| position <- [1 .. n] ]
|
||||
++
|
||||
concat [ exactlyOne [ posLit (hamCell n vertex position) | position <- [1 .. n] ]
|
||||
| vertex <- [1 .. n] ]
|
||||
|
||||
forbidNonAdjacent :: Int -> Set (Int, Int) -> Int -> Int -> [Clause]
|
||||
forbidNonAdjacent n adj fromPos toPos =
|
||||
[ [ neg (posLit (hamCell n u fromPos)), neg (posLit (hamCell n w toPos)) ]
|
||||
| u <- [1 .. n], w <- [1 .. n], u /= w
|
||||
, not (Set.member (u, w) adj) ]
|
||||
|
||||
hamiltonianPath :: Graph -> CNF
|
||||
hamiltonianPath g@(Graph n _) =
|
||||
CNF (positionConstraints n ++ stepClauses)
|
||||
where
|
||||
adj = adjacency g
|
||||
stepClauses = concat [ forbidNonAdjacent n adj i (i + 1) | i <- [1 .. n - 1] ]
|
||||
|
||||
hamiltonianCycle :: Graph -> CNF
|
||||
hamiltonianCycle g@(Graph n _) =
|
||||
CNF (positionConstraints n ++ stepClauses ++ wrapClauses)
|
||||
where
|
||||
adj = adjacency g
|
||||
stepClauses = concat [ forbidNonAdjacent n adj i (i + 1) | i <- [1 .. n - 1] ]
|
||||
wrapClauses = forbidNonAdjacent n adj n 1
|
||||
|
||||
decodeHamiltonian :: Int -> Assignment -> [Int]
|
||||
decodeHamiltonian n asn =
|
||||
map snd (sortOn fst
|
||||
[ (position, vertex)
|
||||
| position <- [1 .. n], vertex <- [1 .. n]
|
||||
, Map.findWithDefault False (hamCell n vertex position) asn ])
|
||||
|
||||
isPermutation :: Int -> [Int] -> Bool
|
||||
isPermutation n xs = Set.fromList xs == Set.fromList [1 .. n] && length xs == n
|
||||
|
||||
edgesOfPath :: [Int] -> [(Int, Int)]
|
||||
edgesOfPath xs = zip xs (drop 1 xs)
|
||||
|
||||
validHamiltonianPath :: Graph -> Assignment -> Bool
|
||||
validHamiltonianPath g@(Graph n _) asn =
|
||||
isPermutation n route
|
||||
&& all (`Set.member` adj) (edgesOfPath route)
|
||||
where
|
||||
route = decodeHamiltonian n asn
|
||||
adj = adjacency g
|
||||
|
||||
validHamiltonianCycle :: Graph -> Assignment -> Bool
|
||||
validHamiltonianCycle g@(Graph n _) asn =
|
||||
isPermutation n route
|
||||
&& all (`Set.member` adj) (edgesOfPath route)
|
||||
&& (n < 2 || Set.member (last route, head route) adj)
|
||||
where
|
||||
route = decodeHamiltonian n asn
|
||||
adj = adjacency g
|
||||
Reference in new issue
Block a user