Skip to content

Commit

Permalink
Merge pull request #30 from CQCL/main
Browse files Browse the repository at this point in the history
  • Loading branch information
PabloAndresCQ authored Sep 22, 2023
2 parents 2680f32 + 972bed6 commit 0ad57f6
Show file tree
Hide file tree
Showing 10 changed files with 34 additions and 21 deletions.
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

0 comments on commit 0ad57f6

Please sign in to comment.