Skip to content

Commit

Permalink
Merge pull request #84 from zapatacomputing/add-reset-gate
Browse files Browse the repository at this point in the history
Add reset gate
  • Loading branch information
Athena Caesura authored Jul 3, 2023
2 parents ecb2726 + 39d516a commit 72a4007
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 7 deletions.
3 changes: 2 additions & 1 deletion src/orquestra/quantum/circuits/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
RY,
RZ,
SWAP,
SX,
U3,
XX,
XY,
Expand Down Expand Up @@ -204,5 +205,5 @@
to_dict,
)
from ._testing import create_random_circuit
from ._wavefunction_operations import MultiPhaseOperation
from ._wavefunction_operations import MultiPhaseOperation, ResetOperation
from .symbolic import natural_key, natural_key_revlex
2 changes: 1 addition & 1 deletion src/orquestra/quantum/circuits/_builtin_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ def builtin_gate_by_name(name) -> GateRef:
"I", _matrices.i_matrix, (), 1, is_hermitian=True
)
S = _gates.MatrixFactoryGate("S", _matrices.s_matrix, (), 1)
SX = _gates.MatrixFactoryGate("SX", _matrices.sx_matrix, (), 1)
T = _gates.MatrixFactoryGate("T", _matrices.t_matrix, (), 1)


# --- parametric, single qubit gates ---


Expand Down
13 changes: 10 additions & 3 deletions src/orquestra/quantum/circuits/_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,16 @@ def to_unitary(self) -> Union[np.ndarray, sympy.Matrix]:
"""
# The `reversed` iterator reflects the fact the matrices are multiplied
# when composing linear operations (i.e. first operation is the rightmost).
lifted_matrices = [
op.lifted_matrix(self.n_qubits) for op in reversed(self.operations)
]
lifted_matrices = []
for op in reversed(self.operations):
if isinstance(op, _gates.GateOperation):
lifted_matrices += [op.lifted_matrix(self.n_qubits)]
else:
raise ValueError(
f"Operation {op} is not a gate operation and so circuit cannot"
"be converted to a unitary matrix."
)

return reduce(operator.matmul, lifted_matrices)

def bind(self, symbols_map: Dict[sympy.Symbol, Any]):
Expand Down
12 changes: 12 additions & 0 deletions src/orquestra/quantum/circuits/_matrices.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ def t_matrix():
)


def sx_matrix():
return sympy.Matrix(
[
[(1 + 1j) / 2, (1 - 1j) / 2],
[(1 - 1j) / 2, (1 + 1j) / 2],
]
)


# --- gates with a single param ---


Expand Down Expand Up @@ -253,6 +262,9 @@ def ms_matrix(phi_0, phi_1):
)


# --- misc ---


def delay_matrix(_duration):
# Note that _duration parameter is not used when constructing the
# matrix, because Delay always acts as identity.
Expand Down
32 changes: 31 additions & 1 deletion src/orquestra/quantum/circuits/_wavefunction_operations.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
################################################################################
# © Copyright 2021-2022 Zapata Computing Inc.
################################################################################
from dataclasses import dataclass
from dataclasses import dataclass, replace
from functools import singledispatch
from numbers import Complex
from typing import Iterable, Tuple
Expand Down Expand Up @@ -86,3 +86,33 @@ def free_symbols(self) -> Iterable[sympy.Symbol]:
gate has one free symbol, `alpha`
"""
return get_free_symbols(self.params)


@dataclass
class ResetOperation:
"""Operation resetting a given qubit to the |0> state.
Cannot be implmented in orquestra because the result would not be a valid
wavefunction. However we include it to perform circuit conversions."""

params: Tuple[Parameter, ...] = ()

def __init__(self, qubit_index: int):
self.qubit_indices = (qubit_index,)

def bind(self, symbols_map) -> "ResetOperation":
return self.replace_params(
tuple(sub_symbols(param, symbols_map) for param in self.params)
)

def replace_params(self, new_params: Tuple[Parameter, ...]) -> "ResetOperation":
return replace(self, params=new_params)

def apply(self, amplitude_vector: ParameterizedVector) -> ParameterizedVector:
raise RuntimeError(
"ResetOperation.apply is not implemented because the result would not be "
"a valid wavefunction."
)

@property
def free_symbols(self) -> Iterable[sympy.Symbol]:
return get_free_symbols(self.params)
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
Y = sympy.Matrix([[0, -sympy.I], [sympy.I, 0]])
Z = sympy.Matrix([[1, 0], [0, -1]])
S = sympy.Matrix([[1, 0], [0, sympy.I]])
SX = sympy.Matrix(
[
[(1 + sympy.I) / 2, (1 - sympy.I) / 2],
[(1 - sympy.I) / 2, (1 + sympy.I) / 2],
]
)
T = sympy.Matrix([[1, 0], [0, (1 + sympy.I) / sympy.sqrt(2)]])

CNOT = sympy.Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
Expand Down Expand Up @@ -322,6 +328,7 @@ def main():
generate_cases_1_qubit_exp_vals(Z, "Z")
generate_cases_1_qubit_exp_vals(H, "H")
generate_cases_1_qubit_exp_vals(S, "S")
generate_cases_1_qubit_exp_vals(SX, "SX")
generate_cases_1_qubit_exp_vals(T, "T")
print("-" * 10)
print("2 qubit gates")
Expand Down
1 change: 1 addition & 0 deletions tests/orquestra/quantum/circuits/_builtin_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class TestBuiltinGatesProperties:
_builtin_gates.T,
_builtin_gates.H,
_builtin_gates.S,
_builtin_gates.SX,
_builtin_gates.SWAP,
_builtin_gates.ISWAP,
_builtin_gates.RX(0.5),
Expand Down
1 change: 1 addition & 0 deletions tests/orquestra/quantum/circuits/_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
_builtin_gates.T,
_builtin_gates.H,
_builtin_gates.I,
_builtin_gates.SX,
_builtin_gates.RX(sympy.Symbol("theta")),
_builtin_gates.RY(0.5),
_builtin_gates.RZ(0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pytest
import sympy

from orquestra.quantum.circuits import MultiPhaseOperation
from orquestra.quantum.circuits import Circuit, H, MultiPhaseOperation, ResetOperation


class TestMultiPhaseOperation:
Expand Down Expand Up @@ -156,3 +156,16 @@ def test_free_symbols_in_parameters_are_correctly_reported(
):
operation = MultiPhaseOperation(params)
assert operation.free_symbols == expected_free_symbols


class TestResetOperation:
def test_apply_throws_error(self):
wavefunction = np.array([1, 0, 0, 0])
operation = ResetOperation(1)
with pytest.raises(RuntimeError):
operation.apply(wavefunction)

def test_reset_operation_in_circuit(self):
circuit = Circuit([H(0), ResetOperation(0)])
with pytest.raises(ValueError):
circuit.to_unitary()

0 comments on commit 72a4007

Please sign in to comment.