Skip to main content
IBM Quantum Platform

QfFermionOperator

QfFermionOperator

struct QfFermionOperator

Um operador fermiónico sem spin.

Nota

Trata-se de uma estrutura de dados opaca para a API do C, cujo funcionamento interno é implementado inteiramente em Rust. O restante desta página descreve o projeto e as funções relacionadas para trabalhar com essa estrutura.



Definição

Esse operador é definido por uma combinação linear de produtos de operadores de criação e aniquilação de férmions que atuam sobre modos férmionicos sem spin. Ou seja, os termos individuais satisfazem as seguintes relações de anticomutação: [1]

{ai,aj}={ai,aj}=0,  and  {ai,aj}=δij,\left\{a^\dagger_i, a^\dagger_j\right\} = \left\{a_i, a_j\right\} = 0,~~\text{and}~~ \left\{a_i, a^\dagger_j\right\} = \delta_{ij} \, ,

onde ii e jj não distinguem as espécies de spin dos modos fermiónicos aos quais se referem.

Isso faz com que a definição do operador completo seja a seguinte:

QfFermionOperator=icijAj^,\text{\texttt{QfFermionOperator}} = \sum_i c_i \bigotimes_j \hat{A_j} \, ,

onde Aj^{aj,aj}\hat{A_j} \in \{ a_j, a^\dagger_j \} e cic_i é o coeficiente (complexo) que compõe a combinação linear dos produtos. O índice jj pode assumir qualquer valor entre 0 e o número de modos fermiónicos sobre os quais o operador atua, menos 1.



implementação

Essa estrutura armazena os termos e coeficientes em vários vetores esparsos, de forma semelhante ao formato de linha esparsa compactada comumente utilizado para matrizes esparsas. Mais especificamente, um único operador contém 4 matrizes:

coeffsUm vetor de coeficientes complexos composto por dois números de ponto flutuante de 64 bits.
actionsUm vetor de valores booleanos que armazena a natureza das ações de segunda quantização.
modesUm vetor de inteiros de 32 bits que armazena os índices dos modos fermiónicos sobre os quais a ação foi realizada.
boundariesUm vetor de números inteiros que indica os limites em e actions modes.

As entradas em actions indicam operadores de criação (aniquilação) por ( True``False ). Os modos fermiónicos indexados por modes são considerados sem spin.

Nota

É possível acessar cópias somente para leitura dessas matrizes internas por meio de suas respectivas funções:

Essa estrutura de dados permite a construção e a manipulação de operadores de maneira muito eficiente. No entanto, isso implica que um operador pode conter termos duplicados a qualquer momento. Esses problemas devem ser resolvidos manualmente por meio do uso de qf_ferm_op_simplify().

Construção

É possível construir um novo operador diretamente, especificando os vetores correspondentes descritos acima. Como alternativa, um vazio QfFermionOperator pode ser inicializado com e qf_ferm_op_zero() os termos podem ser adicionados iterativamente por meio de qf_ferm_op_add_term().

qf_ferm_op_new()Cria um novo operador a partir das matrizes fornecidas.
qf_ferm_op_zero()Constrói o operador de identidade aditiva.
qf_ferm_op_one()Constrói o operador de identidade multiplicativa.
qf_ferm_op_add_term()Adiciona um termo a um já existente QfFermionOperator.
Nota

A QfFermionOperator pode ser liberada com qf_ferm_op_free().

Aritmética

As funções a seguir permitem a realização de operações aritméticas:

qf_ferm_op_add()Soma dois operadores.
qf_ferm_op_mul()Multiplica um operador por um escalar.
qf_ferm_op_compose()Combina dois operadores entre si.
qf_ferm_op_adjoint()Retorna o operador conjugado hermitiano.

manipulação

As funções a seguir fornecem a lógica de manipulação do operador:

qf_ferm_op_ichop()Remove termos com coeficientes de pequena magnitude.
qf_ferm_op_simplify()Retorna um operador equivalente, porém simplificado.
qf_ferm_op_normal_ordered()Retorna um operador equivalente com termos ordenados normalmente.
qf_ferm_op_relabel_modes()Reexibe os modos de um operador.

Propriedades

Existem as seguintes funções para verificar determinadas propriedades de um operador.

qf_ferm_op_is_hermitian()Retorna se um operador é hermitiano.
qf_ferm_op_max_rank()Retorna a classificação máxima dos termos neste operador.
qf_ferm_op_conserves_particle_number()Retorna se um operador conserva o número de partículas.

[ 1 ]

https://en.wikipedia.org/wiki/Second _quantization#Operadores_de_criação_e_aniquilação_de_férmions


Membros

qf_ferm_op_new

QfFermionOperator *qf_ferm_op_new(uint64_t num_terms, uint64_t num_actions, const QkComplex64 *coeffs, const bool *actions, const uint32_t *modes, const uint32_t *boundaries)

Cria um novo operador.

Qualquer um dos argumentos do tipo ponteiro pode ser NULL se, e somente se, seu comprimento correspondente for zero.

Exemplo

1uint64_t num_terms = 3;
2uint64_t num_actions = 4;
3bool actions[4] = {true, false, true, false};
4uint32_t modes[4] = {0, 1, 2, 3};
5QkComplex64 coeffs[3] = {{1.0, 0.0}, {-1.0, 0.0}, {0.0, -1.0}};
6uint32_t boundaries[4] = {0, 0, 2, 4};
7QfFermionOperator *op = qf_ferm_op_new(num_terms, num_actions, coeffs,
8                                       actions, modes, boundaries);

Parâmetros

  • num_terms – O número de termos no operador.
  • num_actions – O número de ações somadas em todos os termos.
  • coeffs – Um ponteiro para uma matriz de coeficientes de termos. O comprimento dessa matriz deve ser num_terms.
  • ações – Um ponteiro para uma matriz de ações sobre todos os termos. O comprimento dessa matriz deve ser num_actions.
  • modos – Um ponteiro para uma matriz de modos de ação em todos os termos. O comprimento dessa matriz deve ser num_actions.
  • limites – Um ponteiro para uma matriz contendo os limites entre os termos. O comprimento dessa matriz deve ser num_terms + 1.

qf_ferm_op_free

void qf_ferm_op_free(QfFermionOperator *op)

Libera um operador existente.

Exemplo

1QfFermionOperator *op = qf_ferm_op_one();
2qf_ferm_op_free(op);

Parâmetros

  • op – Um ponteiro para o operador fermiónico a ser liberado.

qf_ferm_op_get_coeffs

void qf_ferm_op_get_coeffs(const QfFermionOperator *op, QkComplex64 **coeffs_out, uint64_t *coeffs_len)

Oferece acesso somente para leitura aos coeficientes do operador.

Veja Também

A explicação sobre a estrutura interna dos dados está aqui.

Exemplo

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 0;
 3QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 4uint32_t boundaries[3] = {0, 0, 0};
 5QfFermionOperator *op =
 6    qf_ferm_op_new(num_terms, num_actions, coeffs, NULL, NULL, boundaries);
 7
 8QkComplex64 *coeffs_out;
 9uint64_t *coeffs_len;
10
11qf_ferm_op_get_coeffs(op, &coeffs_out, &coeffs_len);
12
13assert(coeffs_len == 2);
Nota

Essa função retorna uma cópia dos dados internos.

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujos coeficientes devem ser acessados.
  • coeffs_out – Um ponteiro para a matriz de valores complexos na qual os coeficientes devem ser gravados.
  • coeffs_len – Um ponteiro para o inteiro no qual deve ser gravado o comprimento da matriz de saída.

qf_ferm_op_get_actions

void qf_ferm_op_get_actions(const QfFermionOperator *op, bool **actions_out, uint64_t *actions_len)

Oferece acesso somente para leitura às ações do operador.

Veja Também

A explicação sobre a estrutura interna dos dados está aqui.

Exemplo

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *actions_out;
11uint64_t *actions_len;
12
13qf_ferm_op_get_actions(op, &actions_out, &actions_len);
14
15assert(actions_len == 2);
Nota

Essa função retorna uma cópia dos dados internos.

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujas ações devem ser acessadas.
  • actions_out – Um ponteiro para a matriz de valores booleanos na qual as ações devem ser gravadas.
  • actions_len – Um ponteiro para o inteiro no qual será gravado o comprimento da matriz de saída.

qf_ferm_op_get_modes

void qf_ferm_op_get_modes(const QfFermionOperator *op, uint32_t **modes_out, uint64_t *modes_len)

Fornece acesso somente para leitura aos índices do modo sobre o qual o operador atua.

Veja Também

A explicação sobre a estrutura interna dos dados está aqui.

Exemplo

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *modes_out;
11uint64_t *modes_len;
12
13qf_ferm_op_get_modes(op, &modes_out, &modes_len);
14
15assert(modes_len == 2);
Nota

Essa função retorna uma cópia dos dados internos.

Parâmetros

  • op – Um ponteiro para o operador fermiônico cujos modos devem ser acessados.
  • modes_out – Um ponteiro para a matriz de valores booleanos na qual os modos devem ser gravados.
  • modes_len – Um ponteiro para o número inteiro no qual será gravado o comprimento da matriz de saída.

qf_ferm_op_get_boundaries

void qf_ferm_op_get_boundaries(const QfFermionOperator *op, size_t **boundaries_out, uint64_t *boundaries_len)

Oferece acesso somente para leitura aos índices que indicam os limites entre os termos do operador.

Veja Também

A explicação sobre a estrutura interna dos dados está aqui.

Exemplo

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *boundaries_out;
11uint64_t *boundaries_len;
12
13qf_ferm_op_get_boundaries(op, &boundaries_out, &boundaries_len);
14
15assert(boundaries_len == 3);
Nota

Essa função retorna uma cópia dos dados internos.

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujos limites devem ser acessados.
  • boundaries_out – Um ponteiro para a matriz de valores booleanos na qual os limites devem ser gravados.
  • boundaries_len – Um ponteiro para o inteiro no qual será gravado o comprimento da matriz de saída.

qf_ferm_op_zero

QfFermionOperator *qf_ferm_op_zero(void)

Constrói o operador de identidade aditiva.

Adicionar o operador criado por esse método a outro não produz nenhum efeito.

Exemplo

1QfFermionOperator *zero = qf_ferm_op_zero();
2
3QfFermionOperator *op_plus_zero = qf_ferm_op_add(op, zero);
4
5assert(qf_ferm_op_equal(op, op_plus_zero));

Retorna

Um ponteiro para o operador criado.

qf_ferm_op_one

QfFermionOperator *qf_ferm_op_one(void)

Constrói o operador de identidade multiplicativa.

A composição do operador construído por esse método com outro operador não produz nenhum efeito.

Exemplo

1QfFermionOperator *one = qf_ferm_op_one();
2
3QfFermionOperator *op_times_one = qf_ferm_op_compose(op, one);
4
5assert(qf_ferm_op_equal(op, op_times_one));

Retorna

Um ponteiro para o operador criado.

qf_ferm_op_has_groups

bool qf_ferm_op_has_groups(const QfFermionOperator *op)

Verifica se este operador rastreia índices de grupo.

Exemplo

1QfFCIDump *fcidump = qf_fcidump_from_file("molecule.fcidump");
2QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
3
4bool has_groups = qf_ferm_op_has_groups(op);
5
6assert(!has_groups);

Parâmetros

  • op – Um ponteiro para o operador fermiónico a ser verificado.

Retorna

Se o operador fornecido possui um atributo groups .

qf_ferm_op_num_groups

uint32_t qf_ferm_op_num_groups(const QfFermionOperator *op)

Obtém o número de grupos de um operador.

Exemplo

1QfFCIDump *fcidump = qf_fcidump_from_file("molecule.fcidump");
2QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
3
4uint32_t num_groups = qf_ferm_op_num_groups(op);
Nota

O número de grupos é calculado de forma preguiçosa como o maior índice de grupo encontrado mais 1.

Parâmetros

  • op – Um ponteiro para o operador fermionico cujo número de grupos deve ser obtido.

Retorna

O número de índices de grupo a partir do atributo groups do operador.

qf_ferm_op_group_weights

void qf_ferm_op_group_weights(const QfFermionOperator *op, double *weights_out)

Calcula a média da magnitude absoluta do coeficiente de cada grupo.

A i-ésima entrada é a soma de abs(coeff) pelos termos do grupo i, dividida pelo número de termos desse grupo. Este é o peso de amostragem de uma fórmula de produto aleatória (por exemplo, qDRIFT ) que seleciona grupos inteiros em vez de termos individuais, e é calculado em uma única passagem pelo operador, em vez de ser obtido pela redução de e qf_ferm_op_get_coeffs() ( qf_ferm_op_get_groups() um valor por termo não agrupado cada) no lado do chamador.

Exemplo

 1uint64_t num_terms = 4;
 2uint64_t num_actions = 8;
 3bool actions[8] = {true, false, true, false, true, false, true, false};
 4uint32_t modes[8] = {0, 1, 2, 3, 1, 0, 3, 2};
 5QkComplex64 coeffs[4] = {{1.0, 0.0}, {2.0, 0.0}, {-1.0, 0.0}, {-2.0, 0.0}};
 6uint32_t boundaries[5] = {0, 2, 4, 6, 8};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10uint32_t groups_in[4] = {0, 1, 0, 1};
11qf_ferm_op_set_groups(op, groups_in, num_terms);
12
13double weights[2];
14qf_ferm_op_group_weights(op, weights);
15
16assert(weights[0] == 1.0);
17assert(weights[1] == 2.0);
Nota

Um índice de grupo que nenhum termo possui pesa 0.0, o que o exclui da amostra.

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujos pesos de grupo devem ser calculados.
  • weights_out – Um ponteiro para a matriz de valores do tipo double na qual os pesos devem ser gravados. Deve ter o tamanho de :c:funcqf_ferm_op_num_groups:.

qf_ferm_op_get_groups

void qf_ferm_op_get_groups(const QfFermionOperator *op, uint32_t **groups_out, uint64_t *groups_len)

Obtém os índices de grupo para todos os termos do operador.

Exemplo

1QfFermionOperator *op = ...;
2uint32_t *groups_out;
3uint32_t groups_len;
4
5qf_ferm_op_get_groups(op, &groups_out, &groups_len);

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujos índices de grupo devem ser obtidos.
  • groups_out – Um ponteiro para a matriz de inteiros na qual os índices dos grupos devem ser gravados.
  • groups_len – Um ponteiro para o número inteiro no qual será gravado o comprimento da matriz de saída.

qf_ferm_op_set_groups

void qf_ferm_op_set_groups(QfFermionOperator *op, const uint32_t *groups_in, uint64_t groups_len)

Define o atributo groups do operador fornecido.

Exemplo

1QfFermionOperator *op = ...;
2
3uint32_t num_terms = 4;
4uint32_t groups_in[4] = {0, 1, 0, 1};
5qf_ferm_op_set_groups(op, groups_in, num_terms);

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujo atributo groups deve ser gravado.
  • groups_in – Um ponteiro para a matriz de inteiros groups na qual o operador deve gravar.
  • groups_len – O número de elementos na groups_in matriz.

qf_ferm_op_del_groups

void qf_ferm_op_del_groups(QfFermionOperator *op)

Exclui o atributo groups do operador fornecido.

Exemplo

1QfFermionOperator *op = ...;
2
3qf_ferm_op_del_groups(op);

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujo atributo groups deve ser excluído.

qf_ferm_op_split_out_groups

void qf_ferm_op_split_out_groups(const QfFermionOperator *op, const uint32_t *group_indices, uint64_t num_indices, QfFermionOperator **group_ops_out)

Divide esse operador em uma lista de novos operadores com base em seu groups atributo.

Um índice duplicado em group_indices é gravado uma vez por cada ocorrência em group_ops_out. Solicitar apenas um pequeno número de grupos de um total muito maior é significativamente mais barato do que solicitar todos eles, já que os termos pertencentes a um grupo que não foi solicitado são ignorados, em vez de serem anexados em qualquer lugar.

Exemplo

 1uint64_t num_terms = 4;
 2uint64_t num_actions = 8;
 3bool actions[8] = {true, false, true, false, true, false, true, false};
 4uint32_t modes[8] = {0, 1, 2, 3, 1, 0, 3, 2};
 5QkComplex64 coeffs[4] = {{1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}};
 6uint32_t boundaries[5] = {0, 2, 4, 6, 8};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10uint32_t groups_in[4] = {0, 1, 0, 1};
11qf_ferm_op_set_groups(op, groups_in, num_terms);
12
13// build every group, in index order
14QfFermionOperator *group_ops[2];
15qf_ferm_op_split_out_groups(op, NULL, 0, group_ops);
16
17// build only group 1
18uint32_t group_indices[1] = {1};
19QfFermionOperator *group_op[1];
20qf_ferm_op_split_out_groups(op, group_indices, 1, group_op);

Parâmetros

  • op – Um ponteiro para o operador fermiónico cujo groups deve ser separado.
  • group_indices – Um ponteiro para a matriz de índices de grupo para os quais serão criados os operadores, na ordem de saída desejada. Talvez NULL; nesse caso, cada grupo é construído em ordem de índice (o que equivale a passar cada índice de até 0 :c:func:qf_ferm_op_num_groups - 1).
  • num_indices – O número de índices na group_indices matriz. Ignorado se group_indices for NULL.
  • group_ops_out – Um ponteiro para a matriz de :c:struct:QfFermionOperator na qual devem ser gravados os operadores para cada grupo solicitado. Deve ser dimensionado para num_indices quando não group_indices for NULL, ou para :c:func:qf_ferm_op_num_groups quando for NULL.

qf_ferm_op_add_term

void qf_ferm_op_add_term(QfFermionOperator *op, uint64_t num_actions, const bool *actions, const uint32_t *modes, const QkComplex64 *coeff)

Adiciona um termo a um operador já existente.

Qualquer um dos argumentos do tipo ponteiro pode ser NULL se, e somente se, seu comprimento correspondente for zero.

Cuidado

Esta função redefine o atributo groups do operador para NULL.

Exemplo

 1QfFermionOperator *one = qf_ferm_op_one();
 2
 3QfFermionOperator *op = qf_ferm_op_zero();
 4bool actions[0] = {};
 5uint32_t modes[0] = {};
 6QkComplex64 coeff = {1.0, 0.0};
 7
 8qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 9
10assert(qf_ferm_op_equal(op, one));

Parâmetros

  • op – Um ponteiro para o operador fermiónico a ser modificado.
  • num_actions – O tamanho da matriz de ações.
  • ações – Um ponteiro para uma matriz de ações. O comprimento dessa matriz deve ser num_actions.
  • modos – Um ponteiro para uma matriz de modos de ação. O comprimento dessa matriz deve ser num_actions.
  • coeff – Um ponteiro para o coeficiente complexo.

qf_ferm_op_add

QfFermionOperator *qf_ferm_op_add(const QfFermionOperator *left, const QfFermionOperator *right)

Soma dois operadores.

Exemplo

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4QfFermionOperator *result = qf_ferm_op_add(one, zero);
5
6assert(qf_ferm_op_equal(result, one));

Parâmetros

  • esquerda – Um ponteiro para o operador de esquerda.
  • direita – Um ponteiro para o operador de direita.

Retorna

Um ponteiro para o operador resultante.

qf_ferm_op_mul

QfFermionOperator *qf_ferm_op_mul(const QfFermionOperator *op, const QkComplex64 *scalar)

Multiplica um operador por um escalar.

Exemplo

 1QfFermionOperator *one = qf_ferm_op_one();
 2QkComplex64 coeff = {2.0, 0.0};
 3QfFermionOperator *result = qf_ferm_op_mul(one, &coeff);
 4
 5QfFermionOperator *expected = qf_ferm_op_zero();
 6bool actions[0] = {};
 7uint32_t modes[0] = {};
 8qf_ferm_op_add_term(expected, 0, actions, modes, &coeff);
 9
10assert(qf_ferm_op_equal(result, expected));

Parâmetros

  • op – Um ponteiro para o operador.
  • escalar – Um ponteiro para o escalar.

Retorna

Um ponteiro para o operador resultante.

qf_ferm_op_compose

QfFermionOperator *qf_ferm_op_compose(const QfFermionOperator *left, const QfFermionOperator *right)

Combina dois operadores entre si.

Exemplo

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4QfFermionOperator *result = qf_ferm_op_compose(one, zero);
5
6assert(qf_ferm_op_equal(result, zero));

Parâmetros

  • esquerda – Um ponteiro para o operador de esquerda.
  • direita – Um ponteiro para o operador de direita.

Retorna

Um ponteiro para o operador resultante.

qf_ferm_op_adjoint

QfFermionOperator *qf_ferm_op_adjoint(const QfFermionOperator *op)

Retorna o conjugado hermitiano (ou adjunto) de um operador.

Isso afeta os termos e coeficientes da seguinte forma:

  • as ações em cada termo invertem sua ordem e alternam entre criação e aniquilação
  • os coeficientes são conjugados complexos

Exemplo

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[0] = {};
 3uint32_t modes[0] = {};
 4QkComplex64 coeff = {0.0, 1.0};
 5qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 6
 7QfFermionOperator *adjoint = qf_ferm_op_adjoint(op);
 8
 9QfFermionOperator *expected = qf_ferm_op_zero();
10QkComplex64 coeff_adj = {0.0, -1.0};
11qf_ferm_op_add_term(expected, 0, actions, modes, &coeff_adj);
12
13assert(qf_ferm_op_equal(adjoint, expected));

Parâmetros

  • op – Um ponteiro para o operador.

Retorna

Um ponteiro para o operador criado.

qf_ferm_op_ichop

void qf_ferm_op_ichop(QfFermionOperator *op, double atol)

Remove termos cuja magnitude do coeficiente seja inferior ao limite especificado.

Cuidado

Essa função trunca os coeficientes de forma avarenta! Se o operador sobre o qual a operação é realizada puder conter coeficientes distintos para termos duplicados, considere chamar qf_ferm_op_simplify() em vez disso!

Exemplo

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[0] = {};
 3uint32_t modes[0] = {};
 4QkComplex64 coeff = {1e-8};
 5qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 6
 7qf_ferm_op_ichop(op, 1e-6);
 8
 9QfFermionOperator *expected = qf_ferm_op_zero();
10
11assert(qf_ferm_op_equal(op, expected));

Parâmetros

  • op – Um ponteiro para o operador.
  • atol – A tolerância absoluta para o truncamento do coeficiente.

qf_ferm_op_simplify

QfFermionOperator *qf_ferm_op_simplify(const QfFermionOperator *op, double atol)

Retorna um operador equivalente, porém simplificado.

O processo de simplificação soma, primeiro, todos os coeficientes que pertencem a termos iguais e, em seguida, retém apenas aqueles cujo coeficiente total exceda a tolerância especificada (exatamente como qf_ferm_op_ichop()).

Quando um operador tiver sido manipulado aritmeticamente ou construído de forma que não garanta a unicidade dos termos, esse método deve ser chamado antes da aplicação de qualquer método que filtre coeficientes numericamente pequenos, a fim de evitar perda de informação. Veja o exemplo abaixo, que mostra como qf_ferm_op_ichop() pode truncar termos cuja soma resulta em um coeficiente de magnitude total que não deveria ser truncado:

 1uint64_t num_terms = 100000;
 2uint64_t num_actions = 0;
 3bool actions[0] = {};
 4uint32_t modes[0] = {};
 5QkComplex64 coeffs[100000];
 6uint32_t boundaries[100001];
 7for (int i = 0; i < 100000; i++) {
 8  coeffs[i].re = 1e-5;
 9  coeffs[i].im = 0.0;
10  boundaries[i] = 0;
11}
12boundaries[100000] = 0;
13QfFermionOperator *op = qf_ferm_op_new(num_terms, num_actions, coeffs,
14                                       actions, modes, boundaries);
15
16QfFermionOperator *canon = qf_ferm_op_simplify(op, 1e-4);
17
18QfFermionOperator *one = qf_ferm_op_one();
19bool canon_is_equal = qf_ferm_op_equiv(canon, one, 1e-6);
20
21qf_ferm_op_ichop(op, 1e-4);
22
23QfFermionOperator *zero = qf_ferm_op_zero();
24bool ichop_is_equal = qf_ferm_op_equiv(op, zero, 1e-6);

Parâmetros

  • op – Um ponteiro para o operador fermiónico a ser simplificado.
  • atol – A tolerância absoluta para o truncamento do coeficiente.

Retorna

Um operador equivalente, porém simplificado.

qf_ferm_op_normal_ordered

QfFermionOperator *qf_ferm_op_normal_ordered(const QfFermionOperator *op, const bool *sandwich)

Retorna um operador equivalente com termos ordenados normalmente.

