Skip to content

Releases: qilimanjaro-tech/qililab

0.28.0

09 Dec 13:43
13f5d59
Compare
Choose a tag to compare

New features since last release

  • Incorporated new check for maximum allowed attenuation in RF modules.

#843

  • Updated to latest qblox-instruments version. Changed some deprecated code from the new version and the QcmQrm into the more generic Module class.

#836

  • Added empty handlers for Blocks in QProgram compilers

#839

  • Support GRES in %%submit_job magic method

#828

  • Added intermediate frequency to single input lines on qm. The default is 0 (this prevents some bugs from qua-qm). Now it is possible to use the set_parameter IF and qm.set_frequency for buses with single_input.

#807

  • A new GetParameter operation has been added to the Experiment class, accessible via the .get_parameter() method. This allows users to dynamically retrieve parameters during experiment execution, which is particularly useful when some variables do not have a value at the time of experiment definition but are provided later through external operations. The operation returns a Variable that can be used seamlessly within SetParameter and ExecuteQProgram.

    Example:

    experiment = Experiment()
    
    # Get a parameter's value
    amplitude = experiment.get_parameter(bus="drive_q0", parameter=Parameter.AMPLITUDE)
    
    # The returned value is of type `Variable`. It's value will be resolved during execution.
    # It can be used as usual in operations.
    
    # Use the variable in a SetOperation.
    experiment.set_parameter(bus="drive_q1", parameter=Parameter.AMPLITUDE, value=amplitude)
    
    # Use the variable in an ExecuteQProgram with the lambda syntax.
    def get_qprogram(amplitude: float, duration: int):
      square_wf = Square(amplitude=amplitude, duration=duration)
    
      qp = QProgram()
      qp.play(bus="readout", waveform=square_wf)
      return qp
    
    experiment.execute_qprogram(lambda: amplitude=amplitude: get_qprogram(amplitude, 2000))
    

    #814

  • Added offset set and get for quantum machines (both OPX+ and OPX1000). For hardware loops there is qp.set_offset(bus: str, offset_path0: float, offset_path1: float | None) where offset_path0 is a mandatory field (for flux, drive and readout lines) and offset_path1 is only used when changing the offset of buses that have to IQ lines (drive and readout). For software loops there is platform.set_parameter(alias=bus_name, parameter=ql.Parameter.OFFSET_PARAMETER, value=offset_value). The possible arguments for ql.Parameter are: DC_OFFSET (flux lines), OFFSET_I (I lines for IQ buses), OFFSET_Q (Q lines for IQ buses), OFFSET_OUT1 (output 1 lines for readout lines), OFFSET_OUT2 (output 2 lines for readout lines).
    #791

  • Added the Ramp class, which represents a waveform that linearly ramps between two amplitudes over a specified duration.

    from qililab import Ramp
    
    # Create a ramp waveform from amplitude 0.0 to 1.0 over a duration of 100 units
    ramp_wf = Ramp(from_amplitude=0.0, to_amplitude=1.0, duration=100)

    #816

  • Added the Chained class, which represents a waveform composed of multiple waveforms chained together in time.

    from qililab import Ramp, Square, Chained
    
    # Create a chained waveform consisting of a ramp up, a square wave, and a ramp down
    chained_wf = Chained(
        waveforms=[
            Ramp(from_amplitude=0.0, to_amplitude=1.0, duration=100),
            Square(amplitude=1.0, duration=200),
            Ramp(from_amplitude=1.0, to_amplitude=0.0, duration=100),
        ]
    )

    #816

  • Added add_block() and get_block() methods to the Calibration class. These methods allow users to store a block of operations in a calibration file and later retrieve it. The block can be inserted into a QProgram or Experiment by calling insert_block().

    from qililab import QProgram, Calibration
    
    # Create a QProgram and add operations
    qp = QProgram()
    # Add operations to qp...
    
    # Store the QProgram's body as a block in the calibration file
    calibration = Calibration()
    calibration.add_block(name="qp_as_block", block=qp.body)
    
    # Retrieve the block by its name
    calibrated_block = calibration.get_block(name="qp_as_block")
    
    # Insert the retrieved block into another QProgram
    another_qp = QProgram()
    another_qp.insert_block(block=calibrated_block)

    #816

  • Added routing algorithms to qililab in function of the platform connectivity. This is done passing Qibo own Routers and Placers classes,
    and can be called from different points of the stack.

    The most common way to route, will be automatically through qililab.execute_circuit.execute(), or also from qililab.platform.execute/compile(). Another way, would be doing the transpilation/routing directly from an instance of the Transpiler, with: qililab.digital.circuit_transpiler.transpile/route_circuit() (with this last one, you can route with a different topology from the platform one, if desired, defaults to platform)

    Example

    from qibo import gates
    from qibo.models import Circuit
    from qibo.transpiler.placer import ReverseTraversal, Trivial
    from qibo.transpiler.router import Sabre
    from qililab import build_platform
    from qililab.circuit_transpiler import CircuitTranspiler
    
    # Create circuit:
    c = Circuit(5)
    c.add(gates.CNOT(1, 0))
    
    ### From execute_circuit:
    # With defaults (ReverseTraversal placer and Sabre routing):
    probabilities = ql.execute(c, runcard="./runcards/galadriel.yml", placer= Trivial, router = Sabre, routing_iterations: int = 10,)
    # Changing the placer to Trivial, and changing the number of iterations:
    probabilities = ql.execute(c, runcard="./runcards/galadriel.yml",
    
    ### From the platform:
    # Create platform:
    platform = build_platform(runcard="<path_to_runcard>")
    # With defaults (ReverseTraversal placer, Sabre routing)
    probabilities = platform.execute(c, num_avg: 1000, repetition_duration: 1000)
    # With non-defaults, and specifying the router with kwargs:
    probabilities = platform.execute(c, num_avg: 1000, repetition_duration: 1000,  placer= Trivial, router = (Sabre, {"lookahead": 2}), routing_iterations: int = 20))
    # With a router instance:
    router = Sabre(connectivity=None, lookahead=1) # No connectivity needed, since it will be overwritten by the platform's one
    probabilities = platform.execute(c, num_avg: 1000, repetition_duration: 1000, placer=Trivial, router=router)
    
    ### Using the transpiler directly:
    ### (If using the routing from this points of the stack, you can route with a different topology from the platform one)
    # Create transpiler:
    transpiler = CircuitTranspiler(platform)
    # Default Transpilation (ReverseTraversal, Sabre and Platform connectivity):
    routed_circ, final_layouts = transpiler.route_circuit([c])
    # With Non-Default Trivial placer, specifying the kwargs, for the router, and different coupling_map:
    routed_circ, final_layouts = transpiler.route_circuit([c], placer=Trivial, router=(Sabre, {"lookahead": 2}, coupling_map=<some_different_topology>))
    # Or finally, Routing with a concrete Routing instance:
    router = Sabre(connectivity=None, lookahead=1) # No connectivity needed, since it will be overwritten by the specified in the Transpiler:
    routed_circ, final_layouts = transpiler.route_circuit([c], placer=Trivial, router=router, coupling_map=<connectivity_to_use>)

