Skip to content

Commit

Permalink
[feature] Introduced GeneralState as a wrapper for NVIDIA's "high-l…
Browse files Browse the repository at this point in the history
…evel" API

* Moved modules dealing with exact TN circuit representation to separate folder.

* Implemented `GeneralState`.

* Added statevector test.

* Added overlap test.

* Added a toffoli box with implicit swaps test and corresponding fix to `GeneralState`.

* Updated public API docs.

* Applying changes from comments

* Moving CuTensorNetHandle to the general.py at the root of the module

* Updated changelog

* Adding error message if circuit contains non-unitary gates

---------

Co-authored-by: PabloAndresCQ <[email protected]>
Co-authored-by: Pablo Andres-Martinez <[email protected]>
  • Loading branch information
3 people authored Jun 26, 2024
1 parent ef0d2fe commit 35e0fd8
Show file tree
Hide file tree
Showing 23 changed files with 817 additions and 88 deletions.
7 changes: 6 additions & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
API documentation
-----------------

.. autoclass:: pytket.extensions.cutensornet.CuTensorNetHandle

.. automethod:: destroy


.. toctree::
modules/fullTN.rst
modules/general_state.rst
modules/structured_state.rst
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
Unreleased
----------

* New API: ``GeneralState`` for exact simulation of circuits via contraction-path optimisation. Currently supports ``get_statevector()`` and ``expectation_value()``.
* New feature: ``add_qubit`` to add fresh qubits at specified positions in an ``MPS``.
* New feature: added an option to ``measure`` to toggle destructive measurement on/off. Currently only supported for ``MPS``.
* New feature: a seed can now be provided to ``Config`` objects, providing reproducibility across ``StructuredState`` simulations.
Expand Down
5 changes: 0 additions & 5 deletions docs/modules/fullTN.rst

This file was deleted.

31 changes: 31 additions & 0 deletions docs/modules/general_state.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
General state (exact) simulation
================================

.. automodule:: pytket.extensions.cutensornet.general_state

.. autoclass:: pytket.extensions.cutensornet.general_state.GeneralState()

.. automethod:: __init__
.. automethod:: get_statevector
.. automethod:: expectation_value
.. automethod:: destroy

cuQuantum `contract` API interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. autoclass:: pytket.extensions.cutensornet.general_state.TensorNetwork

.. autoclass:: pytket.extensions.cutensornet.general_state.PauliOperatorTensorNetwork

.. autoclass:: pytket.extensions.cutensornet.general_state.ExpectationValueTensorNetwork

.. autofunction:: pytket.extensions.cutensornet.general_state.measure_qubits_state

.. autofunction:: pytket.extensions.cutensornet.general_state.tk_to_tensor_network


Pytket backend
~~~~~~~~~~~~~~

.. automodule:: pytket.extensions.cutensornet
:members: CuTensorNetBackend
4 changes: 0 additions & 4 deletions docs/modules/structured_state.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ Simulation

.. automethod:: __init__

.. autoclass:: pytket.extensions.cutensornet.structured_state.CuTensorNetHandle

.. automethod:: destroy


Classes
~~~~~~~
Expand Down
15 changes: 3 additions & 12 deletions pytket/extensions/cutensornet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,8 @@
# limitations under the License.
"""Module for conversion from tket primitives to cuQuantum primitives."""

# _metadata.py is copied to the folder after installation.
from ._metadata import __extension_version__, __extension_name__ # type: ignore

from .backends import CuTensorNetBackend
from .general import CuTensorNetHandle

from .tensor_network_convert import (
TensorNetwork,
PauliOperatorTensorNetwork,
ExpectationValueTensorNetwork,
tk_to_tensor_network,
measure_qubits_state,
)

