Skip to content

Commit c5f502b

Browse files
[feature] Adding support for MPS simulation (#63)
* Adding an MPS simulator * Adding tests for MPS * Using non-destructive measurements * Added a reset method to MPS * Including MPS as a qsim backend for HybridEngine * Adding more bindings for initialisation that are needing for the tests * Allowing users to provide parameters for the MPS simulation from HybridEngine * Add HybridEngine tests for MPS
1 parent dc7b443 commit c5f502b

File tree

14 files changed

+916
-4
lines changed

14 files changed

+916
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ Certain simulators from `pecos.simulators` require external packages that are no
9999

100100
- `QuEST` is installed along with the python package `pyquest` when calling `pip install .[all]`. However, it uses 64-bit float point precision by default, and if you wish to make use of 32-bit float point precision you will need to follow the installation instructions provided by the developers [here](https://github.com/rrmeister/pyQuEST/tree/develop).
101101
- `CuStateVec` requires a Linux machine with an NVIDIA GPU (see requirements [here](https://docs.nvidia.com/cuda/cuquantum/latest/getting_started/getting_started.html#dependencies-custatevec-label)). PECOS' dependencies are specified in the `[cuda]` section of `pyproject.toml`, however, installation via `pip` is not reliable. The recommended method of installation is via `conda`, as discussed [here](https://docs.nvidia.com/cuda/cuquantum/latest/getting_started/getting_started.html#installing-cuquantum). Note that there might be conflicts between `conda` and `venv`; if you intend to use `CuStateVec`, you may follow the installation instructions for PECOS within a `conda` environment without involving the `venv` commands.
102+
- `MPS` uses `pytket-cutensornet` (see [repository](https://github.com/CQCL/pytket-cutensornet)) and can be installed via `pip install .[cuda]`. This simulators uses NVIDIA GPUs and cuQuantum. Unfortunately, installation of cuQuantum does not currently work via `pip`. Please follow the instructions specified above for `CuStateVec` to install cuQuantum.
102103

103104
## Uninstall
104105

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ cuda = [
6464
"cuquantum-python>=24.03.0",
6565
"custatevec>=1.6.0",
6666
"cupy>=10.4.0",
67+
"pytket-cutensornet>=0.7.0",
6768
]
6869
wasmtime = [
6970
"wasmtime>=13.0"

python/pecos/engines/hybrid_engine.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@
3232

3333

3434
class HybridEngine:
35-
"""A simulation engine which is capable of running noisy hybrid classical/quantum programs."""
35+
"""A simulation engine which is capable of running noisy hybrid classical/quantum programs.
36+
37+
Note:
38+
Parameters of the quantum simulator are provided as extra keyword arguments passed
39+
down to ``QuantumSimulator`` as the dictionary ``**params``.
40+
"""
3641

3742
def __init__(
3843
self,
@@ -41,6 +46,7 @@ def __init__(
4146
machine: Machine | None = None,
4247
error_model: ErrorModel | None = None,
4348
op_processor: OpProcessor | None = None,
49+
**params,
4450
) -> None:
4551
self.seed = None
4652

@@ -54,7 +60,7 @@ def __init__(
5460
if self.qsim is None:
5561
self.qsim = QuantumSimulator()
5662
elif isinstance(self.qsim, str):
57-
self.qsim = QuantumSimulator(self.qsim)
63+
self.qsim = QuantumSimulator(self.qsim, **params)
5864

5965
self.machine = machine
6066
if machine is None:

python/pecos/simulators/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,6 @@
5050
import cuquantum
5151

5252
from pecos.simulators.custatevec.state import CuStateVec # wrapper for cuQuantum's cuStateVec
53+
from pecos.simulators.mps_pytket import MPS # MPS implementation from pytket-cutensornet
5354
except ImportError:
5455
pass
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2024 The PECOS Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4+
# the License.You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
9+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
# specific language governing permissions and limitations under the License.
11+
12+
from pecos.simulators.mps_pytket import bindings
13+
from pecos.simulators.mps_pytket.state import MPS
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright 2024 The PECOS Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4+
# the License.You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
9+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
# specific language governing permissions and limitations under the License.
11+
12+
import pecos.simulators.mps_pytket.gates_one_qubit as one_q
13+
import pecos.simulators.mps_pytket.gates_two_qubit as two_q
14+
from pecos.simulators.mps_pytket.gates_init import init_one, init_zero
15+
from pecos.simulators.mps_pytket.gates_meas import meas_z
16+
17+
# Supporting gates from table:
18+
# https://github.com/CQCL/phir/blob/main/spec.md#table-ii---quantum-operations
19+
20+
gate_dict = {
21+
"Init": init_zero,
22+
"Init +Z": init_zero,
23+
"Init -Z": init_one,
24+
"init |0>": init_zero,
25+
"init |1>": init_one,
26+
"leak": init_zero,
27+
"leak |0>": init_zero,
28+
"leak |1>": init_one,
29+
"unleak |0>": init_zero,
30+
"unleak |1>": init_one,
31+
"Measure": meas_z,
32+
"measure Z": meas_z,
33+
"I": one_q.identity,
34+
"X": one_q.X,
35+
"Y": one_q.Y,
36+
"Z": one_q.Z,
37+
"RX": one_q.RX,
38+
"RY": one_q.RY,
39+
"RZ": one_q.RZ,
40+
"R1XY": one_q.R1XY,
41+
"RXY1Q": one_q.R1XY,
42+
"SX": one_q.SX,
43+
"SXdg": one_q.SXdg,
44+
"SqrtX": one_q.SX,
45+
"SqrtXd": one_q.SXdg,
46+
"SY": one_q.SY,
47+
"SYdg": one_q.SYdg,
48+
"SqrtY": one_q.SY,
49+
"SqrtYd": one_q.SYdg,
50+
"SZ": one_q.SZ,
51+
"SZdg": one_q.SZdg,
52+
"SqrtZ": one_q.SZ,
53+
"SqrtZd": one_q.SZdg,
54+
"H": one_q.H,
55+
"F": one_q.F,
56+
"Fdg": one_q.Fdg,
57+
"T": one_q.T,
58+
"Tdg": one_q.Tdg,
59+
"CX": two_q.CX,
60+
"CY": two_q.CY,
61+
"CZ": two_q.CZ,
62+
"RXX": two_q.RXX,
63+
"RYY": two_q.RYY,
64+
"RZZ": two_q.RZZ,
65+
"R2XXYYZZ": two_q.R2XXYYZZ,
66+
"SXX": two_q.SXX,
67+
"SXXdg": two_q.SXXdg,
68+
"SYY": two_q.SYY,
69+
"SYYdg": two_q.SYYdg,
70+
"SZZ": two_q.SZZ,
71+
"SqrtZZ": two_q.SZZ,
72+
"SZZdg": two_q.SZZdg,
73+
"SWAP": two_q.SWAP,
74+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2024 The PECOS Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4+
# the License.You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
9+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
# specific language governing permissions and limitations under the License.
11+
12+
from typing import Any
13+
14+
from pecos.simulators.mps_pytket.gates_meas import meas_z
15+
from pecos.simulators.mps_pytket.gates_one_qubit import X
16+
17+
18+
def init_zero(state, qubit: int, **params: Any) -> None:
19+
"""Initialise or reset the qubit to state |0>
20+
21+
Args:
22+
state: An instance of MPS
23+
qubit: The index of the qubit to be initialised
24+
"""
25+
result = meas_z(state, qubit)
26+
27+
if result != 0:
28+
X(state, qubit)
29+
30+
31+
def init_one(state, qubit: int, **params: Any) -> None:
32+
"""Initialise or reset the qubit to state |1>
33+
34+
Args:
35+
state: An instance of MPS
36+
qubit: The index of the qubit to be initialised
37+
"""
38+
result = meas_z(state, qubit)
39+
40+
if result != 1:
41+
X(state, qubit)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2024 The PECOS Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4+
# the License.You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
9+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
# specific language governing permissions and limitations under the License.
11+
12+
from typing import Any
13+
14+
from pytket import Qubit
15+
16+
17+
def meas_z(state, qubit: int, **params: Any) -> int:
18+
"""Measure in the Z-basis, collapse and normalise.
19+
20+
Notes:
21+
The number of qubits in the state remains the same.
22+
23+
Args:
24+
state: An instance of MPS
25+
qubit: The index of the qubit to be measured
26+
27+
Returns:
28+
The outcome of the measurement, either 0 or 1.
29+
"""
30+
if qubit >= state.num_qubits or qubit < 0:
31+
msg = f"Qubit {qubit} out of range."
32+
raise ValueError(msg)
33+
34+
result = state.mps.measure({Qubit(qubit)}, destructive=False)
35+
36+
return result[Qubit(qubit)]

0 commit comments

Comments
 (0)