-----------------------------------------------------------------------------
-- |
-- Module  :  ForSyDe.Shallow.MoC.Synchronous.Stochastic
-- Copyright   :  (c) ForSyDe Group, KTH 2007-2008
-- License     :  BSD-style (see the file LICENSE)
-- 
-- Maintainer  :  forsyde-dev@ict.kth.se
-- Stability   :  experimental
-- Portability :  portable
--
-- The stochastic library provides a few stochastic skeletons, which are
-- relatives to the skeletons of the synchronous library. These skeletons are
-- based on two elementary functions, 'sigmaUn' and 'sigmaGe'
-- which provide stochastic signals. The background and motivation for this
-- approach is described in the paper 
--
-- Axel Jantsch, Ingo Sander, and Wenbiao Wu,
-- \"The usage of stochastic processes in embedded system specifications\",
-- In /Proceedings of the Ninth International Symposium on Hardware and Software Codesign/, 
-- April 2001 (<http://web.it.kth.se/~axel/papers/2001/codes-2001.pdf>). 
--
-- Unfortunately, not all of the suggested skeletons are
-- implemented. In particular, consolidation-based process
-- constructors and all constructors for the untimed and the discrete
-- timed MoCs are missing.
-----------------------------------------------------------------------------

module ForSyDe.Shallow.MoC.Synchronous.Stochastic (
  -- * Select based synchronous process constructors
  selMapSY, selScanlSY, selMealySY, selMooreSY,
  -- * Elementary stochastic processes
  sigmaUn, sigmaGe) where

import ForSyDe.Shallow.Core.Signal
import ForSyDe.Shallow.MoC.Synchronous.Lib
import System.Random

-- | The skeleton 'selMapSY' is a stochastic variant of 'mapSY'. It
-- has an internal stochastic process and selects one out of two
-- combinatorial functions depending on the output of the stochastic
-- process.
selMapSY :: Int -- ^The seed for the stochastic process
         -> (a -> b) -- ^The first alternative function
         -> (a -> b) -- ^The second alternative function
         -> Signal a -- ^The input signal
         -> Signal b -- ^The output signal of the process
selMapSY :: Int -> (a -> b) -> (a -> b) -> Signal a -> Signal b
selMapSY Int
_ a -> b
_ a -> b
_ Signal a
NullS = Signal b
forall a. Signal a
NullS
selMapSY Int
seed a -> b
f0 a -> b
f1 Signal a
xs = (a -> b) -> (a -> b) -> Signal Int -> Signal a -> Signal b
forall a b.
(a -> b) -> (a -> b) -> Signal Int -> Signal a -> Signal b
selmap1 a -> b
f0 a -> b
f1 (Int -> (Int, Int) -> Signal Int
sigmaUn Int
seed (Int
0,Int
1)) Signal a
xs
  where
    selmap1 :: (a->b)->(a->b)->(Signal Int) -> Signal a -> Signal b
    selmap1 :: (a -> b) -> (a -> b) -> Signal Int -> Signal a -> Signal b
selmap1 a -> b
_ a -> b
_ Signal Int
_ Signal a
NullS = Signal b
forall a. Signal a
NullS
    selmap1 a -> b
f0 a -> b
f1 (Int
s:-Signal Int
_)     (a
x:-Signal a
NullS) 
      = (Int -> (a -> b) -> (a -> b) -> a -> b
forall a b. Int -> (a -> b) -> (a -> b) -> a -> b
select1 Int
s a -> b
f0 a -> b
f1 a
x) b -> Signal b -> Signal b
forall a. a -> Signal a -> Signal a
:- Signal b
forall a. Signal a
NullS
    selmap1 a -> b
f0 a -> b
f1 (Int
s:-Signal Int
NullS) (a
x:-Signal a
_) 
      = (Int -> (a -> b) -> (a -> b) -> a -> b
forall a b. Int -> (a -> b) -> (a -> b) -> a -> b
select1 Int
s a -> b
f0 a -> b
f1 a
x) b -> Signal b -> Signal b
forall a. a -> Signal a -> Signal a
:- Signal b
forall a. Signal a
NullS
    selmap1 a -> b
f0 a -> b
f1 (Int
s:-Signal Int
ss)    (a
x:-Signal a
xs) 
      = (Int -> (a -> b) -> (a -> b) -> a -> b
forall a b. Int -> (a -> b) -> (a -> b) -> a -> b
select1 Int
s a -> b
f0 a -> b
f1 a
x) b -> Signal b -> Signal b
forall a. a -> Signal a -> Signal a
:- ((a -> b) -> (a -> b) -> Signal Int -> Signal a -> Signal b
forall a b.
(a -> b) -> (a -> b) -> Signal Int -> Signal a -> Signal b
selmap1 a -> b
f0 a -> b
f1 Signal Int
ss Signal a
xs)
    selmap1 a -> b
_ a -> b
_ Signal Int
NullS Signal a
_ = [Char] -> Signal b
forall a. HasCallStack => [Char] -> a
error [Char]
"selMapSY: empty seed signal."

-- | The skeleton 'selScanlSY' is a stochastic variant of 'scanlSY'.
selScanlSY :: Int           -- ^The seed
           -> (a -> b -> a) -- ^The first alternative next-state function
           -> (a -> b -> a) -- ^The second alternative function
           -> a             -- ^The initial state
           -> Signal b      -- ^The input signal
           -> Signal a      -- ^The output signal
selScanlSY :: Int -> (a -> b -> a) -> (a -> b -> a) -> a -> Signal b -> Signal a
selScanlSY Int
_ a -> b -> a
_ a -> b -> a
_ a
_ Signal b
NullS = Signal a
forall a. Signal a
NullS
selScanlSY Int
seed a -> b -> a
f0 a -> b -> a
f1 a
mem Signal b
xs = (a -> b -> a)
-> (a -> b -> a) -> a -> Signal Int -> Signal b -> Signal a
forall a b.
(a -> b -> a)
-> (a -> b -> a) -> a -> Signal Int -> Signal b -> Signal a
selscan1 a -> b -> a
f0 a -> b -> a
f1 a
mem (Int -> (Int, Int) -> Signal Int
sigmaUn Int
seed (Int
0,Int
1)) Signal b
xs
  where
    selscan1 :: (a -> b -> a) -> (a -> b -> a) -> a 
             -> Signal Int -> Signal b -> Signal a
    selscan1 :: (a -> b -> a)
-> (a -> b -> a) -> a -> Signal Int -> Signal b -> Signal a
selscan1 a -> b -> a
_ a -> b -> a
_ a
_ Signal Int
_ Signal b
NullS = Signal a
forall a. Signal a
NullS
    selscan1 a -> b -> a
f0 a -> b -> a
f1 a
mem (Int
s:-Signal Int
_) (b
x:-Signal b
NullS)
      = Int -> (a -> b -> a) -> (a -> b -> a) -> a -> b -> a
forall a b c. Int -> (a -> b -> c) -> (a -> b -> c) -> a -> b -> c
select2 Int
s a -> b -> a
f0 a -> b -> a
f1 a
mem b
x a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- Signal a
forall a. Signal a
NullS
    selscan1 a -> b -> a
f0 a -> b -> a
f1 a
mem (Int
s:-Signal Int
NullS) (b
x:-Signal b
_)
      = Int -> (a -> b -> a) -> (a -> b -> a) -> a -> b -> a
forall a b c. Int -> (a -> b -> c) -> (a -> b -> c) -> a -> b -> c
select2 Int
s a -> b -> a
f0 a -> b -> a
f1 a
mem b
x a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- Signal a
forall a. Signal a
NullS
    selscan1 a -> b -> a
f0 a -> b -> a
f1 a
mem (Int
s:-Signal Int
ss) (b
x:-Signal b
xs)
      = Int -> (a -> b -> a) -> (a -> b -> a) -> a -> b -> a
forall a b c. Int -> (a -> b -> c) -> (a -> b -> c) -> a -> b -> c
select2 Int
s a -> b -> a
f0 a -> b -> a
f1 a
mem b
x
        a -> Signal a -> Signal a
forall a. a -> Signal a -> Signal a
:- ((a -> b -> a)
-> (a -> b -> a) -> a -> Signal Int -> Signal b -> Signal a
forall a b.
(a -> b -> a)
-> (a -> b -> a) -> a -> Signal Int -> Signal b -> Signal a
selscan1 a -> b -> a
f0 a -> b -> a
f1 (Int -> (a -> b -> a) -> (a -> b -> a) -> a -> b -> a
forall a b c. Int -> (a -> b -> c) -> (a -> b -> c) -> a -> b -> c
select2 Int
s a -> b -> a
f0 a -> b -> a
f1 a
mem b
x) Signal Int
ss Signal b
xs)
    selscan1 a -> b -> a
_ a -> b -> a
_ a
_ Signal Int
NullS Signal b
_ 
      = [Char] -> Signal a
forall a. HasCallStack => [Char] -> a
error [Char]
"selScanlSY: empty seed signal"
      
select1 :: Int -> (a -> b) -> (a->b) -> a -> b
select1 :: Int -> (a -> b) -> (a -> b) -> a -> b
select1 Int
0 a -> b
f0 a -> b
_ a
x  = a -> b
f0 a
x
select1 Int
1 a -> b
_ a -> b
f1 a
x  = a -> b
f1 a
x
select1 Int
s a -> b
_ a -> b
_ a
_   = [Char] -> b
forall a. HasCallStack => [Char] -> a
error ([Char]
"select1: seed value neither 0 nor 1: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (Int -> [Char]
forall a. Show a => a -> [Char]
show Int
s))

