@@ -32,18 +32,23 @@ def uccsd_operator(single_amplitudes, double_amplitudes, anti_hermitian=True):
3232 """Create a fermionic operator that is the generator of uccsd.
3333
3434 This a the most straight-forward method to generate UCCSD operators,
35- however it is slightly inefficient. In particular, it parameterizes
36- all possible exictations , so it represents a generalized unitary coupled
35+ however it is slightly inefficient. In particular, it parameterizes
36+ all possible excitations , so it represents a generalized unitary coupled
3737 cluster ansatz, but also does not explicitly enforce the uniqueness
38- in paramterization , so it is redundant. For example there will be a linear
38+ in parametrization , so it is redundant. For example there will be a linear
3939 dependency in the ansatz of single_amplitudes[i,j] and
4040 single_amplitudes[j,i].
4141
4242 Args:
43- single_amplitudes(ndarray): [NxN] array storing single excitation
44- amplitudes corresponding to t[i,j] * (a_i^\dagger a_j + H.C.)
45- double_amplitudes(ndarray): [NxNxNxN] array storing double excitation
43+ single_amplitudes(list or ndarray): list of lists with each sublist
44+ storing a list of indices followed by single excitation amplitudes
45+ i.e. [[[i,j],t_ij], ...] OR [NxN] array storing single excitation
4646 amplitudes corresponding to
47+ t[i,j] * (a_i^\dagger a_j + H.C.)
48+ double_amplitudes(list or ndarray): list of lists with each sublist
49+ storing a list of indices followed by double excitation amplitudes
50+ i.e. [[[i,j,k,l],t_ijkl], ...] OR [NxNxNxN] array storing double
51+ excitation amplitudes corresponding to
4752 t[i,j,k,l] * (a_i^\dagger a_j a_k^\dagger a_l + H.C.)
4853 anti_hermitian(Bool): Flag to generate only normal CCSD operator
4954 rather than unitary variant, primarily for testing
@@ -52,34 +57,63 @@ def uccsd_operator(single_amplitudes, double_amplitudes, anti_hermitian=True):
5257 uccsd_generator(FermionOperator): Anti-hermitian fermion operator that
5358 is the generator for the uccsd wavefunction.
5459 """
55- n_orbitals = single_amplitudes .shape [0 ]
56- assert (n_orbitals == double_amplitudes .shape [0 ])
60+
5761 uccsd_generator = FermionOperator ()
5862
63+ # Re-format inputs (ndarrays to lists) if necessary
64+ if (isinstance (single_amplitudes , numpy .ndarray ) or
65+ isinstance (double_amplitudes , numpy .ndarray )):
66+ single_amplitudes , double_amplitudes = convert_amplitude_format (
67+ single_amplitudes ,
68+ double_amplitudes )
69+
5970 # Add single excitations
60- for i , j in itertools .product (range (n_orbitals ), repeat = 2 ):
61- if single_amplitudes [i , j ] == 0. :
62- continue
63- uccsd_generator += FermionOperator (((i , 1 ), (j , 0 )),
64- single_amplitudes [i , j ])
71+ for (i , j ), t_ij in single_amplitudes :
72+ i , j = int (i ), int (j )
73+ uccsd_generator += FermionOperator (((i , 1 ), (j , 0 )), t_ij )
6574 if anti_hermitian :
66- uccsd_generator += FermionOperator (((j , 1 ), (i , 0 )),
67- - single_amplitudes [i , j ])
75+ uccsd_generator += FermionOperator (((j , 1 ), (i , 0 )), - t_ij )
6876
69- # Add double excitations
70- for i , j , k , l in itertools .product (range (n_orbitals ), repeat = 4 ):
71- if double_amplitudes [i , j , k , l ] == 0. :
72- continue
77+ # Add double excitations
78+ for (i , j , k , l ), t_ijkl in double_amplitudes :
79+ i , j , k , l = int (i ), int (j ), int (k ), int (l )
7380 uccsd_generator += FermionOperator (
74- ((i , 1 ), (j , 0 ), (k , 1 ), (l , 0 )),
75- double_amplitudes [i , j , k , l ])
81+ ((i , 1 ), (j , 0 ), (k , 1 ), (l , 0 )), t_ijkl )
7682 if anti_hermitian :
7783 uccsd_generator += FermionOperator (
78- ((l , 1 ), (k , 0 ), (j , 1 ), (i , 0 )),
79- - double_amplitudes [i , j , k , l ])
84+ ((l , 1 ), (k , 0 ), (j , 1 ), (i , 0 )), - t_ijkl )
8085 return uccsd_generator
8186
8287
88+ def convert_amplitude_format (single_amplitudes , double_amplitudes ):
89+ """Re-format single_amplitudes and double_amplitudes from ndarrays to lists.
90+
91+ Args:
92+ single_amplitudes(ndarray): [NxN] array storing single excitation
93+ amplitudes corresponding to t[i,j] * (a_i^\dagger a_j + H.C.)
94+ double_amplitudes(ndarray): [NxNxNxN] array storing double excitation
95+ amplitudes corresponding to
96+ t[i,j,k,l] * (a_i^\dagger a_j a_k^\dagger a_l + H.C.)
97+
98+ Returns:
99+ single_amplitudes_list(list): list of lists with each sublist storing
100+ a list of indices followed by single excitation amplitudes
101+ i.e. [[[i,j],t_ij], ...]
102+ double_amplitudes_list(list): list of lists with each sublist storing
103+ a list of indices followed by double excitation amplitudes
104+ i.e. [[[i,j,k,l],t_ijkl], ...]
105+ """
106+ single_amplitudes_list , double_amplitudes_list = [], []
107+
108+ for i , j in zip (* single_amplitudes .nonzero ()):
109+ single_amplitudes_list .append ([[i , j ], single_amplitudes [i , j ]])
110+
111+ for i , j , k , l in zip (* double_amplitudes .nonzero ()):
112+ double_amplitudes_list .append ([[i , j , k , l ],
113+ double_amplitudes [i , j , k , l ]])
114+ return single_amplitudes_list , double_amplitudes_list
115+
116+
83117def uccsd_singlet_paramsize (n_qubits , n_electrons ):
84118 """Determine number of independent amplitudes for singlet UCCSD
85119
0 commit comments