Portuguese, Brazilian
Idiomas
English
Japanese
German
Korean
Portuguese, Brazilian
French
Shortcuts

Nota

Esta página foi gerada de tutorials/circuits_advanced/05_pulse_gates.ipynb.

Execute interativamente no IBM Quantum lab.

Portas de pulso

Most quantum algorithms can be described with circuit operations alone. When we need more control over the low-level implementation of our program, we can use pulse gates. Pulse gates remove the constraint of executing circuits with basis gates only, and also allow you to override the default implementation of any basis gate.

Portas de pulso permitem mapear uma porta de circuito lógico (por exemplo, X) para um programa Qiskit Pulse chamado de Schedule. Este mapeamento é referido como uma calibração. Uma calibração de alta fidelidade é uma que implementa fielmente a operação lógica da qual é mapeada (por exemplo, se a calibração do X direciona \(|0\rangle\) to \(|1\rangle\), etc.).

Uma programação especifica a dinâmica de tempo exata dos sinais de entrada em todas as entradas canais para o dispositivo. Geralmente, há vários canais por qubit, como direção e medida. Essa interface é mais poderosa e requer uma compreensão mais profunda da física do dispositivo subjacente.

É importante notar que programas Pulse operam em qubits físicos. Um pulso de condução no qubit \(a\) não executará a mesma operação lógica no estado do qubit \(b\) - em outras palavras, calibrações de porta não podem ser trocadas entre os qubits. Isto contrasta com o nível de circuito, onde uma porta X é definida independentemente do operando do qubit.

Esta página mostra como adicionar uma calibração ao seu circuito.

Nota: Para executar um programa com portas de pulso, o backend deve ser habilitado com o OpenPulse. Você pode verificar, via backend.configuration().open_pulse, que é True, quando o OpenPulse está habilitado. Se estiver habilitado e as portas de pulso não estiverem ativados, você pode, no seu circuito de entrada agendar.

Construindo o circuito

Vamos começar com um exemplo muito simples, um circuito do estado Bell.

[1]:
from qiskit import QuantumCircuit

circ = QuantumCircuit(2, 2)
circ.h(0)
circ.cx(0, 1)
circ.measure(0, 0)
circ.measure(1, 1)

circ.draw('mpl')
[1]:
../../_images/tutorials_circuits_advanced_05_pulse_gates_2_0.png

Fazendo as suas calibrações

Agora que temos o nosso circuito, vamos definir uma calibração para a porta Hadamard no qubit 0.

Na prática a forma do pulso e seus parâmetros serão otimizados através de uma série de experimentos Rabi (veja o Qiskit Textbook para uma explicação). Para esta demonstração, nosso Hadamard será um pulso gaussiano. Vamos jogar nosso pulso no canal direção do qubit 0.

Não se preocupe muito com os detalhes de construção da própria calibração; você pode aprender tudo sobre isso na seguinte página: construindo agendamentos pulse.

[2]:
from qiskit import pulse
from qiskit.pulse.library import Gaussian
from qiskit.test.mock import FakeValencia

backend = FakeValencia()

with pulse.build(backend, name='hadamard') as h_q0:
    pulse.play(Gaussian(duration=128, amp=0.1, sigma=16), pulse.drive_channel(0))

Vamos fazer um novo agendamento para ver o que construímos.

[3]:
h_q0.draw()
[3]:
../../_images/tutorials_circuits_advanced_05_pulse_gates_6_0.png

Vincule sua calibração ao seu circuito

Resta, apenas, completar o registro. O método de circuito add_calibration precisa de informações sobre a porta e a referência ao cronograma para completar o mapeamento:

QuantumCircuit.add_calibration(gate, qubits, schedule, parameters)

A porta pode ser um objeto circuit.Gate ou o nome da porta. Geralmente, você precisará de um cronograma diferente para cada conjunto único de qubits e parâmetros. Uma vez que a porta Hadamard não tem nenhum parâmetro, não temos que fornecer nenhum.

