pasqal-io / Pulser

Library for pulse-level/analog control of neutral atom devices. Emulator with QuTiP.
Apache License 2.0
180 stars 65 forks source link

Update displayed device specs #763

Open HaroldErbin opened 1 week ago

HaroldErbin commented 1 week ago

Add more information to _specs() and move the method to BaseDevice.

A public property specs has been added.

See issue #756.

HaroldErbin commented 1 week ago

I don't understand how to make the typing test pass. If I use a try: ... except AttributeError to see if ch has an attribute bottom_detuning, then I get an error saying that ch has no attribute bottom_detuning (which is what I am testing. If I am using a different test withhasattr, then I get an error saying that there is a redundant cast tofloat`. Any pointer to solve this would be appreciated.

HaroldErbin commented 1 week ago

mypy continues to fail, but in a file I did not modify. Should I try to fix it nonetheless?

HGSilveri commented 1 week ago

mypy continues to fail, but in a file I did not modify. Should I try to fix it nonetheless?

Yeah, I saw this pop-up too in another PR. Please just copy this line and it goes away: https://github.com/pasqal-io/Pulser/blob/67197da4032f2dbc37bc40e14618111312f11883/pulser-pasqal/pulser_pasqal/pasqal_cloud.py#L241

HaroldErbin commented 1 week ago

Concerning the test coverage, which is now needed for specs since it's not internal, I was wondering what's the best approach. The simplest way is to assert that the specs string of different devices matches what is expected. However, this means having many lines of text (since we have to split the lines to respect the code style). Do you see a simpler way?

HGSilveri commented 1 week ago

Concerning the test coverage, which is now needed for specs since it's not internal, I was wondering what's the best approach. The simplest way is to assert that the specs string of different devices matches what is expected. However, this means having many lines of text (since we have to split the lines to respect the code style). Do you see a simpler way?

I'm afraid I don't see a way around it, no. I would maybe use a string with some format fields so that you can change some parameters (using @pytest.mark.parametrize) and check that the string always matches what you expect.

HaroldErbin commented 1 week ago

I have added a test for three devices. At the end, I did not use pytest.mark.parametrize but a function, let me know if this works for you.

HaroldErbin commented 1 week ago

To give an example of what has been implemented in the PR, here is the output of AnalogDevice._specs() before:

Register parameters:
 - Dimensions: 2D
 - Rydberg level: 60
 - Maximum number of atoms: 25
 - Maximum distance from origin: 35 μm
 - Minimum distance between neighbouring atoms: 5 μm
 - Maximum layout filling fraction: 0.5
 - SLM Mask: No
 - Maximum sequence duration: 4000 ns

Channels:
 - 'rydberg_global': Rydberg.Global(Max Absolute Detuning: 125.66370614359172 rad/µs, Max Amplitude: 12.566370614359172 rad/µs, Clock period: 4 ns, Minimum pulse duration: 16 ns, Maximum pulse duration: 100000000 ns, Modulation Bandwidth: 8 MHz, Basis: 'ground-rydberg')

and after:

Register parameters:
 - Dimensions: 2D
 - Rydberg level: 60
 - Maximum number of atoms: 25
 - Maximum distance from origin: 35 μm
 - Minimum distance between neighbouring atoms: 5 μm
 - Maximum layout filling fraction: 0.5
 - SLM Mask: No
 - Maximum sequence duration: 4000 ns

Device parameters:
 - Maximum number of runs: 2000
 - Channels can be reused: No
 - Supported bases: ground-rydberg
 - Supported states: r, g
 - Ising interaction coefficient: 865723.02

Layout parameters:
 - Requires layout: Yes
 - Accepts new layout: No
 - Minimal number of traps: 1
 - Maximal number of traps: None

Channels:
 - 'rydberg_global': Rydberg.Global(Max Absolute Detuning: 125.66370614359172 rad/µs, Max Amplitude: 12.566370614359172 rad/µs, Clock period: 4 ns, Minimum pulse duration: 16 ns, Maximum pulse duration: 100000000 ns, Modulation Bandwidth: 8 MHz, Basis: 'ground-rydberg')

Also, we can invoke this method for MockDevice now:

Register parameters:
 - Dimensions: 3D
 - Rydberg level: 70
 - Maximum number of atoms: None
 - Maximum distance from origin: None μm
 - Minimum distance between neighbouring atoms: 0.0 μm
 - Maximum layout filling fraction: 0.5
 - SLM Mask: Yes

Device parameters:
 - Channels can be reused: Yes
 - Supported bases: XY, ground-rydberg, digital
 - Supported states: u, d, r, g, h
 - Ising interaction coefficient: 5420158.53
 - XY interaction coefficient: 3700.0

Layout parameters:
 - Requires layout: No
 - Minimal number of traps: 1
 - Maximal number of traps: None

