Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main #30

Merged
merged 4 commits into from
Sep 22, 2023
Merged

Main #30

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _metadata.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__extension_version__ = "0.2.1"
__extension_version__ = "0.3.0"
__extension_name__ = "pytket-cutensornet"
9 changes: 8 additions & 1 deletion docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
~~~~~~~~~

0.3.0 (September 2023)
----------------------

* Added MPS sampling feature.
* Refactored MPS module for better maintainability and extendability.
* ``Tensor`` class removed from the API since it is no longer necessary.

0.2.1 (August 2023)
-------------------

Expand All @@ -16,4 +23,4 @@ Changelog
0.1.0 (June 2023)
-----------------

* Initial implementation of the converter and backend modules for use on a single GPU.
* Initial implementation of the converter and backend modules for use on a single GPU.
4 changes: 2 additions & 2 deletions pytket/extensions/cutensornet/mps/mps.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
except ImportError:
warnings.warn("local settings failed to import cutensornet", ImportWarning)

from pytket.circuit import Command, Op, OpType, Qubit # type: ignore
from pytket.pauli import Pauli, QubitPauliString # type: ignore
from pytket.circuit import Command, Op, OpType, Qubit
from pytket.pauli import Pauli, QubitPauliString

# An alias so that `intptr_t` from CuQuantum's API (which is not available in
# base python) has some meaningful type name.
Expand Down
2 changes: 1 addition & 1 deletion pytket/extensions/cutensornet/mps/mps_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
except ImportError:
warnings.warn("local settings failed to import cutensornet", ImportWarning)

from pytket.circuit import Op # type: ignore
from pytket.circuit import Op
from .mps import MPS


Expand Down
2 changes: 1 addition & 1 deletion pytket/extensions/cutensornet/mps/mps_mpo.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
except ImportError:
warnings.warn("local settings failed to import cutensornet", ImportWarning)

from pytket.circuit import Op, Qubit # type: ignore
from pytket.circuit import Op, Qubit
from .mps import (
CuTensorNetHandle,
DirectionMPS,
Expand Down
17 changes: 11 additions & 6 deletions pytket/extensions/cutensornet/mps/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from collections import defaultdict # type: ignore
import numpy as np # type: ignore

from pytket.circuit import Circuit, Command, Qubit # type: ignore
from pytket.transform import Transform # type: ignore
from pytket.architecture import Architecture # type: ignore
from pytket.passes import DefaultMappingPass # type: ignore
from pytket.predicates import CompilationUnit # type: ignore
from pytket.circuit import Circuit, Command, Qubit
from pytket.transform import Transform
from pytket.architecture import Architecture
from pytket.passes import DefaultMappingPass
from pytket.predicates import CompilationUnit

from .mps import CuTensorNetHandle, MPS
from .mps_gate import MPSxGate
Expand Down Expand Up @@ -120,7 +120,11 @@ def prepare_circuit(circuit: Circuit) -> tuple[Circuit, dict[Qubit, Qubit]]:
prep_circ = cu.circuit
Transform.DecomposeBRIDGE().apply(prep_circ)

qubit_map = {arch_q: orig_q for orig_q, arch_q in cu.final_map.items()}
qubit_map: dict[Qubit, Qubit] = {}
for orig_q, arch_q in cu.final_map.items():
assert isinstance(orig_q, Qubit)
assert isinstance(arch_q, Qubit)
qubit_map[arch_q] = orig_q

return (prep_circ, qubit_map)

Expand Down Expand Up @@ -190,6 +194,7 @@ def _get_sorted_gates(circuit: Circuit) -> list[Command]:
"nearest neighbour qubits. Consider using prepare_circuit().",
)
elif left_distance is None:
assert right_distance is not None
current_qubit = circuit.qubits[q_index + right_distance]
elif right_distance is None:
current_qubit = circuit.qubits[q_index - left_distance]
Expand Down
2 changes: 1 addition & 1 deletion pytket/extensions/cutensornet/tensor_network_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def _get_gate_tensors(self, adj: bool = False) -> DefaultDict[Any, List[Any]]:
self._logger.debug(f"Adding unitary: \n {com.op.get_unitary()}")
# Add a unitary for a gate pointing "upwards" (e.g. CX[1, 0])
if com.op.n_qubits > 1:
com_qix = [self._circuit.qubits.index(qb) for qb in com.args]
com_qix = [self._circuit.qubits.index(qb) for qb in com.qubits]
self._logger.debug(f"command qubit indices: {com_qix}")
com_qix_compressed = [i for i, _ in enumerate(com_qix)]
self._logger.debug(
Expand Down
7 changes: 4 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import pytest
import numpy as np
from scipy.stats import unitary_group # type: ignore
from pytket.circuit import Circuit, OpType, Unitary2qBox # type: ignore
from pytket.passes import DecomposeBoxes # type: ignore
from pytket.circuit import Circuit, OpType, Unitary2qBox
from pytket.passes import DecomposeBoxes


def random_line_circuit(n_qubits: int, layers: int) -> Circuit:
Expand All @@ -21,7 +21,8 @@ def random_line_circuit(n_qubits: int, layers: int) -> Circuit:
]
# Direction of each CX gate is random
for pair in qubit_pairs:
np.random.shuffle(pair)
if np.random.rand() > 0.5:
pair = [pair[1], pair[0]]

