Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate Cirq-FT module in favour of Qualtran #6362

Merged
merged 4 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 10 additions & 2 deletions cirq-ft/cirq_ft/algos/and_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import itertools
import random
import sys
from typing import List, Tuple

import cirq
Expand All @@ -23,11 +22,13 @@
import pytest
from cirq_ft import infra
from cirq_ft.infra.jupyter_tools import execute_notebook
from cirq_ft.deprecation import allow_deprecated_cirq_ft_use_in_tests

random.seed(12345)


@pytest.mark.parametrize("cv", [(0, 0), (0, 1), (1, 0), (1, 1)])
@allow_deprecated_cirq_ft_use_in_tests
def test_and_gate(cv: Tuple[int, int]):
c1, c2, t = cirq.LineQubit.range(3)
input_states = [(0, 0, 0), (0, 1, 0), (1, 0, 0), (1, 1, 0)]
Expand All @@ -44,6 +45,7 @@ def random_cv(n: int) -> List[int]:


@pytest.mark.parametrize("cv", [[1] * 3, random_cv(5), random_cv(6), random_cv(7)])
@allow_deprecated_cirq_ft_use_in_tests
def test_multi_controlled_and_gate(cv: List[int]):
gate = cirq_ft.And(cv)
r = gate.signature
Expand Down Expand Up @@ -77,6 +79,7 @@ def test_multi_controlled_and_gate(cv: List[int]):
)


@allow_deprecated_cirq_ft_use_in_tests
def test_and_gate_diagram():
gate = cirq_ft.And((1, 0, 1, 0, 1, 0))
qubit_regs = infra.get_named_qubits(gate.signature)
Expand Down Expand Up @@ -186,13 +189,15 @@ def test_and_gate_diagram():
((1, 0, 1), True, "And†(1, 0, 1)"),
],
)
@allow_deprecated_cirq_ft_use_in_tests
def test_and_gate_str_and_repr(cv, adjoint, str_output):
gate = cirq_ft.And(cv, adjoint=adjoint)
assert str(gate) == str_output
cirq.testing.assert_equivalent_repr(gate, setup_code="import cirq_ft\n")


@pytest.mark.parametrize("cv", [(0, 0), (0, 1), (1, 0), (1, 1)])
@allow_deprecated_cirq_ft_use_in_tests
def test_and_gate_adjoint(cv: Tuple[int, int]):
c1, c2, t = cirq.LineQubit.range(3)
all_cvs = [(0, 0), (0, 1), (1, 0), (1, 1)]
Expand All @@ -204,7 +209,7 @@ def test_and_gate_adjoint(cv: Tuple[int, int]):
cirq_ft.testing.assert_circuit_inp_out_cirqsim(circuit, [c1, c2, t], inp, out)


@pytest.mark.skipif(sys.platform != "linux", reason="Linux-only test")
@pytest.mark.skip(reason="Cirq-FT is deprecated, use Qualtran instead.")
def test_notebook():
execute_notebook('and_gate')

Expand All @@ -213,16 +218,19 @@ def test_notebook():
"cv", [*itertools.chain(*[itertools.product(range(2), repeat=n) for n in range(2, 7 + 1)])]
)
@pytest.mark.parametrize("adjoint", [*range(2)])
@allow_deprecated_cirq_ft_use_in_tests
def test_t_complexity(cv, adjoint):
gate = cirq_ft.And(cv=cv, adjoint=adjoint)
cirq_ft.testing.assert_decompose_is_consistent_with_t_complexity(gate)


@allow_deprecated_cirq_ft_use_in_tests
def test_and_gate_raises():
with pytest.raises(ValueError, match="at-least 2 control values"):
_ = cirq_ft.And(cv=(1,))


@allow_deprecated_cirq_ft_use_in_tests
def test_and_gate_power():
cv = (1, 0)
and_gate = cirq_ft.And(cv)
Expand Down
7 changes: 5 additions & 2 deletions cirq-ft/cirq_ft/algos/apply_gate_to_lth_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@ class ApplyGateToLthQubit(unary_iteration_gate.UnaryIterationGate):
)
nth_gate: Callable[..., cirq.Gate]
control_regs: Tuple[infra.Register, ...] = attr.field(
converter=lambda v: (v,) if isinstance(v, infra.Register) else tuple(v),
default=(infra.Register('control', 1),),
converter=lambda v: (v,) if isinstance(v, infra.Register) else tuple(v)
)

