From 7dbbf1a3527fca7289e6338312d321da0f782c79 Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Fri, 15 Feb 2019 23:11:37 +0100 Subject: [PATCH] Improved Spindeterminant --- CI/Phase.ml | 2 +- CI/Spindeterminant.ml | 159 ++++++++++++++++++++++------------------- CI/Spindeterminant.mli | 50 +++++++++++++ 3 files changed, 135 insertions(+), 76 deletions(-) create mode 100644 CI/Spindeterminant.mli diff --git a/CI/Phase.ml b/CI/Phase.ml index 643a7bc..4861c57 100644 --- a/CI/Phase.ml +++ b/CI/Phase.ml @@ -14,7 +14,7 @@ let add_nperm phase = function | (Pos,Pos) | (Neg,Neg) -> Pos | _ -> Neg end - + let pp_phase ppf = function | Pos -> Format.fprintf ppf "@[+1@]" diff --git a/CI/Spindeterminant.ml b/CI/Spindeterminant.ml index 76220d6..dccd981 100644 --- a/CI/Spindeterminant.ml +++ b/CI/Spindeterminant.ml @@ -1,15 +1,29 @@ -type t = +type s = { bitstring : Z.t ; phase : Phase.t ; } +type t = s option + +let phase = function + | Some s -> s.phase + | None -> invalid_arg "Spindeterminant is None" + + +let is_none = function + | None -> true + | _ -> false + + +let bitstring = function + | Some s -> s.bitstring + | None -> invalid_arg "Spindeterminant is None" + let vac = Some { bitstring = Z.zero; - phase = Phase.Pos; - } - + phase = Phase.Pos; } let creation p = function | None -> None @@ -44,101 +58,96 @@ let annihilation q = function Some { bitstring ; phase } end + + let of_list l = - let result = - List.rev l - |> List.fold_left (fun accu p -> creation p accu) vac - in - match result with - | None -> raise (Invalid_argument "Can't create determinant from list") - | Some x -> x + List.rev l + |> List.fold_left (fun accu p -> creation p accu) vac -let rec to_list spindet = - let rec aux accu z = - if z <> Z.zero then - let element = (Z.(trailing_zeros z)+1) in - aux (element::accu) Z.(z land (pred z)) - else List.rev accu - in aux [] spindet - +let rec to_list = function + | None -> [] + | Some spindet -> + let rec aux accu z = + if z <> Z.zero then + let element = (Z.(trailing_zeros z)+1) in + aux (element::accu) Z.(z land (pred z)) + else List.rev accu + in aux [] spindet.bitstring + let pp_bitstring ppf bs = String.init (Z.numbits bs) (fun i -> if (Z.testbit bs i) then '+' else '-') |> Format.fprintf ppf "@[%s@]" -let pp_spindet ppf s = - Format.fprintf ppf "@[%a %a@]" Phase.pp_phase s.phase pp_bitstring s.bitstring +let pp_spindet ppf = function + | None -> Format.fprintf ppf "@[None@]" + | Some s -> + Format.fprintf ppf "@[%a %a@]" Phase.pp_phase s.phase pp_bitstring s.bitstring + +(*-----------------------------------------------------------------------------------*) + + let test_case () = let test_creation () = - let l_a = [ 1 ; 2 ; 3 ; 5 ] in - let det = of_list l_a in - Alcotest.(check (list int )) "bitstring 1" (to_list det.bitstring) l_a; - Alcotest.(check bool) "phase 2" true (det.phase = Phase.Pos); - let l_b = [ 1 ; 3 ; 2 ; 5 ] in - let det = of_list l_b in - Alcotest.(check (list int )) "bitstring 2" (to_list det.bitstring) l_a; - Alcotest.(check bool) "phase 2" true (det.phase = Phase.Neg); + let l_a = [ 1 ; 2 ; 3 ; 5 ] in + let det = of_list l_a in + Alcotest.(check (list int )) "bitstring 1" l_a (to_list det); + Alcotest.(check bool) "phase 2" true (phase det = Phase.Pos); + let l_b = [ 1 ; 3 ; 2 ; 5 ] in + let det = of_list l_b in + Alcotest.(check (list int )) "bitstring 2" l_a (to_list det); + Alcotest.(check bool) "phase 2" true (phase det = Phase.Neg); in let test_operators () = - let det = - creation 5 @@ creation 2 @@ creation 2 @@ creation 1 @@ vac - in - Alcotest.(check bool) "none 1" true (det = None); + let det = + creation 5 @@ creation 2 @@ creation 2 @@ creation 1 @@ vac + in + Alcotest.(check bool) "none 1" true (is_none det); - let det = - match (creation 5 @@ creation 3 @@ creation 2 @@ creation 1 @@ vac) with - | Some x -> x - | None -> assert false - in - let l_a = [ 1 ; 2 ; 3 ; 5 ] in - Alcotest.(check (list int )) "bitstring 1" l_a (to_list det.bitstring); - Alcotest.(check bool) "phase 1" true (det.phase = Phase.Pos); + let det = + creation 5 @@ creation 3 @@ creation 2 @@ creation 1 @@ vac + in + let l_a = [ 1 ; 2 ; 3 ; 5 ] in + Alcotest.(check (list int )) "bitstring 1" l_a (to_list det); + Alcotest.(check bool) "phase 1" true (phase det = Phase.Pos); - let det = - match (creation 1 @@ creation 3 @@ creation 2 @@ creation 5 @@ vac) with - | Some x -> x - | None -> assert false - in - Alcotest.(check (list int )) "bitstring 2" l_a (to_list det.bitstring); - Alcotest.(check bool) "phase 2" true (det.phase = Phase.Neg); + let det = + creation 1 @@ creation 3 @@ creation 2 @@ creation 5 @@ vac + in + Alcotest.(check (list int )) "bitstring 2" l_a (to_list det); + Alcotest.(check bool) "phase 2" true (phase det = Phase.Neg); - let l_b = [ 1 ; 3 ; 2 ; 5 ] in - let det = of_list l_b in - Alcotest.(check (list int )) "bitstring 3" l_a (to_list det.bitstring); - Alcotest.(check bool) "phase 3" true (det.phase = Phase.Neg); + let l_b = [ 1 ; 3 ; 2 ; 5 ] in + let det = of_list l_b in + Alcotest.(check (list int )) "bitstring 3" l_a (to_list det); + Alcotest.(check bool) "phase 3" true (phase det = Phase.Neg); - Alcotest.(check bool) "none 1" true (annihilation 4 (Some det) = None); + Alcotest.(check bool) "none 1" true (annihilation 4 det |> is_none); - let det = - match annihilation 1 (Some det) with - | Some x -> x - | None -> assert false - in - Alcotest.(check (list int )) "bitstring 4" (List.tl l_a) (to_list det.bitstring); - Alcotest.(check bool) "phase 4" true (det.phase = Phase.Neg); + let det = + annihilation 1 det + in + Alcotest.(check (list int )) "bitstring 4" (List.tl l_a) (to_list det); + Alcotest.(check bool) "phase 4" true (phase det = Phase.Neg); - let det = - match annihilation 3 (Some det) with - | Some x -> x - | None -> assert false - in - Alcotest.(check (list int )) "bitstring 5" [ 2 ; 5 ] (to_list det.bitstring); - Alcotest.(check bool) "phase 5" true (det.phase = Phase.Pos); + let det = + annihilation 3 det + in + Alcotest.(check (list int )) "bitstring 5" [ 2 ; 5 ] (to_list det); + Alcotest.(check bool) "phase 5" true (phase det = Phase.Pos); - let det = - match annihilation 5 @@ annihilation 2 (Some det) with - | Some x -> x - | None -> assert false - in - Alcotest.(check (list int )) "bitstring 6" [] (to_list det.bitstring); - Alcotest.(check bool) "phase 6" true (det.phase = Phase.Pos); + let det = + annihilation 5 @@ annihilation 2 det + in + Alcotest.(check (list int )) "bitstring 6" [] (to_list det); + Alcotest.(check bool) "phase 6" true (phase det = Phase.Pos); in [ @@ -146,4 +155,4 @@ let test_case () = "Operators", `Quick, test_operators; ] - + diff --git a/CI/Spindeterminant.mli b/CI/Spindeterminant.mli new file mode 100644 index 0000000..9ab9658 --- /dev/null +++ b/CI/Spindeterminant.mli @@ -0,0 +1,50 @@ +(** +A spin-determinant is one of the two determinants in the Waller-Hartree +double determinant representation of a Slater determinant. It is represented +as a bit string and a phase factor. +*) + +type t + +(** {1 Accessors}. *) + +val phase : t -> Phase.t +(** Phase factor. + @raise [Invalid_argument] if the spin-determinant is [None]. +*) + +val bitstring : t -> Z.t +(** Bit string. + @raise [Invalid_argument] if the spin-determinant is [None]. +*) + +val is_none : t -> bool +(** Tests if a spin-determinant is [None]. *) + + +(** {1 Second quantization operators} *) +val vac : t +(** Vacuum state, [vac = Some ]{% $|\rangle$ %} *) + +val creation : int -> t -> t +(** [creation p] is the creation operator {% $a^\dagger_p$ %}. *) + +val annihilation : int -> t -> t +(** [annihilation q] is the annihilation operator {% $a_q$ %}. *) + +val of_list : int list -> t +(** Builds a spin-determinant from a list of orbital indices. If the creation of the + spin-determinant is not possible because of Pauli's exclusion principle, a [None] + spin-determinant is returned. *) + +val to_list : t -> int list +(** Transforms a spin-determinant into a list of orbital indices. *) + +(** {2 Printers}. *) + +val pp_spindet : Format.formatter -> t -> unit + + +(** {2 Unit testing} *) + +val test_case : unit -> (string * [> `Quick ] * (unit -> unit)) list