Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add converter function for PySCF's RCISD and CCSD/UCCSD to PennyLane statevector #4433

Merged
merged 69 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
5d4d8ba
add excitation function
soranjh Jul 31, 2023
d75a415
add excited states
soranjh Jul 31, 2023
a33369a
modify var names
soranjh Jul 31, 2023
3d2aa33
modify var names
soranjh Jul 31, 2023
d41071b
add tests
soranjh Aug 1, 2023
0a8c78d
make code compact
soranjh Aug 1, 2023
52d8ed4
make code compact
soranjh Aug 1, 2023
e06c7a5
add ucisd wavefunction constructor
Chiffafox Aug 1, 2023
cebd348
added the converter from wf_dict format to pennylane statevector
Chiffafox Aug 1, 2023
1d6bca9
update cisd_state docstring
Chiffafox Aug 1, 2023
16de4e4
update _ucisd_state docstring
Chiffafox Aug 1, 2023
1d29b1f
update docstring of final converter to statevector
Chiffafox Aug 1, 2023
f76de22
fixed the example output for cisd_state
Chiffafox Aug 1, 2023
4db8778
added test for private _ucisd func based on h2 molecule
Chiffafox Aug 2, 2023
6117158
added cc-pvdz test
Chiffafox Aug 2, 2023
9f26454
added how to generate ref data for test_prive_ucisd
Chiffafox Aug 2, 2023
d7168fd
[skip ci] fixed typos
Chiffafox Aug 2, 2023
414965a
modify test to account for sign change
soranjh Aug 2, 2023
782768c
remove comments and modify docstring
soranjh Aug 2, 2023
fc76e11
Merge branch 'master' into initial_state_ucisd
soranjh Aug 2, 2023
4acf9c8
Add functions to return excited basis states (#4417)
soranjh Aug 2, 2023
9be65fa
correct test
soranjh Aug 2, 2023
a4eceaf
correct import
soranjh Aug 2, 2023
99b0fee
add test for statevector
soranjh Aug 2, 2023
41238e6
add test for cisd
soranjh Aug 2, 2023
7e9e1c1
added the wavefunction constructor for restricted cisd, matched ucisd…
Chiffafox Aug 2, 2023
0b8566b
add error test and fix bug
soranjh Aug 2, 2023
541318a
minor comments for clarification added
Chiffafox Aug 2, 2023
ae363b3
add correct input args to test
soranjh Aug 2, 2023
53f00da
Merge branch 'master' into initial_state_ucisd
soranjh Aug 2, 2023
0ddab7b
fix typo
soranjh Aug 2, 2023
c80f7e5
added tests for rcisd and improved ucisd tests
Chiffafox Aug 2, 2023
84067eb
small fixes to _rcisd func
Chiffafox Aug 2, 2023
0ceffc8
updating tests with symm argument
Chiffafox Aug 2, 2023
5731b69
updated tests to use the symm arg
Chiffafox Aug 2, 2023
eee0410
reformatted with black
Chiffafox Aug 2, 2023
6afd6be
fixed black formatting
Chiffafox Aug 2, 2023
3f17546
added Be atom test for rcisd aa->aa and bb->bb check
Chiffafox Aug 3, 2023
9981f15
black format fix
Chiffafox Aug 3, 2023
8320cec
first version of uccsd converter
Chiffafox Aug 3, 2023
3801147
make code compact
soranjh Aug 3, 2023
c8e6983
rename cisd_state to import_state
soranjh Aug 3, 2023
fafef6a
polished uccsd converter and added test for it
Chiffafox Aug 3, 2023
6079d55
added the rccsd converter
Chiffafox Aug 3, 2023
32cd0b1
added tests for rccsd and ccsd_state
Chiffafox Aug 3, 2023
c05ddae
fix black formatting
Chiffafox Aug 3, 2023
699373d
modify docs
soranjh Aug 3, 2023
8df3675
Merge branch 'master' into initial_state_ucisd
soranjh Aug 3, 2023
90f8489
Merge branch 'master' into initial_state_rcisd
Chiffafox Aug 3, 2023
67dc3c1
resolve conflicts
soranjh Aug 3, 2023
e3e8dae
resolve conflicts in tests
soranjh Aug 3, 2023
3f55198
merge functions
soranjh Aug 3, 2023
9ad777f
add small modifications
soranjh Aug 3, 2023
f2bee88
update with master
soranjh Aug 4, 2023
e135a23
merge master and fix conflict
soranjh Aug 4, 2023
8738750
expand import state test
soranjh Aug 4, 2023
b17773e
remove import pyscf
soranjh Aug 4, 2023
c0dcbd1
update docstring
soranjh Aug 4, 2023
69a2b84
update changelog
soranjh Aug 5, 2023
876f671
modify docstring
soranjh Aug 7, 2023
a7ffcdd
modify docstring
soranjh Aug 7, 2023
8b39362
update changelog
soranjh Aug 7, 2023
55da678
modify docstring
soranjh Aug 7, 2023
ae19005
update changelog
soranjh Aug 7, 2023
9f3d1d4
extend object support
soranjh Aug 7, 2023
c9f7ac3
added symmetry=d2h to examples in rcisd / ucisd converters
Chiffafox Aug 8, 2023
f4d0abc
define test data
soranjh Aug 8, 2023
f4a947e
Merge branch 'master' into initial_state_rcisd
soranjh Aug 8, 2023
fbe062c
Merge branch 'initial_state_rcisd' of https://github.com/PennyLaneAI/…
soranjh Aug 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 31 additions & 25 deletions pennylane/qchem/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,20 +624,26 @@ def _wfdict_to_statevector(wf_dict, norbs):


def _rcisd_state(cisd_solver, tol=1e-15):
r"""
r"""Construct a wavefunction from PySCF's `RCISD` solver object.

Args:
cisd_solver (PySCF UCISD Class instance): the class object representing
the CISD calculation in PySCF. Must have already carried out the
calculation, e.g. by calling .kernel() or .run().
cisd_solver (PySCF UCISD Class instance): the class object representing the CISD
soranjh marked this conversation as resolved.
Show resolved Hide resolved
calculation in PySCF.

Returns:
cisd_solver (PySCF UCISD Class instance): the class object representing
the CISD calculation in PySCF. Must have already carried out the
calculation, e.g. by calling .kernel() or .run().
dict: Dictionary of the form `{(int_a, int_b) :coeff}`, with integers `int_a, int_b`
having binary representation corresponding to the Fock occupation vector in alpha and beta
spin sectors, respectively, and coeff being the CI coefficients of those configurations.

**Example**

>>> from pyscf import gto, scf, ci
>>> mol = gto.M(atom=[['H', (0, 0, 0)], ['H', (0,0,0.71)]], basis='sto6g')
soranjh marked this conversation as resolved.
Show resolved Hide resolved
>>> myhf = scf.RHF(mol).run()
>>> myci = ci.CISD(myhf).run()
>>> wf_cisd = _rcisd_state(myci, tol=1e-1)
>>> print(wf_cisd)
{(1, 1): -0.9942969785398775, (2, 2): 0.10664669927602162}
"""
mol = cisd_solver.mol
cisdvec = cisd_solver.ci
Expand Down Expand Up @@ -715,16 +721,16 @@ def _rccsd_state(ccsd_solver, tol=1e-15):
state and `0.01` contribution from the doubly-excited state will be
`{(1, 1): 0.99, (2, 2): 0.01}`.

In the case of the coupled cluster singles and doubles calculation, in the current version, the exponential
ansatz :math:`\exp(\hat{T}_1 + \hat{T}_2) \ket{\text{HF}}` is expanded to second order, with only
single and double excitation terms collected and kept. In the future this will be amended to collect also
terms from higher order. The expansion gives
In the current version, the exponential ansatz :math:`\exp(\hat{T}_1 + \hat{T}_2) \ket{\text{HF}}`
is expanded to second order, with only single and double excitation terms collected and kept.
In the future this will be amended to collect also terms from higher order. The expansion gives

.. math::
\exp(\hat{T}_1 + \hat{T}_2) \ket{\text{HF}} = \left[ 1 + \hat{T}_1 +
\left( \hat{T}_2 + 0.5 * \hat{T}_1^2 \right) \right] \ket{\text{HF}}
\left( \hat{T}_2 + 0.5 * \hat{T}_1^2 \right) \right] \ket{\text{HF}}

The coefficients in this expansion are the CI coefficients used to build the wavefunction representation.
The coefficients in this expansion are the CI coefficients used to build the wavefunction
representation.

Args:
ccsd_solver (PySCF CCSD Class instance): the class object representing the CCSD calculation in PySCF
Expand All @@ -742,10 +748,10 @@ def _rccsd_state(ccsd_solver, tol=1e-15):
>>> mol = gto.M(atom=[['Li', (0, 0, 0)], ['Li', (0,0,0.71)]], basis='sto6g')
soranjh marked this conversation as resolved.
Show resolved Hide resolved
>>> myhf = scf.RHF(mol).run()
>>> mycc = cc.CCSD(myhf).run()
>>> wf_ccsd = ccsd_state(mycc, tol=1e-1)
>>> wf_ccsd = _rccsd_state(mycc, tol=1e-1)
>>> print(wf_ccsd)
{(7, 7): 0.8886969878256522, (11, 11): -0.30584590248164206,
(19, 19): -0.30584590248164145, (35, 35): -0.14507552651170982}
(19, 19): -0.30584590248164145, (35, 35): -0.14507552651170982}
"""

mol = ccsd_solver.mol
Expand Down Expand Up @@ -775,7 +781,7 @@ def _rccsd_state(ccsd_solver, tol=1e-15):
- 0.5
* np.kron(t1b, t1b).reshape(nelec_b, nvir_b, nelec_b, nvir_b).transpose(0, 2, 1, 3).numpy()
)
# this just aligns the entries with how the excitations are ordered when generated by _excited_configurations()
# align the entries with how the excitations are ordered when generated by _excited_configurations()
t2ab = t2ab - 0.5 * np.kron(t1a, t1b).reshape(nelec_a, nvir_a, nelec_b, nvir_b).numpy()

