(*Generated by Lem from relation.lem.*)


open Lem_bool
open Lem_basic_classes
open Lem_tuple
open Lem_set
open Lem_num

(* ========================================================================== *)
(* The type of relations                                                      *)
(* ========================================================================== *)

type( 'a, 'b) rel_pred = 'a -> 'b -> bool
type( 'a, 'b) rel_set = ('a * 'b) Pset.set

(* Binary relations are usually represented as either
   sets of pairs (rel_set) or as curried functions (rel_pred). 
   
   The choice depends on taste and the backend. Lem should not take a 
   decision, but supports both representations. There is an abstract type
   pred, which can be converted to both representations. The representation
   of pred itself then depends on the backend. However, for the time beeing,
   let's implement relations as sets to get them working more quickly. *)

type( 'a, 'b) rel = ('a, 'b) rel_set

(*val relToSet : forall 'a 'b. SetType 'a, SetType 'b => rel 'a 'b -> rel_set 'a 'b*)
(*val relFromSet : forall 'a 'b. SetType 'a, SetType 'b => rel_set 'a 'b -> rel 'a 'b*)

(*val relEq : forall 'a 'b. SetType 'a, SetType 'b => rel 'a 'b -> rel 'a 'b -> bool*)
let relEq dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b r1 r2 = ( Pset.equal r1 r2)

(*val relToPred : forall 'a 'b. SetType 'a, SetType 'b, Eq 'a, Eq 'b => rel 'a 'b -> rel_pred 'a 'b*)
(*val relFromPred : forall 'a 'b. SetType 'a, SetType 'b, Eq 'a, Eq 'b => set 'a -> set 'b -> rel_pred 'a 'b -> rel 'a 'b*)

let relToPred dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b dict_Basic_classes_Eq_a dict_Basic_classes_Eq_b r = (fun x y ->  Pset.mem(x, y) r)
let relFromPred dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b dict_Basic_classes_Eq_a dict_Basic_classes_Eq_b xs ys p = (Pset.filter (fun (x,y) -> p x y) ((Pset.cross (pairCompare  
  dict_Basic_classes_SetType_a.setElemCompare_method  dict_Basic_classes_SetType_b.setElemCompare_method) xs ys)))

 
(* ========================================================================== *)
(* Basic Operations                                                           *)
(* ========================================================================== *)

(* ----------------------- *)
(* membership test         *)
(* ----------------------- *)

(*val inRel : forall 'a 'b. SetType 'a, SetType 'b, Eq 'a, Eq 'b => 'a -> 'b -> rel 'a 'b -> bool*)


(* ----------------------- *)
(* empty relation          *)
(* ----------------------- *)

(*val relEmpty : forall 'a 'b. SetType 'a, SetType 'b => rel 'a 'b*)

(* ----------------------- *)
(* Insertion               *)
(* ----------------------- *)

(*val relAdd : forall 'a 'b. SetType 'a, SetType 'b => 'a -> 'b -> rel 'a 'b -> rel 'a 'b*)


(* ----------------------- *)
(* Identity relation       *)
(* ----------------------- *)

(*val relIdOn : forall 'a. SetType 'a, Eq 'a => set 'a -> rel 'a 'a*)
let relIdOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a s = (relFromPred 
  dict_Basic_classes_SetType_a dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a dict_Basic_classes_Eq_a s s  dict_Basic_classes_Eq_a.isEqual_method)

(*val relId : forall 'a. SetType 'a, Eq 'a => rel 'a 'a*)

(* ----------------------- *)
(* relation union          *)
(* ----------------------- *)

(*val relUnion : forall 'a 'b. SetType 'a, SetType 'b => rel 'a 'b -> rel 'a 'b -> rel 'a 'b*) 

(* ----------------------- *)
(* relation intersection   *)
(* ----------------------- *)

(*val relIntersection : forall 'a 'b. SetType 'a, SetType 'b, Eq 'a, Eq 'b => rel 'a 'b -> rel 'a 'b -> rel 'a 'b*) 

(* ----------------------- *)
(* Relation Composition    *)
(* ----------------------- *)

(*val relComp : forall 'a 'b 'c. SetType 'a, SetType 'b, SetType 'c, Eq 'a, Eq 'b => rel 'a 'b -> rel 'b 'c -> rel 'a 'c*)
let relComp dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b dict_Basic_classes_SetType_c dict_Basic_classes_Eq_a dict_Basic_classes_Eq_b r1 r2 = (let x2 =(Pset.from_list (pairCompare  
  dict_Basic_classes_SetType_a.setElemCompare_method  dict_Basic_classes_SetType_c.setElemCompare_method) []) in  Pset.fold
   (fun(e1,e2) x2 -> Pset.fold
                       (fun(e2',e3) x2 ->
                        if dict_Basic_classes_Eq_b.isEqual_method e2 e2' then
                          Pset.add (e1, e3) x2 else x2) (r2) x2) (r1) 
 x2)

(* ----------------------- *)
(* restrict                *)
(* ----------------------- *)

(*val relRestrict : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> rel 'a 'a*)
let relRestrict dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (let x2 =(Pset.from_list (pairCompare  
  dict_Basic_classes_SetType_a.setElemCompare_method  dict_Basic_classes_SetType_a.setElemCompare_method) []) in  Pset.fold
   (fun a x2 -> Pset.fold
                  (fun b x2 ->
                   if Pset.mem (a, b) r then Pset.add (a, b) x2 else x2) 
                s x2) s x2)


(* ----------------------- *)
(* Converse                *)
(* ----------------------- *)

(*val relConverse : forall 'a 'b. SetType 'a, SetType 'b => rel 'a 'b -> rel 'b 'a*)
let relConverse dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b r = ((Pset.map (pairCompare  
  dict_Basic_classes_SetType_b.setElemCompare_method  dict_Basic_classes_SetType_a.setElemCompare_method) Lem.pair_swap (r)))


(* ----------------------- *)
(* domain                  *)
(* ----------------------- *)

(*val relDomain : forall 'a 'b. SetType 'a, SetType 'b => rel 'a 'b -> set 'a*)
let relDomain dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b r = (Pset.map  
  dict_Basic_classes_SetType_a.setElemCompare_method (fun x -> fst x) (r))

(* ----------------------- *)
(* range                   *)
(* ----------------------- *)

(*val relRange : forall 'a 'b. SetType 'a, SetType 'b => rel 'a 'b -> set 'b*)
let relRange dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b r = (Pset.map  
  dict_Basic_classes_SetType_b.setElemCompare_method (fun x -> snd x) (r))


(* ----------------------- *)
(* field / definedOn       *)
(*                         *)
(* avoid the keyword field *)
(* ----------------------- *)

(*val relDefinedOn : forall 'a. SetType 'a => rel 'a 'a -> set 'a*)

(* ----------------------- *)
(* relOver                 *)
(*                         *)
(* avoid the keyword field *)
(* ----------------------- *)

(*val relOver : forall 'a. SetType 'a => rel 'a 'a -> set 'a -> bool*)
let relOver dict_Basic_classes_SetType_a r s = ( Pset.subset(( Pset.(union)(relDomain 
  dict_Basic_classes_SetType_a dict_Basic_classes_SetType_a r) (relRange dict_Basic_classes_SetType_a dict_Basic_classes_SetType_a r))) s)


(* ----------------------- *)
(* apply a relation        *)
(* ----------------------- *)

(* Given a relation r and a set s, relApply r s applies s to r, i.e.
   it returns the set of all value reachable via r from a value in s.
   This operation can be seen as a generalisation of function application. *)
   
(*val relApply : forall 'a 'b. SetType 'a, SetType 'b, Eq 'a => rel 'a 'b -> set 'a -> set 'b*)
let relApply dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b dict_Basic_classes_Eq_a r s = (let x2 =(Pset.from_list  
  dict_Basic_classes_SetType_b.setElemCompare_method  []) in  Pset.fold (fun(x, y) x2 -> if Pset.mem x s then Pset.add y x2 else x2) 
 (r) x2)


(* ========================================================================== *)
(* Properties                                                                 *)
(* ========================================================================== *)

(* ----------------------- *)
(* subrel                  *)
(* ----------------------- *)

(*val isSubrel : forall 'a 'b. SetType 'a, SetType 'b, Eq 'a, Eq 'b => rel 'a 'b -> rel 'a 'b -> bool*)

(* ----------------------- *)
(* reflexivity             *)
(* ----------------------- *)

(*val isReflexiveOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isReflexiveOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.for_all  
  (fun e -> Pset.mem (e, e) r) s)

(*val isReflexive : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)


(* ----------------------- *)
(* irreflexivity           *)
(* ----------------------- *)

(*val isIrreflexiveOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isIrreflexiveOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.for_all  
  (fun e -> not ( Pset.mem (e, e) r)) s)

(*val isIrreflexive : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)
let isIrreflexive dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r = (Pset.for_all  
  (fun (e1, e2) -> not ( dict_Basic_classes_Eq_a.isEqual_method e1 e2)) (r))


(* ----------------------- *)
(* symmetry                *)
(* ----------------------- *)

(*val isSymmetricOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isSymmetricOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.for_all  
  (fun e1 -> Pset.for_all
               (fun e2 -> ((not ( Pset.mem (e1, e2) r)) ||
                             ( Pset.mem (e2, e1) r))) s) s)

(*val isSymmetric : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)
let isSymmetric dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r = (Pset.for_all  
  (fun (e1, e2) -> Pset.mem (e2, e1) r) r)


(* ----------------------- *)
(* antisymmetry            *)
(* ----------------------- *)

(*val isAntisymmetricOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isAntisymmetricOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.for_all  
  (fun e1 -> Pset.for_all
               (fun e2 -> ((not ( Pset.mem (e1, e2) r)) ||
                             ((not ( Pset.mem (e2, e1) r)) ||
                                ( dict_Basic_classes_Eq_a.isEqual_method 
                                  e1 e2)))) s) s)

(*val isAntisymmetric : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)
let isAntisymmetric dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r = (Pset.for_all  
  (fun (e1, e2) -> ((not ( Pset.mem (e2, e1) r)) ||
                      ( dict_Basic_classes_Eq_a.isEqual_method e1 e2))) r)


(* ----------------------- *)
(* transitivity            *)
(* ----------------------- *)

(*val isTransitiveOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isTransitiveOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.for_all  
  (fun e1 -> Pset.for_all
               (fun e2 -> Pset.for_all
                            (fun e3 -> ((not ( Pset.mem (e1, e2) r)) ||
                                          ((not ( Pset.mem (e2, e3) r)) ||
                                             ( Pset.mem (e1, e3) r)))) 
                          s) s) s)

(*val isTransitive : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)
let isTransitive dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r = (Pset.for_all  
  (fun (e1, e2) -> Pset.for_all (fun e3 -> Pset.mem (e1, e3) r)
                     (relApply dict_Basic_classes_SetType_a
                        dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a
                        r
                        (Pset.from_list
                           dict_Basic_classes_SetType_a.setElemCompare_method
                           [e2]))) r)

(* ----------------------- *)
(* total                   *)
(* ----------------------- *)

(*val isTotalOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isTotalOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.for_all  
  (fun e1 -> Pset.for_all
               (fun e2 -> ( Pset.mem (e1, e2) r) || ( Pset.mem (e2, e1) r)) 
             s) s)


(*val isTotal : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)


(*val isTrichotomousOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isTrichotomousOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.for_all  
  (fun e1 -> Pset.for_all
               (fun e2 -> ( Pset.mem (e1, e2) r) ||
                            (( dict_Basic_classes_Eq_a.isEqual_method e1 e2)
                               || ( Pset.mem (e2, e1) r))) s) s)

(*val isTrichotomous : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)


(* ----------------------- *)
(* is_single_valued        *)
(* ----------------------- *)

(*val isSingleValued : forall 'a 'b. SetType 'a, SetType 'b, Eq 'a, Eq 'b => rel 'a 'b -> bool*)
let isSingleValued dict_Basic_classes_SetType_a dict_Basic_classes_SetType_b dict_Basic_classes_Eq_a dict_Basic_classes_Eq_b r = (Pset.for_all  
  (fun (e1, e2a) -> Pset.for_all
                      (fun e2b -> dict_Basic_classes_Eq_b.isEqual_method 
                                  e2a e2b)
                      (relApply dict_Basic_classes_SetType_a
                         dict_Basic_classes_SetType_b dict_Basic_classes_Eq_a
                         r
                         (Pset.from_list
                            dict_Basic_classes_SetType_a.setElemCompare_method
                            [e1]))) r)


(* ----------------------- *)
(* equivalence relation    *)
(* ----------------------- *)

(*val isEquivalenceOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isEquivalenceOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (isReflexiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && (isSymmetricOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && isTransitiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s))


(*val isEquivalence : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)


(* ----------------------- *)
(* well founded            *)
(* ----------------------- *)

(*val isWellFounded : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)


(* ========================================================================== *)
(* Orders                                                                     *)
(* ========================================================================== *)


(* ----------------------- *)
(* pre- or quasiorders     *)
(* ----------------------- *)

(*val isPreorderOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isPreorderOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (isReflexiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && isTransitiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s)

(*val isPreorder : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)


(* ----------------------- *)
(* partial orders          *)
(* ----------------------- *)

(*val isPartialOrderOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isPartialOrderOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (isReflexiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && (isTransitiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && isAntisymmetricOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s))


(*val isStrictPartialOrderOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isStrictPartialOrderOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (isIrreflexiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && isTransitiveOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s)


(*val isStrictPartialOrder : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)
let isStrictPartialOrder dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r = (isIrreflexive 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r && isTransitive dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r)

(*val isPartialOrder : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)

(* ----------------------- *)
(* total / linear orders   *)
(* ----------------------- *)

(*val isTotalOrderOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isTotalOrderOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (isPartialOrderOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && isTotalOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s)

(*val isStrictTotalOrderOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> bool*)
let isStrictTotalOrderOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (isStrictPartialOrderOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s && isTrichotomousOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s)

(*val isTotalOrder : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)

(*val isStrictTotalOrder : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> bool*)



(* ========================================================================== *)
(* closures                                                                   *)
(* ========================================================================== *)

(* ----------------------- *)
(* transitive closure      *)
(* ----------------------- *)

(*val transitiveClosure : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> rel 'a 'a*)
(*val transitiveClosureByEq  : forall 'a. ('a -> 'a -> bool) -> rel 'a 'a -> rel 'a 'a*)
(*val transitiveClosureByCmp : forall 'a. ('a * 'a -> 'a * 'a -> ordering) -> rel 'a 'a -> rel 'a 'a*)


(* ----------------------- *)
(* transitive closure step *)
(* ----------------------- *)

(*val transitiveClosureAdd : forall 'a. SetType 'a, Eq 'a => 'a -> 'a -> rel 'a 'a -> rel 'a 'a*)

let transitiveClosureAdd dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a x y r = 
  (( Pset.(union)(((Pset.add (x,y) (r)))) ((( Pset.(union)((let x2 =(Pset.from_list (pairCompare  
  dict_Basic_classes_SetType_a.setElemCompare_method  dict_Basic_classes_SetType_a.setElemCompare_method) []) in  Pset.fold (fun z x2 -> if Pset.mem (y, z) r then Pset.add (x, z) x2 else x2)
   (relRange dict_Basic_classes_SetType_a dict_Basic_classes_SetType_a r) 
 x2)) ((let x2 =(Pset.from_list (pairCompare  
  dict_Basic_classes_SetType_a.setElemCompare_method  dict_Basic_classes_SetType_a.setElemCompare_method) []) in  Pset.fold (fun z x2 -> if Pset.mem (z, x) r then Pset.add (z, y) x2 else x2)
   (relDomain dict_Basic_classes_SetType_a dict_Basic_classes_SetType_a r) 
 x2)))))))


(* ========================================================================== *)
(* reflexiv closures                                                          *)
(* ========================================================================== *)

(*val reflexivTransitiveClosureOn : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> set 'a -> rel 'a 'a*)
let reflexivTransitiveClosureOn dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a r s = (Pset.tc (pairCompare  
  dict_Basic_classes_SetType_a.setElemCompare_method  dict_Basic_classes_SetType_a.setElemCompare_method) (( Pset.(union)(r) ((relIdOn 
  dict_Basic_classes_SetType_a dict_Basic_classes_Eq_a s)))))


(*val reflexivTransitiveClosure : forall 'a. SetType 'a, Eq 'a => rel 'a 'a -> rel 'a 'a*)