select2 :: Int -> (a -> b -> c) -> (a->b->c) 
        -> a -> b -> c
select2 :: Int -> (a -> b -> c) -> (a -> b -> c) -> a -> b -> c
select2 Int
0 a -> b -> c
f0 a -> b -> c
_ a
x b
y = a -> b -> c
f0 a
x b
y
select2 Int
1 a -> b -> c
_ a -> b -> c
f1 a
x b
y = a -> b -> c
f1 a
x b
y
select2 Int
s a -> b -> c
_ a -> b -> c
_ a
_ b
_  = [Char] -> c
forall a. HasCallStack => [Char] -> a
error ([Char]
"select2: seed value neither 0 nor 1: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (Int -> [Char]
forall a. Show a => a -> [Char]
show Int
s))

-- | 'selMooreSY' is the stochastic variant of mooreSY. Both the
-- next-state and the output function is randomly selected based on
-- a uniform distribution.
selMooreSY :: Int           -- ^The seed for the next-state function
           -> Int           -- ^The seed for the output function
           -> (a -> b -> a) -- ^First alternative for the next-state function
           -> (a -> b -> a) -- ^Second alternative for the next-state function
           -> (a -> c)      -- ^First alternative for the output function
           -> (a -> c)      -- ^Second alternative for the output function
           -> a             -- ^The initial state
           -> Signal b      -- ^The input signal
           -> Signal c      -- ^The output signal
