Skip to content

Commit

Permalink
Move PauliString to ops module (#717)
Browse files Browse the repository at this point in the history
  • Loading branch information
cduck authored Jul 19, 2018
1 parent 6c439ed commit 155bdcf
Show file tree
Hide file tree
Showing 17 changed files with 822 additions and 798 deletions.
5 changes: 5 additions & 0 deletions cirq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@
ReversibleCompositeGate,
ReversibleEffect,
ParameterizableEffect,
Pauli,
CliffordGate,
PauliTransform,
PauliInteractionGate,
PauliString,
PhaseableEffect,
QasmConvertableGate,
QasmConvertableOperation,
Expand Down
13 changes: 0 additions & 13 deletions cirq/contrib/paulistring/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from cirq.contrib.paulistring.pauli import (
Pauli,
)
from cirq.contrib.paulistring.clifford_gate import (
CliffordGate,
PauliTransform,
)
from cirq.contrib.paulistring.pauli_interaction_gate import (
PauliInteractionGate,
)
from cirq.contrib.paulistring.pauli_string import (
PauliString,
)
from cirq.contrib.paulistring.pauli_string_raw_types import (
PauliStringGateOperation,
)
Expand Down
11 changes: 5 additions & 6 deletions cirq/contrib/paulistring/pauli_string_phasor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@

from cirq import ops, value, study, extension

from cirq.contrib.paulistring import (
Pauli,
CliffordGate,
PauliString,
PauliStringGateOperation,
)
from cirq.ops.pauli import Pauli
from cirq.ops.clifford_gate import CliffordGate
from cirq.ops.pauli_string import PauliString
from cirq.contrib.paulistring.pauli_string_raw_types import (
PauliStringGateOperation)


T_DESIRED = TypeVar('T_DESIRED')
Expand Down
183 changes: 95 additions & 88 deletions cirq/contrib/paulistring/pauli_string_phasor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@
import numpy as np

import cirq

from cirq.contrib.paulistring import (
Pauli,
PauliString,
PauliStringPhasor,
)
from cirq.contrib.paulistring import PauliStringPhasor


def _make_qubits(n):
Expand All @@ -32,14 +27,17 @@ def _make_qubits(n):
def test_eq_ne_hash():
q0, q1, q2 = _make_qubits(3)
eq = cirq.testing.EqualsTester()
ps1 = PauliString({q0: Pauli.X, q1: Pauli.Y, q2: Pauli.Z})
ps2 = PauliString({q0: Pauli.X, q1: Pauli.Y, q2: Pauli.X})
ps1 = cirq.PauliString({q0: cirq.Pauli.X, q1: cirq.Pauli.Y,
q2: cirq.Pauli.Z})
ps2 = cirq.PauliString({q0: cirq.Pauli.X, q1: cirq.Pauli.Y,
q2: cirq.Pauli.X})
eq.make_equality_group(
lambda: PauliStringPhasor(PauliString({}), half_turns=0.5),
lambda: PauliStringPhasor(PauliString({}), half_turns=-1.5),
lambda: PauliStringPhasor(PauliString({}), half_turns=2.5))
lambda: PauliStringPhasor(cirq.PauliString({}), half_turns=0.5),
lambda: PauliStringPhasor(cirq.PauliString({}), half_turns=-1.5),
lambda: PauliStringPhasor(cirq.PauliString({}), half_turns=2.5))
eq.make_equality_group(
lambda: PauliStringPhasor(PauliString({}, True), half_turns=-0.5))
lambda: PauliStringPhasor(cirq.PauliString({}, True),
half_turns=-0.5))
eq.add_equality_group(
PauliStringPhasor(ps1),
PauliStringPhasor(ps1, half_turns=1))
Expand All @@ -61,48 +59,53 @@ def test_eq_ne_hash():
def test_map_qubits():
q0, q1, q2, q3 = _make_qubits(4)
qubit_map = {q1: q2, q0: q3}
before = PauliStringPhasor(PauliString({q0: Pauli.Z, q1: Pauli.Y}),
half_turns=0.1)
after = PauliStringPhasor(PauliString({q3: Pauli.Z, q2: Pauli.Y}),
half_turns=0.1)
before = PauliStringPhasor(
cirq.PauliString({q0: cirq.Pauli.Z, q1: cirq.Pauli.Y}),
half_turns=0.1)
after = PauliStringPhasor(
cirq.PauliString({q3: cirq.Pauli.Z, q2: cirq.Pauli.Y}),
half_turns=0.1)
assert before.map_qubits(qubit_map) == after


