-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add cg.ProcessorSampler
#5361
Add cg.ProcessorSampler
#5361
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am good with these changes modulo some double-checking and fixing tests. Thanks for cleaning this interface up!
@@ -105,7 +106,7 @@ def engine(self) -> 'engine_base.Engine': | |||
@util.deprecated_gate_set_parameter | |||
def get_sampler( | |||
self, gate_set: Optional[serializer.Serializer] = None | |||
) -> engine_sampler.QuantumEngineSampler: | |||
) -> 'cg.engine.QuantumProcessorSampler': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wcourtney Will changing this cause any backwards incompatibility problems? This affects the QCS engine in addition to the simulated version.
I think it should be fine, but want to double-check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a backwards incompatible change for anyone using processor.get_sampler()
and trying to use multiple processor_ids. However, this workflow doesn't make any sense and I don't think many people are using processor.get_sampler()
.
Most people using cg.get_engine().get_sampler()
or cg.get_engine_sampler()
will be unaffected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the PR description
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: should EngineSampler use this class underneath?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it (easily) can.
Engine.run_sweep
and Processor.run_sweep
have meaningfully different semantics: The first will send out a job to one of potentially many processors. This logic happens server-side. While we could theoretically replicate it using a collection of Processors / ProcessorSamplers underneath EngineSampler, it wouldn't be a small change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am starting to agree with maffoo. It seems like ProcessorSampler is basically the same as a QuantumEngineSampler with a processor set already. Seems like these two can/should be combined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After off-line conversations, I am fully on-board with this change.
I think we should deprecate QuantumEngineSampler and switch engine.get_sampler(processor_id) to use engine.get_processor(processor_id).get_sampler() (or, alternatively, make QuantumEngineSampler a thin wrapper around this ProcessorSampler functionality). Since this functionality currently supports multiple processor ids and sending an EngineProgram, it probably needs more thought and should be done in a follow-up PR.
Short story, I approve this PR as is.
Thanks for the preliminary check. I'll flesh this out |
@dstrain115 @wcourtney PTAL now that this is complete |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The relationship between QuantumEngineSampler
and QuantumProcessorSampler
is confusing to me. I'd suggest that we only have one of these and that any custom code that currently lives in QuantumEngineSampler
methods be moved into EngineProcessor
methods that the sampler calls. As for names, I think call this something like ProcessorSampler
would probably be best, since it implements the Sampler
interface given an AbstractProcessor
. We could use that name and deprecate the existing QuantumEngineSampler
name.
) | ||
|
||
@property | ||
def processor(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add return type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
We can't do this because QuantumEngineSampler can dispatch to multiple processors. |
The other glue code relates to repetitions: |
Do we ever use this? To me it makes more sense to just create separate sampler instances for each processor you want to talk to (just like you'd create separate
True, but the code to handle this is almost identical in both |
I agree that QuantumEngineSampler has annoying semantics and should be deprecated. This would have to be done with some care. Is your only remaining concern the duplicate code that exists in One cannot refactor QuantumEngineSampler to use ProcessorSampler because of the multi-processor_id and engineprogram support. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider renaming ProcessorSampler
to EngineSampler
(it is a cirq.Sampler
that returns EngineResult
). As discussed, we plan to deprecate and remove QuantumEngineSampler
, but that can be a separate PR.
I think I'm going to keep it as |
opened #5371 for follow-on work |
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After off-line conversations, I am fully on-board with this change.
I think we should deprecate QuantumEngineSampler and switch engine.get_sampler(processor_id) to use engine.get_processor(processor_id).get_sampler() (or, alternatively, make QuantumEngineSampler a thin wrapper around this ProcessorSampler functionality). Since this functionality currently supports multiple processor ids and sending an EngineProgram, it probably needs more thought and should be done in a follow-up PR.
Short story, I approve this PR as is.
We aim to have interfaces and classical/simulated implementations of all of the `cg.engine.` classes. Wheras `QuantumEngineSampler` turns a `cg.Engine` into a `Sampler`, `ProcessorSampler` turns a `AbstractProcessor` into a `Sampler`. Unfortunately, `QuantumEngineSampler` does **not** work with an `AbstractEngine`; hence the new class. `Engine`, `Engine.get_sampler()`, and `QuantumEngineSampler` can accept a _list_ of processor_ids, so they are preserved for backwards compatibility. `QuantumEngineSampler` and this behavior should be considered for deprecation. This PR unifies the implementations of `AbstractProcessor.get_sampler()` to always just return `ProcessorSampler(processor=self)`. fixes quantumlib#5360 Backwards incompatible changes: - the return type of `AbstractProcessor.get_sampler()` has changed. The behavior of the resulting object has not changed for EngineProcessors (unless you're doing something bad, see below), but has changed for SimulatedLocalProcessors. This fixes the issues like quantumlib#5360 - ProcessorSampler doesn't handle `program` argument types of `EngineProgram`. We'd need to teach `AbstractProgram` some run methods. cc quantumlib#1958 for context - Previously, you could have done something weird where you use the sampler from EngineProcessor.get_sampler() to run on processors other than the one pointed to by EngineProcessor. This is no longer possible. Backwards compatible parts: - QuantumEngineSampler still exists and is returned by Engine.get_sampler or cg.get_engine_sampler() @dstrain115 @verult
We aim to have interfaces and classical/simulated implementations of all of the
cg.engine.
classes.Wheras
QuantumEngineSampler
turns acg.Engine
into aSampler
,ProcessorSampler
turns aAbstractProcessor
into aSampler
. Unfortunately,QuantumEngineSampler
does not work with anAbstractEngine
; hence the new class.Engine
,Engine.get_sampler()
, andQuantumEngineSampler
can accept a list of processor_ids, so they are preserved for backwards compatibility.QuantumEngineSampler
and this behavior should be considered for deprecation.This PR unifies the implementations of
AbstractProcessor.get_sampler()
to always just returnProcessorSampler(processor=self)
.fixes #5360
Backwards incompatible changes:
AbstractProcessor.get_sampler()
has changed. The behavior of the resulting object has not changed for EngineProcessors (unless you're doing something bad, see below), but has changed for SimulatedLocalProcessors. This fixes the issues like SimulatedLocalProcessor.run()
vs.get_sampler().run()
#5360program
argument types ofEngineProgram
. We'd need to teachAbstractProgram
some run methods. cc QuantumEngineSampler doesn't allow any control over program id or job id. #1958 for contextBackwards compatible parts:
@dstrain115 @verult