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

Enable pulling through Clifford operations, also add an option of only applying dd to single qubit gate moments #6675

Merged
merged 7 commits into from
Aug 14, 2024

Conversation

babacry
Copy link
Collaborator

@babacry babacry commented Jul 24, 2024

Enable adding dynamical decoupling in single qubit gate moments only.

Adding mechanism is described in the code. In short:

For each qubit:
      For moments in (first_active_moment, last_active_single_qubit_moment):
            Insert
      Absorb the inverse to the last_active_single_qubit_moment

2 test cases added for single qubit gates moments insertion mode:

Test case 1: add dd preserves the circuit.

0: ───────────────────────────────H───@───
                                      │
1: ───────────────────────H───@───H───X───
                              │
2: ───────────────H───@───H───X───────────
                      │
3: ───H───────@───H───X───────────────────
              │
4: ───H───@───X───────────────────────────
          │
5: ───H───X───────H───@───────────────────
                      │
6: ───────────────H───X───H───@───────────
                              │
7: ───────────────────────H───X───H───@───
                                      │
8: ───────────────────────────────H───X───

Test case 2:

input_circuit's diagram is:

0: ───────────────────────────────H───@───H───
                                      │
1: ───────────────────────H───@───H───X───H───
                              │
2: ───────────────H───@───H───X───────────H───
                      │
3: ───H───────@───H───X───────────────────H───
              │
4: ───H───@───X───────────────────────────H───
          │
5: ───H───X───────H───@───────────────────H───
                      │
6: ───────────────H───X───H───@───────────H───
                              │
7: ───────────────────────H───X───H───@───H───
                                      │
8: ───────────────────────────────H───X───H───

output diagram is

0: ───────────────────────────────H───@───H────────────────────────
                                      │
1: ───────────────────────H───@───H───@───H────────────────────────
                              │
2: ───────────────H───@───H───@───X───────PhXZ(a=-0.5,x=0.5,z=0)───
                      │
3: ───H───────@───H───@───X───────X───────H────────────────────────
              │
4: ───H───@───@───X───────X───────X───────PhXZ(a=-0.5,x=0.5,z=0)───
          │
5: ───H───@───────H───@───X───────X───────H────────────────────────
                      │
6: ───────────────H───@───H───@───X───────PhXZ(a=-0.5,x=0.5,z=0)───
                              │
7: ───────────────────────H───@───H───@───H────────────────────────
                                      │
8: ───────────────────────────────H───@───H────────────────────────

@babacry babacry requested review from vtomole, cduck and a team as code owners July 24, 2024 06:40
@babacry babacry requested a review from viathor July 24, 2024 06:40
@CirqBot CirqBot added the size: M 50< lines changed <250 label Jul 24, 2024
Copy link

codecov bot commented Jul 24, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.83%. Comparing base (e2e8aef) to head (74305a0).
Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #6675    +/-   ##
========================================
  Coverage   97.83%   97.83%            
========================================
  Files        1075     1077     +2     
  Lines       92325    92493   +168     
========================================
+ Hits        90324    90492   +168     
  Misses       2001     2001            

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@eliottrosenberg eliottrosenberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the following logic would be useful to test the correctness of the final circuits:

sampler = cirq.Simulator(dtype=np.complex128)
psi0 = sampler.simulate(circuit).final_state_vector
psi1 = sampler.simulate(transformed_circuit).final_state_vector
assert np.isclose(np.abs(np.vdot(psi0, psi1))**2, 1.0)

In particular, if this is the original circuit:

0: ───────────────────────────────────H───@───H───H───
                                          │
1: ───────────────────────────H───@───H───@───────H───
                                  │
2: ───────────────────H───@───H───@───────────────H───
                          │
3: ───────────H───@───H───@───────────────────────H───
                  │
4: ───H───@───────@───────────────────────────────H───
          │
5: ───H───@───H───@───────────────────────────────H───
                  │
