Nota
Esta página foi gerada a partir de tutorials/finance/11_time_series.ipynb.
Básico sobre Circuito¶
Aqui, fornecemos uma visão geral sobre como trabalhar com o Qiskit. O Qiskit fornece os blocos de construção básicos necessários para programar computadores quânticos. A sua unidade fundamental é o quantum circuit. Um fluxo de trabalho básico usando Qiskit consiste de dois estágios: Construir e Executar. Construir permite que você crie diferentes circuitos quânticos que representam o problema que você está resolvendo, e Executar permite que você os execute em diferentes backends. Após a execução dos trabalhos, os dados são coletados e processados dependendo do resultado desejado.
[1]:
import numpy as np
from qiskit import QuantumCircuit
Construindo o circuito¶
O elemento básico necessário para seu primeiro programa é o QuantumCircuit. Começamos por criar um QuantumCircuit
composto de três qubits.
[2]:
# Create a Quantum Circuit acting on a quantum register of three qubits
circ = QuantumCircuit(3)
Após criar o circuito com seus registradores, você pode adicionar portas (“operações”) para manipular os registradores. Conforme você avançar pelos tutoriais, descobrirá mais portas e circuitos; abaixo há um exemplo de circuito quântico que cria um estado GHZ de três qubits
Para criar tal estado, começamos com um registrador quântico de três qubits. Por padrão, cada qubit no registrador é inicializado para \(|0\rangle\). Para fazer o estado GHZ, aplicamos as seguintes portas: - Uma porta Hadamard \(H\) no qubit 0, que o coloca no estado de superposição \(\left(|0\rangle+|1\rangle\right )/\sqrt{2}\). - Uma operação Controlled-NOT (\(C_{X}\)) entre o qubit 0 e o qubit 1. - Uma operação Controlled-NOT entre o qubit 0 e o qubit 2.
Em um computador quântico ideal, o estado produzido pela execução deste circuito seria o estado GHZ acima.
No Qiskit, as operações podem ser adicionadas ao circuito uma a uma, como mostrado abaixo.
[3]:
# Add a H gate on qubit 0, putting this qubit in superposition.
circ.h(0)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting
# the qubits in a Bell state.
circ.cx(0, 1)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 2, putting
# the qubits in a GHZ state.
circ.cx(0, 2)
[3]:
<qiskit.circuit.instructionset.InstructionSet at 0x7f7c92288310>
Visualizar Circuito¶
Você pode visualizar seu circuito usando Qiskit QuantumCircuit.draw()
, que desenha o circuito na forma encontrada em muitos livros didáticos.
[4]:
circ.draw('mpl')
[4]:
Neste circuito, os qubits são colocados em ordem, com o qubit zero na parte superior e o qubit dois na parte inferior. O circuito é lido da esquerda para a direita (as portas aplicadas antes no circuito aparecem mais para a esquerda).
Ao representar o estado de um sistema multi-qubit, a ordem tensorial utilizada no Qiskit é diferente daquela empregada na maioria dos livros de física. Suponha que existam \(n\) qubits, e o qubit \(j\) é rotulado como \(Q_{j}\). O Qiskit usa uma ordem na qual o qubit \(n^{\mathrm{th}}\) está do lado esquerdo do produto tensorial, de forma que os vetores de base são rotulados como \(Q_{n-1}\otimes \cdots \otimes Q_1\otimes Q_0\).
Por exemplo, se o qubit zero estiver no estado 0, o qubit 1 no estado 0 e o qubit 2 no estado 1, o Qiskit representaria este estado como \(|100\rangle\), enquanto que muitos livros sobre física o representariam como \(|001\rangle\).
Essa diferença de rotulagem afeta a forma como as operações multi-qubit são representadas como matrizes. Por exemplo, o Qiskit representa uma operação X-controlada (\(C_{X}\)) com o qubit 0 sendo o controle e o qubit 1 sendo o alvo como
Simulando circuitos¶
Para simular um circuito, nós usamos o módulo Qiskit quant_info. Ese simulador retorna o estado quântico, que é um vetor complexo de dimensão \(2^n\), na qual \(n\) é o número de qubits (então tenha cuidado ao usá-lo, já que ele rapidamente se tornará grande demais para a execução na sua máquina).
O simulador possui duas etapas, sendo a primeira definir o estado de entrada e a segunda evoluir esse estado com base no circuito quântico.
[5]:
from qiskit.quantum_info import Statevector
# Set the intial state of the simulator to the ground state using from_int
state = Statevector.from_int(0, 2**3)
# Evolve the state by the quantum circuit
state = state.evolve(circ)
#draw using latex
state.draw('latex')
[5]:
[6]:
from qiskit.visualization import array_to_latex
#Alternative way of representing in latex
array_to_latex(state)
[6]:
O Qiskit também fornece uma caixa de ferramentas de visualização a fim de permitir que você observe esses resultados.
Abaixo, utilizaremos a função de visualização para desenhar os componentes reais e imaginários da matriz de densidade de estados \(\rho\).
[7]:
state.draw('qsphere')
[7]:
[8]:
state.draw('hinton')
[8]:
Representação unitária de um circuito¶
O módulo quant_info do Qiskit também tem um método de operador que pode ser usado para criar um operador unitário para o circuito. Ele calcula a matriz \(2^n \times 2^n\) que representa o circuito quântico.
[9]:
from qiskit.quantum_info import Operator
U = Operator(circ)
# Show the results
U.data
[9]:
array([[ 0.70710678+0.j, 0.70710678+0.j, 0. +0.j,
0. +0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0. +0.j, 0. +0.j,
0.70710678+0.j, -0.70710678+0.j],
[ 0. +0.j, 0. +0.j, 0.70710678+0.j,
0.70710678+0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0.70710678+0.j, -0.70710678+0.j,
0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0.70710678+0.j, 0.70710678+0.j,
0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0.70710678+0.j,
-0.70710678+0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0. +0.j],
[ 0. +0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0. +0.j, 0. +0.j,
0.70710678+0.j, 0.70710678+0.j],
[ 0.70710678+0.j, -0.70710678+0.j, 0. +0.j,
0. +0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0. +0.j]])
Backend OpenQASM¶
Os simuladores acima são úteis porque fornecem informação sobre o estado final do circuito ideal e a representação em forma de matriz do circuito. No entanto, um experimento real termina medindo cada qubit (geralmente na base computacional \(|0\rangle, |1\rangle\) ). Sem medições, não podemos obter informações sobre o estado. Medições fazem o sistema quântico colapsar para bits clássicos.
Por exemplo, suponha que façamos medições independentes em cada qubit do estado GHZ de três qubits
e deixe \(xyz\) denotar o bitstring que resultou. Lembre que, sob o rótulo de qubit usado pelo Qiskit, \(x\) corresponderia ao resultado no qubit 2, \(y\) para o resultado no qubit 1 e \(z\) para o resultado no qubit 0.
Obs.: Esta representação do bitstring coloca o bit mais significativo (MSB) à esquerda, e o bit menos significativo (LSB) à direita. Esta é a ordenação padrão de bitstrings binárias. Ordenamos os qubits da mesma forma (qubit representando o MSB tem índice 0), razão pela qual o Qiskit usa uma ordem de produto de tensor não padrão.
Lembre-se que a probabilidade de obter resultado \(xyz\) é dada por
e como tal, a probabilidade de estado GHZ de obter 000 ou 111 são ambos de 1/2.
Para simular um circuito que inclui medição, precisamos adicionar medições ao circuito original acima e usar um backend Aer diferente.
[10]:
# Create a Quantum Circuit
meas = QuantumCircuit(3, 3)
meas.barrier(range(3))
# map the quantum measurement to the classical bits
meas.measure(range(3), range(3))
# The Qiskit circuit object supports composition.
# Here the meas has to be first and front=True (putting it before)
# as compose must put a smaller circuit into a larger one.
qc = meas.compose(circ, range(3), front=True)
#drawing the circuit
qc.draw('mpl')
[10]:
Este circuito adiciona um registro clássico e três medições que são usadas para mapear o resultado dos qubits nos bits clássicos.
Para simular este circuito, usamos o qasm_simulator
do Qiskit Aer. Cada execução desse circuito resultará na bitstring 000 ou 111. Para construir estatísticas sobre a distribuição das bitstrings (para, por exemplo, estimar \(\mathrm{Pr}(000)\)), precisamos repetir o circuito várias vezes. O número de repetições pode ser especificado na função execute
através da palavra-chave shots
.
[11]:
# Adding the transpiler to reduce the circuit to QASM instructions
# supported by the backend
from qiskit import transpile
# Use AerSimulator
from qiskit_aer import AerSimulator
backend = AerSimulator()
# First we have to transpile the quantum circuit
# to the low-level QASM instructions used by the
# backend
qc_compiled = transpile(qc, backend)
# Execute the circuit on the qasm simulator.
# We've set the number of repeats of the circuit
# to be 1024, which is the default.
job_sim = backend.run(qc_compiled, shots=1024)
# Grab the results from the job.
result_sim = job_sim.result()
Uma vez que você possua um objeto de resultado, você pode acessar as contagens através da função get_counts(circuit)
. Isso lhe fornece os resultados binários agregados do circuito que você submeteu.
[12]:
counts = result_sim.get_counts(qc_compiled)
print(counts)
{'111': 522, '000': 502}
Aproximadamente 50% do tempo, a bitstring de saída é 000. O Qiskit também fornece uma função plot_histogram
, que permite você ver os resultados.
[13]:
from qiskit.visualization import plot_histogram
plot_histogram(counts)
[13]:
As probabilidades estimadas do resultado \(\mathrm{Pr}(000)\) e \(\mathrm{Pr}(111)\) são computadas dividindo as contagens agregadas pelo número de shots (vezes que o circuito foi repetido). Tente alterar a palavra-chave shots
na função execute
e veja como as probabilidades estimadas mudam.
[14]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
Qiskit | 0.26.2 |
Terra | 0.17.4 |
Aer | 0.8.2 |
Ignis | 0.6.0 |
Aqua | 0.9.1 |
IBM Q Provider | 0.13.1 |
System information | |
Python | 3.8.5 (default, Sep 4 2020, 07:30:14) [GCC 7.3.0] |
OS | Linux |
CPUs | 2 |
Memory (Gb) | 7.523967742919922 |
Fri Jun 04 17:48:05 2021 IST |
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.