QfFermionOperator
QfFermionOperator
struct QfFermionOperator
Ein spinloser fermionischer Operator.
Es handelt sich hierbei um eine für die C-API undurchsichtige Datenstruktur, deren Interna vollständig in Rust implementiert sind. Im weiteren Verlauf dieser Seite werden der Aufbau und die zugehörigen Funktionen zur Arbeit mit dieser Struktur beschrieben.
Begriffsbestimmung
Dieser Operator wird durch eine Linearkombination von Produkten aus fermionischen Erzeugungs- und Vernichtungsoperatoren definiert, die auf spinlose fermionische Moden wirken. Das heißt, die einzelnen Terme erfüllen die folgenden Antikommutationsrelationen: [1]
wobei „ “ und „ “ keinen Unterschied zwischen den Spinarten der fermionischen Moden machen, die sie indizieren.
Damit lautet die Definition des gesamten Operators wie folgt:
wobei und der (komplexe) Koeffizient ist, der die Linearkombination der Produkte bildet. Der Index kann jeden Wert zwischen 0 und der Anzahl der vom Operator beeinflussten Fermionenmoden minus 1 annehmen.
Bereitstellung
Diese Struktur speichert die Terme und Koeffizienten in mehreren spärlichen Vektoren, ähnlich dem komprimierten spärlichen Zeilenformat, das üblicherweise für spärliche Matrizen verwendet wird. Genauer gesagt enthält ein einzelner Operator vier Arrays:
Kolumne „ 1 “ | Kolumne „ 2 “ |
|---|---|
coeffs | Ein Vektor mit komplexen Koeffizienten, bestehend aus zwei 64-Bit-Gleitkommazahlen. |
actions | Ein Vektor aus Booleschen Werten, der die Art der Zweitsquantisierungsvorgänge speichert. |
modes | Ein Vektor aus 32-Bit-Ganzzahlen, in dem die Indizes der betroffenen Fermionenmoden gespeichert sind. |
boundaries | Ein Vektor aus ganzen Zahlen, der die Grenzen in und actions angibt modes. |
Einträge in bezeichnen actions Erzeugungs- (bzw. Vernichtungs-)Operatoren von True (False). Die durch indizierten Fermionenmoden modes gelten als spinlos.
Über die jeweiligen Funktionen können Sie auf schreibgeschützte Kopien dieser internen Arrays zugreifen:
Diese Datenstruktur ermöglicht eine sehr effiziente Erstellung und Bearbeitung von Operatoren. Dies bedeutet jedoch, dass ein Operator zu jedem Zeitpunkt doppelte Terme enthalten könnte. Diese müssen manuell mithilfe von qf_ferm_op_simplify(). behoben werden.
Bauwesen
Ein neuer Operator kann direkt durch die Angabe der oben beschriebenen entsprechenden Arrays erstellt werden. Alternativ QfFermionOperator kann ein leeres mit initialisiert werden, und qf_ferm_op_zero() Terme können iterativ über hinzugefügt werden qf_ferm_op_add_term().
Kolumne „ 1 “ | Kolumne „ 2 “ |
|---|---|
qf_ferm_op_new() | Erstellt aus den angegebenen Arrays einen neuen Operator. |
qf_ferm_op_zero() | Erzeugt den additiven Identitätsoperator. |
qf_ferm_op_one() | Erzeugt den multiplikativen Identitätsoperator. |
qf_ferm_op_add_term() | Fügt einen Begriff zu einem bestehenden hinzu QfFermionOperator. |
A kann QfFermionOperator mit freigegeben werden qf_ferm_op_free().
Rechenarten
Die folgenden Funktionen ermöglichen arithmetische Operationen:
Kolumne „ 1 “ | Kolumne „ 2 “ |
|---|---|
qf_ferm_op_add() | Addiert zwei Operanden. |
qf_ferm_op_mul() | Multipliziert einen Operator mit einem Skalar. |
qf_ferm_op_compose() | Kombiniert zwei Operatoren miteinander. |
qf_ferm_op_adjoint() | Gibt den hermitisch konjugierten Operator zurück. |
Bearbeitung
Die folgenden Funktionen stellen die Logik zur Bearbeitung von Operatoren bereit:
Kolumne „ 1 “ | Kolumne „ 2 “ |
|---|---|
qf_ferm_op_ichop() | Entfernt Terme mit kleinen Koeffizienten. |
qf_ferm_op_simplify() | Gibt einen gleichwertigen, aber vereinfachten Operator zurück. |
qf_ferm_op_normal_ordered() | Gibt einen Äquivalenzoperator mit normal geordneten Termen zurück. |
qf_ferm_op_relabel_modes() | Benennt die Modi eines Operators um. |
Eigenschaften
Es gibt die folgenden Funktionen, um bestimmte Eigenschaften eines Operators zu überprüfen.
Kolumne „ 1 “ | Kolumne „ 2 “ |
|---|---|
qf_ferm_op_is_hermitian() | Gibt zurück, ob ein Operator hermitisch ist. |
qf_ferm_op_max_rank() | Gibt den höchsten Rang der Terme in diesem Operator zurück. |
qf_ferm_op_conserves_particle_number() | Gibt zurück, ob ein Operator die Teilchenanzahl bewahrt. |
[ 1 ]
https://en.wikipedia.org/wiki/Second _quantization#Fermionen-Erzeugungs- und -Vernichtungsoperatoren
Mitglieder
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)
Erstellt einen neuen Operator.
Jedes der Zeigerargumente kann genau dann sein, NULL wenn seine entsprechende Länge null ist.
Beispiel
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);Parameter
- num_terms – Die Anzahl der Terme im Operator.
- num_actions – Die Anzahl der Aktionen, summiert über alle Terme.
- coeffs – Ein Zeiger auf ein Array von Termkoeffizienten. Die Länge dieses Arrays sollte betragen
num_terms. - Aktionen – Ein Zeiger auf ein Array von Aktionen für alle Terme. Die Länge dieses Arrays sollte betragen
num_actions. - Modi – Ein Zeiger auf ein Array von Aktionsmodi für alle Terme. Die Länge dieses Arrays sollte betragen
num_actions. - Grenzen – Ein Zeiger auf ein Array, das die Grenzen zwischen den Termen enthält. Die Länge dieses Arrays sollte betragen
num_terms + 1.
qf_ferm_op_free
void qf_ferm_op_free(QfFermionOperator *op)
Gibt einen vorhandenen Operator frei.
Beispiel
1QfFermionOperator *op = qf_ferm_op_one();
2qf_ferm_op_free(op);Parameter
- op – Ein Zeiger auf den zu befreienden Fermionenoperator.
qf_ferm_op_get_coeffs
void qf_ferm_op_get_coeffs(const QfFermionOperator *op, QkComplex64 **coeffs_out, uint64_t *coeffs_len)
Bietet Lesezugriff auf die Koeffizienten des Operators.
Die Erläuterung der internen Datenstruktur finden Sie hier.
Beispiel
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);Diese Funktion gibt eine Kopie der internen Daten zurück.
Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen Koeffizienten abgerufen werden sollen.
- coeffs_out – Ein Zeiger auf das Array komplexer Werte, in das die Koeffizienten geschrieben werden sollen.
- coeffs_len – Ein Zeiger auf die Ganzzahl, in die die Länge des Ausgabearrays geschrieben werden soll.
qf_ferm_op_get_actions
void qf_ferm_op_get_actions(const QfFermionOperator *op, bool **actions_out, uint64_t *actions_len)
Bietet Lesezugriff auf die Aktionen des Bedieners.
Die Erläuterung der internen Datenstruktur finden Sie hier.
Beispiel
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);Diese Funktion gibt eine Kopie der internen Daten zurück.
Parameter
- op – Ein Zeiger auf den Fermionenoperator, auf dessen Aktionen zugegriffen werden soll.
- actions_out – Ein Zeiger auf das Array mit booleschen Werten, in das die Aktionen geschrieben werden sollen.
- actions_len – Ein Zeiger auf die Ganzzahl, in die die Länge des Ausgabearrays geschrieben werden soll.
qf_ferm_op_get_modes
void qf_ferm_op_get_modes(const QfFermionOperator *op, uint32_t **modes_out, uint64_t *modes_len)
Bietet Lesezugriff auf die Indizes des Betreibers im „Acted-Upon“-Modus.
Die Erläuterung der internen Datenstruktur finden Sie hier.
Beispiel
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);Diese Funktion gibt eine Kopie der internen Daten zurück.
Parameter
- op – Ein Zeiger auf den Fermionenoperator, auf dessen Moden zugegriffen werden soll.
- modes_out – Ein Zeiger auf das Array mit booleschen Werten, in das die Modi geschrieben werden sollen.
- modes_len – Ein Zeiger auf die Ganzzahl, in die die Länge des Ausgabearrays geschrieben werden soll.
qf_ferm_op_get_boundaries
void qf_ferm_op_get_boundaries(const QfFermionOperator *op, size_t **boundaries_out, uint64_t *boundaries_len)
Bietet Lesezugriff auf die Indizes, die die Grenzen zwischen den Operatorausdrücken angeben.
Die Erläuterung der internen Datenstruktur finden Sie hier.
Beispiel
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);Diese Funktion gibt eine Kopie der internen Daten zurück.
Parameter
- op – Ein Zeiger auf den Fermionenoperator, auf dessen Grenzen zugegriffen werden soll.
- boundaries_out – Ein Zeiger auf das Array mit booleschen Werten, in das die Grenzen geschrieben werden sollen.
- boundaries_len – Ein Zeiger auf die Ganzzahl, in die die Länge des Ausgabearrays geschrieben werden soll.
qf_ferm_op_num_support
uint32_t qf_ferm_op_num_support(const QfFermionOperator *op)
Ermittelt die Größe der Unterstützungsmenge eines Operators.
Verwenden Sie dies, um die Größe des Ausgabepuffers von festzulegen qf_ferm_op_get_support(), der keine eigene Länge angibt.
Beispiel
1bool actions[3] = {true, false, true};
2uint32_t modes[3] = {2, 0, 2};
3QkComplex64 coeffs[2] = {{1.0, 0.0}, {1.0, 0.0}};
4uint32_t boundaries[3] = {0, 2, 3};
5QfFermionOperator *op = qf_ferm_op_new(2, 3, coeffs, actions, modes, boundaries);
6
7uint32_t num_support = qf_ferm_op_num_support(op);
8
9assert(num_support == 2);Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen Unterstützungsgröße ermittelt werden soll.
Rückgabe
Die Anzahl der unterschiedlichen Modusindizes, auf die der Operator wirkt.
qf_ferm_op_get_support
void qf_ferm_op_get_support(const QfFermionOperator *op, uint32_t *support_out)
Ruft die Unterstützung eines Operators ab, d. h. die Modusindizes, auf die der Operator einwirkt.
Die Indizes sind in aufsteigender Reihenfolge aufgeführt, und jeder Index kommt genau einmal vor, unabhängig davon, wie viele Terme auf ihn einwirken.
Beispiel
1bool actions[3] = {true, false, true};
2uint32_t modes[3] = {2, 0, 2};
3QkComplex64 coeffs[2] = {{1.0, 0.0}, {1.0, 0.0}};
4uint32_t boundaries[3] = {0, 2, 3};
5QfFermionOperator *op = qf_ferm_op_new(2, 3, coeffs, actions, modes, boundaries);
6
7uint32_t num_support = qf_ferm_op_num_support(op);
8uint32_t *support_out = malloc(num_support * sizeof(uint32_t));
9
10qf_ferm_op_get_support(op, support_out);
11
12assert(support_out[0] == 0);
13assert(support_out[1] == 2);
14
15free(support_out);Im Gegensatz zu den anderen Gettern gibt dieser keinen Zeiger auf den Operator zurück: Der Wert wird bei Bedarf berechnet und nicht gespeichert, daher muss der Aufrufer den Ausgabepuffer bereitstellen. Ermitteln Sie zunächst qf_ferm_op_num_support() die erforderliche Länge der Abfrage.
Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen Trägermenge abgerufen werden soll.
- support_out – Ein Zeiger auf das Integer-Array, in das die Unterstützung geschrieben werden soll. Es muss eine Größe von mindestens :c:func:
qf_ferm_op_num_supportElementen haben.
qf_ferm_op_zero
QfFermionOperator *qf_ferm_op_zero(void)
Erzeugt den additiven Identitätsoperator.
Das Hinzufügen des auf diese Weise erstellten Operators zu einem anderen hat keine Auswirkung.
Beispiel
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));Rückgabe
Ein Zeiger auf den erstellten Operator.
qf_ferm_op_one
QfFermionOperator *qf_ferm_op_one(void)
Erzeugt den multiplikativen Identitätsoperator.
Die Kombination des auf diese Weise konstruierten Operators mit einem anderen hat keine Auswirkungen.
Beispiel
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));Rückgabe
Ein Zeiger auf den erstellten Operator.
qf_ferm_op_has_groups
bool qf_ferm_op_has_groups(const QfFermionOperator *op)
Prüft, ob dieser Operator Gruppenindizes nachverfolgt.
Beispiel
1QfFCIDump *fcidump = NULL;
2qf_fcidump_from_file("molecule.fcidump", &fcidump);
3QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
4
5bool has_groups = qf_ferm_op_has_groups(op);
6
7assert(!has_groups);Parameter
- op – Ein Zeiger auf den zu prüfenden Fermionenoperator.
Rückgabe
Ob der angegebene Operator ein Attribut groups hat.
qf_ferm_op_num_groups
uint32_t qf_ferm_op_num_groups(const QfFermionOperator *op)
Ruft die Anzahl der Gruppen eines Operators ab.
Beispiel
1QfFCIDump *fcidump = NULL;
2qf_fcidump_from_file("molecule.fcidump", &fcidump);
3QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
4
5uint32_t num_groups = qf_ferm_op_num_groups(op);Die Anzahl der Gruppen wird verzögert als der Index der größten vorkommenden Gruppe plus 1 berechnet.
Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen Gruppenanzahl ermittelt werden soll.
Rückgabe
Die Anzahl der Gruppenindizes aus dem Attribut groups des Operators.
qf_ferm_op_get_groups
void qf_ferm_op_get_groups(const QfFermionOperator *op, uint32_t **groups_out, uint64_t *groups_len)
Ruft die Gruppenindizes für alle Operatorterme ab.
Beispiel
1QfFermionOperator *op = ...;
2uint32_t *groups_out;
3uint32_t groups_len;
4
5qf_ferm_op_get_groups(op, &groups_out, &groups_len);Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen Gruppenindizes abgerufen werden sollen.
- groups_out – Ein Zeiger auf das Integer-Array, in das die Gruppenindizes geschrieben werden sollen.
- groups_len – Ein Zeiger auf die Ganzzahl, in die die Länge des Ausgabearrays geschrieben werden soll.
qf_ferm_op_set_groups
QfExitCode qf_ferm_op_set_groups(QfFermionOperator *op, const uint32_t *groups_in, uint64_t groups_len)
Legt das Attribut groups des angegebenen Operators fest.
Die Länge wird hier überprüft, da sie weiter unten nicht noch einmal überprüft wird: Bei zu wenigen Indizes würden die nachfolgenden Terme stillschweigend weggelassen, wenn Terme zusammen mit ihren Gruppen durchlaufen werden, und bei zu vielen würden Gruppen qf_ferm_op_num_groups() gemeldet, die kein Term enthält.
Beispiel
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);Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen Attribut
groupsgeschrieben werden soll. - groups_in – Ein Zeiger auf das
groupsInteger-Array, in das der Operator schreiben soll. - groups_len – Die Anzahl der Elemente im Array
groups_in.
Rückgabe
Ein Exit-Code.
QfExitCode_Successim ErfolgsfallQfExitCode_ValueErrorwenn von der Anzahl der Terme im Operator abweichtgroups_len
qf_ferm_op_del_groups
void qf_ferm_op_del_groups(QfFermionOperator *op)
Löscht das Attribut groups aus dem angegebenen Operator.
Beispiel
1QfFermionOperator *op = ...;
2
3qf_ferm_op_del_groups(op);Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen Attribut
groupsgelöscht werden soll.
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)
Teilt diesen Operator anhand seines Attributs groups in eine Liste neuer Operatoren auf.
Ein doppelter Index in group_indices wird einmal pro Vorkommen in geschrieben group_ops_out. Das Abfragen nur einer kleinen Anzahl von Gruppen aus einer viel größeren Gesamtmenge ist deutlich kostengünstiger als das Abfragen aller Gruppen, da Begriffe, die zu einer nicht abgefragten Gruppe gehören, übersprungen und nicht irgendwo angehängt werden.
Beispiel
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);Parameter
- op – Ein Zeiger auf den fermionischen Operator, dessen herausgelöst werden
groupssoll. - group_indices – Ein Zeiger auf das Array der Gruppenindizes, für die Operatoren erstellt werden sollen, in der gewünschten Ausgabereihenfolge. Möglicherweise ist dies der Fall
NULL; in diesem Fall wird jede Gruppe in Indexreihenfolge aufgebaut (was der Übergabe jedes Indexes von0an :c:func:qf_ferm_op_num_groupsentspricht- 1). - num_indices – Die Anzahl der Indizes im Array
group_indices. Wird ignoriert, wenn istgroup_indices``NULL. - group_ops_out – Ein Zeiger auf das Array von :c:struct:
QfFermionOperator, in das die Operatoren für jede angeforderte Gruppe geschrieben werden sollen. Muss auf angepasst werden, wennnum_indicesnicht istgroup_indices``NULL, oder auf :c:func:qf_ferm_op_num_groups, wenn es istNULL.
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)
Fügt einem bestehenden Operator einen Term hinzu.
Jedes der Zeigerargumente kann genau dann sein, NULL wenn seine entsprechende Länge null ist.
Diese Funktion setzt das Attribut groups des Operators auf zurück NULL.
Beispiel
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));Parameter
- op – Ein Zeiger auf den zu ändernden Fermionenoperator.
- num_actions – Die Länge des Arrays „actions“.
- Aktionen – Ein Zeiger auf ein Array von Aktionen. Die Länge dieses Arrays sollte betragen
num_actions. - Modi – Ein Zeiger auf ein Array von Aktionsmodi. Die Länge dieses Arrays sollte betragen
num_actions. - coeff – Ein Zeiger auf den komplexen Koeffizienten.
qf_ferm_op_add
QfFermionOperator *qf_ferm_op_add(const QfFermionOperator *left, const QfFermionOperator *right)
Addiert zwei Operanden.
Beispiel
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));Parameter
- links – Ein Zeiger auf den Operator „links“.
- right – Ein Zeiger auf den Operator „right“.
Rückgabe
Ein Zeiger auf den resultierenden Operator.
qf_ferm_op_scaled_add
QfFermionOperator *qf_ferm_op_scaled_add(const QfFermionOperator *left, const QfFermionOperator *right, const QkComplex64 *factor)
Addiert zwei Operatoren und skaliert dabei die Koeffizienten des rechten Operators.
Dadurch wird die Skalierung in die Addition integriert, wodurch vermieden wird, dass eine vollständig skalierte Kopie erstellt werden muss, nur right um sie anzuhängen. Durch die Übergabe eines Faktors von wird -1 somit subtrahiert, weshalb keine separate Subtraktionsfunktion bereitgestellt wird.
Beispiel
1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *other = qf_ferm_op_one();
3
4// Subtracting via a factor of -1 leaves the two terms cancelling each other out.
5QkComplex64 factor = {-1.0, 0.0};
6QfFermionOperator *result = qf_ferm_op_scaled_add(one, other, &factor);
7
8QfFermionOperator *simplified = qf_ferm_op_simplify(result, 1e-10);
9assert(qf_ferm_op_len(simplified) == 0);Das bedeutet qf_ferm_op_add(), dass die Terme von angehängt werden, ohne right sie mit denen von zu kombinieren left, sodass das Ergebnis keine Gruppenindizes enthält. Rufen Sie an, qf_ferm_op_simplify() um die gleichen Konditionen später zu vereinbaren.
Parameter
- links – Ein Zeiger auf den Operator „links“.
- right – Ein Zeiger auf den Operator „right“.
- Faktor – Ein Zeiger auf den Faktor, mit dem die Koeffizienten des rechten Operators skaliert werden sollen.
Rückgabe
Ein Zeiger auf den resultierenden Operator, left + factor * right.
qf_ferm_op_add_inplace
void qf_ferm_op_add_inplace(QfFermionOperator *left, const QfFermionOperator *right)
Fügt einen Operator in einen anderen ein, ohne ihn zu verschieben.
Das In-Place-Äquivalent von qf_ferm_op_add(), wodurch das Kopieren in left ein neu zugewiesenes Ergebnis entfällt.
Diese Funktion setzt das Attribut groups des Operators auf zurück NULL.
Beispiel
1QfFermionOperator *left = qf_ferm_op_one();
2QfFermionOperator *right = qf_ferm_op_one();
3
4qf_ferm_op_add_inplace(left, right);
5
6assert(qf_ferm_op_len(left) == 2);Parameter
- links – Ein Zeiger auf den Operator, in den hinzugefügt werden soll.
- right – Ein Zeiger auf den zu addierenden Operator.
qf_ferm_op_scaled_add_inplace
void qf_ferm_op_scaled_add_inplace(QfFermionOperator *left, const QfFermionOperator *right, const QkComplex64 *factor)
Fügt einen Operator an Ort und Stelle in einen anderen ein und skaliert dabei die Koeffizienten des rechten Operators.
Das In-Place-Äquivalent von qf_ferm_op_scaled_add(), das berechnet, ohne left + factor * right ein Ergebnis zuzuweisen. Da wird ein Faktor von abgezogen -1 .
Diese Funktion setzt das Attribut groups des Operators auf zurück NULL.
Beispiel
1QfFermionOperator *left = qf_ferm_op_one();
2QfFermionOperator *right = qf_ferm_op_one();
3
4// Subtract, leaving two terms that cancel each other out.
5QkComplex64 factor = {-1.0, 0.0};
6qf_ferm_op_scaled_add_inplace(left, right, &factor);
7
8QfFermionOperator *simplified = qf_ferm_op_simplify(left, 1e-10);
9assert(qf_ferm_op_len(simplified) == 0);Parameter
- links – Ein Zeiger auf den Operator, in den hinzugefügt werden soll.
- right – Ein Zeiger auf den zu addierenden Operator.
- Faktor – Ein Zeiger auf den Faktor, mit dem die Koeffizienten des rechten Operators skaliert werden sollen.
qf_ferm_op_mul_inplace
void qf_ferm_op_mul_inplace(QfFermionOperator *op, const QkComplex64 *scalar)
Multipliziert einen Operator mit einem Skalar, ohne die Ergebnisse zu speichern.
Das In-Place-Äquivalent von qf_ferm_op_mul(), wodurch das Kopieren des Operators in ein neu zugewiesenes Ergebnis entfällt.
Beispiel
1QfFermionOperator *op = qf_ferm_op_one();
2QkComplex64 scalar = {2.0, 0.0};
3
4qf_ferm_op_mul_inplace(op, &scalar);Im Gegensatz zu den beiden oben genannten In-Place-Ergänzungen bleibt dabei das Attribut groups erhalten: Durch die Skalierung der Koeffizienten bleiben die Anzahl der Terme und damit die Invariante „ein Index pro Term“ unverändert.
Parameter
- op – Ein Zeiger auf den Operator, mit dem skaliert werden soll.
- Skalar – Ein Zeiger auf den Skalar.
qf_ferm_op_mul
QfFermionOperator *qf_ferm_op_mul(const QfFermionOperator *op, const QkComplex64 *scalar)
Multipliziert einen Operator mit einem Skalar.
Beispiel
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));Parameter
- op – Ein Zeiger auf den Operator.
- Skalar – Ein Zeiger auf den Skalar.
Rückgabe
Ein Zeiger auf den resultierenden Operator.
qf_ferm_op_compose
QfFermionOperator *qf_ferm_op_compose(const QfFermionOperator *left, const QfFermionOperator *right)
Kombiniert zwei Operatoren miteinander.
Beispiel
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));Die Verknüpfung zweier Operatoren verfolgt keine Gruppen, selbst wenn beide Operanden dies tun.
Parameter
- links – Ein Zeiger auf den Operator „links“.
- right – Ein Zeiger auf den Operator „right“.
Rückgabe
Ein Zeiger auf left.compose(right), der dem Operator result = right @ left im Sinne der Matrixmultiplikation entspricht @. Mit anderen Worten: right wird zuerst angewendet. Um das Ergebnis zu erhalten left @ right, tausche die Argumente aus.
qf_ferm_op_adjoint
QfFermionOperator *qf_ferm_op_adjoint(const QfFermionOperator *op)
Gibt das hermitische Konjugat (oder Adjunkten) eines Operators zurück.
Dies wirkt sich wie folgt auf die Terme und Koeffizienten aus:
- Die Vorgänge in jedem Term kehren ihre Reihenfolge um und wechseln zwischen Erzeugung und Vernichtung hin und her
- Die Koeffizienten sind komplex konjugiert
Beispiel
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));Parameter
- op – Ein Zeiger auf den Operator.
Rückgabe
Ein Zeiger auf den erstellten Operator.
qf_ferm_op_ichop
void qf_ferm_op_ichop(QfFermionOperator *op, double atol)
Entfernt Terme, deren Koeffizientenwert unter dem angegebenen Schwellenwert liegt.
Diese Funktion kürzt Koeffizienten ohne Rücksicht auf Verluste! Falls der Operand, auf den die Funktion angewendet wird, möglicherweise separate Koeffizienten für doppelte Terme enthält, sollten Sie stattdessen qf_ferm_op_simplify() den Aufruf in Betracht ziehen!
Beispiel
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));Parameter
- op – Ein Zeiger auf den Operator.
- atol – Die absolute Toleranz für die Koeffizientenabschneidung.
qf_ferm_op_simplify
QfFermionOperator *qf_ferm_op_simplify(const QfFermionOperator *op, double atol)
Gibt einen gleichwertigen, aber vereinfachten Operator zurück.
Bei der Vereinfachung werden zunächst alle Koeffizienten addiert, die zu gleichen Termen gehören, und anschließend nur diejenigen beibehalten, deren Gesamtkoeffizient die festgelegte Toleranz überschreitet (genau wie qf_ferm_op_ichop()).
Wenn ein Operator arithmetisch so manipuliert oder konstruiert wurde, dass keine eindeutigen Terme garantiert sind, sollte diese Methode aufgerufen werden, bevor eine Methode angewendet wird, die numerisch kleine Koeffizienten herausfiltert, um Informationsverlust zu vermeiden. Das folgende Beispiel veranschaulicht, wie Terme abgeschnitten werden qf_ferm_op_ichop() können, deren Koeffizienten in der Summe eine Größe erreichen, die eigentlich nicht abgeschnitten werden sollte:
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);Parameter
- op – Ein Zeiger auf den zu vereinfachenden fermionischen Operator.
- atol – Die absolute Toleranz für die Koeffizientenabschneidung.
Rückgabe
Ein gleichwertiger, aber vereinfachter Operator.
qf_ferm_op_normal_ordered
QfFermionOperator *qf_ferm_op_normal_ordered(const QfFermionOperator *op, const bool *sandwich)
Gibt einen Äquivalenzoperator mit normal geordneten Termen zurück.
Die normale Reihenfolge eines Operatorterms ist so definiert, dass alle Erzeugungsaktionen vor allen Vernichtungsaktionen stehen. Innerhalb jeder Gruppe sind die betroffenen Modi lexikografisch geordnet. Ob die Reihenfolge aufsteigend oder absteigend ist, hängt vom Wert des Arguments sandwich ab:
NULL: Beide Gruppen sind lexikografisch absteigend sortiert (z. B.+_1 +_0 -_1 -_0)True: Größere Indizes erscheinen in der Mitte, d. h., Erzeugungsaktionen sind lexikografisch aufsteigend, während Vernichtungsaktionen absteigend sind (z. B.+_0 +_1 -_1 -_0)False: Kleinere Indizes erscheinen in der Mitte, d. h., Erzeugungsaktionen sind lexikografisch absteigend, während Vernichtungsaktionen aufsteigend sind (z. B.+_1 +_0 -_0 -_1)
Beispiel
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));Bei der Umordnung eines Terms müssen die Antikommutationsrelationen berücksichtigt werden: „ “, was bedeutet, dass sich die Anzahl der Terme ändern kann.
Parameter
- op – Ein Zeiger auf den Operator.
- sandwich – Ein Zeiger auf einen booleschen Wert. Dieser Zeiger kann
NULL. sein.
Rückgabe
Ein Zeiger auf den erstellten Operator.
qf_ferm_op_is_hermitian
bool qf_ferm_op_is_hermitian(const QfFermionOperator *op, double atol)
Prüft, ob ein Operator hermitisch ist.
Beispiel
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));Diese Überprüfung erfolgt qf_ferm_op_equiv() anhand der Differenz qf_ferm_op_normal_ordered() zwischen op und dessen sowie qf_ferm_op_adjoint() qf_ferm_op_zero().
Parameter
- op – Ein Zeiger auf den zu prüfenden Fermionenoperator.
- Atol – Die absolute Toleranz, bis zu der Koeffizienten als gleich angesehen werden.
Rückgabe
Ob der angegebene Operator hermitisch ist.
qf_ferm_op_max_rank
uint32_t qf_ferm_op_max_rank(const QfFermionOperator *op)
Prüft den maximalen Rang eines Operators.
Beispiel
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);Die Länge des längsten Terms kann von der Form des Operators abhängen, was bedeutet, dass (beispielsweise) eine Vereinfachung des Operators oder eine Normalordnung zu einem anderen maximalen Rang führen können.
Parameter
- op – Ein Zeiger auf den zu prüfenden Fermionenoperator.
Rückgabe
Der maximale Rang des Operators.
qf_ferm_op_conserves_particle_number
bool qf_ferm_op_conserves_particle_number(const QfFermionOperator *op)
Prüft, ob ein Operator die Teilchenanzahl bewahrt.
Dies ist der Sonderfall, bei dem qf_ferm_op_conserves_sector() alle Modi als ein einziger Block behandelt werden. Verwenden Sie diese Funktion, um zusätzlich die Erhaltung innerhalb von Modusblöcken zu gewährleisten, beispielsweise um die Erhaltung der z-Komponente des Spins neben der Teilchenzahl zu überprüfen.
Beispiel
1// A hopping term conserves the particle number, ...
2QfFermionOperator *op = qf_ferm_op_zero();
3bool actions[2] = {true, false};
4uint32_t modes[2] = {0, 2};
5QkComplex64 coeff = {1.0, 0.0};
6qf_ferm_op_add_term(op, 2, actions, modes, &coeff);
7
8assert(qf_ferm_op_conserves_particle_number(op));
9
10// ... whereas a bare creation operator does not.
11QfFermionOperator *cre = qf_ferm_op_zero();
12bool cre_actions[1] = {true};
13uint32_t cre_modes[1] = {0};
14qf_ferm_op_add_term(cre, 1, cre_actions, cre_modes, &coeff);
15
16assert(!qf_ferm_op_conserves_particle_number(cre));Parameter
- op – Ein Zeiger auf den zu prüfenden Fermionenoperator.
Rückgabe
Ob der angegebene Operator die Teilchenanzahl bewahrt.
qf_ferm_op_conserves_sector
bool qf_ferm_op_conserves_sector(const QfFermionOperator *op, const uint32_t *block_sizes, uint64_t num_blocks)
Prüft, ob ein Operator die Teilchenzahl innerhalb jedes Modusblocks erhält.
Der Modusbereich wird in aufeinanderfolgende, sich nicht überschneidende Blöcke unterteilt block_sizes : Der Block b umfasst die Modi [start_b, start_b + block_sizes[b]) wobei die Summe aller vorangehenden Blockgrößen start_b ist. Ein Term bewahrt den Sektor genau dann, wenn in jedem Block die Anzahl seiner Erzeugungsoperatoren der Anzahl seiner Vernichtungsoperatoren entspricht. Ein Term, der auf einen Modus außerhalb des letzten Blocks wirkt, bewahrt niemals den Sektor, da es keinen Block gibt, dessen Zählwert er ausgleichen könnte.
Bei einer spin-orbitalen Anordnung von norb Raumorbitalen [norb] prüft die Teilchenzahl eines spinlosen Systems, während [norb, norb] erfordert, [norb, 2 * norb) dass der Alpha-Block [0, norb) und der Beta-Block getrennt voneinander erhalten bleiben, d. h. eine strikte Erhaltung sowohl der Teilchenzahl als auch der z-Komponente des Spins.
Beispiel
1// This term hops an electron from the beta block into the alpha block.
2QfFermionOperator *op = qf_ferm_op_zero();
3bool actions[2] = {true, false};
4uint32_t modes[2] = {0, 2};
5QkComplex64 coeff = {1.0, 0.0};
6qf_ferm_op_add_term(op, 2, actions, modes, &coeff);
7
8// The total particle number is conserved, ...
9uint32_t one_block[1] = {4};
10assert(qf_ferm_op_conserves_sector(op, one_block, 1));
11assert(qf_ferm_op_conserves_sector(op, NULL, 0));
12
13// ... but the two spin sectors are not conserved individually.
14uint32_t spin_blocks[2] = {2, 2};
15assert(!qf_ferm_op_conserves_sector(op, spin_blocks, 2));Bei der Übergabe ( NULL mit auf gesetzt num_blocks``0 ) werden alle Modi als ein einziger unbegrenzter Block behandelt, wodurch dies gleichbedeutend mit ist qf_ferm_op_conserves_particle_number().
Parameter
- op – Ein Zeiger auf den zu prüfenden Fermionenoperator.
- block_sizes – Ein Zeiger auf das Array der Blockgrößen, die den Modusbereich unterteilen. Möglicherweise sollten alle Modi als ein einziger Block behandelt
NULLwerden. - num_blocks – Die Anzahl der Einträge im Array
block_sizes.
Rückgabe
Ob der angegebene Operator die Teilchenanzahl innerhalb jedes Blocks beibehält.
qf_ferm_op_equal
bool qf_ferm_op_equal(const QfFermionOperator *left, const QfFermionOperator *right)
Vergleiche zwei Operanden auf Gleichheit.
Beispiel
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));Parameter
- links – Ein Zeiger auf den Operator „links“.
- right – Ein Zeiger auf den Operator „right“.
Rückgabe
Ob die beiden Operanden gleich sind.
qf_ferm_op_equiv
bool qf_ferm_op_equiv(const QfFermionOperator *left, const QfFermionOperator *right, double atol)
Vergleiche zwei Operatoren auf Gleichheit.
Äquivalenz bedeutet in diesem Zusammenhang eine annähernde Gleichheit bis auf die angegebene absolute Toleranz. Genauer gesagt gibt diese Methode den Wert zurück True, wenn alle Absolutwerte der Koeffizienten in der Differenz unter dem festgelegten Schwellenwert liegen other - self``atol .
Beispiel
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));Parameter
- links – Ein Zeiger auf den Operator „links“.
- right – Ein Zeiger auf den Operator „right“.
- atol – Die absolute Toleranz für die Koeffizientenäquivalenz.
Rückgabe
Ob die beiden Operatoren gleichwertig sind.
qf_ferm_op_len
size_t qf_ferm_op_len(const QfFermionOperator *op)
Gibt die Länge (bzw. die Anzahl der Terme) des angegebenen Operators zurück.
Beispiel
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);Parameter
- op – Ein Zeiger auf den Fermionenoperator.
Rückgabe
Die Länge (bzw. die Anzahl der Terme) des Operators.
qf_ferm_op_relabel_modes
QfExitCode qf_ferm_op_relabel_modes(QfFermionOperator *op, uint64_t num_modes, const uint32_t *permutation)
Benennt die Indizes des angegebenen Operators um.
Beispiel
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);Parameter
- op – Ein Zeiger auf den Fermionenoperator.
- num_modes – Die Anzahl der Modusindizes in der angegebenen Permutationsliste.
- Permutation – Die Liste der Indexpermutationen.
Rückgabe
Ein Exit-Code.
QfExitCode_Successim ErfolgsfallQfExitCode_DuplicateIndexErrorfalls in der Permutation doppelte Indizes gefunden wurdenQfExitCode_IndexErrorbei allen anderen Indexfehlern, wie z. B. ungültigen Indizes.