def test_supports_extensions(): class DummyGate(cirq.Gate): pass ext = cirq.Extensions() ext.add_cast(cirq.BoundedEffect, DummyGate, lambda e: cirq.Z**0.00001) big_ext = cirq.Extensions() big_ext.add_cast(cirq.BoundedEffect, DummyGate, lambda e: cirq.Z**0.75) with_ext = cirq.DropNegligible(tolerance=0.001, extensions=ext) with_big_ext = cirq.DropNegligible(tolerance=0.001, extensions=big_ext) without_ext = cirq.DropNegligible(tolerance=0.001) a = cirq.NamedQubit('a') circuit = cirq.Circuit.from_ops(DummyGate().on(a)) cleared = cirq.Circuit([cirq.Moment()]) assert_optimizes(without_ext, initial_circuit=circuit, expected_circuit=circuit) assert_optimizes(with_ext, initial_circuit=circuit, expected_circuit=cleared) assert_optimizes(with_big_ext, initial_circuit=circuit, expected_circuit=circuit)
def assert_optimizes( before: cirq.Circuit, expected: cirq.Circuit, optimizer: Optional[Callable[[cirq.Circuit], None]] = None): if optimizer is None: optimizer = cirq.MergeSingleQubitGates().optimize_circuit optimizer(before) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations = [ cirq.DropNegligible(), cirq.DropEmptyMoments() ] for post in followup_optimizations: post(before) # type: ignore # error: "object" not callable post(expected) # type: ignore # error: "object" not callable try: assert before == expected except AssertionError: # coverage: ignore # coverage: ignore print("BEFORE") print(before) print("EXPECTED") print(expected) raise
def _get_common_cleanup_optimizers( tolerance: float) -> List[Callable[[cirq.Circuit], None]]: return [ cirq.EjectPhasedPaulis(tolerance=tolerance).optimize_circuit, cirq.EjectZ(tolerance=tolerance).optimize_circuit, cirq.DropNegligible(tolerance=tolerance).optimize_circuit, ]
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit, **kwargs): """Check that optimizing the circuit ``before`` produces the circuit ``expected``. The optimized circuit is cleaned up with follow up optimizations to make the comparison more robust to extra moments or extra gates nearly equal to identity that don't matter. Args: before: The input circuit to optimize. expected: The expected result of optimization to compare against. kwargs: Any extra arguments to pass to the ``MergeInteractionsToSqrtIswap`` constructor. """ actual = before.copy() opt = cirq.MergeInteractionsToSqrtIswap(**kwargs) opt.optimize_circuit(actual) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations: List[Callable[[cirq.Circuit], None]] = [ cirq.merge_single_qubit_gates_into_phased_x_z, cirq.EjectPhasedPaulis().optimize_circuit, cirq.EjectZ().optimize_circuit, cirq.DropNegligible().optimize_circuit, cirq.DropEmptyMoments().optimize_circuit, ] for post in followup_optimizations: post(actual) post(expected) assert actual == expected, f'ACTUAL {actual} : EXPECTED {expected}'
def test_clears_small(): drop = cirq.DropNegligible(0.001) a = cirq.NamedQubit('a') circuit = cirq.Circuit([cirq.Moment([cirq.Z(a)**0.000001])]) assert_optimizes(optimizer=drop, initial_circuit=circuit, expected_circuit=cirq.Circuit([cirq.Moment()]))
def assert_optimizes(atol: float, initial_circuit: cirq.Circuit, expected_circuit: cirq.Circuit): with cirq.testing.assert_deprecated("Use cirq.drop_negligible_operations", deadline='v1.0'): optimizer = cirq.DropNegligible(atol) circuit = cirq.Circuit(initial_circuit) optimizer.optimize_circuit(circuit) assert circuit == expected_circuit
def test_clears_known_empties_even_at_zero_tolerance(): a, b = cirq.LineQubit.range(2) circuit = cirq.Circuit.from_ops( cirq.Z(a)**0, cirq.Y(a)**0.0000001, cirq.X(a)**-0.0000001, cirq.CZ(a, b)**0) assert_optimizes(optimizer=cirq.DropNegligible(tolerance=0.001), initial_circuit=circuit, expected_circuit=cirq.Circuit([cirq.Moment()] * 4)) assert_optimizes(optimizer=cirq.DropNegligible(tolerance=0), initial_circuit=circuit, expected_circuit=cirq.Circuit([ cirq.Moment(), cirq.Moment([cirq.Y(a)**0.0000001]), cirq.Moment([cirq.X(a)**-0.0000001]), cirq.Moment(), ]))
def optimize(c): cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit=c) cirq.MergeSingleQubitGates().optimize_circuit(circuit=c) cirq.EjectZ().optimize_circuit(circuit=c) cirq.EjectPhasedPaulis().optimize_circuit(circuit=c) cirq.MergeSingleQubitGates().optimize_circuit(circuit=c) cirq.DropNegligible().optimize_circuit(circuit=c) cirq.DropEmptyMoments().optimize_circuit(circuit=c) c2=cirq.Circuit() for g in c: for g2 in g: # print(g2) c2.append(g2,strategy=cirq.InsertStrategy.EARLIEST) return c2
def simplify_expectation_value_circuit(circuit_sand: cirq.Circuit): """For low weight operators on low-degree circuits, we can simplify the circuit representation of an expectation value. In particular, this should be used on `circuit_for_expectation_value` circuits. It will merge single- and two-qubit gates from the "forwards" and "backwards" parts of the circuit outside of the operator's lightcone. This might be too slow in practice and you can just use quimb to simplify things for you. """ n_op = sum(1 for _ in circuit_sand.all_operations()) while True: MergeNQubitGates(n_qubits=1).optimize_circuit(circuit_sand) cirq.DropNegligible(tolerance=1e-6).optimize_circuit(circuit_sand) MergeNQubitGates(n_qubits=2).optimize_circuit(circuit_sand) cirq.DropNegligible(tolerance=1e-6) cirq.DropEmptyMoments().optimize_circuit(circuit_sand) new_n_op = sum(1 for _ in circuit_sand.all_operations()) if new_n_op < n_op: n_op = new_n_op else: return
def test_drop_negligible(): q0, = _make_qubits(1) sym = cirq.Symbol('a') circuit = cirq.Circuit.from_ops( PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**0.25, PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**1e-10, PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**sym, ) expected = cirq.Circuit.from_ops( PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**0.25, PauliStringPhasor(cirq.PauliString({q0: cirq.Z}))**sym, ) cirq.DropNegligible().optimize_circuit(circuit) cirq.DropEmptyMoments().optimize_circuit(circuit) assert circuit == expected
def assert_optimizes( before: cirq.Circuit, expected: cirq.Circuit, optimizer: Optional[Callable[[cirq.Circuit], None]] = None, ): if optimizer is None: optimizer = cirq.MergeSingleQubitGates().optimize_circuit optimizer(before) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations = [cirq.DropNegligible(), cirq.DropEmptyMoments()] for post in followup_optimizations: post(before) # type: ignore # error: "object" not callable post(expected) # type: ignore # error: "object" not callable assert before == expected, 'BEFORE:\n{}\nEXPECTED:\n{}'.format(before, expected)
def assert_optimizes(before, after, optimizer=None): if optimizer is None: optimizer = cirq.google.MergeRotations() optimizer.optimize_circuit(before) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations = [cirq.DropNegligible(), cirq.DropEmptyMoments()] for post in followup_optimizations: post.optimize_circuit(before) post.optimize_circuit(after) if before != after: # coverage: ignore print("before:", before) print("after:", after) assert before == after
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit): actual = cirq.Circuit(before) opt = cirq.MergeInteractions() opt.optimize_circuit(actual) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations: List[Callable[[cirq.Circuit], None]] = [ cirq.merge_single_qubit_gates_into_phased_x_z, cirq.EjectPhasedPaulis().optimize_circuit, cirq.EjectZ().optimize_circuit, cirq.DropNegligible().optimize_circuit, cirq.DropEmptyMoments().optimize_circuit, ] for post in followup_optimizations: post(actual) post(expected) assert actual == expected, f'ACTUAL {actual} : EXPECTED {expected}'
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit, optimizer: cirq.OptimizationPass = None): if optimizer is None: optimizer = cirq.MergeSingleQubitGates() optimizer.optimize_circuit(before) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations = [cirq.DropNegligible(), cirq.DropEmptyMoments()] for post in followup_optimizations: post.optimize_circuit(before) post.optimize_circuit(expected) try: assert before == expected except AssertionError: # coverage: ignore # coverage: ignore print("BEFORE") print(before) print("EXPECTED") print(expected) raise
def compile_to_non_negligible(circuit: cirq.Circuit, *, tolerance=1e-5, mutate=False) -> cirq.Circuit: """Remove negligible gates from the circuit. This is a wrapper around cirq.DropNegligible(tolerance) Args: circuit: The circuit tolerance: Gates with trace distance below this value will be considered negligible. mutate: By default, return a copy of the circuit. Otherwise, mutate in place. """ if mutate: c2 = circuit else: c2 = circuit.copy() cirq.DropNegligible(tolerance=tolerance).optimize_circuit(c2) cirq.DropEmptyMoments().optimize_circuit(c2) return c2
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit): actual = cirq.Circuit(before) opt = cirq.MergeInteractions() opt.optimize_circuit(actual) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations = [ cg.MergeRotations(), cg.EjectFullW(), cg.EjectZ(), cirq.DropNegligible(), cirq.DropEmptyMoments() ] for post in followup_optimizations: post.optimize_circuit(actual) post.optimize_circuit(expected) if actual != expected: # coverage: ignore print('ACTUAL') print(actual) print('EXPECTED') print(expected) assert actual == expected
def test_low_rank_trotter_ansatz_circuit(): ansatz = LowRankTrotterAnsatz(lih_hamiltonian, final_rank=2) circuit = ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) cirq.testing.assert_has_diagram(circuit, """ 0 1 2 3 │ │ │ │ Rz(π) Rz(π) Rz(π) Rz(π) │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^0.081 │ │ │ │ │ │ Z^U_0_0 │ YXXY────────#2^-0.081 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ Z^U_1_0 │ Z^U_3_0 │ │ │ │ │ │ Z^U_2_0 │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^-0.051 │ │ │ │ │ │ │ │ YXXY────────#2^0.051 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ @─────────@^V_0_1_0_0 │ │ │ │ │ │ ×─────────× @───────────@^V_2_3_0_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @───────────@^V_0_3_0_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @─────────@^V_1_3_0_0 @───────────@^V_0_2_0_0 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_3_0_0 @───────────@^V_1_2_0_0 Z^U_0_0_0 │ │ │ │ │ ×───────────× │ │ │ │ │ │ Z^U_2_0_0 Z^U_1_0_0 │ │ │ │ │ │ Rz(π) Rz(π) │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^-0.95 │ │ │ │ #2────────YXXY^0.95 │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ @───────────@^V_0_1_1_0 │ │ │ │ @─────────@^V_2_3_1_0 ×───────────× │ │ │ │ ×─────────× │ │ │ │ │ │ │ @───────────@^V_0_3_1_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @─────────@^V_0_2_1_0 @───────────@^V_1_3_1_0 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_0_1_0 @───────────@^V_1_2_1_0 Z^U_3_1_0 │ │ │ │ │ ×───────────× │ │ │ │ │ │ Z^U_1_1_0 Z^U_2_1_0 │ │ │ │ │ │ Rz(π) Rz(π) │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^-0.918 │ │ │ │ │ │ │ │ YXXY────────#2^0.918 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ """, transpose=True) ansatz = LowRankTrotterAnsatz(lih_hamiltonian, final_rank=1, include_all_cz=True, include_all_z=True, iterations=2) circuit = ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) cirq.testing.assert_has_diagram(circuit, """ 0 1 2 3 │ │ │ │ Rz(π) Rz(π) Rz(π) Rz(π) │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^0.081 │ │ │ │ │ │ Z^U_0_0 │ YXXY────────#2^-0.081 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ Z^U_1_0 │ Z^U_3_0 │ │ │ │ │ │ Z^U_2_0 │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^-0.051 │ │ │ │ │ │ │ │ YXXY────────#2^0.051 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ @─────────@^V_0_1_0_0 │ │ │ │ │ │ ×─────────× @───────────@^V_2_3_0_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @───────────@^V_0_3_0_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @─────────@^V_1_3_0_0 @───────────@^V_0_2_0_0 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_3_0_0 @───────────@^V_1_2_0_0 Z^U_0_0_0 │ │ │ │ Rz(π) ×───────────× Rz(π) │ │ │ │ │ Z^U_2_0_0 Z^U_1_0_0 │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^0.132 │ │ │ │ #2────────YXXY^-0.132 │ Rz(π) │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ Rz(π) │ Rz(π) │ │ │ │ │ │ Rz(π) │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^0.081 │ │ │ │ #2────────YXXY^-0.081 │ Z^U_0_1 │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ Z^U_3_1 │ Z^U_1_1 │ │ │ │ │ │ Z^U_2_1 │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^-0.051 │ │ │ │ #2────────YXXY^0.051 │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ @───────────@^V_0_1_0_1 │ │ │ │ @─────────@^V_2_3_0_1 ×───────────× │ │ │ │ ×─────────× │ │ │ │ │ │ │ @───────────@^V_0_3_0_1 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @─────────@^V_0_2_0_1 @───────────@^V_1_3_0_1 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_0_0_1 @───────────@^V_1_2_0_1 Z^U_3_0_1 │ │ │ │ Rz(π) ×───────────× Rz(π) │ │ │ │ │ Z^U_1_0_1 Z^U_2_0_1 │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^0.132 │ │ │ │ │ │ │ │ YXXY────────#2^-0.132 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ """, transpose=True)
def test_split_operator_trotter_ansatz_circuit(): complete_ansatz = SplitOperatorTrotterAnsatz(ones_hamiltonian, include_all_cz=True, include_all_z=True) circuit = complete_ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) cirq.testing.assert_has_diagram(circuit, """ 0 1 2 3 4 │ │ │ │ │ │ │ │ YXXY────────#2^0.5 │ │ │ │ │ │ │ YXXY────────#2^0.608 │ │ │ │ │ │ │ │ │ YXXY────────#2^-0.5 │ │ │ │ │ │ YXXY────────#2^-0.019 │ │ │ │ │ │ │ │ │ YXXY────────#2 │ │ │ │ │ │ YXXY────#2^-0.517 │ YXXY────────#2 │ │ │ │ │ Rz(-π) YXXY────────#2 │ │ │ │ │ │ │ Z^U_0_0 │ YXXY────────#2 │ │ │ │ │ │ Rz(π) Z^U_1_0 │ YXXY────────#2^-0.423 │ │ │ │ │ │ │ Z^U_2_0 │ Rz(-π) │ │ │ │ │ │ │ │ Z^U_3_0 Z^U_4_0 │ │ │ │ │ │ │ │ │ Rz(π) │ │ │ │ │ │ │ │ YXXY────────#2^0.423 │ │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ │ YXXY────#2^0.517 │ YXXY────────#2^-1 │ │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ │ YXXY────────#2^0.019 │ │ │ │ │ │ │ @───────@^V_0_1_0 │ YXXY────────#2^0.5 │ │ │ │ │ ×───────× YXXY────────#2^-0.608 │ │ │ │ │ │ │ │ │ YXXY────────#2^-0.5 │ │ │ │ │ │ │ @───────────@^V_2_3_0 │ │ │ │ │ │ │ │ ×───────────× │ │ │ │ │ │ │ @───────────@^V_0_3_0 @───────────@^V_2_4_0 │ │ │ │ │ │ ×───────────× ×───────────× │ │ │ │ │ @───────@^V_1_3_0 @───────────@^V_0_4_0 │ │ │ │ │ │ ×───────× ×───────────× │ │ │ │ │ │ │ @───────────@^V_1_4_0 @───────────@^V_0_2_0 │ │ │ │ │ │ ×───────────× ×───────────× │ │ │ │ │ @───────@^V_3_4_0 @───────────@^V_1_2_0 │ │ │ │ │ │ ×───────× ×───────────× │ │ │ │ │ │ #2──────YXXY^0.5 │ │ │ │ │ │ │ │ │ #2──────────YXXY^0.608 │ │ │ │ │ │ │ #2──────YXXY^-0.5 │ │ │ │ │ │ │ │ │ │ #2──────────YXXY^-0.019 │ │ │ │ │ │ │ #2──────────YXXY │ │ │ │ │ │ │ #2──────YXXY │ #2──────────YXXY^-0.517 │ │ │ │ │ │ │ #2──────────YXXY Rz(-π) │ │ │ │ │ │ #2──────────YXXY │ Z^U_0_0 │ │ │ │ │ #2──────YXXY^-0.423 │ Z^U_1_0 Rz(π) │ │ │ │ │ Rz(-π) │ Z^U_2_0 │ │ │ │ │ │ │ Z^U_4_0 Z^U_3_0 │ │ │ │ │ │ │ │ Rz(π) │ │ │ │ │ │ │ │ │ #2──────YXXY^0.423 │ │ │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ #2──────YXXY^-1 │ #2──────────YXXY^0.517 │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ │ │ #2──────────YXXY^0.019 │ │ │ │ │ │ #2──────YXXY^0.5 │ │ │ │ │ │ │ │ │ #2──────────YXXY^-0.608 │ │ │ │ │ │ │ #2──────YXXY^-0.5 │ │ │ │ │ │ │ │ """, transpose=True) jellium_ansatz = SplitOperatorTrotterAnsatz(jellium_hamiltonian) circuit = jellium_ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) cirq.testing.assert_has_diagram(circuit, """ 0 1 2 3 │ │ │ │ │ │ YXXY────────#2^0.5 │ │ │ │ │ YXXY────────#2^0.608 │ │ │ │ │ │ │ YXXY────────#2^(-1/3) │ │ │ │ YXXY────#2^(2/3) │ │ │ │ │ │ Rz(-π) YXXY────────#2 │ │ │ │ │ Rz(π) Rz(-π) YXXY────────#2^-0.392 │ │ │ │ │ Z^U_1_0 │ Rz(-π) │ │ │ │ │ Rz(π) Z^U_2_0 Z^U_3_0 │ │ │ │ │ │ │ Rz(π) │ │ │ │ │ │ YXXY────────#2^0.392 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY────#2^(-2/3) │ │ │ │ │ │ │ │ YXXY────────#2^(1/3) │ │ │ │ │ YXXY────────#2^-0.608 │ │ │ │ │ @───────@^V_0_1_0 │ │ │ │ │ │ ×───────× YXXY────────#2^-0.5 │ │ │ │ │ │ @───────────@^V_2_3_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @───────────@^V_0_3_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @───────@^V_1_3_0 @───────────@^V_0_2_0 │ │ │ │ ×───────× ×───────────× │ │ │ │ │ @───────────@^V_1_2_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ #2──────YXXY^0.5 │ │ │ │ │ │ │ #2──────────YXXY^0.608 │ │ │ │ │ #2──────YXXY^(-1/3) │ │ │ │ │ │ │ │ #2──────────YXXY^(2/3) │ │ │ │ │ #2──────────YXXY Rz(-π) │ │ │ │ #2──────YXXY^-0.392 Rz(-π) Rz(π) │ │ │ │ Rz(-π) │ Z^U_1_0 │ │ │ │ │ Z^U_3_0 Z^U_2_0 Rz(π) │ │ │ │ │ Rz(π) │ │ │ │ │ │ │ #2──────YXXY^0.392 │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^(-2/3) │ │ │ │ #2──────YXXY^(1/3) │ │ │ │ │ │ │ #2──────────YXXY^-0.608 │ │ │ │ │ #2──────YXXY^-0.5 │ │ │ │ │ │ """, transpose=True)
def kevin_optimize_circuit(self, circuit): cirq.DropNegligible().optimize_circuit(circuit) cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit)
def test_low_rank_trotter_ansatz_circuit(): ansatz = LowRankTrotterAnsatz(lih_hamiltonian, final_rank=2) circuit = ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) assert circuit.to_text_diagram(transpose=True).strip() == """ 0 1 2 3 │ │ │ │ Z Z Z Z │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^0.0813 │ │ │ │ │ │ Z^U_0_0 │ YXXY────────#2^-0.0813 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ Z^U_1_0 │ Z^U_3_0 │ │ │ │ │ │ Z^U_2_0 │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^-0.051 │ │ │ │ │ │ │ │ YXXY────────#2^0.051 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ @─────────@^V_0_1_0_0 │ │ │ │ │ │ ×─────────× @───────────@^V_2_3_0_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @───────────@^V_0_3_0_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @─────────@^V_1_3_0_0 @───────────@^V_0_2_0_0 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_3_0_0 @───────────@^V_1_2_0_0 Z^U_0_0_0 │ │ │ │ │ ×───────────× │ │ │ │ │ │ Z^U_2_0_0 Z^U_1_0_0 │ │ │ │ │ │ Z Z │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^-0.95 │ │ │ │ #2────────YXXY^0.95 │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ @───────────@^V_0_1_1_0 │ │ │ │ @─────────@^V_2_3_1_0 ×───────────× │ │ │ │ ×─────────× │ │ │ │ │ │ │ @───────────@^V_0_3_1_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @─────────@^V_0_2_1_0 @───────────@^V_1_3_1_0 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_0_1_0 @───────────@^V_1_2_1_0 Z^U_3_1_0 │ │ │ │ │ ×───────────× │ │ │ │ │ │ Z^U_1_1_0 Z^U_2_1_0 │ │ │ │ │ │ Z Z │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY──────#2^-0.918 │ │ │ │ │ │ │ │ YXXY────────#2^0.918 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ """.strip() ansatz = LowRankTrotterAnsatz(lih_hamiltonian, final_rank=1, include_all_cz=True, include_all_z=True, iterations=2) circuit = ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) assert circuit.to_text_diagram(transpose=True).strip() == """ 0 1 2 3 │ │ │ │ Z Z Z Z │ │ │ │ │ YXXY─────────#2^-1 │ │ │ │ │ YXXY──────#2^0.0813 │ │ │ │ │ │ Z^U_0_0 │ YXXY────────#2^-0.0813 │ │ │ │ │ YXXY─────────#2^-1 │ │ │ │ │ │ Z^U_1_0 │ Z^U_3_0 │ │ │ │ │ │ Z^U_2_0 │ │ │ │ │ │ YXXY─────────#2^-1 │ │ │ │ │ YXXY──────#2^-0.051 │ │ │ │ │ │ │ │ YXXY────────#2^0.051 │ │ │ │ │ YXXY─────────#2^-1 │ │ │ │ │ @─────────@^V_0_1_0_0 │ │ │ │ │ │ ×─────────× @───────────@^V_2_3_0_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @────────────@^V_0_3_0_0 │ │ │ │ │ │ ×────────────× │ │ │ │ │ @─────────@^V_1_3_0_0 @───────────@^V_0_2_0_0 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_3_0_0 @────────────@^V_1_2_0_0 Z^U_0_0_0 │ │ │ │ Z ×────────────× Z │ │ │ │ │ Z^U_2_0_0 Z^U_1_0_0 │ │ │ │ │ │ #2───────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^0.132 │ │ │ │ #2────────YXXY^-0.132 │ Z │ │ │ │ │ #2───────────YXXY^-1 │ │ │ │ │ Z │ Z │ │ │ │ │ │ Z │ │ │ │ │ │ │ #2───────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^0.0813 │ │ │ │ #2────────YXXY^-0.0813 │ Z^U_0_1 │ │ │ │ │ #2───────────YXXY^-1 │ │ │ │ │ Z^U_3_1 │ Z^U_1_1 │ │ │ │ │ │ Z^U_2_1 │ │ │ │ │ │ │ #2───────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^-0.051 │ │ │ │ #2────────YXXY^0.051 │ │ │ │ │ │ │ #2───────────YXXY^-1 │ │ │ │ │ │ │ @───────────@^V_0_1_0_1 │ │ │ │ @─────────@^V_2_3_0_1 ×───────────× │ │ │ │ ×─────────× │ │ │ │ │ │ │ @────────────@^V_0_3_0_1 │ │ │ │ │ │ ×────────────× │ │ │ │ │ @─────────@^V_0_2_0_1 @───────────@^V_1_3_0_1 │ │ │ │ ×─────────× ×───────────× │ │ │ │ Z^U_0_0_1 @────────────@^V_1_2_0_1 Z^U_3_0_1 │ │ │ │ Z ×────────────× Z │ │ │ │ │ Z^U_1_0_1 Z^U_2_0_1 │ │ │ │ │ │ YXXY─────────#2^-1 │ │ │ │ │ YXXY──────#2^0.132 │ │ │ │ │ │ │ │ YXXY────────#2^-0.132 │ │ │ │ │ YXXY─────────#2^-1 │ │ │ │ │ """.strip()
def test_split_operator_trotter_ansatz_circuit(): complete_ansatz = SplitOperatorTrotterAnsatz(ones_hamiltonian, include_all_cz=True, include_all_z=True) circuit = complete_ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) assert circuit.to_text_diagram(transpose=True).strip() == """ 0 1 2 3 4 │ │ │ │ │ │ │ │ YXXY─────────#2^0.5 │ │ │ │ │ │ │ YXXY────────#2^0.608 │ │ │ │ │ │ │ │ │ YXXY─────────#2^-0.5 │ │ │ │ │ │ YXXY────────#2^-0.0187 │ │ │ │ │ │ │ │ │ YXXY────────#2 │ │ │ │ │ │ YXXY────#2^-0.517 │ YXXY─────────#2 │ │ │ │ │ Z YXXY────────#2 │ │ │ │ │ │ │ Z^U_0_0 │ YXXY────────#2 │ │ │ │ │ │ Z Z^U_1_0 │ YXXY─────────#2^-0.423 │ │ │ │ │ │ │ Z^U_2_0 │ Z │ │ │ │ │ │ │ │ Z^U_3_0 Z^U_4_0 │ │ │ │ │ │ │ │ │ Z │ │ │ │ │ │ │ │ YXXY─────────#2^0.423 │ │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ │ YXXY────#2^0.517 │ YXXY─────────#2^-1 │ │ │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ │ │ YXXY────────#2^0.0187 │ │ │ │ │ │ │ @───────@^V_0_1_0 │ YXXY─────────#2^0.5 │ │ │ │ │ ×───────× YXXY────────#2^-0.608 │ │ │ │ │ │ │ │ │ YXXY─────────#2^-0.5 │ │ │ │ │ │ │ @───────────@^V_2_3_0 │ │ │ │ │ │ │ │ ×───────────× │ │ │ │ │ │ │ @───────────@^V_0_3_0 @────────────@^V_2_4_0 │ │ │ │ │ │ ×───────────× ×────────────× │ │ │ │ │ @───────@^V_1_3_0 @───────────@^V_0_4_0 │ │ │ │ │ │ ×───────× ×───────────× │ │ │ │ │ │ │ @───────────@^V_1_4_0 @────────────@^V_0_2_0 │ │ │ │ │ │ ×───────────× ×────────────× │ │ │ │ │ @───────@^V_3_4_0 @───────────@^V_1_2_0 │ │ │ │ │ │ ×───────× ×───────────× │ │ │ │ │ │ #2──────YXXY^0.5 │ │ │ │ │ │ │ │ │ #2──────────YXXY^0.608 │ │ │ │ │ │ │ #2──────YXXY^-0.5 │ │ │ │ │ │ │ │ │ │ #2──────────YXXY^-0.0187 │ │ │ │ │ │ │ #2──────────YXXY │ │ │ │ │ │ │ #2──────YXXY │ #2───────────YXXY^-0.517 │ │ │ │ │ │ │ #2──────────YXXY Z │ │ │ │ │ │ #2──────────YXXY │ Z^U_0_0 │ │ │ │ │ #2──────YXXY^-0.423 │ Z^U_1_0 Z │ │ │ │ │ Z │ Z^U_2_0 │ │ │ │ │ │ │ Z^U_4_0 Z^U_3_0 │ │ │ │ │ │ │ │ Z │ │ │ │ │ │ │ │ │ #2──────YXXY^0.423 │ │ │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ #2──────YXXY^-1 │ #2───────────YXXY^0.517 │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ │ │ #2──────────YXXY^0.0187 │ │ │ │ │ │ #2──────YXXY^0.5 │ │ │ │ │ │ │ │ │ #2──────────YXXY^-0.608 │ │ │ │ │ │ │ #2──────YXXY^-0.5 │ │ │ │ │ │ │ │ """.strip() jellium_ansatz = SplitOperatorTrotterAnsatz(jellium_hamiltonian) circuit = jellium_ansatz.circuit cirq.DropNegligible().optimize_circuit(circuit) assert circuit.to_text_diagram(transpose=True).strip() == """ 0 1 2 3 │ │ │ │ │ │ YXXY────────#2^0.5 │ │ │ │ │ YXXY────────#2^0.608 │ │ │ │ │ │ │ YXXY────────#2^-0.333 │ │ │ │ YXXY────#2^0.667 │ │ │ │ │ │ Z YXXY────────#2 │ │ │ │ │ Z Z YXXY────────#2^-0.392 │ │ │ │ │ Z^U_1_0 │ Z │ │ │ │ │ Z Z^U_2_0 Z^U_3_0 │ │ │ │ │ │ │ Z │ │ │ │ │ │ YXXY────────#2^0.392 │ │ │ │ │ YXXY────────#2^-1 │ │ │ │ │ YXXY────#2^-0.667 │ │ │ │ │ │ │ │ YXXY────────#2^0.333 │ │ │ │ │ YXXY────────#2^-0.608 │ │ │ │ │ @───────@^V_0_1_0 │ │ │ │ │ │ ×───────× YXXY────────#2^-0.5 │ │ │ │ │ │ @───────────@^V_2_3_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @───────────@^V_0_3_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ @───────@^V_1_3_0 @───────────@^V_0_2_0 │ │ │ │ ×───────× ×───────────× │ │ │ │ │ @───────────@^V_1_2_0 │ │ │ │ │ │ ×───────────× │ │ │ │ │ #2──────YXXY^0.5 │ │ │ │ │ │ │ #2──────────YXXY^0.608 │ │ │ │ │ #2──────YXXY^-0.333 │ │ │ │ │ │ │ │ #2──────────YXXY^0.667 │ │ │ │ │ #2──────────YXXY Z │ │ │ │ #2──────YXXY^-0.392 Z Z │ │ │ │ Z │ Z^U_1_0 │ │ │ │ │ Z^U_3_0 Z^U_2_0 Z │ │ │ │ │ Z │ │ │ │ │ │ │ #2──────YXXY^0.392 │ │ │ │ │ │ │ #2──────────YXXY^-1 │ │ │ │ │ │ │ #2──────────YXXY^-0.667 │ │ │ │ #2──────YXXY^0.333 │ │ │ │ │ │ │ #2──────────YXXY^-0.608 │ │ │ │ │ #2──────YXXY^-0.5 │ │ │ │ │ │ """.strip()