Skip to content

Allow passing a callable to de/serialization funcs #6855

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 11 commits into from
Dec 19, 2024

Conversation

senecameeks
Copy link
Collaborator

This gives us flexibility to manipulate the cirq.Sweep to add units for example.

@senecameeks senecameeks requested review from wcourtney, vtomole, verult and a team as code owners December 18, 2024 00:33
@CirqBot CirqBot added the size: M 50< lines changed <250 label Dec 18, 2024
Copy link

codecov bot commented Dec 18, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.85%. Comparing base (2448121) to head (8cb0db8).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6855      +/-   ##
==========================================
- Coverage   97.86%   97.85%   -0.01%     
==========================================
  Files        1084     1084              
  Lines       93954    94013      +59     
==========================================
+ Hits        91944    91997      +53     
- Misses       2010     2016       +6     

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

Copy link
Collaborator

@pavoljuhas pavoljuhas left a comment

Choose a reason for hiding this comment

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

Perhaps I am missing something, but I am not sure why is this needed.
The main code seems to be handling Linspace with units just fine,
so why is it necessary to support conversion of plain Linspace to Linspace with-units inside sweep_to_proto with a special callable?

import cirq
import tunits
from cirq_google.api import v2

sweep = cirq.Linspace('foo', 3 * tunits.ns, 6 * tunits.ns, 3)
print(sweep)
msg = v2.sweep_to_proto(sweep)
sweep_rt = v2.sweep_from_proto(msg)
print(sweep_rt)

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.

@senecameeks Great idea Seneca! ... just a few changes


@pavoljuhas this is to allow serialization of sweeps that use the internal units library ... otherwise we will need to replicate the logic in these functions internally.

@senecameeks
Copy link
Collaborator Author

Echoing what Nour said, this ability is needed to support serialization of the internal unit library @pavoljuhas

Copy link
Collaborator

@BichengYing BichengYing left a comment

Choose a reason for hiding this comment

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

lgtm

sweep: cirq.Sweep,
*,
out: Optional[run_context_pb2.Sweep] = None,
sweep_transformer: Callable[[cirq.Points | cirq.Linspace], cirq.Sweep] = lambda x: x,
Copy link
Collaborator

Choose a reason for hiding this comment

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

note in cirq, we have cirq.SingleSweep (the parent class of cirq.Points and cirq.Linspace).

So it can be more precise with
single_sweep_transformer: Callable[[cirq.SingleSweep], cirq.SingleSweep]

Copy link
Collaborator

Choose a reason for hiding this comment

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

@senecameeks for typing you can do this

_SWEEP_T = TypeVar('_SWEEP_T', cirq.Points, cirq.Linspace)  # or just cirq.SingleSweep

Callable[[_SWEEP_T], _SWEEP_T]

this will remove the cast statements below

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this still causes mypy to fail, but also I prefer using cirq.SingleSweep in the call over type vars since IMO the former is more readable. So I'll keep as is

Copy link
Collaborator

@NoureldinYosri NoureldinYosri Dec 19, 2024

Choose a reason for hiding this comment

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

the TypeVar tells mypy that the type of the output is the same as the type of the input e.g. if input is Linspace mypy will expect the output to also be Linspace

Comment on lines +251 to +254
msg = v2.sweep_to_proto(sweep)
sweep = v2.sweep_from_proto(msg, sweep_transformer=add_tunit_func)

assert list(sweep.points)[0] == [1.0 * tunits.ns]
Copy link
Collaborator

@BichengYing BichengYing Dec 19, 2024

Choose a reason for hiding this comment

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

can you add another test that add tunit in sweep_to_proto while remove tunit in sweep_from_proto, this is a more practical usage in the pyle.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

@BichengYing
Copy link
Collaborator

@NoureldinYosri why it is tunits.Value unit instead of tunits.Unit unit here? Is that because of multiple combinations of units and we just ignore the value here?

message Points {
// The values.
repeated float points = 1;
tunits.Value unit = 2;
}

@NoureldinYosri
Copy link
Collaborator

@NoureldinYosri why it is tunits.Value unit instead of tunits.Unit unit here? Is that because of multiple combinations of units and we just ignore the value here?

message Points {
// The values.
repeated float points = 1;
tunits.Value unit = 2;
}

@BichengYing tunits doesn't have a Unit in the public api ... for performance units are implemented in the cython layer as essnetially arrays ... the public api of tunits has only Value, ValueArray and their subclasses

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.

LGTM%typing nit & other reviewers' comments

sweep: cirq.Sweep,
*,
out: Optional[run_context_pb2.Sweep] = None,
sweep_transformer: Callable[[cirq.Points | cirq.Linspace], cirq.Sweep] = lambda x: x,
Copy link
Collaborator

Choose a reason for hiding this comment

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

@senecameeks for typing you can do this

_SWEEP_T = TypeVar('_SWEEP_T', cirq.Points, cirq.Linspace)  # or just cirq.SingleSweep

Callable[[_SWEEP_T], _SWEEP_T]

this will remove the cast statements below

@senecameeks senecameeks enabled auto-merge (squash) December 19, 2024 20:39
@senecameeks senecameeks merged commit 0d9a6ee into quantumlib:main Dec 19, 2024
35 checks passed
@mhucka mhucka changed the title allow passing a callable to de/serialization funcs Allow passing a callable to de/serialization funcs Apr 8, 2025
BichengYing pushed a commit to BichengYing/Cirq that referenced this pull request Jun 20, 2025
* allow passing func to de/serialization funcs

* coverage

* simplify

* typecheck

* nit

* mypy

* comments

* comments
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.

5 participants