-- |
-- Module      : Verismith.Circuit.Base
-- Description : Base types for the circuit module.
-- Copyright   : (c) 2019, Yann Herklotz Grave
-- License     : GPL-3
-- Maintainer  : yann [at] yannherklotz [dot] com
-- Stability   : experimental
-- Portability : POSIX
--
-- Base types for the circuit module.
module Verismith.Circuit.Base
  ( Gate (..),
    Circuit (..),
    CNode (..),
    CEdge (..),
  )
where

import Data.Graph.Inductive (Gr, LEdge, LNode)
import System.Random

-- | The types for all the gates.
data Gate
  = And
  | Or
  | Xor
  deriving (Int -> Gate -> ShowS
[Gate] -> ShowS
Gate -> String
(Int -> Gate -> ShowS)
-> (Gate -> String) -> ([Gate] -> ShowS) -> Show Gate
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Gate -> ShowS
showsPrec :: Int -> Gate -> ShowS
$cshow :: Gate -> String
show :: Gate -> String
$cshowList :: [Gate] -> ShowS
showList :: [Gate] -> ShowS
Show, Gate -> Gate -> Bool
(Gate -> Gate -> Bool) -> (Gate -> Gate -> Bool) -> Eq Gate
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Gate -> Gate -> Bool
== :: Gate -> Gate -> Bool
$c/= :: Gate -> Gate -> Bool
/= :: Gate -> Gate -> Bool
Eq, Int -> Gate
Gate -> Int
Gate -> [Gate]
Gate -> Gate
Gate -> Gate -> [Gate]
Gate -> Gate -> Gate -> [Gate]
(Gate -> Gate)
-> (Gate -> Gate)
-> (Int -> Gate)
-> (Gate -> Int)
-> (Gate -> [Gate])
-> (Gate -> Gate -> [Gate])
-> (Gate -> Gate -> [Gate])
-> (Gate -> Gate -> Gate -> [Gate])
-> Enum Gate
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Gate -> Gate
succ :: Gate -> Gate
$cpred :: Gate -> Gate
pred :: Gate -> Gate
$ctoEnum :: Int -> Gate
toEnum :: Int -> Gate
$cfromEnum :: Gate -> Int
fromEnum :: Gate -> Int
$cenumFrom :: Gate -> [Gate]
enumFrom :: Gate -> [Gate]
$cenumFromThen :: Gate -> Gate -> [Gate]
enumFromThen :: Gate -> Gate -> [Gate]
$cenumFromTo :: Gate -> Gate -> [Gate]
enumFromTo :: Gate -> Gate -> [Gate]
$cenumFromThenTo :: Gate -> Gate -> Gate -> [Gate]
enumFromThenTo :: Gate -> Gate -> Gate -> [Gate]
Enum, Gate
Gate -> Gate -> Bounded Gate
forall a. a -> a -> Bounded a
$cminBound :: Gate
minBound :: Gate
$cmaxBound :: Gate
maxBound :: Gate
Bounded, Eq Gate
Eq Gate =>
(Gate -> Gate -> Ordering)
-> (Gate -> Gate -> Bool)
-> (Gate -> Gate -> Bool)
-> (Gate -> Gate -> Bool)
-> (Gate -> Gate -> Bool)
-> (Gate -> Gate -> Gate)
-> (Gate -> Gate -> Gate)
-> Ord Gate
Gate -> Gate -> Bool
Gate -> Gate -> Ordering
Gate -> Gate -> Gate
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Gate -> Gate -> Ordering
compare :: Gate -> Gate -> Ordering
$c< :: Gate -> Gate -> Bool
< :: Gate -> Gate -> Bool
$c<= :: Gate -> Gate -> Bool
<= :: Gate -> Gate -> Bool
$c> :: Gate -> Gate -> Bool
> :: Gate -> Gate -> Bool
$c>= :: Gate -> Gate -> Bool
>= :: Gate -> Gate -> Bool
$cmax :: Gate -> Gate -> Gate
max :: Gate -> Gate -> Gate
$cmin :: Gate -> Gate -> Gate
min :: Gate -> Gate -> Gate
Ord)

-- | Newtype for the Circuit which implements a Graph from fgl.
newtype Circuit = Circuit {Circuit -> Gr Gate ()
getCircuit :: Gr Gate ()}

-- | Newtype for a node in the circuit, which is an 'LNode Gate'.
newtype CNode = CNode {CNode -> LNode Gate
getCNode :: LNode Gate}

-- | Newtype for a named edge which is empty, as it does not need a label.
newtype CEdge = CEdge {CEdge -> LEdge ()
getCEdge :: LEdge ()}

instance Random Gate where
  randomR :: forall g. RandomGen g => (Gate, Gate) -> g -> (Gate, g)
randomR (Gate
a, Gate
b) g
g =
    case (Int, Int) -> g -> (Int, g)
forall g. RandomGen g => (Int, Int) -> g -> (Int, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Gate -> Int
forall a. Enum a => a -> Int
fromEnum Gate
a, Gate -> Int
forall a. Enum a => a -> Int
fromEnum Gate
b) g
g of
      (Int
x, g
g') -> (Int -> Gate
forall a. Enum a => Int -> a
toEnum Int
x, g
g')

  random :: forall g. RandomGen g => g -> (Gate, g)
random = (Gate, Gate) -> g -> (Gate, g)
forall g. RandomGen g => (Gate, Gate) -> g -> (Gate, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Gate
forall a. Bounded a => a
minBound, Gate
forall a. Bounded a => a
maxBound)