Skip to main contentIBM Quantum Documentation
This page is from an old version of Qiskit SDK and does not exist in the latest version. We recommend you migrate to the latest version. See the release notes for more information.

qiskit.pulse.builder.call

call(target, name=None, value_dict=None, **kw_params)

GitHub

Call the subroutine within the currently active builder context with arbitrary parameters which will be assigned to the target program.

Note

If the target program is a ScheduleBlock, then a Reference instruction will be created and appended to the current context. The target program will be immediately assigned to the current scope as a subroutine. If the target program is Schedule, it will be wrapped by the Call instruction and appended to the current context to avoid a mixed representation of ScheduleBlock and Schedule. If the target program is a QuantumCircuit it will be scheduled and the new Schedule will be added as a Call instruction.

Examples

  1. Calling a schedule block (recommended)
from qiskit import circuit, pulse
from qiskit.providers.fake_provider import FakeBogotaV2
 
backend = FakeBogotaV2()
 
with pulse.build() as x_sched:
    pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0))
 
with pulse.build() as pulse_prog:
    pulse.call(x_sched)
 
print(pulse_prog)
ScheduleBlock(
    ScheduleBlock(
        Play(
            Gaussian(duration=160, amp=(0.1+0j), sigma=40),
            DriveChannel(0)
        ),
        name="block0",
        transform=AlignLeft()
    ),
    name="block1",
    transform=AlignLeft()
)

The actual program is stored in the reference table attached to the schedule.

print(pulse_prog.references)
ReferenceManager:
  - ('block0', '634b3b50bd684e26a673af1fbd2d6c81'): ScheduleBlock(Play(Gaussian(...

In addition, you can call a parameterized target program with parameter assignment.

amp = circuit.Parameter("amp")
 
with pulse.build() as subroutine:
    pulse.play(pulse.Gaussian(160, amp, 40), pulse.DriveChannel(0))
 
with pulse.build() as pulse_prog:
    pulse.call(subroutine, amp=0.1)
    pulse.call(subroutine, amp=0.3)
 
print(pulse_prog)
ScheduleBlock(
    ScheduleBlock(
        Play(
            Gaussian(duration=160, amp=(0.1+0j), sigma=40),
            DriveChannel(0)
        ),
        name="block2",
        transform=AlignLeft()
    ),
    ScheduleBlock(
        Play(
            Gaussian(duration=160, amp=(0.3+0j), sigma=40),
            DriveChannel(0)
        ),
        name="block2",
        transform=AlignLeft()
    ),
    name="block3",
    transform=AlignLeft()
)

If there is a name collision between parameters, you can distinguish them by specifying each parameter object in a python dictionary. For example,

amp1 = circuit.Parameter('amp')
amp2 = circuit.Parameter('amp')
 
with pulse.build() as subroutine:
    pulse.play(pulse.Gaussian(160, amp1, 40), pulse.DriveChannel(0))
    pulse.play(pulse.Gaussian(160, amp2, 40), pulse.DriveChannel(1))
 
with pulse.build() as pulse_prog:
    pulse.call(subroutine, value_dict={amp1: 0.1, amp2: 0.3})
 
print(pulse_prog)
ScheduleBlock(
    ScheduleBlock(
        Play(Gaussian(duration=160, amp=(0.1+0j), sigma=40), DriveChannel(0)),
        Play(Gaussian(duration=160, amp=(0.3+0j), sigma=40), DriveChannel(1)),
        name="block4",
        transform=AlignLeft()
    ),
    name="block5",
    transform=AlignLeft()
)
  1. Calling a schedule
x_sched = backend.instruction_schedule_map.get("x", (0,))
 
with pulse.build(backend) as pulse_prog:
    pulse.call(x_sched)
 
print(pulse_prog)
ScheduleBlock(
    Call(
        Schedule(
            (
                0,
                Play(
                    Drag(
                        duration=160,
                        amp=(0.18989731546729305+0j),
                        sigma=40,
                        beta=-1.201258305015517,
                        name='drag_86a8'
                    ),
                    DriveChannel(0),
                    name='drag_86a8'
                )
            ),
            name="x"
        ),
        name='x'
    ),
    name="block6",
    transform=AlignLeft()
)

Currently, the backend calibrated gates are provided in the form of Schedule. The parameter assignment mechanism is available also for schedules. However, the called schedule is not treated as a reference.

  1. Calling a quantum circuit
backend = FakeBogotaV2()
 
qc = circuit.QuantumCircuit(1)
qc.x(0)
 
with pulse.build(backend) as pulse_prog:
    pulse.call(qc)
 
print(pulse_prog)
ScheduleBlock(
    Call(
        Schedule(
            (
                0,
                Play(
                    Drag(
                        duration=160,
                        amp=(0.18989731546729305+0j),
                        sigma=40,
                        beta=-1.201258305015517,
                        name='drag_86a8'
                    ),
                    DriveChannel(0),
                    name='drag_86a8'
                )
            ),
            name="circuit-87"
        ),
        name='circuit-87'
    ),
    name="block7",
    transform=AlignLeft()
)
Warning

Calling a circuit from a schedule is not encouraged. Currently, the Qiskit execution model is migrating toward the pulse gate model, where schedules are attached to circuits through the QuantumCircuit.add_calibration() method.

Parameters

  • target (Union[QuantumCircuit, Schedule, ScheduleBlock, None]) – Target circuit or pulse schedule to call.
  • name (Optional[str]) – Optional. A unique name of subroutine if defined. When the name is explicitly provided, one cannot call different schedule blocks with the same name.
  • value_dict (Optional[Dict[Union[ParameterExpression, float], Union[ParameterExpression, float]]]) – Optional. Parameters assigned to the target program. If this dictionary is provided, the target program is copied and then stored in the main built schedule and its parameters are assigned to the given values. This dictionary is keyed on Parameter objects, allowing parameter name collision to be avoided.
  • kw_params (Union[ParameterExpression, float]) – Alternative way to provide parameters. Since this is keyed on the string parameter name, the parameters having the same name are all updated together. If you want to avoid name collision, use value_dict with Parameter objects instead.
Was this page helpful?
Report a bug or request content on GitHub.