Skip to content

Speed up clifford simulator by short circuiting on known gates #2919

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

Merged
merged 2 commits into from
Apr 29, 2020

Conversation

mpharrigan
Copy link
Collaborator

This brings run-time down from 1.298s to 0.265s on a particular circuit I was investigating

@mpharrigan mpharrigan requested a review from vtomole April 17, 2020 20:28
@googlebot googlebot added the cla: yes Makes googlebot stop complaining. label Apr 17, 2020
Copy link
Collaborator

@vtomole vtomole left a comment

Choose a reason for hiding this comment

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

Adam has been adding type annotations to "basically everything"(#2914). Feel free to add return types None to the _apply_Gate functions to help.


def _apply_Y(self, qubit: int):
self.tableau._Y(qubit)
self.ch_form._Y(qubit)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we've decided that Clifford gates will define their effect on the tableau/CH form. IOW, this should be defined in the respective gates, not special cased here. Instead, here you should be invoking a protocol. The protocol would check whether a gate defines an effect on tableau/CH form and if so would use it for efficiency. If not, it would fall back to computing the effect.

This is also consistent with _apply_unitary_.

@Strilanc @fedimser

(Also, I wonder whether it makes sense to keep both the tableau and CH form.)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for the reminder. This is stated in #2423. Also, with respect to your last statement; here is my take on it: #2423 (comment)

Copy link
Collaborator

@vtomole vtomole Apr 18, 2020

Choose a reason for hiding this comment

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

_clifford_tableau_ hasn't been created yet so we can block this and wait or merge and have it be fixed once _clifford_tableau_ has been created. I'm down for either.

Copy link
Collaborator

@smitsanghavi smitsanghavi Apr 19, 2020

Choose a reason for hiding this comment

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

Given that using the current implementation (which was recently added) is significantly slowing down the simulation, I'd vote for letting this PR go through.

I will work on implementing the _clifford_tableau_ method and protocol and clean this up ASAP.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@viathor are you okay with letting this optimization merge in and I can clean up later.

@vtomole vtomole self-requested a review April 18, 2020 12:56
self.ch_form._Z(qubit)

def _apply_Y(self, qubit: int):
self.tableau._Y(qubit)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be cleaner if _apply_Gate methods accept the actual Qid and internally resolve that to self.qubit_map[Qid] instead of having the caller do that since the qubit map is an internal implementation detail of the state. (thinking in terms of eventually moving the tableau application to the Gate definitions)

def _apply_Y(self, qubit: int):
self.tableau._Y(qubit)
self.ch_form._Y(qubit)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also add and use _apply_CZ and _apply_CNOT for completeness.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm uncomfortable with the pattern of adding these methods for more and more gates. See comment about method dispatch above.

What is preventing us from implementing the equivalent methods in the gate classes instead?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@viathor Nothing really. Ideally we can take this to conclusion by removing the _GATE methods on the tableau and CH form too and let individual gates modify the internal states of tableau and the CH form. It will be more involved but I can make that change.

Do we want to have two separate protocols: apply_clifford_tableau and apply_stabilizer_ch_form or combine them into one update_clifford_state? (names subject to change)

@mpharrigan Feel free to ignore the initial suggestion in this comment.

@smitsanghavi smitsanghavi requested a review from viathor April 24, 2020 22:10
def _apply_Y(self, qubit: int):
self.tableau._Y(qubit)
self.ch_form._Y(qubit)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm uncomfortable with the pattern of adding these methods for more and more gates. See comment about method dispatch above.

What is preventing us from implementing the equivalent methods in the gate classes instead?

@@ -331,7 +330,21 @@ def apply_unitary(self, op: 'cirq.Operation'):

def apply_single_qubit_unitary(self, op: 'cirq.Operation'):
qubit = self.qubit_map[op.qubits[0]]
# Handle H natively as optimization.
if op.gate == cirq.I:
Copy link
Collaborator

Choose a reason for hiding this comment

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

We're basically implementing method dispatch here. We should not be doing this because python supports it natively.

@smitsanghavi smitsanghavi requested a review from viathor April 29, 2020 00:17
Copy link
Contributor

@Strilanc Strilanc left a comment

Choose a reason for hiding this comment

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

Reasonable change, though it will be replaced soon enough.

@Strilanc Strilanc added the automerge Tells CirqBot to sync and merge this PR. (If it's running.) label Apr 29, 2020
@CirqBot CirqBot added the front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. label Apr 29, 2020
Copy link
Collaborator

@viathor viathor left a comment

Choose a reason for hiding this comment

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

Please file an issue to replace this.

@CirqBot CirqBot merged commit e9b881a into quantumlib:master Apr 29, 2020
@CirqBot CirqBot removed automerge Tells CirqBot to sync and merge this PR. (If it's running.) front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. labels Apr 29, 2020
@mpharrigan
Copy link
Collaborator Author

Thanks all. I agree that a more principled solution is needed; but wanted to share this small change which helped my work and doesn't make anything worse :)

@mpharrigan mpharrigan deleted the cliff-speed branch April 29, 2020 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Makes googlebot stop complaining.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants