10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-12-22 04:13:33 +01:00

Improved Spindeterminant

This commit is contained in:
Anthony Scemama 2019-02-15 23:11:37 +01:00
parent 13005634fb
commit 7dbbf1a352
3 changed files with 135 additions and 76 deletions

View File

@ -14,7 +14,7 @@ let add_nperm phase = function
| (Pos,Pos) | (Neg,Neg) -> Pos | (Pos,Pos) | (Neg,Neg) -> Pos
| _ -> Neg | _ -> Neg
end end
let pp_phase ppf = function let pp_phase ppf = function
| Pos -> Format.fprintf ppf "@[<h>+1@]" | Pos -> Format.fprintf ppf "@[<h>+1@]"

View File

@ -1,15 +1,29 @@
type t = type s =
{ {
bitstring : Z.t ; bitstring : Z.t ;
phase : Phase.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 = let vac =
Some { bitstring = Z.zero; Some { bitstring = Z.zero;
phase = Phase.Pos; phase = Phase.Pos; }
}
let creation p = function let creation p = function
| None -> None | None -> None
@ -44,101 +58,96 @@ let annihilation q = function
Some { bitstring ; phase } Some { bitstring ; phase }
end end
let of_list l = let of_list l =
let result = List.rev l
List.rev l |> List.fold_left (fun accu p -> creation p accu) vac
|> 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
let rec to_list spindet = let rec to_list = function
let rec aux accu z = | None -> []
if z <> Z.zero then | Some spindet ->
let element = (Z.(trailing_zeros z)+1) in let rec aux accu z =
aux (element::accu) Z.(z land (pred z)) if z <> Z.zero then
else List.rev accu let element = (Z.(trailing_zeros z)+1) in
in aux [] spindet aux (element::accu) Z.(z land (pred z))
else List.rev accu
in aux [] spindet.bitstring
let pp_bitstring ppf bs = let pp_bitstring ppf bs =
String.init (Z.numbits bs) (fun i -> if (Z.testbit bs i) then '+' else '-') String.init (Z.numbits bs) (fun i -> if (Z.testbit bs i) then '+' else '-')
|> Format.fprintf ppf "@[<h>%s@]" |> Format.fprintf ppf "@[<h>%s@]"
let pp_spindet ppf s = let pp_spindet ppf = function
Format.fprintf ppf "@[<h>%a %a@]" Phase.pp_phase s.phase pp_bitstring s.bitstring | None -> Format.fprintf ppf "@[<h>None@]"
| Some s ->
Format.fprintf ppf "@[<h>%a %a@]" Phase.pp_phase s.phase pp_bitstring s.bitstring
(*-----------------------------------------------------------------------------------*)
let test_case () = let test_case () =
let test_creation () = let test_creation () =
let l_a = [ 1 ; 2 ; 3 ; 5 ] in let l_a = [ 1 ; 2 ; 3 ; 5 ] in
let det = of_list l_a in let det = of_list l_a in
Alcotest.(check (list int )) "bitstring 1" (to_list det.bitstring) l_a; Alcotest.(check (list int )) "bitstring 1" l_a (to_list det);
Alcotest.(check bool) "phase 2" true (det.phase = Phase.Pos); Alcotest.(check bool) "phase 2" true (phase det = Phase.Pos);
let l_b = [ 1 ; 3 ; 2 ; 5 ] in let l_b = [ 1 ; 3 ; 2 ; 5 ] in
let det = of_list l_b in let det = of_list l_b in
Alcotest.(check (list int )) "bitstring 2" (to_list det.bitstring) l_a; Alcotest.(check (list int )) "bitstring 2" l_a (to_list det);
Alcotest.(check bool) "phase 2" true (det.phase = Phase.Neg); Alcotest.(check bool) "phase 2" true (phase det = Phase.Neg);
in in
let test_operators () = let test_operators () =
let det = let det =
creation 5 @@ creation 2 @@ creation 2 @@ creation 1 @@ vac creation 5 @@ creation 2 @@ creation 2 @@ creation 1 @@ vac
in in
Alcotest.(check bool) "none 1" true (det = None); Alcotest.(check bool) "none 1" true (is_none det);
let det = let det =
match (creation 5 @@ creation 3 @@ creation 2 @@ creation 1 @@ vac) with creation 5 @@ creation 3 @@ creation 2 @@ creation 1 @@ vac
| Some x -> x in
| None -> assert false let l_a = [ 1 ; 2 ; 3 ; 5 ] in
in Alcotest.(check (list int )) "bitstring 1" l_a (to_list det);
let l_a = [ 1 ; 2 ; 3 ; 5 ] in Alcotest.(check bool) "phase 1" true (phase det = Phase.Pos);
Alcotest.(check (list int )) "bitstring 1" l_a (to_list det.bitstring);
Alcotest.(check bool) "phase 1" true (det.phase = Phase.Pos);
let det = let det =
match (creation 1 @@ creation 3 @@ creation 2 @@ creation 5 @@ vac) with creation 1 @@ creation 3 @@ creation 2 @@ creation 5 @@ vac
| Some x -> x in
| None -> assert false Alcotest.(check (list int )) "bitstring 2" l_a (to_list det);
in Alcotest.(check bool) "phase 2" true (phase det = Phase.Neg);
Alcotest.(check (list int )) "bitstring 2" l_a (to_list det.bitstring);
Alcotest.(check bool) "phase 2" true (det.phase = Phase.Neg);
let l_b = [ 1 ; 3 ; 2 ; 5 ] in let l_b = [ 1 ; 3 ; 2 ; 5 ] in
let det = of_list l_b in let det = of_list l_b in
Alcotest.(check (list int )) "bitstring 3" l_a (to_list det.bitstring); Alcotest.(check (list int )) "bitstring 3" l_a (to_list det);
Alcotest.(check bool) "phase 3" true (det.phase = Phase.Neg); 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 = let det =
match annihilation 1 (Some det) with annihilation 1 det
| Some x -> x in
| None -> assert false Alcotest.(check (list int )) "bitstring 4" (List.tl l_a) (to_list det);
in Alcotest.(check bool) "phase 4" true (phase det = Phase.Neg);
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 = let det =
match annihilation 3 (Some det) with annihilation 3 det
| Some x -> x in
| None -> assert false Alcotest.(check (list int )) "bitstring 5" [ 2 ; 5 ] (to_list det);
in Alcotest.(check bool) "phase 5" true (phase det = Phase.Pos);
Alcotest.(check (list int )) "bitstring 5" [ 2 ; 5 ] (to_list det.bitstring);
Alcotest.(check bool) "phase 5" true (det.phase = Phase.Pos);
let det = let det =
match annihilation 5 @@ annihilation 2 (Some det) with annihilation 5 @@ annihilation 2 det
| Some x -> x in
| None -> assert false Alcotest.(check (list int )) "bitstring 6" [] (to_list det);
in Alcotest.(check bool) "phase 6" true (phase det = Phase.Pos);
Alcotest.(check (list int )) "bitstring 6" [] (to_list det.bitstring);
Alcotest.(check bool) "phase 6" true (det.phase = Phase.Pos);
in in
[ [
@ -146,4 +155,4 @@ let test_case () =
"Operators", `Quick, test_operators; "Operators", `Quick, test_operators;
] ]

50
CI/Spindeterminant.mli Normal file
View File

@ -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