From 60c8aa70d4e5d64157dde1e25e5de91e28e17dc6 Mon Sep 17 00:00:00 2001 From: "Kevin J. Sung" Date: Fri, 22 Nov 2024 10:19:01 -0500 Subject: [PATCH 1/3] factor orbital rotation from t1 amplitudes function --- python/ffsim/variational/ucj_spin_balanced.py | 7 ++----- .../ffsim/variational/ucj_spin_unbalanced.py | 18 +++--------------- python/ffsim/variational/ucj_spinless.py | 7 ++----- python/ffsim/variational/util.py | 17 +++++++++++++++++ 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/python/ffsim/variational/ucj_spin_balanced.py b/python/ffsim/variational/ucj_spin_balanced.py index 69d2807c4..11db14097 100644 --- a/python/ffsim/variational/ucj_spin_balanced.py +++ b/python/ffsim/variational/ucj_spin_balanced.py @@ -17,11 +17,11 @@ from typing import cast import numpy as np -import scipy.linalg from ffsim import gates, linalg from ffsim.variational.util import ( orbital_rotation_from_parameters, + orbital_rotation_from_t1_amplitudes, orbital_rotation_to_parameters, validate_interaction_pairs, ) @@ -451,10 +451,7 @@ def from_t_amplitudes( final_orbital_rotation = None if t1 is not None: - final_orbital_rotation_generator = np.zeros((norb, norb), dtype=complex) - final_orbital_rotation_generator[:nocc, nocc:] = t1 - final_orbital_rotation_generator[nocc:, :nocc] = -t1.T - final_orbital_rotation = scipy.linalg.expm(final_orbital_rotation_generator) + final_orbital_rotation = orbital_rotation_from_t1_amplitudes(t1) # Zero out diagonal coulomb matrix entries if requested if pairs_aa is not None: diff --git a/python/ffsim/variational/ucj_spin_unbalanced.py b/python/ffsim/variational/ucj_spin_unbalanced.py index 2279e5c68..51609206f 100644 --- a/python/ffsim/variational/ucj_spin_unbalanced.py +++ b/python/ffsim/variational/ucj_spin_unbalanced.py @@ -17,11 +17,11 @@ from typing import cast import numpy as np -import scipy.linalg from ffsim import gates, linalg from ffsim.variational.util import ( orbital_rotation_from_parameters, + orbital_rotation_from_t1_amplitudes, orbital_rotation_to_parameters, validate_interaction_pairs, ) @@ -579,20 +579,8 @@ def from_t_amplitudes( final_orbital_rotation = None if t1 is not None: t1a, t1b = t1 - - final_orbital_rotation_generator_a = np.zeros((norb, norb), dtype=complex) - final_orbital_rotation_generator_a[:nocc_a, nocc_a:] = t1a - final_orbital_rotation_generator_a[nocc_a:, :nocc_a] = -t1a.T - final_orbital_rotation_a = scipy.linalg.expm( - final_orbital_rotation_generator_a - ) - - final_orbital_rotation_generator_b = np.zeros((norb, norb), dtype=complex) - final_orbital_rotation_generator_b[:nocc_b, nocc_b:] = t1b - final_orbital_rotation_generator_b[nocc_b:, :nocc_b] = -t1b.T - final_orbital_rotation_b = scipy.linalg.expm( - final_orbital_rotation_generator_b - ) + final_orbital_rotation_a = orbital_rotation_from_t1_amplitudes(t1a) + final_orbital_rotation_b = orbital_rotation_from_t1_amplitudes(t1b) final_orbital_rotation = np.stack( [final_orbital_rotation_a, final_orbital_rotation_b] ) diff --git a/python/ffsim/variational/ucj_spinless.py b/python/ffsim/variational/ucj_spinless.py index e274348a3..ea1a23fd0 100644 --- a/python/ffsim/variational/ucj_spinless.py +++ b/python/ffsim/variational/ucj_spinless.py @@ -17,11 +17,11 @@ from typing import cast import numpy as np -import scipy.linalg from ffsim import gates, linalg from ffsim.variational.util import ( orbital_rotation_from_parameters, + orbital_rotation_from_t1_amplitudes, orbital_rotation_to_parameters, validate_interaction_pairs, ) @@ -385,10 +385,7 @@ def from_t_amplitudes( final_orbital_rotation = None if t1 is not None: - final_orbital_rotation_generator = np.zeros((norb, norb), dtype=complex) - final_orbital_rotation_generator[:nocc, nocc:] = t1 - final_orbital_rotation_generator[nocc:, :nocc] = -t1.T - final_orbital_rotation = scipy.linalg.expm(final_orbital_rotation_generator) + final_orbital_rotation = orbital_rotation_from_t1_amplitudes(t1) # Zero out diagonal coulomb matrix entries if requested if interaction_pairs is not None: diff --git a/python/ffsim/variational/util.py b/python/ffsim/variational/util.py index 7f4ff27ca..fd53ea711 100644 --- a/python/ffsim/variational/util.py +++ b/python/ffsim/variational/util.py @@ -107,3 +107,20 @@ def orbital_rotation_from_parameters( generator[rows, cols] += vals generator[cols, rows] -= vals return scipy.linalg.expm(generator) + + +def orbital_rotation_from_t1_amplitudes(t1: np.ndarray) -> np.ndarray: + """Construct an orbital rotation from t1 amplitudes. + + Args: + t1: The t1 amplitudes. + + Returns: + The orbital rotation. + """ + nocc, nvrt = t1.shape + norb = nocc + nvrt + generator = np.zeros((norb, norb), dtype=complex) + generator[:nocc, nocc:] = t1 + generator[nocc:, :nocc] = -t1.T + return scipy.linalg.expm(generator) From db329329881324afbc94ac47c3146c5b0941d6f8 Mon Sep 17 00:00:00 2001 From: "Kevin J. Sung" Date: Fri, 22 Nov 2024 10:53:24 -0500 Subject: [PATCH 2/3] preserve type --- python/ffsim/variational/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ffsim/variational/util.py b/python/ffsim/variational/util.py index fd53ea711..ce34679e4 100644 --- a/python/ffsim/variational/util.py +++ b/python/ffsim/variational/util.py @@ -120,7 +120,7 @@ def orbital_rotation_from_t1_amplitudes(t1: np.ndarray) -> np.ndarray: """ nocc, nvrt = t1.shape norb = nocc + nvrt - generator = np.zeros((norb, norb), dtype=complex) + generator = np.zeros((norb, norb), dtype=t1.dtype) generator[:nocc, nocc:] = t1 generator[nocc:, :nocc] = -t1.T return scipy.linalg.expm(generator) From 4d550aedde72a5bccd393c3b8940076c0c802e33 Mon Sep 17 00:00:00 2001 From: "Kevin J. Sung" Date: Fri, 22 Nov 2024 12:30:58 -0500 Subject: [PATCH 3/3] conj --- python/ffsim/variational/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/ffsim/variational/util.py b/python/ffsim/variational/util.py index ce34679e4..53aada015 100644 --- a/python/ffsim/variational/util.py +++ b/python/ffsim/variational/util.py @@ -112,6 +112,8 @@ def orbital_rotation_from_parameters( def orbital_rotation_from_t1_amplitudes(t1: np.ndarray) -> np.ndarray: """Construct an orbital rotation from t1 amplitudes. + The orbital rotation is constructed as exp(t1 - t1†). + Args: t1: The t1 amplitudes. @@ -122,5 +124,5 @@ def orbital_rotation_from_t1_amplitudes(t1: np.ndarray) -> np.ndarray: norb = nocc + nvrt generator = np.zeros((norb, norb), dtype=t1.dtype) generator[:nocc, nocc:] = t1 - generator[nocc:, :nocc] = -t1.T + generator[nocc:, :nocc] = -t1.T.conj() return scipy.linalg.expm(generator)