diff --git a/.envrc b/.envrc index 01f5f41d0..3af52d88e 100644 --- a/.envrc +++ b/.envrc @@ -2,8 +2,8 @@ if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" fi -nix_direnv_watch_file flake.nix -nix_direnv_watch_file flake.lock +watch_file flake.nix +watch_file flake.lock if ! use flake . --impure; then echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2 fi diff --git a/doc/source/main-documentation/qibolab.rst b/doc/source/main-documentation/qibolab.rst index 09f3789ea..90a6c4f3b 100644 --- a/doc/source/main-documentation/qibolab.rst +++ b/doc/source/main-documentation/qibolab.rst @@ -66,7 +66,7 @@ Now we can create a simple sequence (again, without explicitly giving any qubit ps = PulseSequence() ps.append(platform.create_RX_pulse(qubit=0)) ps.append(platform.create_RX_pulse(qubit=0)) - ps.append(Delay(200, platform.qubits[0].readout.name)) + ps.append(Delay(duration=200, channel=platform.qubits[0].readout.name)) ps.append(platform.create_MZ_pulse(qubit=0)) Now we can execute the sequence on hardware: @@ -274,7 +274,7 @@ To illustrate, here are some examples of single pulses using the Qibolab API: amplitude=0.5, # Amplitude relative to instrument range frequency=1e8, # Frequency in Hz relative_phase=0, # Phase in radians - shape=Rectangular(), + envelope=Rectangular(), channel="channel", type="qd", # Enum type: :class:`qibolab.pulses.PulseType` qubit=0, @@ -292,7 +292,7 @@ Alternatively, you can achieve the same result using the dedicated :class:`qibol amplitude=0.5, # this amplitude is relative to the range of the instrument frequency=1e8, # frequency are in Hz relative_phase=0, # phases are in radians - shape=Rectangular(), + envelope=Rectangular(), channel="channel", qubit=0, ) @@ -312,7 +312,7 @@ To organize pulses into sequences, Qibolab provides the :class:`qibolab.pulses.P amplitude=0.5, # this amplitude is relative to the range of the instrument frequency=1e8, # frequency are in Hz relative_phase=0, # phases are in radians - shape=Rectangular(), + envelope=Rectangular(), channel="channel", qubit=0, ) @@ -321,7 +321,7 @@ To organize pulses into sequences, Qibolab provides the :class:`qibolab.pulses.P amplitude=0.5, # this amplitude is relative to the range of the instrument frequency=1e8, # frequency are in Hz relative_phase=0, # phases are in radians - shape=Rectangular(), + envelope=Rectangular(), channel="channel", qubit=0, ) @@ -330,7 +330,7 @@ To organize pulses into sequences, Qibolab provides the :class:`qibolab.pulses.P amplitude=0.5, # this amplitude is relative to the range of the instrument frequency=1e8, # frequency are in Hz relative_phase=0, # phases are in radians - shape=Rectangular(), + envelope=Rectangular(), channel="channel", qubit=0, ) @@ -339,7 +339,7 @@ To organize pulses into sequences, Qibolab provides the :class:`qibolab.pulses.P amplitude=0.5, # this amplitude is relative to the range of the instrument frequency=1e8, # frequency are in Hz relative_phase=0, # phases are in radians - shape=Rectangular(), + envelope=Rectangular(), channel="channel", qubit=0, ) @@ -356,7 +356,7 @@ To organize pulses into sequences, Qibolab provides the :class:`qibolab.pulses.P .. testoutput:: python :hide: - Total duration: 160 + Total duration: 160.0 We have 0 pulses on channel 1. @@ -383,7 +383,7 @@ Typical experiments may include both pre-defined pulses and new ones: amplitude=0.5, frequency=2500000000, relative_phase=0, - shape=Rectangular(), + envelope=Rectangular(), channel="0", ) ) @@ -499,7 +499,9 @@ For example: sequence = PulseSequence() sequence.append(platform.create_RX_pulse(0)) - sequence.append(Delay(sequence.duration, platform.qubits[0].readout.name)) + sequence.append( + Delay(duration=sequence.duration, channel=platform.qubits[0].readout.name) + ) sequence.append(platform.create_MZ_pulse(0)) sweeper_freq = Sweeper( diff --git a/doc/source/tutorials/calibration.rst b/doc/source/tutorials/calibration.rst index 13d22925c..ba8a2fee6 100644 --- a/doc/source/tutorials/calibration.rst +++ b/doc/source/tutorials/calibration.rst @@ -117,6 +117,7 @@ complex pulse sequence. Therefore with start with that: AveragingMode, AcquisitionType, ) + from qibolab.serialize_ import replace # allocate platform platform = create_platform("dummy") @@ -124,11 +125,10 @@ complex pulse sequence. Therefore with start with that: # create pulse sequence and add pulses sequence = PulseSequence() drive_pulse = platform.create_RX_pulse(qubit=0) - drive_pulse.duration = 2000 - drive_pulse.amplitude = 0.01 + drive_pulse = replace(drive_pulse, duration=2000, amplitude=0.01) readout_pulse = platform.create_MZ_pulse(qubit=0) sequence.append(drive_pulse) - sequence.append(Delay(drive_pulse.duration, readout_pulse.channel)) + sequence.append(Delay(duration=drive_pulse.duration, channel=readout_pulse.channel)) sequence.append(readout_pulse) # allocate frequency sweeper @@ -222,7 +222,9 @@ and its impact on qubit states in the IQ plane. drive_pulse = platform.create_RX_pulse(qubit=0) readout_pulse1 = platform.create_MZ_pulse(qubit=0) one_sequence.append(drive_pulse) - one_sequence.append(Delay(drive_pulse.duration, readout_pulse1.channel)) + one_sequence.append( + Delay(duration=drive_pulse.duration, channel=readout_pulse1.channel) + ) one_sequence.append(readout_pulse1) # create pulse sequence 2 and add pulses diff --git a/doc/source/tutorials/lab.rst b/doc/source/tutorials/lab.rst index f1e80f5ce..7ca2ca210 100644 --- a/doc/source/tutorials/lab.rst +++ b/doc/source/tutorials/lab.rst @@ -24,7 +24,7 @@ using different Qibolab primitives. from qibolab import Platform from qibolab.qubits import Qubit - from qibolab.pulses import Pulse, PulseType + from qibolab.pulses import Gaussian, Pulse, PulseType, Rectangular from qibolab.channels import ChannelMap, Channel from qibolab.native import SingleQubitNatives from qibolab.instruments.dummy import DummyInstrument @@ -48,18 +48,18 @@ using different Qibolab primitives. RX=Pulse( duration=40, amplitude=0.05, - shape="Gaussian(5)", + envelope=Gaussian(rel_sigma=0.2), type=PulseType.DRIVE, - qubit=qubit, - frequency=int(4.5e9), + qubit=qubit.name, + frequency=4.5e9, ), MZ=Pulse( duration=1000, amplitude=0.005, - shape="Rectangular()", + envelope=Rectangular(), type=PulseType.READOUT, - qubit=qubit, - frequency=int(7e9), + qubit=qubit.name, + frequency=7e9, ), ) @@ -97,7 +97,7 @@ hold the parameters of the two-qubit gates. .. testcode:: python from qibolab.qubits import Qubit, QubitPair - from qibolab.pulses import PulseType, Pulse, PulseSequence + from qibolab.pulses import Gaussian, PulseType, Pulse, PulseSequence, Rectangular from qibolab.native import ( SingleQubitNatives, TwoQubitNatives, @@ -112,36 +112,36 @@ hold the parameters of the two-qubit gates. RX=Pulse( duration=40, amplitude=0.05, - shape="Gaussian(5)", + envelope=Gaussian(rel_sigma=0.2), type=PulseType.DRIVE, - qubit=qubit0, - frequency=int(4.7e9), + qubit=qubit0.name, + frequency=4.7e9, ), MZ=Pulse( duration=1000, amplitude=0.005, - shape="Rectangular()", + envelope=Rectangular(), type=PulseType.READOUT, - qubit=qubit0, - frequency=int(7e9), + qubit=qubit0.name, + frequency=7e9, ), ) qubit1.native_gates = SingleQubitNatives( RX=Pulse( duration=40, amplitude=0.05, - shape="Gaussian(5)", + envelope=Gaussian(rel_sigma=0.2), type=PulseType.DRIVE, - qubit=qubit1, - frequency=int(5.1e9), + qubit=qubit1.name, + frequency=5.1e9, ), MZ=Pulse( duration=1000, amplitude=0.005, - shape="Rectangular()", + envelope=Rectangular(), type=PulseType.READOUT, - qubit=qubit1, - frequency=int(7.5e9), + qubit=qubit1.name, + frequency=7.5e9, ), ) @@ -153,9 +153,10 @@ hold the parameters of the two-qubit gates. Pulse( duration=30, amplitude=0.005, - shape="Rectangular()", + envelope=Rectangular(), type=PulseType.FLUX, - qubit=qubit1, + qubit=qubit1.name, + frequency=1e9, ) ], ) @@ -194,9 +195,10 @@ coupler but qibolab will take them into account when calling :class:`qibolab.nat Pulse( duration=30, amplitude=0.005, - shape="Rectangular()", + frequency=1e9, + envelope=Rectangular(), type=PulseType.FLUX, - qubit=qubit1, + qubit=qubit1.name, ) ], ) @@ -269,14 +271,18 @@ a two-qubit system: "duration": 40, "amplitude": 0.0484, "frequency": 4855663000, - "shape": "Drag(5, -0.02)", + "envelope": { + "kind": "drag", + "rel_sigma": 0.2, + "beta": -0.02, + }, "type": "qd", }, "MZ": { "duration": 620, "amplitude": 0.003575, "frequency": 7453265000, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "type": "ro", } }, @@ -285,14 +291,18 @@ a two-qubit system: "duration": 40, "amplitude": 0.05682, "frequency": 5800563000, - "shape": "Drag(5, -0.04)", + "envelope": { + "kind": "drag", + "rel_sigma": 0.2, + "beta": -0.04, + }, "type": "qd", }, "MZ": { "duration": 960, "amplitude": 0.00325, "frequency": 7655107000, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "type": "ro", } } @@ -303,7 +313,7 @@ a two-qubit system: { "duration": 30, "amplitude": 0.055, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "qubit": 1, "type": "qf" }, @@ -371,7 +381,7 @@ we need the following changes to the previous runcard: { "duration": 30, "amplitude": 0.6025, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "qubit": 1, "type": "qf" }, @@ -389,7 +399,7 @@ we need the following changes to the previous runcard: "type": "cf", "duration": 40, "amplitude": 0.1, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "coupler": 0, } ] @@ -564,14 +574,18 @@ The runcard can contain an ``instruments`` section that provides these parameter "duration": 40, "amplitude": 0.0484, "frequency": 4855663000, - "shape": "Drag(5, -0.02)", + "envelope": { + "kind": "drag", + "rel_sigma": 0.2, + "beta": -0.02, + }, "type": "qd", }, "MZ": { "duration": 620, "amplitude": 0.003575, "frequency": 7453265000, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "type": "ro", } }, @@ -580,14 +594,18 @@ The runcard can contain an ``instruments`` section that provides these parameter "duration": 40, "amplitude": 0.05682, "frequency": 5800563000, - "shape": "Drag(5, -0.04)", + "envelope": { + "kind": "drag", + "rel_sigma": 0.2, + "beta": -0.04, + }, "type": "qd", }, "MZ": { "duration": 960, "amplitude": 0.00325, "frequency": 7655107000, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "type": "ro", } } @@ -598,7 +616,7 @@ The runcard can contain an ``instruments`` section that provides these parameter { "duration": 30, "amplitude": 0.055, - "shape": "Rectangular()", + "envelope": {"kind": "rectangular"}, "qubit": 1, "type": "qf" }, diff --git a/doc/source/tutorials/pulses.rst b/doc/source/tutorials/pulses.rst index b68508bc0..b3b0b7233 100644 --- a/doc/source/tutorials/pulses.rst +++ b/doc/source/tutorials/pulses.rst @@ -20,23 +20,23 @@ pulses (:class:`qibolab.pulses.Pulse`) through the amplitude=0.3, duration=60, relative_phase=0, - shape=Gaussian(5), + envelope=Gaussian(rel_sigma=0.2), qubit=0, type=PulseType.DRIVE, - channel=0, + channel="0", ) ) - sequence.append(Delay(100, channel=1)) + sequence.append(Delay(duration=100, channel="1")) sequence.append( Pulse( frequency=20000000.0, amplitude=0.5, duration=3000, relative_phase=0, - shape=Rectangular(), + envelope=Rectangular(), qubit=0, type=PulseType.READOUT, - channel=1, + channel="1", ) ) diff --git a/flake.lock b/flake.lock index 07ae0529b..4f978df5d 100644 --- a/flake.lock +++ b/flake.lock @@ -1,22 +1,80 @@ { "nodes": { + "cachix": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": "flake-compat_2", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1710475558, + "narHash": "sha256-egKrPCKjy/cE+NqCj4hg2fNX/NwLCf0bRDInraYXDgs=", + "owner": "cachix", + "repo": "cachix", + "rev": "661bbb7f8b55722a0406456b15267b5426a3bda6", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, "devenv": { "inputs": { - "flake-compat": "flake-compat", + "cachix": "cachix", + "flake-compat": "flake-compat_4", + "nix": "nix_2", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks": "pre-commit-hooks_2" + }, + "locked": { + "lastModified": 1711095830, + "narHash": "sha256-E67Yh1R1h8b01nVAhiYJsY6eQFqk5VIar13ntSbi56Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "84ce563fcecbdee90b3c3550ab4f2fcd37b37def", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "pre-commit-hooks" + ] }, "locked": { - "lastModified": 1701187605, - "narHash": "sha256-NctguPdUeDVLXFsv6vI1RlEiHLsXkeW3pgZe/mwn1BU=", + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", "owner": "cachix", "repo": "devenv", - "rev": "a7c4dd8f4eb1f98a6b8f04bf08364954e1e73e4f", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", "type": "github" }, "original": { "owner": "cachix", + "ref": "python-rewrite", "repo": "devenv", "type": "github" } @@ -29,11 +87,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1705904706, - "narHash": "sha256-0aJfyNYWy6pS4GfOA+pmGOE+PgJZLG78T+sPh8zRJx8=", + "lastModified": 1711088506, + "narHash": "sha256-USdlY7Tx2oJWqFBpp10+03+h7eVhpkQ4s9t1ERjeIJE=", "owner": "nix-community", "repo": "fenix", - "rev": "8e7851239acf6bfb06637f4d3e180302f53ec542", + "rev": "85f4139f3c092cf4afd9f9906d7ed218ef262c97", "type": "github" }, "original": { @@ -59,6 +117,54 @@ } }, "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { "flake": false, "locked": { "lastModified": 1673956053, @@ -74,16 +180,32 @@ "type": "github" } }, + "flake-compat_6": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", "type": "github" }, "original": { @@ -97,11 +219,47 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", "type": "github" }, "original": { @@ -113,16 +271,17 @@ "inputs": { "nixpkgs": [ "devenv", + "cachix", "pre-commit-hooks", "nixpkgs" ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", "type": "github" }, "original": { @@ -131,53 +290,109 @@ "type": "github" } }, - "lowdown-src": { - "flake": false, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1633514407, - "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", "type": "github" }, "original": { - "owner": "kristapsdz", - "repo": "lowdown", + "owner": "hercules-ci", + "repo": "gitignore.nix", "type": "github" } }, "nix": { "inputs": { - "lowdown-src": "lowdown-src", + "flake-compat": "flake-compat", "nixpkgs": [ + "devenv", + "cachix", "devenv", "nixpkgs" ], "nixpkgs-regression": "nixpkgs-regression" }, "locked": { - "lastModified": 1676545802, - "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "lastModified": 1708577783, + "narHash": "sha256-92xq7eXlxIT5zFNccLpjiP7sdQqQI30Gyui2p/PfKZM=", "owner": "domenkozar", "repo": "nix", - "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "rev": "ecd0af0c1f56de32cbad14daa1d82a132bf298f8", "type": "github" }, "original": { "owner": "domenkozar", - "ref": "relaxed-flakes", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": "flake-compat_5", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_2" + }, + "locked": { + "lastModified": 1710500156, + "narHash": "sha256-zvCqeUO2GLOm7jnU23G4EzTZR7eylcJN+HJ5svjmubI=", + "owner": "domenkozar", + "repo": "nix", + "rev": "c5bbf14ecbd692eeabf4184cc8d50f79c2446549", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", "repo": "nix", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1678875422, - "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", "type": "github" }, "original": { @@ -189,18 +404,18 @@ }, "nixpkgs-python": { "inputs": { - "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils_2", + "flake-compat": "flake-compat_6", + "flake-utils": "flake-utils_4", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1702034373, - "narHash": "sha256-Apubv9die/XRBPI0eRFJyvuyGz/wD4YQUQJHRYCRenc=", + "lastModified": 1710929962, + "narHash": "sha256-CuPuUyX1TmxJDDZFOZMr7kHTzA8zoSJaVw0+jDVo2fw=", "owner": "cachix", "repo": "nixpkgs-python", - "rev": "1cae686aa92dbccafe74fd242f984c3ec27c0b20", + "rev": "a9e19aafbf75b8c7e5adf2d7319939309ebe0d77", "type": "github" }, "original": { @@ -225,29 +440,61 @@ "type": "github" } }, + "nixpkgs-regression_2": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, "nixpkgs-stable": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "lastModified": 1704874635, + "narHash": "sha256-YWuCrtsty5vVZvu+7BchAxmcYzTMfolSPP5io8+WYCg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3dc440faeee9e889fe2d1b4d25ad0f430d449356", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1704874635, + "narHash": "sha256-YWuCrtsty5vVZvu+7BchAxmcYzTMfolSPP5io8+WYCg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "3dc440faeee9e889fe2d1b4d25ad0f430d449356", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1702312524, - "narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=", + "lastModified": 1710806803, + "narHash": "sha256-qrxvLS888pNJFwJdK+hf1wpRCSQcqA6W5+Ox202NDa0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a9bf124c46ef298113270b1f84a164865987a91c", + "rev": "b06025f1533a1e07b6db3e75151caa155d1c7eb3", "type": "github" }, "original": { @@ -257,26 +504,77 @@ "type": "github" } }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat_3", + "flake-utils": "flake-utils_2", + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "cachix", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1708018599, + "narHash": "sha256-M+Ng6+SePmA8g06CmUZWi1AjG2tFBX9WCXElBHEKnyM=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_2": { "inputs": { "flake-compat": [ "devenv", "flake-compat" ], - "flake-utils": "flake-utils", - "gitignore": "gitignore", + "flake-utils": "flake-utils_3", + "gitignore": "gitignore_2", "nixpkgs": [ "devenv", "nixpkgs" ], - "nixpkgs-stable": "nixpkgs-stable" + "nixpkgs-stable": "nixpkgs-stable_2" }, "locked": { - "lastModified": 1688056373, - "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", + "lastModified": 1708018599, + "narHash": "sha256-M+Ng6+SePmA8g06CmUZWi1AjG2tFBX9WCXElBHEKnyM=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", "type": "github" }, "original": { @@ -291,17 +589,17 @@ "fenix": "fenix", "nixpkgs": "nixpkgs_2", "nixpkgs-python": "nixpkgs-python", - "systems": "systems_3" + "systems": "systems_5" } }, "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1705864945, - "narHash": "sha256-ZATChFWHToTZQFLlzrzDUX8fjEbMHHBIyPaZU1JGmjI=", + "lastModified": 1711052942, + "narHash": "sha256-lLsAhLgm/Nbin41wdfGKU7Rgd6ONBxYCUAMv53NXPjo=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "d410d4a2baf9e99b37b03dd42f06238b14374bf7", + "rev": "7ef7f442fc34b5eadb1c6ad6433bd6d0c51b056b", "type": "github" }, "original": { @@ -355,6 +653,36 @@ "repo": "default", "type": "github" } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 2f83dfbc1..ff712b5db 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,10 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; systems.url = "github:nix-systems/default"; - devenv.url = "github:cachix/devenv"; + devenv = { + url = "github:cachix/devenv"; + inputs.nixpkgs.follows = "nixpkgs"; + }; nixpkgs-python = { url = "github:cachix/nixpkgs-python"; inputs.nixpkgs.follows = "nixpkgs"; @@ -35,8 +38,6 @@ forEachSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; - pwd = builtins.getEnv "PWD"; - platforms = builtins.toPath "${pwd}/../qibolab_platforms_qrc/"; in { default = devenv.lib.mkShell { inherit inputs pkgs; @@ -47,7 +48,7 @@ config, ... }: { - packages = with pkgs; [pre-commit poethepoet jupyter stdenv.cc.cc.lib zlib]; + packages = with pkgs; [pre-commit poethepoet jupyter zlib]; env = { QIBOLAB_PLATFORMS = (dirOf config.env.DEVENV_ROOT) + "/qibolab_platforms_qrc"; @@ -66,7 +67,7 @@ poetry = { enable = true; install.enable = true; - install.groups = ["dev" "tests"]; + install.groups = ["dev" "analysis" "tests"]; install.allExtras = true; }; version = "3.11"; diff --git a/poetry.lock b/poetry.lock index b256d5f33..f010201a8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "alabaster" @@ -1705,13 +1705,13 @@ colors = ["colorama (>=0.4.6)"] [[package]] name = "itsdangerous" -version = "2.1.2" +version = "2.2.0" description = "Safely pass data to untrusted environments and back." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, - {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, + {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, + {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, ] [[package]] @@ -2297,13 +2297,13 @@ python-dateutil = ">=2.7" [[package]] name = "matplotlib-inline" -version = "0.1.6" +version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, - {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, + {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, + {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, ] [package.dependencies] @@ -2768,62 +2768,62 @@ tests = ["pytest (>=6.0)", "pyyaml"] [[package]] name = "orjson" -version = "3.10.0" +version = "3.10.1" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.0-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47af5d4b850a2d1328660661f0881b67fdbe712aea905dadd413bdea6f792c33"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c90681333619d78360d13840c7235fdaf01b2b129cb3a4f1647783b1971542b6"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:400c5b7c4222cb27b5059adf1fb12302eebcabf1978f33d0824aa5277ca899bd"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dcb32e949eae80fb335e63b90e5808b4b0f64e31476b3777707416b41682db5"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7d507c7493252c0a0264b5cc7e20fa2f8622b8a83b04d819b5ce32c97cf57b"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e286a51def6626f1e0cc134ba2067dcf14f7f4b9550f6dd4535fd9d79000040b"}, - {file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8acd4b82a5f3a3ec8b1dc83452941d22b4711964c34727eb1e65449eead353ca"}, - {file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:30707e646080dd3c791f22ce7e4a2fc2438765408547c10510f1f690bd336217"}, - {file = "orjson-3.10.0-cp310-none-win32.whl", hash = "sha256:115498c4ad34188dcb73464e8dc80e490a3e5e88a925907b6fedcf20e545001a"}, - {file = "orjson-3.10.0-cp310-none-win_amd64.whl", hash = "sha256:6735dd4a5a7b6df00a87d1d7a02b84b54d215fb7adac50dd24da5997ffb4798d"}, - {file = "orjson-3.10.0-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9587053e0cefc284e4d1cd113c34468b7d3f17666d22b185ea654f0775316a26"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bef1050b1bdc9ea6c0d08468e3e61c9386723633b397e50b82fda37b3563d72"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d16c6963ddf3b28c0d461641517cd312ad6b3cf303d8b87d5ef3fa59d6844337"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4251964db47ef090c462a2d909f16c7c7d5fe68e341dabce6702879ec26d1134"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73bbbdc43d520204d9ef0817ac03fa49c103c7f9ea94f410d2950755be2c349c"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:414e5293b82373606acf0d66313aecb52d9c8c2404b1900683eb32c3d042dbd7"}, - {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:feaed5bb09877dc27ed0d37f037ddef6cb76d19aa34b108db270d27d3d2ef747"}, - {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5127478260db640323cea131ee88541cb1a9fbce051f0b22fa2f0892f44da302"}, - {file = "orjson-3.10.0-cp311-none-win32.whl", hash = "sha256:b98345529bafe3c06c09996b303fc0a21961820d634409b8639bc16bd4f21b63"}, - {file = "orjson-3.10.0-cp311-none-win_amd64.whl", hash = "sha256:658ca5cee3379dd3d37dbacd43d42c1b4feee99a29d847ef27a1cb18abdfb23f"}, - {file = "orjson-3.10.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4329c1d24fd130ee377e32a72dc54a3c251e6706fccd9a2ecb91b3606fddd998"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef0f19fdfb6553342b1882f438afd53c7cb7aea57894c4490c43e4431739c700"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c4f60db24161534764277f798ef53b9d3063092f6d23f8f962b4a97edfa997a0"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1de3fd5c7b208d836f8ecb4526995f0d5877153a4f6f12f3e9bf11e49357de98"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f93e33f67729d460a177ba285002035d3f11425ed3cebac5f6ded4ef36b28344"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:237ba922aef472761acd697eef77fef4831ab769a42e83c04ac91e9f9e08fa0e"}, - {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98c1bfc6a9bec52bc8f0ab9b86cc0874b0299fccef3562b793c1576cf3abb570"}, - {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30d795a24be16c03dca0c35ca8f9c8eaaa51e3342f2c162d327bd0225118794a"}, - {file = "orjson-3.10.0-cp312-none-win32.whl", hash = "sha256:6a3f53dc650bc860eb26ec293dfb489b2f6ae1cbfc409a127b01229980e372f7"}, - {file = "orjson-3.10.0-cp312-none-win_amd64.whl", hash = "sha256:983db1f87c371dc6ffc52931eb75f9fe17dc621273e43ce67bee407d3e5476e9"}, - {file = "orjson-3.10.0-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a667769a96a72ca67237224a36faf57db0c82ab07d09c3aafc6f956196cfa1b"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade1e21dfde1d37feee8cf6464c20a2f41fa46c8bcd5251e761903e46102dc6b"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:23c12bb4ced1c3308eff7ba5c63ef8f0edb3e4c43c026440247dd6c1c61cea4b"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2d014cf8d4dc9f03fc9f870de191a49a03b1bcda51f2a957943fb9fafe55aac"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eadecaa16d9783affca33597781328e4981b048615c2ddc31c47a51b833d6319"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd583341218826f48bd7c6ebf3310b4126216920853cbc471e8dbeaf07b0b80e"}, - {file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:90bfc137c75c31d32308fd61951d424424426ddc39a40e367704661a9ee97095"}, - {file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13b5d3c795b09a466ec9fcf0bd3ad7b85467d91a60113885df7b8d639a9d374b"}, - {file = "orjson-3.10.0-cp38-none-win32.whl", hash = "sha256:5d42768db6f2ce0162544845facb7c081e9364a5eb6d2ef06cd17f6050b048d8"}, - {file = "orjson-3.10.0-cp38-none-win_amd64.whl", hash = "sha256:33e6655a2542195d6fd9f850b428926559dee382f7a862dae92ca97fea03a5ad"}, - {file = "orjson-3.10.0-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4050920e831a49d8782a1720d3ca2f1c49b150953667eed6e5d63a62e80f46a2"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1897aa25a944cec774ce4a0e1c8e98fb50523e97366c637b7d0cddabc42e6643"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9bf565a69e0082ea348c5657401acec3cbbb31564d89afebaee884614fba36b4"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6ebc17cfbbf741f5c1a888d1854354536f63d84bee537c9a7c0335791bb9009"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2817877d0b69f78f146ab305c5975d0618df41acf8811249ee64231f5953fee"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57d017863ec8aa4589be30a328dacd13c2dc49de1c170bc8d8c8a98ece0f2925"}, - {file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:22c2f7e377ac757bd3476ecb7480c8ed79d98ef89648f0176deb1da5cd014eb7"}, - {file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e62ba42bfe64c60c1bc84799944f80704e996592c6b9e14789c8e2a303279912"}, - {file = "orjson-3.10.0-cp39-none-win32.whl", hash = "sha256:60c0b1bdbccd959ebd1575bd0147bd5e10fc76f26216188be4a36b691c937077"}, - {file = "orjson-3.10.0-cp39-none-win_amd64.whl", hash = "sha256:175a41500ebb2fdf320bf78e8b9a75a1279525b62ba400b2b2444e274c2c8bee"}, - {file = "orjson-3.10.0.tar.gz", hash = "sha256:ba4d8cac5f2e2cff36bea6b6481cdb92b38c202bcec603d6f5ff91960595a1ed"}, + {file = "orjson-3.10.1-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8ec2fc456d53ea4a47768f622bb709be68acd455b0c6be57e91462259741c4f3"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e900863691d327758be14e2a491931605bd0aded3a21beb6ce133889830b659"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab6ecbd6fe57785ebc86ee49e183f37d45f91b46fc601380c67c5c5e9c0014a2"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af7c68b01b876335cccfb4eee0beef2b5b6eae1945d46a09a7c24c9faac7a77"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:915abfb2e528677b488a06eba173e9d7706a20fdfe9cdb15890b74ef9791b85e"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe3fd4a36eff9c63d25503b439531d21828da9def0059c4f472e3845a081aa0b"}, + {file = "orjson-3.10.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d229564e72cfc062e6481a91977a5165c5a0fdce11ddc19ced8471847a67c517"}, + {file = "orjson-3.10.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9e00495b18304173ac843b5c5fbea7b6f7968564d0d49bef06bfaeca4b656f4e"}, + {file = "orjson-3.10.1-cp310-none-win32.whl", hash = "sha256:fd78ec55179545c108174ba19c1795ced548d6cac4d80d014163033c047ca4ea"}, + {file = "orjson-3.10.1-cp310-none-win_amd64.whl", hash = "sha256:50ca42b40d5a442a9e22eece8cf42ba3d7cd4cd0f2f20184b4d7682894f05eec"}, + {file = "orjson-3.10.1-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b345a3d6953628df2f42502297f6c1e1b475cfbf6268013c94c5ac80e8abc04c"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caa7395ef51af4190d2c70a364e2f42138e0e5fcb4bc08bc9b76997659b27dab"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b01d701decd75ae092e5f36f7b88a1e7a1d3bb7c9b9d7694de850fb155578d5a"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5028981ba393f443d8fed9049211b979cadc9d0afecf162832f5a5b152c6297"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31ff6a222ea362b87bf21ff619598a4dc1106aaafaea32b1c4876d692891ec27"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e852a83d7803d3406135fb7a57cf0c1e4a3e73bac80ec621bd32f01c653849c5"}, + {file = "orjson-3.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2567bc928ed3c3fcd90998009e8835de7c7dc59aabcf764b8374d36044864f3b"}, + {file = "orjson-3.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4ce98cac60b7bb56457bdd2ed7f0d5d7f242d291fdc0ca566c83fa721b52e92d"}, + {file = "orjson-3.10.1-cp311-none-win32.whl", hash = "sha256:813905e111318acb356bb8029014c77b4c647f8b03f314e7b475bd9ce6d1a8ce"}, + {file = "orjson-3.10.1-cp311-none-win_amd64.whl", hash = "sha256:03a3ca0b3ed52bed1a869163a4284e8a7b0be6a0359d521e467cdef7e8e8a3ee"}, + {file = "orjson-3.10.1-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f02c06cee680b1b3a8727ec26c36f4b3c0c9e2b26339d64471034d16f74f4ef5"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1aa2f127ac546e123283e437cc90b5ecce754a22306c7700b11035dad4ccf85"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2cf29b4b74f585225196944dffdebd549ad2af6da9e80db7115984103fb18a96"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1b130c20b116f413caf6059c651ad32215c28500dce9cd029a334a2d84aa66f"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d31f9a709e6114492136e87c7c6da5e21dfedebefa03af85f3ad72656c493ae9"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d1d169461726f271ab31633cf0e7e7353417e16fb69256a4f8ecb3246a78d6e"}, + {file = "orjson-3.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:57c294d73825c6b7f30d11c9e5900cfec9a814893af7f14efbe06b8d0f25fba9"}, + {file = "orjson-3.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d7f11dbacfa9265ec76b4019efffabaabba7a7ebf14078f6b4df9b51c3c9a8ea"}, + {file = "orjson-3.10.1-cp312-none-win32.whl", hash = "sha256:d89e5ed68593226c31c76ab4de3e0d35c760bfd3fbf0a74c4b2be1383a1bf123"}, + {file = "orjson-3.10.1-cp312-none-win_amd64.whl", hash = "sha256:aa76c4fe147fd162107ce1692c39f7189180cfd3a27cfbc2ab5643422812da8e"}, + {file = "orjson-3.10.1-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a2c6a85c92d0e494c1ae117befc93cf8e7bca2075f7fe52e32698da650b2c6d1"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9813f43da955197d36a7365eb99bed42b83680801729ab2487fef305b9ced866"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec917b768e2b34b7084cb6c68941f6de5812cc26c6f1a9fecb728e36a3deb9e8"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5252146b3172d75c8a6d27ebca59c9ee066ffc5a277050ccec24821e68742fdf"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:536429bb02791a199d976118b95014ad66f74c58b7644d21061c54ad284e00f4"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dfed3c3e9b9199fb9c3355b9c7e4649b65f639e50ddf50efdf86b45c6de04b5"}, + {file = "orjson-3.10.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2b230ec35f188f003f5b543644ae486b2998f6afa74ee3a98fc8ed2e45960afc"}, + {file = "orjson-3.10.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:01234249ba19c6ab1eb0b8be89f13ea21218b2d72d496ef085cfd37e1bae9dd8"}, + {file = "orjson-3.10.1-cp38-none-win32.whl", hash = "sha256:8a884fbf81a3cc22d264ba780920d4885442144e6acaa1411921260416ac9a54"}, + {file = "orjson-3.10.1-cp38-none-win_amd64.whl", hash = "sha256:dab5f802d52b182163f307d2b1f727d30b1762e1923c64c9c56dd853f9671a49"}, + {file = "orjson-3.10.1-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a51fd55d4486bc5293b7a400f9acd55a2dc3b5fc8420d5ffe9b1d6bb1a056a5e"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53521542a6db1411b3bfa1b24ddce18605a3abdc95a28a67b33f9145f26aa8f2"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:27d610df96ac18ace4931411d489637d20ab3b8f63562b0531bba16011998db0"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79244b1456e5846d44e9846534bd9e3206712936d026ea8e6a55a7374d2c0694"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d751efaa8a49ae15cbebdda747a62a9ae521126e396fda8143858419f3b03610"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27ff69c620a4fff33267df70cfd21e0097c2a14216e72943bd5414943e376d77"}, + {file = "orjson-3.10.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ebc58693464146506fde0c4eb1216ff6d4e40213e61f7d40e2f0dde9b2f21650"}, + {file = "orjson-3.10.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5be608c3972ed902e0143a5b8776d81ac1059436915d42defe5c6ae97b3137a4"}, + {file = "orjson-3.10.1-cp39-none-win32.whl", hash = "sha256:4ae10753e7511d359405aadcbf96556c86e9dbf3a948d26c2c9f9a150c52b091"}, + {file = "orjson-3.10.1-cp39-none-win_amd64.whl", hash = "sha256:fb5bc4caa2c192077fdb02dce4e5ef8639e7f20bec4e3a834346693907362932"}, + {file = "orjson-3.10.1.tar.gz", hash = "sha256:a883b28d73370df23ed995c466b4f6c708c1f7a9bdc400fe89165c96c7603204"}, ] [[package]] @@ -2858,7 +2858,6 @@ files = [ {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, @@ -5775,4 +5774,4 @@ zh = ["laboneq"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "1008e6c91ae52ce53280b44fc88b2772d73de8869aa479fabee3bb8d7c085f01" +content-hash = "f6936794bf8da84d55fdff23d1c1ac5730f47e0efebf70fa32990c0f8cb057de" diff --git a/pyproject.toml b/pyproject.toml index a545b77ad..50cf59915 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,12 +26,13 @@ qibo = ">=0.2.6" networkx = "^3.0" numpy = "^1.26.4" more-itertools = "^9.1.0" +pydantic = "^2.6.4" qblox-instruments = { version = "0.12.0", optional = true } qcodes = { version = "^0.37.0", optional = true } qcodes_contrib_drivers = { version = "0.18.0", optional = true } pyvisa-py = { version = "0.5.3", optional = true } qm-qua = { version = "==1.1.6", optional = true } -qualang-tools = { version = "^0.15.0", optional = true} +qualang-tools = { version = "^0.15.0", optional = true } setuptools = { version = ">67.0.0", optional = true } laboneq = { version = "==2.25.0", optional = true } qibosoq = { version = ">=0.1.2,<0.2", optional = true } diff --git a/src/qibolab/compilers/compiler.py b/src/qibolab/compilers/compiler.py index 191971e80..1499f31ca 100644 --- a/src/qibolab/compilers/compiler.py +++ b/src/qibolab/compilers/compiler.py @@ -155,7 +155,7 @@ def compile(self, circuit, platform): for pulse in gate_sequence: if qubit_clock[pulse.qubit] > channel_clock[pulse.qubit]: delay = qubit_clock[pulse.qubit] - channel_clock[pulse.channel] - sequence.append(Delay(delay, pulse.channel)) + sequence.append(Delay(duration=delay, channel=pulse.channel)) channel_clock[pulse.channel] += delay sequence.append(pulse) diff --git a/src/qibolab/compilers/default.py b/src/qibolab/compilers/default.py index c59360c88..227b07af5 100644 --- a/src/qibolab/compilers/default.py +++ b/src/qibolab/compilers/default.py @@ -4,9 +4,9 @@ """ import math -from dataclasses import replace from qibolab.pulses import PulseSequence, VirtualZ +from qibolab.serialize_ import replace def identity_rule(gate, qubit): diff --git a/src/qibolab/dummy/parameters.json b/src/qibolab/dummy/parameters.json index 7cd488097..e1aa0b669 100644 --- a/src/qibolab/dummy/parameters.json +++ b/src/qibolab/dummy/parameters.json @@ -1,640 +1,687 @@ { - "nqubits": 5, - "settings": { - "nshots": 1024, - "relaxation_time": 0 + "nqubits": 5, + "settings": { + "nshots": 1024, + "relaxation_time": 0 + }, + "qubits": [0, 1, 2, 3, 4], + "couplers": [0, 1, 3, 4], + "topology": { + "0": [0, 2], + "1": [1, 2], + "3": [2, 3], + "4": [2, 4] + }, + "instruments": { + "dummy": { + "bounds": { + "waveforms": 0, + "readout": 0, + "instructions": 0 + } }, - "qubits": [ - 0, - 1, - 2, - 3, - 4 - ], - "couplers": [ - 0, - 1, - 3, - 4 - ], - "topology": { - "0": [ - 0, - 2 - ], - "1": [ - 1, - 2 - ], - "3": [ - 2, - 3 - ], - "4": [ - 2, - 4 - ] - }, - "instruments": { - "dummy": { - "bounds": { - "waveforms": 0, - "readout": 0, - "instructions": 0 - } + "twpa_pump": { + "power": 10, + "frequency": 1000000000.0 + } + }, + "native_gates": { + "single_qubit": { + "0": { + "RX": { + "duration": 40, + "amplitude": 0.1, + "envelope": { "kind": "gaussian", "rel_sigma": 5 }, + "frequency": 4000000000.0, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.005, + "envelope": { "kind": "gaussian", "rel_sigma": 5 }, + "frequency": 4700000000, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.1, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "frequency": 5200000000.0, + "type": "ro" + } + }, + "1": { + "RX": { + "duration": 40, + "amplitude": 0.3, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 4200000000.0, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.0484, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 4855663000, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.1, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "frequency": 4900000000.0, + "type": "ro" + } + }, + "2": { + "RX": { + "duration": 40, + "amplitude": 0.3, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 4500000000.0, + "type": "qd" }, - "twpa_pump": { - "power": 10, - "frequency": 1000000000.0 + "RX12": { + "duration": 40, + "amplitude": 0.005, + "envelope": { "kind": "gaussian", "rel_sigma": 5 }, + "frequency": 2700000000, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.1, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "frequency": 6100000000.0, + "type": "ro" + } + }, + "3": { + "RX": { + "duration": 40, + "amplitude": 0.3, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 4150000000.0, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.0484, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 5855663000, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.1, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "frequency": 5800000000.0, + "type": "ro" + } + }, + "4": { + "RX": { + "duration": 40, + "amplitude": 0.3, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 4155663000, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.0484, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 5855663000, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.1, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "frequency": 5500000000.0, + "type": "ro" } + } }, - "native_gates": { - "single_qubit": { - "0": { - "RX": { - "duration": 40, - "amplitude": 0.1, - "shape": "Gaussian(5)", - "frequency": 4000000000.0, - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.005, - "shape": "Gaussian(5)", - "frequency": 4700000000, - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.1, - "shape": "GaussianSquare(5, 0.75)", - "frequency": 5200000000.0, - "type": "ro" - } - }, - "1": { - "RX": { - "duration": 40, - "amplitude": 0.3, - "shape": "Drag(5, 0.02)", - "frequency": 4200000000.0, - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.0484, - "shape": "Drag(5, 0.02)", - "frequency": 4855663000, - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.1, - "shape": "GaussianSquare(5, 0.75)", - "frequency": 4900000000.0, - "type": "ro" - } + "coupler": { + "0": { + "CP": { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "type": "cf" + } + }, + "1": { + "CP": { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "type": "cf" + } + }, + "3": { + "CP": { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "type": "cf" + } + }, + "4": { + "CP": { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 + }, + "type": "cf" + } + } + }, + "two_qubit": { + "0-2": { + "CZ": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "2": { - "RX": { - "duration": 40, - "amplitude": 0.3, - "shape": "Drag(5, 0.02)", - "frequency": 4500000000.0, - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.005, - "shape": "Gaussian(5)", - "frequency": 2700000000, - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.1, - "shape": "GaussianSquare(5, 0.75)", - "frequency": 6100000000.0, - "type": "ro" - } + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 0 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "3": { - "RX": { - "duration": 40, - "amplitude": 0.3, - "shape": "Drag(5, 0.02)", - "frequency": 4150000000.0, - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.0484, - "shape": "Drag(5, 0.02)", - "frequency": 5855663000, - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.1, - "shape": "GaussianSquare(5, 0.75)", - "frequency": 5800000000.0, - "type": "ro" - } + "coupler": 0, + "type": "cf" + } + ], + "iSWAP": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "4": { - "RX": { - "duration": 40, - "amplitude": 0.3, - "shape": "Drag(5, 0.02)", - "frequency": 4155663000, - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.0484, - "shape": "Drag(5, 0.02)", - "frequency": 5855663000, - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.1, - "shape": "GaussianSquare(5, 0.75)", - "frequency": 5500000000.0, - "type": "ro" - } - } - }, - "coupler": { - "0": { - "CP": { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "type": "cf" - } + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 1 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "1": { - "CP": { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "type": "cf" - } + "coupler": 0, + "type": "cf" + } + ] + }, + "1-2": { + "CZ": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "3": { - "CP": { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "type": "cf" - } + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 1 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "4": { - "CP": { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "type": "cf" - } - } - }, - "two_qubit": { - "0-2": { - "CZ": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 0 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 0, - "type": "cf" - } - ], - "iSWAP": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 0, - "type": "cf" - } - ] + "coupler": 1, + "type": "cf" + } + ], + "iSWAP": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "1-2": { - "CZ": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 1, - "type": "cf" - } - ], - "iSWAP": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 1, - "type": "cf" - } - ] + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 1 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "2-3": { - "CZ": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 3 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 3, - "type": "cf" - } - ], - "iSWAP": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 3, - "type": "cf" - } - ], - "CNOT": [ - { - "duration": 40, - "amplitude": 0.3, - "shape": "Drag(5, 0.02)", - "frequency": 4150000000.0, - "type": "qd", - "qubit": 2 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - } - ] + "coupler": 1, + "type": "cf" + } + ] + }, + "2-3": { + "CZ": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "2-4": { - "CZ": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 4 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 4, - "type": "cf" - } - ], - "iSWAP": [ - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": 0.0, - "qubit": 2 - }, - { - "duration": 30, - "amplitude": 0.05, - "shape": "GaussianSquare(5, 0.75)", - "coupler": 4, - "type": "cf" - } - ] - } - } - }, - "characterization": { - "single_qubit": { - "0": { - "bare_resonator_frequency": 0, - "readout_frequency": 5200000000.0, - "drive_frequency": 4000000000.0, - "anharmonicity": 0, - "sweetspot": 0.0, - "asymmetry": 0.0, - "crosstalk_matrix": { - "0": 1 - }, - "Ec": 0.0, - "Ej": 0.0, - "g": 0.0, - "assignment_fidelity": 0.0, - "peak_voltage": 0, - "pi_pulse_amplitude": 0, - "T1": 0.0, - "T2": 0.0, - "T2_spin_echo": 0, - "state0_voltage": 0, - "state1_voltage": 0, - "mean_gnd_states": [ - 0, - 1 - ], - "mean_exc_states": [ - 1, - 0 - ], - "threshold": 0.0, - "iq_angle": 0.0, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 3 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "1": { - "bare_resonator_frequency": 0, - "readout_frequency": 4900000000.0, - "drive_frequency": 4200000000.0, - "anharmonicity": 0, - "sweetspot": 0.0, - "asymmetry": 0.0, - "crosstalk_matrix": { - "1": 1 - }, - "Ec": 0.0, - "Ej": 0.0, - "g": 0.0, - "assignment_fidelity": 0.0, - "peak_voltage": 0, - "pi_pulse_amplitude": 0, - "T1": 0.0, - "T2": 0.0, - "T2_spin_echo": 0, - "state0_voltage": 0, - "state1_voltage": 0, - "mean_gnd_states": [ - 0.25, - 0 - ], - "mean_exc_states": [ - 0, - 0.25 - ], - "threshold": 0.0, - "iq_angle": 0.0, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 + "coupler": 3, + "type": "cf" + } + ], + "iSWAP": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "2": { - "bare_resonator_frequency": 0, - "readout_frequency": 6100000000.0, - "drive_frequency": 4500000000.0, - "anharmonicity": 0, - "sweetspot": 0.0, - "asymmetry": 0.0, - "crosstalk_matrix": { - "2": 1 - }, - "Ec": 0.0, - "Ej": 0.0, - "g": 0.0, - "assignment_fidelity": 0.0, - "peak_voltage": 0, - "pi_pulse_amplitude": 0, - "T1": 0.0, - "T2": 0.0, - "T2_spin_echo": 0, - "state0_voltage": 0, - "state1_voltage": 0, - "mean_gnd_states": [ - 0.5, - 0 - ], - "mean_exc_states": [ - 0, - 0.5 - ], - "threshold": 0.0, - "iq_angle": 0.0, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 1 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "3": { - "bare_resonator_frequency": 0, - "readout_frequency": 5800000000.0, - "drive_frequency": 4150000000.0, - "anharmonicity": 0, - "sweetspot": 0.0, - "asymmetry": 0.0, - "crosstalk_matrix": { - "3": 1 - }, - "Ec": 0.0, - "Ej": 0.0, - "g": 0.0, - "assignment_fidelity": 0.0, - "peak_voltage": 0, - "pi_pulse_amplitude": 0, - "T1": 0.0, - "T2": 0.0, - "T2_spin_echo": 0, - "state0_voltage": 0, - "state1_voltage": 0, - "mean_gnd_states": [ - 0.75, - 0 - ], - "mean_exc_states": [ - 0, - 0.75 - ], - "threshold": 0.0, - "iq_angle": 0.0, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 + "coupler": 3, + "type": "cf" + } + ], + "CNOT": [ + { + "duration": 40, + "amplitude": 0.3, + "envelope": { "kind": "drag", "rel_sigma": 5, "beta": 0.02 }, + "frequency": 4150000000.0, + "type": "qd", + "qubit": 2 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 1 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + } + ] + }, + "2-4": { + "CZ": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "4": { - "bare_resonator_frequency": 0, - "readout_frequency": 5500000000.0, - "drive_frequency": 4100000000.0, - "anharmonicity": 0, - "sweetspot": 0.0, - "asymmetry": 0.0, - "crosstalk_matrix": { - "4": 1 - }, - "Ec": 0.0, - "Ej": 0.0, - "g": 0.0, - "assignment_fidelity": 0.0, - "peak_voltage": 0, - "pi_pulse_amplitude": 0, - "T1": 0.0, - "T2": 0.0, - "T2_spin_echo": 0, - "state0_voltage": 0, - "state1_voltage": 0, - "mean_gnd_states": [ - 1, - 0 - ], - "mean_exc_states": [ - 0, - 1 - ], - "threshold": 0.0, - "iq_angle": 0.0, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - } - }, - "coupler": { - "0": { - "sweetspot": 0.0 + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 4 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "1": { - "sweetspot": 0.0 + "coupler": 4, + "type": "cf" + } + ], + "iSWAP": [ + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "3": { - "sweetspot": 0.0 + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 1 + }, + { + "type": "vz", + "phase": 0.0, + "qubit": 2 + }, + { + "duration": 30, + "amplitude": 0.05, + "envelope": { + "kind": "gaussian_square", + "rel_sigma": 5, + "width": 0.75 }, - "4": { - "sweetspot": 0.0 - } - } + "coupler": 4, + "type": "cf" + } + ] + } + } + }, + "characterization": { + "single_qubit": { + "0": { + "bare_resonator_frequency": 0, + "readout_frequency": 5200000000.0, + "drive_frequency": 4000000000.0, + "anharmonicity": 0, + "sweetspot": 0.0, + "asymmetry": 0.0, + "crosstalk_matrix": { + "0": 1 + }, + "Ec": 0.0, + "Ej": 0.0, + "g": 0.0, + "assignment_fidelity": 0.0, + "peak_voltage": 0, + "pi_pulse_amplitude": 0, + "T1": 0.0, + "T2": 0.0, + "T2_spin_echo": 0, + "state0_voltage": 0, + "state1_voltage": 0, + "mean_gnd_states": [0, 1], + "mean_exc_states": [1, 0], + "threshold": 0.0, + "iq_angle": 0.0, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "1": { + "bare_resonator_frequency": 0, + "readout_frequency": 4900000000.0, + "drive_frequency": 4200000000.0, + "anharmonicity": 0, + "sweetspot": 0.0, + "asymmetry": 0.0, + "crosstalk_matrix": { + "1": 1 + }, + "Ec": 0.0, + "Ej": 0.0, + "g": 0.0, + "assignment_fidelity": 0.0, + "peak_voltage": 0, + "pi_pulse_amplitude": 0, + "T1": 0.0, + "T2": 0.0, + "T2_spin_echo": 0, + "state0_voltage": 0, + "state1_voltage": 0, + "mean_gnd_states": [0.25, 0], + "mean_exc_states": [0, 0.25], + "threshold": 0.0, + "iq_angle": 0.0, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "2": { + "bare_resonator_frequency": 0, + "readout_frequency": 6100000000.0, + "drive_frequency": 4500000000.0, + "anharmonicity": 0, + "sweetspot": 0.0, + "asymmetry": 0.0, + "crosstalk_matrix": { + "2": 1 + }, + "Ec": 0.0, + "Ej": 0.0, + "g": 0.0, + "assignment_fidelity": 0.0, + "peak_voltage": 0, + "pi_pulse_amplitude": 0, + "T1": 0.0, + "T2": 0.0, + "T2_spin_echo": 0, + "state0_voltage": 0, + "state1_voltage": 0, + "mean_gnd_states": [0.5, 0], + "mean_exc_states": [0, 0.5], + "threshold": 0.0, + "iq_angle": 0.0, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "3": { + "bare_resonator_frequency": 0, + "readout_frequency": 5800000000.0, + "drive_frequency": 4150000000.0, + "anharmonicity": 0, + "sweetspot": 0.0, + "asymmetry": 0.0, + "crosstalk_matrix": { + "3": 1 + }, + "Ec": 0.0, + "Ej": 0.0, + "g": 0.0, + "assignment_fidelity": 0.0, + "peak_voltage": 0, + "pi_pulse_amplitude": 0, + "T1": 0.0, + "T2": 0.0, + "T2_spin_echo": 0, + "state0_voltage": 0, + "state1_voltage": 0, + "mean_gnd_states": [0.75, 0], + "mean_exc_states": [0, 0.75], + "threshold": 0.0, + "iq_angle": 0.0, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "4": { + "bare_resonator_frequency": 0, + "readout_frequency": 5500000000.0, + "drive_frequency": 4100000000.0, + "anharmonicity": 0, + "sweetspot": 0.0, + "asymmetry": 0.0, + "crosstalk_matrix": { + "4": 1 + }, + "Ec": 0.0, + "Ej": 0.0, + "g": 0.0, + "assignment_fidelity": 0.0, + "peak_voltage": 0, + "pi_pulse_amplitude": 0, + "T1": 0.0, + "T2": 0.0, + "T2_spin_echo": 0, + "state0_voltage": 0, + "state1_voltage": 0, + "mean_gnd_states": [1, 0], + "mean_exc_states": [0, 1], + "threshold": 0.0, + "iq_angle": 0.0, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + } + }, + "coupler": { + "0": { + "sweetspot": 0.0 + }, + "1": { + "sweetspot": 0.0 + }, + "3": { + "sweetspot": 0.0 + }, + "4": { + "sweetspot": 0.0 + } } + } } diff --git a/src/qibolab/execution_parameters.py b/src/qibolab/execution_parameters.py index b317caf13..13a6ff0f2 100644 --- a/src/qibolab/execution_parameters.py +++ b/src/qibolab/execution_parameters.py @@ -1,4 +1,3 @@ -from dataclasses import dataclass from enum import Enum, auto from typing import Optional @@ -10,6 +9,7 @@ RawWaveformResults, SampleResults, ) +from qibolab.serialize_ import Model class AcquisitionType(Enum): @@ -51,8 +51,7 @@ class AveragingMode(Enum): } -@dataclass(frozen=True) -class ExecutionParameters: +class ExecutionParameters(Model): """Data structure to deal with execution parameters.""" nshots: Optional[int] = None diff --git a/src/qibolab/instruments/qblox/acquisition.py b/src/qibolab/instruments/qblox/acquisition.py index 98aee7c1d..d73685524 100644 --- a/src/qibolab/instruments/qblox/acquisition.py +++ b/src/qibolab/instruments/qblox/acquisition.py @@ -3,7 +3,7 @@ import numpy as np -from qibolab.pulses.shape import demodulate +from qibolab.pulses.modulation import demodulate SAMPLING_RATE = 1 diff --git a/src/qibolab/instruments/qblox/sequencer.py b/src/qibolab/instruments/qblox/sequencer.py index 86e68b35e..e450b8e00 100644 --- a/src/qibolab/instruments/qblox/sequencer.py +++ b/src/qibolab/instruments/qblox/sequencer.py @@ -5,7 +5,7 @@ from qibolab.instruments.qblox.q1asm import Program from qibolab.pulses import Pulse, PulseSequence, PulseType -from qibolab.pulses.shape import modulate +from qibolab.pulses.modulation import modulate from qibolab.sweeper import Parameter, Sweeper SAMPLING_RATE = 1 diff --git a/src/qibolab/instruments/qm/sequence.py b/src/qibolab/instruments/qm/sequence.py index 0e7d3ad3a..c744b4c4c 100644 --- a/src/qibolab/instruments/qm/sequence.py +++ b/src/qibolab/instruments/qm/sequence.py @@ -9,9 +9,9 @@ from qualang_tools.bakery import baking from qualang_tools.bakery.bakery import Baking -from qibolab.instruments.qm.acquisition import Acquisition from qibolab.pulses import Pulse, PulseType +from .acquisition import Acquisition from .config import SAMPLING_RATE, QMConfig DurationsType = Union[List[int], npt.NDArray[int]] @@ -70,7 +70,7 @@ def __post_init__(self): amplitude = format(self.pulse.amplitude, ".6f").rstrip("0").rstrip(".") self.element: str = f"{pulse_type}{self.pulse.qubit}" self.operation: str = ( - f"{pulse_type}({self.pulse.duration}, {amplitude}, {self.pulse.shape})" + f"{pulse_type}({self.pulse.duration}, {amplitude}, {self.pulse.envelope})" ) self.relative_phase: float = self.pulse.relative_phase / (2 * np.pi) self.elements_to_align.add(self.element) @@ -146,11 +146,11 @@ def bake(self, config: QMConfig, durations: DurationsType): for t in durations: with baking(config.__dict__, padding_method="right") as segment: if self.pulse.type is PulseType.FLUX: - waveform = self.pulse.envelope_waveform_i(SAMPLING_RATE).tolist() + waveform = self.pulse.i(SAMPLING_RATE).tolist() waveform = self.calculate_waveform(waveform, t) else: - waveform_i = self.pulse.envelope_waveform_i(SAMPLING_RATE).tolist() - waveform_q = self.pulse.envelope_waveform_q(SAMPLING_RATE).tolist() + waveform_i = self.pulse.i(SAMPLING_RATE).tolist() + waveform_q = self.pulse.q(SAMPLING_RATE).tolist() waveform = [ self.calculate_waveform(waveform_i, t), self.calculate_waveform(waveform_q, t), diff --git a/src/qibolab/instruments/rfsoc/convert.py b/src/qibolab/instruments/rfsoc/convert.py index 73ab0c0de..24dffa51d 100644 --- a/src/qibolab/instruments/rfsoc/convert.py +++ b/src/qibolab/instruments/rfsoc/convert.py @@ -8,7 +8,7 @@ import qibosoq.components.pulses as rfsoc_pulses from qibolab.platform import Qubit -from qibolab.pulses import Pulse, PulseSequence, PulseShape +from qibolab.pulses import Envelope, Pulse, PulseSequence from qibolab.sweeper import BIAS, DURATION, Parameter, Sweeper HZ_TO_MHZ = 1e-6 @@ -16,7 +16,7 @@ def replace_pulse_shape( - rfsoc_pulse: rfsoc_pulses.Pulse, shape: PulseShape, sampling_rate: float + rfsoc_pulse: rfsoc_pulses.Pulse, shape: Envelope, sampling_rate: float ) -> rfsoc_pulses.Pulse: """Set pulse shape parameters in rfsoc_pulses pulse object.""" if shape.name not in {"Gaussian", "Drag", "Rectangular", "Exponential"}: diff --git a/src/qibolab/instruments/zhinst/pulse.py b/src/qibolab/instruments/zhinst/pulse.py index c26e8321c..b9e068acf 100644 --- a/src/qibolab/instruments/zhinst/pulse.py +++ b/src/qibolab/instruments/zhinst/pulse.py @@ -17,15 +17,15 @@ def select_pulse(pulse: Pulse): """Return laboneq pulse object corresponding to the given qibolab pulse.""" - if isinstance(pulse.shape, Rectangular): + if isinstance(pulse.envelope, Rectangular): can_compress = pulse.type is not PulseType.READOUT return lo.pulse_library.const( length=round(pulse.duration * NANO_TO_SECONDS, 9), amplitude=pulse.amplitude, can_compress=can_compress, ) - if isinstance(pulse.shape, Gaussian): - sigma = pulse.shape.rel_sigma + if isinstance(pulse.envelope, Gaussian): + sigma = pulse.envelope.rel_sigma return lo.pulse_library.gaussian( length=round(pulse.duration * NANO_TO_SECONDS, 9), amplitude=pulse.amplitude, @@ -33,9 +33,9 @@ def select_pulse(pulse: Pulse): zero_boundaries=False, ) - if isinstance(pulse.shape, GaussianSquare): - sigma = pulse.shape.rel_sigma - width = pulse.shape.width + if isinstance(pulse.envelope, GaussianSquare): + sigma = pulse.envelope.rel_sigma + width = pulse.envelope.width can_compress = pulse.type is not PulseType.READOUT return lo.pulse_library.gaussian_square( length=round(pulse.duration * NANO_TO_SECONDS, 9), @@ -46,9 +46,9 @@ def select_pulse(pulse: Pulse): zero_boundaries=False, ) - if isinstance(pulse.shape, Drag): - sigma = pulse.shape.rel_sigma - beta = pulse.shape.beta + if isinstance(pulse.envelope, Drag): + sigma = pulse.envelope.rel_sigma + beta = pulse.envelope.beta return lo.pulse_library.drag( length=round(pulse.duration * NANO_TO_SECONDS, 9), amplitude=pulse.amplitude, @@ -57,15 +57,14 @@ def select_pulse(pulse: Pulse): zero_boundaries=False, ) - if np.all(pulse.envelope_waveform_q(SAMPLING_RATE) == 0): + if np.all(pulse.q(SAMPLING_RATE) == 0): return sampled_pulse_real( - samples=pulse.envelope_waveform_i(SAMPLING_RATE), + samples=pulse.i(SAMPLING_RATE), can_compress=True, ) else: return sampled_pulse_complex( - samples=pulse.envelope_waveform_i(SAMPLING_RATE) - + (1j * pulse.envelope_waveform_q(SAMPLING_RATE)), + samples=pulse.i(SAMPLING_RATE) + (1j * pulse.q(SAMPLING_RATE)), can_compress=True, ) diff --git a/src/qibolab/native.py b/src/qibolab/native.py index bbf55bb35..a3454eccb 100644 --- a/src/qibolab/native.py +++ b/src/qibolab/native.py @@ -1,7 +1,8 @@ -from dataclasses import dataclass, field, fields, replace +from dataclasses import dataclass, field, fields from typing import Optional -from qibolab.pulses import Pulse, PulseSequence +from .pulses import Pulse, PulseSequence +from .serialize_ import replace @dataclass diff --git a/src/qibolab/platform.py b/src/qibolab/platform.py index 3d03c6a57..56f3a3850 100644 --- a/src/qibolab/platform.py +++ b/src/qibolab/platform.py @@ -1,7 +1,7 @@ """A platform for executing quantum algorithms.""" from collections import defaultdict -from dataclasses import dataclass, field, fields, replace +from dataclasses import dataclass, field, fields from typing import Dict, List, Optional, Tuple import networkx as nx @@ -12,6 +12,7 @@ from .instruments.abstract import Controller, Instrument, InstrumentId from .pulses import Delay, Drag, PulseSequence, PulseType from .qubits import Qubit, QubitId, QubitPair, QubitPairId +from .serialize_ import replace from .sweeper import Sweeper from .unrolling import batch @@ -25,7 +26,7 @@ def unroll_sequences( sequences: List[PulseSequence], relaxation_time: int -) -> Tuple[PulseSequence, Dict[str, str]]: +) -> Tuple[PulseSequence, dict[str, list[str]]]: """Unrolls a list of pulse sequences to a single pulse sequence with multiple measurements. @@ -54,7 +55,7 @@ def unroll_sequences( pulses_per_channel = sequence.pulses_per_channel for channel in channels: delay = length - pulses_per_channel[channel].duration - total_sequence.append(Delay(delay, channel)) + total_sequence.append(Delay(duration=delay, channel=channel)) return total_sequence, readout_map @@ -463,24 +464,24 @@ def create_coupler_pulse(self, coupler, duration=None, amplitude=None): # TODO Remove RX90_drag_pulse and RX_drag_pulse, replace them with create_qubit_drive_pulse # TODO Add RY90 and RY pulses - def create_RX90_drag_pulse(self, qubit, start, beta, relative_phase=0): + def create_RX90_drag_pulse(self, qubit, beta, relative_phase=0): """Create native RX90 pulse with Drag shape.""" qubit = self.get_qubit(qubit) pulse = qubit.native_gates.RX90 return replace( pulse, relative_phase=relative_phase, - shape=Drag(pulse.shape.rel_sigma, beta), + envelope=Drag(rel_sigma=pulse.envelope.rel_sigma, beta=beta), channel=qubit.drive.name, ) - def create_RX_drag_pulse(self, qubit, start, beta, relative_phase=0): + def create_RX_drag_pulse(self, qubit, beta, relative_phase=0): """Create native RX pulse with Drag shape.""" qubit = self.get_qubit(qubit) pulse = qubit.native_gates.RX return replace( pulse, relative_phase=relative_phase, - shape=Drag(pulse.shape.rel_sigma, beta), + envelope=Drag(rel_sigma=pulse.envelope.rel_sigma, beta=beta), channel=qubit.drive.name, ) diff --git a/src/qibolab/pulses/__init__.py b/src/qibolab/pulses/__init__.py index 437c126d3..d190134e2 100644 --- a/src/qibolab/pulses/__init__.py +++ b/src/qibolab/pulses/__init__.py @@ -1,16 +1,3 @@ +from .envelope import * from .pulse import Delay, Pulse, PulseType, VirtualZ from .sequence import PulseSequence -from .shape import ( - IIR, - SAMPLING_RATE, - SNZ, - Custom, - Drag, - Gaussian, - GaussianSquare, - PulseShape, - Rectangular, - ShapeInitError, - Waveform, - eCap, -) diff --git a/src/qibolab/pulses/envelope.py b/src/qibolab/pulses/envelope.py new file mode 100644 index 000000000..cda3581be --- /dev/null +++ b/src/qibolab/pulses/envelope.py @@ -0,0 +1,345 @@ +"""Library of pulse envelopes.""" + +from abc import ABC +from typing import Annotated, Literal, Union + +import numpy as np +import numpy.typing as npt +from pydantic import Field +from scipy.signal import lfilter +from scipy.signal.windows import gaussian + +from qibolab.serialize_ import Model, NdArray, eq + +__all__ = [ + "Waveform", + "IqWaveform", + "BaseEnvelope", + "Envelope", + "Rectangular", + "Exponential", + "Gaussian", + "GaussianSquare", + "Drag", + "Iir", + "Snz", + "ECap", + "Custom", +] + + +# TODO: they could be distinguished among them, and distinguished from generic float +# arrays, using the NewType pattern -> but this require some more effort to encforce +# types throughout the whole code base +Waveform = npt.NDArray[np.float64] +"""Single component waveform, either I (in-phase) or Q (quadrature).""" +IqWaveform = npt.NDArray[np.float64] +"""Full shape, both I and Q components.""" + + +class BaseEnvelope(ABC, Model): + """Pulse envelopes. + + Generates both i (in-phase) and q (quadrature) components. + """ + + def i(self, samples: int) -> Waveform: + """In-phase envelope.""" + return np.zeros(samples) + + def q(self, samples: int) -> Waveform: + """Quadrature envelope.""" + return np.zeros(samples) + + def envelopes(self, samples: int) -> IqWaveform: + """Stacked i and q envelope waveforms of the pulse.""" + return np.array([self.i(samples), self.q(samples)]) + + +class Rectangular(BaseEnvelope): + """Rectangular envelope.""" + + kind: Literal["rectangular"] = "rectangular" + + def i(self, samples: int) -> Waveform: + """Generate a rectangular envelope.""" + return np.ones(samples) + + +class Exponential(BaseEnvelope): + r"""Exponential shape, i.e. square pulse with an exponential decay. + + .. math:: + + \frac{\exp\left(-\frac{x}{\text{upsilon}}\right) + g \exp\left(-\frac{x}{\text{tau}}\right)}{1 + g} + """ + + kind: Literal["exponential"] = "exponential" + + tau: float + """The decay rate of the first exponential function. + + In units of the interval duration. + """ + upsilon: float + """The decay rate of the second exponential function. + + In units of the interval duration. + """ + g: float = 0.1 + """Weight of the second exponential function.""" + + def i(self, samples: int) -> Waveform: + """Generate a combination of two exponential decays.""" + x = np.arange(samples) + upsilon = self.upsilon * samples + tau = self.tau * samples + return (np.exp(-x / upsilon) + self.g * np.exp(-x / tau)) / (1 + self.g) + + +def _samples_sigma(rel_sigma: float, samples: int) -> float: + """Convert standard deviation in samples. + + `rel_sigma` is assumed in units of the interval duration, and it is turned in units + of samples, by counting the number of samples in the interval. + """ + return rel_sigma * samples + + +class Gaussian(BaseEnvelope): + r"""Gaussian pulse shape. + + Args: + rel_sigma (float): + + .. math:: + + A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}} + """ + + kind: Literal["gaussian"] = "gaussian" + + rel_sigma: float + """Relative Gaussian standard deviation. + + In units of the interval duration. + """ + + def i(self, samples: int) -> Waveform: + """Generate a Gaussian window.""" + return gaussian(samples, _samples_sigma(self.rel_sigma, samples)) + + +class GaussianSquare(BaseEnvelope): + r"""Rectangular envelope with Gaussian rise and fall. + + .. math:: + + A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}}[Rise] + Flat + A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}}[Decay] + """ + + kind: Literal["gaussian_square"] = "gaussian_square" + + rel_sigma: float + """Relative Gaussian standard deviation. + + In units of the interval duration. + """ + width: float + """Length of the flat portion.""" + + def i(self, samples: int) -> Waveform: + """Generate a Gaussian envelope, with a flat central window.""" + + pulse = np.ones(samples) + u, hw = samples / 2, self.width / 2 + ts = np.arange(samples) + tails = (ts < (u - hw)) | ((u + hw) < ts) + pulse[tails] = gaussian(len(ts[tails]), _samples_sigma(self.rel_sigma, samples)) + + return pulse + + +class Drag(BaseEnvelope): + """Derivative Removal by Adiabatic Gate (DRAG) pulse envelope. + + .. todo:: + + - add expression + - add reference + """ + + kind: Literal["drag"] = "drag" + + rel_sigma: float + """Relative Gaussian standard deviation. + + In units of the interval duration. + """ + beta: float + """.. todo::""" + + def i(self, samples: int) -> Waveform: + """Generate a Gaussian envelope.""" + return gaussian(samples, _samples_sigma(self.rel_sigma, samples)) + + def q(self, samples: int) -> Waveform: + """Generate ... + + .. todo:: + """ + ts = np.arange(samples) + mu = (samples - 1) / 2 + sigma = _samples_sigma(self.rel_sigma, samples) + return self.beta * (-(ts - mu) / (sigma**2)) * self.i(samples) + + +class Iir(BaseEnvelope): + """IIR Filter using scipy.signal lfilter. + + https://arxiv.org/pdf/1907.04818.pdf (page 11 - filter formula S22):: + + p = [A, tau_iir] + p = [b0 = 1−k +k ·α, b1 = −(1−k)·(1−α),a0 = 1 and a1 = −(1−α)] + p = [b0, b1, a0, a1] + """ + + kind: Literal["iir"] = "iir" + + a: NdArray + b: NdArray + target: BaseEnvelope + + def _data(self, target: npt.NDArray) -> npt.NDArray: + a = self.a / self.a[0] + gain = np.sum(self.b) / np.sum(a) + b = self.b / gain if gain != 0 else self.b + + data = lfilter(b=b, a=a, x=target) + if np.max(np.abs(data)) != 0: + data /= np.max(np.abs(data)) + return data + + def i(self, samples: int) -> Waveform: + """.. todo::""" + return self._data(self.target.i(samples)) + + def q(self, samples: int) -> Waveform: + """.. todo::""" + return self._data(self.target.q(samples)) + + def __eq__(self, other) -> bool: + """.. todo::""" + return eq(self, other) + + +class Snz(BaseEnvelope): + """Sudden variant Net Zero. + + https://arxiv.org/abs/2008.07411 + (Supplementary materials: FIG. S1.) + + .. todo:: + + - expression + """ + + kind: Literal["snz"] = "snz" + + t_idling: float + """Fraction of interval where idling.""" + b_amplitude: float = 0.5 + """Relative B amplitude (wrt A).""" + + def i(self, samples: int) -> Waveform: + """.. todo::""" + # convert timings to samples + half_pulse_duration = (1 - self.t_idling) * samples / 2 + aspan = np.sum(np.arange(samples) < half_pulse_duration) + idle = samples - 2 * (aspan + 1) + + pulse = np.ones(samples) + # the aspan + 1 sample is B (and so the aspan + 1 + idle + 1), indexes are 0-based + pulse[aspan] = pulse[aspan + 1 + idle] = self.b_amplitude + # set idle time to 0 + pulse[aspan + 1 : aspan + 1 + idle] = 0 + return pulse + + +class ECap(BaseEnvelope): + r"""ECap pulse envelope. + + .. todo:: + + - add reference + + .. math:: + + e_{\cap(t,\alpha)} &=& A[1 + \tanh(\alpha t/t_\theta)][1 + \tanh(\alpha (1 - t/t_\theta))]\\ + &\times& [1 + \tanh(\alpha/2)]^{-2} + """ + + kind: Literal["ecap"] = "ecap" + + alpha: float + """In units of the inverse interval duration.""" + + def i(self, samples: int) -> Waveform: + """.. todo::""" + ss = np.arange(samples) + x = ss / samples + return ( + (1 + np.tanh(self.alpha * ss)) + * (1 + np.tanh(self.alpha * (1 - x))) + / (1 + np.tanh(self.alpha / 2)) ** 2 + ) + + +class Custom(BaseEnvelope): + """Arbitrary envelope. + + .. todo:: + + - expand description + - add attribute docstrings + """ + + kind: Literal["custom"] = "custom" + + i_: npt.NDArray + q_: npt.NDArray + + def i(self, samples: int) -> Waveform: + """.. todo::""" + if len(self.i_) != samples: + raise ValueError + + return self.i_ + + def q(self, samples: int) -> Waveform: + """.. todo::""" + if len(self.q_) != samples: + raise ValueError + + return self.q_ + + def __eq__(self, other) -> bool: + """.. todo::""" + return eq(self, other) + + +Envelope = Annotated[ + Union[ + Rectangular, + Exponential, + Gaussian, + GaussianSquare, + Drag, + Iir, + Snz, + ECap, + Custom, + ], + Field(discriminator="kind"), +] +"""Available pulse shapes.""" diff --git a/src/qibolab/pulses/modulation.py b/src/qibolab/pulses/modulation.py new file mode 100644 index 000000000..05e2b6747 --- /dev/null +++ b/src/qibolab/pulses/modulation.py @@ -0,0 +1,61 @@ +import numpy as np + +from .envelope import IqWaveform + +__all__ = ["modulate", "demodulate"] + + +def modulate( + envelope: IqWaveform, + freq: float, + rate: float, + phase: float = 0.0, +) -> IqWaveform: + """Modulate the envelope waveform with a carrier. + + `envelope` is a `(2, n)`-shaped array of I and Q (first dimension) envelope signals, + as a function of time (second dimension), and `freq` the frequency of the carrier to + modulate with (usually the IF) in GHz. + `rate` is an optional sampling rate, in Gs/s, to sample the carrier. + + .. note:: + + Only the combination `freq / rate` is actually relevant, but it is frequently + convenient to specify one in GHz and the other in Gs/s. Thus the two arguments + are provided for the simplicity of their interpretation. + + `phase` is an optional initial phase for the carrier. + """ + samples = np.arange(envelope.shape[1]) + phases = (2 * np.pi * freq / rate) * samples + phase + cos = np.cos(phases) + sin = np.sin(phases) + mod = np.array([[cos, -sin], [sin, cos]]) + + # the normalization is related to `mod`, but only applied at the end for the sake of + # performances + return np.einsum("ijt,jt->it", mod, envelope) / np.sqrt(2) + + +def demodulate( + modulated: IqWaveform, + freq: float, + rate: float, +) -> IqWaveform: + """Demodulate the acquired pulse. + + The role of the arguments is the same of the corresponding ones in :func:`modulate`, + which is essentially the inverse of this function. + """ + # in case the offsets have not been removed in hardware + modulated = modulated - np.mean(modulated) + + samples = np.arange(modulated.shape[1]) + phases = (2 * np.pi * freq / rate) * samples + cos = np.cos(phases) + sin = np.sin(phases) + demod = np.array([[cos, sin], [-sin, cos]]) + + # the normalization is related to `demod`, but only applied at the end for the sake + # of performances + return np.sqrt(2) * np.einsum("ijt,jt->it", demod, modulated) diff --git a/src/qibolab/pulses/plot.py b/src/qibolab/pulses/plot.py index 6cbbf905a..87319febf 100644 --- a/src/qibolab/pulses/plot.py +++ b/src/qibolab/pulses/plot.py @@ -5,9 +5,17 @@ import matplotlib.pyplot as plt import numpy as np +from .envelope import Waveform +from .modulation import modulate from .pulse import Delay, Pulse from .sequence import PulseSequence -from .shape import SAMPLING_RATE, Waveform, modulate + +SAMPLING_RATE = 1 +"""Default sampling rate in gigasamples per second (GSps). + +Used for generating waveform envelopes if the instruments do not provide +a different value. +""" def waveform(wf: Waveform, filename=None): @@ -28,7 +36,7 @@ def waveform(wf: Waveform, filename=None): plt.close() -def pulse(pulse_: Pulse, filename=None, sampling_rate=SAMPLING_RATE): +def pulse(pulse_: Pulse, filename=None): """Plot the pulse envelope and modulated waveforms. Args: @@ -37,11 +45,11 @@ def pulse(pulse_: Pulse, filename=None, sampling_rate=SAMPLING_RATE): import matplotlib.pyplot as plt from matplotlib import gridspec - waveform_i = pulse_.shape.envelope_waveform_i(sampling_rate) - waveform_q = pulse_.shape.envelope_waveform_q(sampling_rate) + waveform_i = pulse_.i(SAMPLING_RATE) + waveform_q = pulse_.q(SAMPLING_RATE) num_samples = len(waveform_i) - time = np.arange(num_samples) / sampling_rate + time = np.arange(num_samples) / SAMPLING_RATE _ = plt.figure(figsize=(14, 5), dpi=200) gs = gridspec.GridSpec(ncols=2, nrows=1, width_ratios=np.array([2, 1])) ax1 = plt.subplot(gs[0]) @@ -60,8 +68,8 @@ def pulse(pulse_: Pulse, filename=None, sampling_rate=SAMPLING_RATE): linestyle="dashed", ) - envelope = pulse_.shape.envelope_waveforms(sampling_rate) - modulated = modulate(np.array(envelope), pulse_.frequency) + envelope = pulse_.envelopes(SAMPLING_RATE) + modulated = modulate(np.array(envelope), pulse_.frequency, rate=SAMPLING_RATE) ax1.plot(time, modulated[0], label="modulated i", c="C0") ax1.plot(time, modulated[1], label="modulated q", c="C1") ax1.plot(time, -waveform_i, c="silver", linestyle="dashed") @@ -112,7 +120,7 @@ def pulse(pulse_: Pulse, filename=None, sampling_rate=SAMPLING_RATE): plt.close() -def sequence(ps: PulseSequence, filename=None, sampling_rate=SAMPLING_RATE): +def sequence(ps: PulseSequence, filename=None): """Plot the sequence of pulses. Args: @@ -146,22 +154,16 @@ def sequence(ps: PulseSequence, filename=None, sampling_rate=SAMPLING_RATE): start += pulse.duration continue - envelope = pulse.shape.envelope_waveforms(sampling_rate) + envelope = pulse.envelopes(SAMPLING_RATE) num_samples = envelope[0].size - time = start + np.arange(num_samples) / sampling_rate - modulated = modulate(np.array(envelope), pulse.frequency) + time = start + np.arange(num_samples) / SAMPLING_RATE + modulated = modulate( + np.array(envelope), pulse.frequency, rate=SAMPLING_RATE + ) ax.plot(time, modulated[1], c="lightgrey") ax.plot(time, modulated[0], c=f"C{str(n)}") - ax.plot( - time, - pulse.shape.envelope_waveform_i(sampling_rate), - c=f"C{str(n)}", - ) - ax.plot( - time, - -pulse.shape.envelope_waveform_i(sampling_rate), - c=f"C{str(n)}", - ) + ax.plot(time, pulse.i(SAMPLING_RATE), c=f"C{str(n)}") + ax.plot(time, -pulse.i(SAMPLING_RATE), c=f"C{str(n)}") # TODO: if they overlap use different shades ax.axhline(0, c="dimgrey") ax.set_ylabel(f"qubit {qubit} \n channel {channel}") diff --git a/src/qibolab/pulses/pulse.py b/src/qibolab/pulses/pulse.py index aa510bc11..efd4c7b85 100644 --- a/src/qibolab/pulses/pulse.py +++ b/src/qibolab/pulses/pulse.py @@ -1,10 +1,14 @@ """Pulse class.""" -from dataclasses import dataclass, fields +from dataclasses import fields from enum import Enum from typing import Optional -from .shape import SAMPLING_RATE, PulseShape, Waveform +import numpy as np + +from qibolab.serialize_ import Model + +from .envelope import Envelope, IqWaveform, Waveform class PulseType(Enum): @@ -20,33 +24,33 @@ class PulseType(Enum): FLUX = "qf" COUPLERFLUX = "cf" DELAY = "dl" - VIRTUALZ = "virtual_z" + VIRTUALZ = "vz" -@dataclass -class Pulse: +class Pulse(Model): """A pulse to be sent to the QPU.""" - duration: int - """Pulse duration in ns.""" + duration: float + """Pulse duration.""" + amplitude: float """Pulse digital amplitude (unitless). Pulse amplitudes are normalised between -1 and 1. """ - frequency: int = 0 + frequency: float """Pulse Intermediate Frequency in Hz. The value has to be in the range [10e6 to 300e6]. """ - relative_phase: float = 0.0 - """Relative phase of the pulse, in radians.""" - shape: PulseShape = "Rectangular()" - """Pulse shape, as a PulseShape object. + envelope: Envelope + """The pulse envelope shape. See - :py: mod:`qibolab.pulses` for list of available shapes. + :cls:`qibolab.pulses.envelope.Envelopes` for list of available shapes. """ + relative_phase: float = 0.0 + """Relative phase of the pulse, in radians.""" channel: Optional[str] = None """Channel on which the pulse should be played. @@ -60,39 +64,36 @@ class Pulse: qubit: int = 0 """Qubit or coupler addressed by the pulse.""" - def __post_init__(self): - if isinstance(self.type, str): - self.type = PulseType(self.type) - if isinstance(self.shape, str): - self.shape = PulseShape.eval(self.shape) - # TODO: drop the cyclic reference - self.shape.pulse = self - @classmethod - def flux(cls, duration, amplitude, shape, **kwargs): - return cls(duration, amplitude, 0, 0, shape, type=PulseType.FLUX, **kwargs) + def flux(cls, **kwargs): + """Construct a flux pulse. + + It provides a simplified syntax for the :cls:`Pulse` constructor, by applying + suitable defaults. + """ + kwargs["frequency"] = 0 + kwargs["relative_phase"] = 0 + if "type" not in kwargs: + kwargs["type"] = PulseType.FLUX + return cls(**kwargs) @property def id(self) -> int: return id(self) - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: + def i(self, sampling_rate: float) -> Waveform: """The envelope waveform of the i component of the pulse.""" + samples = int(self.duration * sampling_rate) + return self.amplitude * self.envelope.i(samples) - return self.shape.envelope_waveform_i(sampling_rate) - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: + def q(self, sampling_rate: float) -> Waveform: """The envelope waveform of the q component of the pulse.""" + samples = int(self.duration * sampling_rate) + return self.amplitude * self.envelope.q(samples) - return self.shape.envelope_waveform_q(sampling_rate) - - def envelope_waveforms(self, sampling_rate=SAMPLING_RATE): + def envelopes(self, sampling_rate: float) -> IqWaveform: """A tuple with the i and q envelope waveforms of the pulse.""" - - return ( - self.shape.envelope_waveform_i(sampling_rate), - self.shape.envelope_waveform_q(sampling_rate), - ) + return np.array([self.i(sampling_rate), self.q(sampling_rate)]) def __hash__(self): """Hash the content. @@ -118,8 +119,7 @@ def __hash__(self): ) -@dataclass -class Delay: +class Delay(Model): """A wait instruction during which we are not sending any pulses to the QPU.""" @@ -131,13 +131,9 @@ class Delay: """Type fixed to ``DELAY`` to comply with ``Pulse`` interface.""" -@dataclass -class VirtualZ: +class VirtualZ(Model): """Implementation of Z-rotations using virtual phase.""" - duration = 0 - """Duration of the virtual gate should always be zero.""" - phase: float """Phase that implements the rotation.""" channel: Optional[str] = None @@ -145,3 +141,8 @@ class VirtualZ: qubit: int = 0 """Qubit on the drive of which the virtual phase should be added.""" type: PulseType = PulseType.VIRTUALZ + + @property + def duration(self): + """Duration of the virtual gate should always be zero.""" + return 0 diff --git a/src/qibolab/pulses/sequence.py b/src/qibolab/pulses/sequence.py index 8a8675053..b48cb62cd 100644 --- a/src/qibolab/pulses/sequence.py +++ b/src/qibolab/pulses/sequence.py @@ -108,16 +108,18 @@ def duration(self) -> int: if len(channel_pulses) == 1: pulses = next(iter(channel_pulses.values())) return sum(pulse.duration for pulse in pulses) - return max(sequence.duration for sequence in channel_pulses.values()) + return max( + (sequence.duration for sequence in channel_pulses.values()), default=0 + ) @property def channels(self) -> list: """List containing the channels used by the pulses in the sequence.""" channels = [] for pulse in self: - if not pulse.channel in channels: + if pulse.channel not in channels: channels.append(pulse.channel) - channels.sort() + return channels @property diff --git a/src/qibolab/pulses/shape.py b/src/qibolab/pulses/shape.py deleted file mode 100644 index b8371986d..000000000 --- a/src/qibolab/pulses/shape.py +++ /dev/null @@ -1,618 +0,0 @@ -"""PulseShape class.""" - -import re -from abc import ABC, abstractmethod - -import numpy as np -import numpy.typing as npt -from scipy.signal import lfilter - -SAMPLING_RATE = 1 -"""Default sampling rate in gigasamples per second (GSps). - -Used for generating waveform envelopes if the instruments do not provide -a different value. -""" - -# TODO: they could be distinguished among them, and distinguished from generic float -# arrays, using the NewType pattern -> but this require some more effort to encforce -# types throughout the whole code base -Waveform = npt.NDArray[np.float64] -"""""" -IqWaveform = npt.NDArray[np.float64] -"""""" - - -def modulate( - envelope: IqWaveform, - freq: float, - rate: float = SAMPLING_RATE, - phase: float = 0.0, -) -> IqWaveform: - """Modulate the envelope waveform with a carrier. - - `envelope` is a `(2, n)`-shaped array of I and Q (first dimension) envelope signals, - as a function of time (second dimension), and `freq` the frequency of the carrier to - modulate with (usually the IF) in GHz. - `rate` is an optional sampling rate, in Gs/s, to sample the carrier. - - .. note:: - - Only the combination `freq / rate` is actually relevant, but it is frequently - convenient to specify one in GHz and the other in Gs/s. Thus the two arguments - are provided for the simplicity of their interpretation. - - `phase` is an optional initial phase for the carrier. - """ - samples = np.arange(envelope.shape[1]) - phases = (2 * np.pi * freq / rate) * samples + phase - cos = np.cos(phases) - sin = np.sin(phases) - mod = np.array([[cos, -sin], [sin, cos]]) - - # the normalization is related to `mod`, but only applied at the end for the sake of - # performances - return np.einsum("ijt,jt->it", mod, envelope) / np.sqrt(2) - - -def demodulate( - modulated: IqWaveform, - freq: float, - rate: float = SAMPLING_RATE, -) -> IqWaveform: - """Demodulate the acquired pulse. - - The role of the arguments is the same of the corresponding ones in :func:`modulate`, - which is essentially the inverse of this function. - """ - # in case the offsets have not been removed in hardware - modulated = modulated - np.mean(modulated) - - samples = np.arange(modulated.shape[1]) - phases = (2 * np.pi * freq / rate) * samples - cos = np.cos(phases) - sin = np.sin(phases) - demod = np.array([[cos, sin], [-sin, cos]]) - - # the normalization is related to `demod`, but only applied at the end for the sake - # of performances - return np.sqrt(2) * np.einsum("ijt,jt->it", demod, modulated) - - -class ShapeInitError(RuntimeError): - """Error raised when a pulse has not been fully defined.""" - - default_msg = "PulseShape attribute pulse must be initialised in order to be able to generate pulse waveforms" - - def __init__(self, msg=None, *args): - if msg is None: - msg = self.default_msg - super().__init__(msg, *args) - - -class PulseShape(ABC): - """Pulse envelopes. - - Generates both i (in-phase) and q (quadrature) components. - """ - - pulse = None - """Pulse (Pulse): the pulse associated with it. - - Its parameters are used to generate pulse waveforms. - """ - - @abstractmethod - def envelope_waveform_i( - self, sampling_rate=SAMPLING_RATE - ) -> Waveform: # pragma: no cover - raise NotImplementedError - - @abstractmethod - def envelope_waveform_q( - self, sampling_rate=SAMPLING_RATE - ) -> Waveform: # pragma: no cover - raise NotImplementedError - - def envelope_waveforms(self, sampling_rate=SAMPLING_RATE): - """A tuple with the i and q envelope waveforms of the pulse.""" - - return ( - self.envelope_waveform_i(sampling_rate), - self.envelope_waveform_q(sampling_rate), - ) - - def __eq__(self, item) -> bool: - """Overloads == operator.""" - return isinstance(item, type(self)) - - @staticmethod - def eval(value: str) -> "PulseShape": - """Deserialize string representation. - - .. todo:: - - To be replaced by proper serialization. - """ - shape_name = re.findall(r"(\w+)", value)[0] - if shape_name not in globals(): - raise ValueError(f"shape {value} not found") - shape_parameters = re.findall(r"[-\w+\d\.\d]+", value)[1:] - # TODO: create multiple tests to prove regex working correctly - return globals()[shape_name](*shape_parameters) - - -class Rectangular(PulseShape): - """Rectangular pulse shape.""" - - def __init__(self): - self.name = "Rectangular" - self.pulse: "Pulse" = None - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - return self.pulse.amplitude * np.ones(num_samples) - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - return np.zeros(num_samples) - raise ShapeInitError - - def __repr__(self): - return f"{self.name}()" - - -class Exponential(PulseShape): - r"""Exponential pulse shape (Square pulse with an exponential decay). - - Args: - tau (float): Parameter that controls the decay of the first exponential function - upsilon (float): Parameter that controls the decay of the second exponential function - g (float): Parameter that weights the second exponential function - - - .. math:: - - A\frac{\exp\left(-\frac{x}{\text{upsilon}}\right) + g \exp\left(-\frac{x}{\text{tau}}\right)}{1 + g} - """ - - def __init__(self, tau: float, upsilon: float, g: float = 0.1): - self.name = "Exponential" - self.pulse: "Pulse" = None - self.tau: float = float(tau) - self.upsilon: float = float(upsilon) - self.g: float = float(g) - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - x = np.arange(0, num_samples, 1) - return ( - self.pulse.amplitude - * ( - (np.ones(num_samples) * np.exp(-x / self.upsilon)) - + self.g * np.exp(-x / self.tau) - ) - / (1 + self.g) - ) - - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - return np.zeros(num_samples) - raise ShapeInitError - - def __repr__(self): - return f"{self.name}({format(self.tau, '.3f').rstrip('0').rstrip('.')}, {format(self.upsilon, '.3f').rstrip('0').rstrip('.')}, {format(self.g, '.3f').rstrip('0').rstrip('.')})" - - -class Gaussian(PulseShape): - r"""Gaussian pulse shape. - - Args: - rel_sigma (float): relative sigma so that the pulse standard deviation (sigma) = duration / rel_sigma - - .. math:: - - A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}} - """ - - def __init__(self, rel_sigma: float): - self.name = "Gaussian" - self.pulse: "Pulse" = None - self.rel_sigma: float = float(rel_sigma) - - def __eq__(self, item) -> bool: - """Overloads == operator.""" - if super().__eq__(item): - return self.rel_sigma == item.rel_sigma - return False - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - x = np.arange(0, num_samples, 1) - return self.pulse.amplitude * np.exp( - -(1 / 2) - * ( - ((x - (num_samples - 1) / 2) ** 2) - / (((num_samples) / self.rel_sigma) ** 2) - ) - ) - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - return np.zeros(num_samples) - raise ShapeInitError - - def __repr__(self): - return f"{self.name}({format(self.rel_sigma, '.6f').rstrip('0').rstrip('.')})" - - -class GaussianSquare(PulseShape): - r"""GaussianSquare pulse shape. - - Args: - rel_sigma (float): relative sigma so that the pulse standard deviation (sigma) = duration / rel_sigma - width (float): Percentage of the pulse that is flat - - .. math:: - - A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}}[Rise] + Flat + A\exp^{-\frac{1}{2}\frac{(t-\mu)^2}{\sigma^2}}[Decay] - """ - - def __init__(self, rel_sigma: float, width: float): - self.name = "GaussianSquare" - self.pulse: "Pulse" = None - self.rel_sigma: float = float(rel_sigma) - self.width: float = float(width) - - def __eq__(self, item) -> bool: - """Overloads == operator.""" - if super().__eq__(item): - return self.rel_sigma == item.rel_sigma and self.width == item.width - return False - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - - def gaussian(t, rel_sigma, gaussian_samples): - mu = (2 * gaussian_samples - 1) / 2 - sigma = (2 * gaussian_samples) / rel_sigma - return np.exp(-0.5 * ((t - mu) / sigma) ** 2) - - def fvec(t, gaussian_samples, rel_sigma, length=None): - if length is None: - length = t.shape[0] - - pulse = np.ones_like(t, dtype=float) - rise = t < gaussian_samples - fall = t > length - gaussian_samples - 1 - pulse[rise] = gaussian(t[rise], rel_sigma, gaussian_samples) - pulse[fall] = gaussian(t[rise], rel_sigma, gaussian_samples)[::-1] - return pulse - - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - gaussian_samples = num_samples * (1 - self.width) // 2 - t = np.arange(0, num_samples) - - pulse = fvec(t, gaussian_samples, rel_sigma=self.rel_sigma) - - return self.pulse.amplitude * pulse - - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - return np.zeros(num_samples) - raise ShapeInitError - - def __repr__(self): - return f"{self.name}({format(self.rel_sigma, '.6f').rstrip('0').rstrip('.')}, {format(self.width, '.6f').rstrip('0').rstrip('.')})" - - -class Drag(PulseShape): - """Derivative Removal by Adiabatic Gate (DRAG) pulse shape. - - Args: - rel_sigma (float): relative sigma so that the pulse standard deviation (sigma) = duration / rel_sigma - beta (float): relative sigma so that the pulse standard deviation (sigma) = duration / rel_sigma - .. math:: - """ - - def __init__(self, rel_sigma, beta): - self.name = "Drag" - self.pulse: "Pulse" = None - self.rel_sigma = float(rel_sigma) - self.beta = float(beta) - - def __eq__(self, item) -> bool: - """Overloads == operator.""" - if super().__eq__(item): - return self.rel_sigma == item.rel_sigma and self.beta == item.beta - return False - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - x = np.arange(0, num_samples, 1) - return self.pulse.amplitude * np.exp( - -(1 / 2) - * ( - ((x - (num_samples - 1) / 2) ** 2) - / (((num_samples) / self.rel_sigma) ** 2) - ) - ) - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - x = np.arange(0, num_samples, 1) - i = self.pulse.amplitude * np.exp( - -(1 / 2) - * ( - ((x - (num_samples - 1) / 2) ** 2) - / (((num_samples) / self.rel_sigma) ** 2) - ) - ) - return ( - self.beta - * (-(x - (num_samples - 1) / 2) / ((num_samples / self.rel_sigma) ** 2)) - * i - * sampling_rate - ) - raise ShapeInitError - - def __repr__(self): - return f"{self.name}({format(self.rel_sigma, '.6f').rstrip('0').rstrip('.')}, {format(self.beta, '.6f').rstrip('0').rstrip('.')})" - - -class IIR(PulseShape): - """IIR Filter using scipy.signal lfilter.""" - - # https://arxiv.org/pdf/1907.04818.pdf (page 11 - filter formula S22) - # p = [A, tau_iir] - # p = [b0 = 1−k +k ·α, b1 = −(1−k)·(1−α),a0 = 1 and a1 = −(1−α)] - # p = [b0, b1, a0, a1] - - def __init__(self, b, a, target: PulseShape): - self.name = "IIR" - self.target: PulseShape = target - self._pulse: "Pulse" = None - self.a: np.ndarray = np.array(a) - self.b: np.ndarray = np.array(b) - # Check len(a) = len(b) = 2 - - def __eq__(self, item) -> bool: - """Overloads == operator.""" - if super().__eq__(item): - return ( - self.target == item.target - and (self.a == item.a).all() - and (self.b == item.b).all() - ) - return False - - @property - def pulse(self): - return self._pulse - - @pulse.setter - def pulse(self, value): - self._pulse = value - self.target.pulse = value - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - self.a = self.a / self.a[0] - gain = np.sum(self.b) / np.sum(self.a) - if not gain == 0: - self.b = self.b / gain - data = lfilter( - b=self.b, - a=self.a, - x=self.target.envelope_waveform_i(sampling_rate), - ) - if not np.max(np.abs(data)) == 0: - data = data / np.max(np.abs(data)) - return np.abs(self.pulse.amplitude) * data - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - self.a = self.a / self.a[0] - gain = np.sum(self.b) / np.sum(self.a) - if not gain == 0: - self.b = self.b / gain - data = lfilter( - b=self.b, - a=self.a, - x=self.target.envelope_waveform_q(sampling_rate), - ) - if not np.max(np.abs(data)) == 0: - data = data / np.max(np.abs(data)) - return np.abs(self.pulse.amplitude) * data - raise ShapeInitError - - def __repr__(self): - formatted_b = [round(b, 3) for b in self.b] - formatted_a = [round(a, 3) for a in self.a] - return f"{self.name}({formatted_b}, {formatted_a}, {self.target})" - - -class SNZ(PulseShape): - """Sudden variant Net Zero. - - https://arxiv.org/abs/2008.07411 - (Supplementary materials: FIG. S1.) - """ - - def __init__(self, t_idling, b_amplitude=None): - self.name = "SNZ" - self.pulse: "Pulse" = None - self.t_idling: float = t_idling - self.b_amplitude = b_amplitude - - def __eq__(self, item) -> bool: - """Overloads == operator.""" - if super().__eq__(item): - return ( - self.t_idling == item.t_idling and self.b_amplitude == item.b_amplitude - ) - return False - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - if self.t_idling > self.pulse.duration: - raise ValueError( - f"Cannot put idling time {self.t_idling} higher than duration {self.pulse.duration}." - ) - if self.b_amplitude is None: - self.b_amplitude = self.pulse.amplitude / 2 - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - half_pulse_duration = (self.pulse.duration - self.t_idling) / 2 - half_flux_pulse_samples = int( - np.rint(num_samples * half_pulse_duration / self.pulse.duration) - ) - idling_samples = num_samples - 2 * half_flux_pulse_samples - return np.concatenate( - ( - self.pulse.amplitude * np.ones(half_flux_pulse_samples - 1), - np.array([self.b_amplitude]), - np.zeros(idling_samples), - -np.array([self.b_amplitude]), - -self.pulse.amplitude * np.ones(half_flux_pulse_samples - 1), - ) - ) - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - return np.zeros(num_samples) - raise ShapeInitError - - def __repr__(self): - return f"{self.name}({self.t_idling})" - - -class eCap(PulseShape): - r"""ECap pulse shape. - - Args: - alpha (float): - - .. math:: - - e_{\cap(t,\alpha)} &=& A[1 + \tanh(\alpha t/t_\theta)][1 + \tanh(\alpha (1 - t/t_\theta))]\\ - &\times& [1 + \tanh(\alpha/2)]^{-2} - """ - - def __init__(self, alpha: float): - self.name = "eCap" - self.pulse: "Pulse" = None - self.alpha: float = float(alpha) - - def __eq__(self, item) -> bool: - """Overloads == operator.""" - if super().__eq__(item): - return self.alpha == item.alpha - return False - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - if self.pulse: - num_samples = int(self.pulse.duration * sampling_rate) - x = np.arange(0, num_samples, 1) - return ( - self.pulse.amplitude - * (1 + np.tanh(self.alpha * x / num_samples)) - * (1 + np.tanh(self.alpha * (1 - x / num_samples))) - / (1 + np.tanh(self.alpha / 2)) ** 2 - ) - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - if self.pulse: - num_samples = int(self.pulse.duration * sampling_rate) - return np.zeros(num_samples) - raise ShapeInitError - - def __repr__(self): - return f"{self.name}({format(self.alpha, '.6f').rstrip('0').rstrip('.')})" - - -class Custom(PulseShape): - """Arbitrary shape.""" - - def __init__(self, envelope_i, envelope_q=None): - self.name = "Custom" - self.pulse: "Pulse" = None - self.envelope_i: np.ndarray = np.array(envelope_i) - if envelope_q is not None: - self.envelope_q: np.ndarray = np.array(envelope_q) - else: - self.envelope_q = self.envelope_i - - def envelope_waveform_i(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the i component of the pulse.""" - - if self.pulse: - if self.pulse.duration != len(self.envelope_i): - raise ValueError("Length of envelope_i must be equal to pulse duration") - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - - return self.envelope_i * self.pulse.amplitude - raise ShapeInitError - - def envelope_waveform_q(self, sampling_rate=SAMPLING_RATE) -> Waveform: - """The envelope waveform of the q component of the pulse.""" - - if self.pulse: - if self.pulse.duration != len(self.envelope_q): - raise ValueError("Length of envelope_q must be equal to pulse duration") - num_samples = int(np.rint(self.pulse.duration * sampling_rate)) - - return self.envelope_q * self.pulse.amplitude - raise ShapeInitError - - def __repr__(self): - return f"{self.name}({self.envelope_i[:3]}, ..., {self.envelope_q[:3]}, ...)" diff --git a/src/qibolab/serialize.py b/src/qibolab/serialize.py index dc92f7dab..476e05d46 100644 --- a/src/qibolab/serialize.py +++ b/src/qibolab/serialize.py @@ -85,17 +85,16 @@ def load_qubits( def _load_pulse(pulse_kwargs, qubit): - pulse_type = pulse_kwargs.pop("type") - if "coupler" in pulse_kwargs: - q = pulse_kwargs.pop("coupler", qubit.name) - else: - q = pulse_kwargs.pop("qubit", qubit.name) + coupler = "coupler" in pulse_kwargs + q = pulse_kwargs.pop("coupler" if coupler else "qubit", qubit.name) - if pulse_type == "dl": - return Delay(**pulse_kwargs) - if pulse_type == "virtual_z": + if "phase" in pulse_kwargs: return VirtualZ(**pulse_kwargs, qubit=q) - return Pulse(**pulse_kwargs, type=pulse_type, qubit=q) + if "amplitude" not in pulse_kwargs: + return Delay(**pulse_kwargs) + if "frequency" not in pulse_kwargs: + return Pulse.flux(**pulse_kwargs, qubit=q) + return Pulse(**pulse_kwargs, qubit=q) def _load_single_qubit_natives(qubit, gates) -> SingleQubitNatives: @@ -172,11 +171,9 @@ def load_instrument_settings( def _dump_pulse(pulse: Pulse): - data = asdict(pulse) + data = pulse.model_dump() if pulse.type in (PulseType.FLUX, PulseType.COUPLERFLUX): del data["frequency"] - if "shape" in data: - data["shape"] = str(pulse.shape) data["type"] = data["type"].value if "channel" in data: del data["channel"] diff --git a/src/qibolab/serialize_.py b/src/qibolab/serialize_.py new file mode 100644 index 000000000..c7a4a3d12 --- /dev/null +++ b/src/qibolab/serialize_.py @@ -0,0 +1,69 @@ +"""Serialization utilities.""" + +import base64 +import io +from typing import Annotated, Union + +import numpy as np +import numpy.typing as npt +from pydantic import BaseModel, ConfigDict, PlainSerializer, PlainValidator + + +def ndarray_serialize(ar: npt.NDArray) -> str: + """Serialize array to string.""" + buffer = io.BytesIO() + np.save(buffer, ar) + buffer.seek(0) + return base64.standard_b64encode(buffer.read()).decode() + + +def ndarray_deserialize(x: Union[str, npt.NDArray]) -> npt.NDArray: + """Deserialize array.""" + if isinstance(x, np.ndarray): + return x + + buffer = io.BytesIO() + buffer.write(base64.standard_b64decode(x)) + buffer.seek(0) + return np.load(buffer) + + +NdArray = Annotated[ + npt.NDArray, + PlainValidator(ndarray_deserialize), + PlainSerializer(ndarray_serialize, return_type=str), +] +"""Pydantic-compatible array representation.""" + + +def eq(obj1: BaseModel, obj2: BaseModel) -> bool: + """Compare two models with non-default equality. + + Currently, defines custom equality for NumPy arrays. + """ + obj2d = obj2.model_dump() + comparisons = [] + for field, value1 in obj1.model_dump().items(): + value2 = obj2d[field] + if isinstance(value1, np.ndarray): + comparisons.append( + (value1.shape == value2.shape) and (value1 == value2).all() + ) + + comparisons.append(value1 == value2) + + return all(comparisons) + + +class Model(BaseModel): + """Global qibolab model, holding common configurations.""" + + model_config = ConfigDict(arbitrary_types_allowed=True, frozen=True) + + +def replace(model: BaseModel, **update): + """Replace interface for pydantic models. + + To have the same familiar syntax of :func:`dataclasses.replace`. + """ + return model.model_copy(update=update) diff --git a/tests/dummy_qrc/qblox/parameters.json b/tests/dummy_qrc/qblox/parameters.json index 816821391..43a094ea7 100644 --- a/tests/dummy_qrc/qblox/parameters.json +++ b/tests/dummy_qrc/qblox/parameters.json @@ -1,324 +1,321 @@ { - "nqubits": 5, - "settings": { - "nshots": 1024, - "relaxation_time": 20000 + "nqubits": 5, + "settings": { + "nshots": 1024, + "relaxation_time": 20000 + }, + "qubits": [0, 1, 2, 3, 4], + "topology": [ + [0, 2], + [1, 2], + [2, 3], + [2, 4] + ], + "instruments": { + "qblox_controller": { + "bounds": { + "instructions": 1000000, + "readout": 250, + "waveforms": 40000 + } }, - "qubits": [ - 0, - 1, - 2, - 3, - 4 - ], - "topology": [ - [ - 0, - 2 - ], - [ - 1, - 2 - ], - [ - 2, - 3 - ], - [ - 2, - 4 - ] - ], - "instruments": { - "qblox_controller": { - "bounds": { - "instructions": 1000000, - "readout": 250, - "waveforms": 40000 - } + "twpa_pump": { + "frequency": 6535900000, + "power": 4 + }, + "qcm_rf0": { + "o1": { + "attenuation": 20, + "lo_frequency": 5252833073, + "gain": 0.47 + }, + "o2": { + "attenuation": 20, + "lo_frequency": 5652833073, + "gain": 0.57 + } + }, + "qcm_rf1": { + "o1": { + "attenuation": 20, + "lo_frequency": 5995371914, + "gain": 0.55 + }, + "o2": { + "attenuation": 20, + "lo_frequency": 6961018001, + "gain": 0.596 + } + }, + "qcm_rf2": { + "o1": { + "attenuation": 20, + "lo_frequency": 6786543060, + "gain": 0.47 + } + }, + "qrm_rf_a": { + "o1": { + "attenuation": 36, + "lo_frequency": 7300000000, + "gain": 0.6 + }, + "i1": { + "acquisition_hold_off": 500, + "acquisition_duration": 900 + } + }, + "qrm_rf_b": { + "o1": { + "attenuation": 36, + "lo_frequency": 7850000000, + "gain": 0.6 + }, + "i1": { + "acquisition_hold_off": 500, + "acquisition_duration": 900 + } + } + }, + "native_gates": { + "single_qubit": { + "0": { + "RX": { + "duration": 40, + "amplitude": 0.5028, + "frequency": 5050304836, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "twpa_pump": { - "frequency": 6535900000, - "power": 4 + "RX12": { + "duration": 40, + "amplitude": 0.5028, + "frequency": 5050304836, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "qcm_rf0": { - "o1": { - "attenuation": 20, - "lo_frequency": 5252833073, - "gain": 0.47 - }, - "o2": { - "attenuation": 20, - "lo_frequency": 5652833073, - "gain": 0.57 - } + "MZ": { + "duration": 2000, + "amplitude": 0.1, + "frequency": 7213299307, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "1": { + "RX": { + "duration": 40, + "amplitude": 0.5078, + "frequency": 4852833073, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "qcm_rf1": { - "o1": { - "attenuation": 20, - "lo_frequency": 5995371914, - "gain": 0.55 - }, - "o2": { - "attenuation": 20, - "lo_frequency": 6961018001, - "gain": 0.596 - } + "RX12": { + "duration": 40, + "amplitude": 0.5078, + "frequency": 4852833073, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "qcm_rf2": { - "o1": { - "attenuation": 20, - "lo_frequency": 6786543060, - "gain": 0.47 - } + "MZ": { + "duration": 2000, + "amplitude": 0.2, + "frequency": 7452990931, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "2": { + "RX": { + "duration": 40, + "amplitude": 0.5016, + "frequency": 5795371914, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "qrm_rf_a": { - "o1": { - "attenuation": 36, - "lo_frequency": 7300000000, - "gain": 0.6 - }, - "i1": { - "acquisition_hold_off": 500, - "acquisition_duration": 900 - } + "RX12": { + "duration": 40, + "amplitude": 0.5016, + "frequency": 5795371914, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "qrm_rf_b": { - "o1": { - "attenuation": 36, - "lo_frequency": 7850000000, - "gain": 0.6 - }, - "i1": { - "acquisition_hold_off": 500, - "acquisition_duration": 900 - } + "MZ": { + "duration": 2000, + "amplitude": 0.25, + "frequency": 7655083068, + "envelope": { "kind": "rectangular" }, + "type": "ro" } - }, - "native_gates": { - "single_qubit": { - "0": { - "RX": { - "duration": 40, - "amplitude": 0.5028, - "frequency": 5050304836, - "shape": "Gaussian(5)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.5028, - "frequency": 5050304836, - "shape": "Gaussian(5)", - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.1, - "frequency": 7213299307, - "shape": "Rectangular()", - "type": "ro" - } - }, - "1": { - "RX": { - "duration": 40, - "amplitude": 0.5078, - "frequency": 4852833073, - "shape": "Gaussian(5)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.5078, - "frequency": 4852833073, - "shape": "Gaussian(5)", - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.2, - "frequency": 7452990931, - "shape": "Rectangular()", - "type": "ro" - } - }, - "2": { - "RX": { - "duration": 40, - "amplitude": 0.5016, - "frequency": 5795371914, - "shape": "Gaussian(5)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.5016, - "frequency": 5795371914, - "shape": "Gaussian(5)", - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.25, - "frequency": 7655083068, - "shape": "Rectangular()", - "type": "ro" - } - }, - "3": { - "RX": { - "duration": 40, - "amplitude": 0.5026, - "frequency": 6761018001, - "shape": "Gaussian(5)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.5026, - "frequency": 6761018001, - "shape": "Gaussian(5)", - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.2, - "frequency": 7803441221, - "shape": "Rectangular()", - "type": "ro" - } - }, - "4": { - "RX": { - "duration": 40, - "amplitude": 0.5172, - "frequency": 6586543060, - "shape": "Gaussian(5)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.5172, - "frequency": 6586543060, - "shape": "Gaussian(5)", - "type": "qd" - }, - "MZ": { - "duration": 2000, - "amplitude": 0.4, - "frequency": 8058947261, - "shape": "Rectangular()", - "type": "ro" - } - } + }, + "3": { + "RX": { + "duration": 40, + "amplitude": 0.5026, + "frequency": 6761018001, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "two_qubit": { - "2-3": { - "CZ": [ - { - "duration": 32, - "amplitude": -0.6025, - "shape": "Exponential(12, 5000, 0.1)", - "qubit": 3, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": -3.63, - "qubit": 3 - }, - { - "type": "virtual_z", - "phase": -0.041, - "qubit": 2 - } - ] - }, - "0-2": { - "CZ": [ - { - "duration": 28, - "amplitude": -0.142, - "shape": "Exponential(12, 5000, 0.1)", - "qubit": 2, - "type": "qf" - } - ] - }, - "1-2": { - "CZ": [ - { - "duration": 32, - "amplitude": -0.6025, - "shape": "Exponential(12, 5000, 0.1)", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": -3.63, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": -0.041, - "qubit": 2 - } - ] - } + "RX12": { + "duration": 40, + "amplitude": 0.5026, + "frequency": 6761018001, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.2, + "frequency": 7803441221, + "envelope": { "kind": "rectangular" }, + "type": "ro" } + }, + "4": { + "RX": { + "duration": 40, + "amplitude": 0.5172, + "frequency": 6586543060, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.5172, + "frequency": 6586543060, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.4, + "frequency": 8058947261, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + } }, - "characterization": { - "single_qubit": { - "0": { - "readout_frequency": 7213299307, - "drive_frequency": 5050304836, - "anharmonicity": 291463266, - "T1": 5857, - "T2": 0, - "sweetspot": 0.5507 - }, - "1": { - "readout_frequency": 7452990931, - "drive_frequency": 4852833073, - "anharmonicity": 292584018, - "T1": 1253, - "T2": 0, - "sweetspot": 0.2227, - "iq_angle": 146.297, - "threshold": 0.003488 + "two_qubit": { + "2-3": { + "CZ": [ + { + "duration": 32, + "amplitude": -0.6025, + "envelope": { + "kind": "exponential", + "tau": 12, + "upsilon": 5000, + "g": 0.1 }, - "2": { - "readout_frequency": 7655083068, - "drive_frequency": 5795371914, - "anharmonicity": 276187576, - "T1": 4563, - "T2": 0, - "sweetspot": -0.378, - "iq_angle": 97.821, - "threshold": 0.002904 + "qubit": 3, + "type": "qf" + }, + { + "type": "vz", + "phase": -3.63, + "qubit": 3 + }, + { + "type": "vz", + "phase": -0.041, + "qubit": 2 + } + ] + }, + "0-2": { + "CZ": [ + { + "duration": 28, + "amplitude": -0.142, + "envelope": { + "kind": "exponential", + "tau": 12, + "upsilon": 5000, + "g": 0.1 }, - "3": { - "readout_frequency": 7803441221, - "drive_frequency": 6761018001, - "anharmonicity": 262310994, - "T1": 4232, - "T2": 0, - "sweetspot": -0.8899, - "iq_angle": 91.209, - "threshold": 0.004318 + "qubit": 2, + "type": "qf" + } + ] + }, + "1-2": { + "CZ": [ + { + "duration": 32, + "amplitude": -0.6025, + "envelope": { + "kind": "exponential", + "tau": 12, + "upsilon": 5000, + "g": 0.1 }, - "4": { - "readout_frequency": 8058947261, - "drive_frequency": 6586543060, - "anharmonicity": 261390626, - "T1": 492, - "T2": 0, - "sweetspot": 0.589, - "iq_angle": 7.997, - "threshold": 0.002323 - } - } + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": -3.63, + "qubit": 1 + }, + { + "type": "vz", + "phase": -0.041, + "qubit": 2 + } + ] + } + } + }, + "characterization": { + "single_qubit": { + "0": { + "readout_frequency": 7213299307, + "drive_frequency": 5050304836, + "anharmonicity": 291463266, + "T1": 5857, + "T2": 0, + "sweetspot": 0.5507 + }, + "1": { + "readout_frequency": 7452990931, + "drive_frequency": 4852833073, + "anharmonicity": 292584018, + "T1": 1253, + "T2": 0, + "sweetspot": 0.2227, + "iq_angle": 146.297, + "threshold": 0.003488 + }, + "2": { + "readout_frequency": 7655083068, + "drive_frequency": 5795371914, + "anharmonicity": 276187576, + "T1": 4563, + "T2": 0, + "sweetspot": -0.378, + "iq_angle": 97.821, + "threshold": 0.002904 + }, + "3": { + "readout_frequency": 7803441221, + "drive_frequency": 6761018001, + "anharmonicity": 262310994, + "T1": 4232, + "T2": 0, + "sweetspot": -0.8899, + "iq_angle": 91.209, + "threshold": 0.004318 + }, + "4": { + "readout_frequency": 8058947261, + "drive_frequency": 6586543060, + "anharmonicity": 261390626, + "T1": 492, + "T2": 0, + "sweetspot": 0.589, + "iq_angle": 7.997, + "threshold": 0.002323 + } } + } } diff --git a/tests/dummy_qrc/qm/parameters.json b/tests/dummy_qrc/qm/parameters.json index b0b4e0025..d4a67753e 100644 --- a/tests/dummy_qrc/qm/parameters.json +++ b/tests/dummy_qrc/qm/parameters.json @@ -1,310 +1,293 @@ { - "nqubits": 5, - "qubits": [ - 0, - 1, - 2, - 3, - 4 - ], - "settings": { - "nshots": 1024, - "relaxation_time": 50000 + "nqubits": 5, + "qubits": [0, 1, 2, 3, 4], + "settings": { + "nshots": 1024, + "relaxation_time": 50000 + }, + "topology": [ + [0, 2], + [1, 2], + [2, 3], + [2, 4] + ], + "instruments": { + "qm": { + "bounds": { + "waveforms": 10000, + "readout": 30, + "instructions": 1000000 + } }, - "topology": [ - [ - 0, - 2 - ], - [ - 1, - 2 - ], - [ - 2, - 3 - ], - [ - 2, - 4 - ] - ], - "instruments": { - "qm": { - "bounds": { - "waveforms" : 10000, - "readout": 30, - "instructions": 1000000 - } + "con1": { + "i1": { "gain": 0 }, + "i2": { "gain": 0 } + }, + "con2": { + "o2": { + "filter": { + "feedforward": [1.0684635881381783, -1.0163217174522334], + "feedback": [0.947858129314055] + } + }, + "i1": { "gain": 0 }, + "i2": { "gain": 0 } + }, + "lo_readout_a": { + "frequency": 7300000000, + "power": 18 + }, + "lo_readout_b": { + "frequency": 7900000000, + "power": 15 + }, + "lo_drive_low": { + "frequency": 4700000000, + "power": 16 + }, + "lo_drive_mid": { + "frequency": 5600000000, + "power": 16 + }, + "lo_drive_high": { + "frequency": 6500000000, + "power": 16 + }, + "twpa_a": { + "frequency": 6511000000, + "power": 4.5 + } + }, + "native_gates": { + "single_qubit": { + "0": { + "RX": { + "duration": 40, + "amplitude": 0.005, + "frequency": 4700000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "con1": { - "i1": {"gain": 0}, - "i2": {"gain": 0} + "RX12": { + "duration": 40, + "amplitude": 0.005, + "frequency": 4700000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "con2": { - "o2": { - "filter": { - "feedforward": [1.0684635881381783, -1.0163217174522334], - "feedback": [0.947858129314055] - } - }, - "i1": {"gain": 0}, - "i2": {"gain": 0} + "MZ": { + "duration": 1000, + "amplitude": 0.0025, + "frequency": 7226500000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "1": { + "RX": { + "duration": 40, + "amplitude": 0.0484, + "frequency": 4855663000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.02 }, + "type": "qd" }, - "lo_readout_a": { - "frequency": 7300000000, - "power": 18 + "RX12": { + "duration": 40, + "amplitude": 0.0484, + "frequency": 4855663000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.02 }, + "type": "qd" }, - "lo_readout_b": { - "frequency": 7900000000, - "power": 15 + "MZ": { + "duration": 620, + "amplitude": 0.003575, + "frequency": 7453265000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "2": { + "RX": { + "duration": 40, + "amplitude": 0.05682, + "frequency": 5800563000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.04 }, + "type": "qd" }, - "lo_drive_low": { - "frequency": 4700000000, - "power": 16 + "RX12": { + "duration": 40, + "amplitude": 0.05682, + "frequency": 5800563000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.04 }, + "type": "qd" }, - "lo_drive_mid": { - "frequency": 5600000000, - "power": 16 + "MZ": { + "duration": 960, + "amplitude": 0.00325, + "frequency": 7655107000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "3": { + "RX": { + "duration": 40, + "amplitude": 0.138, + "frequency": 6760922000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "lo_drive_high": { - "frequency": 6500000000, - "power": 16 + "RX12": { + "duration": 40, + "amplitude": 0.138, + "frequency": 6760922000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "twpa_a": { - "frequency": 6511000000, - "power": 4.5 + "MZ": { + "duration": 960, + "amplitude": 0.004225, + "frequency": 7802191000, + "envelope": { "kind": "rectangular" }, + "type": "ro" } - }, - "native_gates": { - "single_qubit": { - "0": { - "RX": { - "duration": 40, - "amplitude": 0.005, - "frequency": 4700000000, - "shape": "Gaussian(5)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.005, - "frequency": 4700000000, - "shape": "Gaussian(5)", - "type": "qd" - }, - "MZ": { - "duration": 1000, - "amplitude": 0.0025, - "frequency": 7226500000, - "shape": "Rectangular()", - "type": "ro" - } - }, - "1": { - "RX": { - "duration": 40, - "amplitude": 0.0484, - "frequency": 4855663000, - "shape": "Drag(5, 0.02)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.0484, - "frequency": 4855663000, - "shape": "Drag(5, 0.02)", - "type": "qd" - }, - "MZ": { - "duration": 620, - "amplitude": 0.003575, - "frequency": 7453265000, - "shape": "Rectangular()", - "type": "ro" - } - }, - "2": { - "RX": { - "duration": 40, - "amplitude": 0.05682, - "frequency": 5800563000, - "shape": "Drag(5, 0.04)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.05682, - "frequency": 5800563000, - "shape": "Drag(5, 0.04)", - "type": "qd" - }, - "MZ": { - "duration": 960, - "amplitude": 0.00325, - "frequency": 7655107000, - "shape": "Rectangular()", - "type": "ro" - } - }, - "3": { - "RX": { - "duration": 40, - "amplitude": 0.138, - "frequency": 6760922000, - "shape": "Gaussian(5)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.138, - "frequency": 6760922000, - "shape": "Gaussian(5)", - "type": "qd" - }, - "MZ": { - "duration": 960, - "amplitude": 0.004225, - "frequency": 7802191000, - "shape": "Rectangular()", - "type": "ro" - } - }, - "4": { - "RX": { - "duration": 40, - "amplitude": 0.0617, - "frequency": 6585053000, - "shape": "Drag(5, 0)", - "type": "qd" - }, - "RX12": { - "duration": 40, - "amplitude": 0.0617, - "frequency": 6585053000, - "shape": "Drag(5, 0)", - "type": "qd" - }, - "MZ": { - "duration": 640, - "amplitude": 0.0039, - "frequency": 8057668000, - "shape": "Rectangular()", - "type": "ro" - } - } + }, + "4": { + "RX": { + "duration": 40, + "amplitude": 0.0617, + "frequency": 6585053000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0 }, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.0617, + "frequency": 6585053000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0 }, + "type": "qd" }, - "two_qubit": { - "1-2": { - "CZ": [ - { - "duration": 30, - "amplitude": 0.055, - "shape": "Rectangular()", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 2 - } - ] - }, - "2-3": { - "CZ": [ - { - "duration": 32, - "amplitude": -0.0513, - "shape": "Rectangular()", - "qubit": 3, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 2 - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 3 - } - ] - } + "MZ": { + "duration": 640, + "amplitude": 0.0039, + "frequency": 8057668000, + "envelope": { "kind": "rectangular" }, + "type": "ro" } + } }, - "characterization": { - "single_qubit": { - "0": { - "readout_frequency": 0.0, - "drive_frequency": 0.0, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.0, - "threshold": 0.0, - "iq_angle": 0.0, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "1": { - "readout_frequency": 7453265000, - "drive_frequency": 4855663000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": -0.047, - "threshold": 0.00028502261712637096, - "iq_angle": 1.283105298787488, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "2": { - "readout_frequency": 7655107000, - "drive_frequency": 5799876000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": -0.045, - "threshold": 0.0002694329123116206, - "iq_angle": 4.912447775569025, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "3": { - "readout_frequency": 7802391000, - "drive_frequency": 6760700000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.034, - "threshold": 0.0003363427381347193, - "iq_angle": 1.6124890998581591, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "4": { - "readout_frequency": 8057668000, - "drive_frequency": 6585053000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": -0.057, - "threshold": 0.00013079660165463033, - "iq_angle": 5.6303684840135, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - } - } + "two_qubit": { + "1-2": { + "CZ": [ + { + "duration": 30, + "amplitude": 0.055, + "envelope": { "kind": "rectangular" }, + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 1 + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 2 + } + ] + }, + "2-3": { + "CZ": [ + { + "duration": 32, + "amplitude": -0.0513, + "envelope": { "kind": "rectangular" }, + "qubit": 3, + "type": "qf" + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 2 + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 3 + } + ] + } + } + }, + "characterization": { + "single_qubit": { + "0": { + "readout_frequency": 0.0, + "drive_frequency": 0.0, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.0, + "threshold": 0.0, + "iq_angle": 0.0, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "1": { + "readout_frequency": 7453265000, + "drive_frequency": 4855663000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": -0.047, + "threshold": 0.00028502261712637096, + "iq_angle": 1.283105298787488, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "2": { + "readout_frequency": 7655107000, + "drive_frequency": 5799876000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": -0.045, + "threshold": 0.0002694329123116206, + "iq_angle": 4.912447775569025, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "3": { + "readout_frequency": 7802391000, + "drive_frequency": 6760700000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.034, + "threshold": 0.0003363427381347193, + "iq_angle": 1.6124890998581591, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "4": { + "readout_frequency": 8057668000, + "drive_frequency": 6585053000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": -0.057, + "threshold": 0.00013079660165463033, + "iq_angle": 5.6303684840135, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + } } + } } diff --git a/tests/dummy_qrc/qm_octave/parameters.json b/tests/dummy_qrc/qm_octave/parameters.json index c4300b169..a77220498 100644 --- a/tests/dummy_qrc/qm_octave/parameters.json +++ b/tests/dummy_qrc/qm_octave/parameters.json @@ -1,318 +1,315 @@ { - "nqubits": 5, - "qubits": [ - 0, - 1, - 2, - 3, - 4 - ], - "settings": { - "nshots": 1024, - "relaxation_time": 50000 + "nqubits": 5, + "qubits": [0, 1, 2, 3, 4], + "settings": { + "nshots": 1024, + "relaxation_time": 50000 + }, + "topology": [ + [0, 2], + [1, 2], + [2, 3], + [2, 4] + ], + "instruments": { + "qm": { + "bounds": { + "waveforms": 10000, + "readout": 30, + "instructions": 1000000 + } }, - "topology": [ - [ - 0, - 2 - ], - [ - 1, - 2 - ], - [ - 2, - 3 - ], - [ - 2, - 4 - ] - ], - "instruments": { - "qm": { - "bounds": { - "waveforms" : 10000, - "readout": 30, - "instructions": 1000000 - } + "con1": { + "i1": { + "gain": 0 + }, + "i2": { + "gain": 0 + } + }, + "con2": { + "i1": { + "gain": 0 + }, + "i2": { + "gain": 0 + } + }, + "octave1": { + "o1": { + "lo_frequency": 4700000000, + "gain": 0 + }, + "o2": { + "lo_frequency": 5600000000, + "gain": 0 + }, + "o3": { + "lo_frequency": 6500000000, + "gain": 0 + }, + "o4": { + "lo_frequency": 6500000000, + "gain": 0 + }, + "o5": { + "lo_frequency": 7300000000, + "gain": 0 + }, + "i1": { + "lo_frequency": 7300000000 + } + }, + "octave2": { + "o5": { + "lo_frequency": 7900000000, + "gain": 0 + }, + "i1": { + "lo_frequency": 7900000000 + } + }, + "octave3": { + "o1": { + "lo_frequency": 4700000000, + "gain": 0 + } + }, + "twpa_a": { + "frequency": 6511000000, + "power": 4.5 + } + }, + "native_gates": { + "single_qubit": { + "0": { + "RX": { + "duration": 40, + "amplitude": 0.005, + "frequency": 4700000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.005, + "frequency": 4700000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "MZ": { + "duration": 1000, + "amplitude": 0.0025, + "frequency": 7226500000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "1": { + "RX": { + "duration": 40, + "amplitude": 0.0484, + "frequency": 4855663000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.02 }, + "type": "qd" }, - "con1": { - "i1": { - "gain": 0 - }, - "i2": { - "gain": 0 - } + "RX12": { + "duration": 40, + "amplitude": 0.0484, + "frequency": 4855663000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.02 }, + "type": "qd" }, - "con2": { - "i1": { - "gain": 0 - }, - "i2": { - "gain": 0 - } + "MZ": { + "duration": 620, + "amplitude": 0.003575, + "frequency": 7453265000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "2": { + "RX": { + "duration": 40, + "amplitude": 0.05682, + "frequency": 5800563000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.04 }, + "type": "qd" }, - "octave1": { - "o1": { - "lo_frequency": 4700000000, - "gain": 0 - }, - "o2": { - "lo_frequency": 5600000000, - "gain": 0 - }, - "o3": { - "lo_frequency": 6500000000, - "gain": 0 - }, - "o4": { - "lo_frequency": 6500000000, - "gain": 0 - }, - "o5": { - "lo_frequency": 7300000000, - "gain": 0 - }, - "i1": { - "lo_frequency": 7300000000 - } + "RX12": { + "duration": 40, + "amplitude": 0.05682, + "frequency": 5800563000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.04 }, + "type": "qd" }, - "octave2": { - "o5": { - "lo_frequency": 7900000000, - "gain": 0 - }, - "i1": { - "lo_frequency": 7900000000 - } + "MZ": { + "duration": 960, + "amplitude": 0.00325, + "frequency": 7655107000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "3": { + "RX": { + "duration": 40, + "amplitude": 0.138, + "frequency": 6760922000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "octave3": { - "o1": { - "lo_frequency": 4700000000, - "gain": 0 - } + "RX12": { + "duration": 40, + "amplitude": 0.138, + "frequency": 6760922000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "twpa_a": { - "frequency": 6511000000, - "power": 4.5 + "MZ": { + "duration": 960, + "amplitude": 0.004225, + "frequency": 7802191000, + "envelope": { "kind": "rectangular" }, + "type": "ro" } - }, - "native_gates": { - "single_qubit": { - "0": { - "RX": { - "duration": 40, - "amplitude": 0.005, - "frequency": 4700000000, - "shape": "Gaussian(5)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.005, - "frequency": 4700000000, - "shape": "Gaussian(5)", - "type": "qd"}, - "MZ": { - "duration": 1000, - "amplitude": 0.0025, - "frequency": 7226500000, - "shape": "Rectangular()", - "type": "ro"} - }, - "1": { - "RX": { - "duration": 40, - "amplitude": 0.0484, - "frequency": 4855663000, - "shape": "Drag(5, 0.02)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.0484, - "frequency": 4855663000, - "shape": "Drag(5, 0.02)", - "type": "qd"}, - "MZ": { - "duration": 620, - "amplitude": 0.003575, - "frequency": 7453265000, - "shape": "Rectangular()", - "type": "ro"} - }, - "2": { - "RX": { - "duration": 40, - "amplitude": 0.05682, - "frequency": 5800563000, - "shape": "Drag(5, 0.04)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.05682, - "frequency": 5800563000, - "shape": "Drag(5, 0.04)", - "type": "qd"}, - "MZ": { - "duration": 960, - "amplitude": 0.00325, - "frequency": 7655107000, - "shape": "Rectangular()", - "type": "ro"} - }, - "3": { - "RX": { - "duration": 40, - "amplitude": 0.138, - "frequency": 6760922000, - "shape": "Gaussian(5)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.138, - "frequency": 6760922000, - "shape": "Gaussian(5)", - "type": "qd"}, - "MZ": { - "duration": 960, - "amplitude": 0.004225, - "frequency": 7802191000, - "shape": "Rectangular()", - "type": "ro"} - }, - "4": { - "RX": { - "duration": 40, - "amplitude": 0.0617, - "frequency": 6585053000, - "shape": "Drag(5, 0)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.0617, - "frequency": 6585053000, - "shape": "Drag(5, 0)", - "type": "qd"}, - "MZ": { - "duration": 640, - "amplitude": 0.0039, - "frequency": 8057668000, - "shape": "Rectangular()", - "type": "ro"} - } + }, + "4": { + "RX": { + "duration": 40, + "amplitude": 0.0617, + "frequency": 6585053000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0 }, + "type": "qd" + }, + "RX12": { + "duration": 40, + "amplitude": 0.0617, + "frequency": 6585053000, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0 }, + "type": "qd" }, - "two_qubit": { - "1-2": { - "CZ": [ - { - "duration": 30, - "amplitude": 0.055, - "shape": "Rectangular()", - "qubit": 2, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 2 - } - ] - }, - "2-3": { - "CZ": [ - { - "duration": 32, - "amplitude": -0.0513, - "shape": "Rectangular()", - "qubit": 3, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 2 - }, - { - "type": "virtual_z", - "phase": -1.5707963267948966, - "qubit": 3 - } - ] - } + "MZ": { + "duration": 640, + "amplitude": 0.0039, + "frequency": 8057668000, + "envelope": { "kind": "rectangular" }, + "type": "ro" } + } }, - "characterization": { - "single_qubit": { - "0": { - "readout_frequency": 0.0, - "drive_frequency": 0.0, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.0, - "threshold": 0.0, - "iq_angle": 0.0, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "1": { - "readout_frequency": 7453265000, - "drive_frequency": 4855663000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": -0.047, - "threshold": 0.00028502261712637096, - "iq_angle": 1.283105298787488, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "2": { - "readout_frequency": 7655107000, - "drive_frequency": 5799876000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": -0.045, - "threshold": 0.0002694329123116206, - "iq_angle": 4.912447775569025, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "3": { - "readout_frequency": 7802391000, - "drive_frequency": 6760700000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.034, - "threshold": 0.0003363427381347193, - "iq_angle": 1.6124890998581591, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - }, - "4": { - "readout_frequency": 8057668000, - "drive_frequency": 6585053000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": -0.057, - "threshold": 0.00013079660165463033, - "iq_angle": 5.6303684840135, - "mixer_drive_g": 0.0, - "mixer_drive_phi": 0.0, - "mixer_readout_g": 0.0, - "mixer_readout_phi": 0.0 - } - } + "two_qubit": { + "1-2": { + "CZ": [ + { + "duration": 30, + "amplitude": 0.055, + "envelope": { "kind": "rectangular" }, + "qubit": 2, + "type": "qf" + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 1 + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 2 + } + ] + }, + "2-3": { + "CZ": [ + { + "duration": 32, + "amplitude": -0.0513, + "envelope": { "kind": "rectangular" }, + "qubit": 3, + "type": "qf" + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 2 + }, + { + "type": "vz", + "phase": -1.5707963267948966, + "qubit": 3 + } + ] + } + } + }, + "characterization": { + "single_qubit": { + "0": { + "readout_frequency": 0.0, + "drive_frequency": 0.0, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.0, + "threshold": 0.0, + "iq_angle": 0.0, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "1": { + "readout_frequency": 7453265000, + "drive_frequency": 4855663000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": -0.047, + "threshold": 0.00028502261712637096, + "iq_angle": 1.283105298787488, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "2": { + "readout_frequency": 7655107000, + "drive_frequency": 5799876000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": -0.045, + "threshold": 0.0002694329123116206, + "iq_angle": 4.912447775569025, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "3": { + "readout_frequency": 7802391000, + "drive_frequency": 6760700000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.034, + "threshold": 0.0003363427381347193, + "iq_angle": 1.6124890998581591, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + }, + "4": { + "readout_frequency": 8057668000, + "drive_frequency": 6585053000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": -0.057, + "threshold": 0.00013079660165463033, + "iq_angle": 5.6303684840135, + "mixer_drive_g": 0.0, + "mixer_drive_phi": 0.0, + "mixer_readout_g": 0.0, + "mixer_readout_phi": 0.0 + } } + } } diff --git a/tests/dummy_qrc/rfsoc/parameters.json b/tests/dummy_qrc/rfsoc/parameters.json index 0f24f2da8..eb1b24813 100644 --- a/tests/dummy_qrc/rfsoc/parameters.json +++ b/tests/dummy_qrc/rfsoc/parameters.json @@ -1,78 +1,70 @@ { - "nqubits": 1, - "qubits": [ - 0 - ], - "topology": [], - "settings": { - "nshots": 1024, - "relaxation_time": 100000 + "nqubits": 1, + "qubits": [0], + "topology": [], + "settings": { + "nshots": 1024, + "relaxation_time": 100000 + }, + "instruments": { + "tii_rfsoc4x2": { + "bounds": { + "waveforms": 0, + "readout": 0, + "instructions": 0 + } }, - "instruments": { - "tii_rfsoc4x2": { - "bounds": { - "waveforms": 0, - "readout": 0, - "instructions": 0 - } + "twpa_a": { + "frequency": 6200000000, + "power": -1 + }, + "ErasynthLO": { + "frequency": 0, + "power": 0 + } + }, + "native_gates": { + "single_qubit": { + "0": { + "RX": { + "duration": 30, + "amplitude": 0.05284168507293318, + "frequency": 5542341844, + "envelope": { "kind": "rectangular" }, + "type": "qd" }, - "twpa_a": { - "frequency": 6200000000, - "power": -1 + "RX12": { + "duration": 30, + "amplitude": 0.05284168507293318, + "frequency": 5542341844, + "envelope": { "kind": "rectangular" }, + "type": "qd" }, - "ErasynthLO": { - "frequency": 0, - "power": 0 + "MZ": { + "duration": 600, + "amplitude": 0.03, + "frequency": 7371258599, + "envelope": { "kind": "rectangular" }, + "type": "ro" } + } }, - "native_gates": { - "single_qubit": { - "0": { - "RX": { - "duration": 30, - "amplitude": 0.05284168507293318, - "frequency": 5542341844, - "shape": "Rectangular()", - "type": "qd" - }, - "RX12": { - "duration": 30, - "amplitude": 0.05284168507293318, - "frequency": 5542341844, - "shape": "Rectangular()", - "type": "qd" - }, - "MZ": { - "duration": 600, - "amplitude": 0.03, - "frequency": 7371258599, - "shape": "Rectangular()", - "type": "ro" - } - } - }, - "two_qubit": {} - }, - "characterization": { - "single_qubit": { - "0": { - "readout_frequency": 7371258599, - "drive_frequency": 5542341844, - "pi_pulse_amplitude": 0.05284168507293318, - "T1": 10441.64173639732, - "T2": 4083.4697338939845, - "threshold": -0.8981346462690887, - "iq_angle": -1.2621946150226666, - "mean_gnd_states": [ - -0.17994037940379404, - -2.4709365853658536 - ], - "mean_exc_states": [ - 0.6854460704607047, - 0.24369105691056914 - ], - "T2_spin_echo": 5425.5448969467925 - } - } + "two_qubit": {} + }, + "characterization": { + "single_qubit": { + "0": { + "readout_frequency": 7371258599, + "drive_frequency": 5542341844, + "pi_pulse_amplitude": 0.05284168507293318, + "T1": 10441.64173639732, + "T2": 4083.4697338939845, + "threshold": -0.8981346462690887, + "iq_angle": -1.2621946150226666, + "mean_gnd_states": [-0.17994037940379404, -2.4709365853658536], + "mean_exc_states": [0.6854460704607047, 0.24369105691056914], + "T2_spin_echo": 5425.5448969467925 + } } + } } diff --git a/tests/dummy_qrc/zurich/parameters.json b/tests/dummy_qrc/zurich/parameters.json index ba5b9c8f8..3ab0c3c07 100644 --- a/tests/dummy_qrc/zurich/parameters.json +++ b/tests/dummy_qrc/zurich/parameters.json @@ -1,319 +1,286 @@ { - "nqubits": 5, - "qubits": [ - 0, - 1, - 2, - 3, - 4 - ], - "couplers": [ - 0, - 1, - 3, - 4 - ], - "topology": { - "0": [ - 0, - 2 - ], - "1": [ - 1, - 2 - ], - "3": [ - 2, - 3 - ], - "4": [ - 2, - 4 - ] + "nqubits": 5, + "qubits": [0, 1, 2, 3, 4], + "couplers": [0, 1, 3, 4], + "topology": { + "0": [0, 2], + "1": [1, 2], + "3": [2, 3], + "4": [2, 4] + }, + "settings": { + "nshots": 4096, + "relaxation_time": 300000 + }, + "instruments": { + "EL_ZURO": { + "bounds": { + "instructions": 1000000, + "readout": 250, + "waveforms": 40000 + } + }, + "lo_readout": { + "frequency": 5500000000 + }, + "lo_drive_0": { + "frequency": 4200000000 }, - "settings": { - "nshots": 4096, - "relaxation_time": 300000 + "lo_drive_1": { + "frequency": 4600000000 }, - "instruments": { - "EL_ZURO": { - "bounds": { - "instructions": 1000000, - "readout": 250, - "waveforms": 40000 - } + "lo_drive_2": { + "frequency": 4800000000 + } + }, + "native_gates": { + "single_qubit": { + "0": { + "RX": { + "duration": 40, + "amplitude": 0.625, + "frequency": 4095830788, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.04 }, + "type": "qd" }, - "lo_readout": { - "frequency": 5500000000 + "RX12": { + "duration": 40, + "amplitude": 0.625, + "frequency": 4095830788, + "envelope": { "kind": "drag", "rel_sigma": 0.2, "beta": 0.04 }, + "type": "qd" }, - "lo_drive_0": { - "frequency": 4200000000 + "MZ": { + "duration": 2000, + "amplitude": 0.5, + "frequency": 5229200000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "1": { + "RX": { + "duration": 90, + "amplitude": 0.2, + "frequency": 4170000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "lo_drive_1": { - "frequency": 4600000000 + "RX12": { + "duration": 90, + "amplitude": 0.2, + "frequency": 4170000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "lo_drive_2": { - "frequency": 4800000000 + "MZ": { + "duration": 1000, + "amplitude": 0.1, + "frequency": 4931000000, + "envelope": { "kind": "rectangular" }, + "type": "ro" } - }, - "native_gates": { - "single_qubit": { - "0": { - "RX": { - "duration": 40, - "amplitude": 0.625, - "frequency": 4095830788, - "shape": "Drag(5, 0.04)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.625, - "frequency": 4095830788, - "shape": "Drag(5, 0.04)", - "type": "qd"}, - "MZ": { - "duration": 2000, - "amplitude": 0.5, - "frequency": 5229200000, - "shape": "Rectangular()", - "type": "ro"} - }, - "1": { - "RX": { - "duration": 90, - "amplitude": 0.2, - "frequency": 4170000000, - "shape": "Gaussian(5)", - "type": "qd"}, - "RX12": { - "duration": 90, - "amplitude": 0.2, - "frequency": 4170000000, - "shape": "Gaussian(5)", - "type": "qd"}, - "MZ": { - "duration": 1000, - "amplitude": 0.1, - "frequency": 4931000000, - "shape": "Rectangular()", - "type": "ro"} - }, - "2": { - "RX": { - "duration": 40, - "amplitude": 0.59, - "frequency": 4300587281, - "shape": "Gaussian(5)", - "type": "qd"}, - "RX12": { - "duration": 40, - "amplitude": 0.59, - "frequency": 4300587281, - "shape": "Gaussian(5)", - "type": "qd"}, - "MZ": { - "duration": 2000, - "amplitude": 0.54, - "frequency": 6109000000.0, - "shape": "Rectangular()", - "type": "ro"} - }, - "3": { - "RX": { - "duration": 90, - "amplitude": 0.75, - "frequency": 4100000000, - "shape": "Gaussian(5)", - "type": "qd"}, - "RX12": { - "duration": 90, - "amplitude": 0.75, - "frequency": 4100000000, - "shape": "Gaussian(5)", - "type": "qd"}, - "MZ": { - "duration": 2000, - "amplitude": 0.01, - "frequency": 5783000000, - "shape": "Rectangular()", - "type": "ro"} - }, - "4": { - "RX": { - "duration": 53, - "amplitude": 1, - "frequency": 4196800000, - "shape": "Gaussian(5)", - "type": "qd"}, - "RX12": { - "duration": 53, - "amplitude": 1, - "frequency": 4196800000, - "shape": "Gaussian(5)", - "type": "qd"}, - "MZ": { - "duration": 1000, - "amplitude": 0.5, - "frequency": 5515000000, - "shape": "Rectangular()", - "type": "ro"} - } + }, + "2": { + "RX": { + "duration": 40, + "amplitude": 0.59, + "frequency": 4300587281, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "coupler": { - "0": { - "CP": { - "type": "cf", - "duration": 1000, - "amplitude": 0.5, - "shape": "Rectangular()" - } - }, - "1": { - "CP": { - "type": "cf", - "duration": 1000, - "amplitude": 0.5, - "shape": "Rectangular()" - } - }, - "3": { - "CP": { - "type": "cf", - "duration": 1000, - "amplitude": 0.5, - "shape": "Rectangular()" - } - }, - "4": { - "CP": { - "type": "cf", - "duration": 1000, - "amplitude": 0.5, - "shape": "Rectangular()" - } - } + "RX12": { + "duration": 40, + "amplitude": 0.59, + "frequency": 4300587281, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "two_qubit": { - "1-2": { - "CZ": [ - { - "duration": 32, - "amplitude": -0.6025, - "shape": "Exponential(12, 5000, 0.1)", - "qubit": 3, - "type": "qf" - }, - { - "type": "virtual_z", - "phase": -3.63, - "qubit": 1 - }, - { - "type": "virtual_z", - "phase": -0.041, - "qubit": 2 - } - ] - } + "MZ": { + "duration": 2000, + "amplitude": 0.54, + "frequency": 6109000000.0, + "envelope": { "kind": "rectangular" }, + "type": "ro" } - }, - "characterization": { - "single_qubit": { - "0": { - "readout_frequency": 5229200000, - "drive_frequency": 4095830788, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.05, - "mean_gnd_states": [ - 1.542, - 0.1813 - ], - "mean_exc_states": [ - 2.4499, - -0.5629 - ], - "threshold": 0.8836, - "iq_angle": -1.551 - }, - "1": { - "readout_frequency": 4931000000, - "drive_frequency": 4170000000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.0, - "mean_gnd_states": [ - 0, - 0 - ], - "mean_exc_states": [ - 0, - 0 - ] - }, - "2": { - "readout_frequency": 6109000000.0, - "drive_frequency": 4300587281, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.0, - "mean_gnd_states": [ - -1.8243, - 1.5926 - ], - "mean_exc_states": [ - -0.8083, - 2.3929 - ], - "threshold": -0.0593, - "iq_angle": -0.667 - }, - "3": { - "readout_frequency": 5783000000, - "drive_frequency": 4100000000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.0, - "mean_gnd_states": [ - 0, - 0 - ], - "mean_exc_states": [ - 0, - 0 - ] - }, - "4": { - "readout_frequency": 5515000000, - "drive_frequency": 4196800000, - "T1": 0.0, - "T2": 0.0, - "sweetspot": 0.0, - "mean_gnd_states": [ - 0, - 0 - ], - "mean_exc_states": [ - 0, - 0 - ], - "threshold": 0.233806, - "iq_angle": 0.481 - } + }, + "3": { + "RX": { + "duration": 90, + "amplitude": 0.75, + "frequency": 4100000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" }, - "coupler": { - "0": { - "sweetspot": 0.0 - }, - "1": { - "sweetspot": 0.0 - }, - "3": { - "sweetspot": 0.0 - }, - "4": { - "sweetspot": 0.0 - } + "RX12": { + "duration": 90, + "amplitude": 0.75, + "frequency": 4100000000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "MZ": { + "duration": 2000, + "amplitude": 0.01, + "frequency": 5783000000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + }, + "4": { + "RX": { + "duration": 53, + "amplitude": 1, + "frequency": 4196800000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "RX12": { + "duration": 53, + "amplitude": 1, + "frequency": 4196800000, + "envelope": { "kind": "gaussian", "rel_sigma": 0.2 }, + "type": "qd" + }, + "MZ": { + "duration": 1000, + "amplitude": 0.5, + "frequency": 5515000000, + "envelope": { "kind": "rectangular" }, + "type": "ro" + } + } + }, + "coupler": { + "0": { + "CP": { + "type": "cf", + "duration": 1000, + "amplitude": 0.5, + "envelope": { "kind": "rectangular" } } + }, + "1": { + "CP": { + "type": "cf", + "duration": 1000, + "amplitude": 0.5, + "envelope": { "kind": "rectangular" } + } + }, + "3": { + "CP": { + "type": "cf", + "duration": 1000, + "amplitude": 0.5, + "envelope": { "kind": "rectangular" } + } + }, + "4": { + "CP": { + "type": "cf", + "duration": 1000, + "amplitude": 0.5, + "envelope": { "kind": "rectangular" } + } + } + }, + "two_qubit": { + "1-2": { + "CZ": [ + { + "duration": 32, + "amplitude": -0.6025, + "envelope": { + "kind": "exponential", + "tau": 12, + "upsilon": 5000, + "g": 0.1 + }, + "qubit": 3, + "type": "qf" + }, + { + "type": "vz", + "phase": -3.63, + "qubit": 1 + }, + { + "type": "vz", + "phase": -0.041, + "qubit": 2 + } + ] + } + } + }, + "characterization": { + "single_qubit": { + "0": { + "readout_frequency": 5229200000, + "drive_frequency": 4095830788, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.05, + "mean_gnd_states": [1.542, 0.1813], + "mean_exc_states": [2.4499, -0.5629], + "threshold": 0.8836, + "iq_angle": -1.551 + }, + "1": { + "readout_frequency": 4931000000, + "drive_frequency": 4170000000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.0, + "mean_gnd_states": [0, 0], + "mean_exc_states": [0, 0] + }, + "2": { + "readout_frequency": 6109000000.0, + "drive_frequency": 4300587281, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.0, + "mean_gnd_states": [-1.8243, 1.5926], + "mean_exc_states": [-0.8083, 2.3929], + "threshold": -0.0593, + "iq_angle": -0.667 + }, + "3": { + "readout_frequency": 5783000000, + "drive_frequency": 4100000000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.0, + "mean_gnd_states": [0, 0], + "mean_exc_states": [0, 0] + }, + "4": { + "readout_frequency": 5515000000, + "drive_frequency": 4196800000, + "T1": 0.0, + "T2": 0.0, + "sweetspot": 0.0, + "mean_gnd_states": [0, 0], + "mean_exc_states": [0, 0], + "threshold": 0.233806, + "iq_angle": 0.481 + } + }, + "coupler": { + "0": { + "sweetspot": 0.0 + }, + "1": { + "sweetspot": 0.0 + }, + "3": { + "sweetspot": 0.0 + }, + "4": { + "sweetspot": 0.0 + } } + } } diff --git a/tests/pulses/test_envelope.py b/tests/pulses/test_envelope.py new file mode 100644 index 000000000..ed991d18b --- /dev/null +++ b/tests/pulses/test_envelope.py @@ -0,0 +1,231 @@ +import numpy as np +import pytest + +from qibolab.pulses import ( + Drag, + ECap, + Gaussian, + GaussianSquare, + Iir, + Pulse, + PulseType, + Rectangular, + Snz, +) + + +@pytest.mark.parametrize( + "shape", + [ + Rectangular(), + Gaussian(rel_sigma=5), + GaussianSquare(rel_sigma=5, width=0.9), + Drag(rel_sigma=5, beta=1), + ], +) +def test_sampling_rate(shape): + pulse = Pulse( + duration=40, + amplitude=0.9, + frequency=int(100e6), + envelope=shape, + relative_phase=0, + type=PulseType.DRIVE, + ) + assert len(pulse.i(sampling_rate=1)) == 40 + assert len(pulse.i(sampling_rate=100)) == 4000 + + +def test_drag_shape(): + pulse = Pulse( + duration=2, + amplitude=1, + frequency=int(4e9), + envelope=Drag(rel_sigma=0.5, beta=1), + relative_phase=0, + type=PulseType.DRIVE, + ) + # envelope i & envelope q should cross nearly at 0 and at 2 + waveform = pulse.i(sampling_rate=10) + target_waveform = np.array( + [ + 0.63683161, + 0.69680478, + 0.7548396, + 0.80957165, + 0.85963276, + 0.90370708, + 0.94058806, + 0.96923323, + 0.98881304, + 0.99875078, + 0.99875078, + 0.98881304, + 0.96923323, + 0.94058806, + 0.90370708, + 0.85963276, + 0.80957165, + 0.7548396, + 0.69680478, + 0.63683161, + ] + ) + np.testing.assert_allclose(waveform, target_waveform) + + +def test_rectangular(): + pulse = Pulse( + duration=50, + amplitude=1, + frequency=200_000_000, + relative_phase=0, + envelope=Rectangular(), + channel="1", + qubit=0, + ) + + assert pulse.duration == 50 + assert isinstance(pulse.envelope, Rectangular) + + sampling_rate = 1 + num_samples = int(pulse.duration / sampling_rate) + i, q = ( + pulse.amplitude * np.ones(num_samples), + pulse.amplitude * np.zeros(num_samples), + ) + + np.testing.assert_allclose(pulse.i(sampling_rate), i) + np.testing.assert_allclose(pulse.q(sampling_rate), q) + + +def test_gaussian(): + pulse = Pulse( + duration=50, + amplitude=1, + frequency=200_000_000, + relative_phase=0, + envelope=Gaussian(rel_sigma=5), + channel="1", + qubit=0, + ) + + assert pulse.duration == 50 + assert isinstance(pulse.envelope, Gaussian) + assert pulse.envelope.rel_sigma == 5 + + sampling_rate = 1 + num_samples = int(pulse.duration / sampling_rate) + x = np.arange(0, num_samples, 1) + i = pulse.amplitude * np.exp( + -( + ((x - (num_samples - 1) / 2) ** 2) + / (2 * (num_samples * pulse.envelope.rel_sigma) ** 2) + ) + ) + q = pulse.amplitude * np.zeros(num_samples) + + np.testing.assert_allclose(pulse.i(sampling_rate), i) + np.testing.assert_allclose(pulse.q(sampling_rate), q) + + +def test_drag(): + pulse = Pulse( + duration=50, + amplitude=1, + frequency=200_000_000, + relative_phase=0, + envelope=Drag(rel_sigma=0.2, beta=0.2), + qubit=0, + ) + + assert pulse.duration == 50 + assert isinstance(pulse.envelope, Drag) + assert pulse.envelope.rel_sigma == 0.2 + assert pulse.envelope.beta == 0.2 + + sampling_rate = 1 + num_samples = int(pulse.duration / sampling_rate) + x = np.arange(num_samples) + i = pulse.amplitude * np.exp( + -( + ((x - (num_samples - 1) / 2) ** 2) + / (2 * (num_samples * pulse.envelope.rel_sigma) ** 2) + ) + ) + q = pulse.amplitude * ( + pulse.envelope.beta + * ( + -(x - (num_samples - 1) / 2) + / ((num_samples * pulse.envelope.rel_sigma) ** 2) + ) + * i + * sampling_rate + ) + + np.testing.assert_allclose(pulse.i(sampling_rate), i) + np.testing.assert_allclose(pulse.q(sampling_rate), q) + + +def test_eq(): + """Checks == operator for pulse shapes.""" + + shape1 = Rectangular() + shape2 = Rectangular() + shape3 = Gaussian(rel_sigma=5) + assert shape1 == shape2 + assert not shape1 == shape3 + + shape1 = Gaussian(rel_sigma=4) + shape2 = Gaussian(rel_sigma=4) + shape3 = Gaussian(rel_sigma=5) + assert shape1 == shape2 + assert not shape1 == shape3 + + shape1 = GaussianSquare(rel_sigma=4, width=0.01) + shape2 = GaussianSquare(rel_sigma=4, width=0.01) + shape3 = GaussianSquare(rel_sigma=5, width=0.01) + shape4 = GaussianSquare(rel_sigma=4, width=0.05) + shape5 = GaussianSquare(rel_sigma=5, width=0.05) + assert shape1 == shape2 + assert not shape1 == shape3 + assert not shape1 == shape4 + assert not shape1 == shape5 + + shape1 = Drag(rel_sigma=4, beta=0.01) + shape2 = Drag(rel_sigma=4, beta=0.01) + shape3 = Drag(rel_sigma=5, beta=0.01) + shape4 = Drag(rel_sigma=4, beta=0.05) + shape5 = Drag(rel_sigma=5, beta=0.05) + assert shape1 == shape2 + assert not shape1 == shape3 + assert not shape1 == shape4 + assert not shape1 == shape5 + + shape1 = Iir(a=np.array([-0.5, 2]), b=np.array([1]), target=Rectangular()) + shape2 = Iir(a=np.array([-0.5, 2]), b=np.array([1]), target=Rectangular()) + shape3 = Iir(a=np.array([-0.5, 4]), b=np.array([1]), target=Rectangular()) + shape4 = Iir(a=np.array([-0.4, 2]), b=np.array([1]), target=Rectangular()) + shape5 = Iir(a=np.array([-0.5, 2]), b=np.array([2]), target=Rectangular()) + shape6 = Iir(a=np.array([-0.5, 2]), b=np.array([2]), target=Gaussian(rel_sigma=5)) + assert shape1 == shape2 + assert not shape1 == shape3 + assert not shape1 == shape4 + assert not shape1 == shape5 + assert not shape1 == shape6 + + shape1 = Snz(t_idling=5) + shape2 = Snz(t_idling=5) + shape3 = Snz(t_idling=2) + shape4 = Snz(t_idling=2, b_amplitude=0.1) + shape5 = Snz(t_idling=2, b_amplitude=0.1) + assert shape1 == shape2 + assert not shape1 == shape3 + assert not shape1 == shape4 + assert not shape1 == shape5 + + shape1 = ECap(alpha=4) + shape2 = ECap(alpha=4) + shape3 = ECap(alpha=5) + assert shape1 == shape2 + assert not shape1 == shape3 diff --git a/tests/pulses/test_modulation.py b/tests/pulses/test_modulation.py new file mode 100644 index 000000000..fe72e6fcf --- /dev/null +++ b/tests/pulses/test_modulation.py @@ -0,0 +1,72 @@ +import numpy as np + +from qibolab.pulses import Gaussian, IqWaveform, Rectangular +from qibolab.pulses.modulation import demodulate, modulate + + +def test_modulation(): + amplitude = 0.9 + renvs: IqWaveform = Rectangular().envelopes(30) * amplitude + # fmt: off + np.testing.assert_allclose(modulate(renvs, 0.04, rate=1), + np.array([[ 6.36396103e-01, 6.16402549e-01, 5.57678156e-01, + 4.63912794e-01, 3.40998084e-01, 1.96657211e-01, + 3.99596419e-02, -1.19248738e-01, -2.70964282e-01, + -4.05654143e-01, -5.14855263e-01, -5.91706132e-01, + -6.31377930e-01, -6.31377930e-01, -5.91706132e-01, + -5.14855263e-01, -4.05654143e-01, -2.70964282e-01, + -1.19248738e-01, 3.99596419e-02, 1.96657211e-01, + 3.40998084e-01, 4.63912794e-01, 5.57678156e-01, + 6.16402549e-01, 6.36396103e-01, 6.16402549e-01, + 5.57678156e-01, 4.63912794e-01, 3.40998084e-01], + [ 0.00000000e+00, 1.58265275e-01, 3.06586161e-01, + 4.35643111e-01, 5.37327002e-01, 6.05248661e-01, + 6.35140321e-01, 6.25123778e-01, 5.75828410e-01, + 4.90351625e-01, 3.74064244e-01, 2.34273031e-01, + 7.97615814e-02, -7.97615814e-02, -2.34273031e-01, + -3.74064244e-01, -4.90351625e-01, -5.75828410e-01, + -6.25123778e-01, -6.35140321e-01, -6.05248661e-01, + -5.37327002e-01, -4.35643111e-01, -3.06586161e-01, + -1.58265275e-01, 4.09361195e-16, 1.58265275e-01, + 3.06586161e-01, 4.35643111e-01, 5.37327002e-01]]) + ) + # fmt: on + + genvs: IqWaveform = Gaussian(rel_sigma=0.5).envelopes(20) + # fmt: off + np.testing.assert_allclose(modulate(genvs, 0.3,rate=1), + np.array([[ 4.50307953e-01, -1.52257426e-01, -4.31814602e-01, + 4.63124693e-01, 1.87836646e-01, -6.39017403e-01, + 2.05526028e-01, 5.54460924e-01, -5.65661777e-01, + -2.18235048e-01, 7.06223450e-01, -2.16063573e-01, + -5.54460924e-01, 5.38074127e-01, 1.97467237e-01, + -6.07852156e-01, 1.76897892e-01, 4.31814602e-01, + -3.98615117e-01, -1.39152810e-01], + [ 0.00000000e+00, 4.68600175e-01, -3.13731672e-01, + -3.36479785e-01, 5.78101754e-01, 2.34771185e-16, + -6.32544073e-01, 4.02839441e-01, 4.10977338e-01, + -6.71658414e-01, -5.18924572e-16, 6.64975301e-01, + -4.02839441e-01, -3.90933736e-01, 6.07741665e-01, + 6.69963778e-16, -5.44435729e-01, 3.13731672e-01, + 2.89610835e-01, -4.28268313e-01]]) + ) + # fmt: on + + +def test_demodulation(): + signal = np.ones((2, 100)) + freq = 0.15 + rate = 1 + mod = modulate(signal, freq, rate) + + demod = demodulate(mod, freq, rate) + np.testing.assert_allclose(demod, signal) + + mod1 = modulate(demod, freq * 3.0, rate=3.0) + np.testing.assert_allclose(mod1, mod) + + mod2 = modulate(signal, freq, rate, phase=2 * np.pi) + np.testing.assert_allclose(mod2, mod) + + demod1 = demodulate(mod + np.ones_like(mod), freq, rate) + np.testing.assert_allclose(demod1, demod) diff --git a/tests/pulses/test_plot.py b/tests/pulses/test_plot.py index 7164ee8e2..c895404fd 100644 --- a/tests/pulses/test_plot.py +++ b/tests/pulses/test_plot.py @@ -4,34 +4,82 @@ import numpy as np from qibolab.pulses import ( - IIR, - SNZ, Drag, + ECap, Gaussian, GaussianSquare, + Iir, Pulse, PulseSequence, PulseType, Rectangular, - eCap, + Snz, plot, ) -from qibolab.pulses.shape import modulate +from qibolab.pulses.modulation import modulate HERE = pathlib.Path(__file__).parent +SAMPLING_RATE = 1 def test_plot_functions(): - p0 = Pulse(40, 0.9, 0, 0, Rectangular(), 0, PulseType.FLUX, 0) - p1 = Pulse(40, 0.9, 50e6, 0, Gaussian(5), 0, PulseType.DRIVE, 2) - p2 = Pulse(40, 0.9, 50e6, 0, Drag(5, 2), 0, PulseType.DRIVE, 200) - p3 = Pulse.flux(40, 0.9, IIR([-0.5, 2], [1], Rectangular()), channel=0, qubit=200) - p4 = Pulse.flux(40, 0.9, SNZ(t_idling=10), channel=0, qubit=200) - p5 = Pulse(40, 0.9, 400e6, 0, eCap(alpha=2), 0, PulseType.DRIVE) - p6 = Pulse(40, 0.9, 50e6, 0, GaussianSquare(5, 0.9), 0, PulseType.DRIVE, 2) + p0 = Pulse( + duration=40, + amplitude=0.9, + frequency=0, + envelope=Rectangular(), + relative_phase=0, + type=PulseType.FLUX, + qubit=0, + ) + p1 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=Gaussian(rel_sigma=0.2), + relative_phase=0, + type=PulseType.DRIVE, + qubit=2, + ) + p2 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=Drag(rel_sigma=0.2, beta=2), + relative_phase=0, + type=PulseType.DRIVE, + qubit=200, + ) + p3 = Pulse.flux( + duration=40, + amplitude=0.9, + envelope=Iir(a=np.array([-0.5, 2]), b=np.array([1]), target=Rectangular()), + channel="0", + qubit=200, + ) + p4 = Pulse.flux( + duration=40, amplitude=0.9, envelope=Snz(t_idling=10), channel="0", qubit=200 + ) + p5 = Pulse( + duration=40, + amplitude=0.9, + frequency=400e6, + envelope=ECap(alpha=2), + relative_phase=0, + type=PulseType.DRIVE, + ) + p6 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=GaussianSquare(rel_sigma=0.2, width=0.9), + relative_phase=0, + type=PulseType.DRIVE, + qubit=2, + ) ps = PulseSequence([p0, p1, p2, p3, p4, p5, p6]) - envelope = p0.envelope_waveforms() - wf = modulate(np.array(envelope), 0.0) + envelope = p0.envelopes(SAMPLING_RATE) + wf = modulate(np.array(envelope), 0.0, rate=SAMPLING_RATE) plot_file = HERE / "test_plot.png" diff --git a/tests/pulses/test_pulse.py b/tests/pulses/test_pulse.py index 774ba58d3..29650dc8e 100644 --- a/tests/pulses/test_pulse.py +++ b/tests/pulses/test_pulse.py @@ -1,23 +1,20 @@ """Tests ``pulses.py``.""" -import copy - import numpy as np import pytest from qibolab.pulses import ( - IIR, - SNZ, + BaseEnvelope, Custom, Drag, + ECap, Gaussian, GaussianSquare, + Iir, Pulse, - PulseShape, PulseType, Rectangular, - ShapeInitError, - eCap, + Snz, ) @@ -28,8 +25,8 @@ def test_init(): amplitude=0.9, frequency=20_000_000, relative_phase=0.0, - shape=Rectangular(), - channel=0, + envelope=Rectangular(), + channel="0", type=PulseType.READOUT, qubit=0, ) @@ -40,8 +37,8 @@ def test_init(): amplitude=0.9, frequency=20_000_000, relative_phase=0.0, - shape=Rectangular(), - channel=0, + envelope=Rectangular(), + channel="0", type=PulseType.READOUT, qubit=0, ) @@ -53,12 +50,12 @@ def test_init(): amplitude=0.9, frequency=int(20e6), relative_phase=0, - shape=Rectangular(), - channel=0, + envelope=Rectangular(), + channel="0", type=PulseType.READOUT, qubit=0, ) - assert isinstance(p2.frequency, int) and p2.frequency == 20_000_000 + assert isinstance(p2.frequency, float) and p2.frequency == 20_000_000 # initialisation with non float (int) relative_phase p3 = Pulse( @@ -66,8 +63,8 @@ def test_init(): amplitude=0.9, frequency=20_000_000, relative_phase=1.0, - shape=Rectangular(), - channel=0, + envelope=Rectangular(), + channel="0", type=PulseType.READOUT, qubit=0, ) @@ -79,12 +76,12 @@ def test_init(): amplitude=0.9, frequency=20_000_000, relative_phase=0, - shape="Rectangular()", - channel=0, + envelope=Rectangular(), + channel="0", type=PulseType.READOUT, qubit=0, ) - assert isinstance(p4.shape, Rectangular) + assert isinstance(p4.envelope, Rectangular) # initialisation with str channel and str qubit p5 = Pulse( @@ -92,24 +89,82 @@ def test_init(): amplitude=0.9, frequency=20_000_000, relative_phase=0, - shape="Rectangular()", + envelope=Rectangular(), channel="channel0", type=PulseType.READOUT, - qubit="qubit0", + qubit=0, ) - assert p5.qubit == "qubit0" + assert p5.qubit == 0 # initialisation with different frequencies, shapes and types - p6 = Pulse(40, 0.9, -50e6, 0, Rectangular(), 0, PulseType.READOUT) - p7 = Pulse(40, 0.9, 0, 0, Rectangular(), 0, PulseType.FLUX, 0) - p8 = Pulse(40, 0.9, 50e6, 0, Gaussian(5), 0, PulseType.DRIVE, 2) - p9 = Pulse(40, 0.9, 50e6, 0, Drag(5, 2), 0, PulseType.DRIVE, 200) + p6 = Pulse( + duration=40, + amplitude=0.9, + frequency=-50e6, + envelope=Rectangular(), + relative_phase=0, + type=PulseType.READOUT, + ) + p7 = Pulse( + duration=40, + amplitude=0.9, + frequency=0, + envelope=Rectangular(), + relative_phase=0, + type=PulseType.FLUX, + qubit=0, + ) + p8 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=Gaussian(rel_sigma=0.2), + relative_phase=0, + type=PulseType.DRIVE, + qubit=2, + ) + p9 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=Drag(rel_sigma=0.2, beta=2), + relative_phase=0, + type=PulseType.DRIVE, + qubit=200, + ) p10 = Pulse.flux( - 40, 0.9, IIR([-1, 1], [-0.1, 0.1001], Rectangular()), channel=0, qubit=200 + duration=40, + amplitude=0.9, + envelope=Iir( + a=np.array([-1, 1]), b=np.array([-0.1, 0.1001]), target=Rectangular() + ), + channel="0", + qubit=200, + ) + p11 = Pulse.flux( + duration=40, + amplitude=0.9, + envelope=Snz(t_idling=10, b_amplitude=0.5), + channel="0", + qubit=200, + ) + p13 = Pulse( + duration=40, + amplitude=0.9, + frequency=400e6, + envelope=ECap(alpha=2), + relative_phase=0, + type=PulseType.DRIVE, + ) + p14 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=GaussianSquare(rel_sigma=0.2, width=0.9), + relative_phase=0, + type=PulseType.READOUT, + qubit=2, ) - p11 = Pulse.flux(40, 0.9, SNZ(t_idling=10, b_amplitude=0.5), channel=0, qubit=200) - p13 = Pulse(40, 0.9, 400e6, 0, eCap(alpha=2), 0, PulseType.DRIVE) - p14 = Pulse(40, 0.9, 50e6, 0, GaussianSquare(5, 0.9), 0, PulseType.READOUT, 2) # initialisation with float duration p12 = Pulse( @@ -117,8 +172,8 @@ def test_init(): amplitude=0.9, frequency=20_000_000, relative_phase=1, - shape=Rectangular(), - channel=0, + envelope=Rectangular(), + channel="0", type=PulseType.READOUT, qubit=0, ) @@ -127,7 +182,7 @@ def test_init(): def test_attributes(): - channel = 0 + channel = "0" qubit = 0 p10 = Pulse( @@ -135,37 +190,17 @@ def test_attributes(): amplitude=0.9, frequency=20_000_000, relative_phase=0.0, - shape=Rectangular(), + envelope=Rectangular(), channel=channel, qubit=qubit, ) - assert type(p10.duration) == int and p10.duration == 50 - assert type(p10.amplitude) == float and p10.amplitude == 0.9 - assert type(p10.frequency) == int and p10.frequency == 20_000_000 - assert isinstance(p10.shape, PulseShape) and repr(p10.shape) == "Rectangular()" - assert type(p10.channel) == type(channel) and p10.channel == channel - assert type(p10.qubit) == type(qubit) and p10.qubit == qubit - - -def test_hash(): - rp = Pulse(40, 0.9, 100e6, 0, Rectangular(), 0, PulseType.DRIVE) - dp = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 0, PulseType.DRIVE) - hash(rp) - my_dict = {rp: 1, dp: 2} - assert list(my_dict.keys())[0] == rp - assert list(my_dict.keys())[1] == dp - - p1 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 0, PulseType.DRIVE) - p2 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 0, PulseType.DRIVE) - - assert p1 == p2 - - p1 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 0, PulseType.DRIVE) - p2 = copy.copy(p1) - p3 = copy.deepcopy(p1) - assert p1 == p2 - assert p1 == p3 + assert isinstance(p10.duration, float) and p10.duration == 50 + assert isinstance(p10.amplitude, float) and p10.amplitude == 0.9 + assert isinstance(p10.frequency, float) and p10.frequency == 20_000_000 + assert isinstance(p10.envelope, BaseEnvelope) + assert isinstance(p10.channel, type(channel)) and p10.channel == channel + assert isinstance(p10.qubit, type(qubit)) and p10.qubit == qubit def test_aliases(): @@ -174,9 +209,9 @@ def test_aliases(): amplitude=0.9, frequency=20_000_000, relative_phase=0.0, - shape=Rectangular(), + envelope=Rectangular(), type=PulseType.READOUT, - channel=0, + channel="0", qubit=0, ) assert rop.qubit == 0 @@ -186,17 +221,17 @@ def test_aliases(): amplitude=0.9, frequency=200_000_000, relative_phase=0.0, - shape=Gaussian(5), - channel=0, + envelope=Gaussian(rel_sigma=5), + channel="0", qubit=0, ) assert dp.amplitude == 0.9 - assert isinstance(dp.shape, Gaussian) + assert isinstance(dp.envelope, Gaussian) fp = Pulse.flux( - duration=300, amplitude=0.9, shape=Rectangular(), channel=0, qubit=0 + duration=300, amplitude=0.9, envelope=Rectangular(), channel="0", qubit=0 ) - assert fp.channel == 0 + assert fp.channel == "0" def test_pulse(): @@ -208,8 +243,8 @@ def test_pulse(): amplitude=1, duration=duration, relative_phase=0, - shape=f"Drag({rel_sigma}, {beta})", - channel=1, + envelope=Drag(rel_sigma=rel_sigma, beta=beta), + channel="1", ) assert pulse.duration == duration @@ -222,8 +257,8 @@ def test_readout_pulse(): amplitude=1, duration=duration, relative_phase=0, - shape=f"Rectangular()", - channel=11, + envelope=Rectangular(), + channel="11", type=PulseType.READOUT, ) @@ -233,28 +268,19 @@ def test_readout_pulse(): def test_envelope_waveform_i_q(): envelope_i = np.cos(np.arange(0, 10, 0.01)) envelope_q = np.sin(np.arange(0, 10, 0.01)) - custom_shape_pulse = Custom(envelope_i, envelope_q) - custom_shape_pulse_old_behaviour = Custom(envelope_i) + custom_shape_pulse = Custom(i_=envelope_i, q_=envelope_q) pulse = Pulse( duration=1000, amplitude=1, frequency=10e6, relative_phase=0, - shape="Rectangular()", - channel=1, + envelope=Rectangular(), + channel="1", ) - with pytest.raises(ShapeInitError): - custom_shape_pulse.envelope_waveform_i() - with pytest.raises(ShapeInitError): - custom_shape_pulse.envelope_waveform_q() - - custom_shape_pulse.pulse = pulse - custom_shape_pulse_old_behaviour.pulse = pulse - pulse.duration = 2000 + custom_shape_pulse = custom_shape_pulse.model_copy(update={"i_": pulse.i(1)}) + pulse = pulse.model_copy(update={"duration": 2000}) with pytest.raises(ValueError): - custom_shape_pulse.pulse = pulse - custom_shape_pulse.envelope_waveform_i() + custom_shape_pulse.i(samples=10) with pytest.raises(ValueError): - custom_shape_pulse.pulse = pulse - custom_shape_pulse.envelope_waveform_q() + custom_shape_pulse.q(samples=10) diff --git a/tests/pulses/test_sequence.py b/tests/pulses/test_sequence.py index 29c179b82..c44eacbe8 100644 --- a/tests/pulses/test_sequence.py +++ b/tests/pulses/test_sequence.py @@ -17,31 +17,31 @@ def test_add_readout(): amplitude=0.3, duration=60, relative_phase=0, - shape="Gaussian(5)", - channel=1, + envelope=Gaussian(rel_sigma=0.2), + channel="1", ) ) - sequence.append(Delay(4, channel=1)) + sequence.append(Delay(duration=4, channel="1")) sequence.append( Pulse( frequency=200_000_000, amplitude=0.3, duration=60, relative_phase=0, - shape="Drag(5, 2)", - channel=1, - type="qf", + envelope=Drag(rel_sigma=0.2, beta=2), + channel="1", + type=PulseType.FLUX, ) ) - sequence.append(Delay(4, channel=1)) + sequence.append(Delay(duration=4, channel="1")) sequence.append( Pulse( frequency=20_000_000, amplitude=0.9, duration=2000, relative_phase=0, - shape="Rectangular()", - channel=11, + envelope=Rectangular(), + channel="11", type=PulseType.READOUT, ) ) @@ -52,31 +52,54 @@ def test_add_readout(): def test_get_qubit_pulses(): - p1 = Pulse(400, 0.9, 20e6, 0, Gaussian(5), 10, qubit=0) + p1 = Pulse( + duration=400, + amplitude=0.9, + frequency=20e6, + envelope=Gaussian(rel_sigma=0.2), + relative_phase=10, + qubit=0, + ) p2 = Pulse( - 400, - 0.9, - 20e6, - 0, - Rectangular(), - channel=30, + duration=400, + amplitude=0.9, + frequency=20e6, + envelope=Rectangular(), + channel="30", qubit=0, type=PulseType.READOUT, ) - p3 = Pulse(400, 0.9, 20e6, 0, Drag(5, 50), 20, qubit=1) - p4 = Pulse(400, 0.9, 20e6, 0, Drag(5, 50), 30, qubit=1) + p3 = Pulse( + duration=400, + amplitude=0.9, + frequency=20e6, + envelope=Drag(rel_sigma=0.2, beta=50), + relative_phase=20, + qubit=1, + ) + p4 = Pulse( + duration=400, + amplitude=0.9, + frequency=20e6, + envelope=Drag(rel_sigma=0.2, beta=50), + relative_phase=30, + qubit=1, + ) p5 = Pulse( - 400, - 0.9, - 20e6, - 0, - Rectangular(), - channel=30, + duration=400, + amplitude=0.9, + frequency=20e6, + envelope=Rectangular(), + channel="30", qubit=1, type=PulseType.READOUT, ) - p6 = Pulse.flux(400, 0.9, Rectangular(), channel=40, qubit=1) - p7 = Pulse.flux(400, 0.9, Rectangular(), channel=40, qubit=2) + p6 = Pulse.flux( + duration=400, amplitude=0.9, envelope=Rectangular(), channel="40", qubit=1 + ) + p7 = Pulse.flux( + duration=400, amplitude=0.9, envelope=Rectangular(), channel="40", qubit=2 + ) ps = PulseSequence([p1, p2, p3, p4, p5, p6, p7]) assert ps.qubits == [0, 1, 2] @@ -87,35 +110,108 @@ def test_get_qubit_pulses(): def test_get_channel_pulses(): - p1 = Pulse(400, 0.9, 20e6, 0, Gaussian(5), 10) - p2 = Pulse(400, 0.9, 20e6, 0, Rectangular(), 30, type=PulseType.READOUT) - p3 = Pulse(400, 0.9, 20e6, 0, Drag(5, 50), 20) - p4 = Pulse(400, 0.9, 20e6, 0, Drag(5, 50), 30) - p5 = Pulse(400, 0.9, 20e6, 0, Rectangular(), 20, type=PulseType.READOUT) - p6 = Pulse(400, 0.9, 20e6, 0, Gaussian(5), 30) + p1 = Pulse( + duration=400, + frequency=0.9, + amplitude=20e6, + envelope=Gaussian(rel_sigma=0.2), + channel="10", + ) + p2 = Pulse( + duration=400, + frequency=0.9, + amplitude=20e6, + envelope=Rectangular(), + channel="30", + type=PulseType.READOUT, + ) + p3 = Pulse( + duration=400, + frequency=0.9, + amplitude=20e6, + envelope=Drag(rel_sigma=0.2, beta=5), + channel="20", + ) + p4 = Pulse( + duration=400, + frequency=0.9, + amplitude=20e6, + envelope=Drag(rel_sigma=0.2, beta=5), + channel="30", + ) + p5 = Pulse( + duration=400, + frequency=0.9, + amplitude=20e6, + envelope=Rectangular(), + channel="20", + type=PulseType.READOUT, + ) + p6 = Pulse( + duration=400, + frequency=0.9, + amplitude=20e6, + envelope=Gaussian(rel_sigma=0.2), + channel="30", + ) ps = PulseSequence([p1, p2, p3, p4, p5, p6]) - assert ps.channels == [10, 20, 30] - assert len(ps.get_channel_pulses(10)) == 1 - assert len(ps.get_channel_pulses(20)) == 2 - assert len(ps.get_channel_pulses(30)) == 3 - assert len(ps.get_channel_pulses(20, 30)) == 5 + assert sorted(ps.channels) == ["10", "20", "30"] + assert len(ps.get_channel_pulses("10")) == 1 + assert len(ps.get_channel_pulses("20")) == 2 + assert len(ps.get_channel_pulses("30")) == 3 + assert len(ps.get_channel_pulses("20", "30")) == 5 def test_sequence_duration(): - p0 = Delay(20, 1) - p1 = Pulse(40, 0.9, 200e6, 0, Drag(5, 1), 1, PulseType.DRIVE) - p2 = Pulse(1000, 0.9, 20e6, 0, Rectangular(), 1, PulseType.READOUT) + p0 = Delay(duration=20, channel="1") + p1 = Pulse( + duration=40, + amplitude=0.9, + frequency=200e6, + envelope=Drag(rel_sigma=0.2, beta=1), + channel="1", + type=PulseType.DRIVE, + ) + p2 = Pulse( + duration=1000, + amplitude=0.9, + frequency=20e6, + envelope=Rectangular(), + channel="1", + type=PulseType.READOUT, + ) ps = PulseSequence([p0, p1]) + [p2] assert ps.duration == 20 + 40 + 1000 - p2.channel = 2 + ps[-1] = p2.model_copy(update={"channel": "2"}) assert ps.duration == 1000 def test_init(): - p1 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 3, PulseType.DRIVE) - p2 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 2, PulseType.DRIVE) - p3 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 1, PulseType.DRIVE) + p1 = Pulse( + duration=40, + amplitude=0.9, + frequency=100e6, + envelope=Drag(rel_sigma=0.2, beta=1), + channel="3", + type=PulseType.DRIVE, + ) + p2 = Pulse( + duration=40, + amplitude=0.9, + frequency=100e6, + envelope=Drag(rel_sigma=0.2, beta=1), + channel="2", + type=PulseType.DRIVE, + ) + p3 = Pulse( + duration=40, + amplitude=0.9, + frequency=100e6, + envelope=Drag(rel_sigma=0.2, beta=1), + channel="1", + type=PulseType.DRIVE, + ) ps = PulseSequence() assert type(ps) == PulseSequence @@ -141,13 +237,61 @@ def test_init(): def test_operators(): ps = PulseSequence() - ps += [Pulse(200, 0.9, 20e6, 0, Rectangular(), 1, type=PulseType.READOUT)] - ps = ps + [Pulse(200, 0.9, 20e6, 0, Rectangular(), 2, type=PulseType.READOUT)] - ps = [Pulse(200, 0.9, 20e6, 0, Rectangular(), 3, type=PulseType.READOUT)] + ps + ps += [ + Pulse( + duration=200, + amplitude=0.9, + frequency=20e6, + envelope=Rectangular(), + channel="3", + type=PulseType.DRIVE, + ) + ] + ps = ps + [ + Pulse( + duration=200, + amplitude=0.9, + frequency=20e6, + envelope=Rectangular(), + channel="2", + type=PulseType.DRIVE, + ) + ] + ps = [ + Pulse( + duration=200, + amplitude=0.9, + frequency=20e6, + envelope=Rectangular(), + channel="3", + type=PulseType.DRIVE, + ) + ] + ps - p4 = Pulse(40, 0.9, 50e6, 0, Gaussian(5), 3, PulseType.DRIVE) - p5 = Pulse(40, 0.9, 50e6, 0, Gaussian(5), 2, PulseType.DRIVE) - p6 = Pulse(40, 0.9, 50e6, 0, Gaussian(5), 1, PulseType.DRIVE) + p4 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=Gaussian(rel_sigma=0.2), + channel="3", + type=PulseType.DRIVE, + ) + p5 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=Gaussian(rel_sigma=0.2), + channel="2", + type=PulseType.DRIVE, + ) + p6 = Pulse( + duration=40, + amplitude=0.9, + frequency=50e6, + envelope=Gaussian(rel_sigma=0.2), + channel="1", + type=PulseType.DRIVE, + ) another_ps = PulseSequence() another_ps.append(p4) @@ -164,7 +308,14 @@ def test_operators(): # ps.plot() - p7 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 1, PulseType.DRIVE) + p7 = Pulse( + duration=40, + amplitude=0.9, + frequency=100e6, + envelope=Drag(rel_sigma=0.2, beta=1), + channel="1", + type=PulseType.DRIVE, + ) yet_another_ps = PulseSequence([p7]) assert len(yet_another_ps) == 1 yet_another_ps *= 3 @@ -172,7 +323,21 @@ def test_operators(): yet_another_ps *= 3 assert len(yet_another_ps) == 9 - p8 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 1, PulseType.DRIVE) - p9 = Pulse(40, 0.9, 100e6, 0, Drag(5, 1), 2, PulseType.DRIVE) + p8 = Pulse( + duration=40, + amplitude=0.9, + frequency=100e6, + envelope=Drag(rel_sigma=0.2, beta=1), + channel="1", + type=PulseType.DRIVE, + ) + p9 = Pulse( + duration=40, + amplitude=0.9, + frequency=100e6, + envelope=Drag(rel_sigma=0.2, beta=1), + channel="2", + type=PulseType.DRIVE, + ) and_yet_another_ps = 2 * PulseSequence([p9]) + [p8] * 3 assert len(and_yet_another_ps) == 5 diff --git a/tests/pulses/test_shape.py b/tests/pulses/test_shape.py deleted file mode 100644 index 96e34f7ce..000000000 --- a/tests/pulses/test_shape.py +++ /dev/null @@ -1,368 +0,0 @@ -import numpy as np -import pytest - -from qibolab.pulses import ( - IIR, - SNZ, - Drag, - Gaussian, - GaussianSquare, - Pulse, - PulseShape, - PulseType, - Rectangular, - ShapeInitError, - eCap, -) -from qibolab.pulses.shape import IqWaveform, demodulate, modulate - - -@pytest.mark.parametrize( - "shape", [Rectangular(), Gaussian(5), GaussianSquare(5, 0.9), Drag(5, 1)] -) -def test_sampling_rate(shape): - pulse = Pulse(40, 0.9, 100e6, 0, shape, 0, PulseType.DRIVE) - assert len(pulse.envelope_waveform_i(sampling_rate=1)) == 40 - assert len(pulse.envelope_waveform_i(sampling_rate=100)) == 4000 - - -def test_eval(): - shape = PulseShape.eval("Rectangular()") - assert isinstance(shape, Rectangular) - with pytest.raises(ValueError): - shape = PulseShape.eval("Ciao()") - - -@pytest.mark.parametrize("rel_sigma,beta", [(5, 1), (5, -1), (3, -0.03), (4, 0.02)]) -def test_drag_shape_eval(rel_sigma, beta): - shape = PulseShape.eval(f"Drag({rel_sigma}, {beta})") - assert isinstance(shape, Drag) - assert shape.rel_sigma == rel_sigma - assert shape.beta == beta - - -def test_raise_shapeiniterror(): - shape = Rectangular() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_i() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_q() - - shape = Gaussian(0) - with pytest.raises(ShapeInitError): - shape.envelope_waveform_i() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_q() - - shape = GaussianSquare(0, 1) - with pytest.raises(ShapeInitError): - shape.envelope_waveform_i() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_q() - - shape = Drag(0, 0) - with pytest.raises(ShapeInitError): - shape.envelope_waveform_i() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_q() - - shape = IIR([0], [0], None) - with pytest.raises(ShapeInitError): - shape.envelope_waveform_i() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_q() - - shape = SNZ(0) - with pytest.raises(ShapeInitError): - shape.envelope_waveform_i() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_q() - - shape = eCap(0) - with pytest.raises(ShapeInitError): - shape.envelope_waveform_i() - with pytest.raises(ShapeInitError): - shape.envelope_waveform_q() - - -def test_drag_shape(): - pulse = Pulse(2, 1, 4e9, 0, Drag(2, 1), 0, PulseType.DRIVE) - # envelope i & envelope q should cross nearly at 0 and at 2 - waveform = pulse.envelope_waveform_i(sampling_rate=10) - target_waveform = np.array( - [ - 0.63683161, - 0.69680478, - 0.7548396, - 0.80957165, - 0.85963276, - 0.90370708, - 0.94058806, - 0.96923323, - 0.98881304, - 0.99875078, - 0.99875078, - 0.98881304, - 0.96923323, - 0.94058806, - 0.90370708, - 0.85963276, - 0.80957165, - 0.7548396, - 0.69680478, - 0.63683161, - ] - ) - np.testing.assert_allclose(waveform, target_waveform) - - -def test_rectangular(): - pulse = Pulse( - duration=50, - amplitude=1, - frequency=200_000_000, - relative_phase=0, - shape=Rectangular(), - channel=1, - qubit=0, - ) - _if = 0 - - assert pulse.duration == 50 - assert isinstance(pulse.shape, Rectangular) - assert pulse.shape.name == "Rectangular" - assert repr(pulse.shape) == "Rectangular()" - - sampling_rate = 1 - num_samples = int(pulse.duration / sampling_rate) - i, q = ( - pulse.amplitude * np.ones(num_samples), - pulse.amplitude * np.zeros(num_samples), - ) - - np.testing.assert_allclose(pulse.shape.envelope_waveform_i(sampling_rate), i) - np.testing.assert_allclose(pulse.shape.envelope_waveform_q(sampling_rate), q) - - -def test_gaussian(): - pulse = Pulse( - duration=50, - amplitude=1, - frequency=200_000_000, - relative_phase=0, - shape=Gaussian(5), - channel=1, - qubit=0, - ) - _if = 0 - - assert pulse.duration == 50 - assert isinstance(pulse.shape, Gaussian) - assert pulse.shape.name == "Gaussian" - assert pulse.shape.rel_sigma == 5 - assert repr(pulse.shape) == "Gaussian(5)" - - sampling_rate = 1 - num_samples = int(pulse.duration / sampling_rate) - x = np.arange(0, num_samples, 1) - i = pulse.amplitude * np.exp( - -(1 / 2) - * ( - ((x - (num_samples - 1) / 2) ** 2) - / (((num_samples) / pulse.shape.rel_sigma) ** 2) - ) - ) - q = pulse.amplitude * np.zeros(num_samples) - - np.testing.assert_allclose(pulse.shape.envelope_waveform_i(sampling_rate), i) - np.testing.assert_allclose(pulse.shape.envelope_waveform_q(sampling_rate), q) - - -def test_drag(): - pulse = Pulse( - duration=50, - amplitude=1, - frequency=200_000_000, - relative_phase=0, - shape=Drag(5, 0.2), - channel=1, - qubit=0, - ) - _if = 0 - - assert pulse.duration == 50 - assert isinstance(pulse.shape, Drag) - assert pulse.shape.name == "Drag" - assert pulse.shape.rel_sigma == 5 - assert pulse.shape.beta == 0.2 - assert repr(pulse.shape) == "Drag(5, 0.2)" - - sampling_rate = 1 - num_samples = int(pulse.duration / 1 * sampling_rate) - x = np.arange(0, num_samples, 1) - i = pulse.amplitude * np.exp( - -(1 / 2) - * ( - ((x - (num_samples - 1) / 2) ** 2) - / (((num_samples) / pulse.shape.rel_sigma) ** 2) - ) - ) - q = ( - pulse.shape.beta - * (-(x - (num_samples - 1) / 2) / ((num_samples / pulse.shape.rel_sigma) ** 2)) - * i - * sampling_rate - ) - - np.testing.assert_allclose(pulse.shape.envelope_waveform_i(sampling_rate), i) - np.testing.assert_allclose(pulse.shape.envelope_waveform_q(sampling_rate), q) - - -def test_eq(): - """Checks == operator for pulse shapes.""" - - shape1 = Rectangular() - shape2 = Rectangular() - shape3 = Gaussian(5) - assert shape1 == shape2 - assert not shape1 == shape3 - - shape1 = Gaussian(4) - shape2 = Gaussian(4) - shape3 = Gaussian(5) - assert shape1 == shape2 - assert not shape1 == shape3 - - shape1 = GaussianSquare(4, 0.01) - shape2 = GaussianSquare(4, 0.01) - shape3 = GaussianSquare(5, 0.01) - shape4 = GaussianSquare(4, 0.05) - shape5 = GaussianSquare(5, 0.05) - assert shape1 == shape2 - assert not shape1 == shape3 - assert not shape1 == shape4 - assert not shape1 == shape5 - - shape1 = Drag(4, 0.01) - shape2 = Drag(4, 0.01) - shape3 = Drag(5, 0.01) - shape4 = Drag(4, 0.05) - shape5 = Drag(5, 0.05) - assert shape1 == shape2 - assert not shape1 == shape3 - assert not shape1 == shape4 - assert not shape1 == shape5 - - shape1 = IIR([-0.5, 2], [1], Rectangular()) - shape2 = IIR([-0.5, 2], [1], Rectangular()) - shape3 = IIR([-0.5, 4], [1], Rectangular()) - shape4 = IIR([-0.4, 2], [1], Rectangular()) - shape5 = IIR([-0.5, 2], [2], Rectangular()) - shape6 = IIR([-0.5, 2], [2], Gaussian(5)) - assert shape1 == shape2 - assert not shape1 == shape3 - assert not shape1 == shape4 - assert not shape1 == shape5 - assert not shape1 == shape6 - - shape1 = SNZ(5) - shape2 = SNZ(5) - shape3 = SNZ(2) - shape4 = SNZ(2, 0.1) - shape5 = SNZ(2, 0.1) - assert shape1 == shape2 - assert not shape1 == shape3 - assert not shape1 == shape4 - assert not shape1 == shape5 - - shape1 = eCap(4) - shape2 = eCap(4) - shape3 = eCap(5) - assert shape1 == shape2 - assert not shape1 == shape3 - - -def test_modulation(): - rect = Pulse( - duration=30, - amplitude=0.9, - frequency=20_000_000, - relative_phase=0.0, - shape=Rectangular(), - channel=0, - type=PulseType.READOUT, - qubit=0, - ) - renvs: IqWaveform = np.array(rect.shape.envelope_waveforms()) - # fmt: off - np.testing.assert_allclose(modulate(renvs, 0.04), - np.array([[ 6.36396103e-01, 6.16402549e-01, 5.57678156e-01, - 4.63912794e-01, 3.40998084e-01, 1.96657211e-01, - 3.99596419e-02, -1.19248738e-01, -2.70964282e-01, - -4.05654143e-01, -5.14855263e-01, -5.91706132e-01, - -6.31377930e-01, -6.31377930e-01, -5.91706132e-01, - -5.14855263e-01, -4.05654143e-01, -2.70964282e-01, - -1.19248738e-01, 3.99596419e-02, 1.96657211e-01, - 3.40998084e-01, 4.63912794e-01, 5.57678156e-01, - 6.16402549e-01, 6.36396103e-01, 6.16402549e-01, - 5.57678156e-01, 4.63912794e-01, 3.40998084e-01], - [ 0.00000000e+00, 1.58265275e-01, 3.06586161e-01, - 4.35643111e-01, 5.37327002e-01, 6.05248661e-01, - 6.35140321e-01, 6.25123778e-01, 5.75828410e-01, - 4.90351625e-01, 3.74064244e-01, 2.34273031e-01, - 7.97615814e-02, -7.97615814e-02, -2.34273031e-01, - -3.74064244e-01, -4.90351625e-01, -5.75828410e-01, - -6.25123778e-01, -6.35140321e-01, -6.05248661e-01, - -5.37327002e-01, -4.35643111e-01, -3.06586161e-01, - -1.58265275e-01, 4.09361195e-16, 1.58265275e-01, - 3.06586161e-01, 4.35643111e-01, 5.37327002e-01]]) - ) - # fmt: on - - gauss = Pulse( - duration=20, - amplitude=3.5, - frequency=2_000_000, - relative_phase=0.0, - shape=Gaussian(0.5), - channel=0, - type=PulseType.READOUT, - qubit=0, - ) - genvs: IqWaveform = np.array(gauss.shape.envelope_waveforms()) - # fmt: off - np.testing.assert_allclose(modulate(genvs, 0.3), - np.array([[ 2.40604965e+00, -7.47704261e-01, -1.96732725e+00, - 1.97595317e+00, 7.57582564e-01, -2.45926187e+00, - 7.61855973e-01, 1.99830815e+00, -2.00080760e+00, - -7.64718297e-01, 2.47468039e+00, -7.64240497e-01, - -1.99830815e+00, 1.99456483e+00, 7.59953712e-01, - -2.45158868e+00, 7.54746949e-01, 1.96732725e+00, - -1.95751517e+00, -7.43510231e-01], - [ 0.00000000e+00, 2.30119709e+00, -1.42934692e+00, - -1.43561401e+00, 2.33159938e+00, 9.03518154e-16, - -2.34475159e+00, 1.45185586e+00, 1.45367181e+00, - -2.35356091e+00, -1.81836565e-15, 2.35209040e+00, - -1.45185586e+00, -1.44913618e+00, 2.33889703e+00, - 2.70209720e-15, -2.32287226e+00, 1.42934692e+00, - 1.42221802e+00, -2.28828920e+00]]) - ) - # fmt: on - - -def test_demodulation(): - signal = np.ones((2, 100)) - freq = 0.15 - mod = modulate(signal, freq) - - demod = demodulate(mod, freq) - np.testing.assert_allclose(demod, signal) - - mod1 = modulate(demod, freq * 3.0, rate=3.0) - np.testing.assert_allclose(mod1, mod) - - mod2 = modulate(signal, freq, phase=2 * np.pi) - np.testing.assert_allclose(mod2, mod) - - demod1 = demodulate(mod + np.ones_like(mod), freq) - np.testing.assert_allclose(demod1, demod) diff --git a/tests/test_compilers_default.py b/tests/test_compilers_default.py index e226137cf..945f098c8 100644 --- a/tests/test_compilers_default.py +++ b/tests/test_compilers_default.py @@ -190,7 +190,12 @@ def test_add_measurement_to_sequence(platform): mz_pulse = platform.create_MZ_pulse(0) delay = 2 * rx90_pulse1.duration s = PulseSequence( - [rx90_pulse1, rx90_pulse2, Delay(delay, mz_pulse.channel), mz_pulse] + [ + rx90_pulse1, + rx90_pulse2, + Delay(duration=delay, channel=mz_pulse.channel), + mz_pulse, + ] ) # assert sequence == s @@ -205,7 +210,7 @@ def test_align_delay_measurement(platform, delay): mz_pulse = platform.create_MZ_pulse(0) target_sequence = PulseSequence() if delay > 0: - target_sequence.append(Delay(delay, mz_pulse.channel)) + target_sequence.append(Delay(duration=delay, channel=mz_pulse.channel)) target_sequence.append(mz_pulse) assert sequence == target_sequence assert len(sequence.ro_pulses) == 1 diff --git a/tests/test_dummy.py b/tests/test_dummy.py index 5d01a0bca..58d9779b0 100644 --- a/tests/test_dummy.py +++ b/tests/test_dummy.py @@ -2,8 +2,9 @@ import pytest from qibolab import AcquisitionType, AveragingMode, ExecutionParameters, create_platform -from qibolab.pulses import Delay, Pulse, PulseSequence, PulseType +from qibolab.pulses import Delay, GaussianSquare, Pulse, PulseSequence, PulseType from qibolab.qubits import QubitPair +from qibolab.serialize_ import replace from qibolab.sweeper import Parameter, QubitParameter, Sweeper SWEPT_POINTS = 5 @@ -60,8 +61,8 @@ def test_dummy_execute_pulse_sequence_couplers(): sequence.extend(cz.get_qubit_pulses(qubit_ordered_pair.qubit1.name)) sequence.extend(cz.get_qubit_pulses(qubit_ordered_pair.qubit2.name)) sequence.extend(cz.coupler_pulses(qubit_ordered_pair.coupler.name)) - sequence.append(Delay(40, platform.qubits[0].readout.name)) - sequence.append(Delay(40, platform.qubits[2].readout.name)) + sequence.append(Delay(duration=40, channel=platform.qubits[0].readout.name)) + sequence.append(Delay(duration=40, channel=platform.qubits[2].readout.name)) sequence.append(platform.create_MZ_pulse(0)) sequence.append(platform.create_MZ_pulse(2)) options = ExecutionParameters(nshots=None) @@ -140,11 +141,11 @@ def test_dummy_single_sweep_coupler( coupler_pulse = Pulse.flux( duration=40, amplitude=0.5, - shape="GaussianSquare(5, 0.75)", + envelope=GaussianSquare(rel_sigma=0.2, width=0.75), channel="flux_coupler-0", qubit=0, ) - coupler_pulse.type = PulseType.COUPLERFLUX + coupler_pulse = replace(coupler_pulse, type=PulseType.COUPLERFLUX) if parameter is Parameter.amplitude: parameter_range = np.random.rand(SWEPT_POINTS) else: @@ -239,7 +240,9 @@ def test_dummy_double_sweep(name, parameter1, parameter2, average, acquisition, pulse = platform.create_qubit_drive_pulse(qubit=0, duration=1000) ro_pulse = platform.create_MZ_pulse(qubit=0) sequence.append(pulse) - sequence.append(Delay(pulse.duration, channel=platform.qubits[0].readout.name)) + sequence.append( + Delay(duration=pulse.duration, channel=platform.qubits[0].readout.name) + ) sequence.append(ro_pulse) parameter_range_1 = ( np.random.rand(SWEPT_POINTS) diff --git a/tests/test_instruments_qm.py b/tests/test_instruments_qm.py index 5d335dffa..5a0e840f2 100644 --- a/tests/test_instruments_qm.py +++ b/tests/test_instruments_qm.py @@ -94,7 +94,6 @@ def test_qmpulse_previous_and_next(): f"readout{qubit}", PulseType.READOUT, qubit=qubit, - type=PulseType.READOUT, ) ) ro_qmpulses.append(ro_pulse) diff --git a/tests/test_instruments_qmsim.py b/tests/test_instruments_qmsim.py index 6b7cf83df..ceea34f9d 100644 --- a/tests/test_instruments_qmsim.py +++ b/tests/test_instruments_qmsim.py @@ -23,7 +23,7 @@ from qibolab import AcquisitionType, AveragingMode, ExecutionParameters, create_platform from qibolab.backends import QibolabBackend -from qibolab.pulses import SNZ, Pulse, PulseSequence, Rectangular +from qibolab.pulses import Pulse, PulseSequence, Rectangular, Snz from qibolab.sweeper import Parameter, Sweeper from .conftest import set_platform_profile @@ -489,7 +489,7 @@ def test_qmsim_snz_pulse(simulator, folder, qubit): duration = 30 amplitude = 0.01 sequence = PulseSequence() - shape = SNZ(t_half_flux_pulse=duration // 2, b_amplitude=2) + shape = Snz(t_half_flux_pulse=duration // 2, b_amplitude=2) channel = simulator.qubits[qubit].flux.name qd_pulse = simulator.create_RX_pulse(qubit, start=0) flux_pulse = Pulse.flux(qd_pulse.finish, duration, amplitude, shape, channel, qubit) diff --git a/tests/test_instruments_zhinst.py b/tests/test_instruments_zhinst.py index 094b8fcef..ea89655dd 100644 --- a/tests/test_instruments_zhinst.py +++ b/tests/test_instruments_zhinst.py @@ -16,14 +16,14 @@ measure_channel_name, ) from qibolab.pulses import ( - IIR, - SNZ, Drag, Gaussian, + Iir, Pulse, PulseSequence, PulseType, Rectangular, + Snz, ) from qibolab.sweeper import Parameter, Sweeper from qibolab.unrolling import batch @@ -34,18 +34,60 @@ @pytest.mark.parametrize( "pulse", [ - Pulse(40, 0.05, int(3e9), 0.0, Rectangular(), "ch0", qubit=0), - Pulse(40, 0.05, int(3e9), 0.0, Gaussian(5), "ch0", qubit=0), - Pulse(40, 0.05, int(3e9), 0.0, Gaussian(5), "ch0", qubit=0), - Pulse(40, 0.05, int(3e9), 0.0, Drag(5, 0.4), "ch0", qubit=0), - Pulse(40, 0.05, int(3e9), 0.0, SNZ(10, 0.01), "ch0", qubit=0), Pulse( - 40, - 0.05, - int(3e9), - 0.0, - IIR([10, 1], [0.4, 1], target=Gaussian(5)), - "ch0", + duration=40, + amplitude=0.05, + frequency=int(3e9), + relative_phase=0.0, + envelope=Rectangular(), + channel="ch0", + qubit=0, + ), + Pulse( + duration=40, + amplitude=0.05, + frequency=int(3e9), + relative_phase=0.0, + envelope=Gaussian(rel_sigma=5), + channel="ch0", + qubit=0, + ), + Pulse( + duration=40, + amplitude=0.05, + frequency=int(3e9), + relative_phase=0.0, + envelope=Gaussian(rel_sigma=5), + channel="ch0", + qubit=0, + ), + Pulse( + duration=40, + amplitude=0.05, + frequency=int(3e9), + relative_phase=0.0, + envelope=Drag(rel_sigma=5, beta=0.4), + channel="ch0", + qubit=0, + ), + Pulse( + duration=40, + amplitude=0.05, + frequency=int(3e9), + relative_phase=0.0, + envelope=Snz(t_idling=10, b_amplitude=0.01), + channel="ch0", + qubit=0, + ), + Pulse( + duration=40, + amplitude=0.05, + frequency=int(3e9), + relative_phase=0.0, + envelope=Iir( + a=np.array([10, 1]), b=np.array([0.4, 1]), target=Gaussian(rel_sigma=5) + ), + channel="ch0", qubit=0, ), ], @@ -54,7 +96,7 @@ def test_zhpulse_pulse_conversion(pulse): shape = pulse.shape zhpulse = ZhPulse(pulse).zhpulse assert isinstance(zhpulse, laboneq_pulse.Pulse) - if isinstance(shape, (SNZ, IIR)): + if isinstance(shape, (Snz, Iir)): assert len(zhpulse.samples) == 80 else: assert zhpulse.length == 40e-9 @@ -251,8 +293,9 @@ def test_zhsequence(dummy_qrc): IQM5q = create_platform("zurich") controller = IQM5q.instruments["EL_ZURO"] - drive_channel, readout_channel = IQM5q.qubits[0].drive.name, measure_channel_name( - IQM5q.qubits[0] + drive_channel, readout_channel = ( + IQM5q.qubits[0].drive.name, + measure_channel_name(IQM5q.qubits[0]), ) qd_pulse = Pulse(0, 40, 0.05, int(3e9), 0.0, Rectangular(), drive_channel, qubit=0) ro_pulse = Pulse( @@ -285,8 +328,9 @@ def test_zhsequence_couplers(dummy_qrc): IQM5q = create_platform("zurich") controller = IQM5q.instruments["EL_ZURO"] - drive_channel, readout_channel = IQM5q.qubits[0].drive.name, measure_channel_name( - IQM5q.qubits[0] + drive_channel, readout_channel = ( + IQM5q.qubits[0].drive.name, + measure_channel_name(IQM5q.qubits[0]), ) couplerflux_channel = IQM5q.couplers[0].flux.name qd_pulse = Pulse(0, 40, 0.05, int(3e9), 0.0, Rectangular(), drive_channel, qubit=0) diff --git a/tests/test_platform.py b/tests/test_platform.py index 469fca465..f543c7575 100644 --- a/tests/test_platform.py +++ b/tests/test_platform.py @@ -2,7 +2,6 @@ :class:`qibolab.platforms.platform.DesignPlatform`.""" import pathlib -import pickle import warnings import numpy as np @@ -39,7 +38,9 @@ def test_unroll_sequences(platform): qd_pulse = platform.create_RX_pulse(qubit) ro_pulse = platform.create_MZ_pulse(qubit) sequence.append(qd_pulse) - sequence.append(Delay(qd_pulse.duration, platform.qubits[qubit].readout.name)) + sequence.append( + Delay(duration=qd_pulse.duration, channel=platform.qubits[qubit].readout.name) + ) sequence.append(ro_pulse) total_sequence, readouts = unroll_sequences(10 * [sequence], relaxation_time=10000) assert len(total_sequence.ro_pulses) == 10 @@ -60,14 +61,6 @@ def test_platform_sampling_rate(platform): assert platform.sampling_rate >= 1 -@pytest.mark.xfail(reason="Cannot pickle all platforms") -def test_platform_pickle(platform): - serial = pickle.dumps(platform) - new_platform = pickle.loads(serial) - assert new_platform.name == platform.name - assert new_platform.is_connected == platform.is_connected - - def test_dump_runcard(platform, tmp_path): dump_runcard(platform, tmp_path) final_runcard = load_runcard(tmp_path) @@ -350,7 +343,10 @@ def test_ground_state_probabilities_pulses(qpu_platform, start_zero): if not start_zero: qd_pulse = platform.create_RX_pulse(qubit) sequence.append( - Delay(qd_pulse.duration, platform.qubits[qubit].readout.name) + Delay( + duration=qd_pulse.duration, + channel=platform.qubits[qubit].readout.name, + ) ) ro_pulse = platform.create_MZ_pulse(qubit) sequence.append(ro_pulse) @@ -372,14 +368,13 @@ def test_create_RX_drag_pulses(): qubits = [q for q, qb in platform.qubits.items() if qb.drive is not None] beta = 0.1234 for qubit in qubits: - drag_pi = platform.create_RX_drag_pulse(qubit, 0, beta=beta) - assert drag_pi.shape == Drag(drag_pi.shape.rel_sigma, beta=beta) - drag_pi_half = platform.create_RX90_drag_pulse( - qubit, drag_pi.duration, beta=beta + drag_pi = platform.create_RX_drag_pulse(qubit, beta=beta) + assert drag_pi.envelope == Drag(rel_sigma=drag_pi.envelope.rel_sigma, beta=beta) + drag_pi_half = platform.create_RX90_drag_pulse(qubit, beta=beta) + assert drag_pi_half.envelope == Drag( + rel_sigma=drag_pi_half.envelope.rel_sigma, beta=beta ) - assert drag_pi_half.shape == Drag(drag_pi_half.shape.rel_sigma, beta=beta) np.testing.assert_almost_equal(drag_pi.amplitude, 2 * drag_pi_half.amplitude) - # to check ShapeInitError - drag_pi.shape.envelope_waveforms() - drag_pi_half.shape.envelope_waveforms() + drag_pi.envelopes(sampling_rate=1) + drag_pi_half.envelopes(sampling_rate=1) diff --git a/tests/test_serialize.py b/tests/test_serialize.py new file mode 100644 index 000000000..6fcccc3ef --- /dev/null +++ b/tests/test_serialize.py @@ -0,0 +1,21 @@ +import numpy as np +from pydantic import BaseModel, ConfigDict + +from qibolab.serialize_ import NdArray, eq + + +class ArrayModel(BaseModel): + ar: NdArray + + model_config = ConfigDict(arbitrary_types_allowed=True) + + +def test_equality(): + assert eq(ArrayModel(ar=np.arange(10)), ArrayModel(ar=np.arange(10))) + assert not eq(ArrayModel(ar=np.arange(10)), ArrayModel(ar=np.arange(11))) + ar = np.arange(10) + ar[5:] = 42 + assert not eq(ArrayModel(ar=np.arange(10)), ArrayModel(ar=ar)) + + assert not eq(ArrayModel(ar=np.arange(10)), ArrayModel(ar=np.ones((10, 2)))) + assert eq(ArrayModel(ar=np.ones((10, 2))), ArrayModel(ar=np.ones((10, 2)))) diff --git a/tests/test_sweeper.py b/tests/test_sweeper.py index a6ac1f8be..a14829e09 100644 --- a/tests/test_sweeper.py +++ b/tests/test_sweeper.py @@ -8,7 +8,13 @@ @pytest.mark.parametrize("parameter", Parameter) def test_sweeper_pulses(parameter): - pulse = Pulse(40, 0.1, int(1e9), 0.0, Rectangular(), "channel") + pulse = Pulse( + duration=40, + amplitude=0.1, + frequency=1e9, + envelope=Rectangular(), + channel="channel", + ) if parameter is Parameter.amplitude: parameter_range = np.random.rand(10) else: @@ -34,7 +40,13 @@ def test_sweeper_qubits(parameter): def test_sweeper_errors(): - pulse = Pulse(40, 0.1, int(1e9), 0.0, Rectangular(), "channel") + pulse = Pulse( + duration=40, + amplitude=0.1, + frequency=1e9, + envelope=Rectangular(), + channel="channel", + ) qubit = Qubit(0) parameter_range = np.random.randint(10, size=10) with pytest.raises(ValueError): diff --git a/tests/test_unrolling.py b/tests/test_unrolling.py index ce4d4e079..65411acf0 100644 --- a/tests/test_unrolling.py +++ b/tests/test_unrolling.py @@ -7,13 +7,55 @@ def test_bounds_update(): - p1 = Pulse(40, 0.9, int(100e6), 0, Drag(5, 1), 3, PulseType.DRIVE) - p2 = Pulse(40, 0.9, int(100e6), 0, Drag(5, 1), 2, PulseType.DRIVE) - p3 = Pulse(40, 0.9, int(100e6), 0, Drag(5, 1), 1, PulseType.DRIVE) - - p4 = Pulse(1000, 0.9, int(20e6), 0, Rectangular(), 3, PulseType.READOUT) - p5 = Pulse(1000, 0.9, int(20e6), 0, Rectangular(), 2, PulseType.READOUT) - p6 = Pulse(1000, 0.9, int(20e6), 0, Rectangular(), 1, PulseType.READOUT) + p1 = Pulse( + duration=40, + amplitude=0.9, + frequency=int(100e6), + envelope=Drag(rel_sigma=0.2, beta=1), + channel="3", + type=PulseType.DRIVE, + ) + p2 = Pulse( + duration=40, + amplitude=0.9, + frequency=int(100e6), + envelope=Drag(rel_sigma=0.2, beta=1), + channel="2", + type=PulseType.DRIVE, + ) + p3 = Pulse( + duration=40, + amplitude=0.9, + frequency=int(100e6), + envelope=Drag(rel_sigma=0.2, beta=1), + channel="1", + type=PulseType.DRIVE, + ) + + p4 = Pulse( + duration=1000, + amplitude=0.9, + frequency=int(20e6), + envelope=Rectangular(), + channel="3", + type=PulseType.READOUT, + ) + p5 = Pulse( + duration=1000, + amplitude=0.9, + frequency=int(20e6), + envelope=Rectangular(), + channel="2", + type=PulseType.READOUT, + ) + p6 = Pulse( + duration=1000, + amplitude=0.9, + frequency=int(20e6), + envelope=Rectangular(), + channel="1", + type=PulseType.READOUT, + ) ps = PulseSequence([p1, p2, p3, p4, p5, p6]) bounds = Bounds.update(ps) @@ -51,13 +93,55 @@ def test_bounds_comparison(): ], ) def test_batch(bounds): - p1 = Pulse(40, 0.9, int(100e6), 0, Drag(5, 1), 3, PulseType.DRIVE) - p2 = Pulse(40, 0.9, int(100e6), 0, Drag(5, 1), 2, PulseType.DRIVE) - p3 = Pulse(40, 0.9, int(100e6), 0, Drag(5, 1), 1, PulseType.DRIVE) - - p4 = Pulse(1000, 0.9, int(20e6), 0, Rectangular(), 3, PulseType.READOUT) - p5 = Pulse(1000, 0.9, int(20e6), 0, Rectangular(), 2, PulseType.READOUT) - p6 = Pulse(1000, 0.9, int(20e6), 0, Rectangular(), 1, PulseType.READOUT) + p1 = Pulse( + duration=40, + amplitude=0.9, + frequency=int(100e6), + envelope=Drag(rel_sigma=0.2, beta=1), + channel="3", + type=PulseType.DRIVE, + ) + p2 = Pulse( + duration=40, + amplitude=0.9, + frequency=int(100e6), + envelope=Drag(rel_sigma=0.2, beta=1), + channel="2", + type=PulseType.DRIVE, + ) + p3 = Pulse( + duration=40, + amplitude=0.9, + frequency=int(100e6), + envelope=Drag(rel_sigma=0.2, beta=1), + channel="1", + type=PulseType.DRIVE, + ) + + p4 = Pulse( + duration=1000, + amplitude=0.9, + frequency=int(20e6), + envelope=Rectangular(), + channel="3", + type=PulseType.READOUT, + ) + p5 = Pulse( + duration=1000, + amplitude=0.9, + frequency=int(20e6), + envelope=Rectangular(), + channel="2", + type=PulseType.READOUT, + ) + p6 = Pulse( + duration=1000, + amplitude=0.9, + frequency=int(20e6), + envelope=Rectangular(), + channel="1", + type=PulseType.READOUT, + ) ps = PulseSequence([p1, p2, p3, p4, p5, p6])