6: ───────────H───@───H───@───────────────────────H───
                          │
7: ───────────────────H───@───H───@───────────────H───
                                  │
8: ───────────────────────────H───@───H───@───────H───
                                          │
9: ───────────────────────────────────H───@───H───H───

Then with schema='X_XINV' and single_qubit_gate_moments_only=True, it gets transformed to

0: ───────────────────────────────────H───@───H───H────────────────────────
                                          │
1: ───────────────────────────H───@───H───@───X───PhXZ(a=-0.5,x=0.5,z=0)───
                                  │
2: ───────────────────H───@───H───@───X───────X───H────────────────────────
                          │
3: ───────────H───@───H───@───X───────X───────X───PhXZ(a=-0.5,x=0.5,z=0)───
                  │
4: ───H───@───X───@───X───────X───────X───────X───PhXZ(a=-0.5,x=0.5,z=0)───
          │
5: ───H───@───H───@───X───────X───────X───────X───H────────────────────────
                  │
6: ───────────H───@───H───@───X───────X───────X───PhXZ(a=-0.5,x=0.5,z=0)───
                          │
7: ───────────────────H───@───H───@───X───────X───H────────────────────────
                                  │
8: ───────────────────────────H───@───H───@───X───PhXZ(a=-0.5,x=0.5,z=0)───
                                          │
9: ───────────────────────────────────H───@───H───H────────────────────────

which fails this test.

If I try the same transformation with single_qubit_gate_moments_only=False, then I get the following circuit

0: ───────X───X───X───X───X───X───────H───@───H───H───
                                          │
1: ───────X───X───X───X───────H───@───H───@───────H───
                                  │
2: ───────X───X───────H───@───H───@───X───X───────H───
                          │
3: ───────────H───@───H───@───X───X───X───X───────H───
                  │
4: ───H───@───────@───X───X───X───X───X───X───────H───
          │
5: ───H───@───H───@───X───X───X───X───X───X───────H───
                  │
6: ───────────H───@───H───@───X───X───X───X───────H───
                          │
7: ───────X───X───────H───@───H───@───X───X───────H───
                                  │
8: ───────X───X───X───X───────H───@───H───@───────H───
                                          │
9: ───────X───X───X───X───X───X───────H───@───H───H───

which doesn't quite behave as expected; many qubits could fit two more cirq.X gates. (Also the more ideal behavior would be to not add any DD gates prior to the first moment that acts on that qubit.)

@eliottrosenberg
Copy link
Collaborator

I suspect that the bug is in the logic of how to pull Pauli gates through Clifford gates (e.g. cirq.CZ)

@babacry
Copy link
Collaborator Author

babacry commented Jul 31, 2024

  • For single-qubit-gate moments insertion only: the bug was fixed in this commit. And it was tested via
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
        input_circuit, transformed_circuit, {q: q for q in input_circuit.all_qubits()}
    )

and

sampler = cirq.Simulator(dtype=np.complex128)
psi0 = sampler.simulate(input_circuit).final_state_vector
psi1 = sampler.simulate(transformed_circuit).final_state_vector
assert np.isclose(np.abs(np.vdot(psi0, psi1)) ** 2, 1.0)

both passed for all test cases.

  • For non-single-qubit-gate moments insertion, there are 2 issues
    • op wasn't inserted from first active moment, it's fixed in the latest commit.
    • Now, we fill in operations in consecutive idle pieces only, while I am not sure what is the expected transformed circuit for the following cases.
  • Input circuit:
a: ───H───@───────?───────────────H───
          │
b: ───────X───@───@───@───@───@───H───
              │   │   │   │   │
c: ───────────X───X───X───X───X───H───

where ? can be any single-qubit-gate, e.g., X / H.

  • Transformed circuit with schema="XX_PAIR"
    • Current code would transform the circuit into as for a, the idle pieces lengths are 1, 3
a: ───H───@───────?───X───X───────H───
          │
