Skip to main content
IBM Quantum Platform

QkObs

typedef struct QkObs QkObs

Un'osservabile su basi di Pauli che memorizza i suoi dati in un formato qubit-sparse.


Matematica

Questa osservabile rappresenta una somma di stringhe degli operatori di Pauli e dei proiettori di autovalori di Pauli, con ogni termine ponderato per un numero complesso. Cioè, l'osservabile completo è

QkObs=icinAi(n)\text{\texttt{QkObs}} = \sum_i c_i \bigotimes_n A^{(n)}_i

per i numeri complessi cic_i e gli operatori single-qubit che agiscono sui qubit nn da un alfabeto ristretto Ai(n)A^{(n)}_i. La somma su ii è la somma dei singoli termini e il prodotto tensoriale produce le stringhe di operatori. L'alfabeto degli operatori a singolo bit consentiti da cui è tratto Ai(n)A^{(n)}_i è costituito dagli operatori di Pauli e dagli operatori di proiezione degli autostati di Pauli. Esplicitamente, questi sono:

Operatore
QkBitTerm
Valore numerico
II (identità)Non conservato.Non conservato.
XX (Pauli X)QkBitTerm_X0b0010 (2)
YY (Pauli Y)QkBitTerm_Y0b0011 (3)
ZZ (Pauli Z)QkBitTerm_Z0b0001 (1)
++\lvert+\rangle\langle+\rvert (proiettore all'autostato positivo di X)QkBitTerm_Plus0b1010 (10)
\lvert-\rangle\langle-\rvert (proiettore all'autostato negativo di X)QkBitTerm_Minus0b0110 (6)
rr\lvert r\rangle\langle r\rvert (proiettore all'autostato positivo di Y)QkBitTerm_Right0b1011 (11)
ll\lvert l\rangle\langle l\rvert (proiettore all'autostato negativo di Y)QkBitTerm_Left0b0111 (7)
00\lvert0\rangle\langle0\rvert (proiettore verso un autostato positivo di Z)QkBitTerm_Zero0b1001 (9)
11\lvert1\rangle\langle1\rvert (proiettore all'autostato negativo di Z)QkBitTerm_One0b0101 (5)

Poiché sono ammessi sia i Paoli che i loro proiettori, l'alfabeto ammesso forma una base sovra-completa dello spazio degli operatori. Ciò significa che non esiste un'unica sommatoria per rappresentare una determinata osservabile. Di conseguenza, il confronto richiede una maggiore attenzione e l'uso di qk_obs_canonicalize su due osservabili matematicamente equivalenti potrebbe non portare alla stessa rappresentazione.

QkObs utilizza la sua particolare base sovracompleta con l'obiettivo di rendere l'"efficienza della misurazione" equivalente all'"efficienza della rappresentazione". Ad esempio, l'osservabile 00n{\lvert0\rangle\langle0\rvert}^{\otimes n} può essere misurata in modo efficiente sull'hardware con semplici misure ZZ, ma può essere rappresentata in termini di Paulis solo come (I+Z)n/2n{(I + Z)}^{\otimes n}/2^n, che richiede termini memorizzati 2n2^n. QkObs richiede un solo termine per memorizzarlo. L'aspetto negativo è che non è pratico prendere una matrice arbitraria e trovare la migliore rappresentazione QkObs . In genere si vuole costruire direttamente un QkObs , piuttosto che cercare di decomporlo.


Rappresentazione

La rappresentazione interna di un QkObs memorizza solo gli operatori dei qubit non identici. Questo rende molto più efficiente la rappresentazione di osservabili come nqubitsZ(n)\sum_{n\in \text{qubits}} Z^{(n)}; QkObs richiede una quantità di memoria lineare rispetto al numero totale di qubit. I termini vengono memorizzati compressi, in modo simile al formato compresso delle matrici rade. In questa analogia, i termini della somma sono le "righe" e i termini dei qubit sono le "colonne", dove una voce assente rappresenta l'identità piuttosto che uno zero. Più esplicitamente, la rappresentazione è costituita da quattro array contigui:

Attributo accessibile da
Lunghezza
Descrizione
qk_obs_coeffsttIl moltiplicatore scalare complesso per ogni termine.
qk_obs_bit_termsssOgnuno dei termini non identici a singolo qubit per tutti gli operatori, nell'ordine. Questi corrispondono alla non identità Ai(n)A^{(n)}_i nella descrizione della somma, dove le voci sono memorizzate in ordine crescente ii prima, e in ordine crescente nn all'interno di ogni termine.
qk_obs_indicesssIl qubit corrispondente ( nn ) per ciascuno dei termini di bit. QkObs richiede che questo elenco sia ordinato per termini e gli algoritmi possono fare affidamento sul mantenimento di questo invariante.
qk_obs_boundariest+1t+1Gli indici che suddividono i termini e gli indici di bit in termini completi. Per il numero di termine ii, il suo coefficiente complesso è memorizzato all'indice i, e i suoi operatori single-qubit non identici e i loro qubit corrispondenti sono nell'intervallo [boundaries[i], boundaries[i+1]) nei termini e negli indici dei bit, rispettivamente. I confini hanno sempre uno 0 esplicito come primo elemento.

Il parametro di lunghezza tt è il numero di termini della somma e può essere interrogato con qk_obs_num_terms. Il parametro ss è il numero totale di termini single-qubit non identitari e può essere interrogato con qk_obs_len.

Come esempi illustrativi:

  • nel caso di un operatore zero, i confini sono di lunghezza 1 (un singolo 0) e tutti gli altri vettori sono vuoti.
  • nel caso di un operatore identità completamente semplificato, i limiti sono {0, 0}, i coefficienti hanno una sola voce e sia i termini di bit che gli indici sono vuoti.
  • per l'operatore Z2Z0X3Y1Z_2 Z_0 - X_3 Y_1, i confini sono {0, 2, 4}, i coeff sono {1.0, -1.0}, i termini di bit sono {QkBitTerm_Z, QkBitTerm_Z, QkBitTerm_Y, QkBitTerm_X} e gli indici sono {0, 2, 1, 3}. L'operatore può agire su più di quattro qubit, a seconda del numero di qubit (vedere qk_obs_num_qubits). Si noti che i termini e gli indici a bit singolo sono ordinati in modo termale.

Questi casi non sono speciali, sono pienamente coerenti con le regole e non dovrebbero richiedere una gestione speciale.

Ordinamento canonico

Per una data osservabile matematica, esistono diversi modi di rappresentarla con QkObs. Ad esempio, lo stesso insieme di termini a bit singolo e i loro indici corrispondenti possono comparire più volte nell'osservabile. Dal punto di vista matematico, ciò equivale ad avere un solo termine con tutti i coefficienti sommati. Allo stesso modo, i termini della somma in un QkObs possono essere in qualsiasi ordine pur rappresentando lo stesso osservabile, poiché l'addizione è commutativa (sebbene l'addizione in virgola mobile non sia associativa, QkObs non fornisce garanzie sull'ordine della somma).

Queste due categorie di degenerazione della rappresentazione possono far sì che l'operatore di uguaglianza, qk_obs_equal, affermi che due osservabili non sono uguali, nonostante rappresentino lo stesso oggetto. In questi casi, può essere conveniente definire una forma canonica che permetta di confrontare strutturalmente le osservabili. È possibile mettere un QkObs in forma canonica utilizzando la funzione qk_obs_canonicalize . L'ordine preciso dei termini nell'ordinamento canonico non è specificato e può cambiare da una versione all'altra di Qiskit. All'interno della stessa versione di Qiskit, tuttavia, è possibile confrontare due osservabili dal punto di vista strutturale, confrontando le loro forme semplificate.

Nota

Se si desidera tenere conto della tolleranza in virgola mobile nel confronto, è più sicuro utilizzare una ricetta come:

bool equivalent(QkObs *left, QkObs *right, double tol) {
  // compare a canonicalized version of left - right to the zero observable
  QkObs *neg_right = qk_obs_multiply(right, &(QkComplex64){-1, 0});
  QkObs *diff = qk_obs_add(left, neg_right);
  QkObs *canonical = qk_obs_canonicalize(diff, tol);

  QkObs *zero = qk_obs_zero(qk_obs_num_qubits(left));
  bool equiv = qk_obs_equal(diff, zero);
  // free all temporary variables
  qk_obs_free(neg_right);
  qk_obs_free(diff);
  qk_obs_free(canonical);
  qk_obs_free(zero);
  return equiv;
}
Nota

La forma canonica prodotta da qk_obs_canonicalize non è in grado di rilevare universalmente tutte le osservabili equivalenti a causa dell'alfabeto di basi troppo completo.

Indicizzazione

I singoli termini di somma osservabili in QkObs sono accessibili tramite qk_obs_term e restituiscono oggetti di tipo QkObsTerm. Questi termini contengono campi con il coefficiente del termine, i suoi termini di bit, gli indici e il numero di qubit su cui è definito. Insieme alle informazioni sul numero di termini, è possibile iterare su tutti i termini osservabili come

size_t num_terms = qk_obs_num_terms(obs);  // obs is QkObs*
for (size_t i = 0; i < num_terms; i++) {
    QkObsTerm term;  // allocate term on stack
    int exit = qk_obs_term(obs, i, &term);  // get the term (exit > 0 upon index errors)
    // do something with the term...
}
Avvertenza

Il popolamento di un QkObsTerm tramite qk_obs_term farà riferimento ai dati del QkObs originale. La modifica dei termini o degli indici dei bit cambia l'osservabile e può lasciarla in uno stato incoerente.


Costruzioni

QkObs può essere costruito inizializzando un'osservabile vuota (con qk_obs_zero) e aggiungendo iterativamente termini (con qk_obs_add_term). In alternativa, un'osservabile può essere costruita da dati "grezzi" (con qk_obs_new) se tutti i dati interni sono specificati. Ciò richiede attenzione per garantire che i dati siano coerenti e risultino in un osservabile valido.

Funzione
Riepilogo
qk_obs_zeroCostruire un'osservabile vuota su un dato numero di qubit.
qk_obs_identityCostruire l'osservabile identità su un dato numero di qubit.
qk_obs_newCostruire un osservabile dagli array di dati grezzi.

Manipolazione matematica

QkObs supporta le operazioni aritmetiche fondamentali tra osservabili o con scalari. Sarai in grado di:

  • aggiungere due osservabili utilizzando qk_obs_add e qk_obs_add_inplace
  • moltiplicare per un numero complesso con qk_obs_multiply e qk_obs_multiply_inplace
  • comporre (moltiplicare) due osservabili tramite qk_obs_compose e qk_obs_compose_map
  • calcolare left + scalar * right per due grandezze osservabili e uno scalare complesso con qk_obs_scaled_add e qk_obs_scaled_add_inplace

Funzioni

qk_obs_zero

QkObs *qk_obs_zero(uint32_t num_qubits)

Costruire l'osservabile zero (senza termini).

Esempio

QkObs *zero = qk_obs_zero(100);

Parametri

  • num_qubit - Il numero di qubit su cui è definita l'osservabile.

Risultati

Un puntatore all'osservabile creato.

qk_obs_identity

QkObs *qk_obs_identity(uint32_t num_qubits)

Costruire l'osservabile identità.

Esempio

QkObs *identity = qk_obs_identity(100);

Parametri

  • num_qubit - Il numero di qubit su cui è definita l'osservabile.

Risultati

Un puntatore all'osservabile creato.

qk_obs_new

QkObs *qk_obs_new(uint32_t num_qubits, uint64_t num_terms, uint64_t num_bits, QkComplex64 *coeffs, QkBitTerm *bit_terms, uint32_t *indices, size_t *boundaries)

Costruire una nuova osservabile dai dati grezzi.

Uno qualsiasi degli argomenti di tipo puntatore può essere solo NULL se la sua lunghezza corrispondente è pari a zero.

Esempio

// define the raw data for the 100-qubit observable |01><01|_{0, 1} - |+-><+-|_{98, 99}
uint32_t num_qubits = 100;
uint64_t num_terms = 2;  // we have 2 terms: |01><01|, -1 * |+-><+-|
uint64_t num_bits = 4; // we have 4 non-identity bits: 0, 1, +, -
QkComplex64 coeffs[] = {{1, 0}, {-1, 0}};
QkBitTerm bits[4] = {QkBitTerm_Zero, QkBitTerm_One, QkBitTerm_Plus, QkBitTerm_Minus};

uint32_t indices[4] = {0, 1, 98, 99};  // <-- e.g. {1, 0, 99, 98} would be invalid
size_t boundaries[3] = {0, 2, 4};
QkObs *obs = qk_obs_new(
    num_qubits, num_terms, num_bits, coeffs, bits, indices, boundaries
);
qk_obs_free(obs);

Sicurezza

Il comportamento è indefinito se una delle seguenti condizioni è violata:

  • coeffs è un puntatore ad una matrice QkComplex64 di lunghezza num_terms
  • bit_terms è un puntatore a una matrice di elementi validi di QkBitTerm di lunghezza num_bits
  • indices è un puntatore a una matrice uint32_t di lunghezza num_bits, ordinata per termini in ordine rigorosamente crescente e ogni elemento è più piccolo di num_qubits
  • boundaries è un puntatore a una matrice size_t di lunghezza num_terms + 1, ordinata in ordine crescente, il cui primo elemento è 0 e l'ultimo elemento è più piccolo di num_terms

Parametri

  • num_qubit - Il numero di qubit su cui è definita l'osservabile.
  • num_termini - Il numero di termini.
  • num_bits - Il numero totale di termini di bit non identici.
  • coeff - Puntatore al primo elemento dell'array dei coefficienti, di lunghezza num_terms.
  • bit_terms - Puntatore al primo elemento dell'array di termini di bit, di lunghezza num_bits.
  • indici - Un puntatore al primo elemento dell'array degli indici, di lunghezza num_bits. Si noti che, per ogni termine, questi devono essere ordinati in modo incrementale.
  • boundaries - Puntatore al primo elemento dell'array boundaries, di lunghezza num_terms + 1.

Risultati

Se i dati di input sono coerenti e la costruzione ha successo, il risultato è un puntatore all'osservabile. Altrimenti viene restituito un puntatore nullo.

qk_obs_free

void qk_obs_free(QkObs *obs)

Liberare l'osservabile.

Esempio

QkObs *obs = qk_obs_zero(100);
qk_obs_free(obs);

Sicurezza

Il comportamento è indefinito se obs non è nullo o un puntatore valido a un QkObs.

Parametri

  • obs - Un puntatore all'osservabile da liberare.

qk_obs_add_term

QkExitCode qk_obs_add_term(QkObs *obs, const QkObsTerm *cterm)

Aggiungere un termine all'osservabile.

Esempio

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
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};

QkExitCode exit_code = qk_obs_add_term(obs, &term);

Sicurezza

Il comportamento è indefinito se viene violato uno dei seguenti punti:

  • obs è un puntatore valido e non nullo a un oggetto QkObs
  • cterm è un puntatore valido e non nullo a un oggetto QkObsTerm

Parametri

  • obs - Un puntatore all'osservabile.
  • cterm - Un puntatore al termine da aggiungere.

Risultati

Un codice di uscita. Questo è >0 se il termine è incoerente o se l'aggiunta del termine fallisce.

qk_obs_term

QkExitCode qk_obs_term(QkObs *obs, uint64_t index, QkObsTerm *out)

Ottenere un termine osservabile per riferimento.

Un QkObsTerm contiene puntatori agli indici e ai bit del termine, che possono essere utilizzati per modificare i dati interni dell'osservabile. Questo può lasciare l'osservabile in uno stato incoerente e dovrebbe essere evitato, a meno che non si presti molta attenzione. In genere è più sicuro costruire un nuovo osservabile invece di tentare modifiche in-place.

Esempio

QkObs *obs = qk_obs_identity(100);
QkObsTerm term;
QkExitCode exit_code = qk_obs_term(obs, 0, &term);
// out-of-bounds indices return an error code
// QkExitCode error = qk_obs_term(obs, 12, &term);

Sicurezza

Il comportamento è indefinito se viene violato uno qualsiasi dei seguenti punti

  • obs è un puntatore valido e non nullo a un oggetto QkObs
  • out è un puntatore valido e non nullo a un oggetto QkObsTerm

Parametri

  • obs - Un puntatore all'osservabile.
  • indice - L'indice del termine da ottenere.
  • out - Puntatore a QkObsTerm utilizzato per restituire il termine osservabile.

Risultati

Un codice di uscita.

qk_obs_num_terms

size_t qk_obs_num_terms(const QkObs *obs)

Ottenere il numero di termini dell'osservabile.

Esempio

QkObs *obs = qk_obs_identity(100);
size_t num_terms = qk_obs_num_terms(obs);  // num_terms==1

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Il numero di termini dell'osservabile.

qk_obs_num_qubits

uint32_t qk_obs_num_qubits(const QkObs *obs)

Ottiene il numero di qubit su cui è definita l'osservabile.

Esempio

QkObs *obs = qk_obs_identity(100);
uint32_t num_qubits = qk_obs_num_qubits(obs);  // num_qubits==100

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Il numero di qubit su cui è definita l'osservabile.

qk_obs_len

size_t qk_obs_len(const QkObs *obs)

Ottiene il numero di termini/indici di bit nell'osservabile.

Esempio

QkObs *obs = qk_obs_identity(100);
size_t len = qk_obs_len(obs);  // len==0, as there are no non-trivial bit terms

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Il numero di termini dell'osservabile.

qk_obs_coeffs

QkComplex64 *qk_obs_coeffs(QkObs *obs)

Ottenere un puntatore ai coefficienti.

Questo può essere usato per leggere e modificare i coefficienti dell'osservabile. Il puntatore risultante è valido per la lettura di qk_obs_num_terms(obs) elementi di QkComplex64.

Esempio

QkObs *obs = qk_obs_identity(100);
size_t num_terms = qk_obs_num_terms(obs);
QkComplex64 *coeffs = qk_obs_coeffs(obs);

for (size_t i = 0; i < num_terms; i++) {
    printf("%f + i%f\n", coeffs[i].re, coeffs[i].im);
}

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Un puntatore ai coefficienti.

qk_obs_indices

uint32_t *qk_obs_indices(QkObs *obs)

Ottenere un puntatore agli indici.

Può essere usato per leggere e modificare gli indici dell'osservabile. Il puntatore risultante è valido per la lettura di qk_obs_len(obs) elementi di dimensione uint32_t.

Esempio

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t term_indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, term_indices, num_qubits};
qk_obs_add_term(obs, &term);

size_t len = qk_obs_len(obs);
uint32_t *indices = qk_obs_indices(obs);

for (size_t i = 0; i < len; i++) {
    printf("index %i: %i\n", i, indices[i]);
}

qk_obs_free(obs);

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Un puntatore agli indici.

qk_obs_boundaries

size_t *qk_obs_boundaries(QkObs *obs)

Ottenere un puntatore ai confini del termine.

Questo può essere usato per leggere e modificare i limiti dei termini dell'osservabile. Il puntatore risultante è valido per la lettura di qk_obs_num_terms(obs) + 1 elementi di dimensione size_t.

Esempio

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
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);

size_t num_terms = qk_obs_num_terms(obs);
size_t *boundaries = qk_obs_boundaries(obs);

for (size_t i = 0; i < num_terms + 1; i++) {
    printf("boundary %i: %i\n", i, boundaries[i]);
}

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Un puntatore ai confini.

qk_obs_bit_terms

QkBitTerm *qk_obs_bit_terms(QkObs *obs)

Ottenere un puntatore ai termini di bit.

Questo può essere usato per leggere e modificare i termini di bit dell'osservabile. Il puntatore risultante è valido per la lettura di qk_obs_len(obs) elementi di dimensione uint8_t.

Esempio

uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);

QkComplex64 coeff = {1, 0};
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);