def test_extrapolate_effect():
op1 = PauliStringPhasor(PauliString({}), half_turns=0.5)
op2 = PauliStringPhasor(PauliString({}), half_turns=1.5)
op3 = PauliStringPhasor(PauliString({}), half_turns=0.125)
op1 = PauliStringPhasor(cirq.PauliString({}), half_turns=0.5)
op2 = PauliStringPhasor(cirq.PauliString({}), half_turns=1.5)
op3 = PauliStringPhasor(cirq.PauliString({}), half_turns=0.125)
assert op1 ** 3 == op2
assert op1 ** 0.25 == op3


def test_extrapolate_effect_with_symbol():
eq = cirq.testing.EqualsTester()
eq.add_equality_group(
PauliStringPhasor(PauliString({}), half_turns=cirq.value.Symbol('a')),
PauliStringPhasor(PauliString({})) ** cirq.value.Symbol('a'))
PauliStringPhasor(cirq.PauliString({}),
half_turns=cirq.value.Symbol('a')),
PauliStringPhasor(cirq.PauliString({})) ** cirq.value.Symbol('a'))
eq.add_equality_group(
PauliStringPhasor(PauliString({})) ** cirq.value.Symbol('b'))
PauliStringPhasor(cirq.PauliString({})) ** cirq.value.Symbol('b'))
with pytest.raises(ValueError):
_ = PauliStringPhasor(PauliString({}), half_turns=0.5
_ = PauliStringPhasor(cirq.PauliString({}), half_turns=0.5
) ** cirq.value.Symbol('b')
with pytest.raises(ValueError):
_ = PauliStringPhasor(PauliString({}), half_turns=cirq.value.Symbol('a')
_ = PauliStringPhasor(cirq.PauliString({}),
half_turns=cirq.value.Symbol('a')
) ** 0.5
with pytest.raises(ValueError):
_ = PauliStringPhasor(PauliString({}), half_turns=cirq.value.Symbol('a')
_ = PauliStringPhasor(cirq.PauliString({}),
half_turns=cirq.value.Symbol('a')
) ** cirq.value.Symbol('b')


def test_inverse():
op1 = PauliStringPhasor(PauliString({}), half_turns=0.25)
op2 = PauliStringPhasor(PauliString({}), half_turns=-0.25)
op1 = PauliStringPhasor(cirq.PauliString({}), half_turns=0.25)
op2 = PauliStringPhasor(cirq.PauliString({}), half_turns=-0.25)
assert op1.inverse() == op2


def test_try_cast_to():
class Dummy: pass
op = PauliStringPhasor(PauliString({}))
op = PauliStringPhasor(cirq.PauliString({}))
ext = cirq.Extensions()
assert not op.try_cast_to(cirq.CompositeOperation, ext) is None
assert not op.try_cast_to(cirq.BoundedEffect, ext) is None
Expand All @@ -111,7 +114,8 @@ class Dummy: pass
assert not op.try_cast_to(cirq.ReversibleEffect, ext) is None
assert op.try_cast_to(Dummy, ext) is None

op = PauliStringPhasor(PauliString({}), half_turns=cirq.value.Symbol('a'))
op = PauliStringPhasor(cirq.PauliString({}),
half_turns=cirq.value.Symbol('a'))
ext = cirq.Extensions()
assert not op.try_cast_to(cirq.CompositeOperation, ext) is None
assert not op.try_cast_to(cirq.BoundedEffect, ext) is None
Expand All @@ -123,32 +127,33 @@ class Dummy: pass


def test_is_parametrized():
op = PauliStringPhasor(PauliString({}))
op = PauliStringPhasor(cirq.PauliString({}))
assert not op.is_parameterized()
assert not (op ** 0.1).is_parameterized()
assert (op ** cirq.value.Symbol('a')).is_parameterized()


def test_with_parameters_resolved_by():
op = PauliStringPhasor(PauliString({}), half_turns=cirq.value.Symbol('a'))
op = PauliStringPhasor(cirq.PauliString({}),
half_turns=cirq.value.Symbol('a'))
resolver = cirq.study.ParamResolver({'a': 0.1})
actual = op.with_parameters_resolved_by(resolver)
expected = PauliStringPhasor(PauliString({}), half_turns=0.1)
expected = PauliStringPhasor(cirq.PauliString({}), half_turns=0.1)
assert actual == expected


def test_drop_negligible():
q0, = _make_qubits(1)
sym = cirq.value.Symbol('a')
circuit = cirq.Circuit.from_ops(
PauliStringPhasor(PauliString({q0: Pauli.Z})) ** 0.25,
PauliStringPhasor(PauliString({q0: Pauli.Z})) ** 1e-10,
PauliStringPhasor(PauliString({q0: Pauli.Z})) ** sym,
)
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z})) ** 0.25,
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z})) ** 1e-10,
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z})) ** sym,
)
expected = cirq.Circuit.from_ops(
PauliStringPhasor(PauliString({q0: Pauli.Z})) ** 0.25,
PauliStringPhasor(PauliString({q0: Pauli.Z})) ** sym,
)
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z})) ** 0.25,
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z})) ** sym,
)
cirq.DropNegligible().optimize_circuit(circuit)
cirq.DropEmptyMoments().optimize_circuit(circuit)
assert circuit == expected
Expand All @@ -158,34 +163,34 @@ def test_manual_default_decompose():
q0, q1, q2 = _make_qubits(3)

