Skip to main content
IBM Quantum Platform

Note di rilascio di Qiskit SDK 2.1


2.1.2

Preludio

Qiskit 2.1.2 è una piccola patch che corregge alcuni bug riscontrati nella serie 2.1.

Correzioni di bug

  • In Qiskit 2.1.0 il VF2PostLayout è stato aggiunto allo stadio optimization del gestore dei passaggi preimpostati quando optimization_level=3. Tuttavia, l'uscita del pass non è mai stata applicata al circuito. Questa versione rimuove il passaggio dallo stadio optimization del gestore dei passaggi preimpostati per risparmiare i costi di esecuzione. In Qiskit 2.2.0 il passaggio sarà parte dello stadio optimization e l'uscita sarà applicata se il passaggio trova un layout migliore.

  • È stato risolto un problema nel passaggio VF2Layout in cui, anche con un set di semi fisso, l'output del passaggio era potenzialmente non deterministico; in particolare se il circuito di ingresso aveva qubit attivi che contenevano solo operazioni a qubit singolo. Corretto #14729

  • Corretto un bug in PassManager.run() in cui la funzione callback non veniva invocata quando si eseguivano circuiti multipli. Il callback viene ora attivato correttamente per ogni passaggio su ogni circuito, anche nell'esecuzione parallela.

  • I passaggi di transpiler incorporati che impostano la proprietà final_layout ora gestiscono correttamente l'aggiornamento di questo campo se era già impostato. Questo può essere osservato come il metodo TranspileLayout.routing_permutation restituisce ora una permutazione corretta dopo aver eseguito più di un passaggio che imposta final_layout.

    Questo non ha influito sulle normali chiamate a transpile() o generate_preset_pass_manager() utilizzando i plugin integrati di Qiskit; nessuna pipeline costruita in questa forma tenterebbe di impostare final_layout più di una volta.

  • È stato corretto un bug in Target.instruction_supported() in cui il controllo dell'ordine dei qubit dell'istruzione veniva saltato quando il metodo veniva chiamato con gli argomenti operation_name e parameters che corrispondevano a un'istruzione esistente.

  • È stato corretto un bug di correttezza quando si esportano circuiti con istruzioni di ritardo utilizzando le unità di ps in QASM3.

  • Corretto un caso limite nella visualizzazione del QFT circuito. In precedenza, quando si chiamava QFT.inverse() e poi si modificavano gli attributi del circuito QFT, il nome del QFT veniva visualizzato come "IQFT_dg". Questo non era corretto e ora mostra correttamente "IQFT". Corretto #14758.

  • Corretta una perdita di memoria nel coordinamento dell'uso di qk_circuit_get_instruction e qk_circuit_instruction_clear.

  • Chiarito il messaggio di errore per le versioni non valide specificate in qpy.dump() per renderlo più facile da interpretare.

  • È stato risolto un problema con la funzione generate_preset_pass_manager() in cui la funzione ignorava erroneamente i dati relativi ai vincoli di temporizzazione contenuti nell'oggetto Target fornito quando l'argomento backend non era impostato. Corretto #14329

  • Corretto un bug in SparsePauliOp.simplify() in cui il metodo rimuoveva i termini Pauli in base alle grandezze dei loro coefficienti prima di combinare i duplicati. Ciò ha causato un comportamento errato in due casi limite fondamentali:

    1. Quando più termini di Pauli identici avevano coefficienti piccoli, singolarmente inferiori alla soglia di semplificazione, ma la cui somma superava la soglia, tali termini venivano erroneamente rimossi.
    2. Quando più termini di Pauli identici avevano coefficienti superiori alla soglia ma sommati quasi a zero, venivano erroneamente mantenuti.

    Vedere #14194 per maggiori dettagli.


2.1.1

Preludio

Qiskit 2.1.1 è una piccola patch che corregge alcuni bug riscontrati nella serie 2.1.

Correzioni di bug

  • Corretto un bug nel controllo di DAGOpNode in cui il confronto tra due oggetti DAGOpNode che contengono un'istruzione BoxOp istruzione. In precedenza, l'attributo BoxOp.unit non veniva considerato come parte del controllo di uguaglianza, il che poteva portare a valutare come uguali due nodi non uguali.

  • Corretto l'avviso di deprezzamento per Python 3.9 in modo che sia correttamente identificato come causato dal codice utente quando si importa Qiskit. In precedenza, non veniva identificato come causato dal codice utente e ciò significava che i filtri di avviso predefiniti di Python non mostravano l'avviso all'utente.

  • Corretto il comportamento dell'argomento max_trials per VF2Layout quando è impostato su None o su un numero negativo. È stato documentato che il passaggio limita la ricerca in base alla dimensione del circuito o dell'obiettivo se l'opzione è impostata su None e che accetta valori negativi per specificare una ricerca senza limiti. Tuttavia, in 2.1.0 questo comportamento è stato erroneamente modificato in modo che None eseguisse una ricerca senza limiti e l'uso di un numero negativo generasse un errore. Queste sviste sono state corrette in modo che il passaggio si comporti come documentato e sia coerente con le versioni precedenti.

  • Corretto un problema nei plugin di sintesi ad alto livello MCXSynthesis1DirtyKG24 e MCXSynthesis2DirtyKG24 per MCXGatein cui i plugin non consideravano i qubit ausiliari puliti disponibili come qubit ausiliari sporchi disponibili. In particolare, il plugin MCXSynthesis2DirtyKG24 non si applica quando sono disponibili un qubit ausiliario pulito e uno sporco.

  • Corretta una regressione delle prestazioni quando si costruisce in modo incrementale ParameterExpression combinando un gran numero di sottoespressioni. Corretto #14653


2.1.0

Preludio

La release di Qiskit v2.1 introduce diversi importanti miglioramenti in aree chiave, tra cui l'API C, le funzionalità del transpiler e l'usabilità dei circuiti quantistici. Inoltre, include molti miglioramenti generali e correzioni di bug. I punti salienti includono:

  • Estensioni dell'API C: Sulla base del lavoro iniziato nella versione precedente, Qiskit v2.1 aggiunge il supporto per la creazione e l'interazione con i circuiti quantistici tramite funzioni API C, supportando l'aggiunta di porte standard, istruzioni standard e porte unitarie. In questa versione è stato aggiunto anche un insieme di funzioni C per costruire e manipolare un oggetto Target in preparazione al supporto di un flusso di lavoro completo di transpilazione basato su API C nella prossima versione. Inoltre, QkComplex64 è ora definito come una struct, che serve a rappresentare in modo indipendente dal compilatore i numeri complessi quando si lavora con l'API C di Qiskit. Anche il file di intestazione dell'API C è stato aggiornato in modo che sia generalmente compatibile con l'uso nativo in C++.
  • Supporto del set di basi Clifford+T: Il transpiling dei circuiti per un target con porte Clifford+T è ora supportato immediatamente. Se l'insieme di basi è costituito solo da porte Clifford+T, Qiskit assicura che i passaggi appropriati per la gestione di queste porte siano aggiunti ai gestori di passaggi preimpostati. Si tratta di un primo passo verso il supporto della transpilazione per i backend a tolleranza di errore.
  • Miglioramenti a BoxOp: Questa versione aggiunge la possibilità di allegare annotazioni personalizzate alle istruzioni BoxOp alle istruzioni, supportando ulteriormente il concetto di box statement di OpenQASM 3 in Qiskit. Questo include anche la serializzazione delle annotazioni nei formati QASM e QPY. Inoltre, è stato aggiunto il supporto per l'uso della durata del tratto nelle caselle.
  • Python 3.9 deprecazione: Python 3.9 è deprecato a partire da Qiskit v2.1 e non sarà più supportato in Qiskit v2.3.

Per maggiori dettagli su quanto sopra e molto altro, consultate le note di rilascio qui sotto e la documentazione aggiornata.

Funzionalità API C

  • L' API Qiskit C ( qiskit.h ) ora supporta la costruzione e l'interazione con i circuiti quantistici. L'API dei circuiti C è incentrata sul tipo opaco QkCircuit che rappresenta il circuito. Il tipo QkCircuit consente di costruire un circuito con qualsiasi elemento di circuito definito in modo nativo nel modello di dati Rust interno di Qiskit per QuantumCircuit. Attualmente comprende cancelli standard, Measure, Delay, Reset, Barrier, e UnitaryGate. Le funzionalità dell'API C dei circuiti si amplieranno nelle prossime versioni, man mano che il modello di dati di Qiskit verrà aggiunto in modo nativo al modello di dati interno di Rust, consentendo di utilizzarlo nell'API C.

    Ad esempio, è possibile utilizzare l'API C per costruire uno stato GHZ a 1000 qubit:

    #include <qiskit.h>
    
    int main() {
        // Create an empty circuit with 1000 qubits and 1000 clbits
        QkCircuit *qc = qk_circuit_new(1000, 1000);
    
        // Add a Hadamard Gate on Qubit 0
        uint32_t one_qubit[1] = {0,};
        qk_circuit_gate(qc, QkGate_H, one_qubit, NULL); // The NULL pointer is for the parameter array.
                                                        // Since Hadamard doesn't have parameters it
                                                        // is never accessed.
    
        // Add the CX Gates:
        uint32_t qubits[2] = {0, 0};
        uint32_t num_qubits = qk_circuit_num_qubits(qc);
        for (int i = 1; i<num_qubits; i++) {
            qubits[1] = i;
            qk_circuit_gate(qc, QkGate_CX, qubits, NULL);
        }
    
        // Add the measurements:
        uint32_t num_clbits = qk_circuit_num_clbits(qc);
    
        for (uint32_t i = 0; i<num_clbits; i++) {
            qk_circuit_measure(qc, i, i);
        }
        qk_circuit_free(qc);
        return 0;
    }
  • L' API di Qiskit C ( qiskit.h ) ora supporta la costruzione di un oggetto Target per rappresentare un obiettivo di transpilazione. Ad esempio:

    #include <qiskit.h>
    #include <math.h>
    
    int main() {
        // Create a Target with 3 qubits
        QkTarget *target = qk_target_new(3);
    
        // Create a Target Entry for a CX Gate
        QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
        // Define properties for CX between qubits (0, 1) with a duration of 1.93e-9 sec and error rate 3.17e-10.
        uint32_t qargs[2] = {0, 1};
        qk_target_entry_add_property(cx_entry, qargs, 2, 1.93e-9, 3.17e-10);
        // Define properties for cx between qubits (1, 0) with a duration of 1.27e-9 sec and no error.
        uint32_t rev_qargs[2] = {1, 2};
        qk_target_entry_add_property(cx_entry, rev_qargs, 2, 1.27e-9, NAN);
        // Add the cx entry to the target.
        QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
        // Add global ideal Y gate entry to the target
        QkExitCode result_y = qk_target_add_instruction(target, qk_target_entry_new(QkGate_Y));
        // Create a Target entry for a Measurement with increasing duration and error as the qubit indices increase
        QkTargetEntry *measure = qk_target_entry_new_measure();
        for (uint32_t i = 0; i< qk_target_num_qubits(target); i++) {
            uint32_t q[1] = {i};
            qk_target_entry_add_property(measure, q, 1, 1e-6 * (i + 1), 1e-3 * (i + 1));
        }
        QkExitCode result_measure = qk_target_add_instruction(target, measure);
        return 0;
    }
    
  • È stato aggiunto il supporto per l'interrogazione delle informazioni sulla versione di Qiskit dall'API C utilizzando le seguenti macro:

    • QISKIT_VERSION_MAJOR contiene il numero di versione principale.
    • QISKIT_VERSION_MINOR contiene il numero di versione minore.
    • QISKIT_VERSION_PATCH contiene il numero di versione della patch.
    • QISKIT_VERSION contiene una rappresentazione numerica delle informazioni sulla versione, che può essere utilizzata per i confronti.
    • QISKIT_VERSION_NUMERIC(M,m,p) : macro simile a una funzione che restituisce la versione " M.m.p " come valore numerico, utilizzabile per i confronti.

    Ad esempio, per verificare se la versione corrente è almeno 2.1.0, si può usare:

    if (QISKIT_VERSION >= QISKIT_VERSION_NUMERIC(2, 1, 0)) {
        // Code for version 2.1.0 or later
    }
  • Abilitata la compatibilità con il C++ per l'API C. L'intestazione generata consente ora di chiamare direttamente oggetti e funzioni dal C++. Per esempio, un'osservabile a 100 qubit con il termine XYZ sui primi 3 qubit può essere costruita come

    #include <iostream>
    #include <complex>
    #include <vector>
    #include <qiskit.h>
    
    int main() {
        uint32_t num_qubits = 100;
    
        // Use smart pointer with custom deleter to manage QkObs memory
        QkObs *obs = qk_obs_zero(num_qubits);
    
        // Construct the observable term
        std::complex<double> coeff_complex = 2.0;
        QkComplex64 coeff = qk_complex64_from_native(coeff_complex);
        std::vector<QkBitTerm> bit_terms = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
        std::vector<uint32_t> indices = {0, 1, 2};
    
        QkObsTerm term {
            .coeff      = coeff,
            .len        = bit_terms.size(),
            .bit_terms  = bit_terms.data(),
            .indices    = indices.data(),
            .num_qubits = num_qubits
        };
    
        qk_obs_add_term(obs.get(), &term);
    
        // Print observable properties
        std::cout << "num_qubits: " << qk_obs_num_qubits(obs) << "\n";
        std::cout << "num_terms: "  << qk_obs_num_terms(obs)  << "\n";
    
        qk_obs_free(obs);
        return 0;
    }

Caratteristiche dei circuiti

  • Aggiunta una funzione random_circuit_from_graph() che genera un circuito casuale che induce lo stesso grafo di interazione specificato da interaction_graph.

    La probabilità di estrarre casualmente un bordo dal grafo di interazione come porta a due qubit può essere impostata dall'utente nell'attributo del peso di un bordo nel grafo di interazione in ingresso. Se l'utente non imposta la probabilità, ogni bordo viene disegnato in modo uniforme. Cioè, ogni porta a due equbit rappresentata da un bordo nel grafo di interazione ha la stessa probabilità di essere aggiunta al circuito casuale. Se viene impostato solo un sottoinsieme di probabilità dei bordi, verrà sollevato ValueError .

    In questo esempio, cp_map è un elenco di bordi con pesi arbitrari.

    from qiskit.circuit.random.utils import random_circuit_from_graph
    import rustworkx as rx
    pydi_graph = rx.PyDiGraph()
    n_q = 5
    cp_map = [(0, 1, 0.18), (1, 2, 0.15), (2, 3, 0.15), (3, 4, 0.22)]
    pydi_graph.extend_from_weighted_edge_list(cp_map)
    # cp_map can be passed in directly as interaction_graph
    qc = random_circuit_from_graph(interaction_graph = pydi_graph,
      min_2q_gate_per_edge = 1,
      max_operands = 2,
      measure = True,
      conditional = True,
      reset = True,
      seed = 0,
      insert_1q_oper = True,
      prob_conditional = 0.21,
      prob_reset = 0.1)
    qc.draw(output='mpl')
    _images/release_notes-1.png
  • Aggiunto un nuovo QuantumCircuit metodo: QuantumCircuit.has_control_flow_op() per verificare se un QuantumCircuit contiene operazioni sul flusso di controllo.

  • Un nuovo modulo qiskit.circuit.annotation e l'oggetto principio Annotation sono stati aggiunti.

    Le annotazioni sono un modo per etichettare le istruzioni (al momento solo BoxOp) con dati locali e personalizzati dall'utente. Questi dati sono destinati a essere consumati da passaggi di transpiler personalizzati. Le annotazioni forniscono un modo per allegare i dati a istruzioni specifiche, invece di utilizzare l'oggetto contesto globale PropertySet durante la compilazione.

    Tutti gli Annotation hanno un campo namespace . Questa chiave stringa è usata per le ricerche, in modo che i consumatori possano sapere se gestiscono o meno una particolare annotazione. Attualmente non esistono metodi per interrogare la semantica astratta di una sottoclasse Annotation ma si prevede che questi metodi saranno ampliati in futuro.

    Per una discussione completa delle funzionalità e dei casi d'uso, vedere qiskit.circuit.annotation per una discussione completa delle funzionalità e dei casi d'uso.

  • BoxOp (create da QuantumCircuit.box()) possono ora essere annotate con istanze Annotation istanze personalizzate. L'uguaglianza di due caselle dipende dall'uguaglianza delle annotazioni.

    In genere, questo si ottiene passando un elenco di annotazioni come unico argomento posizionale quando si usa QuantumCircuit.box() nella forma di gestore di contesto:

    from qiskit.circuit import annotation, QuantumCircuit
    
    class MyAnnotation(annotation.Annotation):
        namespace = "my.annotation"
    
        def __eq__(self, other):
            return isinstance(other, MyAnnotation)
    
    qc = QuantumCircuit()
    with qc.box([MyAnnotation()]):
        pass
  • Il metodo UnitaryGate.control() utilizza internamente il metodo qs_decomposition() invece di Isometry per la decomposizione utilizzata per definire il controllo UnitaryGate. Questa modifica riduce il numero di CXGate utilizzati nel file definition per i risultati restituiti ControlledGate di circa 2x.

  • Miglioramento della sintesi di un sistema multicontrollato U1Gatein modo che non cresca esponenzialmente con il numero di controlli.

  • L'attributo BoxOp.duration può ora essere un expr.Expr con tipo Duration, proprio come Delay.duration. Questo include anche il supporto Stretch per la durata di un BoxOp.

Caratteristiche primitive

OpenQASM Caratteristiche

  • qasm3.dump() e qasm3.dumps() hanno un nuovo argomento annotation_handlers , utilizzato per fornire istanze di annotation.OpenQASM3Serializer al processo di esportazione di OpenQASM 3, che può serializzare oggetti personalizzati Annotation in OpenQASM 3.

  • Quando è installato qiskit_qasm3_import>=0.6.0 , qasm3.load() e qasm3.loads() hanno un nuovo argomento annotation_handlers , che viene utilizzato per fornire istanze di annotation.OpenQASM3Serializer al processo di importazione di OpenQASM 3, che può deserializzare gli oggetti personalizzati di Annotation da OpenQASM 3. Questo supporto è attualmente limitato alle dichiarazioni box , poiché questo è l'unico posto in cui Qiskit può rappresentare le annotazioni nel suo modello di dati.

Caratteristiche QPY

  • Aggiunta di un nuovo formato QPY versione 15 che include il supporto per i nuovi oggetti Annotation con il supporto di serializzatori e deserializzatori esterni. Il formato consente a tali serializzatori di essere statici e nel formato binario sono allocati posti sicuri per gli oggetti di stato e le rappresentazioni di annotazioni personalizzate.

  • qpy.dump() e qpy.load() hanno ora un argomento opzionale annotation_factories , che viene utilizzato per fornire funzioni di costruzione di oggetti annotation.QPYSerializer oggetti per gestire Annotation sottoclassi. Questi devono essere forniti dall'utente, in modo simile a metadata_serializer, poiché in generale Qiskit non può conoscere tutti i possibili oggetti definiti dall'esterno Annotation definiti dall'esterno.

  • Aggiunta di una nuova funzione get_qpy_version() al modulo qpy modulo. Questa funzione ispeziona un file QPY e recupera la versione del formato QPY utilizzata nel payload. La versione viene restituita come numero intero, che può essere utilizzato per scopi di registrazione o debug. vedere #14201.

Caratteristiche dell'informazione quantistica

  • È stata aggiunta una nuova classe, PauliLindbladMapche è una parametrizzazione basata su Pauli di un sottoinsieme di mappe lineari di operatori multi-qubit, utilizzate in applicazioni di apprendimento del rumore. Questa classe dovrebbe costituire la spina dorsale di algoritmi di apprendimento del rumore migliorati e fornire un controllo migliore e più efficiente sui modelli di rumore nelle future versioni di Qiskit.

  • Introdotto il QubitSparsePauli e QubitSparsePauliList che rappresentano gli stessi concetti di Pauli e PauliList rispettivamente, ma memorizzano solo termini non identici, in modo analogo a SparseObservable. Queste classi sono destinate principalmente a essere utilizzate con il nuovo PauliLindbladMap.

Caratteristiche della sintesi

  • Aggiunto un nuovo algoritmo di sintesi per HalfAdderGate che non richiede qubit ausiliari e ha un miglior numero di CX rispetto a adder_qft_d00():

  • Aggiunte nuove scomposizioni per MCXGate l'utilizzo di ancille pulite, migliorando la profondità e l'efficienza del circuito:

    Utilizzo di esempio:

    from qiskit.synthesis.multi_controlled import synth_mcx_1_clean_kg24
    
    n_ctrls = 10
    qc = synth_mcx_1_clean_kg24(n_ctrls)
    qc.draw()
  • La sintesi di porte multicontrollate CZGate è stata migliorata per ridurre il numero di porte sintetizzate; in alcuni casi è possibile una riduzione fino al 99%. Questo risultato è stato ottenuto sfruttando la sintesi migliorata intorno alla MCXGate con una sintesi controllata CZGate sintesi controllata.

  • Migliorato il plugin predefinito per la sintetizzazione di AnnotatedOperation oggetti. Il miglioramento è particolarmente utile quando si creano e si traspongono circuiti controllati con porte controllate al loro interno. Ad esempio:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import CXGate
    from qiskit.compiler import transpile
    
    inner = QuantumCircuit(5)
    inner.append(CXGate().control(3, annotated=True), [0, 1, 2, 3, 4])
    controlled_inner_gate = inner.to_gate().control(2, annotated=True)
    qc = QuantumCircuit(15)
    qc.append(controlled_inner_gate, [0, 1, 2, 3, 4, 5, 6])
    qct = transpile(qc, basis_gates=["cx", "u"])

    Questo codice crea un circuito quantistico qc che contiene un circuito quantistico a 2 controlli con una porta CX a 3 controlli. Con questo miglioramento, il numero di porte CX nel circuito transpilato si riduce da 378 a 30. Si noti che specificando annotated=True quando si definisce la logica di controllo, le porte controllate vengono create come operazioni annotate. In questo modo si evita una sintesi avida, si permette al transpiler di rilevare che controlled_inner_gate è equivalente a una porta X a 6 controlli e di scegliere il miglior metodo di sintesi disponibile per le porte X a più controlli, in particolare utilizzando i qubit ancilla disponibili.

  • La funzione adder_qft_d00(), utilizzata per sintetizzare ModularAdderGate e HalfAdderGate accetta ora un parametro aggiuntivo annotated. Se True, l'inverse-QFT-gate all'interno degli adders è implementato come un'operazione annotata, consentendo al transpiler di applicare ulteriori ottimizzazioni.

  • La decomposizione quantistica di Shannon (qs_decomposition()) include ora un'ottimizzazione che riduce il numero di CXGate nel caso in cui l'unitario di ingresso sia un unitario controllato.

  • La funzione di sintesi synth_mcx_1_clean_b95() produce ora un circuito con meno porte CX.

  • La classe SolovayKitaevDecomposition ha ora degli argomenti aggiuntivi nell'inizializzatore, che permettono di costruirla direttamente da un insieme di basis_gates e da un depth per le approssimazioni di base.

  • Aggiunto SolovayKitaevDecomposition.save_basic_approximations() per salvare l'insieme delle approssimazioni di base utilizzate dalla classe in un formato binario. Questa modifica, in combinazione con i nuovi argomenti dell'inizializzatore, consente agli utenti di evitare l'uso esplicito di generate_basic_approximations() e affidarsi solo a SolovayKitaevDecomposition.

Funzionalità del transpiler

  • La funzione generate_preset_pass_manager() genera ora uno speciale gestore di passaggi quando l'insieme di basi consiste solo di porte Clifford+T. Formalmente, un insieme di basi Clifford+T deve contenere solo porte Clifford, con o TGate, TdgGate, o entrambi. L'elenco completo delle porte di Clifford supportate può essere ottenuto utilizzando get_clifford_gate_names().

    Ad esempio:

    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    from qiskit.quantum_info import get_clifford_gate_names
    
    basis_gates = get_clifford_gate_names() + ["t", "tdg"]
    pm = generate_preset_pass_manager(basis_gates=basis_gates)
    
    qc = QuantumCircuit(1)
    qc.rx(0.8, 0)
    qct = pm.run(qc)
    print(qct.count_ops())

    Risulterebbe con:

    OrderedDict([('h', 10210), ('t', 4508), ('tdg', 4503), ('sdg', 943), ('s', 941)])

    In precedenza, il gestore dei passaggi generati non era in grado di gestire l'esempio precedente perché non riusciva a decomporre le porte di rotazione a singolo-qubit UGate di rotazione a singolo qubit in porte Clifford+T. Tuttavia, il nuovo gestore del passaggio utilizza la decomposizione di Solovay-Kitaev per approssimare le porte di rotazione a singolo qubit utilizzando le porte H, T e Tdg , e chiama il passaggio transpiler per tradurre ulteriormente le porte nell'insieme di basi di destinazione BasisTranslator per tradurre ulteriormente le porte nell'insieme di basi di destinazione. Il nuovo gestore di passaggi presenta anche altre modifiche per consentire una traduzione più efficiente in porte Clifford+T.

    È importante notare che l'insieme di basi di Clifford+T specificato deve essere universale, altrimenti la trasposizione potrebbe non riuscire. Sebbene l'insieme di porte ["h", "t", "tdg"] o anche ["h", "t"] sia sufficiente per l'universalità, si raccomanda di aggiungere altre porte di Clifford all'insieme, se possibile, perché altrimenti la traduzione potrebbe essere meno efficiente. Ad esempio, se la porta S non è inclusa, le porte S potrebbero essere decomposte in coppie di porte T (cioè, le porte Clifford potrebbero essere decomposte in porte non Clifford, il che potrebbe non essere il comportamento desiderato).

    Segue un esempio leggermente più grande:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import QFTGate
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    
    qc = QuantumCircuit(4)
    qc.append(QFTGate(4), [0, 1, 2, 3])
    
    basis_gates = ["cx", "s", "sdg", "h", "t", "tdg"]
    pm = generate_preset_pass_manager(basis_gates=basis_gates, optimization_level=2)
    
    qc = QuantumCircuit(4)
    qc.append(QFTGate(4), [0, 1, 2, 3])
    
    qct = pm.run(qc)
    print(qct.count_ops())

    Risulterebbe con:

    OrderedDict([('h', 96510), ('tdg', 42396), ('t', 42389), ('s', 8240), ('sdg', 8235), ('cx', 12)])
  • Aggiunto un nuovo plugin di sintesi ad alto livello HalfAdderSynthesisR25 per sintetizzare un file HalfAdderGate. Il nuovo plugin si basa su adder_ripple_r25().

    L'aggiornamento è stato fatto anche per seguire la seguente sequenza di sintetizzatori half-adder HalfAdderSynthesisDefault è stata aggiornata per seguire la seguente sequenza di sintetizzatori di half-adder: "HalfAdder.ripple_r25" quando ci sono 3\leq 3 qubit, "HalfAdder.ripple_c04" quando è disponibile un qubit ausiliario e "HalfAdder.ripple_r25" in tutti i casi restanti.

  • Sono stati aggiunti più plugin di sintesi ad alto livello per sintetizzare una MCXGate:

    La classe MCXSynthesisDefault è stata aggiornata per eseguire la seguente sequenza di metodi di sintesi MCX finché il primo non ha successo: : "mcx.2_clean_kg24", "mcx.1_clean_kg24", "mcx.n_clean_m15", "mcx.n_dirty_i15"`, ``"mcx.2_dirty_kg24", "mcx.1_dirty_kg24", "mcx.1_clean_b95", "mcx.noaux_v24". I metodi sono ordinati in modo da applicare per primi quelli di migliore qualità.

  • VF2PostLayout è stato aggiunto alla fine della fase di ottimizzazione predefinita, quando si utilizza il livello di ottimizzazione 3.

  • Aggiunto un nuovo OptimizeCliffordT che unisce coppie di porte T consecutive in porte S e coppie di porte Tdg consecutive in porte Sdg. Questa ottimizzazione è particolarmente efficace per ridurre il numero di T in seguito alla decomposizione di Solovay-Kitaev, che produce più porte T o Tdg consecutive. Ad esempio:

    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler.passes import SolovayKitaev, OptimizeCliffordT
    
    qc = QuantumCircuit(1)
    qc.rx(0.8, 0)
    
    # Run Solovay-Kitaev pass on qc
    transpiled = SolovayKitaev()(qc)
    print(transpiled.count_ops().get("t", 0) + transpiled.count_ops().get("tdg", 0))
    # Should print 12779
    
    # Run Clifford+T optimization
    optimized = OptimizeCliffordT()(transpiled)
    print(optimized.count_ops().get("t", 0) + optimized.count_ops().get("tdg", 0))
    # Should print 9011
  • È stato aggiunto il ContextAwareDynamicalDecoupling che implementa un disaccoppiamento dinamico consapevole del contesto basato su sequenze Walsh-Hadamard. Le sequenze di ritardo inserite saranno reciprocamente ortogonali alle sequenze sui qubit vicini e terranno conto degli spettatori di controllo/target delle porte CX ed ECR. Vedere arXiv:2403.06852 per ulteriori informazioni.

    Esempio:

    from qiskit.circuit.library import QFT
    from qiskit.transpiler import PassManager, CouplingMap
    from qiskit.transpiler.passes import ALAPScheduleAnalysis, ContextAwareDynamicalDecoupling
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    from qiskit.providers.fake_provider import GenericBackendV2
    
    num_qubits = 10
    circuit = QFT(num_qubits)
    circuit.measure_all()
    
    target = GenericBackendV2(
        100,
        basis_gates=["id", "rz", "sx", "x", "ecr"],
        coupling_map=CouplingMap.from_grid(10, 10)
    ).target
    
    pm = generate_preset_pass_manager(optimization_level=2, target=target)
    dd = PassManager([
        ALAPScheduleAnalysis(target=target),
        ContextAwareDynamicalDecoupling(target=target),
    ])
    
    transpiled = pm.run(circuit)
    with_dd = dd.run(transpiled)
    
    with_dd.draw("mpl", idle_wires=False)
    _images/release_notes-2.png
  • Aggiunti i seguenti attributi alla classe DAGCircuit per consentire l'interrogazione del numero di variabili di stiramento: num_stretches, num_captured_stretches e num_declared_stretches.

  • Aggiunto un nuovo plugin per la sintesi unitaria CliffordUnitarySynthesis che tenta di sintetizzare una data porta unitaria verificando se può essere rappresentata da una Clifford, nel qual caso restituisce un circuito che implementa questa unità e che consiste solo di porte Clifford.

    Il plugin viene invocato dal passaggio UnitarySynthesis quando il parametro method è impostato su "clifford".

    Inoltre, il parametro plugin_config di UnitarySynthesis può essere usato per passare i seguenti parametri specifici del plugin:

    • min_qubit: il numero minimo di qubit da considerare (il valore predefinito è 1).
    • max_qubit: il numero massimo di qubit da considerare (il valore predefinito è 3).

    Ad esempio:

    import math
    
    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import UnitaryGate
    from qiskit.quantum_info import Operator
    from qiskit.transpiler.passes import UnitarySynthesis
    
    # clifford unitary over 2 qubits
    c2 = QuantumCircuit(2)
    c2.h(0)
    c2.rz(math.pi / 4, 1)
    c2.rz(math.pi / 4, 1)
    c2.sdg(1)
    uc2 = UnitaryGate(Operator(c2).data)
    
    # non-clifford unitary over 2 qubits
    n2 = QuantumCircuit(2)
    n2.h(0)
    n2.rz(math.pi / 4, 1)
    n2.sdg(1)
    un2 = UnitaryGate(Operator(n2).data)
    
    # quantum circuit with two unitary gates
    qc = QuantumCircuit(3)
    qc.append(uc2, [2, 1])
    qc.append(un2, [0, 2])
    
    transpiled = UnitarySynthesis(method="clifford")(qc)
    transpiled.draw("mpl")
    _images/release_notes-3.png

    L'esecuzione del codice sopra riportato risintetizza la prima porta unitaria in porte Clifford, mentre la seconda porta rimane invariata.

    Se modifichiamo l'esempio precedente come segue:

    config = {"min_qubits": 3}
    transpiled = UnitarySynthesis(method="clifford", plugin_config=config)(qc)

    allora entrambe le porte unitarie rimangono invariate.

Funzionalità di visualizzazione

  • Introdotti stili personalizzati per la funzione dag_drawer() funzione. Ciò consente di passare un dizionario al parametro style con attributi personalizzati che modificano lo stile del DAG restituito dalla funzione. Ad esempio:

    from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
    from qiskit.converters import circuit_to_dag
    from qiskit.visualization import dag_drawer
    
    q = QuantumRegister(3, 'q')
    c = ClassicalRegister(3, 'c')
    circ = QuantumCircuit(q, c)
    circ.h(q[0])
    circ.cx(q[0], q[1])
    circ.measure(q[0], c[0])
    circ.rz(0.5, q[1]).c_if(c, 2)
    
    dag = circuit_to_dag(circ)
    
    style = {
        "inputnodecolor": "pink",
        "outputnodecolor": "lightblue",
        "opnodecolor": "red",
    }
    
    dag_drawer(dag, style=style)

Note sull'aggiornamento

  • La libreria python-dateutil non è più una dipendenza di Qiskit. Da quando Qiskit v2.0 nulla della libreria utilizzava python-dateutil e Qiskit non dipendeva più dalla libreria. Questa versione lo rimuove dall'elenco delle dipendenze, in modo che non venga installato automaticamente come prerequisito per utilizzare Qiskit. Se ci si affidava a Qiskit per l'installazione di dateutil come dipendenza, ora è necessario assicurarsi di installarlo manualmente (è la prassi migliore per le dipendenze dirette).

  • sympy non è più un requisito per l'installazione di Qiskit. Dopo la migrazione a un motore simbolico basato su Rust per la classe ParameterExpression l'uso di SymPy è stato isolato ad alcune utilità di visualizzazione, al TemplateOptimization transpiler pass, ParameterExpression.sympify() (che è esplicitamente per l'interoperabilità di SymPy ) e SparsePauliOp.simplify() se si usano coefficienti parametrizzati. Questa funzionalità non è la più comunemente usata, quindi SymPy è ora trattato come una dipendenza opzionale e queste funzioni solleveranno un'eccezione se vengono usate e non è installato MissingOptionalLibraryError se vengono utilizzate e SymPy non è installato.

  • La dipendenza da symengine , utilizzata per la costruzione di oggetti ParameterExpression è stata rimossa. È stato sostituito da un motore simbolico interno e non è più necessario per le funzionalità principali di Qiskit. L'unica eccezione è che symengine è stato incorporato nei formati QPY 10, 11 e 12, quindi è ancora necessario se si deserializzano questi formati. La dipendenza da symengine per qpy.load() è stata resa esplicitamente facoltativa in 2.0.0, ma se in precedenza si faceva affidamento sul fatto che symengine fosse installato di default per questa funzionalità, ora sarà necessario installarlo manualmente per caricare il payload. Se si usasse ParameterExpression.sympify() per ottenere un oggetto espressione symengine da un oggetto ParameterExpression ora restituirà un'espressione sympy . Se si ha bisogno di usarlo con symengine, si può sfruttare symengine.sympify per convertire l'espressione sympy in una espressione symengine.

Note sull'aggiornamento dei circuiti

  • L'attributo definition dell'attributo HalfAdderGate è stato modificato per utilizzare internamente adder_ripple_r25() per generare la definizione del gate per un circuito più efficiente senza qubit ausiliari. Se per qualche motivo si desidera la vecchia definizione, è possibile utilizzare direttamente la funzione adder_qft_d00() che genererà un circuito equivalente a quello che definition nelle versioni precedenti.

  • Il circuito restituito dalla funzione excitation_preserving() e dalla classe ExcitationPreserving sono ora costruiti utilizzando un singolo XXPlusYYGate. Questo è un cambiamento rispetto alle versioni precedenti che utilizzavano un carattere RXXGate seguito da un RYYGate. Questa nuova costruzione di circuito è equivalente, ma utilizza un numero inferiore di porte che sono tutte a conservazione dell'eccitazione, per definizione più semplici.

  • Gli definition di alcune porte standard sono stati aggiornati secondo i seguenti principi:

    • Quando è disponibile, una definizione che utilizza le porte di Clifford è preferita a quelle che includono porte non di Clifford.
    • Quando è disponibile, una definizione che utilizza le porte Clifford+T è preferibile a una che utilizza una porta Clifford UGate.
    • L'uso di PhaseGate è preferibile a U1Gate.
    • L'uso di UGate è preferibile a `U2Gate e `U3Gate.

    In particolare, il seguente invariante è ancora valido: espandendo ricorsivamente le definizioni delle porte, qualsiasi porta può essere espressa in ultima analisi utilizzando solo la base ["cx", "u"] . Le definizioni di tutte le porte standard sono tutte equivalenti, quindi non cambia la semantica delle porte, ma solo l'esatta costruzione del circuito restituita per alcune porte non è più esattamente la stessa. Questa modifica era necessaria per supportare la trasposizione Clifford+T.

  • Qiskit ora utilizza la propria libreria di espressioni simboliche basata su Rust per implementare gli interni di ParameterExpression e Parameter. Poiché si tratta di una nuova implementazione del motore matematico simbolico di base utilizzato per ParameterExpression potrebbero esserci piccole differenze nel comportamento esatto di alcune funzionalità. Dovrebbe sempre produrre risultati equivalenti per l'API documentata. Se si riscontrano problemi di correttezza, aprire un problema.

Note sull'aggiornamento dell'API C

  • Il modo in cui i numeri complessi sono esposti nell'API C di Qiskit è cambiato. In precedenza, QkComplex64 era un typedef dipendente dal compilatore che consentiva di passare tipi complessi nativi tramite puntatore all'API di Qiskit (ad esempio come double complex*). Pur essendo conveniente, questo approccio si basa implicitamente su ipotesi di layout di memoria che non sono strettamente garantite.

    Qiskit v2.1 espone ora QkComplex64 { double re; double im; } come struct, per garantire che la disposizione della memoria sia sempre compatibile e per un più ampio supporto del compilatore. Per comodità, vengono forniti i convertitori dipendenti dal compilatore qk_complex64_from_native e qk_complex64_to_native , che consentono di tradurre dalla struct a un numero complesso nativo. Si noti che questi funzionano solo su piattaforme che supportano double complex o per compilatori MSVC che utilizzano _Dcomplex.

    Ad esempio:

    #include <qiskit.h>
    #include <math.h>
    #include <stdio.h>
    #include <complex.h>
    
    int main(int argc, char *argv[]) {
        // platform-independent constructions:
        QkComplex64 coeff = {5.0, 3.0};
    
        // ... or using converter
        // double complex native = 5.0 + I * 3; // uses C11 standard, does not work on MSVC
        // QkComplex64 coeff = qk_complex64_from_native(&native);  // convert from native
    
        uint32_t num_qubits = 100;
        QkObs *obs = qk_obs_zero(num_qubits);
        QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
        uint32_t indices[3] = {0, 1, 2};
        QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};
        qk_obs_add_term(obs, &term);
        printf("num_qubits: %u\n", qk_obs_num_qubits(obs));
        printf("num_terms: %lu\n", qk_obs_num_terms(obs));
    
        qk_obs_free(obs);
        return 0;
    }

Note sull'aggiornamento QPY

  • La versione predefinita di QPY emessa da qpy.dump() è stata cambiata con l'ultima versione 15 di QPY. Se per qualche motivo è necessario generare una versione più vecchia del formato, si può usare l'argomento della parola chiave version su qpy.dump() per specificare una versione precedente da generare.

Note sull'aggiornamento della sintesi

  • Il formato di serializzazione per le approssimazioni di base negli algoritmi di Solovay-Kitaev è stato cambiato da .npy a un altro formato binario, basato su serde e bincode di Rust. Tutte le routine che caricano approssimazioni di base (come ad esempio generate_basic_approximations(), SolovayKitaevDecomposition.load_basic_approximations() o l'inizializzatore di SolovayKitaev) supportano ancora il caricamento del formato legacy. Ogni nuovo file, tuttavia, verrà memorizzato nel nuovo formato. Se ci si è affidati al vecchio formato, si deve eseguire il downgrade di Qiskit a 2.2 e memorizzare i file necessari.

  • I valori predefiniti per SolovayKitaev (e le classi correlate) sono aumentati a depth=12 e reps=5. Questo è dovuto al fatto che l'implementazione sottostante è ora in Rust, che ci permette di aumentare la precisione predefinita, pur rimanendo significativamente più veloce della precedente versione Python.

Note sull'aggiornamento del transpiler

  • I plugin di layout integrati per gli attuali gestori di passaggi non conterranno più il loro componente principale (ad esempio un'istanza per lo stadio "sciabola") se non vengono forniti vincoli di accoppiamento SabreLayout per il palco "sciabola" ) se non vengono forniti vincoli di accoppiamento. In precedenza, i plugin costruivano istanze non valide dei loro passaggi di layout, assumendo che la logica separata impedisse ai passaggi di essere eseguiti e di sollevare eccezioni.

    Questo non dovrebbe avere alcun effetto significativo sull'uso dei gestori di pass preimpostati o dei plugin, poiché non è mai stato valido chiamare i pass in uno stato non valido.

Note di deprecazione

  • Il supporto per l'esecuzione di Qiskit con Python 3.9 è stato deprecato e sarà rimosso nella versione di Qiskit v2.3. La versione 2.3.0 è il primo rilascio dopo che Python 3.9 ha terminato il suo ciclo di vita e non è più supportato [.] Ciò significa che a partire dalla versione 2.3.0 sarà necessario aggiornare la versione Python in uso a Python 3.9 o superiore.

    [1] https://devguide.python.org/versions/

Circuiti deprecati

Correzioni di bug

  • Corretto un bug nella funzione dag_drawer() e nel metodo DAGCircuit.draw() in cui l'impostazione dell'argomento della parola chiave style=plain non mostrava le etichette dei circuiti per i nodi del DAG nella visualizzazione.

  • Corretto un bug nel metodo QuantumCircuit.assign_parameters() in cui i parametri non utilizzati nel circuito e passati come stringhe non venivano ignorati quando l'argomento strict=False veniva impostato. Fare riferimento al problema #13933 per maggiori dettagli.

  • Corretto un caso limite nella configurazione di Makefile per Windows, in cui la variabile d'ambiente predefinita OS non corrispondeva all'output del comando uname -s .

  • È stato corretto l'attributo name dell'attributo OrGateche in precedenza era impostato erroneamente sulla stringa "and" invece che sul valore atteso "or" , che ora viene restituito. Questo valore errato "and" entrava in conflitto con il valore AndGate.name e avrebbe potuto portare a diversi problemi nell'utilizzo di Orgate e nella sua differenziazione da un file di tipo AndGate.

  • Corretto un bug nella funzione qpy.load() che poteva non riuscire a deserializzare circuiti i cui parametri erano stati riassegnati a parametri con gli stessi nomi. Corretti i punti #13720, #13720 e #13720.

  • Il campo GenericBackendV2 per includere ora BoxOp come tipo di istruzione supportata nella classe generata GenericBackendV2.target quando l'argomento chiave control_flow=True è impostato nel costruttore.

  • Quando si sintetizza un MCXGate gate con 3 controlli, la funzione di sintesi synth_mcx_n_dirty_i15() richiedeva un qubit ausiliario, producendo un circuito con 5 qubit (3 di controllo, 1 di destinazione e 1 ausiliario). Tuttavia, l'algoritmo di sintesi attuale non fa uso di questo qubit ausiliario. Questo comportamento è stato corretto: il circuito sintetizzato è di oltre 4 qubit (3 di controllo e 1 di destinazione), consentendo di applicare la funzione di sintesi in un numero leggermente maggiore di casi.

  • Il QuantumCircuit.draw() e circuit_drawer() renderà ora le istruzioni BoxOp in un'istruzione QuantumCircuit nella stessa fetta verticale, se gli intervalli verticali non si sovrappongono, vengono ora rese nella stessa fetta verticale, quando possibile.

  • Fissato il metodo QuantumCircuit.draw() e la funzione circuit_drawer() in modalità "mpl" per inserire meno spazio estraneo all'interno del bordo sinistro quando si disegnano BoxOp istanze in un file QuantumCircuit.

Altre note

  • Aggiunto un nuovo target opzionale di dipendenza extra qpy-compat. Questo target dovrebbe essere utilizzato se si intende caricare file qpy utilizzando i vecchi formati QPY. Il target installa i requisiti aggiuntivi utilizzati per caricare i file QPY utilizzando le versioni di formato < 13. If you are only using newer QPY format versions you do no need to install this. The qpy.dump() only generates QPY > =13 Questo è necessario solo per caricare i file generati con le versioni di Qiskit più vecchie (precedenti a 2.0.0 ) È possibile installare questa nuova variante opzionale con pip install qiskit[qpy-compat].

  • I pesi relativi delle componenti "base" e "lookahead" dei SabreSwap e SabreLayout sono stati modificati quando l'inseguimento a insiemi estesi è attivo (come lo è sempre in SabreLayouted è predefinito in SabreSwap). La componente euristica relativa alla distanza tra i qubit in un singolo gate nello strato anteriore ora non si indebolisce più in modo proporzionale al numero di gate nello strato anteriore; questo comportamento era una scelta storica, ma a circuiti di grandi dimensioni ha l'effetto accidentale di far sì che lo strato anteriore venga quasi ignorato, il che è disastroso per l'efficienza.

    I miglioramenti di routing che ne derivano dovrebbero essere più evidenti per i circuiti che possono essere spesso stratificati in strati di più di 20 porte parallele a due qubit.

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.