Costruisci circuiti nell'SDK - Amazon Braket

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Costruisci circuiti nell'SDK

Questa sezione fornisce esempi di definizione di un circuito, visualizzazione dei cancelli disponibili, estensione di un circuito e visualizzazione di cancelli supportati da ciascun dispositivo. Contiene anche istruzioni su come allocare manualmentequbits, istruisci il compilatore di eseguire i tuoi circuiti esattamente come definito e costruisci circuiti rumorosi con un simulatore di rumore.

Cancelli e circuiti

I cancelli e i circuiti quantistici sono definiti nelbraket.circuitsclasse dellaAmazon BraketSDK Python. Dall'SDK, è possibile creare un'istanza di un nuovo oggetto circuito chiamandoCircuit().

Esempio: Definizione di un circuito

L'esempio inizia definendo un circuito campione di quattroqubits(etichettato)q0,q1,q2, eq3) costituito da cancelli standard Hadamard a qubit singolo e cancelli CNOT a due qubit. È possibile visualizzare questo circuito chiamando ilprintfunzione, come mostra l'esempio.

# 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 |

Esempio: Vedi tutti i cancelli disponibili

L'esempio seguente mostra come visualizzare tutti i cancelli disponibili inAmazon 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)

L'output di questo codice elenca tutte le porte.

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

Ognuno di questi cancelli può essere aggiunto a un circuito chiamando il metodo per quel tipo di circuito. Ad esempio, chiameresticirc.h(0), per aggiungere un cancello Hadamard al primoqubit.

Nota

I cancelli vengono aggiunti in posizione e l'esempio che segue aggiunge tutti i cancelli elencati nell'esempio precedente allo stesso 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) # 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(-iXY 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)

Oltre al set di gate predefinito, è anche possibile applicare cancelli unitari autodefiniti al circuito. Questi possono essere gate a qubit singolo (come mostrato nel seguente codice sorgente) o cancelli multi-qubit applicati alqubitsdefinito daltargetsParametro .

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

Esempio: Estensione dei circuiti esistenti

È possibile estendere i circuiti esistenti aggiungendo istruzioni. Un recordInstructionè una direttiva quantistica che descrive il compito da eseguire su un dispositivo quantistico.Instructiongli operatori includono oggetti di tipoGateSolo

# 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})

Esempio: Visualizza i cancelli supportati da ciascun dispositivo

I simulatori supportano tutti i cancelli delBraketSDK, ma i dispositivi QPU supportano un sottoinsieme più piccolo. È possibile trovare i cancelli supportati di un dispositivo nelle proprietà 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:::device/qpu/rigetti/Aspen-11") # 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-11: ['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']

È possibile che i cancelli supportati debbano essere compilati in gate nativi prima che possano essere eseguiti su hardware quantistico. Quando invii un circuito,Amazon Braketesegue questa compilazione automaticamente.

Manualequbitallocazione

Quando si esegue un circuito quantistico su computer quantisticiRigetti, è possibile utilizzare facoltativamente il manualequbitallocazione per ottenere il controllo su qualequbitsvengono utilizzati per il tuo algoritmo. LaConsole Amazon Brakete laSDK Amazon Braketaiuta a ispezionare i dati di taratura più recenti del dispositivo QPU (Quantium Processing Unit) selezionato, in modo da poter selezionare il migliorequbitsper il tuo esperimento.

Manualequbitl'allocazione consente di eseguire circuiti con maggiore precisione e di indagare individualmentequbitproprietà. Ricercatori e utenti avanzati ottimizzano la progettazione del circuito in base ai più recenti dati di calibrazione del dispositivo e quindi possono ottenere risultati più accurati.

L'esempio seguente mostra come allocarequbitsesplicitamente.

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)

Per ulteriori informazioni, consultagli esempi di Amazon Braket su GitHub, o più specificamente, questo notebook: Allocazione di qubit su dispositivi QPU.

Nota

LaOQCil compilatore oggi non supporta l'impostazionedisable_qubit_rewiring=True. Impostazione di questo flag suTrueverrà generato il seguente errore: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.

Compilazione verbatim

Quando si esegue un circuito quantistico su computer quantisticiRigettioOxford Quantum Circuits(OQC), hai la possibilità di indirizzare il compilatore per eseguire i circuiti esattamente come definito, senza alcuna modifica. Utilizzando la compilazione verbatim, è possibile specificare che un intero circuito sia conservato con precisione (supportato daRigettieOQC) come specificato o che solo parti specifiche di esso siano conservate (supportate daRigetti(solo). Quando si sviluppano algoritmi per il benchmarking hardware o i protocolli di mitigazione degli errori, è necessario essere in grado di specificare i cancelli e i layout dei circuiti che devono essere eseguiti esattamente sull'hardware. La compilazione verbatim ti dà il controllo diretto sul processo di compilazione disabilitando alcuni passaggi di ottimizzazione, garantendo così che i tuoi circuiti vengano eseguiti esattamente come progettato.

La compilazione Verbatim è attualmente supportataRigettieOxford Quantum Circuits(OQC) dispositivi e richiede l'uso di cancelli nativi. Quando si utilizza la compilazione verbatim, è consigliabile verificare la topologia del dispositivo per assicurarsi che i cancelli siano chiamati collegatiqubitse che il circuito utilizza i cancelli nativi supportati sull'hardware. Nell'esempio seguente viene illustrato come accedere a livello di programmazione all'elenco di gate nativi supportati da un dispositivo.

rigetti.properties.paradigm.nativeGateSet

PerRigetti,qubitil ricablaggio deve essere disabilitato impostandodisableQubitRewiring=Trueda utilizzare con compilation verbatim. SedisableQubitRewiring=Falseè impostato quando si utilizzano caselle verbatim in una compilation, il circuito quantistico non riesce a convalidare e non viene eseguito.

Se la compilazione verbatim è abilitata per un circuito e viene eseguita su un QPU che non lo supporta, viene generato un errore che indica che un'operazione non supportata ha causato il fallimento dell'attività. Poiché più hardware quantistico supportano nativamente le funzioni del compilatore, questa funzionalità verrà ampliata per includere questi dispositivi. I dispositivi che supportano la compilazione verbatim lo includono come operazione supportata quando vengono interrogati con il seguente codice.

from braket.aws import AwsDevice from braket.device_schema.device_action_properties import DeviceActionType device = AwsDevice("arn:aws:braket:::device/qpu/rigetti/Aspen-11") device.properties.action[DeviceActionType.JAQCD].supportedOperations

Non sono previsti costi aggiuntivi associati all'utilizzo della compilazione verbatim. Continuano a essere addebitati costi per attività eseguiteBraketDispositivi QPU, istanze notebook e simulatori on demand in base alle velocità correnti come specificato nellaPrezzi di Amazon Braket(Certificato creato). Per ulteriori informazioni, consulta la .Compilazione verbatimnotebook di esempio.

Nota

Se si utilizza OpenQASM per scrivere i circuiti perOQCdispositivo, e si desidera mappare il circuito direttamente ai qubit fisici, è necessario utilizzare il#pragma braket verbatimcome ildisableQubitRewiringflag è completamente ignorato da OpenQASM.

simulazione di rumore

Per creare un'istanza del simulatore di rumore locale è possibile modificare il backend come segue.

device = LocalSimulator(backend="braket_dm")

È possibile costruire circuiti rumorosi in due modi: (i) Costruire il circuito rumoroso dal basso verso l'alto. (ii) Prendere un circuito esistente, privo di rumore e iniettare rumore in tutto. L'esempio seguente mostra gli approcci utilizzando un circuito semplice con rumore depolarizzante e un canale Kraus personalizzato.

# 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)

L'esecuzione di un circuito è la stessa esperienza utente di prima, come mostrato negli esempi seguenti.

task = device.run(circ, s3_location)

Oppure

task = device.run(circ_noise, s3_location)

Per ulteriori esempi, consultal'esempio introduttivo del simulatore di rumore Braket