b: ───────X───@───@───@───@───@───H───
              │   │   │   │   │
c: ───────────X───X───X───X───X───H───

Is this expected? I suspect we can't commute through the moment ? at due to non commutativity, right? or should we take care of ? case by case? for example, if ?=X, then, we can add 2 more X gates for qubit a in the transformed circuit above. while, '?=H', we can't insert more, right?

@babacry babacry marked this pull request as draft August 6, 2024 20:24
@babacry babacry marked this pull request as ready for review August 13, 2024 17:55
Copy link
Collaborator

@eliottrosenberg eliottrosenberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!! (with one small nit)

Thank you so much, Renyi!



@transformer_api.transformer
def add_dynamical_decoupling(
circuit: 'cirq.AbstractCircuit',
*,
context: Optional['cirq.TransformerContext'] = None,
schema: Union[str, Sequence['cirq.Gate']] = 'X_XINV',
schema: Union[str, Tuple['cirq.Gate', ...]] = 'X_XINV',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change the default schema to (cirq.X, cirq.Y, cirq.X, cirq.Y). I think that gives better performance experimentally.

Copy link
Collaborator

@eliottrosenberg eliottrosenberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that if the circuit ends in a measurement, e.g.

0: ───────────H───@───H───M───
                  │       │
1: ───H───@───────@───────M───
          │               │
2: ───H───@───H───@───────M───
                  │       │
3: ───────────H───@───H───M───

then the transformer misbehaves. In this case, it outputs

0: ───────────H───@───H───M───X───
                  │       │
1: ───H───@───X───@───X───M───────
          │               │
2: ───H───@───H───@───X───M───X───
                  │       │
3: ───────────H───@───H───M───────

One option is to raise a NotImplementedError if the circuit contains measure gates. Alternatively, you could add support for circuits that include measure gates. (You can't pull single-qubit gates through measure gates, and no need to add DD unless there are more gates after the measure gate.)

Also enabling only apply dd to single qubit gates moments.

Multiple test cases with diagrams in docstrings are added.
@babacry
Copy link
Collaborator Author

babacry commented Aug 14, 2024

Now, we rely on cirq.has_stabilizer_effect to determine if an operation is Clifford. While, cirq.has_stabilizer_effect(cirq.M) returns True, resulting in a polluted clifford piece. Add a criteria for function _is_clifford_moment and the test case in the comment above.

@babacry
Copy link
Collaborator Author

babacry commented Aug 14, 2024

Also changed default schema in the new commit.

Copy link
Collaborator

@eliottrosenberg eliottrosenberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you, Renyi!

Copy link
Collaborator

@NoureldinYosri NoureldinYosri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to simplify this code?


The single qubit clifford algebra is implemented in the SingleQubitCliffordGate class this may help simplify the implementation

)


def test_exceptions():
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this test

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, should delete this.

@babacry babacry changed the title Enable only apply dd to single qubit gates moments Enable pulling through Clifford operations, also add option of applying dd to single qubit gates moments Aug 14, 2024
@babacry babacry changed the title Enable pulling through Clifford operations, also add option of applying dd to single qubit gates moments Enable pulling through Clifford operations, also add an option of applying dd to single qubit gates moments Aug 14, 2024
@babacry babacry changed the title Enable pulling through Clifford operations, also add an option of applying dd to single qubit gates moments Enable pulling through Clifford operations, also add an option of only applying dd to single qubit gate moments Aug 14, 2024
Copy link
Collaborator

@NoureldinYosri NoureldinYosri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging now to unblock users but this code can probably be simplified

@NoureldinYosri NoureldinYosri merged commit 8d8a6c5 into quantumlib:main Aug 14, 2024
34 checks passed
@babacry babacry deleted the single_moments branch September 5, 2024 01:44
harry-phasecraft pushed a commit to PhaseCraft/Cirq that referenced this pull request Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size: M 50< lines changed <250
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants