Skip to content

Commit

Permalink
fix(test): make unit tests deterministic (deepmodeling#3856)
Browse files Browse the repository at this point in the history
Fix deepmodeling#3847.
This PR makes all unit tests deterministic. We have found
non-deterministic unit tests have more disadvantages than advantages.
Read more:
https://softwareengineering.stackexchange.com/questions/221632/testing-deterministic-or-non-deterministic

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Tests**
- Introduced a global seed for consistent random number generation
across various test files.
- Updated the initialization of random tensors to include a generator
parameter seeded with the global seed.
- Adjusted epsilon values and setup methods in specific test cases for
accuracy and consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Jinzhe Zeng <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and Mathieu Taillefumier committed Sep 18, 2024
1 parent 80d73d2 commit 7ad7cfb
Show file tree
Hide file tree
Showing 56 changed files with 397 additions and 138 deletions.
5 changes: 4 additions & 1 deletion source/tests/common/dpmodel/test_descriptor_dpa1.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
DescrptDPA1,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -19,7 +22,7 @@ def setUp(self):
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 4))
dstd = rng.normal(size=(self.nt, nnei, 4))
Expand Down
5 changes: 4 additions & 1 deletion source/tests/common/dpmodel/test_descriptor_dpa2.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
RepinitArgs,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -23,7 +26,7 @@ def setUp(self):
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 4))
dstd = rng.normal(size=(self.nt, nnei, 4))
Expand Down
7 changes: 5 additions & 2 deletions source/tests/common/dpmodel/test_descriptor_hybrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
DescrptSeR,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -29,7 +32,7 @@ def setUp(self):
def test_get_parameters(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 4))
dstd = rng.normal(size=(self.nt, nnei, 4))
Expand Down Expand Up @@ -72,7 +75,7 @@ def test_get_parameters(
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 4))
dstd = rng.normal(size=(self.nt, nnei, 4))
Expand Down
5 changes: 4 additions & 1 deletion source/tests/common/dpmodel/test_descriptor_se_e2_a.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
DescrptSeA,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -19,7 +22,7 @@ def setUp(self):
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 4))
dstd = rng.normal(size=(self.nt, nnei, 4))
Expand Down
5 changes: 4 additions & 1 deletion source/tests/common/dpmodel/test_descriptor_se_r.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
DescrptSeR,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -19,7 +22,7 @@ def setUp(self):
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 1))
dstd = rng.normal(size=(self.nt, nnei, 1))
Expand Down
5 changes: 4 additions & 1 deletion source/tests/common/dpmodel/test_descriptor_se_t.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
DescrptSeT,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -19,7 +22,7 @@ def setUp(self):
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 4))
dstd = rng.normal(size=(self.nt, nnei, 4))
Expand Down
7 changes: 5 additions & 2 deletions source/tests/common/dpmodel/test_dp_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
EnergyModel,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
TestCaseSingleFrameWithoutNlist,
Expand Down Expand Up @@ -50,7 +53,7 @@ def test_self_consistency(
np.testing.assert_allclose(ret0["energy_redu"], ret1["energy_redu"])

def test_prec_consistency(self):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
ds = DescrptSeA(
self.rcut,
Expand Down Expand Up @@ -102,7 +105,7 @@ def setUp(self):
TestCaseSingleFrameWithoutNlist.setUp(self)

def test_prec_consistency(self):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc = self.atype.shape
ds = DescrptSeA(
self.rcut,
Expand Down
5 changes: 4 additions & 1 deletion source/tests/common/dpmodel/test_env_mat.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
EnvMat,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -19,7 +22,7 @@ def setUp(self):
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 4))
dstd = rng.normal(size=(self.nt, nnei, 4))
Expand Down
9 changes: 6 additions & 3 deletions source/tests/common/dpmodel/test_fitting_invar_fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
InvarFitting,
)

from ...seed import (
GLOBAL_SEED,
)
from .case_single_frame_with_nlist import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -23,7 +26,7 @@ def setUp(self):
def test_self_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
ds = DescrptSeA(self.rcut, self.rcut_smth, self.sel)
dd = ds.call(self.coord_ext, self.atype_ext, self.nlist)
Expand Down Expand Up @@ -102,7 +105,7 @@ def test_mask(self):
def test_self_exception(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
nf, nloc, nnei = self.nlist.shape
ds = DescrptSeA(self.rcut, self.rcut_smth, self.sel)
dd = ds.call(self.coord_ext, self.atype_ext, self.nlist)
Expand Down Expand Up @@ -160,7 +163,7 @@ def test_get_set(self):
3,
1,
)
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
foo = rng.normal([3, 4])
for ii in [
"bias_atom_e",
Expand Down
9 changes: 7 additions & 2 deletions source/tests/common/dpmodel/test_neighbor_stat.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@
neighbor_stat,
)

from ...seed import (
GLOBAL_SEED,
)


def gen_sys(nframes):
rng = np.random.default_rng(GLOBAL_SEED)
natoms = 1000
data = {}
X, Y, Z = np.mgrid[0:2:3j, 0:2:3j, 0:2:3j]
positions = np.vstack([X.ravel(), Y.ravel(), Z.ravel()]).T # + 0.1
data["coords"] = np.repeat(positions[np.newaxis, :, :], nframes, axis=0)
data["forces"] = np.random.default_rng().random([nframes, natoms, 3])
data["forces"] = rng.random([nframes, natoms, 3])
data["cells"] = np.array([3.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 3.0]).reshape(
1, 3, 3
)
data["energies"] = np.random.default_rng().random([nframes, 1])
data["energies"] = rng.random([nframes, 1])
data["atom_names"] = ["TYPE"]
data["atom_numbs"] = [27]
data["atom_types"] = np.repeat(0, 27)
Expand Down
6 changes: 5 additions & 1 deletion source/tests/common/dpmodel/test_region.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
to_face_distance,
)