#821

  • Added a timeout inside quantum machines to control the wait_for_all_values function. The timeout is controlled through the runcard as shown in the example:

    instruments:
      - name: quantum_machines_cluster
        alias: QMM
        ...
        timeout: 10000 # optional timeout in seconds
        octaves:
        ...

    #826

  • Added shareable trigger inside runcard for quantum machines controller. The controller is defined in the runcard following this example:

    instruments:
      - name: con1
          analog_outputs:
          - port: 1
            offset: 0.0
            shareable: True
    

#844

Improvements

  • Legacy linting and formatting tools such as pylint, flake8, isort, bandit, and black have been removed. These have been replaced with Ruff, a more efficient tool that handles both linting and formatting. All configuration settings have been consolidated into the pyproject.toml file, simplifying the project's configuration and maintenance. Integration config files like pre-commit-config.yaml and .github/workflows/code_quality.yml have been updated accordingly. Several rules from Ruff have also been implemented to improve code consistency and quality across the codebase. Additionally, the development dependencies in dev-requirements.txt have been updated to their latest versions, ensuring better compatibility and performance. #813

  • platform.execute_experiment() and the underlying ExperimentExecutor can now handle experiments with multiple qprograms and multiple measurements. Parallel loops are also supported in both experiment and qprogram. The structure of the HDF5 results file as well as the functionality of ExperimentResults cl...

Read more

0.27.1

16 Sep 10:08
235f4ca
Compare
Choose a tag to compare

New features since last release

  • Introduced the possibility to run multiple shots and averages at the same time for execute_anneal_program method.
    #797

  • Introduced the Experiment class, which inherits from StructuredProgram. This new class enables the ability to set parameters and execute quantum programs within a structured experiment. Added the set_parameter method to allow setting platfform parameters and execute_qprogram method to facilitate the execution of quantum programs within the experiment.
    #782

  • Introduced the ExperimentExecutor class to manage and execute quantum experiments within the Qililab framework. This class provides a streamlined way to handle the setup, execution, and results retrieval of experiments.

    Temporary Constraints:

    • The experiment must contain only one QProgram.
    • The QProgram must contain a single measure operation.
    • Parallel loops are not supported.
      #790
  • Introduced the platform.execute_experiment() method for executing experiments. This method simplifies the interaction with the ExperimentExecutor by allowing users to run experiments with a single call.

    Example:

    # Define the QProgram
    qp = QProgram()
    gain = qp.variable(label='resonator gain', domain=Domain.Voltage)
    with qp.for_loop(gain, 0, 10, 1):
        qp.set_gain(bus="readout_bus", gain=gain)
        qp.measure(bus="readout_bus", waveform=IQPair(I=Square(1.0, 1000), Q=Square(1.0, 1000)), weights=IQPair(I=Square(1.0, 2000), Q=Square(1.0, 2000)))
    
    # Define the Experiment
    experiment = Experiment()
    bias_z = experiment.variable(label='bias_z voltage', domain=Domain.Voltage)
    frequency = experiment.variable(label='LO Frequency', domain=Domain.Frequency)
    experiment.set_parameter(alias="drive_q0", parameter=Parameter.VOLTAGE, value=0.5)
    experiment.set_parameter(alias="drive_q1", parameter=Parameter.VOLTAGE, value=0.5)
    experiment.set_parameter(alias="drive_q2", parameter=Parameter.VOLTAGE, value=0.5)
    with experiment.for_loop(bias_z, 0.0, 1.0, 0.1):
        experiment.set_parameter(alias="readout_bus", parameter=Parameter.VOLTAGE, value=bias_z)
        with experiment.for_loop(frequency, 2e9, 8e9, 1e9):
            experiment.set_parameter(alias="readout_bus", parameter=Parameter.LO_FREQUENCY, value=frequency)
            experiment.execute_qprogram(qp)
    
    # Execute the Experiment and display the progress bar.
    # Results will be streamed to an h5 file. The path of this file is returned from the method.
    path = platform.execute_experiment(experiment=experiment, results_path="/tmp/results/")
    
    # Load results
    results, loops = load_results(path)

    #790

  • Introduced a robust context manager platform.session() for managing platform lifecycle operations. The manager automatically calls platform.connect(), platform.initial_setup(), and platform.turn_on_instruments() to set up the platform environment before experiment execution. It then ensures proper resource cleanup by invoking platform.turn_off_instruments() and platform.disconnect() after the experiment, even in the event of an error or exception during execution. If multiple exceptions occur during cleanup (e.g., failures in both turn_off_instruments() and disconnect()), they are aggregated into a single ExceptionGroup (Python 3.11+) or a custom exception for earlier Python versions.

    Example:

    with platform.session():
      # do stuff...

    #792

  • Add crosstalk compensation to AnnealingProgram workflow. Add methods to CrosstalkMatrix to ease crosstalk compensation in the annealing workflow
    #775

  • Add default measurement to execute_anneal_program() method. This method takes now a calibration file and parameters
    to add the dispersive measurement at the end of the annealing schedule.
    #778

  • Added a try/except clause when executing a QProgram on Quantum Machines cluster that controls the execution failing to perform a turning off of the instrument so the _qm object gets
    removed. This, plus setting the close_other_machines=True by default allows to open more than one QuantumMachines VM at the same time to allow more than one experimentalist to work at the same time in the cluster.
    #760

  • Added __str__ method to qprogram. The string is a readable qprogram.
    #767

  • Added workflow for the execution of annealing programs.

    Example:

    import qililab as ql
    
    platform = ql.build_platform("examples/runcards/galadriel.yml")
    anneal_program_dict = [
      {qubit_0": {"sigma_x" : 0, "sigma_y": 0, "sigma_z": 1, "phix":1, "phiz":1},
        "qubit_1": {"sigma_x" : 0.1, "sigma_y": 0.1, "sigma_z": 0.1},
        "coupler_0_1": {"sigma_x" : 1, "sigma_y": 0.2, "sigma_z": 0.2}
       },
      {"qubit_0": {"sigma_x" : 0.1, "sigma_y": 0.1, "sigma_z": 1.1},
        "qubit_1": {"sigma_x" : 0.2, "sigma_y": 0.2, "sigma_z": 0.2},
        "coupler_0_1": {"sigma_x" : 0.9, "sigma_y": 0.1, "sigma_z": 0.1}
       },
       {"qubit_0": {"sigma_x" : 0.3, "sigma_y": 0.3, "sigma_z": 0.7},
        "qubit_1": {"sigma_x" : 0.5, "sigma_y": 0.2, "sigma_z": 0.01},
        "coupler_0_1": {"sigma_x" : 0.5, "sigma_y": 0, "sigma_z": -1}
        }
    ]
    
    results = platform.execute_anneal_program(anneal_program_dict=anneal_program_dict, transpiler=lambda delta, epsilon: (delta, epsilon), averages=100_000)

    Alternatively, each step of the workflow can be executed separately i.e. the following is equivalent to the above:

    import qililab as ql
    
    platform = ql.build_platform("examples/runcards/galadriel.yml")
    anneal_program_dict = [...]  # same as in the above example
    # intialize annealing program class
    anneal_program = ql.AnnealingProgram(
        platform=platform, anneal_program=anneal_program_dict
    )
    # transpile ising to flux, now flux values can be accessed same as ising coeff values
    # eg. for phix qubit 0 at t=1ns anneal_program.anneal_program[1]["qubit_0"]["phix"]
    anneal_program.transpile(lambda delta, epsilon: (delta, epsilon))
    # get a dictionary {control_flux: (bus, waveform) from the transpiled fluxes
    anneal_waveforms = anneal_program.get_waveforms()
    # from here on we can create a qprogram to execute the annealing schedule

    #767

  • Added CrosstalkMatrix class to represent and manipulate a crosstalk matrix, where each index corresponds to a bus. The class includes methods for initializing the matrix, getting and setting crosstalk values, and generating string representations of the matrix.

    Example:

    # Create an empty crosstalk matrix
    crosstalk_matrix = CrosstalkMatrix()
    
    # Add crosstalk values, where the keys are in matrix shape [row][column]
    crosstalk_matrix["bus1"]["bus2"] = 0.9
    crosstalk_matrix["bus2"]["bus1"] = 0.1
    
    # Alternatively, create a matrix from a collection of buses.
    # All crosstalk values are initialized to 1.0
    crosstalk_matrix = CrosstalkMatrix.from_buses({"bus1", "bus2", "bus3"})
    
    # Get a formatted string representation of the matrix
    #        bus1     bus2     bus3
    # bus1   \        1.0      1.0
    # bus2   1.0      \        1.0
    # bus3   1.0      1.0      \
    
    print(crosstalk_matrix)
  • Added the Qblox-specific set_markers() method in QProgram. This method takes a 4-bit binary mask as input, where 0 means that the associated marker will be open (no signal) and 1 means that the associated marker will be closed (signal). The mapping between bit indexes and markers depends on the Qblox module that the compiled QProgram will run on.

    Example:

    qp = QProgram()
    qp.qblox.set_markers(bus='drive_q0', mask='0111')

    #747

  • Added set_markers_override_enabled_by_port and set_markers_override_value_by_port methods in QbloxModule to set markers through QCoDeS, overriding Q1ASM values.
    #747

  • Added from_qprogram method to the Counts class to compute the counts of quantum states obtained from a QProgram. The Counts object is designed to work for circuits that have only one measurement per bus at the end of the circuit execution. It is the user's responsibility to ensure that this method is used appropriately when it makes sense to compute the state counts for a QProgram. Note that probabilities can easily be obtained by calling the probabilities() method. See an example below.

    Example:

    from qililab.result.counts import Counts
    
    qp = QProgram()
    # Define instructions for QProgram
    # ...
    qp_results = platform.execute_qprogram(qp)  # Platform previously defined
    counts_object = Counts.from_qprogram(qp_results)
    probs = counts_object.probabilities()

    #743

  • Added threshold_rotations argument to compile() method in QProgram. This argument allows to use rotation angles on measurement instructions if not specified. Currently used to use the angle rotations specified on the runcard (if any) so the user does not have to explicitly pass it as argument to the measure instruction. Used for classification of results in Quantum Machines's modules. The following example shows how to specify this value on the runcard.
    ...