A ordem normal de um termo de operador é definida de forma que todas as ações de criação apareçam antes de todas as ações de aniquilação. Dentro de cada grupo, os modos sobre os quais se atua são ordenados lexicograficamente. O fato de a ordem ser crescente ou decrescente depende do valor do argumento sandwich :

  • NULL: ambos os grupos estão ordenados em ordem lexicográfica decrescente (por exemplo, +_1 +_0 -_1 -_0)
  • True: os índices maiores aparecem mais para o meio, ou seja, as ações de criação estão em ordem lexicográfica ascendente, enquanto as de aniquilação estão em ordem descendente (por exemplo, +_0 +_1 -_1 -_0)
  • False: os índices menores aparecem no meio, ou seja, as ações de criação estão em ordem lexicográfica decrescente, enquanto as de aniquilação estão em ordem crescente (por exemplo, +_1 +_0 -_0 -_1)

Exemplo

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[4] = {false, true, false, true};
 3uint32_t modes[4] = {1, 1, 0, 0};
 4QkComplex64 coeff = {1.0, 0.0};
 5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
 6
 7QfFermionOperator *normal_ordered = qf_ferm_op_normal_ordered(op, NULL);
 8
 9uint64_t num_terms = 4;
10uint64_t num_actions = 8;
11bool actions_exp[8] = {true, false, true, false, true, true, false, false};
12uint32_t modes_exp[8] = {0, 0, 1, 1, 1, 0, 1, 0};
13QkComplex64 coeffs_exp[4] = {
14    {1.0, 0.0}, {-1.0, 0.0}, {-1.0, 0.0}, {-1.0, 0.0}};
15uint32_t boundaries_exp[5] = {0, 0, 2, 4, 8};
16QfFermionOperator *expected =
17    qf_ferm_op_new(num_terms, num_actions, coeffs_exp, actions_exp,
18                   modes_exp, boundaries_exp);
19
20assert(qf_ferm_op_equal(normal_ordered, expected));
Nota

Quando um termo está sendo reordenado, é preciso levar em conta as relações de anticomutação, aiaj=δijajaia_i a^\dagger_j = \delta_{ij} - a^\dagger_j a^i, o que implica que o número de termos pode mudar.

Parâmetros

  • op – Um ponteiro para o operador.
  • sandwich – Um ponteiro para um valor booleano. Esse ponteiro pode ser NULL.

Retorna

Um ponteiro para o operador criado.

qf_ferm_op_is_hermitian

bool qf_ferm_op_is_hermitian(const QfFermionOperator *op, double atol)

Verifica se um operador é hermitiano.

Exemplo

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions1[2] = {true, false};
 3uint32_t modes1[2] = {0, 1};
 4QkComplex64 coeff1 = {0.0, 1.00001};
 5qf_ferm_op_add_term(op, 2, actions1, modes1, &coeff1);
 6bool actions2[2] = {true, false};
 7uint32_t modes2[2] = {1, 0};
 8QkComplex64 coeff2 = {0.0, -1};
 9qf_ferm_op_add_term(op, 2, actions2, modes2, &coeff1);
10
11assert(qf_ferm_op_is_hermitian(op, 1e-4));
12assert(!qf_ferm_op_is_hermitian(op, 1e-8));
Nota

Essa verificação é implementada com qf_ferm_op_equiv() base na diferença qf_ferm_op_normal_ordered() entre e op seus e qf_ferm_op_adjoint() qf_ferm_op_zero().

Parâmetros

  • op – Um ponteiro para o operador fermiónico a ser verificado.
  • atol – A tolerância absoluta até a qual os coeficientes são considerados iguais.

Retorna

Se o operador fornecido é hermitiano.

qf_ferm_op_max_rank

uint32_t qf_ferm_op_max_rank(const QfFermionOperator *op)

Verifica a ordem máxima de um operador.

Exemplo

1QfFermionOperator *op = qf_ferm_op_zero();
2bool actions[4] = {true, false, true, false};
3uint32_t modes[4] = {0, 1, 2, 3};
4QkComplex64 coeff = {1.0, 0.0};
5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
6
7assert(qf_ferm_op_max_rank(op), 4);
Nota

O comprimento do termo mais longo pode depender da forma do operador, o que significa que (por exemplo) a simplificação do operador ou a ordenação normal podem resultar em um grau máximo diferente.

Parâmetros

  • op – Um ponteiro para o operador fermiónico a ser verificado.

Retorna

A classificação máxima do operador.

qf_ferm_op_conserves_particle_number

bool qf_ferm_op_conserves_particle_number(const QfFermionOperator *op)

Verifica se um operador conserva o número de partículas.

