Portuguese
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

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

\[|\psi\rangle = \left(|000\rangle+|111\rangle\right)/\sqrt{2}.\]

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]:
../../_images/tutorials_circuits_01_circuit_basics_7_0.svg

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

\[\begin{split}C_X = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\\end{pmatrix}.\end{split}\]

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]:
$$ \begin{bmatrix} \tfrac{1}{\sqrt{2}} & 0 & 0 & 0 & 0 & 0 & 0 & \tfrac{1}{\sqrt{2}} \\ \end{bmatrix} $$
[6]:
from qiskit.visualization import array_to_latex

#Alternative way of representing in latex
array_to_latex(state)
[6]:
$$ \begin{bmatrix} \tfrac{1}{\sqrt{2}} & 0 & 0 & 0 & 0 & 0 & 0 & \tfrac{1}{\sqrt{2}} \\ \end{bmatrix} $$

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]:
../../_images/tutorials_circuits_01_circuit_basics_14_0.svg
[8]:
state.draw('hinton')
[8]:
../../_images/tutorials_circuits_01_circuit_basics_15_0.svg

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

\[|\psi\rangle = (|000\rangle +|111\rangle)/\sqrt{2},\]

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

\[\mathrm{Pr}(xyz) = |\langle xyz | \psi \rangle |^{2}\]

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]:
../../_images/tutorials_circuits_01_circuit_basics_21_0.svg

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]:
../../_images/tutorials_circuits_01_circuit_basics_27_0.svg

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 SoftwareVersion
Qiskit0.26.2
Terra0.17.4
Aer0.8.2
Ignis0.6.0
Aqua0.9.1
IBM Q Provider0.13.1
System information
Python3.8.5 (default, Sep 4 2020, 07:30:14) [GCC 7.3.0]
OSLinux
CPUs2
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.