# numbers representing the Hartree-Fock vector, e.g., bin(ref_a)[::-1] = 1111...10...0
Expand Down Expand Up @@ -852,21 +858,21 @@ def _uccsd_state(ccsd_solver, tol=1e-15):
state and `0.01` contribution from the doubly-excited state will be
`{(1, 1): 0.99, (2, 2): 0.01}`.

In the case of the coupled cluster singles and doubles calculation, in the current version, the exponential
ansatz :math:`\exp(\hat{T}_1 + \hat{T}_2) \ket{\text{HF}}` is expanded to second order, with only
single and double excitation terms collected and kept. In the future this will be amended to collect also
terms from higher order. The expansion gives
In the current version, the exponential ansatz :math:`\exp(\hat{T}_1 + \hat{T}_2) \ket{\text{HF}}`
is expanded to second order, with only single and double excitation terms collected and kept.
In the future this will be amended to collect also terms from higher order. The expansion gives

.. math::
\exp(\hat{T}_1 + \hat{T}_2) \ket{\text{HF}} = \left[ 1 + \hat{T}_1 +
\left( \hat{T}_2 + 0.5 * \hat{T}_1^2 \right) \right] \ket{\text{HF}}

The coefficients in this expansion are the CI coefficients used to build the wavefunction representation.
The coefficients in this expansion are the CI coefficients used to build the wavefunction
representation.

