QISKIT 

Qiskit IBMk ordenagailu kuantikoekin lan egiteko garatutako kode irekiko tresna multzo bat da. Garatzaileei eta datu-zientzialariei ,gailu errealetan edo simulagailu kuantikoetan, algoritmo kuantikoak esperimentatzea, garatzea eta exekutatzea ahalbidetzen dien esparru integral bat eskaintzen du. Sartu eta hasi "Start", "Build"... IBMren hardware kuantiko errealeko programak exekutatzen amaitu arte.

Hauek dira Qiskiten ezaugarri eta osagai nagusiak:

  1. Terra: Zirkuitu kuantikoak eraikitzeko eta manipulatzeko tresnak eskaintzen ditu, baita simulazioak egiteko ere. Terrak hardware kuantikoan exekutatzeko zirkuituen transpilazioa ere errazten du.

  2. Aer: Errendimendu handiko simulagailu kuantikoen multzo bat da, Qiskiten sartua. Zirkuitu kuantikoen portaera simulatzeko aukera ematen du, hainbat baldintzatan.

  3. Ignis: Konputagailu kuantikoetako erroreak ezaugarritzea eta arintzea du helburu. Inplementazio kuantikoen kalitatea ebaluatzeko eta hobetzeko tresnak eskaintzen ditu.

  4. Aqua: Goi-mailako liburutegi eta algoritmo kuantikoen multzoa da, hainbat aplikazio kuantikotarako diseinatuak, adibidez optimizaziorako, ikaskuntza automatikorako, kimika kuantikorako eta finantza kuantikoetarako.

  5. Algoritmos cuánticos: Qiskitek funtsezko algoritmo kuantikoen inplementazioak barne hartzen ditu, hala nola Shorren faktorizazio-algoritmoa, Groverren bilaketa kuantikoko algoritmoa, eta beste batzuk.

Qiskit baliabide baliotsua da konputazio kuantikoaren komunitatearentzat; izan ere, erabiltzaile hasiberriei zein esperientziadunei informatika kuantikoaren mundua esploratzeko eta aplikazio eta algoritmo kuantikoen garapenean laguntzeko aukera ematen die.

 

Oraingoz, simulagailu bat instalatu beharko dugu lokalean, ziurrenik Jupyter lagun duela.

Hemen daude jarraibideak: https://docs.quantum.ibm.com/start/install

 

Hortxe bertan duzu konputazio kuantikoarekin esperimentatzeko baliabideak eta tresnak eskuratzeko aukera. Sartu eta hasi "Start", "Build"... IBMren hardware kuantiko errealean programak exekutatzen amaitu arte.

ZIRKUITU KUANTIKOAK SIMULAGAILU BATEAN ERAIKITZEA ETA EXEKUTATZEA

ORDENAGAILU KUANTIKO ERREALETAN EXEKUTATU

 
Ordenagailu kuantiko erreal batean zirkuitu bat exekutatzeko hainbat lan egin behar dira:
  1. Ibm Quantum Plataformean alta ematea 

ehenik eta behin, Ibm Quantum @-@en alta eman beharko duzu, doakoa da.

Ibm Quantum plataforman hiru erlaitz ikusiko dituzu:

    • Dashboard, informazio orokorra erakusten dituena, baita  Jobs berrienak, erabilitako QPUak, QPU guztiak, "Documentation", "Learning".
    • Compute resources, eskuragarri dauden QPU guztiak erakusten dituena.
    • Jobs, gure Jobs guztiak erakusten
  •  
  1. Manage accountera joan beharko duzu zure API tokena lortzeko.

Esteka: https://quantum.ibm.com/

  1. Beharrezkoa izango da Qiskit instalatuta izatea zure lan-ingurunean

HEmen daude jarraibideak: https://docs.quantum.ibm.com/start/install

  1. Hrrengo urratsak eman beharko dira:
    • Gorde Ibm Quantum-en kredentzialak (lehengo aldian bakarrik).
    • Kredentzialak berreskuratu eta dena ondo dagoela egiaztatu.
    • Ikusi eskuragarri dauden backend-ak (ordenagailu kuantikoak), hautatu gutxien okupatzen duena eta sortu saio bat backend horretan
    • Gure zirkuitua eraiki.
    • "Transpilar" gure zirkuitua.
    • Exekutatu
    • Emaitzak aztertu.
  •  

 

TRANSPILER prozesuari buruzko oharrak:

Zirkuitu kuantiko bat "transpilatzea", goi mailako zirkuitu kuantiko bat ordenagailu kuantiko zehatz batekin bateragarria den bertsio baliokide bihurtzeko prozesua da. Prozesu hori erabakigarria da, ordenagailu kuantiko bakoitzaren muga fisikoak eta zehaztapen bakarrak direla eta. Prozesu horrek hainbat ataza egiten ditu:

  • Ateen bateragarritasuna bermatzea: ordenagailu kuantikoak ateren bat jasaten ez badu, ateetan deskonposatu behar da.
  • Ate mota jakin batzuk qubit mota jakin batzuekin konektatzeko orduan murrizketak daude; transpilazio prozesuak zirkuitua berrantolatzen du eta/edo trukaketa eragiketak txertatzen ditu murrizketa horiek konpontzeko.
  • Optimizazioa. Ate kopurua murrizten saiatzea da, ondoko ateak fusionatuz eta beharrezkoak ez diren ateak kenduz.
  • Zirkuitua exekutatuko den hardware zehatzaren kalibrazio espezifikoak.

Atal honen bigarren exekuzioan bi sakontasun maila dituen zirkuitu bat transpilatzeko adibide bat ikusiko dugu, emaitzak alderatzeko.

from qiskit_ibm_runtime import QiskitRuntimeService, Session, SamplerV2, EstimatorV2


# Save an IBM Quantum account.
QiskitRuntimeService.save_account(channel="ibm_quantum",
token="142aca5fb28d52d699c972fde878f1c3kjdue845lo3b7d2f99d52d01369195e4f5979af8dd832608ff633f475abf0eac9264d2ed3fc6e6492f7a497596e7eda3",

name="nombre_para_guardar",
set_as_default=True,
overwrite=True)
service = QiskitRuntimeService



# Cargar las credenciales guardadas
try:
service = QiskitRuntimeService(name="nombre_para_guardar")
print("Credenciales de la cuenta cargadas correctamente")
except Exception as e:
print(f"Error al cargar las credenciales: {e}")


# Optional: List all the instances you can access.
service = QiskitRuntimeService(channel='ibm_quantum')
print(f"Instancias accesibles: {service.instances()}")


# Verificar que la autenticación fue exitosa mostrando los backends disponibles
try:
backends = service.backends()
print("Backends disponibles:")
for backend in backends:
config = backend.configuration()
status = backend.status()
print(f"Backend: {backend.name}, Simulator: {config.simulator}, Operational: {status.operational}, Pending Jobs: {status.pending_jobs}")


# Filtrar los backends que no sean simuladores y que estén operativos
filtered_backends = [b for b in backends if b.status().operational]
# Verificar si hay backends disponibles después del filtrado
if not filtered_backends:
raise ValueError("No hay backends disponibles que no sean simuladores y que estén operativos.")

# Seleccionar el backend menos ocupado
backend = min(filtered_backends, key=lambda b: b.status().pending_jobs)
print(f"Seleccionado backend: {backend.name}")

# Crear una sesión
with Session(service=service, backend=backend) as session:
# Crear el Estimator y Sampler
estimator = EstimatorV2(session=session)
sampler = SamplerV2(backend=backend)
print("Sesión creada y Estimator y Sampler inicializados.")
except Exception as e:
print(f"Error durante la configuración de backends o creación de sesión: {e}")

 

 

# ESTA EJECUCIÓN NOS DA EL SIGUIENTE RESULTADO:

Credenciales de la cuenta cargadas correctamente
Instancias accesibles: ['ibm-q/open/main']
Backends disponibles:
Backend: ibm_brisbane, Simulator: False, Operational: True, Pending Jobs: 67
Backend: ibm_kyoto, Simulator: False, Operational: True, Pending Jobs: 7
Backend: ibm_osaka, Simulator: False, Operational: True, Pending Jobs: 53
Backend: ibm_sherbrooke, Simulator: False, Operational: True, Pending Jobs: 15
Seleccionado backend: ibm_kyoto
Sesión creada y Estimator y Sampler inicializados.


Gure Ibm Quantumi buruzko informazioa behar bezala gorde eta berreskuratu dugula adierazi digu,
eta hainbat makina ditugula eskuragarri: Brisbane, Kyoto, Osaka eta Sherbrooke.
Aukeratzen du askeen dagoena, kasu honetan ibm_kyoto.
>>>>>>>>>>>>>>>>

# Preparamos un circuito con una puerta Hadamard y una Cnot (Bell, qubits entrelazados)

from qiskit import QuantumCircuit
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_histogram
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

bell = QuantumCircuit(2)
bell.h(0)
bell.cx(0, 1)
# bell.measure_all()


bell.draw(output="mpl", style="iqp")

# EMAITZA ESKUMAKO ZIRKUITOA DA

:

# Obtenemos la distribución de resultados ideal
ideal_distribution = Statevector.from_instruction(bell).probabilities_dict()
plot_histogram(ideal_distribution)

 

# EMAITZA ESKUMAKO DIAGRAMA DA

### Ejecutamos en el BAckend elegido: ibm_kyoto

bell.measure_all()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1) #esto es para compilar para la máquina backend

isa_bell = pm.run(bell) # Compilamos
job = sampler.run([isa_bell]) # lanzamos el job

# Información sobre el job
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")

# Información sobre los resultaados
result = job.result()

# Mostrar los resultados
for idx, pub_result in enumerate(result):
print(f" > Counts for pub {idx}: {pub_result.data.meas.get_counts()}") # esto es en caso de measure_all
# print(f" > Counts for pub {idx}: {pub_result.data.c.get_counts()}") # esto es en caso de NO measure_all

# EXEKUZIO HONEK HURRENGO EMAITZA EMAN DIGU:

>>> Job ID: ct7zkx77rgf00085k3qg
>>> Job Status: QUEUED
 > Counts for pub 0: {'00': 2136, '01': 328, '11': 1369, '10': 263}



Esaten digu ID horrekin Bidali duela Job bat. Amaitu ondoren emaitza hauek eman digu:
Emaitza '00' izan da 2136 alditan, '01' 328 alditan, '11' 1369tan eta '10' 263tan

# Ahora mostraremos los resultados de forma gráfica

# Obtener las counts del resultado
# counts = pub_result.data.c.get_counts()
counts = pub_result.data.meas.get_counts() # esto es en caso de measure_all

# Convertir las claves numéricas a binario y almacenar en binary_prob
binary_prob = {k: v / sum(counts.values()) for k, v in counts.items()}

# Simular la distribución ideal
ideal_distribution = {'11': 0.5, '00': 0.5, '01': 0, '10': 0}

# Mostrar los resultados
plot_histogram([binary_prob, ideal_distribution], bar_labels=False, title="Resultados de Medida", legend=["Ejecución Real", "Ideal"])

 

# EMAITZA HEMEN BEHEKO DIAGRAMA DA:

 

Jarraian, Ibm Quantum Plataformean exekuzioaren egoeraren hiru irudi ikusiko ditugu: lehena, Joba itxoiten; bigarrena, exekuzioaren ondoren; eta hirugarrena, eskaintzen digun informazioa.

# No necesitaremos conectarnos a nuestra cuenta de Ibm Quantum porque ya lo hemos hecho en el ejercicio anterior

# Create circuit to test transpiler on
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import GroverOperator, Diagonal

# Use Statevector object to calculate the ideal output
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_histogram

# Qiskit Runtime
from qiskit_ibm_runtime import QiskitRuntimeService, Batch

# Seleccionaremos la computadora con menos trabajos encolados y mostramos su nombre
service = QiskitRuntimeService(channel="ibm_quantum")
backend = service.least_busy(operational=True, simulator=False)
backend.name

# EMAITZA:

'ibm_kyoto'

# Construimos un circuito para ver como funciona el operador de GROVER que es
# un algoritmo cuántico para la búsqueda en una base de datos no estructurada
# La primera instrucción rea una matriz diagonal con 7 "1" y un "-1" en el elemento a buscar

oracle = Diagonal([1] * 7 + [-1])
qc = QuantumCircuit(3,3)
qc.h([0, 1, 2])
qc = qc.compose(GroverOperator(oracle))

 

qc.draw(output="mpl", style="iqp")

 

# EMAITZA ESKUMAKO ZIRKUITUA DA:

# Obtenemos la distribución de resultados ideal
ideal_distribution = Statevector.from_instruction(qc).probabilities_dict()
plot_histogram(ideal_distribution)

 

# EMAITZA ESKUMAKO DIAGRAMA DA:

# Vamos a profundizar un poco con la cuestión del "Transpiler".

# las explicaciones en amarillo

 

from qiskit import transpile
from qiskit.transpiler import PassManager
from qiskit_ibm_runtime.transpiler.passes.scheduling import (
ASAPScheduleAnalysis,
PadDynamicalDecoupling,)
from qiskit.circuit.library import XGate

# Mediremos los tres qubits quedando su reultado en los bits correspondientes
qc.measure([0, 1, 2], [0, 1, 2])

# Se inicializa una lista vacía para almacenar los circuitos transpileados.
circuits = []

# Se itera sobre dos niveles de optimización: 0 y 3. El nivel 0 es sin optimización y el nivel 3 es el máximo nivel de optimización
for optimization_level in [0, 3]:
t_qc = transpile(qc, backend, optimization_level=optimization_level, seed_transpiler=0) #se transpila qc para que sea compatible con el backend
count_ops = t_qc.count_ops() # Se cuentan las operaciones en el circuito transpileado.
print (t_qc.count_ops())
if "cx" in count_ops: # Se cuentan, por ejemplo, puertas "cx"
print(f"CNOTs (optimization_level={optimization_level}): ", count_ops["cx"])
else:
print(f"CNOTs (optimization_level={optimization_level}): 0")

circuits.append(t_qc) # Se agrega el circuito transpileado a la lista circuits.

 

# Get gate durations so the transpiler knows how long each operation takes
# Obtiene la duración de las puertas para que el transpiler sepa cuanto va a tardar la ejecución
durations = backend.target.durations()


# Define una secuencia de decoupling dinámico (dos puertas X) que se aplicará a los qubits en estado de espera.
# Esto se hace para contrarrestan los efectos de los ruidos y prolongan la coherencia de los qubits en espera.
dd_sequence = [XGate(), XGate()]


# Ejecuta el PassManager en el segundo circuito transpileado (con optimización nivel 3) para aplicar el decoupling dinámico.
pm = PassManager([ASAPScheduleAnalysis(durations), PadDynamicalDecoupling(durations, dd_sequence)])
circ_dd = pm.run(circuits[1])

# Add this new circuit to our list
# Agrega el nuevo circuito con decoupling dinámico a la lista circuits.
circuits.append(circ_dd)

""" NOTA IMPORTANTE: ¿Qué hemos hecho hasta ahora?

Hemos transpilado el cirduito originar con dos niveles de optimización:
Circuitos Transpilados con Diferentes Niveles de Optimización:

Nivel de Optimización 0: Transpilación sin optimización.
Nivel de Optimización 3: Transpilación con el nivel máximo de optimización.
Se hace esto para comparar el impacto de la optimización en el circuito, especialmente en términos de la cantidad de puertas CNOT (cx),
que son costosas en términos de tiempo de ejecución y propensas a errores.

Después de obtener el circuito optimizado, hemos aplicado una secuencia de desacoplamiento dinámico para mitigar los efectos del ruido
y prolongar la coherencia de los qubits.
EL objetivo sería evaluar cómo la transpilación con diferentes niveles de optimización afecta el circuito, específicamente cantidad de operaciones cx.

¿Cuántos Circuitos se Ejecutan?
En total, se añaden tres circuitos a la lista circuits:

Circuito transpilado con nivel de optimización 0.
Circuito transpilado con nivel de optimización 3.
Circuito transpilado con nivel de optimización 3 y con desacoplamiento dinámico aplicado.

Finalmente, podemos decidir cuál o cuáles de estos circuitos ejecutar en el backend cuántico.
En muchos casos, se ejecutan todos los circuitos para comparar los resultados y elegir el mejor
enfoque para futuras implementaciones.

Por ejemplo, podríamos ejecutar los circuitos así:
# from qiskit import execute
# results = []
# for circuit in circuits:
# job = execute(circuit, backend)
# result = job.result()
# results.append(result)
#
# Analizar los resultados
# for idx, result in enumerate(results):
# counts = result.get_counts() counts = result.get_counts()
# print(f"Resultados del circuito {idx}: {counts}")
"""


""" NOTA: El tercer ejemplo trata de explicar este tipo de circuitos generados """
# Dibuja el circuito final, especificando el formato de salida (en este caso, una imagen Matplotlib),
# el estilo (iqp), y sin mostrar los cables en espera.
circ_dd.draw(output="mpl", style="iqp", idle_wires=False)

 

# JARRAIAN IKUSI AHAL DUGU ZIRKUITUAREN DIAGRAMA, TRANSPILATU ONDOREN:

# Ejecutamos el circuito

from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2

sampler=SamplerV2(backend)

job = sampler.run(circuits, shots=8000,)


# Información sobre el job
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")

# Información sobre los resultaados
result = job.result()

for idx, pub_result in enumerate(result):
print(f" > Counts for pub {idx}: {pub_result.data.c.get_counts()}")
# print(f" > Counts for pub {idx}: {pub_result.data.meas.get_counts()}") # esto es en caso de measure_all

# EMAITZA BEHEAN:

>>> Job ID: ct6q5s7wmw20008w88h0
>>> Job Status: QUEUED
 > Counts for pub 0: {'010': 773, '000': 1302, '001': 652, '110': 700, '111': 1699, '011': 1179, '101': 699, '100': 996}
 > Counts for pub 1: {'000': 546, '111': 2354, '011': 2128, '101': 1090, '001': 938, '110': 286, '010': 412, '100': 246}
 > Counts for pub 2: {'001': 948, '100': 263, '011': 1432, '111': 3533, '101': 686, '010': 449, '000': 433, '110': 256}

# Veamos gráficamente los resultados

from qiskit.visualization import plot_histogram

# Obtener las counts del resultado
counts = pub_result.data.c.get_counts()
# counts = pub_result.data.meas.get_counts() # esto es en caso de measure_all

# Convertir las claves numéricas a binario y almacenar en binary_prob
binary_prob = {k: v / sum(counts.values()) for k, v in counts.items()}

# Simular la distribución ideal
ideal_distribution = {'111': 0.781, '000': 0.031, '001': 0.031, '010': 0.031, '011': 0.031, '100': 0.031, '101': 0.031, '110': 0.031}

# Mostrar los resultados
plot_histogram([binary_prob, ideal_distribution], bar_labels=False, title="Resultados de Medida", legend=["Ejecución Real", "Ideal"])

measure_all

# EMAITZA HEMEN BEHEAN:

Ateen interpretazioa transpiler egin ondoren

Esan bezala, zirkuitu kuantiko bat transpilatzen dugunean, zirkuituaren ezaugarriak egokitu egiten ditugu zirkuitua egiteko aukeratutako makinaren ezaugarrietara, eta prozesuaren ondorioz ate kuantikoak deskonposatu egin daitezke, beste batzuk sartu... Eta aurreko exekuzioetan ikusten dugun zirkuiturik konplexuenak baditu zenbait ate agian ezagutzen ez ditugunak; hona hemen batzuk:

  • Rz:
    • Describapena: Blochen esferako qubitaren z ardatzaren inguruko errotazioa da.
    • Sinboloa: Oro har, Rz(θ) bezala irudikatzen da, eta, bertan, θ errotazio angelua da.
    • Funtzioa: Qubitaren egoeraren fasea aldatzen du, 0 edo 1 neurtzeko probabilitatea aldatu gabe.
  • √X (X-ren erro karratua o “SX”):
    • Deskribapena: Pauli-X atearen erro karratua irudikatzen du. Hadamardeko ate partziala ere esaten zaio.
    • Sinboloa: Batzuetan horrela agertzen da: √X
    • Funtzioa: Operadore unitario bat da, bi aldiz jarraian aplikatzen denean, X ate baten baliokidea dena. Blochen esferan, x ardatzaren inguruko 90 graduko errotazio gisa ikus daiteke.
  • X:
    • Deskribapena: Pauli-X atea da, NOT ate kuantikoa bezala ere ezagutzen dena.
    • Sinboloa: X gisa agertzen da.
    • Funtzioa: Aldatu qubit baten egoera |0⟩ tik  |1⟩era eta alderantziz. 180 graduko biraketa da, X ardatzaren inguruan, Blochen esferan.
  • Delay:
    • Deskribapena: Zirkuituan etenaldi bat edo itxaronaldi bat irudikatzen du.
      Sinboloa: Batzuetan "delay" bezala edo etenaldi sinbolo batekin agertzen da.
      Funtzioa: Qubitetan eragiketak sinkronizatzeko edo hurrengo eragiketa egin aurretik denbora jakin bat itxaroteko erabiltzen da.

 

Hadamard ateko deskonposizioa

Hadamard H atea,  Rz eta √X (SX) ateen arteko konbinazio batean deskonposatu daiteke:

H=Rz(π/2)⋅SX⋅Rz(π/2)

Hadamard atea Blochen esferan errotazio espezifiko gisa ikus daitekeelako. Rz eta SX erabiltzea H erabili beharrean onuragarria izan daiteke ate horiek eraginkortasun handiagoz inplementatzen dituzten zenbait backendentzat.

La transpilación puede resultar en diferentes configuraciones de puertas para distintos qubits debido a optimizaciones específicas del backend cuántico, interacciones entre puertas en el circuito, y características específicas de cada qubit. Esto puede resultar en que una puerta H se descomponga en Rz y SX  en un qubit, y de manera diferente en otro, todo con el objetivo de optimizar la ejecución en el hardware cuántico específico.


Transpilazioa, qubit desberdinetarako ateen konfigurazio desberdinetan gerta daiteke, eta hori izan daiteke backend kuantikoaren optimizazio espezifikoak direla eta, baita zirkuituko ateen arteko interakzioen arabera eta qubit bakoitzaren ezaugarri espezifikoen ondorioz. Qubit batetarako H ate bat Rz eta SX batean  deskonposatzean gerta daiteke, eta modu desberdinean beste qubit batean, dena hardware kuantiko espezifikoan exekuzioa optimizatzeko helburuarekin.

Jarraian ikusiko dugu Hadamard ate bat aplikatzea, Rz·SX·Rz aplikatzearen baliokidea dela. 

 

# Preparamos un circuito con solamente una puerta Hadamard

from qiskit import QuantumCircuit, transpile
from qiskit_aer import Aer
from qiskit.visualization import plot_bloch_multivector, plot_state_city
import matplotlib.pyplot as plt
import numpy as np
# Qiskit Runtime
from qiskit_ibm_runtime import QiskitRuntimeService, Batch

# Crear el circuito cuántico
qc = QuantumCircuit(1)
qc.h(0)
# qc.measure_all()

qc.draw(output="mpl", style="iqp")

# Ejecutamos el circuito en un simulador para visualizar el estado del qubit
# en la esfera de Bloch.

# Simulador de estado cuántico
simulator = Aer.get_backend('statevector_simulator')

# Ejecutar la simulación
result = simulator.run(transpile(qc, simulator)).result()
statevector = result.get_statevector()


print(" ")
print("Statevector resultante:")
print(statevector_array)

# Imprimir los estados base y sus correspondientes amplitudes de probabilidad
n = qc.num_qubits
for i, amplitude in enumerate(statevector_array):
binary_state = format(i, f'0{n}b')
print(f"|{binary_state}⟩: {amplitude}")
# ____________________________________________________________

# Visualizar el estado final en la esfera de Bloch
from qiskit.visualization import plot_bloch_multivector, plot_state_city
import matplotlib.pyplot as plt

plot_bloch_multivector(statevector)

Ateen interpretazioa transpiler egin ondoren

Esan bezala, zirkuitu kuantiko bat transpilatzen dugunean, zirkuituaren ezaugarriak egokitu egiten ditugu zirkuitua egiteko aukeratutako makinaren ezaugarrietara, eta prozesuaren ondorioz ate kuantikoak deskonposatu egin daitezke, beste batzuk sartu... Eta aurreko exekuzioetan ikusten dugun zirkuiturik konplexuenak baditu zenbait ate agian ezagutzen ez ditugunak; hona hemen batzuk:

  • Rz:
    • Describapena: Blochen esferako qubitaren z ardatzaren inguruko errotazioa da.
    • Sinboloa: Oro har, Rz(θ) bezala irudikatzen da, eta, bertan, θ errotazio angelua da.
    • Funtzioa: Qubitaren egoeraren fasea aldatzen du, 0 edo 1 neurtzeko probabilitatea aldatu gabe.
  • √X (X-ren erro karratua o “SX”):
    • Deskribapena: Pauli-X atearen erro karratua irudikatzen du. Hadamardeko ate partziala ere esaten zaio.
    • Sinboloa: Batzuetan horrela agertzen da: √X
    • Funtzioa: Operadore unitario bat da, bi aldiz jarraian aplikatzen denean, X ate baten baliokidea dena. Blochen esferan, x ardatzaren inguruko 90 graduko errotazio gisa ikus daiteke.
  • X:
    • Deskribapena: Pauli-X atea da, NOT ate kuantikoa bezala ere ezagutzen dena.
    • Sinboloa: X gisa agertzen da.
    • Funtzioa: Aldatu qubit baten egoera |0⟩ tik  |1⟩era eta alderantziz. 180 graduko biraketa da, X ardatzaren inguruan, Blochen esferan.
  • Delay:
    • Deskribapena: Zirkuituan etenaldi bat edo itxaronaldi bat irudikatzen du.
      Sinboloa: Batzuetan "delay" bezala edo etenaldi sinbolo batekin agertzen da.
      Funtzioa: Qubitetan eragiketak sinkronizatzeko edo hurrengo eragiketa egin aurretik denbora jakin bat itxaroteko erabiltzen da.

 

Hadamard ateko deskonposizioa

Hadamard H atea,  Rz eta √X (SX) ateen arteko konbinazio batean deskonposatu daiteke:

H=Rz(π/2)⋅SX⋅Rz(π/2)

Hadamard atea Blochen esferan errotazio espezifiko gisa ikus daitekeelako. Rz eta SX erabiltzea H erabili beharrean onuragarria izan daiteke ate horiek eraginkortasun handiagoz inplementatzen dituzten zenbait backendentzat.

La transpilación puede resultar en diferentes configuraciones de puertas para distintos qubits debido a optimizaciones específicas del backend cuántico, interacciones entre puertas en el circuito, y características específicas de cada qubit. Esto puede resultar en que una puerta H se descomponga en Rz y SX  en un qubit, y de manera diferente en otro, todo con el objetivo de optimizar la ejecución en el hardware cuántico específico.


Transpilazioa, qubit desberdinetarako ateen konfigurazio desberdinetan gerta daiteke, eta hori izan daiteke backend kuantikoaren optimizazio espezifikoak direla eta, baita zirkuituko ateen arteko interakzioen arabera eta qubit bakoitzaren ezaugarri espezifikoen ondorioz. Qubit batetarako H ate bat Rz eta SX batean  deskonposatzean gerta daiteke, eta modu desberdinean beste qubit batean, dena hardware kuantiko espezifikoan exekuzioa optimizatzeko helburuarekin.

Jarraian ikusiko dugu Hadamard ate bat aplikatzea, Rz·SX·Rz aplikatzearen baliokidea dela. 

 

# HACEMOS AHORA UN CIRCUITO CON PUERTAS Rz, SX y Rz
#====================================================#

from qiskit import QuantumCircuit
from qiskit_aer import Aer
from qiskit.visualization import plot_bloch_multivector, plot_state_city
import matplotlib.pyplot as plt
import numpy as np
from math import pi

# Crear un nuevo circuito cuántico
qc = QuantumCircuit(1)
qc.rz(pi/2, 0)
qc.sx(0)
qc.rz(pi/2, 0)

qc.draw(output="mpl", style="iqp")

# Ejecutamos el circuito en un simulador para visualizar el estado del qubit
# en la esfera de Bloch.

# Simulador de estado cuántico
simulator = Aer.get_backend('statevector_simulator')

# Ejecutar la simulación
result = simulator.run(transpile(qc, simulator)).result()
statevector = result.get_statevector()

print(" ")
print("Statevector resultante:")
print(statevector_array)

# Imprimir los estados base y sus correspondientes amplitudes de probabilidad
n = qc.num_qubits
for i, amplitude in enumerate(statevector_array):
binary_state = format(i, f'0{n}b')
print(f"|{binary_state}⟩: {amplitude}")
# ____________________________________________________________

# Visualizar el estado final en la esfera de Bloch
from qiskit.visualization import plot_bloch_multivector, plot_state_city
import matplotlib.pyplot as plt

plot_bloch_multivector(statevector)

 

Ikusi dugu RZ · SX · Rz H ate bat aplikatzea bezalakoa dela, baina pausoz pauso ikusiko dugu azaltzen saiatzeko:

 
 

 

 

Rz ate bakarreko zirkuitua prestatuko dugu.

Exekutatzean ikusiko dugu ez duela islarik izan Blochen esferan; hori da, bektorea "z" ardatzean zegoelako eta Rz ateak, hain zuzen ere, qubitaren "z" ardatzaren inguruan errotazio bat aplikatzen duelako Blochen esferan.

 

# Circuito con una puerta Rz

qc = QuantumCircuit(1)

qc.rz(pi/2, 0)

 

qc.draw(output="mpl", style="iqp")

 

Rz eta SX ateak dituena zirkuitua pretatuko dugu orain.

 
Exekutatzean, "x" ardatzaren inguruan errotazio bat aplikatu dela ikusiko dugu.

 

# Circuito con una puerta Rz y una SX

qc = QuantumCircuit(1)

qc.rz(pi/2, 0)

qc.sx(0)

 

qc.draw(output="mpl", style="iqp")

 

Aurreko zirkuituari beste Rz ate bat gehituko diogu, eta ikusiko dugu nola oraingo honetan Rz ateak eragina duen Blochen esferan, "x" ardatzaren inguruan Pi/2 biraketa bat aplikatzen baitio irudikatutako bektoreari.

 

 

# Circuito con una puerta Rz, una SX y una Rz

qc = QuantumCircuit(1)

qc.rz(pi/2, 0)

qc.sx(0)

qc.rz(pi/2, 0)

 

qc.draw(output="mpl", style="iqp")

OHARRA

GHZ (Greenberger-Horne-Zeilinger) egoera kuantiko mota berezi bat da, elkarri oso lotuta dagoena. Qubit ugari (normalean hiru edo gehiago) hartzen dituen egoera bat da, eta ezaugarri berezi bat du: qubit guztiak gainjartze maximo batean daude, eta qubitetako bateko edozein neurrik berehala eragiten die beste qubitei.

5 qubitetarako GHZ egoera honela idatz daiteke:

GHZ= 1/√2 · (∣00000+∣11111⟩)

Horrek esan nahi du bost qubitak ∣00000⟩ eta ∣11111⟩ estatuen gainjartze batean daudela. Qubitetako bat neurtzen bada eta ∣0⟩ egoeran badago, beste laurak ∣0⟩| estatuan egongo dira ere, eta ∣1⟩ estatuan neurtzen bada, beste laurak ere ∣1⟩ estatuan egongo dira. Elkarloturaren adibide bat da, qubitetako baten egoerak beste lauren egoera zehazten duena.

 

1. urratsa: GHZ zirkuitoa eraiki:

from qiskit import QuantumCircuit

def GHZ(num_qubits):

qc = QuantumCircuit(num_qubits)
qc.h(0)
for qubit in range(num_qubits-1):
    qc.cx(qubit, qubit + 1)
qc.measure_all()
return qc

num_qubits = 5
circuit = GHZ(num_qubits=num_qubits)
circuit.draw("mpl")

# EMAITZA:

2. urratsa: Backend aukeratu

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

service = QiskitRuntimeService(channel="ibm_quantum")

### ELEGIR EL BACKEND MAS LIBRE DE TRABAJO
backend = service.least_busy(operational=True, simulator=False)

### ELEGIR UN BACKEND CONCRETO POR NOMBRE
# Seleccionar un backend específico por nombre
# backend_name = 'ibm_kyiv' # Cambia esto por el nombre del backend que deseas
# backend = service.get_backend(backend_name)

print(f"Backend seleccionado: {backend.name}")

print(backend)

# EMAITZA:

3. urratsa: Zirkuitoa "transpilatu" exekutatu ahal izateko

pass_manager = generate_preset_pass_manager(optimization_level=3, backend=backend)
isa_circuit = pass_manager.run(circuit)
isa_circuit.draw("mpl", idle_wires=False, scale=0.7, fold=-1)

 

# SORTUTAKO ZIRKUITOA:

4. urratsa: SIMULAGAILUAN eta aukeratutako BAKCKENDEAN exekutatu

from qiskit_ibm_runtime import SamplerV2
from qiskit_aer import AerSimulator

# Ideal simulation
aer_sim = AerSimulator()
sampler_aer = SamplerV2(backend=aer_sim)
job_aer = sampler_aer.run([isa_circuit], shots=1000)

# Run on the real backend
sampler = SamplerV2(backend=backend)
job = sampler.run([isa_circuit], shots=1000)
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job status: {job.status()}")

# EMAITZA:

5. urratsa: konparatu exekuzioa SIMULAGAILUAN eta HARDWARE ERREALEAN

from qiskit.visualization import plot_distribution

result_aer = job_aer.result()
result = job.result()
samp_dist_aer = result_aer[0].data.meas.get_counts()
samp_dist = result[0].data.meas.get_counts()
plot_distribution([samp_dist_aer, samp_dist], legend=['Ideal', 'Real hardware'])

 

# EMAITZA HEMEN BEHEAN:

AZALPENA:

Ikus dezakegunez, SIMULAGAILUAN egindako exekuzioak espero den emaitza eskaintzen digu, hau da, % 50eko aukera inguru emaitza posible bakoitzean, zehazki: % 49 '00000' -rako eta % 51 '11111' -rako.

Hala ere, benetako exekuzioak sistema kuantikoen deskoherentziak eragindako akatsak nabariak dira. Zehazki, exekuzio horretan, % 50era hurbildu beharko liratekeen erroreak % 33,3an geratzen dira '00000' emaitzarako, eta % 39,8an '11111' emaitzarako, eta gainerako % 100era arteko erroreak balizko 32 balioen artean banatzen dira.
Jauzi esanguratsua ( % 15,7) ikusi dugu '00010' balioan, baina ez dugu azalpenik aurkitu; izan ere, exekuzio berri batean emaitzak normalagoak izan dira.
JARRAIAN, exekuzio berri honen grafikoa sartu dugu, baina aurrekoa ere uztea erabaki dugu, erakusteko emaitzak ez direla beti espero direnak. 

Diseinatu eta Exekutatu IBM Quantum Composerekin

Atal honetan IBM Quantum Composer-rekin lan egiten ikasiko dugu.

Tresna honek gure ekipoan ezer instalatu beharrik gabe zirkuitu kuantikoak sortu eta exekutatzeko aukera ematen digu.

Tresna honetara esteka honen bidez sar gaitezke, eta dokumentazio osoa hemen aurki dezakegu.

Edukia:

  • Zer da Composer?
  • Zirkuitu bat eraikitzea
  • Pausoz pauso aztertu eta qubiten egoeraren irudikapena interpretatzea
  • Ikusizko tresnak (probabilitateak, q-esfera eta statevector-a)
  • Composer Operations
  • Zirkuituak exekutatzea

IBM Quantum Composer IBM Platform tresna bat da, simulagailuetan edo sistema kuantikoetan zirkuitu kuantikoak sortzea, bistaratzea eta exekutatzea errazten duena; zirkuituak eraiki ondoren, aukera ematen du:

  • Bistaratu qubiten egoera

Qubit bakoitzerako esfera interaktibo bat erakusten da, eta bertan ikusten dira qubiten egoeran zirkuituak eragiten dituen aldaketak.

  • Hardware kuantikoan exekutatu

Zirkuituak hardware kuantiko errealean exekutatzea, zaratak prozesuan dituen ondorioak ulertzeko.

  • Sortu kodea automatikoki beste ingurune batzuetan erabiltzeko

Zirkuitua sortu ahala, dagokion kodea sortuko da OpenQASM edo Python sistemetan

Hau da Composer-en pantaila; ikus ditzagun atalik interesgarrienak:

    1. Circuit Name edit
    2. Menu bar - Erabili menu hauek zirkuitu berri bat sortzeko, gordetako zirkuituak eta erregistroak administratzeko, zure lan-espazioa pertsonalizatzeko eta gehiago.
    3. Run area – Zirkuitua exekutatzeko simulagailu batean edo benetako hardwarean.
    4. Tools panels – Gordetako zirkuituak ikusteko hiru ikono, exekutatutako job 's eta laguntza dokumentazioa. Ikonoan berriro klikatuz panela ixten da.
    5. Operations catalog - Hauek dira zirkuitu kuantikoen oinarrizko osagaiak. Arrastatu eta askatu ate horiek eta beste eragiketa batzuk zirkuituen editore grafikoan. Ate motak kolorearen arabera taldekatzen dira. Adibidez, ate klasikoak urdin ilunak dira, fase-ateak urdin argiak eta eragiketa ez-unitarioak grisak.
    6. Inspect – Hemendik zirkuitua urratsez urrats exekutatu ahal izango dugu. Ikusi Inspect your circuit, step-by-step.
    7. Phase disks – Qubitaren egoera-bektorearen fasearen eta haren lotura-mailaren adierazpena.
    8. Code editore – Hemendik zuzenean OpenQASM edo Qiskit kodea ikusi eta editatu ahal izango dugu.
    9. Graphical circuit editorea – Hemen eraikitzen dugu zirkuitua. Ateak eta beste eragiketa batzuk arrastatuko ditugu zirkuitu kuantikoa osatzen duten qubit-kable horizontaletan. Ateen parametroak eta konfigurazioak editatzeko, hautatu atea editore grafikoan eta klikatu Editatu.
    10. Visualizations – Aurrerago hiru bistaratzeak azaltzen dira: Probabilitateak, Q-Esfera eta Statevector

Saia gaitezen zirkuitu sinple batekin, zehazki, bi qubiteko Bell egoerarekin (gehieneko elkarlotura).

Horretarako, Hadamardeko ate bat arrastatuko dugu lehen qubitaren gainean (q 0):

 

Bistaratze-eremuan honako hau izango dugu:

Emaitza logikoa da, 1 qubita beti 0an dago eta 1 qubita % 50ean dago 0an edo 1ean egoteko. Aurrerago azalduko ditugu bistaratzeko modu horiek.

Ondoren, bi qubitak CNOT baten bidez gurutzatuko ditugu q0 eta q1 artean.

Gure bistaratzea aldatu egingo da, orain bi qubitak 0an egotea eta bi qubitak 1ean egotea baita aukera bakarra.

Amaitzeko, neurketak egin ditzakegu:

 

Eskuinean, sortutako kodea ikus dezakegu, eta esportatu egin dezakegu, beste aplikazio batzuetan erabiltzeko.

Zirkuitua urratsez urrats ikuskatzea

  • "Ikusi" menuan, erabili nahi ditugun bistaratzeetarako panelak hautatuko ditugu.
  • Tresna-barraren Ikuskatu etengailuan klik egingo dugu. Kontuan izan behar da zirkuituen ikuskatzailea aktibatuta dagoenean ezin izango dugula eragiketa gehiago gehitu desaktibatu arte.
  • Zirkuituaren osagaien bistaratzeetan zehar urratsez urrats mugitzeko, aitzinamendu- eta atzerakada-botoiak erabil ditzakegu.
  • Eragiketaren bat/batzuk bakarrik ikuskatzeko, eragiketa horietan klik egin dezakegu, eta gainposizio bat agertuko da, zirkuituen ikuskatzaileak exekutatzen duenean sartuko direla adierazten duena. Eragiketa baten hautaketa baliogabetzeko, egin klik berriro eta gainjartzea desagertu egingo da.

Ikuskatzailea ixteko eta zirkuitua berriro editatzeko, berriro egin behar da klik tresna-barran Ikuskatu botoian.

 

Qubiten egoeraren adierazpena

IBM Quantum Composer-en qubita irudikatzen duen lerroaren amaieran ikusten dugun diskoak qubit bakoitzaren egoera lokala ematen du kalkuluaren amaieran. Informazio hau ematen digu.

Qubita ∣1⟩ egoeran egoteko probabilitatea

 

Qubita "1" egoeran egoteko probabilitatea disko urdinaren betegarriak adierazten du:

 

2. Fase kuantikoa

Qubitaren egoeraren fase kuantikoa diagramaren erditik disko grisaren ertzeraino hedatzen den lerroak ematen du (erdiko puntuaren inguruan ordutegiaren aurkako noranzkoan biratzen da).

 

3. Qubitaren garbitasun/elkarlotzea

Eraztun beltzaren erradioak qubitaren egoeraren garbitasun murriztua adierazten du. Purutasuna [0.5, 1] tartean dago; baten balioak adierazten du qubita ez dagoela beste inon lotuta. Aitzitik, 0.5eko purutasun murriztuak erakusten du qubita egoera erabat mistoan geratzen dela, eta nolabaiteko lotura duela gainerako N − 1 q ubitekin, eta, beharbada, baita ingurunearekin ere.

 

Hauek dira Composer-ek eskaintzen dizkigun hiru bistaratze motak:

1. Vista de Probabuilidades

(Máximo 8 qubits)

 

2. Q-Esferaren ikuspegia

(Gehienez 5 qubit)

Nodoak q esferan kokatzen dira. Horrela, zero guztiak ∣000⟩ egoera bere ipar poloan dago, eta "1" guztietako base_ egoera ∣111⟩  bere hego poloan dago. Zero (edo bat) kopuru bera duten oinarri-egoerak q esferaren latitude partekatu batean daude (adibidez, ∣001⟩, ∣010⟩, ∣100⟩, ∣001 ⟩, ∣010 ⟩, ∣100 ⟩). Q-esferaren ipar poloan hasi eta hegoalderantz eginez, ondoz ondoko latitude "1" gehiago ditu oinarri-egoerak; oinarri-egoera baten latitudea Hamming-eko distantziaren araberakoa da zero estatutik. Q-esferak egoera kuantikoari buruzko informazio osoa dauka irudikapen trinko batean.

 

Oharra:

Zein da Bloch esfera baten eta Q-Esfera baten arteko aldea? Garrantzitsua da azpimarratzea q-Esfera eta Bloch esfera ez direla gauza bera, baita qubit bakarrerako ere. Bloch esferak egoera kuantikoaren ikuspegi lokala eskaintzen du, qubit bakoitza bere kabuz ikusten delarik. Qubit-erregistroek (qubit anitzeko egoerak) zirkuitu kuantikoen aplikazioan nola jokatzen duten ulertzen saiatzen garenean, argigarriagoa da ikuspegi orokor bat hartzea eta egoera kuantiko osoa behatzea. Q-Esferak egoera kuantikoaren irudikapen bisuala ematen du, eta, beraz, ikuspegi orokor hori. Beraz, qubit kopuru txikietan aplikazio eta algoritmo kuantikoak arakatzean, Q-Esferak izan beharko luke bistaratzeko metodo nagusia.

3. Statevector_earen bista

(6 qubit gehienez)

Ikuspegi horrek barra-grafiko gisa ikusten ditu anplitude kuantikoak. Ardatz horizontalak oinarri konputazionaleko egoerak etiketatzen ditu. Ardatz bertikalak konputazio-oinarriaren egoera bakoitzari lotutako anplitudeen magnitudea neurtzen du. Barra bakoitzaren koloreak fase kuantikoa adierazten du.

 

Zutabe batetan gelditzen badugu kurtsorea, dagokion informazioa ikusiko dugu.

Operadoreak azaltzen dituen PDF bat deskargatu ahal duzu esteka honetan.

Zirkuituak exekutatu

  • Egin klik "Setup and run" goiko eskuineko izkinan. Irekitzen den leihoan, sistema edo simulagailu bat hautatu. Horretarako, interesgarria izango da makina bakoitzean kolatutako lan kopurua kontuan hartzea: "Total pending Jobs"
  • Jarraian, gure zirkuituarekin egin nahi dugun "shots" kopurua (exekuzioak) ezar dezakegu.
  • Etiketak ere gehitu ditzakegu panel honetan.
  • Klik egin "Run in....."
  • Lanaren aurrerapena Lanak ikonoan klik eginez ikusi ahal izango dugu:

 

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram