packages feed

AERN-Net-0.2.0: tests/DemoSqrt.hs

{-|
    A simple exact real number network, computing the
    square root of 2 using the continued fraction expansion
    of sqrt(x).
-}
module Main where

import qualified Control.ERNet.Foundations.Manager as MAN
import qualified Control.ERNet.Foundations.Channel as CH
import qualified Control.ERNet.Foundations.Event.Logger as LG
import Control.ERNet.Foundations.Event.JavaScript

import Control.ERNet.Deployment.Local.Manager

import Control.ERNet.Foundations.Protocol
import Control.ERNet.Foundations.Protocol.StandardCombinators
import Control.ERNet.Foundations.Process

import Control.ERNet.Blocks.Basic
import Control.ERNet.Blocks.Control.Basic
import Control.ERNet.Blocks.Real.Basic
import Control.ERNet.Blocks.Real.Protocols

import qualified Data.Number.ER.Real.Approx as RA
import Data.Number.ER.BasicTypes

import qualified Data.Number.ER.Real.DefaultRepr as RATypes


type B = RATypes.BAP
type IRA = RATypes.IRA B
type RA = RATypes.RA B

sampleRA = (0 :: RA)

chtpR = chTIx $ chTReal sampleRA

waitTillEnd = True 
{- 
    Use the above to produce a HTML+JavaScript document for browsing the trace.
    The fixed HTML page "ernet-trace.html" imports the JavaScript file
    "ernet-trace.js", which is generated by this program.
    
    Instead, you can enable the code below for a continual textual log
    to the standard output.  This can be overwhelming but is the only
    option when the network does not terminate correctly.
-}
--waitTillEnd = False

runTheNet = runSqrtIx

main = 
    do
    RA.initialiseBaseArithmetic (0 :: RA)
    (ernetManager, _) <- MAN.new "main"
    let _ = ernetManager :: ManagerLocal
    logger <- runTheNet ernetManager waitTillEnd
    case waitTillEnd of
        True ->
            do
            events <- LG.emptyAndGetEvents logger
            writeFile "ernet-trace.js" $ constructJS events
        False ->
            LG.emptyAndDo logger $ 
                putStrLn . show

runSqrtIx ::
    (MAN.Manager man lg sIn sOut sInAnyProt sOutAnyProt) =>
    man ->
    Bool ->
    IO lg
runSqrtIx ernetManager waitTillEnd =
    MAN.runDialogue 
        ernetManager
        sqrtProcess
        sqrtSockN
        sqrtSockT
        sqrtDialogue
        waitTillEnd

sqrtDialogue makeQueryGetAnswer =
    do
    mapM doQuerySol [3..12]
    return ()
    where
    doQuerySol ix =
        do
        a <- makeQueryGetAnswer $ QAIxQ ix $ QARealQ
        let _ = [a, (QAIxA $ QARealA sampleRA)]
        return ()

sqrtSockT = chtpR
sqrtSockN = 0

sqrtProcess ::
    (CH.Channel sIn sOut sInAnyProt sOutAnyProt) =>
    ERProcess sInAnyProt sOutAnyProt
sqrtProcess =
    subnetProcess
        "SQRT"
        [] -- input sockets
        [(chtpR, resN)] -- output sockets
        -- sub-processes:
        [
         (constantProcess "A" (makeAnswerR (\ix -> RA.setMinGranularity (2 * (effIx2gran ix) + 10) (2::RA))) chtpR
         ,([],     [aN])
         )
        ,
         (passThroughProcess False "A-1" 
            id (\ _ (QAIxA (QARealA r)) -> (QAIxA $ QARealA $ (r::RA) - 1)) 
            chtpR chtpR
         ,([aN],    [aM1N])
         )
        ,
         (passThroughProcess False "X+1" 
            id (\ _ (QAIxA (QARealA r)) -> (QAIxA $ QARealA $ (r::RA) + 1)) 
            chtpR chtpR
         ,([resN],    [resP1N])
         )
        ,
         (passThroughBinaryProcess False "(A-1)/(X+1)"
            (\ qry -> (qry,qry)) 
            (\ _ ((QAIxA (QARealA num)), (QAIxA (QARealA den))) -> (QAIxA $ QARealA $ (num::RA) / den)) 
            (chtpR, chtpR) chtpR
         ,([aM1N, resP1N],    [resM1N])
         )
        ,
         (passThroughProcess False "(A-1)/(X+1) + 1" 
            id (\ _ (QAIxA (QARealA r)) -> (QAIxA $ QARealA $ (r::RA) + 1)) 
            chtpR chtpR
         ,([resM1N],    [resCycleN])
         )
        ,
         (constantProcess "[0,oo]" 
            (\(QAIxQ _ QARealQ) -> (QAIxA $ QARealA $ ((max 0 RA.bottomApprox)::RA))) chtpR
         ,([],    [resInitN])
         )
        ,
         (improverIxSimpleProcess "IMPR"
            chtpR
            (QARealA (0::RA))
         ,([resInitN, resCycleN],    [resN])
         )
        ]
    where
    resN : resInitN : resCycleN : resM1N : resP1N : aM1N : aN
        : _ = [0..]