{-| Module  : FiniteCategories
Description : Select a random diagram in a category.
Copyright   : Guillaume Sabbagh 2021
License     : GPL-3
Maintainer  : guillaumesabbagh@protonmail.com
Stability   : experimental
Portability : portable

This module provide functions to generate random diagrams.
It can be used to test functions, to generate examples or to test hypothesis.
-}

module RandomDiagram.RandomDiagram 
(
    mkRandomDiagram,
    defaultMkRandomDiagram
)
where
    import FiniteCategory.FiniteCategory
    import CompositionGraph.CompositionGraph
    import RandomCompositionGraph.RandomCompositionGraph
    import System.Random                            (RandomGen, uniformR)
    import Data.Maybe                               (isNothing, fromJust)
    import Utils.Sample
    import FunctorCategory.FunctorCategory
    import Diagram.Diagram

    -- | Choose a random diagram in the functor category of an index category and an image category.

    mkRandomDiagram :: (FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1,
                        FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2,
                        RandomGen g) => c1 -> c2 -> g -> (Diagram c1 m1 o1 c2 m2 o2, g)
    mkRandomDiagram :: forall c1 m1 o1 c2 m2 o2 g.
(FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1,
 FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2,
 RandomGen g) =>
c1 -> c2 -> g -> (Diagram c1 m1 o1 c2 m2 o2, g)
mkRandomDiagram c1
index c2
cat g
gen = [Diagram c1 m1 o1 c2 m2 o2] -> g -> (Diagram c1 m1 o1 c2 m2 o2, g)
forall g a. RandomGen g => [a] -> g -> (a, g)
pickOne (FunctorCategory c1 m1 o1 c2 m2 o2 -> [Diagram c1 m1 o1 c2 m2 o2]
forall c m o. FiniteCategory c m o => c -> [o]
ob FunctorCategory :: forall c1 m1 o1 c2 m2 o2.
c1 -> c2 -> FunctorCategory c1 m1 o1 c2 m2 o2
FunctorCategory{sourceCat :: c1
sourceCat=c1
index, targetCat :: c2
targetCat=c2
cat}) g
gen
    
    
    -- | Constructs two random composition graphs and choose a random diagram between the two.

    defaultMkRandomDiagram  :: (RandomGen g) => g ->  (Diagram (CompositionGraph Int Int) (CGMorphism Int Int) Int (CompositionGraph Int Int) (CGMorphism Int Int) Int, g)
    defaultMkRandomDiagram :: forall g.
RandomGen g =>
g
-> (Diagram
      (CompositionGraph Int Int)
      (CGMorphism Int Int)
      Int
      (CompositionGraph Int Int)
      (CGMorphism Int Int)
      Int,
    g)
defaultMkRandomDiagram g
g1 = CompositionGraph Int Int
-> CompositionGraph Int Int
-> g
-> (Diagram
      (CompositionGraph Int Int)
      (CGMorphism Int Int)
      Int
      (CompositionGraph Int Int)
      (CGMorphism Int Int)
      Int,
    g)
forall c1 m1 o1 c2 m2 o2 g.
(FiniteCategory c1 m1 o1, Morphism m1 o1, Eq m1, Eq o1,
 FiniteCategory c2 m2 o2, Morphism m2 o2, Eq m2, Eq o2,
 RandomGen g) =>
c1 -> c2 -> g -> (Diagram c1 m1 o1 c2 m2 o2, g)
mkRandomDiagram CompositionGraph Int Int
cat1 CompositionGraph Int Int
cat2 g
g3
        where 
            (Int
nbArrows1, g
g2) = (Int, Int) -> g -> (Int, g)
forall g a. (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
uniformR (Int
1,Int
8) g
g1
            (Int
nbAttempts1, g
g3) = (Int, Int) -> g -> (Int, g)
forall g a. (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
uniformR (Int
0,Int
nbArrows1Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
nbArrows1) g
g2
            (CompositionGraph Int Int
cat1, g
g4) = Int -> Int -> Int -> g -> (CompositionGraph Int Int, g)
forall g.
RandomGen g =>
Int -> Int -> Int -> g -> (CompositionGraph Int Int, g)
mkRandomCompositionGraph Int
nbArrows1 Int
nbAttempts1 Int
5 g
g3
            (Int
nbArrows2, g
g5) = (Int, Int) -> g -> (Int, g)
forall g a. (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
uniformR (Int
1,Int
11Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
nbArrows1) g
g4
            (Int
nbAttempts2, g
g6) = (Int, Int) -> g -> (Int, g)
forall g a. (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
uniformR (Int
0,Int
nbArrows2Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
nbArrows2) g
g5
            (CompositionGraph Int Int
cat2, g
g7) = Int -> Int -> Int -> g -> (CompositionGraph Int Int, g)
forall g.
RandomGen g =>
Int -> Int -> Int -> g -> (CompositionGraph Int Int, g)
mkRandomCompositionGraph Int
nbArrows2 Int
nbAttempts2 Int
5 g
g6