Read more

0.27.0

28 Jun 09:44
6bf3e96
Compare
Choose a tag to compare

New features since last release

  • Added Calibration class to manage calibrated waveforms and weights for QProgram. Included methods to add (add_waveform/add_weights), check (has_waveform/has_weights), retrieve (get_waveform/get_weights), save (save_to), and load (load_from) calibration data.

    Example:

    # Create a Calibration instance
    calibration = Calibration()
    
    # Define waveforms and weights
    drag_wf = IQPair.DRAG(amplitude=1.0, duration=40, num_sigmas=4.5, drag_coefficient=-2.5)
    readout_wf = ql.IQPair(I=ql.Square(amplitude=1.0, duration=200), Q=ql.Square(amplitude=0.0, duration=200))
    weights = ql.IQPair(I=ql.Square(amplitude=1.0, duration=200), Q=ql.Square(amplitude=1.0, duration=200))
    
    # Add waveforms to the calibration
    calibration.add_waveform(bus='drive_q0_bus', name='Xpi', waveform=drag_wf)
    calibration.add_waveform(bus='readout_q0_bus', name='Measure', waveform=readout_wf)
    
    # Add weights to the calibration
    calibration.add_weights(bus='readout_q0_bus', name='optimal_weights', weights=weights)
    
    # Save the calibration data to a file
    calibration.save_to('calibration_data.yml')
    
    # Load the calibration data from a file
    loaded_calibration = Calibration.load_from('calibration_data.yml')

    The contents of calibration_data.yml will be:

    !Calibration
    waveforms:
      drive_q0_bus:
        Xpi: !IQPair
          I: &id001 !Gaussian {amplitude: 1.0, duration: 40, num_sigmas: 4.5}
          Q: !DragCorrection
            drag_coefficient: -2.5
            waveform: *id001
      readout_q0_bus:
        Measure: !IQPair
          I: !Square {amplitude: 1.0, duration: 200}
          Q: !Square {amplitude: 0.0, duration: 200}
    weights:
      readout_q0_bus:
        optimal_weights: !IQPair
          I: !Square {amplitude: 1.0, duration: 200}
          Q: !Square {amplitude: 1.0, duration: 200}

    Calibrated waveforms and weights can be used in QProgram by providing their name.

    qp = QProgram()
    qp.play(bus='drive_q0_bus', waveform='Xpi')
    qp.measure(bus='readout_q0_bus', waveform='Measure', weights='optimal_weights')

    In that case, a Calibration instance must be provided when executing the QProgram. (see following changelog entries)

    #729
    #736

  • Introduced qililab.yaml namespace that exports a single YAML instance for common use throughout qililab. Classes should be registered to this instance with the @yaml.register_class decorator.

    from qililab.yaml import yaml
    
    @yaml.register_class
    class MyClass:
        ...

    MyClass can now be saved to and loaded from a yaml file.

    from qililab.yaml import yaml
    
    my_instance = MyClass()
    
    # Save to file
    with open(file="my_file.yml", mode="w", encoding="utf-8") as stream:
        yaml.dump(data=my_instance, stream=stream)
    
    # Load from file
    with open(file="my_file.yml", mode="r", encoding="utf8") as stream:
        loaded_instance = yaml.load(stream)

    #729

  • Added serialize(), serialize_to(), deserialize(), deserialize_from() functions to enable a unified method for serializing and deserializing Qililab classes to and from YAML memory strings and files.

    import qililab as ql
    
    qp = QProgram()
    
    # Serialize QProgram to a memory string and deserialize from it.
    yaml_string = ql.serialize(qp)
    deserialized_qprogram = ql.deserialize(yaml_string)
    
    # Specify the class for deserialization using the `cls` parameter.
    deserialized_qprogram = ql.deserialize(yaml_string, cls=ql.QProgram)
    
    # Serialize to and deserialize from a file.
    ql.serialize_to(qp, 'qprogram.yml')
    deserialized_qprogram = ql.deserialize_from('qprogram.yml', cls=ql.QProgram)

    #737

  • Added Qblox support for QProgram's measure operation. The method can now be used for both Qblox
    and Quantum Machines, and the expected behaviour is the same.

    readout_pair = IQPair(I=Square(amplitude=1.0, duration=1000), Q=Square(amplitude=0.0, duration=1000))
    weights_pair = IQPair(I=Square(amplitude=1.0, duration=2000), Q=Square(amplitude=0.0, duration=2000))
    qp = QProgram()
    
    # The measure operation has the same behaviour in both vendors.
    # Time of flight between readout pulse and beginning of acquisition is retrieved from the instrument's settings.
    qp.measure(bus="readout_bus", waveform=readout_pair, weights=weights_pair, save_adc=True)

    #734
    #736
    #738

  • Update Qibo version to v.0.2.8.
    #732

Improvements

  • Introduced QProgram.with_bus_mapping method to remap buses within the QProgram.

    Example:

    # Define the bus mapping
    bus_mapping = {"drive": "drive_q0"}
    
    # Apply the bus mapping to a QProgram instance
    mapped_qprogram = qprogram.with_bus_mapping(bus_mapping=bus_mapping)

    #729
    #740

  • Introduced QProgram.with_calibration method to apply calibrated waveforms and weights to the QProgram.

    Example:

    # Load the calibration data from a file
    calibration = Calibration.load_from('calibration_data.yml')
    
    # Apply the calibration to a QProgram instance
    calibrated_qprogram = qprogram.with_calibration(calibration=calibration)

    #729
    #736

  • Extended Platform.execute_qprogram method to accept a calibration instance.

    # Load the calibration data from a file
    calibration = Calibration.load_from('calibration_data.yml')
    
    platform.execute_qprogram(qprogram=qprogram, calibration=calibration)

    #729

  • Added interfaces for Qblox and Quantum Machines to QProgram. The interfaces contain vendor-specific methods and parameters. They can be accessed by qprogram.qblox and qprogram.quantum_machines properties.

    #736

  • Added time_of_flight setting to Qblox QRM and QRM-RF sequencers.

    #738

Breaking changes

  • QProgram interface now contains methods and parameters that have common functionality for all hardware vendors. Vendor-specific methods and parameters have been move to their respective interface.

    Examples:

    # Acquire method has been moved to Qblox interface. Instead of running
    # qp.acquire(bus="readout_q0_bus", weights=weights)
    # you should run
    qp.qblox.acquire(bus="readout_q0_bus", weights=weights)
    
    # Play method with `wait_time` parameter has been moved to Qblox interface. Instead of running
    # qp.play(bus="readout_q0_bus", waveform=waveform, wait_time=40)
    # you should run
    qp.qblox.play(bus="readout_q0_bus", waveform=waveform, wait_time=40)
    
    # `disable_autosync` parameter has been moved to Qblox interface. Instead of running
    # qp = QProgram(disable_autosync=True)
    # you should run
    qp = QProgram()
    qp.qblox.disable_autosync = True
    
    # Measure method with parameters `rotation` and `demodulation` has been moved to Quantum Machines interface. Instead of running
    # qp.measure(bus="readout_q0_bus", waveform=waveform, weights=weights, save_adc=True, rotation=np.pi, demodulation=True)
    # you should run
    qp.quantum_machines.measure(bus="readout_q0_bus", waveform=waveform, weights=weights, save_adc=True, rotation=np.pi, demodulation=True)

    #736

  • time_of_flight parameter must be added to Qblox QRM and QRM-RF sequencers's runcard settings.

    #738

Deprecations / Removals

  • Remove qiboconnection dependency from Qililab. It is not a requirement anymore.
    #732

  • Following the remove of Qiboconnection, LivePlot has been removed along with the creation of a Platform via API.
    #732

  • Remove the deprecated path argument from build_platform().

    #739

0.26.2

28 May 09:33
bd9d51d
Compare
Choose a tag to compare

New features since last release

  • Introduce the Two-Step pulse shape to improve readout
    #730

Deprecations / Removals

  • Remove qiboconnection_api.block_device() and release_device()
    #728

0.26.1

26 Apr 15:20
92e1990
Compare
Choose a tag to compare

Bug fixes

  • Hotfix for the 2readout problem
    #720

0.25.1

27 Mar 15:25
6bfbf64
Compare
Choose a tag to compare

Bug fixes

  • Appended hardcoded Time of Flight
    #711

0.25.0

26 Mar 09:21
7525b68
Compare
Choose a tag to compare

New features since last release

  • Add FlatTop pulse shape
    #680

  • Add FlatTop waveform
    #680

  • Add support for multiple QRM modules
    #680

  • Update qpysequence to 10.1
    #680

Improvements

  • The method CalibrationNode._execute_notebook() now changes the working directory to the notebook directory before the execution and restores the previous one after the papermill execution. It allows the notebooks now to use relative paths. Also, the initialization of CalibrationNode will now contain absolute paths for the attributes nb_folder and nb_path
    #693