size_t len = qk_obs_len(obs);
QkBitTerm *bits = qk_obs_bit_terms(obs);

for (size_t i = 0; i < len; i++) {
    printf("bit term %i: %i\n", i, bits[i]);
}

qk_obs_free(obs);

Sicurezza

Il comportamento è indefinito obs se il puntatore non è valido QkObs o non è nullo, oppure se nel puntatore QkBitTerm risultante vengono scritti valori non validi.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Un puntatore ai termini di bit.

qk_obs_multiply

QkObs *qk_obs_multiply(const QkObs *obs, const QkComplex64 *coeff)

Moltiplicare l'osservabile per un coefficiente complesso.

Esempio

QkObs *obs = qk_obs_identity(100);
QkComplex64 coeff = {2, 0};
QkObs *result = qk_obs_multiply(obs, &coeff);

Sicurezza

Il comportamento è indefinito se viene violato uno qualsiasi dei seguenti punti

  • obs è un puntatore valido e non nullo a un oggetto QkObs
  • coeff è un puntatore valido e non nullo a un oggetto QkComplex64

Parametri

  • obs - Un puntatore all'osservabile.
  • coeff - Il coefficiente con cui moltiplicare l'osservabile.

Risultati

Un puntatore al risultato obs * coeff.

qk_obs_multiply_inplace

