{-# 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)
|
|
|