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

Remove tetris_concat #5659

Merged
merged 4 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 0 additions & 66 deletions cirq-core/cirq/circuits/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1505,64 +1505,6 @@ def concat_ragged(

return cirq.Circuit(buffer[offset : offset + n_acc])

@_compat.deprecated(deadline='v0.16', fix='Renaming to concat_ragged')
def tetris_concat(
*circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
) -> 'cirq.AbstractCircuit':
"""Concatenates circuits while overlapping them if possible.

Starts with the first circuit (index 0), then iterates over the other
circuits while folding them in. To fold two circuits together, they
are placed one after the other and then moved inward until just before
their operations would collide. If any of the circuits do not share
qubits and so would not collide, the starts or ends of the circuits will
be aligned, acording to the given align parameter.

Beware that this method is *not* associative. For example:

>>> a, b = cirq.LineQubit.range(2)
>>> A = cirq.Circuit(cirq.H(a))
>>> B = cirq.Circuit(cirq.H(b))
>>> f = cirq.Circuit.tetris_concat
>>> f(f(A, B), A) == f(A, f(B, A))
False
>>> len(f(f(f(A, B), A), B)) == len(f(f(A, f(B, A)), B))
False

Args:
*circuits: The circuits to concatenate.
align: When to stop when sliding the circuits together.
'left': Stop when the starts of the circuits align.
'right': Stop when the ends of the circuits align.
'first': Stop the first time either the starts or the ends align. Circuits
are never overlapped more than needed to align their starts (in case
the left circuit is smaller) or to align their ends (in case the right
circuit is smaller)

Returns:
The concatenated and overlapped circuit.
"""
if len(circuits) == 0:
return Circuit()
n_acc = len(circuits[0])

if isinstance(align, str):
align = Alignment[align.upper()]

# Allocate a buffer large enough to append and prepend all the circuits.
pad_len = sum(len(c) for c in circuits) - n_acc
buffer = np.zeros(shape=pad_len * 2 + n_acc, dtype=object)

# Put the initial circuit in the center of the buffer.
offset = pad_len
buffer[offset : offset + n_acc] = circuits[0].moments

# Accumulate all the circuits into the buffer.
for k in range(1, len(circuits)):
offset, n_acc = _concat_ragged_helper(offset, n_acc, buffer, circuits[k].moments, align)

return cirq.Circuit(buffer[offset : offset + n_acc])

def get_independent_qubit_sets(self) -> List[Set['cirq.Qid']]:
"""Divide circuit's qubits into independent qubit sets.

Expand Down Expand Up @@ -1909,14 +1851,6 @@ def concat_ragged(

concat_ragged.__doc__ = AbstractCircuit.concat_ragged.__doc__

@_compat.deprecated(deadline='v0.16', fix='Renaming to concat_ragged')
def tetris_concat(
*circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
) -> 'cirq.Circuit':
return AbstractCircuit.tetris_concat(*circuits, align=align).unfreeze(copy=False)

tetris_concat.__doc__ = AbstractCircuit.tetris_concat.__doc__

def zip(
*circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
) -> 'cirq.Circuit':
Expand Down
207 changes: 0 additions & 207 deletions cirq-core/cirq/circuits/circuit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4261,213 +4261,6 @@ def _circuit_diagram_info_(self, args):
assert '|c>' in circuit._repr_html_()


def test_tetris_concat_deprecated():
a, b = cirq.LineQubit.range(2)
empty = cirq.Circuit()

with cirq.testing.assert_deprecated('ragged', deadline='v0.16', count=None):
assert cirq.Circuit.tetris_concat(empty, empty) == empty
assert cirq.Circuit.tetris_concat() == empty
assert empty.tetris_concat(empty) == empty
assert empty.tetris_concat(empty, empty) == empty

ha = cirq.Circuit(cirq.H(a))
hb = cirq.Circuit(cirq.H(b))
assert ha.tetris_concat(hb) == ha.zip(hb)

assert ha.tetris_concat(empty) == ha
assert empty.tetris_concat(ha) == ha

hac = cirq.Circuit(cirq.H(a), cirq.CNOT(a, b))
assert hac.tetris_concat(hb) == hac + hb
assert hb.tetris_concat(hac) == hb.zip(hac)

zig = cirq.Circuit(cirq.H(a), cirq.CNOT(a, b), cirq.H(b))
assert zig.tetris_concat(zig) == cirq.Circuit(
cirq.H(a),
cirq.CNOT(a, b),
cirq.Moment(cirq.H(a), cirq.H(b)),
cirq.CNOT(a, b),
cirq.H(b),
)

zag = cirq.Circuit(cirq.H(a), cirq.H(a), cirq.CNOT(a, b), cirq.H(b), cirq.H(b))
assert zag.tetris_concat(zag) == cirq.Circuit(
cirq.H(a),
cirq.H(a),
cirq.CNOT(a, b),
cirq.Moment(cirq.H(a), cirq.H(b)),
cirq.Moment(cirq.H(a), cirq.H(b)),
cirq.CNOT(a, b),
cirq.H(b),
cirq.H(b),
)

space = cirq.Circuit(cirq.Moment()) * 10
f = cirq.Circuit.tetris_concat
assert len(f(space, ha)) == 10
assert len(f(space, ha, ha, ha)) == 10
assert len(f(space, f(ha, ha, ha))) == 10
assert len(f(space, ha, align='LEFT')) == 10
assert len(f(space, ha, ha, ha, align='RIGHT')) == 12
assert len(f(space, f(ha, ha, ha, align='LEFT'))) == 10
assert len(f(space, f(ha, ha, ha, align='RIGHT'))) == 10
assert len(f(space, f(ha, ha, ha), align='LEFT')) == 10
assert len(f(space, f(ha, ha, ha), align='RIGHT')) == 10

# L shape overlap (vary c1).
assert 7 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 5),
cirq.Circuit([cirq.H(b)] * 5, cirq.CZ(a, b)),
)
)
assert 7 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 4),
cirq.Circuit([cirq.H(b)] * 5, cirq.CZ(a, b)),
)
)
assert 7 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 1),
cirq.Circuit([cirq.H(b)] * 5, cirq.CZ(a, b)),
)
)
assert 8 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 6),
cirq.Circuit([cirq.H(b)] * 5, cirq.CZ(a, b)),
)
)
assert 9 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 7),
cirq.Circuit([cirq.H(b)] * 5, cirq.CZ(a, b)),
)
)

# L shape overlap (vary c2).
assert 7 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 5),
cirq.Circuit([cirq.H(b)] * 5, cirq.CZ(a, b)),
)
)
assert 7 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 5),
cirq.Circuit([cirq.H(b)] * 4, cirq.CZ(a, b)),
)
)
assert 7 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 5),
cirq.Circuit([cirq.H(b)] * 1, cirq.CZ(a, b)),
)
)
assert 8 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 5),
cirq.Circuit([cirq.H(b)] * 6, cirq.CZ(a, b)),
)
)
assert 9 == len(
f(
cirq.Circuit(cirq.CZ(a, b), [cirq.H(a)] * 5),
cirq.Circuit([cirq.H(b)] * 7, cirq.CZ(a, b)),
)
)

# When scanning sees a possible hit, continues scanning for earlier hit.
assert 10 == len(
f(
cirq.Circuit(
cirq.Moment(),
cirq.Moment(),
cirq.Moment(),
cirq.Moment(),
cirq.Moment(),
cirq.Moment(cirq.H(a)),
cirq.Moment(),
cirq.Moment(),
cirq.Moment(cirq.H(b)),
),
cirq.Circuit(
cirq.Moment(),
cirq.Moment(),
cirq.Moment(),
cirq.Moment(cirq.H(a)),
cirq.Moment(),
cirq.Moment(cirq.H(b)),
),
)
)
# Correct tie breaker when one operation sees two possible hits.
for cz_order in [cirq.CZ(a, b), cirq.CZ(b, a)]:
assert 3 == len(
f(
cirq.Circuit(cirq.Moment(cz_order), cirq.Moment(), cirq.Moment()),
cirq.Circuit(cirq.Moment(cirq.H(a)), cirq.Moment(cirq.H(b))),
)
)

# Types.
v = ha.freeze().tetris_concat(empty)
assert type(v) is cirq.FrozenCircuit and v == ha.freeze()
v = ha.tetris_concat(empty.freeze())
assert type(v) is cirq.Circuit and v == ha
v = ha.freeze().tetris_concat(empty)
assert type(v) is cirq.FrozenCircuit and v == ha.freeze()
v = cirq.Circuit.tetris_concat(ha, empty)
assert type(v) is cirq.Circuit and v == ha
v = cirq.FrozenCircuit.tetris_concat(ha, empty)
assert type(v) is cirq.FrozenCircuit and v == ha.freeze()


def test_tetris_concat_alignment_deprecated():
a, b = cirq.LineQubit.range(2)

with cirq.testing.assert_deprecated('ragged', deadline='v0.16', count=None):

assert cirq.Circuit.tetris_concat(
cirq.Circuit(cirq.X(a)),
cirq.Circuit(cirq.Y(b)) * 4,
cirq.Circuit(cirq.Z(a)),
align='first',
) == cirq.Circuit(
cirq.Moment(cirq.X(a), cirq.Y(b)),
cirq.Moment(cirq.Y(b)),
cirq.Moment(cirq.Y(b)),
cirq.Moment(cirq.Z(a), cirq.Y(b)),
)

assert cirq.Circuit.tetris_concat(
cirq.Circuit(cirq.X(a)),
cirq.Circuit(cirq.Y(b)) * 4,
cirq.Circuit(cirq.Z(a)),
align='left',
) == cirq.Circuit(
cirq.Moment(cirq.X(a), cirq.Y(b)),
cirq.Moment(cirq.Z(a), cirq.Y(b)),
cirq.Moment(cirq.Y(b)),
cirq.Moment(cirq.Y(b)),
)

assert cirq.Circuit.tetris_concat(
cirq.Circuit(cirq.X(a)),
cirq.Circuit(cirq.Y(b)) * 4,
cirq.Circuit(cirq.Z(a)),
align='right',
) == cirq.Circuit(
cirq.Moment(cirq.Y(b)),
cirq.Moment(cirq.Y(b)),
cirq.Moment(cirq.Y(b)),
cirq.Moment(cirq.X(a), cirq.Y(b)),
cirq.Moment(cirq.Z(a)),
)


def test_concat_ragged():
a, b = cirq.LineQubit.range(2)
empty = cirq.Circuit()
Expand Down
9 changes: 0 additions & 9 deletions cirq-core/cirq/circuits/frozen_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from cirq.circuits import AbstractCircuit, Alignment, Circuit
from cirq.circuits.insert_strategy import InsertStrategy
from cirq.type_workarounds import NotImplementedType
from cirq import ops, protocols, _compat

if TYPE_CHECKING:
import cirq
Expand Down Expand Up @@ -172,14 +171,6 @@ def concat_ragged(

concat_ragged.__doc__ = AbstractCircuit.concat_ragged.__doc__

@_compat.deprecated(deadline='v0.16', fix='Renaming to concat_ragged')
def tetris_concat(
*circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
) -> 'cirq.FrozenCircuit':
return AbstractCircuit.tetris_concat(*circuits, align=align).freeze()

tetris_concat.__doc__ = AbstractCircuit.tetris_concat.__doc__

def zip(
*circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
) -> 'cirq.FrozenCircuit':
Expand Down