[4]:
circ.add_calibration('h', [0], h_q0)

Por último, note que o transpilador respeitará suas calibrações. Use-o como você normalmente usaria (nosso exemplo é muito simples para que o transpilador o otimize, então a saída é a mesma).

[5]:
from qiskit import transpile
from qiskit.test.mock import FakeAlmaden

backend = FakeAlmaden()

circ = transpile(circ, backend)

print(backend.configuration().basis_gates)
circ.draw('mpl', idle_wires=False)
['id', 'u1', 'u2', 'u3', 'cx']
[5]:
../../_images/tutorials_circuits_advanced_05_pulse_gates_10_1.png

Observe que h não é uma porta base para o falso backend FakeAlmaden. Uma vez que adicionamos uma calibração para ele, o transpiler tratará a nossa porta como uma porta base; mas apenas nas qubits para as quais foi definida. Uma Hadamard aplicada a um qubit diferente, seria destinado às portas base.

É isso!

Portas personalizadas

Mostraremos, brevemente, o mesmo processo para portas totalmente customizadas que não são padrões. Esta demonstração inclui uma porta com parâmetros.

[6]:
from qiskit import QuantumCircuit
from qiskit.circuit import Gate

circ = QuantumCircuit(1, 1)
custom_gate = Gate('my_custom_gate', 1, [3.14, 1])
# 3.14 is an arbitrary parameter for demonstration
circ.append(custom_gate, [0])
circ.measure(0, 0)

circ.draw('mpl')
[6]:
../../_images/tutorials_circuits_advanced_05_pulse_gates_12_0.png
[7]:
with pulse.build(backend, name='custom') as my_schedule:
    pulse.play(Gaussian(duration=64, amp=0.2, sigma=8), pulse.drive_channel(0))

circ.add_calibration('my_custom_gate', [0], my_schedule, [3.14, 1])
# Alternatively: circ.add_calibration(custom_gate, [0], my_schedule)

Se usarmos a variável de instância Gate custom_gate para adicionar a calibração, os parâmetros são derivados dessa instância. Lembre-se de que a ordem dos parâmetros é significativa.

[8]:
circ = transpile(circ, backend)
circ.draw('mpl', idle_wires=False)
[8]:
../../_images/tutorials_circuits_advanced_05_pulse_gates_15_0.png

Normalmente, se tentássemos transpilar nosso circ, teríamos um erro. Não haveria nenhuma definição funcional fornecida para "my_custom_gate", então o transpiler não poderia associar para o conjunto porta base do dispositivo de destino. Podemos mostrar isto tentando adicionar "my_custom_gate" a outro qubit que não foi calibrado.

[9]:
circ = QuantumCircuit(2, 2)
circ.append(custom_gate, [1])


from qiskit import QiskitError
try:
    circ = transpile(circ, backend)
except QiskitError as e:
    print(e)
"Cannot unroll the circuit to the given basis, ['id', 'u1', 'u2', 'u3', 'cx']. Instruction my_custom_gate not found in equivalence library and no rule found to expand."
[10]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
/Users/thomas/opt/anaconda3/envs/qiskit-3.8/lib/python3.8/site-packages/qiskit/aqua/operators/operator_globals.py:48: DeprecationWarning: `from_label` is deprecated and will be removed no earlier than 3 months after the release date. Use Pauli(label) instead.
  X = make_immutable(PrimitiveOp(Pauli.from_label('X')))

Version Information

Qiskit SoftwareVersion
Qiskit0.23.6
Terra0.17.0
Aer0.7.5
Ignis0.5.2
Aqua0.8.2
IBM Q Provider0.11.1
System information
Python3.8.5 (default, Aug 5 2020, 03:39:04) [Clang 10.0.0 ]
OSDarwin
CPUs8
Memory (Gb)32.0
Sat Feb 27 11:07:23 2021 AST

This code is a part of Qiskit

© Copyright IBM 2017, 2021.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.