packages feed

srtree-0.1.0.0: src/Data/SRTree/Print.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.SRTree.Print 
-- Copyright   :  (c) Fabricio Olivetti 2021 - 2021
-- License     :  BSD3
-- Maintainer  :  fabricio.olivetti@gmail.com
-- Stability   :  experimental
-- Portability :  
--
-- Conversion functions to display the expression trees in different formats.
--
-----------------------------------------------------------------------------
module Data.SRTree.Print 
         ( DisplayNodes(..)
         , showExpr
         , showTree
         , printExpr
         , showDefault
         , showTikz
         , showPython
         , showLatex
         )
         where

import Control.Monad.Reader ( asks, runReader, Reader )
import Data.Char ( toLower )

import Data.SRTree.Internal

-- | Data structure containing the needed definitions to print a SRTree.
data DisplayNodes ix val = D
  { _displayVar      :: ix -> String
  , _displayPar      :: ix -> String
  , _displayVal      :: val -> String
  , _displayFun      :: Function -> String
  , _displayPow      :: String
  , _displayFloatPow :: String
  }

-- Auxiliary function to print a tree as an infix expression
asExpr :: (Show ix, Show val) => SRTree ix val -> Reader (DisplayNodes ix val) String
asExpr Empty = pure ""
asExpr (Var ix) = do
  display <- asks _displayVar
  pure $ display ix
asExpr (Param ix) = do
  display <- asks _displayPar
  pure $ display ix
asExpr (Const val) = do
  display <- asks _displayVal
  pure $ display val 
asExpr (Fun f t) = do
  display <- asks _displayFun
  st      <- asExpr t
  pure $ mconcat [display f, "(", st, ")"]
asExpr (Pow t ix) = do
  st  <- asExpr t
  pow <- asks _displayPow
  pure $ mconcat ["(", st, ")", pow, "(", show ix, ")"]
asExpr (Add l r) = do
  sl <- asExpr l
  sr <- asExpr r
  pure $ mconcat ["(", sl, ") + (", sr, ")"]
asExpr (Sub l r) = do
  sl <- asExpr l
  sr <- asExpr r
  pure $ mconcat ["(", sl, ") - (", sr, ")"]
asExpr (Mul l r) = do
  sl <- asExpr l
  sr <- asExpr r
  pure $ mconcat ["(", sl, ") * (", sr, ")"]
asExpr (Div l r) = do
  sl <- asExpr l
  sr <- asExpr r
  pure $ mconcat ["(", sl, ") / (", sr, ")"]
asExpr (Power l r) = do
  sl  <- asExpr l
  sr  <- asExpr r
  pow <- asks _displayFloatPow
  pure $ mconcat ["(", sl, ")", pow, "(", sr, ")"]
asExpr (LogBase l r) = do
  sl  <- asExpr l
  sr  <- asExpr r
  pure $ mconcat ["log(", sl, ",", sr, ")"]

-- Auxiliary function to print a tree as a tree-like structure
asTree :: (Show ix, Show val) => SRTree ix val -> Reader (DisplayNodes ix val) String
asTree Empty = pure ""
asTree (Var ix) = do
  display <- asks _displayVar
  pure $ mconcat ["[", display ix, "]\n"]
asTree (Param ix) = do
  display <- asks _displayPar
  pure $ mconcat ["[", display ix, "]\n"]
asTree (Const val) = do
  display <- asks _displayVal
  pure $ mconcat ["[", display val, "]\n"]
asTree (Fun f t) = do
  display <- asks _displayFun
  st      <- asTree t
  pure $ mconcat ["[", display f, "\n", st, "]\n"]
asTree (Pow t ix) = do
  st  <- asTree t
  pow <- asks _displayPow
  pure $ mconcat ["[", pow, "\n", st, "[", show ix, "]\n]"] 
asTree (Add l r) = do
  sl <- asTree l
  sr <- asTree r
  pure $ mconcat ["[+\n", sl, sr, "]\n"]
asTree (Sub l r) = do
  sl <- asTree l
  sr <- asTree r
  pure $ mconcat ["[-\n", sl, sr, "]\n"]
asTree (Mul l r) = do
  sl <- asTree l
  sr <- asTree r
  pure $ mconcat ["[×\n", sl, sr, "]\n"]
asTree (Div l r) = do
  sl <- asTree l
  sr <- asTree r
  pure $ mconcat ["[÷\n", sl, sr, "]\n"]
