Skip to content
Merged
5 changes: 3 additions & 2 deletions fanpy/wfn/cc/pccd_ap1rog.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,13 @@ def __init__(
annihilation to the creation operators.

"""
# indices are used for assign_exops, without any modification
# we can pass it here to BaseCC as assign_exops gets overwritten by PCCD and its child classes
super().__init__(
nelec, nspin, memory=memory, params=params, exop_combinations=exop_combinations, refresh_exops=refresh_exops
nelec, nspin, memory=memory, params=params, exop_combinations=exop_combinations, indices=indices, refresh_exops=refresh_exops
)
self.assign_s_type(s_type=s_type)
self.assign_ranks(ranks=ranks)
self.assign_exops(indices=indices)
self.assign_refwfn(refwfn=refwfn)

# mapping from indices to exops
Expand Down
57 changes: 57 additions & 0 deletions tests/test_wfn_cc_ap1rog_generalized.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
""" Test for AP1roGSD """

import numpy as np
import pytest
from fanpy.tools.sd_list import sd_list
from fanpy.tools.slater import excite, ground

from fanpy.wfn.cc.ap1rog_generalized import AP1roGSDGeneralized

def test_assign_ranks():
# only default rank allowed
with pytest.raises(TypeError):
AP1roGSDGeneralized(2, 4, ranks=2)

with pytest.raises(TypeError):
AP1roGSDGeneralized(2, 4, ranks=[1, 2, 3])

# AP1roGSD only has single and double excitations
wfn = AP1roGSDGeneralized(2, 4)
assert wfn.ranks == [1, 2]

def test_assign_expos():
# only default exops allowed
with pytest.raises(TypeError):
AP1roGSDGeneralized(2, 4, indices=[[0, 2]])
# build double excitations for PCCD:
n_elec = 6
n_spin = 14
wfn = AP1roGSDGeneralized(n_elec, n_spin)

# build single and double excitations manually
doubles = sd_list(n_elec, n_spin, exc_orders=[2], spin=0, seniority=0)
singles = sd_list(n_elec, n_spin, exc_orders=[1])
exc_sds = []
# sd list adds ground state as well because it satisfies the spin and sen restrictions
# ground is added as the first element, we jump over it here
exc_sds.extend(doubles[1:])
exc_sds.extend(singles[1:])

# generate excited sds from exc ops in wfn
wfn_exc_sds = []
ground_state = ground(n_elec, n_spin)
for exc_orders in wfn.exops.keys():
sd = excite(ground_state, *exc_orders)
wfn_exc_sds.append(sd)

# convert arrays to numpy so that comparison easier
exc_sds_np = np.asarray(exc_sds, dtype=int)
exc_sds_np = np.sort(exc_sds_np)
# sort arrays
wfn_exc_sds_np = np.asarray(wfn_exc_sds, dtype=int)
wfn_exc_sds_np = np.sort(wfn_exc_sds_np)

# compare sds
np.testing.assert_array_equal(exc_sds_np, wfn_exc_sds_np)


53 changes: 53 additions & 0 deletions tests/test_wfn_cc_ap1rog_spin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""tests for fanpy.wfn.cc.ap1rog_spin"""

import pytest
import numpy as np

from fanpy.wfn.cc.ap1rog_spin import AP1roGSDSpin
from fanpy.tools.slater import excite, ground
from fanpy.tools.sd_list import sd_list

def test_assign_ranks():
# only default rank allowed
with pytest.raises(TypeError):
AP1roGSDSpin(2, 4, ranks=2)

with pytest.raises(TypeError):
AP1roGSDSpin(2, 4, ranks=[1, 2, 3])

# AP1roGSD only has single and double excitations
wfn = AP1roGSDSpin(2, 4)
assert wfn.ranks == [1, 2]

def test_assign_expos():
# only default exops allowed
with pytest.raises(TypeError):
AP1roGSDSpin(2, 4, indices=[[0, 2]])
# build double excitations for PCCD:
n_elec = 6
n_spin = 14
wfn = AP1roGSDSpin(n_elec, n_spin)

# build single and double excitations manually
doubles = sd_list(n_elec, n_spin, exc_orders=[2], spin=0, seniority=0)
singles = sd_list(n_elec, n_spin, exc_orders=[1], spin=0)
exc_sds = []
exc_sds.extend(doubles[1:])
exc_sds.extend(singles[1:])

# generate excited sds from exc ops in wfn
wfn_exc_sds = []
ground_state = ground(n_elec, n_spin)
for exc_orders in wfn.exops.keys(): # keys are excitation inds
sd = excite(ground_state, *exc_orders)
wfn_exc_sds.append(sd)

# convert arrays to numpy so that comparison easier
exc_sds_np = np.asarray(exc_sds, dtype=int)
exc_sds_np = np.sort(exc_sds_np)
# sort arrays
wfn_exc_sds_np = np.asarray(wfn_exc_sds, dtype=int)
wfn_exc_sds_np = np.sort(wfn_exc_sds_np)

# compare sds
np.testing.assert_array_equal(exc_sds_np, wfn_exc_sds_np)
52 changes: 51 additions & 1 deletion tests/test_wfn_cc_apset1gro_d.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Test fanpy.wavefunction.cc.apset1rog_d."""
import pytest
from fanpy.wfn.cc.apset1rog_d import APset1roGD
from fanpy.tools.slater import ground, vir_indices


class TempAPset1roGD(APset1roGD):
Expand All @@ -10,7 +11,7 @@ def __init__(self):
self.exop_combinations = {}


def test_assign_exops():
def test_assign_exops_default_inds():
"""Test APset1roGD.assign_exops."""
test = TempAPset1roGD()
test.assign_nelec(4)
Expand All @@ -21,3 +22,52 @@ def test_assign_exops():
test.assign_exops()
assert test.exops == {(0, 4, 2, 6): 0, (0, 4, 2, 7): 1, (0, 4, 3, 6): 2, (0, 4, 3, 7): 3,
(1, 5, 2, 6): 4, (1, 5, 2, 7): 5, (1, 5, 3, 6): 6, (1, 5, 3, 7): 7}

def test_assign_exops_non_default_inds():
test = TempAPset1roGD()
nelec = 6
nspin = 14
test.assign_nelec(nelec)
test.assign_nspin(nspin)
test.assign_refwfn()
ground_state = ground(nelec, nspin)
vir_idx = vir_indices(ground_state, nspin).tolist()
alpha_idx = vir_idx[:len(vir_idx)//2]
beta_idx = vir_idx[len(vir_idx)//2:]
# trigger non-default case, but with same alpha beta subsets
# as for the default case. This allows easier testing.
test.assign_exops([alpha_idx, beta_idx])

test_default = TempAPset1roGD()
test_default.assign_nelec(nelec)
test_default.assign_nspin(nspin)
test_default.assign_refwfn()
test_default.assign_exops()

assert test_default.exops == test.exops

def test_assign_exops_errors():
test = TempAPset1roGD()
test.assign_nelec(4)
test.assign_nspin(8)
test.assign_refwfn()

# not having two sets:
with pytest.raises(TypeError, match="`indices` must have exactly 2 elements"):
test.assign_exops([[ 2, 3 ], [6], [7, 5]])

# non int inds:
with pytest.raises(TypeError, match="The elements of `indices` must be lists of non-negative ints"):
test.assign_exops([[ 2, 3 ], [ 6, 7.5]])

# negative inds:
with pytest.raises(ValueError, match="All `indices` must be lists of non-negative ints"):
test.assign_exops([[ -2, 3 ], [ 6, 7]])

# set has occ orbitals
with pytest.raises(ValueError, match="`indices` cannot correspond to occupied spin-orbitals"):
test.assign_exops([[0, 1, 4, 5], [2, 3, 6, 7]])

# not a disjoint set
with pytest.raises(ValueError, match="The sets of creation operators must be disjoint"):
test.assign_exops([[ 3, 6], [ 6, 7]])
53 changes: 53 additions & 0 deletions tests/test_wfn_cc_apset1gro_sd.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,56 @@ def test_generate_possible_exops():
test.exop_combinations[(0, 1, 4, 2, 3, 6)][2][1],
[test.get_ind((1, 3)), test.get_ind((0, 4, 2, 6)), sign if sign == 1 else 0],
)

def test_assign_exops_errors():
test = TempAPset1GroSD()
test.assign_nelec(4)
test.assign_nspin(8)
test.assign_refwfn()
# wrong type
with pytest.raises(TypeError, match="The elements of `indices` must be lists of non-negative ints" ):
test.assign_exops(["not a list", "not a list"])

# not having two sets:
with pytest.raises(TypeError, match="`indices` must have exactly 2 elements"):
test.assign_exops([[ 2, 3 ], [6], [7, 5]])

# non int inds:
with pytest.raises(TypeError, match="The elements of `indices` must be lists of non-negative ints"):
test.assign_exops([[ 2, 3 ], [ 6, 7.5]])

# negative inds:
with pytest.raises(ValueError, match="All `indices` must be lists of non-negative ints"):
test.assign_exops([[ -2, 3 ], [ 6, 7]])

# set has occ orbitals
with pytest.raises(ValueError, match="`indices` cannot correspond to occupied spin-orbitals"):
test.assign_exops([[0, 1, 4, 5], [2, 3, 6, 7]])

# not a disjoint set
with pytest.raises(ValueError, match="The sets of annihilation operators must be disjoint"):
test.assign_exops([[ 3, 6], [ 6, 7]])

def test_assign_exops_non_default_inds():
test = TempAPset1GroSD()
nelec = 6
nspin = 14
test.assign_nelec(nelec)
test.assign_nspin(nspin)
test.assign_refwfn()
ground_state = slater.ground(nelec, nspin)
vir_idx = slater.vir_indices(ground_state, nspin).tolist()
alpha_idx = vir_idx[:len(vir_idx)//2]
beta_idx = vir_idx[len(vir_idx)//2:]
# trigger non-default case, but with same alpha beta subsets
# as for the default case. This allows easier testing.
# print("DEBUG >>> test.exop_combs: ", test.exops)
test.assign_exops([alpha_idx, beta_idx])

test_default = TempAPset1GroSD()
test_default.assign_nelec(nelec)
test_default.assign_nspin(nspin)
test_default.assign_refwfn()
test_default.assign_exops()

assert test_default.exops == test.exops
Loading
Loading