chore: Run pre-commit on all files
This commit is contained in:
9
setup.py
9
setup.py
@@ -1,6 +1,7 @@
|
|||||||
from setuptools import setup, find_packages
|
|
||||||
import re
|
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import re
|
||||||
|
|
||||||
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
HERE = pathlib.Path(__file__).parent.absolute()
|
HERE = pathlib.Path(__file__).parent.absolute()
|
||||||
PACKAGE = "qibotn"
|
PACKAGE = "qibotn"
|
||||||
@@ -8,8 +9,8 @@ PACKAGE = "qibotn"
|
|||||||
|
|
||||||
# Returns the qibotn version
|
# Returns the qibotn version
|
||||||
def version():
|
def version():
|
||||||
"""Gets the version from the package's __init__ file
|
"""Gets the version from the package's __init__ file if there is some
|
||||||
if there is some problem, let it happily fail"""
|
problem, let it happily fail."""
|
||||||
version_file = HERE / "src" / PACKAGE / "__init__.py"
|
version_file = HERE / "src" / PACKAGE / "__init__.py"
|
||||||
version_regex = r"^__version__ = ['\"]([^'\"]*)['\"]"
|
version_regex = r"^__version__ = ['\"]([^'\"]*)['\"]"
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,19 @@
|
|||||||
import cupy as cp
|
import cupy as cp
|
||||||
from cuquantum.cutensornet.experimental import contract_decompose
|
|
||||||
from cuquantum import contract
|
from cuquantum import contract
|
||||||
|
from cuquantum.cutensornet.experimental import contract_decompose
|
||||||
|
|
||||||
# Reference: https://github.com/NVIDIA/cuQuantum/blob/main/python/samples/cutensornet/tn_algorithms/mps_algorithms.ipynb
|
# Reference: https://github.com/NVIDIA/cuQuantum/blob/main/python/samples/cutensornet/tn_algorithms/mps_algorithms.ipynb
|
||||||
|
|
||||||
|
|
||||||
def initial(num_qubits, dtype):
|
def initial(num_qubits, dtype):
|
||||||
"""
|
"""Generate the MPS with an initial state of |00...00>"""
|
||||||
Generate the MPS with an initial state of |00...00>
|
|
||||||
"""
|
|
||||||
state_tensor = cp.asarray([1, 0], dtype=dtype).reshape(1, 2, 1)
|
state_tensor = cp.asarray([1, 0], dtype=dtype).reshape(1, 2, 1)
|
||||||
mps_tensors = [state_tensor] * num_qubits
|
mps_tensors = [state_tensor] * num_qubits
|
||||||
return mps_tensors
|
return mps_tensors
|
||||||
|
|
||||||
|
|
||||||
def mps_site_right_swap(mps_tensors, i, **kwargs):
|
def mps_site_right_swap(mps_tensors, i, **kwargs):
|
||||||
"""
|
"""Perform the swap operation between the ith and i+1th MPS tensors."""
|
||||||
Perform the swap operation between the ith and i+1th MPS tensors.
|
|
||||||
"""
|
|
||||||
# contraction followed by QR decomposition
|
# contraction followed by QR decomposition
|
||||||
a, _, b = contract_decompose(
|
a, _, b = contract_decompose(
|
||||||
"ipj,jqk->iqj,jpk",
|
"ipj,jqk->iqj,jpk",
|
||||||
@@ -30,8 +26,7 @@ def mps_site_right_swap(mps_tensors, i, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def apply_gate(mps_tensors, gate, qubits, **kwargs):
|
def apply_gate(mps_tensors, gate, qubits, **kwargs):
|
||||||
"""
|
"""Apply the gate operand to the MPS tensors in-place.
|
||||||
Apply the gate operand to the MPS tensors in-place.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import numpy as np
|
|||||||
|
|
||||||
|
|
||||||
class QiboCircuitToEinsum:
|
class QiboCircuitToEinsum:
|
||||||
"""Convert a circuit to a Tensor Network (TN) representation.
|
"""Convert a circuit to a Tensor Network (TN) representation. The circuit
|
||||||
The circuit is first processed to an intermediate form by grouping each gate
|
is first processed to an intermediate form by grouping each gate matrix
|
||||||
matrix with its corresponding qubit it is acting on to a list. It is then
|
with its corresponding qubit it is acting on to a list. It is then
|
||||||
converted to an equivalent TN expression through the class function
|
converted to an equivalent TN expression through the class function
|
||||||
state_vector_operands() following the Einstein summation convention in the
|
state_vector_operands() following the Einstein summation convention in the
|
||||||
interleave format.
|
interleave format.
|
||||||
@@ -79,9 +79,8 @@ class QiboCircuitToEinsum:
|
|||||||
return mode_labels, operands
|
return mode_labels, operands
|
||||||
|
|
||||||
def op_shape_from_qubits(self, nqubits):
|
def op_shape_from_qubits(self, nqubits):
|
||||||
"""Modify tensor to cuQuantum shape
|
"""Modify tensor to cuQuantum shape (qubit_states,input_output) *
|
||||||
(qubit_states,input_output) * qubits_involved
|
qubits_involved."""
|
||||||
"""
|
|
||||||
return (2, 2) * nqubits
|
return (2, 2) * nqubits
|
||||||
|
|
||||||
def init_intermediate_circuit(self, circuit):
|
def init_intermediate_circuit(self, circuit):
|
||||||
@@ -134,8 +133,7 @@ class QiboCircuitToEinsum:
|
|||||||
self.active_qubits_inverse = np.unique(gates_qubits_inverse)
|
self.active_qubits_inverse = np.unique(gates_qubits_inverse)
|
||||||
|
|
||||||
def get_pauli_gates(self, pauli_map, dtype="complex128", backend=cp):
|
def get_pauli_gates(self, pauli_map, dtype="complex128", backend=cp):
|
||||||
"""
|
"""Populate the gates for all pauli operators.
|
||||||
Populate the gates for all pauli operators.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
pauli_map: A dictionary mapping qubits to pauli operators.
|
pauli_map: A dictionary mapping qubits to pauli operators.
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import cupy as cp
|
import cupy as cp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from cuquantum import cutensornet as cutn
|
from cuquantum import cutensornet as cutn
|
||||||
|
|
||||||
|
from qibotn.MPSUtils import apply_gate, initial
|
||||||
from qibotn.QiboCircuitConvertor import QiboCircuitToEinsum
|
from qibotn.QiboCircuitConvertor import QiboCircuitToEinsum
|
||||||
from qibotn.MPSUtils import initial, apply_gate
|
|
||||||
|
|
||||||
|
|
||||||
class QiboCircuitToMPS:
|
class QiboCircuitToMPS:
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
from qibotn.backends.gpu import CuTensorNet
|
|
||||||
from qibotn.backends.cpu import QuTensorNet
|
from qibotn.backends.cpu import QuTensorNet
|
||||||
|
from qibotn.backends.gpu import CuTensorNet
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from qibo.backends.numpy import NumpyBackend
|
from qibo.backends.numpy import NumpyBackend
|
||||||
from qibo.states import CircuitResult
|
|
||||||
from qibo.config import raise_error
|
from qibo.config import raise_error
|
||||||
|
from qibo.states import CircuitResult
|
||||||
|
|
||||||
|
|
||||||
class CuTensorNet(NumpyBackend): # pragma: no cover
|
class CuTensorNet(NumpyBackend): # pragma: no cover
|
||||||
@@ -107,7 +106,6 @@ class CuTensorNet(NumpyBackend): # pragma: no cover
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
xxx.
|
xxx.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import qibotn.eval as eval
|
import qibotn.eval as eval
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
from qibotn.QiboCircuitConvertor import QiboCircuitToEinsum
|
|
||||||
from cuquantum import contract
|
|
||||||
from cupy.cuda.runtime import getDeviceCount
|
|
||||||
import cupy as cp
|
import cupy as cp
|
||||||
|
from cupy.cuda.runtime import getDeviceCount
|
||||||
|
from cuquantum import contract
|
||||||
|
|
||||||
from qibotn.QiboCircuitToMPS import QiboCircuitToMPS
|
|
||||||
from qibotn.mps_contraction_helper import MPSContractionHelper
|
from qibotn.mps_contraction_helper import MPSContractionHelper
|
||||||
|
from qibotn.QiboCircuitConvertor import QiboCircuitToEinsum
|
||||||
|
from qibotn.QiboCircuitToMPS import QiboCircuitToMPS
|
||||||
|
|
||||||
|
|
||||||
def dense_vector_tn(qibo_circ, datatype):
|
def dense_vector_tn(qibo_circ, datatype):
|
||||||
"""Convert qibo circuit to tensornet (TN) format and perform contraction to dense vector."""
|
"""Convert qibo circuit to tensornet (TN) format and perform contraction to
|
||||||
|
dense vector."""
|
||||||
myconvertor = QiboCircuitToEinsum(qibo_circ, dtype=datatype)
|
myconvertor = QiboCircuitToEinsum(qibo_circ, dtype=datatype)
|
||||||
return contract(*myconvertor.state_vector_operands())
|
return contract(*myconvertor.state_vector_operands())
|
||||||
|
|
||||||
|
|
||||||
def expectation_pauli_tn(qibo_circ, datatype, pauli_string_pattern):
|
def expectation_pauli_tn(qibo_circ, datatype, pauli_string_pattern):
|
||||||
"""Convert qibo circuit to tensornet (TN) format and perform contraction to expectation of given Pauli string."""
|
"""Convert qibo circuit to tensornet (TN) format and perform contraction to
|
||||||
|
expectation of given Pauli string."""
|
||||||
myconvertor = QiboCircuitToEinsum(qibo_circ, dtype=datatype)
|
myconvertor = QiboCircuitToEinsum(qibo_circ, dtype=datatype)
|
||||||
return contract(
|
return contract(
|
||||||
*myconvertor.expectation_operands(
|
*myconvertor.expectation_operands(
|
||||||
@@ -24,14 +26,19 @@ def expectation_pauli_tn(qibo_circ, datatype, pauli_string_pattern):
|
|||||||
|
|
||||||
|
|
||||||
def dense_vector_tn_MPI(qibo_circ, datatype, n_samples=8):
|
def dense_vector_tn_MPI(qibo_circ, datatype, n_samples=8):
|
||||||
"""Convert qibo circuit to tensornet (TN) format and perform contraction using multi node and multi GPU through MPI.
|
"""Convert qibo circuit to tensornet (TN) format and perform contraction
|
||||||
The conversion is performed by QiboCircuitToEinsum(), after which it goes through 2 steps: pathfinder and execution.
|
using multi node and multi GPU through MPI.
|
||||||
The pathfinder looks at user defined number of samples (n_samples) iteratively to select the least costly contraction path. This is sped up with multi thread.
|
|
||||||
After pathfinding the optimal path is used in the actual contraction to give a dense vector representation of the TN.
|
The conversion is performed by QiboCircuitToEinsum(), after which it
|
||||||
|
goes through 2 steps: pathfinder and execution. The pathfinder looks
|
||||||
|
at user defined number of samples (n_samples) iteratively to select
|
||||||
|
the least costly contraction path. This is sped up with multi
|
||||||
|
thread. After pathfinding the optimal path is used in the actual
|
||||||
|
contraction to give a dense vector representation of the TN.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from mpi4py import MPI
|
|
||||||
from cuquantum import Network
|
from cuquantum import Network
|
||||||
|
from mpi4py import MPI
|
||||||
|
|
||||||
root = 0
|
root = 0
|
||||||
comm = MPI.COMM_WORLD
|
comm = MPI.COMM_WORLD
|
||||||
@@ -86,14 +93,19 @@ def dense_vector_tn_MPI(qibo_circ, datatype, n_samples=8):
|
|||||||
|
|
||||||
|
|
||||||
def dense_vector_tn_nccl(qibo_circ, datatype, n_samples=8):
|
def dense_vector_tn_nccl(qibo_circ, datatype, n_samples=8):
|
||||||
"""Convert qibo circuit to tensornet (TN) format and perform contraction using multi node and multi GPU through NCCL.
|
"""Convert qibo circuit to tensornet (TN) format and perform contraction
|
||||||
The conversion is performed by QiboCircuitToEinsum(), after which it goes through 2 steps: pathfinder and execution.
|
using multi node and multi GPU through NCCL.
|
||||||
The pathfinder looks at user defined number of samples (n_samples) iteratively to select the least costly contraction path. This is sped up with multi thread.
|
|
||||||
After pathfinding the optimal path is used in the actual contraction to give a dense vector representation of the TN.
|
The conversion is performed by QiboCircuitToEinsum(), after which it
|
||||||
|
goes through 2 steps: pathfinder and execution. The pathfinder looks
|
||||||
|
at user defined number of samples (n_samples) iteratively to select
|
||||||
|
the least costly contraction path. This is sped up with multi
|
||||||
|
thread. After pathfinding the optimal path is used in the actual
|
||||||
|
contraction to give a dense vector representation of the TN.
|
||||||
"""
|
"""
|
||||||
from mpi4py import MPI
|
|
||||||
from cuquantum import Network
|
|
||||||
from cupy.cuda import nccl
|
from cupy.cuda import nccl
|
||||||
|
from cuquantum import Network
|
||||||
|
from mpi4py import MPI
|
||||||
|
|
||||||
root = 0
|
root = 0
|
||||||
comm_mpi = MPI.COMM_WORLD
|
comm_mpi = MPI.COMM_WORLD
|
||||||
@@ -159,15 +171,22 @@ def dense_vector_tn_nccl(qibo_circ, datatype, n_samples=8):
|
|||||||
|
|
||||||
|
|
||||||
def expectation_pauli_tn_nccl(qibo_circ, datatype, pauli_string_pattern, n_samples=8):
|
def expectation_pauli_tn_nccl(qibo_circ, datatype, pauli_string_pattern, n_samples=8):
|
||||||
"""Convert qibo circuit to tensornet (TN) format and perform contraction to expectation of given Pauli string using multi node and multi GPU through NCCL.
|
"""Convert qibo circuit to tensornet (TN) format and perform contraction to
|
||||||
The conversion is performed by QiboCircuitToEinsum(), after which it goes through 2 steps: pathfinder and execution.
|
expectation of given Pauli string using multi node and multi GPU through
|
||||||
The pauli_string_pattern is used to generate the pauli string corresponding to the number of qubits of the system.
|
NCCL.
|
||||||
The pathfinder looks at user defined number of samples (n_samples) iteratively to select the least costly contraction path. This is sped up with multi thread.
|
|
||||||
After pathfinding the optimal path is used in the actual contraction to give an expectation value.
|
The conversion is performed by QiboCircuitToEinsum(), after which it
|
||||||
|
goes through 2 steps: pathfinder and execution. The
|
||||||
|
pauli_string_pattern is used to generate the pauli string
|
||||||
|
corresponding to the number of qubits of the system. The pathfinder
|
||||||
|
looks at user defined number of samples (n_samples) iteratively to
|
||||||
|
select the least costly contraction path. This is sped up with multi
|
||||||
|
thread. After pathfinding the optimal path is used in the actual
|
||||||
|
contraction to give an expectation value.
|
||||||
"""
|
"""
|
||||||
from mpi4py import MPI
|
|
||||||
from cuquantum import Network
|
|
||||||
from cupy.cuda import nccl
|
from cupy.cuda import nccl
|
||||||
|
from cuquantum import Network
|
||||||
|
from mpi4py import MPI
|
||||||
|
|
||||||
root = 0
|
root = 0
|
||||||
comm_mpi = MPI.COMM_WORLD
|
comm_mpi = MPI.COMM_WORLD
|
||||||
@@ -235,14 +254,21 @@ def expectation_pauli_tn_nccl(qibo_circ, datatype, pauli_string_pattern, n_sampl
|
|||||||
|
|
||||||
|
|
||||||
def expectation_pauli_tn_MPI(qibo_circ, datatype, pauli_string_pattern, n_samples=8):
|
def expectation_pauli_tn_MPI(qibo_circ, datatype, pauli_string_pattern, n_samples=8):
|
||||||
"""Convert qibo circuit to tensornet (TN) format and perform contraction to expectation of given Pauli string using multi node and multi GPU through MPI.
|
"""Convert qibo circuit to tensornet (TN) format and perform contraction to
|
||||||
The conversion is performed by QiboCircuitToEinsum(), after which it goes through 2 steps: pathfinder and execution.
|
expectation of given Pauli string using multi node and multi GPU through
|
||||||
The pauli_string_pattern is used to generate the pauli string corresponding to the number of qubits of the system.
|
MPI.
|
||||||
The pathfinder looks at user defined number of samples (n_samples) iteratively to select the least costly contraction path. This is sped up with multi thread.
|
|
||||||
After pathfinding the optimal path is used in the actual contraction to give an expectation value.
|
The conversion is performed by QiboCircuitToEinsum(), after which it
|
||||||
|
goes through 2 steps: pathfinder and execution. The
|
||||||
|
pauli_string_pattern is used to generate the pauli string
|
||||||
|
corresponding to the number of qubits of the system. The pathfinder
|
||||||
|
looks at user defined number of samples (n_samples) iteratively to
|
||||||
|
select the least costly contraction path. This is sped up with multi
|
||||||
|
thread. After pathfinding the optimal path is used in the actual
|
||||||
|
contraction to give an expectation value.
|
||||||
"""
|
"""
|
||||||
from mpi4py import MPI # this line initializes MPI
|
|
||||||
from cuquantum import Network
|
from cuquantum import Network
|
||||||
|
from mpi4py import MPI # this line initializes MPI
|
||||||
|
|
||||||
root = 0
|
root = 0
|
||||||
comm = MPI.COMM_WORLD
|
comm = MPI.COMM_WORLD
|
||||||
@@ -299,7 +325,8 @@ def expectation_pauli_tn_MPI(qibo_circ, datatype, pauli_string_pattern, n_sample
|
|||||||
|
|
||||||
|
|
||||||
def dense_vector_mps(qibo_circ, gate_algo, datatype):
|
def dense_vector_mps(qibo_circ, gate_algo, datatype):
|
||||||
"""Convert qibo circuit to matrix product state (MPS) format and perform contraction to dense vector."""
|
"""Convert qibo circuit to matrix product state (MPS) format and perform
|
||||||
|
contraction to dense vector."""
|
||||||
myconvertor = QiboCircuitToMPS(qibo_circ, gate_algo, dtype=datatype)
|
myconvertor = QiboCircuitToMPS(qibo_circ, gate_algo, dtype=datatype)
|
||||||
mps_helper = MPSContractionHelper(myconvertor.num_qubits)
|
mps_helper = MPSContractionHelper(myconvertor.num_qubits)
|
||||||
|
|
||||||
@@ -309,7 +336,9 @@ def dense_vector_mps(qibo_circ, gate_algo, datatype):
|
|||||||
|
|
||||||
|
|
||||||
def pauli_string_gen(nqubits, pauli_string_pattern):
|
def pauli_string_gen(nqubits, pauli_string_pattern):
|
||||||
"""Used internally to generate the string based on given pattern and number of qubit.
|
"""Used internally to generate the string based on given pattern and number
|
||||||
|
of qubit.
|
||||||
|
|
||||||
Example: pattern: "XZ", number of qubit: 7, output = XZXZXZX
|
Example: pattern: "XZ", number of qubit: 7, output = XZXZXZX
|
||||||
"""
|
"""
|
||||||
if nqubits <= 0:
|
if nqubits <= 0:
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
from cuquantum import contract, contract_path, CircuitToEinsum, tensor
|
from cuquantum import contract, contract_path
|
||||||
|
|
||||||
# Reference: https://github.com/NVIDIA/cuQuantum/blob/main/python/samples/cutensornet/tn_algorithms/mps_algorithms.ipynb
|
# Reference: https://github.com/NVIDIA/cuQuantum/blob/main/python/samples/cutensornet/tn_algorithms/mps_algorithms.ipynb
|
||||||
|
|
||||||
|
|
||||||
class MPSContractionHelper:
|
class MPSContractionHelper:
|
||||||
"""
|
"""A helper class to compute various quantities for a given MPS.
|
||||||
A helper class to compute various quantities for a given MPS.
|
|
||||||
|
|
||||||
Interleaved format is used to construct the input args for `cuquantum.contract`.
|
Interleaved format is used to construct the input args for `cuquantum.contract`.
|
||||||
A concrete example on how the modes are populated for a 7-site MPS is provided below:
|
A concrete example on how the modes are populated for a 7-site MPS is provided below:
|
||||||
@@ -43,8 +42,8 @@ class MPSContractionHelper:
|
|||||||
]
|
]
|
||||||
|
|
||||||
def contract_norm(self, mps_tensors, options=None):
|
def contract_norm(self, mps_tensors, options=None):
|
||||||
"""
|
"""Contract the corresponding tensor network to form the norm of the
|
||||||
Contract the corresponding tensor network to form the norm of the MPS.
|
MPS.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
||||||
@@ -64,8 +63,8 @@ class MPSContractionHelper:
|
|||||||
return self._contract(interleaved_inputs, options=options).real
|
return self._contract(interleaved_inputs, options=options).real
|
||||||
|
|
||||||
def contract_state_vector(self, mps_tensors, options=None):
|
def contract_state_vector(self, mps_tensors, options=None):
|
||||||
"""
|
"""Contract the corresponding tensor network to form the state vector
|
||||||
Contract the corresponding tensor network to form the state vector representation of the MPS.
|
representation of the MPS.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
||||||
@@ -86,8 +85,8 @@ class MPSContractionHelper:
|
|||||||
def contract_expectation(
|
def contract_expectation(
|
||||||
self, mps_tensors, operator, qubits, options=None, normalize=False
|
self, mps_tensors, operator, qubits, options=None, normalize=False
|
||||||
):
|
):
|
||||||
"""
|
"""Contract the corresponding tensor network to form the expectation of
|
||||||
Contract the corresponding tensor network to form the expectation of the MPS.
|
the MPS.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
mps_tensors: A list of rank-3 ndarray-like tensor objects.
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from timeit import default_timer as timer
|
from timeit import default_timer as timer
|
||||||
|
|
||||||
import config
|
import config
|
||||||
import numpy as np
|
|
||||||
import cupy as cp
|
import cupy as cp
|
||||||
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
import qibo
|
import qibo
|
||||||
from qibo.models import QFT
|
from qibo.models import QFT
|
||||||
|
|||||||
Reference in New Issue
Block a user