satchmo-2.9.7.3: examples/PP.hs
-- | find incidence matrix of projective plane of given order
-- example usage: ./dist/build/PP/PP 2
{-# language PatternSignatures #-}
{-# language FlexibleContexts #-}
import Prelude hiding ( not, and, or )
import qualified Prelude
import Satchmo.Relation
import Satchmo.Code
import Satchmo.Boolean
import qualified Satchmo.Counting.Binary as CB
import qualified Satchmo.Counting.Unary as CU
import qualified Satchmo.Counting.Direct as CD
import qualified Satchmo.Binary as B
import Satchmo.SAT.Mini
import Data.List (sort)
import qualified Data.Array as A
import Control.Monad ( guard, when, forM, void )
import System.Environment
import Data.Ix ( range)
main :: IO ()
main = do
argv <- getArgs
let [ o ] = case argv of
[] -> [5]
_ -> map read argv
Just ( a :: A.Array (Int,Int) Bool ) <- solve $ pp o
putStrLn $ unlines $ do
let ((u,l),(o,r)) = A.bounds a
x <- [ u .. o ]
return $ unwords $ do
y <- [ l .. r ]
return $ if a A.! (x,y) then "* " else ". "
fill k cs = replicate (k - length cs) ' ' ++ cs
pp o = do
let n = o*o + o + 1
points = [ 1 .. n ] ; lines = [ 1 .. n ]
i :: Relation Int Int <- relation ((1,1),(n,n))
contains (o+1) i
contains (o+1) $ mirror i
any_two_determine_one i
any_two_determine_one $ mirror i
monotone i
monotone $ transpose i
return $ decode i
transpose a =
let ((1,1),(h,w)) = bounds a
in build ((1,1),(w,h)) $ do
((x,y),v) <- assocs a
return ((y,x),v)
-- | see http://www.maa.org/programs/maa-awards/writing-awards/the-search-for-a-finite-projective-plane-of-order-10
fixed_start o i = do
let n = o*o + o + 1
return ()
monotone i = assertM $ do
let ((1,1),(points, lines)) = bounds i
rows = for [ 1 .. points ] $ \ p ->
B.make $ for [ 1 .. lines ] $ \ l -> i ! (p,l)
monadic and $ for ( zip rows $ tail rows ) $ \ (r, r') ->
B.lt r r'
contains o i = assertM $ do
let ((1,1),(points, lines)) = bounds i
monadic and $ for [ 1 .. points ] $ \ p ->
monadic ( CB.exactly o ) $ for [ 1 .. lines ] $ \ l ->
return $ i ! (p, l)
any_two_determine_one i = assertM $ do
let ((1,1),(points, lines)) = bounds i
monadic and $ for [1..points] $ \ p ->
monadic and $ for [p+1 .. points] $ \ q ->
monadic ( CB.exactly 1 ) $ for [1 .. lines] $ \ l ->
and [ i ! (p,l), i ! (q,l) ]
for = flip map
assertM this = do x <- this ; assert [x]