TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
state.hpp
Go to the documentation of this file.
1// Copyright (c) 2015-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2015-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2023 Simons Foundation
4// Copyright (c) 2015-2016 Igor Krivenko
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You may obtain a copy of the License at
17// https://www.gnu.org/licenses/gpl-3.0.txt
18//
19// Authors: Michel Ferrero, Igor Krivenko, Olivier Parcollet, Nils Wentzell
20
25
26#pragma once
27
28#include "./hilbert_space.hpp"
29#include "../arrays.hpp"
31
32#include <boost/operators.hpp>
33
34#include <cstddef>
35#include <iostream>
36#include <unordered_map>
37
38namespace triqs::hilbert_space {
39
44
45 // Forward declaration.
46 template <typename HS, typename T, bool BasedOnMap> class state {};
47
62 template <typename HS, typename T, bool BasedOnMap> auto make_zero_state(state<HS, T, BasedOnMap> const &phi) {
63 return state<HS, T, BasedOnMap>{phi.get_hilbert()};
64 }
65
87 template <typename HS, typename T> class state<HS, T, true> : boost::additive<state<HS, T, true>>, boost::multiplicative<state<HS, T, true>, T> {
88 public:
90 using value_type = T;
91
93 using hilbert_space_t = HS;
94
96 using amplitude_t = std::unordered_map<fock_state_t, value_type>;
97
99 state() : hs_ptr_(nullptr) {}
100
106 state(hilbert_space_t const &hs) : hs_ptr_(&hs) {}
107
117 state(hilbert_space_t const &hs, fock_state_t f) : hs_ptr_(&hs) { map_[f] = value_type(1.0); }
118
120 [[nodiscard]] int size() const { return hs_ptr_->size(); }
121
123 [[nodiscard]] int nterms() const { return map_.size(); }
124
133 value_type &operator()(fock_state_t f) { return map_[f]; }
134
143 value_type const &operator()(fock_state_t f) const { return map_[f]; }
144
154 state &operator+=(state const &phi) {
155 for (auto const &[f, b_f] : phi.map_) {
156 auto [it, inserted] = map_.insert({f, b_f});
157 if (!inserted) it->second += b_f;
158 }
159 prune();
160 return *this;
161 }
162
172 state &operator-=(state const &phi) {
173 for (auto const &[f, b_f] : phi.map_) {
174 auto [it, inserted] = map_.insert({f, -b_f});
175 if (!inserted) it->second -= b_f;
176 }
177 prune();
178 return *this;
179 }
180
191 for (auto &[f, a_f] : map_) { a_f *= x; }
192 prune();
193 return *this;
194 }
195
206
221 friend value_type dot_product(state const &phi, state const &psi) {
222 value_type res(0.0);
223 for (auto const &[f, b_f] : phi.map_) {
225 if (psi.map_.count(f) == 1) res += conj(b_f) * psi.map_.at(f);
226 }
227 return res;
228 }
229
240 template <typename F> friend void foreach (state const &psi, F lambda) {
241 const_cast<state &>(psi).prune(); // NOLINT (why do we const cast here?)
242 for (auto const &[f, a_f] : psi.map_) lambda(f, a_f);
243 }
244
246 hilbert_space_t const &get_hilbert() const { return *hs_ptr_; }
247
252 void set_hilbert(hilbert_space_t const &new_hs) { hs_ptr_ = &new_hs; }
253
254 private:
255 // Discard all amplitudes smaller than a specific threshold.
256 void prune() {
257 for (auto it = map_.begin(); it != map_.end();) {
259 if (is_zero(it->second)) {
260 it = map_.erase(it);
261 } else {
262 ++it;
263 }
264 }
265 }
266
267 private:
268 const hilbert_space_t *hs_ptr_;
269 amplitude_t map_;
270 };
271
292 template <typename HS, typename T> class state<HS, T, false> : boost::additive<state<HS, T, false>>, boost::multiplicative<state<HS, T, false>, T> {
293 public:
295 using value_type = T;
296
298 using hilbert_space_t = HS;
299
301 using amplitude_t = nda::vector<value_type>;
302
304 state() : hs_ptr_(nullptr) {}
305
311 state(hilbert_space_t const &hs) : hs_ptr_(&hs), vec_(amplitude_t::zeros(hs.size())) {}
312
322 state(hilbert_space_t const &hs, fock_state_t f) : hs_ptr_(&hs), vec_(amplitude_t::zeros(hs.size())) { vec_[f] = value_type(1.0); }
323
325 [[nodiscard]] int size() const { return hs_ptr_->size(); }
326
336 value_type &operator()(int i) { return vec_[i]; }
337
347 value_type const &operator()(int i) const { return vec_[i]; }
348
358 state &operator+=(state const &phi) {
359 vec_ += phi.vec_;
360 return *this;
361 }
362
372 state &operator-=(state const &phi) {
373 vec_ -= phi.vec_;
374 return *this;
375 }
376
386 vec_ *= x;
387 return *this;
388 }
389
399 vec_ /= x;
400 return *this;
401 }
402
417 friend value_type dot_product(state const &phi, state const &psi) { return nda::blas::dotc(phi.vec_, psi.vec_); }
418
429 template <typename F> friend void foreach (state const &psi, F lambda) {
430 const auto dim = psi.size();
431 for (size_t i = 0; i < dim; ++i) lambda(i, psi(i));
432 }
433
435 amplitude_t const &amplitudes() const { return vec_; }
436
438 amplitude_t &amplitudes() { return vec_; }
439
441 hilbert_space_t const &get_hilbert() const { return *hs_ptr_; }
442
447 void set_hilbert(hilbert_space_t const &new_hs) { hs_ptr_ = &new_hs; }
448
449 private:
450 const hilbert_space_t *hs_ptr_;
451 amplitude_t vec_;
452 };
453
465 template <typename HS, typename T, bool BasedOnMap> std::ostream &operator<<(std::ostream &sout, state<HS, T, BasedOnMap> const &psi) {
466 bool something_written = false;
467 auto const &hs = psi.get_hilbert();
468
469 foreach (psi, [&sout, hs, &something_written](int i, auto a_f_i) {
471 if (!is_zero(a_f_i)) {
472 sout << " +(" << a_f_i << ")"
473 << "|" << hs.get_fock_state(i) << ">";
474 something_written = true;
475 }
476 });
477
478 if (!something_written) sout << 0;
479 return sout;
480 }
481
500 template <typename TargetState, typename OriginalState> TargetState project(OriginalState const &psi, hilbert_space const &proj_hs) {
501 TargetState proj_psi(proj_hs);
502 auto const &hs = psi.get_hilbert();
503 foreach (psi, [&](int i, auto a_f_i) { proj_psi(hs.get_fock_state(i)) = a_f_i; });
504 return proj_psi;
505 }
506
524 template <typename TargetState, typename OriginalState> TargetState project(OriginalState const &psi, sub_hilbert_space const &proj_hs) {
525 TargetState proj_psi(proj_hs);
526 auto const &hs = psi.get_hilbert();
527 foreach (psi, [&](int i, auto a_f_i) {
528 auto f = hs.get_fock_state(i);
529 if (proj_hs.has_state(f)) proj_psi(proj_hs.get_state_index(f)) = a_f_i;
530 });
531 return proj_psi;
532 }
533
535
536} // namespace triqs::hilbert_space
Backward-compatibility umbrella header pulling in the nda array library.
Fermionic Hilbert (Fock) space generated by a fundamental operator set.
state & operator/=(value_type x)
Division assignment operator to divide by a scalar .
Definition state.hpp:398
HS hilbert_space_t
Type of the Hilbert (Fock) space this state belongs to.
Definition state.hpp:298
nda::vector< value_type > amplitude_t
Container type for amplitudes.
Definition state.hpp:301
void set_hilbert(hilbert_space_t const &new_hs)
Set the Hilbert (Fock) space for this state.
Definition state.hpp:447
friend value_type dot_product(state const &phi, state const &psi)
Calculate the dot product of two states .
Definition state.hpp:417
state(hilbert_space_t const &hs, fock_state_t f)
Construct a new many-body state .
Definition state.hpp:322
state & operator+=(state const &phi)
Addition assignment operator to add another state .
Definition state.hpp:358
state & operator*=(value_type x)
Multiplication assignment operator to multiply a scalar .
Definition state.hpp:385
hilbert_space_t const & get_hilbert() const
Get the Hilbert (Fock) space the current state belongs to.
Definition state.hpp:441
amplitude_t & amplitudes()
Get the amplitudes as an nda::vector.
Definition state.hpp:438
state & operator-=(state const &phi)
Subtraction assignment operator to subtract another state .
Definition state.hpp:372
state(hilbert_space_t const &hs)
Construct a new many-body state .
Definition state.hpp:311
int size() const
Get the dimension of the associated Hilbert (Fock) space, i.e. .
Definition state.hpp:325
value_type & operator()(int i)
Get the amplitude for a given index .
Definition state.hpp:336
value_type const & operator()(int i) const
Get the amplitude for a given index .
Definition state.hpp:347
state()
Default constructor for a dummy state that does not belong to any Hilbert (Fock) space.
Definition state.hpp:304
amplitude_t const & amplitudes() const
Get the amplitudes as an nda::vector.
Definition state.hpp:435
T value_type
Value type of the amplitudes (either real or complex).
Definition state.hpp:295
T value_type
Value type of the amplitudes (either real or complex).
Definition state.hpp:90
int nterms() const
Get the number of non-vanishing amplitudes in the state.
Definition state.hpp:123
state & operator*=(value_type x)
Multiplication assignment operator to multiply a scalar .
Definition state.hpp:190
state()
Default constructor for a dummy state that does not belong to any Hilbert (Fock) space.
Definition state.hpp:99
friend value_type dot_product(state const &phi, state const &psi)
Calculate the dot product of two states .
Definition state.hpp:221
value_type const & operator()(fock_state_t f) const
Get the amplitude for a given Fock state .
Definition state.hpp:143
state & operator-=(state const &phi)
Subtraction assignment operator to subtract another state .
Definition state.hpp:172
void set_hilbert(hilbert_space_t const &new_hs)
Set the Hilbert (Fock) space for this state.
Definition state.hpp:252
state & operator+=(state const &phi)
Addition assignment operator to add another state .
Definition state.hpp:154
HS hilbert_space_t
Type of the Hilbert (Fock) space this state belongs to.
Definition state.hpp:93
state(hilbert_space_t const &hs)
Construct a new many-body state .
Definition state.hpp:106
int size() const
Get the dimension of the associated Hilbert (Fock) space, i.e. .
Definition state.hpp:120
std::unordered_map< fock_state_t, value_type > amplitude_t
Container type for amplitudes.
Definition state.hpp:96
state & operator/=(value_type x)
Division assignment operator to divide by a scalar .
Definition state.hpp:205
state(hilbert_space_t const &hs, fock_state_t f)
Construct a new many-body state .
Definition state.hpp:117
value_type & operator()(fock_state_t f)
Get the amplitude for a given Fock state .
Definition state.hpp:133
hilbert_space_t const & get_hilbert() const
Get the Hilbert (Fock) space the current state belongs to.
Definition state.hpp:246
Subspace of a fermionic Hilbert (Fock) space.
auto get_state_index(fock_state_t f) const
Get the index of a given Fock state within this subspace.
bool has_state(fock_state_t f) const
Check if a given Fock state belongs to this subspace.
auto make_zero_state(state< HS, T, BasedOnMap > const &phi)
Create a zero state in the same Hilbert (Fock) space as the given state.
Definition state.hpp:62
std::ostream & operator<<(std::ostream &sout, state< HS, T, BasedOnMap > const &psi)
Write a triqs::hilbert_space::state<HS, T, true> or a triqs::hilbert_space::state<HS,...
Definition state.hpp:465
uint64_t fock_state_t
Integer type representing a fermionic fock state .
TargetState project(OriginalState const &psi, hilbert_space const &proj_hs)
Project a state to a new Hilbert (Fock) space .
Definition state.hpp:500
I conj(I const &x)
Complex conjugate of an integral value.
bool is_zero(I const &x)
Exact zero check for integral values.
Provides a class to represent Hilbert (Fock) spaces.
Numeric helpers overloaded for various types.