diff --git a/src/qibo/backends/abstract.py b/src/qibo/backends/abstract.py index 9cf431016f..2c91139486 100644 --- a/src/qibo/backends/abstract.py +++ b/src/qibo/backends/abstract.py @@ -303,8 +303,8 @@ def sample_frequencies(self, probabilities, nshots): # pragma: no cover raise_error(NotImplementedError) @abc.abstractmethod - def calculate_norm(self, state, order=2): # pragma: no cover - """Calculate norm of a state vector. + def calculate_vector_norm(self, state, order=2): # pragma: no cover + """Calculate norm of an :math:`1`-dimensional array. For specifications on possible values of the parameter ``order`` for the ``tensorflow`` backend, please refer to @@ -315,9 +315,10 @@ def calculate_norm(self, state, order=2): # pragma: no cover raise_error(NotImplementedError) @abc.abstractmethod - def calculate_norm_density_matrix(self, state, order="nuc"): # pragma: no cover - """Calculate norm of a density matrix. Default is the ``nuclear`` norm. + def calculate_matrix_norm(self, state, order="nuc"): # pragma: no cover + """Calculate norm of a :math:`2`-dimensional array. + Default is the ``nuclear`` norm. If ``order="nuc"``, it returns the nuclear norm of ``state``, assuming ``state`` is Hermitian (also known as trace norm). For specifications on the other possible values of the diff --git a/src/qibo/backends/numpy.py b/src/qibo/backends/numpy.py index daef2a4606..9845dc4728 100644 --- a/src/qibo/backends/numpy.py +++ b/src/qibo/backends/numpy.py @@ -719,11 +719,11 @@ def apply_bitflips(self, noiseless_samples, bitflip_probabilities): noisy_samples = noisy_samples - noiseless_samples * flip_1 return noisy_samples - def calculate_norm(self, state, order=2): + def calculate_vector_norm(self, state, order=2): state = self.cast(state) return self.np.linalg.norm(state, order) - def calculate_norm_density_matrix(self, state, order="nuc"): + def calculate_matrix_norm(self, state, order="nuc"): state = self.cast(state) return self.np.linalg.norm(state, ord=order) diff --git a/src/qibo/callbacks.py b/src/qibo/callbacks.py index 2313e42e95..2b45212824 100644 --- a/src/qibo/callbacks.py +++ b/src/qibo/callbacks.py @@ -181,12 +181,12 @@ class Norm(Callback): """ def apply(self, backend, state): - norm = backend.calculate_norm(state) + norm = backend.calculate_vector_norm(state) self.append(norm) return norm def apply_density_matrix(self, backend, state): - norm = backend.calculate_norm_density_matrix(state) + norm = backend.calculate_matrix_norm_density_matrix(state) self.append(norm) return norm diff --git a/src/qibo/models/evolution.py b/src/qibo/models/evolution.py index 0a53e4917e..71f73ad59a 100644 --- a/src/qibo/models/evolution.py +++ b/src/qibo/models/evolution.py @@ -81,7 +81,7 @@ def __init__(self, hamiltonian, dt, solver="exp", callbacks=[], accelerators=Non def _create_normalize_state(self, solver): if "rk" in solver: log.info("Normalizing state during RK solution.") - return lambda s: s / self.backend.calculate_norm(s) + return lambda s: s / self.backend.calculate_vector_norm(s) else: return lambda s: s diff --git a/src/qibo/quantum_info/entropies.py b/src/qibo/quantum_info/entropies.py index 48767896d0..729f5309ac 100644 --- a/src/qibo/quantum_info/entropies.py +++ b/src/qibo/quantum_info/entropies.py @@ -783,7 +783,7 @@ def renyi_entropy(state, alpha: Union[float, int], base: float = 2, backend=None if alpha == np.inf: return ( -1 - * backend.np.log2(backend.calculate_norm_density_matrix(state, order=2)) + * backend.np.log2(backend.calculate_matrix_norm_density_matrix(state, order=2)) / np.log2(base) ) @@ -890,7 +890,7 @@ def relative_renyi_entropy( new_target = matrix_power(target, 0.5, backend=backend) log = backend.np.log2( - backend.calculate_norm_density_matrix(new_state @ new_target, order=1) + backend.calculate_matrix_norm_density_matrix(new_state @ new_target, order=1) ) return -2 * log / np.log2(base) diff --git a/src/qibo/quantum_info/metrics.py b/src/qibo/quantum_info/metrics.py index 61503cb48c..c67b2655fc 100644 --- a/src/qibo/quantum_info/metrics.py +++ b/src/qibo/quantum_info/metrics.py @@ -34,7 +34,7 @@ def purity(state, backend=None): ) if len(state.shape) == 1: - pur = backend.np.real(backend.calculate_norm(state)) ** 2 + pur = backend.np.real(backend.calculate_vector_norm(state)) ** 2 else: pur = backend.np.real(backend.np.trace(backend.np.matmul(state, state))) return float(pur) @@ -109,7 +109,7 @@ def trace_distance(state, target, check_hermitian: bool = False, backend=None): if check_hermitian is True: hermitian = bool( float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( backend.np.transpose(backend.np.conj(difference), (1, 0)) - difference, order=2, @@ -440,7 +440,7 @@ def process_fidelity(channel, target=None, check_unitary: bool = False, backend= if check_unitary is True: norm_channel = float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( backend.np.matmul( backend.np.conj(backend.np.transpose(channel, (1, 0))), channel ) @@ -451,7 +451,7 @@ def process_fidelity(channel, target=None, check_unitary: bool = False, backend= raise_error(TypeError, "Channel is not unitary and Target is None.") if target is not None: norm_target = float( - backend.calculate_norm( + backend.calculate_vector_norm( backend.np.matmul( backend.np.conj(backend.np.transpose(target, (1, 0))), target ) @@ -762,7 +762,7 @@ def expressibility( circuit.nqubits, power_t, samples=None, backend=backend ) - pqc_integral(circuit, power_t, samples, backend=backend) - fid = float(backend.calculate_norm(deviation, order=order)) + fid = float(backend.calculate_vector_norm(deviation, order=order)) return fid @@ -929,7 +929,7 @@ def _check_hermitian(matrix, backend=None): """ backend = _check_backend(backend) - norm = backend.calculate_norm_density_matrix( + norm = backend.calculate_matrix_norm_density_matrix( backend.np.conj(matrix).T - matrix, order=2 ) diff --git a/src/qibo/quantum_info/quantum_networks.py b/src/qibo/quantum_info/quantum_networks.py index 0976094978..084eb00571 100644 --- a/src/qibo/quantum_info/quantum_networks.py +++ b/src/qibo/quantum_info/quantum_networks.py @@ -298,7 +298,7 @@ def is_hermitian( adjoint = self._backend.np.transpose(reshaped) mat_diff = self._backend.np.conj(adjoint) - reshaped - norm = self._backend.calculate_norm_density_matrix(mat_diff, order=order) + norm = self._backend.calculate_matrix_norm_density_matrix(mat_diff, order=order) return float(norm) <= precision_tol @@ -787,7 +787,7 @@ def is_causal( sub_comb = self._tensordot(reduced, trace_in, axes=(-1, 0)) expected = self._tensordot(sub_comb, trace_in / dim_in, axes=0) - norm = self._backend.calculate_norm(reduced - expected, order=order) + norm = self._backend.calculate_vector_norm(reduced - expected, order=order) if float(norm) > precision_tol: return False @@ -926,7 +926,7 @@ def is_unital( sub_comb = self._tensordot(reduced, trace_out, axes=(0, 0)) expected = self._tensordot(trace_out / dim_out, sub_comb, axes=0) - norm = self._backend.calculate_norm((reduced - expected), order=order) + norm = self._backend.calculate_vector_norm((reduced - expected), order=order) if float(norm) > precision_tol: return False diff --git a/src/qibo/quantum_info/superoperator_transformations.py b/src/qibo/quantum_info/superoperator_transformations.py index fa7d2902ba..7ee898f029 100644 --- a/src/qibo/quantum_info/superoperator_transformations.py +++ b/src/qibo/quantum_info/superoperator_transformations.py @@ -517,7 +517,7 @@ def choi_to_kraus( if validate_cp: norm = float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( choi_super_op - backend.np.conj(choi_super_op).T, order=2 ) ) @@ -2132,7 +2132,9 @@ def function(x0, operators): for prob, oper in zip(x0, operators): operator = operator + prob * oper - return float(backend.calculate_norm_density_matrix(target - operator, order=2)) + return float( + backend.calculate_matrix_norm_density_matrix(target - operator, order=2) + ) # initial parameters as flat distribution x0 = [1.0 / (len(kraus_ops) + 1)] * len(kraus_ops) diff --git a/src/qibo/quantum_info/utils.py b/src/qibo/quantum_info/utils.py index 273e9af9dc..3e1cd1f1ba 100644 --- a/src/qibo/quantum_info/utils.py +++ b/src/qibo/quantum_info/utils.py @@ -251,7 +251,7 @@ def hellinger_distance(prob_dist_p, prob_dist_q, validate: bool = False, backend raise_error(ValueError, "Second probability array must sum to 1.") distance = float( - backend.calculate_norm( + backend.calculate_vector_norm( backend.np.sqrt(prob_dist_p) - backend.np.sqrt(prob_dist_q) ) / np.sqrt(2) @@ -386,7 +386,7 @@ def total_variation_distance( if backend.np.abs(backend.np.sum(prob_dist_q) - 1.0) > PRECISION_TOL: raise_error(ValueError, "Second probability array must sum to 1.") - tvd = backend.calculate_norm(prob_dist_p - prob_dist_q, order=1) + tvd = backend.calculate_vector_norm(prob_dist_p - prob_dist_q, order=1) return tvd / 2 diff --git a/src/qibo/transpiler/unitary_decompositions.py b/src/qibo/transpiler/unitary_decompositions.py index 40bda6d296..7d109fd473 100644 --- a/src/qibo/transpiler/unitary_decompositions.py +++ b/src/qibo/transpiler/unitary_decompositions.py @@ -98,7 +98,7 @@ def calculate_single_qubit_unitaries(psi, backend=None): psi_magic = backend.np.matmul(backend.np.conj(backend.cast(magic_basis)).T, psi) if ( backend.np.real( - backend.calculate_norm_density_matrix(backend.np.imag(psi_magic)) + backend.calculate_matrix_norm_density_matrix(backend.np.imag(psi_magic)) ) > 1e-6 ): # pragma: no cover diff --git a/tests/test_gates_channels.py b/tests/test_gates_channels.py index a1a7974541..214efe1894 100644 --- a/tests/test_gates_channels.py +++ b/tests/test_gates_channels.py @@ -108,7 +108,7 @@ def test_kraus_channel(backend, pauli_order): backend.assert_allclose( float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( channel.to_liouville(backend=backend) - test_superop, order=2 ) ) @@ -117,7 +117,7 @@ def test_kraus_channel(backend, pauli_order): ) backend.assert_allclose( float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( channel.to_choi(backend=backend) - test_choi, order=2 ) ) @@ -126,7 +126,7 @@ def test_kraus_channel(backend, pauli_order): ) backend.assert_allclose( float( - backend.calculate_norm( + backend.calculate_vector_norm( channel.to_pauli_liouville(pauli_order=pauli_order, backend=backend) - test_pauli ) @@ -240,7 +240,7 @@ def test_pauli_noise_channel(backend, pauli_order): normalize=True, pauli_order=pauli_order, backend=backend ) norm = float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( backend.to_numpy(liouville) - test_representation, order=2 ) ) @@ -384,7 +384,7 @@ def test_thermal_relaxation_channel(backend, t_1, t_2, time, excpop): backend.assert_allclose( float( - backend.calculate_norm_density_matrix(final_state - target_state, order=2) + backend.calculate_matrix_norm_density_matrix(final_state - target_state, order=2) ) < PRECISION_TOL, True, diff --git a/tests/test_models_encodings.py b/tests/test_models_encodings.py index 164e287e57..9adc68f3f7 100644 --- a/tests/test_models_encodings.py +++ b/tests/test_models_encodings.py @@ -138,7 +138,7 @@ def test_unary_encoder(backend, nqubits, architecture, kind): backend.assert_allclose( state, - backend.cast(data, dtype=np.float64) / backend.calculate_norm(data, 2), + backend.cast(data, dtype=np.float64) / backend.calculate_vector_norm(data, 2), rtol=1e-5, ) diff --git a/tests/test_quantum_info_entropies.py b/tests/test_quantum_info_entropies.py index 7c289009f9..a97a55f0f0 100644 --- a/tests/test_quantum_info_entropies.py +++ b/tests/test_quantum_info_entropies.py @@ -590,7 +590,7 @@ def test_renyi_entropy(backend, alpha, base): elif alpha == 1.0: target = von_neumann_entropy(state, base=base, backend=backend) elif alpha == np.inf: - target = backend.calculate_norm_density_matrix(state, order=2) + target = backend.calculate_matrix_norm_density_matrix(state, order=2) target = -1 * backend.np.log2(target) / np.log2(base) else: target = np.log2( @@ -687,7 +687,7 @@ def test_relative_renyi_entropy(backend, alpha, base, state_flag, target_flag): new_target = matrix_power(target_outer, 0.5, backend=backend) log = backend.np.log2( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( new_state @ new_target, order=1 ) ) diff --git a/tests/test_quantum_info_random.py b/tests/test_quantum_info_random.py index d522f1458d..6a662aa237 100644 --- a/tests/test_quantum_info_random.py +++ b/tests/test_quantum_info_random.py @@ -112,14 +112,14 @@ def test_random_hermitian(backend): dims = 4 matrix = random_hermitian(dims, backend=backend) matrix_dagger = backend.np.conj(matrix).T - norm = float(backend.calculate_norm_density_matrix(matrix - matrix_dagger, order=2)) + norm = float(backend.calculate_matrix_norm_density_matrix(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) # test if function returns semidefinite Hermitian operator dims = 4 matrix = random_hermitian(dims, semidefinite=True, backend=backend) matrix_dagger = backend.np.conj(matrix).T - norm = float(backend.calculate_norm_density_matrix(matrix - matrix_dagger, order=2)) + norm = float(backend.calculate_matrix_norm_density_matrix(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) eigenvalues = np.linalg.eigvalsh(backend.to_numpy(matrix)) @@ -130,7 +130,7 @@ def test_random_hermitian(backend): dims = 4 matrix = random_hermitian(dims, normalize=True, backend=backend) matrix_dagger = backend.np.conj(matrix).T - norm = float(backend.calculate_norm_density_matrix(matrix - matrix_dagger, order=2)) + norm = float(backend.calculate_matrix_norm_density_matrix(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) eigenvalues = np.linalg.eigvalsh(backend.to_numpy(matrix)) @@ -141,7 +141,7 @@ def test_random_hermitian(backend): dims = 4 matrix = random_hermitian(dims, semidefinite=True, normalize=True, backend=backend) matrix_dagger = backend.np.conj(matrix).T - norm = float(backend.calculate_norm(matrix - matrix_dagger, order=2)) + norm = float(backend.calculate_vector_norm(matrix - matrix_dagger, order=2)) backend.assert_allclose(norm < PRECISION_TOL, True) eigenvalues = np.linalg.eigvalsh(backend.to_numpy(matrix)) @@ -178,7 +178,7 @@ def test_random_unitary(backend, measure): else np.linalg.inv(matrix) ) norm = float( - backend.calculate_norm_density_matrix(matrix_inv - matrix_dagger, order=2) + backend.calculate_matrix_norm_density_matrix(matrix_inv - matrix_dagger, order=2) ) backend.assert_allclose(norm < PRECISION_TOL, True) @@ -275,7 +275,7 @@ def test_random_density_matrix(backend, dims, pure, metric, basis, normalize): test = random_density_matrix(dims=dims, normalize=True) else: norm_function = ( - backend.calculate_norm_density_matrix + backend.calculate_matrix_norm_density_matrix if basis is None else backend.calculate_norm ) @@ -416,7 +416,7 @@ def test_pauli_single(backend): backend.assert_allclose( np.abs( backend.to_numpy( - backend.calculate_norm_density_matrix(matrix - result, order=2) + backend.calculate_matrix_norm_density_matrix(matrix - result, order=2) ) ) < PRECISION_TOL, @@ -457,7 +457,7 @@ def test_random_pauli( if subset is None: backend.assert_allclose( float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( matrix - result_complete_set, order=2 ) ) @@ -467,7 +467,7 @@ def test_random_pauli( else: backend.assert_allclose( float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( matrix - result_subset, order=2 ) ) @@ -482,7 +482,7 @@ def test_random_pauli( if subset is None: backend.assert_allclose( float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( matrix - result_complete_set, order=2 ) ) @@ -492,7 +492,7 @@ def test_random_pauli( else: backend.assert_allclose( float( - backend.calculate_norm_density_matrix( + backend.calculate_matrix_norm_density_matrix( matrix - result_subset, order=2 ) ) diff --git a/tests/test_quantum_info_utils.py b/tests/test_quantum_info_utils.py index f9b8c0ff2b..7a38ad0f32 100644 --- a/tests/test_quantum_info_utils.py +++ b/tests/test_quantum_info_utils.py @@ -167,7 +167,7 @@ def test_hellinger(backend, validate, kind): prob_q = backend.cast(prob_q, dtype=prob_q.dtype) target = float( - backend.calculate_norm(backend.np.sqrt(prob_p) - backend.np.sqrt(prob_q)) + backend.calculate_vector_norm(backend.np.sqrt(prob_p) - backend.np.sqrt(prob_q)) / np.sqrt(2) ) @@ -242,7 +242,7 @@ def test_total_variation_distance(backend, validate, kind): prob_p = backend.cast(prob_p, dtype=prob_p.dtype) prob_q = backend.cast(prob_q, dtype=prob_q.dtype) - target = float(backend.calculate_norm(prob_p - prob_q, order=1) / 2) + target = float(backend.calculate_vector_norm(prob_p - prob_q, order=1) / 2) prob_p = ( kind(prob_p) if kind is not None else backend.cast(prob_p, dtype=prob_p.dtype)