void qk_obs_multiply_inplace(QkObs *obs, const QkComplex64 *coeff)

Moltiplica l'osservabile in loco per un coefficiente complesso.

Esempio

QkObs *obs = qk_obs_identity(100);
QkComplex64 coeff = {2, 0};
qk_obs_multiply_inplace(obs, &coeff);

Sicurezza

Il comportamento è indefinito se viene violato uno qualsiasi dei seguenti punti

  • obs è un puntatore valido e non nullo a un oggetto QkObs
  • coeff è un puntatore valido e non nullo a un oggetto QkComplex64

Parametri

  • obs - Un puntatore all'osservabile.
  • coeff - Il coefficiente con cui moltiplicare l'osservabile.

qk_obs_add

QkObs *qk_obs_add(const QkObs *left, const QkObs *right)

Aggiungere due osservabili.

Esempio

QkObs *left = qk_obs_identity(100);
QkObs *right = qk_obs_zero(100);
QkObs *result = qk_obs_add(left, right);

Sicurezza

Il comportamento è indefinito se left o right non sono puntatori non nulli validi a QkObs.

Parametri

  • left - Puntatore all'osservabile di sinistra.
  • right - Puntatore all'osservabile destro.

Risultati

Un puntatore al risultato left + right.

qk_obs_add_inplace

void qk_obs_add_inplace(QkObs *left, const QkObs *right)

Aggiungi un osservabile a uno esistente.

Esempio

QkObs *left = qk_obs_identity(100);
QkObs *right = qk_obs_zero(100);
qk_obs_add_inplace(left, right);

Sicurezza

Il comportamento è indefinito se left o right non sono puntatori non nulli validi a QkObs.

Parametri

  • left - Puntatore all'osservabile di sinistra.
  • right - Puntatore all'osservabile destro.

qk_obs_scaled_add

QkObs *qk_obs_scaled_add(const QkObs *left, const QkObs *right, const QkComplex64 *factor)

Aggiungi due osservabili modificando i coefficienti di quello a destra.

Esempio

QkObs *left = qk_obs_zero(100);
QkObs *right = qk_obs_identity(100);
QkComplex64 factor = {2, 0};
QkObs *result = qk_obs_scaled_add(left, right, &factor);

Sicurezza

Il comportamento è indefinito se left o right non sono puntatori non nulli validi a QkObs.

Parametri

  • left - Puntatore all'osservabile di sinistra.
  • right - Puntatore all'osservabile destro.
  • fattore – Il fattore con cui moltiplicare i coefficienti.

Risultati

Un puntatore di proprietà al risultato left + factor * right.

qk_obs_scaled_add_inplace

void qk_obs_scaled_add_inplace(QkObs *left, const QkObs *right, const QkComplex64 *factor)

Aggiungi un osservabile ridimensionato a uno esistente.

Esempio

QkObs *left = qk_obs_zero(100);
QkObs *right = qk_obs_identity(100);
QkComplex64 factor = {2, 0};
qk_obs_scaled_add_inplace(left, right, &factor);

Sicurezza

Il comportamento è indefinito se left o right non sono puntatori non nulli validi a QkObs.

Parametri

  • left - Puntatore all'osservabile di sinistra.
  • right - Puntatore all'osservabile destro.
  • fattore – Il fattore con cui moltiplicare i coefficienti.

qk_obs_compose

QkObs *qk_obs_compose(const QkObs *first, const QkObs *second)

Comporre (moltiplicare) due osservabili.

Esempio

QkObs *first = qk_obs_zero(100);
QkObs *second = qk_obs_identity(100);
QkObs *result = qk_obs_compose(first, second);

Sicurezza

Il comportamento è indefinito se first o second non sono puntatori non nulli validi a QkObs.

Parametri

  • primo - Un osservabile.
  • secondo - L'altro osservabile.

Risultati

first.compose(second) che equivale all'osservabile result = second @ first, in termini di moltiplicazione matriciale @.