asTree (Power l r) = do
  sl  <- asTree l
  sr  <- asTree r
  pow <- asks _displayFloatPow
  pure $ mconcat ["[", pow, "\n", sl, sr, "]\n"]
asTree (LogBase l r) = do
  sl  <- asTree l
  sr  <- asTree r
  pure $ mconcat ["[log\n", sl, sr, "]\n"]

-- | Converts a tree to a `String` using the specifications given by `DisplayNodes`
showExpr, showTree :: (Show ix, Show val) => SRTree ix val -> DisplayNodes ix val -> String
showExpr t = runReader (asExpr t)
{-# INLINE showExpr #-}
showTree t = runReader (asTree t)
{-# INLINE showTree #-}

-- | Prints a tree as an expression using the specifications given by `DisplayNodes`
printExpr :: (Show ix, Show val) => SRTree ix val -> DisplayNodes ix val -> IO ()
printExpr t = putStrLn . showExpr t

-- | Displays a tree as an expression
showDefault t = showExpr t d
  where
    d = D (\ix -> mconcat ["x", show ix])
          (\ix -> mconcat ["t", show ix])
          show
          show
          "^"
          "**"

-- | Displays a tree in Tikz format
showTikz :: (Show ix, Show val, RealFrac val) => SRTree ix val -> String 
showTikz t = showTree t d
  where
    d = D (\ix -> mconcat ["$x_{", show ix, "}$"])
          (\ix -> mconcat ["$\\theta_{", show ix, "}$"])
          (\val -> mconcat ["$", show $ (/100) $ fromIntegral $ round $ val*100, "$"])
          show
          "\\^{}"
          "**"

-- | Displays a tree as a numpy compatible expression.
showPython t = showExpr t d
  where
    d = D (\ix -> mconcat ["x[:,", show ix, "]"])
          (\ix -> mconcat ["t[", show ix, "]"])
          show
          pyFun
          "**"
          "**"
          
    pyFun Id     = ""
    pyFun Abs    = "np.abs"
    pyFun Sin    = "np.sin"
    pyFun Cos    = "np.cos"
    pyFun Tan    = "np.tan"
    pyFun Sinh   = "np.sinh"
    pyFun Cosh   = "np.cosh"
    pyFun Tanh   = "np.tanh"
    pyFun ASin   = "np.asin"
    pyFun ACos   = "np.acos"
    pyFun ATan   = "np.atan"
    pyFun ASinh  = "np.asinh"
    pyFun ACosh  = "np.acosh"
    pyFun ATanh  = "np.atanh"
    pyFun Sqrt   = "np.sqrt"
    pyFun Square = "np.square"
    pyFun Log    = "np.log"
    pyFun Exp    = "np.exp"

-- | Displays a tree as a sympy compatible expression.
showLatex :: (Show ix, Show val) => SRTree ix val -> String
showLatex Empty         = ""
showLatex (Var ix)      = mconcat ["x_{", show ix, "}"]
showLatex (Param ix)    = mconcat ["\\theta_{", show ix, "}"]
showLatex (Const val)   = show val
showLatex (Fun Abs t)   = mconcat ["\\left |", showLatex t, "\\right |"]
showLatex (Fun f t)     = mconcat [showLatexFun f, "\\left(", showLatex t, "\\right)"]
showLatex (Pow t ix)    = mconcat ["\\left(", showLatex t, "\\right)^{", show ix, "}"]
showLatex (Add l r)     = mconcat ["\\left(", showLatex l, "\\right) + \\left(", showLatex r, "\\right)"]
showLatex (Sub l r)     = mconcat ["\\left(", showLatex l, "\\right) - \\left(", showLatex r, "\\right)"]
showLatex (Mul l r)     = mconcat ["\\left(", showLatex l, "\\right) \\left(", showLatex r, "\\right)"]
showLatex (Div l r)     = mconcat ["\\frac{", showLatex l, "}{", showLatex r, "}"]
showLatex (Power l r)   = mconcat ["\\left(", showLatex l, "\\right)^{", showLatex r, "}"]
showLatex (LogBase l r) = mconcat ["\\log_{", showLatex r, "}{", showLatex l, "}"]

showLatexFun :: Function -> String
showLatexFun f = mconcat ["\\operatorname{", map toLower $ show f, "}"]