Channels:
 - 'rydberg_global': Rydberg.Global(Max Absolute Detuning: None, Max Amplitude: None, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'ground-rydberg')
 - 'rydberg_local': Rydberg.Local(Max Absolute Detuning: None, Max Amplitude: None, Minimum retarget time: 0 ns, Fixed retarget time: 0 ns, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'ground-rydberg')
 - 'raman_global': Raman.Global(Max Absolute Detuning: None, Max Amplitude: None, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'digital')
 - 'raman_local': Raman.Local(Max Absolute Detuning: None, Max Amplitude: None, Minimum retarget time: 0 ns, Fixed retarget time: 0 ns, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'digital')
 - 'mw_global': Microwave.Global(Max Absolute Detuning: None, Max Amplitude: None, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'XY')
 - 'dmm_0': DMM.Global(Max Absolute Detuning: None, Max Amplitude: 0, Clock period: 1 ns, Minimum pulse duration: 1 ns, Maximum pulse duration: 100000000 ns, Basis: 'ground-rydberg')
HaroldErbin commented 1 week ago

I have updated the codes with your suggestions, leaving only two conversations open for further discussions.

HaroldErbin commented 1 week ago

I have implemented the changes suggested by @HGSilveri:

  1. Individual private methods have been created for each section (register, layout, device, channels).
  2. The layout section is defined only for Device.
  3. I have reverted back to using lists instead of strings.
  4. I have defined two new private methods which are used to improve handling of None and boolean parameters.

Here are the results:

DigitalAnalogDevice

Register parameters:
 - Dimensions: 2D
 - Rydberg level: 70
 - Maximum number of atoms: 100
 - Maximum distance from origin: 50 µm
 - Minimum distance between neighbouring atoms: 4 μm
 - SLM Mask: Yes

Layout parameters:
 - Requires layout: Yes
 - Accepts new layout: Yes
 - Minimal number of traps: 1
 - Maximum layout filling fraction: 0.5

Device parameters:
 - Channels can be reused: No
 - Supported bases: digital, ground-rydberg
 - Supported states: r, g, h
 - Ising interaction coefficient: 5420158.53

Channels:
 - 'rydberg_global': Rydberg.Global(Max Absolute Detuning: 125.66370614359172 rad/µs, Max Amplitude: 15.707963267948966 rad/µs, Clock period: 4 ns, Minimum pulse duration: 16 ns, Maximum pulse duration: 67108864 ns, Basis: 'ground-rydberg')
 - 'rydberg_local': Rydberg.Local(Max Absolute Detuning: 125.66370614359172 rad/µs, Max Amplitude: 62.83185307179586 rad/µs, Minimum retarget time: 220 ns, Fixed retarget time: 0 ns, Max targets: 1, Clock period: 4 ns, Minimum pulse duration: 16 ns, Maximum pulse duration: 67108864 ns, Basis: 'ground-rydberg')
 - 'raman_local': Raman.Local(Max Absolute Detuning: 125.66370614359172 rad/µs, Max Amplitude: 62.83185307179586 rad/µs, Minimum retarget time: 220 ns, Fixed retarget time: 0 ns, Max targets: 1, Clock period: 4 ns, Minimum pulse duration: 16 ns, Maximum pulse duration: 67108864 ns, Basis: 'digital')
 - 'dmm_0': DMM.Global(Max Absolute Detuning: None, Max Amplitude: 0, Clock period: 4 ns, Minimum pulse duration: 16 ns, Maximum pulse duration: 67108864 ns, Basis: 'ground-rydberg')

MockDevice

Register parameters:
 - Dimensions: 3D
 - Rydberg level: 70
 - Minimum distance between neighbouring atoms: 0.0 μm
 - SLM Mask: Yes

Device parameters:
 - Channels can be reused: Yes
 - Supported bases: digital, ground-rydberg, XY
 - Supported states: u, d, r, g, h
 - Ising interaction coefficient: 5420158.53
 - XY interaction coefficient: 3700.0

Channels:
 - 'rydberg_global': Rydberg.Global(Max Absolute Detuning: None, Max Amplitude: None, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'ground-rydberg')
 - 'rydberg_local': Rydberg.Local(Max Absolute Detuning: None, Max Amplitude: None, Minimum retarget time: 0 ns, Fixed retarget time: 0 ns, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'ground-rydberg')
 - 'raman_global': Raman.Global(Max Absolute Detuning: None, Max Amplitude: None, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'digital')
 - 'raman_local': Raman.Local(Max Absolute Detuning: None, Max Amplitude: None, Minimum retarget time: 0 ns, Fixed retarget time: 0 ns, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'digital')
 - 'mw_global': Microwave.Global(Max Absolute Detuning: None, Max Amplitude: None, Clock period: 1 ns, Minimum pulse duration: 1 ns, Basis: 'XY')
 - 'dmm_0': DMM.Global(Max Absolute Detuning: None, Max Amplitude: 0, Clock period: 1 ns, Minimum pulse duration: 1 ns, Maximum pulse duration: 100000000 ns, Basis: 'ground-rydberg')