{- Optimal cuts on a 2x2 mirror cube. Answer: 1/7, 2/7 ...
Copyright 2016 Ken Takusagawa
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-}
{-# LANGUAGE ScopedTypeVariables, LambdaCase #-}
module Main where {
import System.Environment(getArgs);
import Control.Exception(assert);
import Debug.Trace(trace);
import Data.Function((&));
import Control.Category((>>>));
import Prelude hiding((.),(>>));
import Data.List;
--import Control.Monad;
--import Data.Maybe;
--import qualified Data.Map as Map;
--import Data.Map(Map);
--import qualified Data.Set as Set;
--import Data.Set(Set);
import System.Random(RandomGen,Random,StdGen,mkStdGen,random,randoms);
import Data.Ord(comparing);
import Control.Monad.Random(getRandomR,evalRand);
import HillClimb(randomized_hill_climb);
-- to avoid the redundancy warning
trace_placeholder :: ();
trace_placeholder = (trace,assert) & (id >>> error) "trace_placeholder";
main :: IO();
main = getArgs >>= \case{
["big",seed] -> sorted_ntuples (better_mkStdGen $ read seed) 3 & zip_map worst_multiplicative & running_maximum (undefined,1) (comparing snd) & mapM_ print;
["smallview",thresh] -> sorted_ntuples (better_mkStdGen 1) 3 & zip_map worst_multiplicative & filter (\x -> snd x>read thresh) & mapM_ print;
["small",thresh] -> sorted_ntuples (better_mkStdGen 1) 3 & zip_map worst_multiplicative & filter (\x -> snd x>read thresh) & map fst & many_ranges & zip (enumFrom (0::Integer)) & mapM_ print;
["ranged",srange,thresh] -> ranged_ntuples (better_mkStdGen 1) (read srange) & zip_map worst_multiplicative & filter (\x -> snd x>read thresh) & map fst & map (take 3) & many_ranges & zip (enumFrom (0::Integer)) & mapM_ print;
["bigranged",srange,seed] -> ranged_ntuples (better_mkStdGen $ read seed) (read srange) & zip_map worst_multiplicative & running_maximum (undefined,1) (comparing snd) & mapM_ print;
["hill",seed] -> read seed & better_mkStdGen & go_hill & mapM_ print;
_ -> undefined;
};
small_randoms :: RandomGen g => g -> [Double];
small_randoms gen = do {
x :: Double <- randoms gen;
x/2 & return;
};
n_chunk :: Integral i => i -> [a] -> [[a]];
n_chunk n = unfoldr $ genericSplitAt n >>> Just;
sorted_ntuples :: RandomGen g => g -> Integer -> [[Double]];
sorted_ntuples gen size = small_randoms gen & n_chunk size & map sort & map append_unity_minus ;
append_unity_minus :: [Double] -> [Double];
append_unity_minus x = x ++ (reverse $ map (1-) x);
pair_indices :: Integer -> [(Integer,Integer)];
pair_indices size = do {
x <- enumFromTo 1 $ pred size;
return (x-1,x);
};
all_pairs_analyze :: (a -> a -> b) -> [a] -> [b];
all_pairs_analyze op l = do {
(small, large) <- pair_indices $ genericLength l;
return $ op (genericIndex l large) (genericIndex l small);
};
worst_subtractive :: [Double] -> Double;
-- bounding below by zero keeps the smallest dimension large
worst_subtractive = (0:) >>> all_pairs_analyze (-) >>> minimum;
zip_map :: (a -> b) -> [a] -> [(a,b)];
zip_map f l = zip l $ map f l;
type GenericRandom g a = g -> (a,g);
type RandomSG a = GenericRandom StdGen a;
better_mkStdGen :: Int -> StdGen;
-- discard first random sample, see rzzllapd
better_mkStdGen = mkStdGen >>> (random::RandomSG Bool) >>> snd;
-- this program has a space leak!
worst_multiplicative :: [Double] -> Double;
worst_multiplicative = (++[1]) >>> all_pairs_analyze (/) >>> minimum;
running_maximum :: a -> (a -> a -> Ordering) -> [a] -> [a];
running_maximum _ _ [] = [];
running_maximum start f (h:t) = case f start h of {
LT -> h:running_maximum h f t;
_ -> running_maximum start f t;
};
range_update :: (Ord a) => (a,a) -> a -> (a,a);
range_update (low,hi) x = (if x [[(Double,Double)]];
many_ranges = scanl (zipWith range_update) (repeat (1,0)) >>> tail;
random_in_ranges_forever :: (Random a, RandomGen g) => [(a,a)] -> g -> [[a]];
random_in_ranges_forever = mapM getRandomR >>> repeat >>> sequence >>> evalRand;
ranged_ntuples :: RandomGen g => g -> [(Double,Double)] -> [[Double]];
ranged_ntuples gen ranges = random_in_ranges_forever ranges gen & map append_unity_minus;
go_hill :: (RandomGen g) => g -> [([Double],Double)];
go_hill = randomized_hill_climb scorefunc 0.001 gstart;
gstart :: [Double];
gstart = [0.2, 0.3, 0.45];
scorefunc :: [Double] -> Double;
scorefunc = append_unity_minus >>> worst_multiplicative;
} --end