packages feed

satchmo-2.9.4: examples/Ramsey.hs

-- | find colouring without complete subgraphs
-- example usage: ./dist/build/Ramsey/Ramsey 3 3 3 16
-- last number is size of graph,
-- earlier numbers are sizes of forbidden cliques

{-# language PatternSignatures #-}

import Prelude hiding ( not, and, or, product )
import qualified Prelude

import Satchmo.Relation
import Satchmo.Code
import Satchmo.Boolean hiding ( implies )
import Satchmo.Counting

import qualified Satchmo.Binary as B

import Satchmo.SAT.Mini

import Data.List (sort, tails)
import qualified Data.Array as A
import Control.Monad ( guard, when, forM, foldM, void )
import System.Environment
import Data.Ix ( range)


main :: IO ()
main = do
    argv <- getArgs
    let ns = map read $ case argv of
          [] -> [ "3", "3", "3", "16" ]
          _ -> argv
        cs = init ns 
        n = last ns
    Just ( p : fs ) <- solve $ ramsey cs n
    forM ( zip [ 1.. ] fs ) $ \ (k, f) -> do 
        putStrLn $ unwords [ "colour", show k ]
        printA f
    putStrLn "with isomorphism" ; printA p

printA :: A.Array (Int,Int) Bool -> IO ()
printA a = putStrLn $ unlines $ do
         let ((u,l),(o,r)) = A.bounds a
         x <- [u .. o]
         return $ unwords $ do 
             y <- [ l ..r ]
             return $ case a A.! (x,y) of
                  True -> "* " ; False -> ". "

ramsey (cs :: [Int]) (n :: Int) = do
    fs <- forM cs $ \ c -> 
         relation ((1 :: Int,1 :: Int),(n,n))
    
    p <- relation ((1,1),(n,n))
    -- forM fs $ isomorphism p

    -- forM fs $ cyclic 3

    when False $ void $ do
        forM [ 1 .. n ] $ \ x -> 
            forM [ x + 1 .. n ] $ \ y -> 
                assertM $ exactly 1 $ 
                    for fs $ \ f -> f ! (x,y) 
    when True $ void $ do
        forM [ 1 .. n ] $ \ x -> 
            forM [ x + 1 .. n ] $ \ y -> 
                assert $ for fs $ \ f -> f ! (x,y)

    forM ( zip cs fs ) $ \ (c,f) -> 
        forM ( cliquesA c [1..n] ) $ \ xs ->
            assert $ for ( cliquesA 2 xs ) $ \ [x,y] -> not $ f ! (x,y)
    return $ forM (p : fs) decode
    
isomorphism p e = do
    assertM $ regular 1 p
    assertM $ regular 1 $ mirror p
    e' <- foldM product ( mirror p ) [ e, p ]
    assertM $ implies e e'
    assertM $ implies e' e

cyclic off f = forM ( indices f ) $ \ (i,j) -> 
    when ( off < i Prelude.&& i < j ) 
         $ assert_fun2 (==) ( f!(i,j) ) (f!(i-off,j-off))

cliquesA k xs = 
      let -- spec:  c!(i,j) == cliques i (drop j xs)
          bnd = ((0,0),(k, length xs))
          c = A.array bnd $ do
            (i,j) <- A.range bnd
            return ( (i,j)
                   , if i == 0 then [ [] ]
                     else if i > length xs - j then []               
                     else c A.! (i,j+1) 
                          ++ map (xs !! j : ) ( c A.! (i-1,j+1))
                   )             
      in  c A.! (k,0)         

cliques 0 xs = return []
cliques k xs | k > length xs = []
cliques k (x:xs) =
    cliques k xs ++ map (x :) ( cliques (k-1) xs )

for = flip map

assertM this = do x <- this ; assert [x]