selMooreSY :: Int
-> Int
-> (a -> b -> a)
-> (a -> b -> a)
-> (a -> c)
-> (a -> c)
-> a
-> Signal b
-> Signal c
selMooreSY Int
_ Int
_ a -> b -> a
_ a -> b -> a
_ a -> c
_ a -> c
_ a
_ Signal b
NullS = Signal c
forall a. Signal a
NullS
selMooreSY Int
seedg Int
seedf a -> b -> a
g0 a -> b -> a
g1 a -> c
f0 a -> c
f1 a
w0 Signal b
s
  = ((Int -> (a -> c) -> (a -> c) -> Signal a -> Signal c
forall a b. Int -> (a -> b) -> (a -> b) -> Signal a -> Signal b
selMapSY Int
seedf a -> c
f0 a -> c
f1 ) (Signal a -> Signal c)
-> (Signal b -> Signal a) -> Signal b -> Signal c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (a -> b -> a) -> (a -> b -> a) -> a -> Signal b -> Signal a
forall a b.
Int -> (a -> b -> a) -> (a -> b -> a) -> a -> Signal b -> Signal a
selScanlSY Int
seedg a -> b -> a
g0 a -> b -> a
g1 a
w0)) Signal b
s

-- | 'selMealySY' is the stochastic variant of mealySY. Both the
-- next-state and the output function is randomly selected based on
-- a uniform distribution.
selMealySY :: Int           -- ^The seed for the next-state function
           -> Int           -- ^The seed for the output function
           -> (a -> b -> a) -- ^First alternative for the next-state function
           -> (a -> b -> a) -- ^Second alternative for the next-state function
           -> (a -> b -> c) -- ^First alternative for the output function
           -> (a -> b -> c) -- ^Second alternative for the output function
           -> a             -- ^The initial state
           -> Signal b      -- ^The input signal
           -> Signal c      -- ^The output signal
selMealySY :: Int
-> Int
-> (a -> b -> a)
-> (a -> b -> a)
-> (a -> b -> c)
-> (a -> b -> c)
-> a
-> Signal b
-> Signal c
selMealySY Int
_ Int
_ a -> b -> a
_ a -> b -> a
_ a -> b -> c
_ a -> b -> c
_ a
_ Signal b
NullS = Signal c
forall a. Signal a
NullS
selMealySY Int
seedg Int
seedf a -> b -> a
g0 a -> b -> a
g1 a -> b -> c
f0 a -> b -> c
f1 a
w0 Signal b
s
  = ((Int -> ((b, a) -> c) -> ((b, a) -> c) -> Signal (b, a) -> Signal c
forall a b. Int -> (a -> b) -> (a -> b) -> Signal a -> Signal b
selMapSY Int
seedf (b, a) -> c
f0' (b, a) -> c
f1' ) (Signal (b, a) -> Signal c)
-> (Signal b -> Signal (b, a)) -> Signal b -> Signal c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signal b -> Signal a -> Signal (b, a)
forall a b. Signal a -> Signal b -> Signal (a, b)
zipSY Signal b
s) (Signal a -> Signal (b, a))
-> (Signal b -> Signal a) -> Signal b -> Signal (b, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (a -> b -> a) -> (a -> b -> a) -> a -> Signal b -> Signal a
forall a b.
Int -> (a -> b -> a) -> (a -> b -> a) -> a -> Signal b -> Signal a
selScanlSY Int
seedg a -> b -> a
g0 a -> b -> a
g1 a
w0)) Signal b
s
  where
    f0' :: (b, a) -> c
f0' (b
b, a
a) = a -> b -> c
f0 a
a b
b
    f1' :: (b, a) -> c
f1' (b
b, a
a) = a -> b -> c
f1 a
a b
b
-- |'sigmaUn' generates a signal list of uniformly distributed Int
                      -- within the given range and with a given seed.
sigmaUn :: Int        -- ^The seed
        -> (Int, Int) -- ^The interval from which the stochastic
                      -- values are taken
        -> Signal Int -- ^The sequence of stochastic values
sigmaUn :: Int -> (Int, Int) -> Signal Int
sigmaUn Int
seed (Int, Int)
range = [Int] -> Signal Int
forall a. [a] -> Signal a
signal ((Int, Int) -> StdGen -> [Int]
stoch (Int, Int)
range (Int -> StdGen
mkStdGen Int
seed))
  where
    stoch :: (Int, Int) -> StdGen -> [Int]
    stoch :: (Int, Int) -> StdGen -> [Int]
stoch (Int, Int)
range StdGen
g = Int
newNum Int -> [Int] -> [Int]
`seq` (Int
newNum Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: ((Int, Int) -> StdGen -> [Int]
stoch (Int, Int)
range StdGen
newGen))
      where newNum :: Int
newNum = ((Int, StdGen) -> Int
forall a b. (a, b) -> a
fst ((Int, Int) -> StdGen -> (Int, StdGen)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Int, Int)
range StdGen
g)) 
            newGen :: StdGen
newGen = (Int, StdGen) -> StdGen
forall a b. (a, b) -> b
snd (StdGen -> (Int, StdGen)
forall g. RandomGen g => g -> (Int, g)
next StdGen
g)

-- |'sigmaGe' is a more general stochastic process. The first argument
-- is a function f which describes the distribution. For each value v
-- in the given range (r1,r2), f(v) is the probability that v is
-- generated.
--
-- Note, that the user has to make sure that sum(f(v))=1 for v in
-- (r1,r2).
--
-- For illustration consider the following example.
--
-- > pdist :: Float -> Float
-- > pdist d = 1\/\(2**d\)
-- > pdistsum 1 = pdist 1
-- > pdistsum d = \(pdist d\) + \(pdistsum \(d-1\)\)
--
-- > pdistnorm :: Float -> Float -> Float
-- > pdistnorm dmax d = 1\/((pdistsum dmax) * (2**d))
--
-- @pdistnorm dmax d@ gives the probability of a value <= d;
--
-- @pdistnorm dmax dmax@ is always 1.0
--
-- Hence, using pdistnorm as a function in 'sigmaGe' gives an exponantial
-- distribution for values in the range \[0, dmax\].
sigmaGe :: (Float -> Float) -- ^The stochastic distribution
        -> Int              -- ^The seed
        -> (Int, Int)       -- ^The range
        -> Signal Int       -- ^The sequence of stochastic values
sigmaGe :: (Float -> Float) -> Int -> (Int, Int) -> Signal Int
sigmaGe Float -> Float
f Int
seed (Int
r1,Int
r2) = Float -> (Float -> Float) -> Int -> (Int, Int) -> Signal Int
forall a a.
(Fractional a, Integral a, Show a, Ord a) =>
a -> (Float -> Float) -> Int -> (a, a) -> Signal Int
sigma2 ((Float -> Float) -> Float -> Float -> Float
checkSum Float -> Float
f (Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
r1) 
                                 (Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
r2)) Float -> Float
f Int
seed (Int
r1,Int
r2)
  where
    sigma2 :: a -> (Float -> Float) -> Int -> (a, a) -> Signal Int
sigma2 a
s Float -> Float
f Int
seed (a
r1,a
r2) 
      | a
s a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0.999 = [Int] -> Signal Int
forall a. [a] -> Signal a
signal (StdGen -> [Float] -> [Int]
sigma1 (Int -> StdGen
mkStdGen Int
seed) 
                            ((Float -> Float) -> Float -> [Float]
mkdlist Float -> Float
f (a -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
r2a -> a -> a
forall a. Num a => a -> a -> a
-a
r1))))
      | Bool
otherwise = [Char] -> Signal Int
forall a. HasCallStack => [Char] -> a
error 
                    ([Char]
"sigmaGe: sum of probabilitites is "
                     [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (a -> [Char]
forall a. Show a => a -> [Char]
show a
s) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
". It must be 1.")
    checkSum :: (Float -> Float) -> Float -> Float -> Float
    checkSum :: (Float -> Float) -> Float -> Float -> Float
checkSum Float -> Float
f Float
c Float
max | Float
c Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
max = Float -> Float
f Float
c
                     | Bool
otherwise = Float -> Float
f(Float
c) Float -> Float -> Float
forall a. Num a => a -> a -> a
+ ((Float -> Float) -> Float -> Float -> Float
checkSum Float -> Float
f (Float
cFloat -> Float -> Float
forall a. Num a => a -> a -> a
+Float
1) Float
max)
  
    sigma1 :: StdGen -> [Float] -> [Int]
    sigma1 :: StdGen -> [Float] -> [Int]
sigma1 StdGen
g [Float]
fl = (Float -> [Float] -> Int
findk ((Float, StdGen) -> Float
forall a b. (a, b) -> a
fst ((Float, Float) -> StdGen -> (Float, StdGen)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Float
0.0,Float
1.0) StdGen
g)) [Float]
fl)
                  Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: (StdGen -> [Float] -> [Int]
sigma1 ((Int, StdGen) -> StdGen
forall a b. (a, b) -> b
snd (StdGen -> (Int, StdGen)
forall g. RandomGen g => g -> (Int, g)
next StdGen
g)) [Float]
fl)
  
    findk :: Float -> [Float] -> Int
    findk :: Float -> [Float] -> Int
findk Float
r [Float]
fs = Int -> Float -> [Float] -> Int
forall t t. (Ord t, Num t) => t -> t -> [t] -> t
findk1 Int
0 Float
r [Float]
fs
  
    findk1 :: t -> t -> [t] -> t
findk1 t
k t
r (t
f:[t]
fs) | t
r t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
f = t
k
                      | Bool
otherwise = t -> t -> [t] -> t
findk1 (t
kt -> t -> t
forall a. Num a => a -> a -> a
+t
1) t
r [t]
fs
    findk1 t
k t
_ [] = t
k
  
    mkdlist :: (Float -> Float) -> Float -> [Float]
    mkdlist :: (Float -> Float) -> Float -> [Float]
mkdlist Float -> Float
f Float
d = (Float -> Float -> Float) -> Float -> [Float] -> [Float]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl ((Float -> Float) -> Float -> Float -> Float
sumf Float -> Float
f) Float
0.0 [Float
1..Float
d]
  
    sumf :: (Float -> Float) -> Float -> Float -> Float
    sumf :: (Float -> Float) -> Float -> Float -> Float
sumf Float -> Float
g Float
x Float
y = Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ (Float -> Float
g Float
y)

--pdist :: Float -> Float
--pdist d = 1/(2**d)

--pdistsum 1 = pdist 1
--pdistsum d = (pdist d) + (pdistsum (d-1))

-- The function pdistnorm can be used as a function in sigmaGe for an
-- exponantial distribution of values in the range [0, dmax]:
--pdistnorm :: Float -> Float -> Float
--pdistnorm dmax d = 1/((pdistsum dmax) * (2**d))

--pdnormsum dmax 1 = pdistnorm dmax 1
--pdnormsum dmax d = (pdistnorm dmax d) + (pdnormsum dmax (d-1))


-----------------------------------------------------------------------------
-- Test section:
--
-- These tests are commented to avoid warnings about not-used functions.
-- But the test functions work and are useful.
-- testAll = "test selMapSY: " ++ testSelMap 
--       ++ ", test selMooreSY: " ++ testSelMoore
--       ++ ", test selMealySY: " ++ testSelMealy

-- testSelMap = show so ++ " -> " ++ (cmpSig so (signal [0,3,4,5,4,5,8,9,8,11]))
--     where f0 x = x + 1
--       f1 x = x - 1
--       so = takeS 10 (selMapSY 876876 f0 f1 (signal [1,2..]))

-- testSelMoore = show so ++ " -> " 
--        ++ (cmpSig so (signal [10,2,3,-40,-5,0,7,-80,0,-100]))
--     where so = takeS 10 (selMooreSY 7667567 123234 g0 g1 f0 f1 w0 
--                 (signal [1,2..]))
--       g0 (0,y) x | even x     = (0,x)
--          | otherwise  = (1,x)
--       g0 (1,y) x | x `mod` 3 == 0 = (0,x)
--          | otherwise  = (1,x)
--       g1 (0,y) x | even x     = (1,x)
--          | otherwise  = (0, x)
--       g1 (1,y) x | x `mod` 3 == 0 = (0,0)
--          | otherwise  = (1,x)
--       f0 (0,y) = y
--       f0 (1,y) = -1 * y
--       f1 (0,y) = 10 * y
--       f1 (1,y) = -10 * y
--       w0 = (0,0)

-- testSelMealy = show so ++ " -> " 
--        ++ (cmpSig so (signal [10,2,3,-40,-5,0,7,-80,0,-100]))
--     where so = takeS 10 (selMealySY 7667567 123234 g0 g1 f0 f1 w0 
--                 (signal [1,2..]))
--       g0 (0,y) x | even x     = (0,x)
--          | otherwise  = (1,x)
--       g0 (1,y) x | x `mod` 3 == 0 = (0,x)
--          | otherwise  = (1,x)
--       g1 (0,y) x | even x     = (1,x)
--          | otherwise  = (0, x)
--       g1 (1,y) x | x `mod` 3 == 0 = (0,0)
--          | otherwise  = (1,x)
--       f0 (0,y) x = y
--       f0 (1,y) x = -1 * y
--       f1 (0,y) x = 10 * y
--       f1 (1,y) x = -10 * y
--       w0 = (0,0)
--
--
-- cmpSig :: Eq a => Signal a -> Signal a -> String
-- cmpSig s1 s2 | s1 == s2 = "OK"
--      | otherwise = "Not OK"