mat = cirq.Circuit.from_ops(
PauliStringPhasor(PauliString({q0: Pauli.Z})) ** 0.25,
cirq.Z(q0) ** -0.25,
).to_unitary_matrix()
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z})) ** 0.25,
cirq.Z(q0) ** -0.25,
).to_unitary_matrix()
cirq.testing.assert_allclose_up_to_global_phase(mat, np.eye(2),
rtol=1e-7, atol=1e-7)

mat = cirq.Circuit.from_ops(
PauliStringPhasor(PauliString({q0: Pauli.Y})) ** 0.25,
cirq.Y(q0) ** -0.25,
).to_unitary_matrix()
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Y})) ** 0.25,
cirq.Y(q0) ** -0.25,
).to_unitary_matrix()
cirq.testing.assert_allclose_up_to_global_phase(mat, np.eye(2),
rtol=1e-7, atol=1e-7)

mat = cirq.Circuit.from_ops(
PauliStringPhasor(PauliString({q0: Pauli.Z,
q1: Pauli.Z,
q2: Pauli.Z}))
).to_unitary_matrix()
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z,
q1: cirq.Pauli.Z,
q2: cirq.Pauli.Z}))
).to_unitary_matrix()
cirq.testing.assert_allclose_up_to_global_phase(
mat,
np.diag([1, -1, -1, 1, -1, 1, 1, -1]),
rtol=1e-7, atol=1e-7)

mat = cirq.Circuit.from_ops(
PauliStringPhasor(PauliString({q0: Pauli.Z,
q1: Pauli.Y,
q2: Pauli.X})) ** 0.5
).to_unitary_matrix()
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q2: cirq.Pauli.X})) ** 0.5
).to_unitary_matrix()
cirq.testing.assert_allclose_up_to_global_phase(
mat,
np.array([
Expand All @@ -203,23 +208,23 @@ def test_manual_default_decompose():

@pytest.mark.parametrize('paulis,half_turns,neg',
itertools.product(
itertools.product(Pauli.XYZ + (None,), repeat=3),
itertools.product(cirq.Pauli.XYZ + (None,), repeat=3),
(0, 0.1, 0.5, 1, -0.25),
(False, True)))
def test_default_decompose(paulis, half_turns, neg):
paulis = [pauli for pauli in paulis if pauli is not None]
qubits = _make_qubits(len(paulis))

# Get matrix from decomposition
pauli_string = PauliString({q: p for q, p in zip(qubits, paulis)}, neg)
pauli_string = cirq.PauliString({q: p for q, p in zip(qubits, paulis)}, neg)
actual = cirq.Circuit.from_ops(
PauliStringPhasor(pauli_string, half_turns=half_turns)
).to_unitary_matrix()
PauliStringPhasor(pauli_string, half_turns=half_turns)
).to_unitary_matrix()

# Calculate expected matrix
to_z_mats = {Pauli.X: (cirq.Y ** -0.5).matrix(),
Pauli.Y: (cirq.X ** 0.5).matrix(),
Pauli.Z: np.eye(2)}
to_z_mats = {cirq.Pauli.X: (cirq.Y ** -0.5).matrix(),
cirq.Pauli.Y: (cirq.X ** 0.5).matrix(),
cirq.Pauli.Z: np.eye(2)}
expected_convert = np.eye(1)
for pauli in paulis:
expected_convert = np.kron(expected_convert, to_z_mats[pauli])
Expand All @@ -233,13 +238,13 @@ def test_default_decompose(paulis, half_turns, neg):

def test_decompose_with_symbol():
q0, = _make_qubits(1)
ps = PauliString({q0: Pauli.Y})
ps = cirq.PauliString({q0: cirq.Pauli.Y})
op = PauliStringPhasor(ps, half_turns=cirq.value.Symbol('a'))
circuit = cirq.Circuit.from_ops(op)
cirq.ExpandComposite().optimize_circuit(circuit)
assert circuit.to_text_diagram() == "q0: ───X^0.5───Z^a───X^-0.5───"

ps = PauliString({q0: Pauli.Y}, True)
ps = cirq.PauliString({q0: cirq.Pauli.Y}, True)
op = PauliStringPhasor(ps, half_turns=cirq.value.Symbol('a'))
circuit = cirq.Circuit.from_ops(op)
cirq.ExpandComposite().optimize_circuit(circuit)
Expand All @@ -249,21 +254,21 @@ def test_decompose_with_symbol():
def test_text_diagram():
q0, q1, q2 = _make_qubits(3)
circuit = cirq.Circuit.from_ops(
PauliStringPhasor(PauliString({q0: Pauli.Z})),
PauliStringPhasor(PauliString({q0: Pauli.Y})) ** 0.25,
PauliStringPhasor(PauliString({q0: Pauli.Z,
q1: Pauli.Z,
q2: Pauli.Z})),
PauliStringPhasor(PauliString({q0: Pauli.Z,
q1: Pauli.Y,
q2: Pauli.X}, True)) ** 0.5,
PauliStringPhasor(PauliString({q0: Pauli.Z,
q1: Pauli.Y,
q2: Pauli.X}),
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z})),
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Y})) ** 0.25,
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z,
q1: cirq.Pauli.Z,
q2: cirq.Pauli.Z})),
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q2: cirq.Pauli.X}, True)) ** 0.5,
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q2: cirq.Pauli.X}),
half_turns=cirq.value.Symbol('a')),
PauliStringPhasor(PauliString({q0: Pauli.Z,
q1: Pauli.Y,
q2: Pauli.X}, True),
PauliStringPhasor(cirq.PauliString({q0: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q2: cirq.Pauli.X}, True),
half_turns=cirq.value.Symbol('b')))
assert circuit.to_text_diagram() == """
q0: ───[Z]───[Y]^0.25───[Z]───[Z]────────[Z]─────[Z]──────
Expand All @@ -276,27 +281,29 @@ def test_text_diagram():

def test_repr():
q0, q1, q2 = _make_qubits(3)
ps = PauliStringPhasor(PauliString({q2: Pauli.Z,
q1: Pauli.Y,
q0: Pauli.X})) ** 0.5
ps = PauliStringPhasor(cirq.PauliString({q2: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q0: cirq.Pauli.X})) ** 0.5
assert (repr(ps) ==
'PauliStringPhasor({+, q0:X, q1:Y, q2:Z}, half_turns=0.5)')

ps = PauliStringPhasor(PauliString({q2: Pauli.Z,
q1: Pauli.Y,
q0: Pauli.X}, True)) ** -0.5
ps = PauliStringPhasor(cirq.PauliString({q2: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q0: cirq.Pauli.X}, True)
) ** -0.5
assert (repr(ps) ==
'PauliStringPhasor({-, q0:X, q1:Y, q2:Z}, half_turns=-0.5)')


def test_str():
q0, q1, q2 = _make_qubits(3)
ps = PauliStringPhasor(PauliString({q2: Pauli.Z,
q1: Pauli.Y,
q0: Pauli.X}, False)) ** 0.5
ps = PauliStringPhasor(cirq.PauliString({q2: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q0: cirq.Pauli.X}, False)
) ** 0.5
assert (str(ps) == '{+, q0:X, q1:Y, q2:Z}**0.5')

ps = PauliStringPhasor(PauliString({q2: Pauli.Z,
q1: Pauli.Y,
q0: Pauli.X}, True)) ** -0.5
ps = PauliStringPhasor(cirq.PauliString({q2: cirq.Pauli.Z,
q1: cirq.Pauli.Y,
q0: cirq.Pauli.X}, True)) ** -0.5
assert (str(ps) == '{-, q0:X, q1:Y, q2:Z}**-0.5')
2 changes: 1 addition & 1 deletion cirq/contrib/paulistring/pauli_string_raw_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from cirq import ops, abc

from cirq.contrib.paulistring import PauliString
from cirq.ops.pauli_string import PauliString


TSelf_PauliStringGateOperation = TypeVar('TSelf_PauliStringGateOperation',
Expand Down
Loading

0 comments on commit 155bdcf

Please sign in to comment.