You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
6.2 KiB

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# OPTIONS -Wall #-}
module Main where
import Control.DeepSeq (deepseq, NFData(..))
import Data.Int
import qualified Data.ByteString.Lazy.Char8 as BS
import System.Environment
import System.Random
import System.Clock
import GHC.Generics
import Data.Aeson
import Data.Maybe
import StrategyManager
import Strategy0
import Datatypes.Game(Game,Command)
import VM
import Opt
import JSONDeser(readInput)
import PowerPhrases
strategyTag :: String
strategyTag = "lilik0"
logFileName :: String
logFileName = "scores"
timeLimitRatio :: Double
timeLimitRatio = 0.96
memLimitRatio :: Double
memLimitRatio = 1.0
computationsPerStep :: Int
computationsPerStep = 10
data JSONSer = JSONSer { problemId :: Int,
problemSeed :: Int,
problemTag :: String,
problemSolution :: String
} deriving (Show, Generic)
instance FromJSON JSONSer
instance ToJSON JSONSer
type Id = Int
type Seed = Int
strategies :: Game -> StdGen -> Maybe [Command] -> GameComputation
strategies g sgen cmd = [MkStrategyWrapper (initst g sgen cmd :: Strategy0)]
-- = [MkStrategyWrapper (initst g sgen cmd :: NullStrategy1),
-- MkStrategyWrapper (initst g sgen cmd :: NullStrategy2)]
-- example ::
-- = [MkStrategyWrapper (init g sgen cmd :: Strat0),
-- MkStrategyWrapper (init g sgen cmd :: Strat1),
-- MkStrategyWrapper (init g sgen cmd :: Strat2)]
main :: IO ()
main = do initTime <- secTime
args <- getArgs
opt <- parseArgs args
let files = optFile opt
let maxTime = optTime opt
let maxMem = optMem opt
let powerPhrase = optPowerPhrase opt
let logFile = optLog opt
rng <- getStdGen
initialData <- createComputationsFromFiles files rng powerPhrase
let (_, _,gameComputations) = unzip3 initialData
commandResults <- iterateGame gameComputations (timeStruct maxTime initTime) maxMem
let stringResults = map (\(cmds,score,algoIdx) -> (cmdToString cmds,score,algoIdx)) commandResults
let outJSONstructs = zipWith jsonBuilder initialData stringResults
BS.putStrLn $ encode outJSONstructs
writeLogFile logFile (zipWith logFileBuilder initialData stringResults)
where
timeStruct Nothing _ = Nothing
timeStruct (Just stopTime) initialTime = Just (fromIntegral stopTime,fromIntegral initialTime)
jsonBuilder (idx, seed, _) (strCmds, _, _) = (JSONSer idx seed strategyTag strCmds)
logFileBuilder (idx, seed, _) (_ ,score , algoIdx) = (idx, seed, score, algoIdx)
createComputationsFromFiles :: [String] -> StdGen -> Maybe String -> IO [(Id,Seed,GameComputation)]
createComputationsFromFiles fileNames randomGen powerPhrase = do inputs <- readFiles fileNames
let igames = map readInput inputs
let cstruct = compstruct igames
return (gcstruct cstruct)
where
compstruct ig = concat (map genf ig)
genf (i,g) = zipWith (\x (y,z) -> (x,y,z)) (replicate (length g) i) g
gcstruct cst = map (\(x,y,z) -> (x,y,j z)) cst
where
j game = strategies game randomGen (powerCommands powerPhrase)
powerCommands Nothing = Nothing
powerCommands (Just a) = Just (mapMaybe charToCommand a)
readFiles :: [String] -> IO [BS.ByteString]
readFiles [] = return []
readFiles (x:xs) = do f <- BS.readFile x
fs <- readFiles xs
return (f:fs)
instance NFData Command where rnf x = seq x ()
iterateGame :: [GameComputation] -> Maybe (Double,Double) -> Maybe Int -> IO [FinishedGame]
iterateGame gameComputations timeLimitData memLimitData = do alive <- checkComputationAlive
if alive
then nextPass
else return bestGames
where
nextPass = (bestGames `deepseq` (iterateGame nextGameComputations timeLimitData memLimitData))
nextGameComputations = (applyNtimes computationsPerStep advanceGameComputations gameComputations)
checkComputationAlive = do timeLimitFlag <- timeLimit timeLimitData
memLimitFlag <- memLimit memLimitData
let finishedComputation = (and $ map finishedGameComputation gameComputations)
return $ not (timeLimitFlag || memLimitFlag || finishedComputation)
advanceGameComputations computations = map advanceGameComputation computations
bestGames = map getBestGameComputation gameComputations
timeLimit :: Maybe (Double, Double) -> IO Bool
timeLimit Nothing = return False
timeLimit (Just (initialTime,stopTime)) = do actualTime <- secTime
let actualTimeD = fromIntegral actualTime
let timeDifference = (actualTimeD - initialTime)
return (stopTime <= timeDifference)
memLimit :: Maybe Int -> IO Bool
memLimit _ = return False
secTime :: IO Int64
secTime = do (TimeSpec s _) <- getTime Monotonic
return s
writeLogFile :: Bool -> [(Int,Int,Int,Int)] -> IO ()
writeLogFile False _ = return ()
writeLogFile _ els = writeFile logFileName scoredata
where
scoredata = foldl strlog "\n" els
strlog x (a,b,c,d) = sa ++ sb ++ sc ++ sd ++ x ++ "\n\n"
where
sa = (show a) ++ " "
sb = (show b) ++ " "
sc = (show c) ++ " "
sd = (show d) ++ " "
applyNtimes :: Int -> (a -> a) -> a -> a
applyNtimes 0 _ accum = accum
applyNtimes n f accum = applyNtimes (n - 1) f (f accum)