qk_obs_compose_map

QkObs *qk_obs_compose_map(const QkObs *first, const QkObs *second, const uint32_t *qargs)

Comporre (moltiplicare) due osservabili secondo un ordine di qubit personalizzato.

In particolare, ciò consente di comporre due osservabili di dimensioni diverse.

Esempio

QkObs *first = qk_obs_zero(100);
QkObs *second = qk_obs_identity(100);
QkObs *result = qk_obs_compose(first, second);

Sicurezza

Per chiamare questa funzione in modo sicuro

  • first e second devono essere puntatori validi e non nulli a QkObs\ s
  • qargs deve puntare a un array di uint32_t, leggibile per gli elementi di qk_obs_num_qubits(second) (cioè il numero di qubit in second)

Parametri

  • primo - Un osservabile.
  • secondo - L'altro osservabile. Il numero di qubit deve corrispondere alla lunghezza di qargs.
  • qargs - Gli argomenti dei qubit specificano quali indici in first associare a quelli in second.

Risultati

first.compose(second) che equivale all'osservabile result = second @ first, in termini di moltiplicazione matriciale @.

qk_obs_apply_layout

QkExitCode qk_obs_apply_layout(QkObs *obs, const uint32_t *layout, uint32_t num_qubits)

Applicare una nuova disposizione dei qubit all'osservabile.

