10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-11-07 06:33:39 +01:00
QCaml/CI/Spindeterminant.ml

245 lines
7.4 KiB
OCaml
Raw Normal View History

2019-02-15 23:11:37 +01:00
type s =
2019-02-15 13:48:48 +01:00
{
2019-03-25 19:28:38 +01:00
bitstring : Bitstring.t;
2019-02-15 13:48:48 +01:00
phase : Phase.t ;
}
2019-02-15 23:11:37 +01:00
type t = s option
2019-02-16 10:36:56 +01:00
type hole = int
type particle = int
2019-02-15 23:11:37 +01:00
let phase = function
| Some s -> s.phase
2019-02-18 12:41:54 +01:00
| None -> Phase.Pos
2019-02-15 23:11:37 +01:00
let is_none = function
| None -> true
| _ -> false
let bitstring = function
| Some s -> s.bitstring
| None -> invalid_arg "Spindeterminant is None"
2019-02-15 16:25:47 +01:00
2019-03-26 01:20:17 +01:00
let vac n =
Some { bitstring = Bitstring.zero n;
2019-02-15 23:11:37 +01:00
phase = Phase.Pos; }
2019-02-15 16:25:47 +01:00
2019-03-25 19:28:38 +01:00
2019-02-15 16:25:47 +01:00
let creation p = function
| None -> None
| Some spindet ->
let i = pred p in
2019-03-25 19:28:38 +01:00
if Bitstring.testbit spindet.bitstring i then
2019-02-15 16:25:47 +01:00
None
else
begin
2019-03-26 01:20:17 +01:00
let numbits = Bitstring.numbits spindet.bitstring in
let x = Bitstring.shift_left_one numbits i in
2019-03-25 19:28:38 +01:00
let bitstring = Bitstring.logor spindet.bitstring x in
let mask = Bitstring.minus_one x in
let r = Bitstring.logand bitstring mask in
let phase = Phase.add_nperm spindet.phase (Bitstring.popcount r) in
2019-02-15 16:25:47 +01:00
Some { bitstring ; phase }
end
2019-02-16 10:36:56 +01:00
let annihilation h = function
2019-02-15 16:25:47 +01:00
| None -> None
| Some spindet ->
2019-02-16 10:36:56 +01:00
let i = pred h in
2019-03-25 19:28:38 +01:00
if not (Bitstring.testbit spindet.bitstring i) then
2019-02-15 16:25:47 +01:00
None
else
begin
2019-03-26 01:20:17 +01:00
let numbits = Bitstring.numbits spindet.bitstring in
let x = Bitstring.shift_left_one numbits i in
2019-03-25 19:28:38 +01:00
let mask = Bitstring.minus_one x in
let r = Bitstring.logand spindet.bitstring mask in
let phase = Phase.add_nperm spindet.phase (Bitstring.popcount r) in
let bitstring = Bitstring.logand spindet.bitstring (Bitstring.lognot x) in
2019-02-15 16:25:47 +01:00
Some { bitstring ; phase }
end
2019-02-16 10:36:56 +01:00
let single_excitation_reference h p spindet =
creation p @@ annihilation h @@ spindet
2019-02-15 23:11:37 +01:00
2019-02-16 11:05:38 +01:00
let single_excitation h p =
single_excitation_reference h p
let double_excitation_reference h' p' h p spindet =
creation p' @@ creation p @@ annihilation h @@ annihilation h' @@ spindet
let double_excitation h' p' h p =
double_excitation_reference h' p' h p
2019-02-18 15:39:26 +01:00
2019-04-03 22:17:20 +02:00
let degree t t' =
Bitstring.hamdist (bitstring t) (bitstring t') / 2
2019-02-18 15:39:26 +01:00
let holes_of t t' =
2019-03-25 19:28:38 +01:00
Bitstring.logand (bitstring t) (Bitstring.logxor (bitstring t) (bitstring t'))
2019-03-26 01:20:17 +01:00
|> Bitstring.to_list
2019-02-18 15:39:26 +01:00
let particles_of t t' =
2019-03-25 19:28:38 +01:00
Bitstring.logand (bitstring t') (Bitstring.logxor (bitstring t) (bitstring t'))
2019-03-26 01:20:17 +01:00
|> Bitstring.to_list
2019-02-18 15:39:26 +01:00
2019-02-22 00:18:32 +01:00
let holes_particles_of t t' =
2019-03-25 19:28:38 +01:00
let x = Bitstring.logxor (bitstring t) (bitstring t') in
2019-03-26 01:20:17 +01:00
let holes = Bitstring.logand (bitstring t) x |> Bitstring.to_list
and particles = Bitstring.logand (bitstring t') x |> Bitstring.to_list
2019-02-22 00:18:32 +01:00
in
List.map2 (fun h p -> (h,p)) holes particles
2019-02-18 19:45:41 +01:00
let negate_phase = function
| Some t -> Some { t with phase = Phase.neg t.phase }
| None -> None
2019-02-18 15:39:26 +01:00
2019-02-15 23:11:37 +01:00
2019-02-19 17:36:07 +01:00
let of_bitstring ?(phase=Phase.Pos) bitstring =
Some { bitstring ; phase }
2019-03-26 01:20:17 +01:00
let of_list n l =
2019-02-15 23:11:37 +01:00
List.rev l
2019-03-26 01:20:17 +01:00
|> List.fold_left (fun accu p -> creation p accu) (vac n)
2019-02-15 16:25:47 +01:00
2019-02-15 13:48:48 +01:00
2019-02-15 23:11:37 +01:00
let rec to_list = function
| None -> []
| Some spindet ->
let rec aux accu z =
2019-03-25 19:28:38 +01:00
if not (Bitstring.is_zero z) then
let element = ((Bitstring.trailing_zeros z)+1) in
aux (element::accu) (Bitstring.logand z (Bitstring.minus_one z) )
2019-02-15 23:11:37 +01:00
else List.rev accu
in aux [] spindet.bitstring
2019-04-05 09:46:23 +02:00
let rec to_array t =
to_list t
|> Array.of_list
2019-02-15 13:48:48 +01:00
2019-03-19 19:07:55 +01:00
let n_electrons = function
2019-03-25 19:28:38 +01:00
| Some t -> Bitstring.popcount t.bitstring
2019-03-19 19:07:55 +01:00
| None -> 0
2019-02-20 19:43:16 +01:00
let pp_spindet n ppf = function
2019-02-15 23:11:37 +01:00
| None -> Format.fprintf ppf "@[<h>None@]"
| Some s ->
2019-03-26 01:20:17 +01:00
Format.fprintf ppf "@[<h>%a %a@]" Phase.pp_phase s.phase Bitstring.pp
2019-03-25 19:28:38 +01:00
s.bitstring
2019-02-15 13:48:48 +01:00
2019-02-15 23:11:37 +01:00
(*-----------------------------------------------------------------------------------*)
2019-02-15 13:48:48 +01:00
let test_case () =
let test_creation () =
2019-02-15 23:11:37 +01:00
let l_a = [ 1 ; 2 ; 3 ; 5 ] in
2019-03-26 01:20:17 +01:00
let det = of_list 10 l_a in
2019-02-15 23:11:37 +01:00
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
2019-03-26 01:20:17 +01:00
let det = of_list 10 l_b in
2019-02-15 23:11:37 +01:00
Alcotest.(check (list int )) "bitstring 2" l_a (to_list det);
Alcotest.(check bool) "phase 2" true (phase det = Phase.Neg);
2019-02-15 16:25:47 +01:00
in
2019-02-16 10:36:56 +01:00
let test_a_operators () =
2019-02-15 23:11:37 +01:00
let det =
2019-03-26 01:20:17 +01:00
creation 5 @@ creation 2 @@ creation 2 @@ creation 1 @@ (vac 10)
2019-02-15 23:11:37 +01:00
in
Alcotest.(check bool) "none 1" true (is_none det);
let det =
2019-03-26 01:20:17 +01:00
creation 5 @@ creation 3 @@ creation 2 @@ creation 1 @@ (vac 10)
2019-02-15 23:11:37 +01:00
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 =
2019-03-26 01:20:17 +01:00
creation 1 @@ creation 3 @@ creation 2 @@ creation 5 @@ (vac 10)
2019-02-15 23:11:37 +01:00
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
2019-03-26 01:20:17 +01:00
let det = of_list 10 l_b in
2019-02-15 23:11:37 +01:00
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 det |> is_none);
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 =
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 =
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);
2019-02-15 16:25:47 +01:00
2019-02-15 13:48:48 +01:00
in
2019-02-16 10:36:56 +01:00
let test_exc_operators () =
let l_a = [ 1 ; 2 ; 3 ; 5 ] in
2019-03-26 01:20:17 +01:00
let det = of_list 10 l_a in
2019-02-16 10:36:56 +01:00
let l_b = [ 1 ; 7 ; 3 ; 5 ] in
2019-03-26 01:20:17 +01:00
let det2 = of_list 10 l_b in
Format.printf "%a@." (pp_spindet 7) det;
Format.printf "%a@." (pp_spindet 7) det2;
Format.printf "%a@." (pp_spindet 7) (single_excitation_reference 2 7 det);
2019-02-16 11:05:38 +01:00
Alcotest.(check bool) "single 1" true (single_excitation_reference 2 7 det = det2);
Alcotest.(check bool) "single 2" true (single_excitation 2 7 det = single_excitation_reference 2 7 det);
Alcotest.(check bool) "single 3" true (single_excitation_reference 4 7 det |> is_none);
Alcotest.(check bool) "single 4" true (single_excitation 4 7 det |> is_none);
let l_c = [ 1 ; 7 ; 6 ; 5 ] in
2019-03-26 01:20:17 +01:00
let det3 = of_list 10 l_c in
2019-02-16 11:05:38 +01:00
Alcotest.(check bool) "double 1" true (double_excitation_reference 2 7 3 6 det = det3);
Alcotest.(check bool) "double 2" true (double_excitation 2 7 3 6 det = double_excitation_reference 2 7 3 6 det);
Alcotest.(check bool) "double 3" true (double_excitation_reference 4 7 3 6 det |> is_none);
Alcotest.(check bool) "double 4" true (double_excitation 4 7 3 6 det |> is_none);
2019-02-16 10:36:56 +01:00
in
2019-02-18 15:39:26 +01:00
let test_exc_spindet () =
let l_a = [ 1 ; 2 ; 3 ; 5 ] in
2019-03-26 01:20:17 +01:00
let det = of_list 10 l_a in
2019-02-18 15:39:26 +01:00
let l_b = [ 1 ; 7 ; 3 ; 5 ] in
2019-03-26 01:20:17 +01:00
let det2 = of_list 10 l_b in
2019-02-18 15:39:26 +01:00
Alcotest.(check int) "single" 1 (degree det det2);
Alcotest.(check (list int)) "holes" [2] (holes_of det det2);
Alcotest.(check (list int)) "particles" [7] (particles_of det det2);
let l_b = [ 1 ; 7 ; 3 ; 6 ] in
2019-03-26 01:20:17 +01:00
let det2 = of_list 10 l_b in
2019-02-18 15:39:26 +01:00
Alcotest.(check int) "double" 2 (degree det det2);
Alcotest.(check (list int)) "holes" [2 ; 5] (holes_of det det2);
Alcotest.(check (list int)) "particles" [6 ; 7] (particles_of det det2);
in
2019-02-15 13:48:48 +01:00
[
"Creation", `Quick, test_creation;
2019-02-16 10:36:56 +01:00
"Creation/Annihilation Operators", `Quick, test_a_operators;
"Excitation Operators", `Quick, test_exc_operators;
2019-02-18 15:39:26 +01:00
"Excitation of spindet", `Quick, test_exc_spindet;
2019-02-15 13:48:48 +01:00
]
2019-02-15 23:11:37 +01:00