for pair in qubit_pairs:
c.CX(pair[0], pair[1])
Expand Down
4 changes: 2 additions & 2 deletions tests/test_mps.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,13 @@ def test_circ_approx_explicit(circuit: Circuit) -> None:
# Fixed virtual bond dimension
# Check for MPSxGate
mps_gate = simulate(libhandle, circuit, ContractionAlg.MPSxGate, chi=8)
assert np.isclose(mps_gate.fidelity, 0.05, atol=1e-2)
assert np.isclose(mps_gate.fidelity, 0.03, atol=1e-2)
assert mps_gate.is_valid()
assert np.isclose(mps_gate.vdot(mps_gate), 1.0, atol=mps_gate._atol)

# Check for MPSxMPO
mps_mpo = simulate(libhandle, circuit, ContractionAlg.MPSxMPO, chi=8)
assert np.isclose(mps_mpo.fidelity, 0.09, atol=1e-2)
assert np.isclose(mps_mpo.fidelity, 0.06, atol=1e-2)
assert mps_mpo.is_valid()
assert np.isclose(mps_mpo.vdot(mps_mpo), 1.0, atol=mps_mpo._atol)

Expand Down
6 changes: 3 additions & 3 deletions tests/test_tensor_network_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ def test_toffoli_box_with_implicit_swaps() -> None:
ket_circ = Circuit(3)

# Create the circuit
ket_circ.add_toffolibox(ToffoliBox(perm), [Qubit(0), Qubit(1)])
ket_circ.add_toffolibox(ToffoliBox(perm), [Qubit(1), Qubit(2)])
ket_circ.add_toffolibox(ToffoliBox(perm), [Qubit(0), Qubit(1)]) # type: ignore
ket_circ.add_toffolibox(ToffoliBox(perm), [Qubit(1), Qubit(2)]) # type: ignore

DecomposeBoxes().apply(ket_circ)
CnXPairwiseDecomposition().apply(ket_circ)
Expand Down Expand Up @@ -116,7 +116,7 @@ def to_bool_tuple(n_qubits: int, x: int) -> tuple:
perm[to_bool_tuple(n_qubits, orig)] = to_bool_tuple(n_qubits, dest)

# Create a circuit implementing the permutation above
ket_circ = ToffoliBox(perm).get_circuit()
ket_circ = ToffoliBox(perm).get_circuit() # type: ignore

DecomposeBoxes().apply(ket_circ)
CnXPairwiseDecomposition().apply(ket_circ)
Expand Down