Breaking changes

  • Added support for Qblox cluster firmware v0.6.1 and qblox-instruments v0.11.2. This changes some of the i/o mappings in the runcard for qblox sequencers so with older versions is broken.
    #680

Bug fixes

  • Resolved an issue where attempting to execute a previously compiled QUA program on a newly instantiated Quantum Machine resulted in errors due to cache invalidation.
    #706

0.24.0

05 Mar 16:30
2e0bf29
Compare
Choose a tag to compare

New features since last release

  • Introduced a new parameter, disable_autosync, to the QProgram constructor. This parameter allows users to control the automatic synchronization behavior of loops within their quantum programs. By default, the parameter is set to False, enabling the compiler to automatically insert synchronization operations at the conclusion of each loop. Users have the option to set disable_autosync to True to indicate that they prefer to manage loop timing manually. This feature is particularly useful for operations on Qblox hardware, due to its constraints on dynamic synchronization. It's important to note that Quantum Machines will disregard this setting and adhere to the default synchronization behavior.
    #694

Breaking changes

  • The unit of measurement for phases within QProgram has been updated from degrees to radians.
    #695

Bug fixes

  • Resolved an issue encountered during the retrieval of results from QProgram executions on Qblox hardware, where acquisition data from other sequencers would unintentionally be deleted.
    #691

0.23.3

19 Feb 14:10
bdb44c6
Compare
Choose a tag to compare

Bug fixes

  • Fixed an issue when serializing / deserializing a QProgram so results are returned in a standard results class.
    #688

0.23.2

13 Feb 15:09
077ae31
Compare
Choose a tag to compare

Bug fixes

  • Fixed an issue when serializing / deserializing a QProgram that contained an Arbitrary waveform or a DRAG pulse.
    #686