Skip to content

Commit

Permalink
feat: update tf backend with qibo's new PR
Browse files Browse the repository at this point in the history
  • Loading branch information
MatteoRobbiati committed Oct 16, 2024
1 parent 4f9112d commit 40ff72b
Showing 1 changed file with 44 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/qiboml/backends/tensorflow.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import collections
import os
from typing import Union

import numpy as np
from qibo import __version__
from qibo.backends.npmatrices import NumpyMatrices
from qibo.backends.numpy import NumpyBackend
from qibo.backends.numpy import NumpyBackend, _calculate_negative_power_singular_matrix
from qibo.config import TF_LOG_LEVEL, log, raise_error


Expand Down Expand Up @@ -192,11 +193,53 @@ def calculate_matrix_exp(self, a, matrix, eigenvectors=None, eigenvalues=None):
return self.tf.linalg.expm(-1j * a * matrix)
return super().calculate_matrix_exp(a, matrix, eigenvectors, eigenvalues)

def calculate_matrix_power(
self,
matrix,
power: Union[float, int],
precision_singularity: float = 1e-14,
):
if not isinstance(power, (float, int)):
raise_error(
TypeError,
f"``power`` must be either float or int, but it is type {type(power)}.",
)

if power < 0.0:
# negative powers of singular matrices via SVD
determinant = self.tf.linalg.det(matrix)
if abs(determinant) < precision_singularity:
return _calculate_negative_power_singular_matrix(
matrix, power, precision_singularity, self.tf, self
)

return super().calculate_matrix_power(matrix, power, precision_singularity)

def calculate_singular_value_decomposition(self, matrix):
# needed to unify order of return
S, U, V = self.tf.linalg.svd(matrix)
return U, S, self.np.conj(self.np.transpose(V))

def calculate_jacobian_matrix(
self, circuit, parameters=None, initial_state=None, return_complex: bool = True
):
copied = circuit.copy(deep=True)

# necessary for the tape to properly watch the variables
parameters = self.tf.Variable(parameters)

with self.tf.GradientTape(persistent=return_complex) as tape:
copied.set_parameters(parameters)
state = self.execute_circuit(copied, initial_state=initial_state).state()
real = self.np.real(state)
if return_complex:
imag = self.np.imag(state)

if return_complex:
return tape.jacobian(real, parameters), tape.jacobian(imag, parameters)

return tape.jacobian(real, parameters)

def calculate_hamiltonian_matrix_product(self, matrix1, matrix2):
if self.is_sparse(matrix1) or self.is_sparse(matrix2):
raise_error(
Expand Down

0 comments on commit 40ff72b

Please sign in to comment.