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

Defining the new Backend API classes #764

Open
wants to merge 43 commits into
base: develop
Choose a base branch
from
Open

Conversation

HGSilveri
Copy link
Collaborator

@HGSilveri HGSilveri commented Nov 19, 2024

  • Introduces the Results class and make Result a subclass of it in backwards compatible way
  • Defines the State and Operator ABCs
  • Updates BackendConfig and defines EmulatorConfig
  • Defines the EmulatorBackend ABC
  • Defines the Callback and Observable ABCs
  • Defines the default observables

To do:

  • Define QutipState to have an example
  • Idem for QutipOperator
  • Solve relevant TODOs
  • Write UTs

@HGSilveri HGSilveri marked this pull request as ready for review January 3, 2025 14:51
@HGSilveri HGSilveri assigned a-corni and HGSilveri and unassigned a-corni Jan 3, 2025
@HGSilveri HGSilveri requested a review from a-corni January 3, 2025 14:52
"""
return list(self._results[self._find_uuid(observable)].keys())

def get_result(self, observable: Observable | str, time: float) -> Any:
Copy link

Choose a reason for hiding this comment

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

There is an interesting feature request in emu-mps that is related to this.

Also this morning we discussed with Kemal that the "dict" data structure indexed by time is maybe not the most appropriate:

  • most people use the data to make plots, where they need a list of values in chronological order
  • few people request value at a given time individually, except the latest time (with a list [-1])
  • dict has probably a lot of overhead compared to list

Copy link

Choose a reason for hiding this comment

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

Should we specify that the _store method is called in increasing order of time for a given callback? In which case the dict entries are always sorted by time according to this

Keys and values are iterated over in insertion order.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree with this, although we should still store the evaluation times of each observable in a separate list

Copy link

Choose a reason for hiding this comment

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

That sounds reasonable I think. Maybe allow sth like plt.plot(*results["energy"]), that is, return both times and values in unzipped format in the __getitem__?

There is also this thing that evaluation_times could just be a sort of observable dt/integer multiple of dt (or -1 for just the final time for instance), except if there is some strong use case for evaluating observables at non-regular times. In that case, it is not needed to store the times. At least all notebooks I saw of people using emu_mps API use a range of x multiples.
Sounds insignificant but when we get to serialize it for repeated usage in cloud, can save some traffic.

On the side, I think having a plot method for adequate observables would greatly help people working with simulation data. Throwing here some ideas:

results = MPSBackend().run(...)

plt.plot(*results["energy"])
# or
results["energy"].plot()
# or
results.plot("energy")

This plot method would be observable-specific and NotImplementedError by default in the base class

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That sounds reasonable I think. Maybe allow sth like plt.plot(*results["energy"]), that is, return both times and values in unzipped format in the __getitem__?

I'm not sure about this, not all observables are plottable and I think it would make for a counter-intuitive return type for __getitem__().
(Side note: you might have noticed that I went for __getattr__ instead of __getitem__ - so it would be results.energy rather than results["energy"]. This is to avoid confusion between Results and Sequence[Results], which some backends return. )

There is also this thing that evaluation_times could just be a sort of observable dt/integer multiple of dt (or -1 for just the final time for instance), except if there is some strong use case for evaluating observables at non-regular times. In that case, it is not needed to store the times. At least all notebooks I saw of people using emu_mps API use a range of x multiples.
Sounds insignificant but when we get to serialize it for repeated usage in cloud, can save some traffic.

I don't feel comfortable enforcing this at the base class level. I'd rather take the (minor) hit of making the serialized object a bit larger, we won't be saving much there anyway.

On the side, I think having a plot method for adequate observables would greatly help people working with simulation data. Throwing here some ideas:

results = MPSBackend().run(...)

plt.plot(*results["energy"])
# or
results["energy"].plot()
# or
results.plot("energy")

This plot method would be observable-specific and NotImplementedError by default in the base class

I'm not opposed to this but I think this is the sort of thing that would make more sense to implement first in a MPS specific Results subclass, for two main reasons:

  • All users are currently interacting with Results via EMU-MPS
  • I suspect there will be some trial and error before the best format is found, so it's better for you to have the freedom and flexibility to make adjustments without relying on pulser-core
    Once the format is well-established, we can potentially move it up to Results so it's shared by all backends.

@HGSilveri
Copy link
Collaborator Author

@a-corni This is ready for review

Copy link
Collaborator

@a-corni a-corni left a comment

Choose a reason for hiding this comment

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

First two comments

pulser-core/pulser/backend/config.py Outdated Show resolved Hide resolved
pulser-core/pulser/backend/__init__.py Outdated Show resolved Hide resolved
pulser-core/pulser/backend/config.py Show resolved Hide resolved
@HGSilveri HGSilveri added this to the v1.3 milestone Feb 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants