Construya circuitos en el SDK - Amazon Braket

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Construya circuitos en el SDK

Esta sección proporciona ejemplos de cómo definir un circuito, ver las puertas disponibles, ampliar un circuito y ver las puertas compatibles con cada dispositivo. También contiene instrucciones sobre cómo asignar manualmentequbits, indicar al compilador que ejecute los circuitos exactamente como se han definido y crear circuitos ruidosos con un simulador de ruido.

También puedes trabajar a nivel de pulso en Braket para varias puertas con determinadas QPU. Para obtener más información, consulte Control de impulsos en Amazon Braket.

Puertas y circuitos

Las puertas y circuitos cuánticos se definen en la braket.circuitsclase del SDK de Python deAmazon Braket. Desde el SDK, puede crear una instancia de un nuevo objeto de circuito mediante una llamadaCircuit().

Ejemplo: Definir un circuito

El ejemplo comienza definiendo un circuito de muestra de cuatroqubits (denominado,q0q1q2, yq3) que consiste en puertas Hadamard estándar de un solo cúbit y puertas CNOT de dos cúbits. Puede visualizar este circuito llamando a laprint función, como se muestra en el siguiente ejemplo.

# import the circuit module from braket.circuits import Circuit # define circuit with 4 qubits my_circuit = Circuit().h(range(4)).cnot(control=0, target=2).cnot(control=1, target=3) print(my_circuit)
T : |0| 1 | q0 : -H-C--- | q1 : -H-|-C- | | q2 : -H-X-|- | q3 : -H---X- T : |0| 1 |

Ejemplo: Definir un circuito parametrizado

En este ejemplo, definimos un circuito con puertas que dependen de parámetros libres. Podemos especificar los valores de estos parámetros para crear un nuevo circuito o, al enviar el circuito, para ejecutarlo como una tarea en ciertos dispositivos.

from braket.circuits import Circuit, FreeParameter #define a FreeParameter to represent the angle of a gate alpha = FreeParameter("alpha") #define a circuit with three qubits my_circuit = Circuit().h(range(3)).cnot(control=0, target=2).rx(0, alpha).rx(1, alpha) print(my_circuit)

Puede crear un circuito nuevo no parametrizado a partir de uno parametrizado proporcionando un argumento únicofloat (que es el valor que adoptarán todos los parámetros libres) o de palabras clave que especifiquen el valor de cada parámetro en el circuito de la siguiente manera.

my_fixed_circuit = my_circuit(1.2) my_fixed_circuit = my_circuit(alpha=1.2)

Tenga en cuenta que nomy_circuit está modificado, por lo que puede usarlo para crear instancias de muchos circuitos nuevos con valores de parámetros fijos.

Ejemplo: Ver todas las puertas disponibles

En el ejemplo siguiente se muestra cómo ver todas las compuertas disponibles enAmazon Braket.

import string from braket.circuits import Gate # print all available gates in Amazon Braket gate_set = [attr for attr in dir(Gate) if attr[0] in string.ascii_uppercase] print(gate_set)

La salida de este código muestra todas las puertas.

['CCNot', 'CNot', 'CPhaseShift', 'CPhaseShift00', 'CPhaseShift01', 'CPhaseShift10', 'CSwap', 'CV', 'CY', 'CZ', 'ECR', 'H', 'I', 'ISwap', 'PSwap', 'PhaseShift', 'Rx', 'Ry', 'Rz', 'S', 'Si', 'Swap', 'T', 'Ti', 'Unitary', 'V', 'Vi', 'X', 'XX', 'XY', 'Y', 'YY', 'Z', 'ZZ']

Cualquiera de estas puertas se puede añadir a un circuito llamando al método de ese tipo de circuito. Por ejemplocirc.h(0), llamarías para añadir una puerta de Hadamard a la primeraqubit.

nota

Las puertas se anexan en su lugar y, en el ejemplo siguiente, se agregan todas las puertas enumeradas en el ejemplo anterior al mismo circuito.

circ = Circuit() # toffoli gate with q0, q1 the control qubits and q2 the target. circ.ccnot(0, 1, 2) # cnot gate circ.cnot(0, 1) # controlled-phase gate that phases the |11> state, cphaseshift(phi) = diag((1,1,1,exp(1j*phi))), where phi=0.15 in the examples below circ.cphaseshift(0, 1, 0.15) # controlled-phase gate that phases the |00> state, cphaseshift00(phi) = diag([exp(1j*phi),1,1,1]) circ.cphaseshift00(0, 1, 0.15) # controlled-phase gate that phases the |01> state, cphaseshift01(phi) = diag([1,exp(1j*phi),1,1]) circ.cphaseshift01(0, 1, 0.15) # controlled-phase gate that phases the |10> state, cphaseshift10(phi) = diag([1,1,exp(1j*phi),1]) circ.cphaseshift10(0, 1, 0.15) # controlled swap gate circ.cswap(0, 1, 2) # swap gate circ.swap(0,1) # phaseshift(phi)= diag([1,exp(1j*phi)]) circ.phaseshift(0,0.15) # controlled Y gate circ.cy(0, 1) # controlled phase gate circ.cz(0, 1) # Echoed cross-resonance gate applied to q0, q1 circ = Circuit().ecr(0,1) # X rotation with angle 0.15 circ.rx(0, 0.15) # Y rotation with angle 0.15 circ.ry(0, 0.15) # Z rotation with angle 0.15 circ.rz(0, 0.15) # Hadamard gates applied to q0, q1, q2 circ.h(range(3)) # identity gates applied to q0, q1, q2 circ.i([0, 1, 2]) # iswap gate, iswap = [[1,0,0,0],[0,0,1j,0],[0,1j,0,0],[0,0,0,1]] circ.iswap(0, 1) # pswap gate, PSWAP(phi) = [[1,0,0,0],[0,0,exp(1j*phi),0],[0,exp(1j*phi),0,0],[0,0,0,1]] circ.pswap(0, 1, 0.15) # X gate applied to q1, q2 circ.x([1, 2]) # Y gate applied to q1, q2 circ.y([1, 2]) # Z gate applied to q1, q2 circ.z([1, 2]) # S gate applied to q0, q1, q2 circ.s([0, 1, 2]) # conjugate transpose of S gate applied to q0, q1 circ.si([0, 1]) # T gate applied to q0, q1 circ.t([0, 1]) # conjugate transpose of T gate applied to q0, q1 circ.ti([0, 1]) # square root of not gate applied to q0, q1, q2 circ.v([0, 1, 2]) # conjugate transpose of square root of not gate applied to q0, q1, q2 circ.vi([0, 1, 2]) # exp(i(XX+YY) theta/4), where theta=0.15 in the examples below circ.xx(0, 1, 0.15) # exp(-iXX theta/2) circ.xy(0, 1, 0.15) # exp(-iYY theta/2) circ.yy(0, 1, 0.15) # exp(-iZZ theta/2) circ.zz(0, 1, 0.15)

Además del conjunto de puertas predefinido, también puede aplicar puertas unitarias autodefinidas al circuito. Pueden ser puertas de un solo cúbit (como se muestra en el siguiente código fuente) o puertas de varios cúbits aplicadas a lasqubits definidas por eltargets parámetro.

import numpy as np # apply a general unitary my_unitary = np.array([[0, 1],[1, 0]]) circ.unitary(matrix=my_unitary, targets=[0])

Ejemplo: ampliar los circuitos existentes

Puede ampliar los circuitos existentes añadiendo instrucciones. AnInstruction es una directiva cuántica que describe la tarea a realizar en un dispositivo cuántico. Instructionlos operadoresGate solo incluyen objetos de tipo.

# import the Gate and Instruction modules from braket.circuits import Gate, Instruction # add instructions directly. circ = Circuit([Instruction(Gate.H(), 4), Instruction(Gate.CNot(), [4, 5])]) # or with add_instruction/add functions instr = Instruction(Gate.CNot(), [0, 1]) circ.add_instruction(instr) circ.add(instr) # specify where the circuit is appended circ.add_instruction(instr, target=[3, 4]) circ.add_instruction(instr, target_mapping={0: 3, 1: 4}) # print the instructions print(circ.instructions) # if there are multiple instructions, you can print them in a for loop for instr in circ.instructions: print(instr) # instructions can be copied new_instr = instr.copy() # appoint the instruction to target new_instr = instr.copy(target=[5]) new_instr = instr.copy(target_mapping={0: 5})

Ejemplo: Ver las puertas que admite cada dispositivo

Los simuladores admiten todas las puertas del SDK de Braket, pero los dispositivos QPU admiten un subconjunto más pequeño. Puede encontrar las puertas compatibles de un dispositivo en las propiedades del dispositivo.

# import the device module from braket.aws import AwsDevice device = AwsDevice("arn:aws:braket:::device/qpu/ionq/ionQdevice") # get device name device_name = device.name # show supportedQuantumOperations (supported gates for a device) device_operations = device.properties.dict()['action']['braket.ir.jaqcd.program']['supportedOperations'] print('Quantum Gates supported by {}:\n {}'.format(device_name, device_operations))
Quantum Gates supported by IonQ Device: ['x', 'y', 'z', 'rx', 'ry', 'rz', 'h', 'cnot', 's', 'si', 't', 'ti', 'v', 'vi', 'xx', 'yy', 'zz', 'swap', 'i']
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Aspen-M-3") # get device name device_name = device.name # show supportedQuantumOperations (supported gates for a device) device_operations = device.properties.dict()['action']['braket.ir.jaqcd.program']['supportedOperations'] print('Quantum Gates supported by {}:\n {}'.format(device.name, device_operations))
Quantum Gates supported by Aspen-M-3: ['cz', 'xy', 'ccnot', 'cnot', 'cphaseshift', 'cphaseshift00', 'cphaseshift01', 'cphaseshift10', 'cswap', 'h', 'i', 'iswap', 'phaseshift', 'pswap', 'rx', 'ry', 'rz', 's', 'si', 'swap', 't', 'ti', 'x', 'y', 'z']

Es posible que las puertas compatibles deban compilarse en puertas nativas antes de que puedan ejecutarse en hardware cuántico. Al enviar un circuito,Amazon Braket realiza esta compilación automáticamente.

qubitAsignación manual

Al ejecutar un circuito cuántico en ordenadores cuánticos desdeRigetti, opcionalmente, puede utilizar laqubit asignación manual para controlarqubits cuáles se utilizan en su algoritmo. La consola de Amazon Braket y el SDK de Amazon Braket le ayudan a inspeccionar los datos de calibración más recientes del dispositivo de unidad de procesamiento cuántico (QPU) seleccionado, de modo que pueda seleccionar el mejorqubits para su experimento.

Laqubit asignación manual le permite ejecutar circuitos con mayor precisión e investigarqubit las propiedades individuales. Los investigadores y los usuarios avanzados optimizan el diseño de sus circuitos basándose en los datos de calibración más recientes del dispositivo y pueden obtener resultados más precisos.

En el siguiente ejemplo se muestra cómo asignarqubits explícitamente.

circ = Circuit().h(0).cnot(0, 7) # Indices of actual qubits in the QPU my_task = device.run(circ, s3_location, shots=100, disable_qubit_rewiring=True)

Para obtener más información, consulte los ejemplos de Amazon Braket en GitHub, o más específicamente, este cuaderno: Asignación de cúbits en dispositivos de QPU.

nota

ElOQC compilador no admite la configuracióndisable_qubit_rewiring=True. Si se establece este indicador en, seTrue produce el siguiente error:An error occurred (ValidationException) when calling the CreateQuantumTask operation: Device arn:aws:braket:eu-west-2::device/qpu/oqc/Lucy does not support disabled qubit rewiring.

Compilación literal

Cuando ejecutas un circuito cuántico en ordenadores cuánticos desdeRigettiIonQ, oOxford Quantum Circuits (OQC), puedes indicar al compilador que ejecute tus circuitos exactamente como están definidos sin ninguna modificación. Mediante la compilación literal, puede especificar que un circuito completo se conserve con precisión (compatible conRigettiIonQ, yOQC) según lo especificado o que solo se conserven partes específicas del mismo (Rigettisolo compatible con). Al desarrollar algoritmos para la evaluación comparativa del hardware o los protocolos de mitigación de errores, debe tener la opción de especificar exactamente las compuertas y los diseños de circuitos que ejecuta en el hardware. La compilación literal le brinda un control directo sobre el proceso de compilación al desactivar ciertos pasos de optimización, lo que garantiza que sus circuitos funcionen exactamente como se diseñaron.

Actualmente, la compilación literal es compatible con los dispositivosRigettiIonQ, yOxford Quantum Circuits (OQC) y requiere el uso de puertas nativas. Al utilizar la compilación literal, es recomendable comprobar la topología del dispositivo para asegurarse de que las puertas se activen al conectarsequbits y que el circuito utilice las puertas nativas compatibles con el hardware. El siguiente ejemplo muestra cómo acceder mediante programación a la lista de puertas nativas compatibles con un dispositivo.

device.properties.paradigm.nativeGateSet

ParaRigetti ello,qubit el recableado debe desactivarsedisableQubitRewiring=True configurando su uso con la compilación literal. SidisableQubitRewiring=False se establece cuando se utilizan cuadros textuales en una compilación, el circuito cuántico no pasa la validación y no se ejecuta.

Si la compilación literal está habilitada para un circuito y se ejecuta en una QPU que no la admite, se genera un error que indica que una operación no compatible ha provocado el error de la tarea. A medida que más hardware cuántico admita de forma nativa las funciones del compilador, esta función se ampliará para incluir estos dispositivos. Los dispositivos que admiten la compilación literal la incluyen como operación compatible cuando se les consulta con el siguiente código.

from braket.aws import AwsDevice from braket.device_schema.device_action_properties import DeviceActionType device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Aspen-M-3") device.properties.action[DeviceActionType.OPENQASM].supportedPragmas

No se generan costos adicionales por el uso de la compilación literal. Se te seguirán cobrando las tareas ejecutadas en los dispositivos QPU de Braket, las instancias de portátiles y los simuladores bajo demanda en función de las tarifas actuales, tal como se especifica en la página de precios de Amazon Braket. Para obtener más información, consulte ejemplo de compilación literal.

nota

Si utiliza OpenQASM para escribir sus circuitos para losIonQ dispositivosOQC y, si desea mapear su circuito directamente a los cúbits físicos, debe usarlo,#pragma braket verbatim ya que OpenQASM ignora por completo eldisableQubitRewiring indicador.

Simulación de ruido

Para crear una instancia del simulador de ruido local, puede cambiar el backend de la siguiente manera.

device = LocalSimulator(backend="braket_dm")

Puede construir circuitos ruidosos de dos formas:

  1. Construya el circuito ruidoso de abajo hacia arriba.

  2. Tome un circuito existente libre de ruido e inyecte ruido en todas partes.

El siguiente ejemplo muestra los enfoques que utilizan un circuito simple con ruido despolarizante y un canal de Kraus personalizado.

# Bottom up approach # apply depolarizing noise to qubit 0 with probability of 0.1 circ = Circuit().x(0).x(1).depolarizing(0, probability=0.1) # create an arbitrary 2-qubit Kraus channel E0 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.8) E1 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.2) K = [E0, E1] # apply a two-qubit Kraus channel to qubits 0 and 2 circ = circ.kraus([0,2], K)
# Inject noise approach # define phase damping noise noise = Noise.PhaseDamping(gamma=0.1) # the noise channel is applied to all the X gates in the circuit circ = Circuit().x(0).y(1).cnot(0,2).x(1).z(2) circ_noise = circ.copy() circ_noise.apply_gate_noise(noise, target_gates = Gate.X)

Ejecutar un circuito es la misma experiencia de usuario que antes, como se muestra en los dos ejemplos siguientes.

Ejemplo 1

task = device.run(circ, s3_location)

O bien

Ejemplo 2

task = device.run(circ_noise, s3_location)

Para ver más ejemplos, consulta el ejemplo introductorio del simulador de ruido Braket