Construir circuitos
O código desta página foi desenvolvido usando os seguintes requisitos. Recomendamos o uso dessas versões ou de versões mais recentes.
qiskit[all]~=2.3.1
Esta página dá uma olhada mais de perto na classe QuantumCircuit no Qiskit SDK, incluindo alguns métodos mais avançados que você pode usar para criar circuitos quânticos.
O que é um circuito quântico?
Um circuito quântico simples é uma coleção de qubits e uma lista de instruções que atuam sobre esses qubits. Para demonstrar, a célula a seguir cria um novo circuito com dois novos qubits e, em seguida, exibe o atributo qubits do circuito, que é uma lista de Qubits em ordem do bit menos significativo para o bit mais significativo .
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
qc.qubitsOutput:
[<Qubit register=(2, "q"), index=0>, <Qubit register=(2, "q"), index=1>]
Vários objetos QuantumRegister e ClassicalRegister podem ser combinados para criar um circuito. Todos os QuantumRegister e ClassicalRegister também podem ser nomeados.
from qiskit.circuit import QuantumRegister, ClassicalRegister
qr1 = QuantumRegister(2, "qreg1") # Create a QuantumRegister with 2 qubits
qr2 = QuantumRegister(1, "qreg2") # Create a QuantumRegister with 1 qubit
cr1 = ClassicalRegister(3, "creg1") # Create a ClassicalRegister with 3 cbits
combined_circ = QuantumCircuit(
qr1, qr2, cr1
) # Create a quantum circuit with 2 QuantumRegisters and 1 ClassicalRegister
combined_circ.qubitsOutput:
[<Qubit register=(2, "qreg1"), index=0>,
<Qubit register=(2, "qreg1"), index=1>,
<Qubit register=(1, "qreg2"), index=0>]
É possível encontrar o índice e o registro de um qubit usando o método find_bit do circuito e seus atributos.
desired_qubit = qr2[0] # Qubit 0 of register 'qreg2'
print("Index:", combined_circ.find_bit(desired_qubit).index)
print("Register:", combined_circ.find_bit(desired_qubit).registers)Output:
Index: 2
Register: [(QuantumRegister(1, 'qreg2'), 0)]
A adição de uma instrução ao circuito anexa a instrução ao atributo data do circuito. A saída da célula a seguir mostra que data é uma lista de CircuitInstruction objetos, cada um dos quais tem um atributo operation e um atributo qubits .
qc.x(0) # Add X-gate to qubit 0
qc.dataOutput:
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]
A maneira mais fácil de visualizar essas informações é por meio do método draw que retorna uma visualização de um circuito. Consulte Visualizar circuitos para conhecer diferentes maneiras de exibir circuitos quânticos.
qc.draw("mpl")Output:
Os objetos de instrução de circuito podem conter circuitos de "definição" que descrevem a instrução em termos de instruções mais fundamentais. Por exemplo, o X-gate é definido como um caso específico do U3-gate um portão de um único qubit mais geral.
# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")Output:
As instruções e os circuitos são semelhantes, pois ambos descrevem operações em bits e qubits, mas têm finalidades diferentes:
- As instruções são tratadas como fixas, e seus métodos geralmente retornam novas instruções (sem alterar o objeto original).
- Os circuitos são projetados para serem construídos com muitas linhas de código, e
QuantumCircuite os métodos geralmente alteram o objeto existente.
O que é profundidade de circuito?
A profundidade() de um circuito quântico é uma medida do número de "camadas" de portas quânticas, executadas em paralelo, necessárias para concluir o cálculo definido pelo circuito. Como as portas quânticas levam tempo para serem implementadas, a profundidade de um circuito corresponde aproximadamente à quantidade de tempo que o computador quântico leva para executar o circuito. Assim, a profundidade de um circuito é uma quantidade importante usada para medir se um circuito quântico pode ser executado em um dispositivo.
O restante desta página ilustra como manipular circuitos quânticos.
Construa circuitos
Métodos como QuantumCircuit.h e QuantumCircuit.cx adicionam instruções específicas aos circuitos. Para adicionar instruções a um circuito de forma mais geral, use o método append método. Isso recebe uma instrução e uma lista de qubits aos quais aplicar a instrução. Consulte a documentação da API da biblioteca de circuitos para obter uma lista das instruções compatíveis.
from qiskit.circuit.library import HGate
qc = QuantumCircuit(1)
qc.append(
HGate(), # New HGate instruction
[0], # Apply to qubit 0
)
qc.draw("mpl")Output:
Para combinar dois circuitos, use o método compose método. Isso aceita outro QuantumCircuit e uma lista opcional de mapeamentos de qubit.
qc_a = QuantumCircuit(4)
qc_a.x(0)
qc_b = QuantumCircuit(2, name="qc_b")
qc_b.y(0)
qc_b.z(1)
# compose qubits (0, 1) of qc_a to qubits (1, 3) of qc_b respectively
combined = qc_a.compose(qc_b, qubits=[1, 3])
combined.draw("mpl")Output:
Talvez você também queira compilar circuitos em instruções para manter seus circuitos organizados. Você pode converter um circuito em uma instrução usando o método to_instruction e, em seguida, anexá-lo a outro circuito como faria com qualquer outra instrução. O circuito desenhado na célula seguinte é funcionalmente equivalente ao circuito desenhado na célula anterior.
inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")Output:
Se seu circuito for unitário, você poderá convertê-lo em um circuito Gate usando o método to_gate método. Gate os objetos são tipos específicos de instruções que têm alguns recursos extras, como o control que adiciona um controle quântico.
gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")Output:
Para ver o que está acontecendo, você pode usar o método decompose para expandir cada instrução em sua definição.
O método decompose retorna um novo circuito e não altera o circuito no qual ele atua.
qc_a.decompose().draw("mpl")Output:
Medir qubits
As medições são utilizadas para amostrar os estados de qubits individuais e transferir os resultados para um registro clássico. Observe que, se você estiver enviando circuitos para uma primitiva Sampler, é necessário fornecer as medidas. No entanto, se os circuitos enviados a uma primitiva do Estimador contiverem medidas, essas medidas serão ignoradas.
Os Qubits podem ser medidos usando três métodos: measure, measure_all e measure_active. Para saber como visualizar os resultados medidos, consulte a página Visualizar resultados.
-
QuantumCircuit.measuremede cada qubit no primeiro argumento sobre o bit clássico fornecido como segundo argumento. Esse método permite controle total sobre onde o resultado da medição é armazenado. -
QuantumCircuit.measure_allo termo "quantum" não recebe nenhum argumento e pode ser usado para circuitos quânticos sem bits clássicos predefinidos. Ele cria fios clássicos e armazena os resultados das medições em ordem. Por exemplo, a medição do qubit é armazenada no cbit ). Ele também adiciona uma barreira antes da medição. -
QuantumCircuit.measure_active: semelhante aomeasure_all, mas mede apenas os qubits que têm operações.
qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)Output:
qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)Output:
qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)Output:
Circuitos parametrizados
Muitos algoritmos quânticos de curto prazo envolvem a execução de muitas variações de um circuito quântico. Como a construção e a otimização de circuitos grandes podem ser computacionalmente caras, o Qiskit oferece suporte a circuitos parametrizados. Esses circuitos têm parâmetros indefinidos, e seus valores não precisam ser definidos até pouco antes da execução do circuito. Isso permite que você mova a construção e a otimização do circuito para fora do loop do programa principal. A célula a seguir cria e exibe um circuito parametrizado.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit import Parameter
angle = Parameter("angle") # undefined number
# Create and optimize circuit once
qc = QuantumCircuit(1)
qc.rx(angle, 0)
qc = generate_preset_pass_manager(
optimization_level=3, basis_gates=["u", "cx"]
).run(qc)
qc.draw("mpl")Output:
A célula a seguir cria muitas variações desse circuito e exibe uma das variações.
circuits = []
for value in range(100):
circuits.append(qc.assign_parameters({angle: value}))
circuits[0].draw("mpl")Output:
Você pode encontrar uma lista dos parâmetros indefinidos de um circuito em seu atributo parameters .
qc.parametersOutput:
ParameterView([Parameter(angle)])
Alterar o nome de um parâmetro
Por padrão, os nomes dos parâmetros de um circuito parametrizado são prefixados por x- por exemplo, x[0]. Você pode alterar os nomes após defini-los, conforme mostrado no exemplo a seguir.
from qiskit.circuit.library import z_feature_map
from qiskit.circuit import ParameterVector
# Define a parameterized circuit with default names
# For example, x[0]
circuit = z_feature_map(2)
# Set new parameter names
# They will now be prefixed by `hi` instead
# For example, hi[0]
training_params = ParameterVector("hi", 2)
# Assign parameter names to the quantum circuit
circuit = circuit.assign_parameters(parameters=training_params)Forgotten the method name? Try asking Qiskit Code Assistant.
# Assign all parameters in qc to 0É novo no assistente de código? Consulte Qiskit Code Assistant para obter informações sobre instalação e uso. Observe que esse é um recurso experimental e está disponível apenas para usuários do IBM Quantum Premium Plan.
Próximas etapas
- Para saber mais sobre algoritmos quânticos de curto prazo, faça o curso Variational algorithm design.
- Veja um exemplo de circuitos sendo usados no tutorial do Algoritmo de Grover.
- Trabalhe com circuitos simples usando o IBM Quantum Composer.