from .utils import circuit_statevector_postselect
# _metadata.py is copied to the folder after installation.
from ._metadata import __extension_version__, __extension_name__ # type: ignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from pytket.backends.backend import KwargTypes, Backend, BackendResult
from pytket.backends.backendinfo import BackendInfo
from pytket.backends.resulthandle import _ResultIdTuple
from pytket.extensions.cutensornet.tensor_network_convert import (
from pytket.extensions.cutensornet.general_state import (
TensorNetwork,
ExpectationValueTensorNetwork,
tk_to_tensor_network,
Expand Down
76 changes: 76 additions & 0 deletions pytket/extensions/cutensornet/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,85 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations # type: ignore
import warnings
import logging
from logging import Logger

from typing import Any, Optional

try:
import cupy as cp # type: ignore
except ImportError:
warnings.warn("local settings failed to import cupy", ImportWarning)
try:
import cuquantum.cutensornet as cutn # type: ignore
except ImportError:
warnings.warn("local settings failed to import cutensornet", ImportWarning)


class CuTensorNetHandle:
"""Initialise the cuTensorNet library with automatic workspace memory
management.
Note:
Always use as ``with CuTensorNetHandle() as libhandle:`` so that cuTensorNet
handles are automatically destroyed at the end of execution.
Attributes:
handle (int): The cuTensorNet library handle created by this initialisation.
device_id (int): The ID of the device (GPU) where cuTensorNet is initialised.
If not provided, defaults to ``cp.cuda.Device()``.
"""

def __init__(self, device_id: Optional[int] = None):
self._is_destroyed = False

# Make sure CuPy uses the specified device
dev = cp.cuda.Device(device_id)
dev.use()

self.dev = dev
self.device_id = dev.id

self._handle = cutn.create()

@property
def handle(self) -> Any:
if self._is_destroyed:
raise RuntimeError(
"The cuTensorNet library handle is out of scope.",
"See the documentation of CuTensorNetHandle.",
)
return self._handle

def destroy(self) -> None:
"""Destroys the memory handle, releasing memory.
Only call this method if you are initialising a ``CuTensorNetHandle`` outside
a ``with CuTensorNetHandle() as libhandle`` statement.
"""
cutn.destroy(self._handle)
self._is_destroyed = True

def __enter__(self) -> CuTensorNetHandle:
return self

def __exit__(self, exc_type: Any, exc_value: Any, exc_tb: Any) -> None:
self.destroy()

def print_device_properties(self, logger: Logger) -> None:
"""Prints local GPU properties."""
device_props = cp.cuda.runtime.getDeviceProperties(self.dev.id)
logger.debug("===== device info ======")
logger.debug("GPU-name:", device_props["name"].decode())
logger.debug("GPU-clock:", device_props["clockRate"])
logger.debug("GPU-memoryClock:", device_props["memoryClockRate"])
logger.debug("GPU-nSM:", device_props["multiProcessorCount"])
logger.debug("GPU-major:", device_props["major"])
logger.debug("GPU-minor:", device_props["minor"])
logger.debug("========================")


def set_logger(
logger_name: str,
Expand Down
26 changes: 26 additions & 0 deletions pytket/extensions/cutensornet/general_state/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2019-2024 Quantinuum
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Module for simulating circuits with no predetermined tensor network structure."""

from .utils import circuit_statevector_postselect

from .tensor_network_convert import (
TensorNetwork,
PauliOperatorTensorNetwork,
ExpectationValueTensorNetwork,
tk_to_tensor_network,
measure_qubits_state,
)

from .tensor_network_state import GeneralState
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
from networkx.classes.reportviews import OutMultiEdgeView, OutMultiEdgeDataView # type: ignore
import numpy as np
from numpy.typing import NDArray
from pytket import Qubit # type: ignore
from pytket.utils import Graph
from pytket.pauli import QubitPauliString # type: ignore
from pytket.circuit import Circuit, Qubit # type: ignore
from pytket.pauli import QubitPauliString
from pytket.circuit import Circuit, Qubit
from pytket.utils import permute_rows_cols_in_unitary
from pytket.extensions.cutensornet.general import set_logger

Expand Down
Loading

0 comments on commit 35e0fd8

Please sign in to comment.