from ...seed import (
GLOBAL_SEED,
)


class TestRegion(unittest.TestCase):
def setUp(self):
Expand All @@ -19,7 +23,7 @@ def setUp(self):
self.prec = 1e-8

def test_inter_to_phys(self):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
inter = rng.normal(size=[4, 5, 3, 3])
phys = inter2phys(inter, self.cell)
for ii in range(4):
Expand Down
6 changes: 5 additions & 1 deletion source/tests/common/dpmodel/test_update_sel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
UpdateSel,
)

from ...seed import (
GLOBAL_SEED,
)


def update_sel(jdata):
type_map = jdata["model"].get("type_map")
Expand All @@ -23,7 +27,7 @@ def update_sel(jdata):
class TestTrain(unittest.TestCase):
def setUp(self) -> None:
self.update_sel = UpdateSel()
self.mock_min_nbor_dist = random.random()
self.mock_min_nbor_dist = random.Random(GLOBAL_SEED).random()
return super().setUp()

@patch("deepmd.dpmodel.utils.update_sel.UpdateSel.get_nbor_stat")
Expand Down
7 changes: 6 additions & 1 deletion source/tests/consistent/test_activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
)
from deepmd.dpmodel.utils.network import get_activation_fn as get_activation_fn_dp

from ..seed import (
GLOBAL_SEED,
)
from .common import (
INSTALLED_PT,
INSTALLED_TF,
Expand All @@ -33,7 +36,9 @@
class TestActivationFunctionConsistent(unittest.TestCase):
def setUp(self):
(self.activation,) = self.param
self.random_input = np.random.default_rng().normal(scale=10, size=(10, 10))
self.random_input = np.random.default_rng(GLOBAL_SEED).normal(
scale=10, size=(10, 10)
)
self.ref = get_activation_fn_dp(self.activation)(self.random_input)

@unittest.skipUnless(INSTALLED_TF, "TensorFlow is not installed")
Expand Down
16 changes: 11 additions & 5 deletions source/tests/pt/model/test_autodiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
to_numpy_array,
)

from ...seed import (
GLOBAL_SEED,
)

dtype = torch.float64

from .test_permutation import (
Expand Down Expand Up @@ -58,11 +62,12 @@ def test(
places = 5
delta = 1e-5
natoms = 5
cell = torch.rand([3, 3], dtype=dtype, device="cpu")
generator = torch.Generator(device="cpu").manual_seed(GLOBAL_SEED)
cell = torch.rand([3, 3], dtype=dtype, device="cpu", generator=generator)
cell = (cell + cell.T) + 5.0 * torch.eye(3, device="cpu")
coord = torch.rand([natoms, 3], dtype=dtype, device="cpu")
coord = torch.rand([natoms, 3], dtype=dtype, device="cpu", generator=generator)
coord = torch.matmul(coord, cell)
spin = torch.rand([natoms, 3], dtype=dtype, device="cpu")
spin = torch.rand([natoms, 3], dtype=dtype, device="cpu", generator=generator)
atype = torch.IntTensor([0, 0, 0, 1, 1])
# assumes input to be numpy tensor
coord = coord.numpy()
Expand Down Expand Up @@ -129,9 +134,10 @@ def test(
places = 5
delta = 1e-4
natoms = 5
cell = torch.rand([3, 3], dtype=dtype, device="cpu")
generator = torch.Generator(device="cpu").manual_seed(GLOBAL_SEED)
cell = torch.rand([3, 3], dtype=dtype, device="cpu", generator=generator)
cell = (cell) + 5.0 * torch.eye(3, device="cpu")
coord = torch.rand([natoms, 3], dtype=dtype, device="cpu")
coord = torch.rand([natoms, 3], dtype=dtype, device="cpu", generator=generator)
coord = torch.matmul(coord, cell)
atype = torch.IntTensor([0, 0, 0, 1, 1])
# assumes input to be numpy tensor
Expand Down
1 change: 0 additions & 1 deletion source/tests/pt/model/test_descriptor_hybrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ def test_jit(
def test_get_parameters(
self,
):
rng = np.random.default_rng()
nf, nloc, nnei = self.nlist.shape
ddsub0 = DescrptSeA(
rcut=self.rcut,
Expand Down
9 changes: 6 additions & 3 deletions source/tests/pt/model/test_descriptor_se_r.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
EnvMatStatSe,
)

from ...seed import (
GLOBAL_SEED,
)
from .test_env_mat import (
TestCaseSingleFrameWithNlist,
)
Expand All @@ -37,7 +40,7 @@ def setUp(self):
def test_consistency(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
_, _, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 1))
dstd = rng.normal(size=(self.nt, nnei, 1))
Expand Down Expand Up @@ -107,7 +110,7 @@ def test_consistency(
)

def test_load_stat(self):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
_, _, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 1))
dstd = rng.normal(size=(self.nt, nnei, 1))
Expand Down Expand Up @@ -157,7 +160,7 @@ def test_load_stat(self):
def test_jit(
self,
):
rng = np.random.default_rng()
rng = np.random.default_rng(GLOBAL_SEED)
_, _, nnei = self.nlist.shape
davg = rng.normal(size=(self.nt, nnei, 1))
dstd = rng.normal(size=(self.nt, nnei, 1))
Expand Down
Loading

0 comments on commit 7ad7cfb

Please sign in to comment.