Il layout è impostato da un array layout di nuovi indici, che specifica che il qubit all'indice corrente i è rietichettato all'indice layout[i]. Il numero di qubit su cui agisce l'osservabile può essere esteso impostando un num_qubits più grande di quello dell'osservabile corrente.

Esempio

Questa interfaccia consente di rietichettare ed estendere gli indici dei qubit:

QkObs *obs = qk_obs_zero(4);

// add a term to the observable
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t qubits[3] = {1, 2, 3};
complex double coeff = 1;
QkObsTerm term = {coeff, 3, bit_terms, qubits, 4};
qk_obs_add_term(obs, &term);

uint32_t layout[3] = {0, 10, 9};  // qubit mapping is: 0->0, 1->10, 2->9
uint32_t num_output_qubits = 11;
QkExitCode exit = qk_obs_apply_layout(obs, layout, num_output_qubits);

In un flusso di lavoro del compilatore, questa funzione può essere utilizzata per applicare un QkTranspileLayout* ottenuto da un passaggio di transpiler, chiamato transpile_layout nell'esempio seguente:

// get the number of output qubits
uint32_t num_output_qubits = qk_transpile_layout_num_output_qubits(transpile_layout);

// get the layout including the ancillas (hence the ``false`` in the function call)
uint32_t *layout = malloc(sizeof(uint32_t) * num_output_qubits);
qk_transpile_layout_final_layout(transpile_layout, false, layout);

// apply the layout
QkExitCode exit = qk_obs_apply_layout(obs, layout, num_output_qubits);

// free the layout array
free(layout);

Sicurezza

Il comportamento è indefinito se obs non è un puntatore valido e non nullo a QkObs o se layout non è un puntatore valido e non nullo a una sequenza di qk_obs_num_qubits(obs) elementi consecutivi di uint32_t.

Parametri

  • obs - Un puntatore all'osservabile, che verrà modificato al suo posto in caso di successo. Controllare il codice di uscita per verificare che il layout sia stato applicato correttamente.
  • layout - Un puntatore al layout. Il puntatore deve puntare a un array di qk_obs_num_qubits(obs) elementi di tipo uint32_t. Ogni elemento deve avere valori in [0, num_qubits).
  • num_qubit - Il numero di qubit in uscita.

Risultati

Un codice di uscita.

  • QkExitCode_Success in caso di successo
  • QkExitCode_DuplicteIndexError se sono stati trovati indici di qubit duplicati
  • QkExitCode_MismatchedQubits se num_qubits è più piccolo del numero di qubit dell'osservabile
  • QkExitCode_IndexError per qualsiasi altro errore di indice, come ad esempio valori non validi in layout.

qk_obs_canonicalize

QkObs *qk_obs_canonicalize(const QkObs *obs, double tol)

Calcolare la rappresentazione canonica dell'osservabile.

Esempio

QkObs *iden = qk_obs_identity(100);
QkObs *two = qk_obs_add(iden, iden);

double tol = 1e-6;
QkObs *canonical = qk_obs_canonicalize(two, tol);

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.
  • tol - La tolleranza al di sotto della quale i coefficienti sono considerati nulli.

Risultati

La rappresentazione canonica dell'osservabile.

qk_obs_copy

QkObs *qk_obs_copy(const QkObs *obs)

Copiare l'osservabile.

Esempio

QkObs *original = qk_obs_identity(100);
QkObs *copied = qk_obs_copy(original);

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

Parametri

  • obs - Un puntatore all'osservabile.

Risultati

Un puntatore a una copia dell'osservabile.

qk_obs_equal

bool qk_obs_equal(const QkObs *obs, const QkObs *other)

Confrontare due osservabili per verificarne l'uguaglianza.

Si noti che questo non confronta l'uguaglianza matematica, ma l'uguaglianza dei dati. Ciò significa che due osservabili potrebbero rappresentare la stessa osservabile ma non essere paragonate come uguali.

Esempio

QkObs *observable = qk_obs_identity(100);
QkObs *other = qk_obs_identity(100);
bool are_equal = qk_obs_equal(observable, other);

Sicurezza

Il comportamento è indefinito se obs o other non sono puntatori non nulli validi a QkObs.

Parametri

  • obs - Puntatore a un osservabile.
  • other - Puntatore a un altro osservabile.

Risultati

true se le osservabili sono uguali, false altrimenti.

qk_obs_str

char *qk_obs_str(const QkObs *obs)

Restituisce una rappresentazione in stringa di QkObs.

Esempio

QkObs *obs = qk_obs_identity(100);
char *string = qk_obs_str(obs);
qk_str_free(string);
qk_obs_free(obs);

Sicurezza

Il comportamento è indefinito obs non è un puntatore non nullo valido a QkObs.

La stringa non deve essere liberata con il normale free del C, ma si deve usare qk_str_free per liberare la memoria consumata dalla stringa. La mancata chiamata a qk_str_free provoca una perdita di memoria.

Non modificare la lunghezza della stringa dopo che è stata restituita (scrivendo un byte nul da qualche parte all'interno della stringa o rimuovendo quello finale), anche se i valori possono essere mutati.

Parametri

  • obs - Un puntatore a QkObs per cui ottenere la stringa.

Risultati

Un puntatore a un array di caratteri nul-terminato della rappresentazione di stringa per obs

qk_str_free

void qk_str_free(char *string)

Libera una rappresentazione di stringa.

Sicurezza

Il comportamento è indefinito se str non è un puntatore restituito da qk_obs_str o qk_obsterm_str.

Parametri

  • string - Un puntatore alla rappresentazione della stringa restituita da qk_obs_str o qk_obsterm_str.

qk_obs_to_python

PyObject *qk_obs_to_python(QkObs *obs)

Trasferisci la proprietà di un QkObs oggetto a Python.

Non è sicuro utilizzare il QkObs puntatore dopo aver chiamato questa funzione. In particolare, non dovresti cercare di ripulirlo o liberarlo. Chi effettua la chiamata deve essere il proprietario dell'oggetto QkObs, non possedere un riferimento preso in prestito (ad esempio, un oggetto QkObs * recuperato da non qk_obs_borrow_from_python è di sua proprietà).

Sicurezza

Chi chiama deve essere collegato a un interprete dell' Python. Il comportamento è indefinito se non obs è un puntatore non nullo valido a un oggetto inizializzato e di proprietà dell'utente QkObs.

Parametri

  • obs – L'oggetto di proprietà.

Risultati

Un riferimento di tipo " Python " all'oggetto.

qk_obs_borrow_from_python

QkObs *qk_obs_borrow_from_python(PyObject *ob)

Recupera un QkObs puntatore da un oggetto Python.

Questa operazione prende in prestito un riferimento a un oggetto di tipo Python ed estrae il QkObs puntatore corrispondente, se è del tipo corretto. Il puntatore restituito viene preso in prestito dal ob puntatore. Se il non PyObject è del tipo corretto, il valore restituito è NULL e viene impostato lo stato di eccezione dell'interprete di Python.

Per chiamare questa funzione è necessario essere collegati a un interprete Python.

È inoltre possibile utilizzare qk_obs_convert_from_python, che dal punto di vista logico è esattamente identico a questa funzione, ma può essere utilizzato direttamente come funzione di "conversione" per la PyArg_Parse* famiglia di funzioni di conversione di Python.

Sicurezza

Chi chiama deve essere collegato a un interprete dell' Python. Il comportamento è indefinito se non ob è un puntatore valido e non nullo a un oggetto Python.

Parametri

  • ob – Un oggetto preso in prestito dall' Python.

Risultati

Un puntatore all'oggetto nativo, oppure NULL se l'oggetto Python è di tipo errato.

qk_obs_convert_from_python

int qk_obs_convert_from_python(PyObject *object, void *address)

Recupera un QkObs puntatore da un oggetto Python.

Questa operazione prende in prestito un riferimento di tipo Python ed estrae il QkObs puntatore corrispondente in address,, se è del tipo corretto. Il puntatore restituito viene preso in prestito dal object puntatore. Se il tipo PyObject non è corretto, il valore restituito è 1, viene impostato lo stato di eccezione dell'interprete di Python e e address rimane invariato.

Per chiamare questa funzione è necessario essere collegati a un interprete Python.

Puoi anche usare qk_obs_borrow_from_python, che dal punto di vista logico è esattamente uguale a questo, ma presenta una sintassi più intuitiva per l'uso diretto.

Sicurezza

Chi chiama deve essere collegato a un interprete dell' Python. Il comportamento è indefinito se non object è un puntatore valido e non nullo a un oggetto Python, oppure se non address è un puntatore a dati scrivibili del tipo corretto.

Parametri

  • oggetto – Un oggetto Python preso in prestito.
  • destinazione – La posizione in cui scrivere l'output.

Risultati

1 in caso di successo, 0 in caso di fallimento.

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