@control_regs.default
def control_regs_default(self):
return (infra.Register('control', 1),)

@classmethod
def make_on(
cls, *, nth_gate: Callable[..., cirq.Gate], **quregs: Sequence[cirq.Qid]
Expand Down
8 changes: 5 additions & 3 deletions cirq-ft/cirq_ft/algos/apply_gate_to_lth_target_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import sys

import cirq
import cirq_ft
import pytest
from cirq_ft import infra
from cirq_ft.infra.bit_tools import iter_bits
from cirq_ft.infra.jupyter_tools import execute_notebook
from cirq_ft.deprecation import allow_deprecated_cirq_ft_use_in_tests


@pytest.mark.parametrize("selection_bitsize,target_bitsize", [[3, 5], [3, 7], [4, 5]])
@allow_deprecated_cirq_ft_use_in_tests
def test_apply_gate_to_lth_qubit(selection_bitsize, target_bitsize):
greedy_mm = cirq.GreedyQubitManager(prefix="_a", maximize_reuse=True)
gate = cirq_ft.ApplyGateToLthQubit(
Expand Down Expand Up @@ -51,6 +51,7 @@ def test_apply_gate_to_lth_qubit(selection_bitsize, target_bitsize):
)


@allow_deprecated_cirq_ft_use_in_tests
def test_apply_gate_to_lth_qubit_diagram():
# Apply Z gate to all odd targets and Identity to even targets.
gate = cirq_ft.ApplyGateToLthQubit(
Expand Down Expand Up @@ -87,6 +88,7 @@ def test_apply_gate_to_lth_qubit_diagram():
)


@allow_deprecated_cirq_ft_use_in_tests
def test_apply_gate_to_lth_qubit_make_on():
gate = cirq_ft.ApplyGateToLthQubit(
cirq_ft.SelectionRegister('selection', 3, 5),
Expand All @@ -103,6 +105,6 @@ def test_apply_gate_to_lth_qubit_make_on():
assert op.gate.control_regs == op2.gate.control_regs


@pytest.mark.skipif(sys.platform != "linux", reason="Linux-only test")
@pytest.mark.skip(reason="Cirq-FT is deprecated, use Qualtran instead.")
def test_notebook():
execute_notebook('apply_gate_to_lth_target')
6 changes: 6 additions & 0 deletions cirq-ft/cirq_ft/algos/arithmetic_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@

from cirq_ft import infra
from cirq_ft.algos import and_gate
from cirq_ft.deprecation import deprecated_cirq_ft_class


@deprecated_cirq_ft_class()
@attr.frozen
class LessThanGate(cirq.ArithmeticGate):
"""Applies U_a|x>|z> = |x> |z ^ (x < a)>"""
Expand Down Expand Up @@ -297,6 +299,7 @@ def _equality_with_zero(
yield and_gate.And(cv=[0] * len(qubits)).on(*qubits, *ancilla, z)


@deprecated_cirq_ft_class()
@attr.frozen
class LessThanEqualGate(cirq.ArithmeticGate):
"""Applies U|x>|y>|z> = |x>|y> |z ^ (x <= y)>"""
Expand Down Expand Up @@ -454,6 +457,7 @@ def _has_unitary_(self):
return True


@deprecated_cirq_ft_class()
@attr.frozen
class ContiguousRegisterGate(cirq.ArithmeticGate):
"""Applies U|x>|y>|0> -> |x>|y>|x(x-1)/2 + y>
Expand Down Expand Up @@ -530,6 +534,7 @@ def __pow__(self, power: int):
return NotImplemented # pragma: no cover


@deprecated_cirq_ft_class()
@attr.frozen
class AdditionGate(cirq.ArithmeticGate):
"""Applies U|p>|q> -> |p>|p+q>.
Expand Down Expand Up @@ -613,6 +618,7 @@ def __repr__(self) -> str:
return f'cirq_ft.AdditionGate({self.bitsize})'


@deprecated_cirq_ft_class()
@attr.frozen(auto_attribs=True)
class AddMod(cirq.ArithmeticGate):
"""Applies U_{M}_{add}|x> = |(x + add) % M> if x < M else |x>.
Expand Down
20 changes: 20 additions & 0 deletions cirq-ft/cirq_ft/algos/arithmetic_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
import numpy as np
import pytest
from cirq_ft.infra import bit_tools
from cirq_ft.deprecation import allow_deprecated_cirq_ft_use_in_tests


def identity_map(n: int):
"""Returns a dict of size `2**n` mapping each integer in range [0, 2**n) to itself."""
return {i: i for i in range(2**n)}


@allow_deprecated_cirq_ft_use_in_tests
def test_less_than_gate():
qubits = cirq.LineQubit.range(4)
gate = cirq_ft.LessThanGate(3, 5)
Expand Down Expand Up @@ -61,6 +63,7 @@ def test_less_than_gate():

@pytest.mark.parametrize("bits", [*range(8)])
@pytest.mark.parametrize("val", [3, 5, 7, 8, 9])
@allow_deprecated_cirq_ft_use_in_tests
def test_decompose_less_than_gate(bits: int, val: int):
qubit_states = list(bit_tools.iter_bits(bits, 3))
circuit = cirq.Circuit(
Expand All @@ -81,6 +84,7 @@ def test_decompose_less_than_gate(bits: int, val: int):

@pytest.mark.parametrize("n", [*range(2, 5)])
@pytest.mark.parametrize("val", [3, 4, 5, 7, 8, 9])
@allow_deprecated_cirq_ft_use_in_tests
def test_less_than_consistent_protocols(n: int, val: int):
g = cirq_ft.LessThanGate(n, val)
cirq_ft.testing.assert_decompose_is_consistent_with_t_complexity(g)
Expand All @@ -90,6 +94,7 @@ def test_less_than_consistent_protocols(n: int, val: int):
np.testing.assert_allclose(u @ u, np.eye(2 ** (n + 1)))


@allow_deprecated_cirq_ft_use_in_tests
def test_multi_in_less_equal_than_gate():
qubits = cirq.LineQubit.range(7)
op = cirq_ft.LessThanEqualGate(3, 3).on(*qubits)
Expand All @@ -114,6 +119,7 @@ def test_multi_in_less_equal_than_gate():

@pytest.mark.parametrize("x_bitsize", [*range(1, 5)])
@pytest.mark.parametrize("y_bitsize", [*range(1, 5)])
@allow_deprecated_cirq_ft_use_in_tests
def test_less_than_equal_consistent_protocols(x_bitsize: int, y_bitsize: int):
g = cirq_ft.LessThanEqualGate(x_bitsize, y_bitsize)
cirq_ft.testing.assert_decompose_is_consistent_with_t_complexity(g)
Expand All @@ -138,6 +144,7 @@ def test_less_than_equal_consistent_protocols(x_bitsize: int, y_bitsize: int):
assert g.with_registers([2] * 4, [2] * 5, [2]) == cirq_ft.LessThanEqualGate(4, 5)


@allow_deprecated_cirq_ft_use_in_tests
def test_contiguous_register_gate():
gate = cirq_ft.ContiguousRegisterGate(3, 6)
circuit = cirq.Circuit(gate.on(*cirq.LineQubit.range(12)))
Expand All @@ -163,13 +170,15 @@ def test_contiguous_register_gate():


@pytest.mark.parametrize('n', [*range(1, 10)])
@allow_deprecated_cirq_ft_use_in_tests
def test_contiguous_register_gate_t_complexity(n):
gate = cirq_ft.ContiguousRegisterGate(n, 2 * n)
toffoli_complexity = cirq_ft.t_complexity(cirq.CCNOT)
assert cirq_ft.t_complexity(gate) == (n**2 + n - 1) * toffoli_complexity


@pytest.mark.parametrize('a,b,num_bits', itertools.product(range(4), range(4), range(3, 5)))
@allow_deprecated_cirq_ft_use_in_tests
def test_add(a: int, b: int, num_bits: int):
num_anc = num_bits - 1
gate = cirq_ft.AdditionGate(num_bits)
Expand Down Expand Up @@ -199,6 +208,7 @@ def test_add(a: int, b: int, num_bits: int):
@pytest.mark.parametrize('mod', [5, 8])
@pytest.mark.parametrize('add_val', [1, 2])
@pytest.mark.parametrize('cv', [[], [0, 1], [1, 0], [1, 1]])
@allow_deprecated_cirq_ft_use_in_tests
def test_add_mod_n(bitsize, mod, add_val, cv):
gate = cirq_ft.AddMod(bitsize, mod, add_val=add_val, cv=cv)
basis_map = {}
Expand All @@ -225,6 +235,7 @@ def test_add_mod_n(bitsize, mod, add_val, cv):
cirq.testing.assert_equivalent_repr(gate, setup_code='import cirq_ft')


@allow_deprecated_cirq_ft_use_in_tests
def test_add_mod_n_protocols():
with pytest.raises(ValueError, match="must be between"):
_ = cirq_ft.AddMod(3, 10)
Expand All @@ -238,6 +249,7 @@ def test_add_mod_n_protocols():
assert cirq.circuit_diagram_info(add_two).wire_symbols == ('@', '@(0)') + ('Add_2_Mod_5',) * 3


@allow_deprecated_cirq_ft_use_in_tests
def test_add_truncated():
num_bits = 3
num_anc = num_bits - 1
Expand Down Expand Up @@ -286,6 +298,7 @@ def test_add_truncated():


@pytest.mark.parametrize('a,b,num_bits', itertools.product(range(4), range(4), range(3, 5)))
@allow_deprecated_cirq_ft_use_in_tests
def test_subtract(a, b, num_bits):
num_anc = num_bits - 1
gate = cirq_ft.AdditionGate(num_bits)
Expand All @@ -309,13 +322,15 @@ def test_subtract(a, b, num_bits):


@pytest.mark.parametrize("n", [*range(3, 10)])
@allow_deprecated_cirq_ft_use_in_tests
def test_addition_gate_t_complexity(n: int):
g = cirq_ft.AdditionGate(n)
cirq_ft.testing.assert_decompose_is_consistent_with_t_complexity(g)
cirq.testing.assert_equivalent_repr(g, setup_code='import cirq_ft')


@pytest.mark.parametrize('a,b', itertools.product(range(2**3), repeat=2))
@allow_deprecated_cirq_ft_use_in_tests
def test_add_no_decompose(a, b):
num_bits = 5
qubits = cirq.LineQubit.range(2 * num_bits)
Expand All @@ -335,6 +350,7 @@ def test_add_no_decompose(a, b):

@pytest.mark.parametrize("P,n", [(v, n) for n in range(1, 4) for v in range(1 << n)])
@pytest.mark.parametrize("Q,m", [(v, n) for n in range(1, 4) for v in range(1 << n)])
@allow_deprecated_cirq_ft_use_in_tests
def test_decompose_less_than_equal_gate(P: int, n: int, Q: int, m: int):
qubit_states = list(bit_tools.iter_bits(P, n)) + list(bit_tools.iter_bits(Q, m))
circuit = cirq.Circuit(
Expand All @@ -353,6 +369,7 @@ def test_decompose_less_than_equal_gate(P: int, n: int, Q: int, m: int):


@pytest.mark.parametrize("adjoint", [False, True])
@allow_deprecated_cirq_ft_use_in_tests
def test_single_qubit_compare_protocols(adjoint: bool):
g = cirq_ft.algos.SingleQubitCompare(adjoint=adjoint)
cirq_ft.testing.assert_decompose_is_consistent_with_t_complexity(g)
Expand All @@ -370,6 +387,7 @@ def test_single_qubit_compare_protocols(adjoint: bool):


@pytest.mark.parametrize("v1,v2", [(v1, v2) for v1 in range(2) for v2 in range(2)])
@allow_deprecated_cirq_ft_use_in_tests
def test_single_qubit_compare(v1: int, v2: int):
g = cirq_ft.algos.SingleQubitCompare()
qubits = cirq.LineQid.range(4, dimension=2)
Expand All @@ -388,6 +406,7 @@ def test_single_qubit_compare(v1: int, v2: int):


@pytest.mark.parametrize("adjoint", [False, True])
@allow_deprecated_cirq_ft_use_in_tests
def test_bi_qubits_mixer_protocols(adjoint: bool):
g = cirq_ft.algos.BiQubitsMixer(adjoint=adjoint)
cirq_ft.testing.assert_decompose_is_consistent_with_t_complexity(g)
Expand All @@ -399,6 +418,7 @@ def test_bi_qubits_mixer_protocols(adjoint: bool):

@pytest.mark.parametrize("x", [*range(4)])
@pytest.mark.parametrize("y", [*range(4)])
@allow_deprecated_cirq_ft_use_in_tests
def test_bi_qubits_mixer(x: int, y: int):
g = cirq_ft.algos.BiQubitsMixer()
qubits = cirq.LineQid.range(7, dimension=2)
Expand Down