Exemplo

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions1[2] = {true, false};
 3uint32_t modes1[2] = {0, 1};
 4QkComplex64 coeff1 = {0.0, 1.00001};
 5qf_ferm_op_add_term(op, 2, actions1, modes1, &coeff1);
 6bool actions2[2] = {true, false};
 7uint32_t modes2[2] = {1, 0};
 8QkComplex64 coeff2 = {0.0, -1};
 9qf_ferm_op_add_term(op, 2, actions2, modes2, &coeff2);
10
11assert(qf_ferm_op_is_hermitian(op, 1e-4));
12assert(!qf_ferm_op_is_hermitian(op, 1e-8));

Parâmetros

  • op – Um ponteiro para o operador fermiónico a ser verificado.

Retorna

Se o operador fornecido conserva o número de partículas.

qf_ferm_op_equal

bool qf_ferm_op_equal(const QfFermionOperator *left, const QfFermionOperator *right)

Compare dois operadores para verificar se são iguais.

Exemplo

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4assert(qf_ferm_op_equal(one, one));
5assert(!qf_ferm_op_equal(one, zero));

Parâmetros

  • esquerda – Um ponteiro para o operador de esquerda.
  • direita – Um ponteiro para o operador de direita.

Retorna

Se os dois operadores são iguais.

qf_ferm_op_equiv

bool qf_ferm_op_equiv(const QfFermionOperator *left, const QfFermionOperator *right, double atol)

Compare dois operadores para verificar se são equivalentes.

Equivalência, neste contexto, significa igualdade aproximada dentro dos limites da tolerância absoluta especificada. Para ser mais preciso, esse método retorna True, quando todos os valores absolutos dos coeficientes da diferença other - self estão abaixo do limite especificado atol.

Exemplo

 1QfFermionOperator *zero = qf_ferm_op_zero();
 2
 3QfFermionOperator *op = qf_ferm_op_zero();
 4bool actions[0] = {};
 5uint32_t modes[0] = {};
 6QkComplex64 coeff = {1e-7, 0.0};
 7qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 8
 9assert(qf_ferm_op_equiv(op, zero, 1e-6));
10assert(!qf_ferm_op_equiv(op, zero, 1e-8));

Parâmetros

  • esquerda – Um ponteiro para o operador de esquerda.
  • direita – Um ponteiro para o operador de direita.
  • atol – A tolerância absoluta para a equivalência de coeficientes.

Retorna

Se as duas operações são equivalentes.

qf_ferm_op_len

size_t qf_ferm_op_len(const QfFermionOperator *op)

Retorna o comprimento (ou o número de termos) do operador fornecido.

Exemplo

1QfFermionOperator *op = qf_ferm_op_zero();
2bool actions[4] = {true, false, true, false};
3uint32_t modes[4] = {0, 1, 2, 3};
4QkComplex64 coeff = {1.0, 0.0};
5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
6
7assert(qf_ferm_op_len(op) == 1);

Parâmetros

  • op – Um ponteiro para o operador fermiónico.

Retorna

O comprimento (ou número de termos) do operador.

qf_ferm_op_relabel_modes

QfExitCode qf_ferm_op_relabel_modes(QfFermionOperator *op, uint64_t num_modes, const uint32_t *permutation)

Renomeia os índices do operador fornecido.

Exemplo

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[4] = {true, false, true, false};
 3uint32_t indices[4] = {0, 1, 2, 3};
 4QkComplex64 coeff = {1.0, 0.0};
 5qf_ferm_op_add_term(op, 4, actions, indices, &coeff);
 6
 7uint32_t permutation[4] = {3, 2, 1, 0};
 8
 9QfExitCode exit = qf_ferm_op_relabel_modes(op, 4, permutation);
10
11assert(exit == QfExitCode_Success);

Parâmetros

  • op – Um ponteiro para o operador fermiónico.
  • num_modes – O número de índices de modo na lista de permutações fornecida.
  • permutação – A lista de permutações de índices.

Retorna

Um código de saída.

  • QfExitCode_Success em caso de sucesso
  • QfExitCode_DuplicateIndexError se forem encontrados índices duplicados na permutação
  • QfExitCode_IndexError para quaisquer outros erros de índice, como índices inválidos.
Esta página foi útil?
Relate um bug, erro de digitação ou solicite conteúdo no GitHub.