Args:
ccsd_solver (PySCF UCCSD Class instance): the class object representing the UCCSD calculation in PySCF
tol (float): the tolerance to which the wavefunction is being built -- Slater determinants
with coefficients smaller than this are discarded. Default is 1e-15 (all coefficients are included).
with coefficients smaller than this are discarded. Default is 1e-15 (all coefficients are included).

Returns:
dict: Dictionary of the form `{(int_a, int_b) :coeff}`, with integers `int_a, int_b`
Expand All @@ -879,10 +885,10 @@ def _uccsd_state(ccsd_solver, tol=1e-15):
>>> mol = gto.M(atom=[['Li', (0, 0, 0)], ['Li', (0,0,0.71)]], basis='sto6g')
soranjh marked this conversation as resolved.
Show resolved Hide resolved
>>> myhf = scf.UHF(mol).run()
>>> mycc = cc.UCCSD(myhf).run()
>>> wf_ccsd = ccsd_state(mycc, tol=1e-1)
>>> wf_ccsd = _uccsd_state(mycc, tol=1e-1)
>>> print(wf_ccsd)
{(7, 7): 0.8886970081919591, (11, 11): -0.3058459002168582,
(19, 19): -0.30584590021685887, (35, 35): -0.14507552387854625}
(19, 19): -0.30584590021685887, (35, 35): -0.14507552387854625}
"""

mol = ccsd_solver.mol
Expand All @@ -907,7 +913,7 @@ def _uccsd_state(ccsd_solver, tol=1e-15):
- 0.5
* np.kron(t1b, t1b).reshape(nelec_b, nvir_b, nelec_b, nvir_b).transpose(0, 2, 1, 3).numpy()
)
# this just aligns the entries with how the excitations are ordered when generated by _excited_configurations()
# align the entries with how the excitations are ordered when generated by _excited_configurations()
t2ab = (
t2ab.transpose(0, 2, 1, 3)
- 0.5 * np.kron(t1a, t1b).reshape(nelec_a, nvir_a, nelec_b, nvir_b).numpy()
Expand Down
59 changes: 59 additions & 0 deletions tests/qchem/of_tests/test_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,65 @@ def test_import_state_error():
_ = qchem.convert.import_state(myci, method)


@pytest.mark.parametrize(
("molecule", "basis", "symm", "tol", "wf_ref"),
[
(
[["H", (0, 0, 0)], ["H", (0, 0, 0.71)]],
"sto6g",
"d2h",
1e-1,
{(1, 1): -0.9942969785398778, (2, 2): 0.10664669927602179},
),
(
[["H", (0, 0, 0)], ["H", (0, 0, 0.71)]],
"cc-pvdz",
"d2h",
4e-2,
{
(1, 1): 0.9919704795977625,
(2, 2): -0.048530356564386895,
(2, 8): 0.044523330850078625,
(4, 4): -0.050035945684911876,
(8, 2): 0.04452333085007864,
(8, 8): -0.052262303220437775,
(16, 16): -0.040475973747662694,
(32, 32): -0.040475973747662694,
},
),
(
[["Be", (0, 0, 0)]],
"sto6g",
"d2h",
1e-3,
{
(3, 3): 0.9446343496981953,
(6, 5): 0.003359774446779245,
(10, 9): 0.003359774446779244,
(18, 17): 0.003359774446779245,
(5, 6): 0.003359774446779244,
(5, 5): -0.18938190575578503,
(9, 10): 0.003359774446779243,
(9, 9): -0.18938190575578523,
(17, 18): 0.003359774446779244,
(17, 17): -0.18938190575578503,
},
),
],
soranjh marked this conversation as resolved.
Show resolved Hide resolved
)
def test_rcisd_state(molecule, basis, symm, tol, wf_ref):
r"""Test that _rcisd_state returns the correct wavefunction."""

mol = pyscf.gto.M(atom=molecule, basis=basis, symmetry=symm)
myhf = pyscf.scf.RHF(mol).run()
myci = pyscf.ci.CISD(myhf).run()

wf_cisd = qchem.convert._rcisd_state(myci, tol=tol)

assert wf_cisd.keys() == wf_ref.keys()
assert np.allclose(np.array(list(wf_cisd.values())), np.array(list(wf_ref.values())))
soranjh marked this conversation as resolved.
Show resolved Hide resolved


@pytest.mark.parametrize(
("molecule", "basis", "symm", "tol", "wf_ref"),
[
Expand Down
Loading