Quantum 3xplorer (Q3)
An AI-native quantum simulation engine
Loading...
Searching...
No Matches
hermitian_eigensolver.hpp
Go to the documentation of this file.
1
#pragma once
2
3
/**
4
* HermitianEigensolver — every eigenvalue and eigenvector of a Hermitian
5
* matrix, through zheev, in one place.
6
*
7
* The workspace query, the second call and the check on `info` are the same
8
* wherever a small Hermitian matrix needs diagonalising. The caller's name is
9
* the one thing that differs, so it is the constructor argument, and the
10
* failure names it.
11
*
12
* SubspaceDiagonalizer (layer 4) is not this: it solves the generalized
13
* problem with an overlap, reports `info` for its callers to interpret, and
14
* sits two layers up, where nothing in a lower layer can reach it.
15
*/
16
17
#include <algorithm>
18
#include <stdexcept>
19
#include <string>
20
#include <utility>
21
#include <vector>
22
23
#include "
layer_0_core/math/linear_algebra/dense_matrix.hpp
"
24
#include "
layer_0_core/math/linear_algebra/hermitian_eigen_decomposition.hpp
"
25
#include "
layer_0_core/math/linear_algebra/lapack.hpp
"
26
#include "
layer_0_core/types/type_aliases.hpp
"
27
28
namespace
q3
{
29
30
class
HermitianEigensolver
{
31
public
:
32
/// `context` opens every error this solver raises: the caller, and what it was diagonalising.
33
explicit
HermitianEigensolver
(std::string context) : context_(std::move(context)) {}
34
35
/**
36
* The decomposition of `matrix`, whose upper triangle is read. Taken by
37
* value because zheev overwrites its input with the eigenvectors, which is
38
* where they are then read from.
39
*/
40
[[nodiscard]]
HermitianEigenDecomposition
solve
(
DenseMatrix<Complex>
matrix)
const
{
41
if
(matrix.
rows
() != matrix.
columns
()) {
42
throw
std::invalid_argument(context_ +
43
": a Hermitian eigenproblem needs a square "
44
"matrix, got "
+
45
std::to_string(matrix.
rows
()) +
" x "
+
46
std::to_string(matrix.
columns
()));
47
}
48
int
dimension = matrix.
rows
();
49
HermitianEigenDecomposition
decomposition;
50
decomposition.
eigenvalues
.assign(
static_cast<
std::size_t
>
(dimension), 0.0);
51
if
(dimension == 0) {
52
decomposition.
eigenvectors
= std::move(matrix);
53
return
decomposition;
54
}
55
56
int
info = 0;
57
int
workspace_size = -1;
58
Complex
workspace_query;
59
std::vector<Real> real_workspace(
static_cast<
std::size_t
>
(std::max(1, 3 * dimension - 2)));
60
lapack::zheev_
(
"V"
,
61
"U"
,
62
&dimension,
63
matrix.
data
(),
64
&dimension,
65
decomposition.
eigenvalues
.data(),
66
&workspace_query,
67
&workspace_size,
68
real_workspace.data(),
69
&info);
70
if
(info != 0) {
71
throw
std::runtime_error(
72
context_ +
": zheev workspace query failed with info = "
+ std::to_string(info));
73
}
74
workspace_size = std::max(1,
static_cast<
int
>
(workspace_query.real()));
75
std::vector<Complex> workspace(
static_cast<
std::size_t
>
(workspace_size));
76
lapack::zheev_
(
"V"
,
77
"U"
,
78
&dimension,
79
matrix.
data
(),
80
&dimension,
81
decomposition.
eigenvalues
.data(),
82
workspace.data(),
83
&workspace_size,
84
real_workspace.data(),
85
&info);
86
if
(info != 0) {
87
throw
std::runtime_error(
88
context_ +
": zheev failed with info = "
+ std::to_string(info) +
89
(info > 0 ?
"; the iteration did not converge"
:
"; an argument was invalid"
));
90
}
91
decomposition.
eigenvectors
= std::move(matrix);
92
return
decomposition;
93
}
94
95
private
:
96
std::string context_;
97
};
98
99
}
// namespace q3
q3::DenseMatrix
Definition
dense_matrix.hpp:42
q3::DenseMatrix::rows
int rows() const
Definition
dense_matrix.hpp:74
q3::DenseMatrix::data
T * data()
The column-major buffer: with rows() it is the (pointer, leading dimension) BLAS takes.
Definition
dense_matrix.hpp:95
q3::DenseMatrix::columns
int columns() const
Definition
dense_matrix.hpp:77
q3::HermitianEigensolver
Definition
hermitian_eigensolver.hpp:30
q3::HermitianEigensolver::HermitianEigensolver
HermitianEigensolver(std::string context)
context opens every error this solver raises: the caller, and what it was diagonalising.
Definition
hermitian_eigensolver.hpp:33
q3::HermitianEigensolver::solve
HermitianEigenDecomposition solve(DenseMatrix< Complex > matrix) const
Definition
hermitian_eigensolver.hpp:40
dense_matrix.hpp
hermitian_eigen_decomposition.hpp
lapack.hpp
q3::lapack::zheev_
void zheev_(const char *jobz, const char *uplo, const int *n, std::complex< double > *a, const int *lda, double *w, std::complex< double > *work, const int *lwork, double *rwork, int *info)
q3
Definition
q3_core_api.hpp:33
q3::Complex
std::complex< double > Complex
Definition
type_aliases.hpp:21
q3::HermitianEigenDecomposition
Definition
hermitian_eigen_decomposition.hpp:15
q3::HermitianEigenDecomposition::eigenvectors
DenseMatrix< Complex > eigenvectors
Definition
hermitian_eigen_decomposition.hpp:17
q3::HermitianEigenDecomposition::eigenvalues
std::vector< Real > eigenvalues
Definition
hermitian_eigen_decomposition.hpp:16
type_aliases.hpp
src
layer_0_core
math
linear_algebra
hermitian_eigensolver.hpp
Generated by
1.9.8