Skip to content

Commit

Permalink
Merge pull request #44 from CQCL/feature/TKET-3469-rng-seed
Browse files Browse the repository at this point in the history
TKET-3469 Allow setting of RNG seed
  • Loading branch information
doug-q authored Aug 22, 2023
2 parents d86c7c2 + 1622df2 commit 675463d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
5 changes: 5 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
~~~~~~~~~

Unreleased
--------------------

* Allow setting of rng seed in qulacs backend.

0.29.0 (June 2023)
------------------

Expand Down
18 changes: 16 additions & 2 deletions pytket/extensions/qulacs/backends/qulacs_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
"""Methods to allow tket circuits to be ran on the Qulacs simulator
"""

from typing import List, Optional, Sequence, Union
from typing import List, Optional, Sequence, Union, cast
from logging import warning
from random import Random
from uuid import uuid4
import numpy as np
from sympy import Expr # type: ignore
Expand Down Expand Up @@ -181,6 +182,9 @@ def process_circuits(
if valid_check:
self._check_all_circuits(circuits, nomeasure_warn=False)

seed = cast(Optional[int], kwargs.get("seed"))
rng = Random(seed) if seed else None

handle_list = []
for circuit, n_shots_circ in zip(circuits, n_shots_list):
qulacs_state = self._sim(circuit.n_qubits)
Expand All @@ -205,7 +209,9 @@ def process_circuits(
else:
bits, choose_indices = zip(*bits2index)

samples = qulacs_state.sampling(n_shots_circ)
samples = self._sample_quantum_state(
qulacs_state, n_shots_circ, rng
)
shots = OutcomeArray.from_ints(samples, circuit.n_qubits)
shots = shots.choose_indices(choose_indices)
try:
Expand All @@ -228,6 +234,14 @@ def process_circuits(
del qulacs_circ
return handle_list

def _sample_quantum_state(
self, quantum_state: QuantumState, n_shots: int, rng: Optional[Random]
) -> List[int]:
if rng:
return quantum_state.sampling(n_shots, rng.randint(0, 2**32 - 1))
else:
return quantum_state.sampling(n_shots)

def circuit_status(self, handle: ResultHandle) -> CircuitStatus:
if handle in self._cache:
return CircuitStatus(StatusEnum.COMPLETED)
Expand Down
31 changes: 28 additions & 3 deletions tests/test_qulacs_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,51 @@
# limitations under the License.

from collections import Counter
from typing import List, Sequence, Union, Optional
import warnings
import math
from hypothesis import given, strategies
import numpy as np
import pytest
from openfermion.ops import QubitOperator # type: ignore
from openfermion.linalg import eigenspectrum # type: ignore
from pytket.backends import ResultHandle
from pytket.circuit import Circuit, BasisOrder, OpType, Qubit # type: ignore
from pytket.pauli import Pauli, QubitPauliString # type: ignore
from pytket.passes import CliffordSimp # type: ignore
from pytket.utils.operators import QubitPauliOperator
from pytket.utils.results import KwargTypes
from pytket.extensions.qulacs import QulacsBackend

backends = [QulacsBackend()]

def make_seeded_QulacsBackend(base: type[QulacsBackend]) -> type:
class SeededQulacsBackend(base): # type: ignore
def __init__(self, seed: int):
base.__init__(self)
self._seed = seed

def process_circuits(
self,
circuits: Sequence[Circuit],
n_shots: Union[None, int, Sequence[Optional[int]]] = None,
valid_check: bool = True,
**kwargs: KwargTypes
) -> List[ResultHandle]:
if not "seed" in kwargs:
kwargs["seed"] = self._seed
return base.process_circuits(self, circuits, n_shots, valid_check, **kwargs)

return SeededQulacsBackend


backends = [QulacsBackend(), make_seeded_QulacsBackend(QulacsBackend)(-1)]

try:
from pytket.extensions.qulacs import QulacsGPUBackend

backends.append(QulacsGPUBackend())
backends.extend(
[QulacsGPUBackend(), make_seeded_QulacsBackend(QulacsGPUBackend)(1)]
)
except ImportError:
warnings.warn("local settings failed to import QulacsGPUBackend", ImportWarning)

Expand Down Expand Up @@ -266,7 +292,6 @@ def test_shots_bits_edgecases(n_shots, n_bits) -> None:
c = Circuit(n_bits, n_bits)

for qulacs_backend in backends:

# TODO TKET-813 add more shot based backends and move to integration tests
h = qulacs_backend.process_circuit(c, n_shots)
res = qulacs_backend.get_result(h)
Expand Down

0 comments on commit 675463d

Please sign in to comment.