• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

adc-connect / adcc / 5362537629

pending completion
5362537629

push

github

mfherbst
Bump version: 0.15.16 → 0.15.17

1487 of 2318 branches covered (64.15%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

7130 of 9470 relevant lines covered (75.29%)

191956.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.16
/adcc/solver/power_method.py
1
#!/usr/bin/env python3
2
## vi: tabstop=4 shiftwidth=4 softtabstop=4 expandtab
3
## ---------------------------------------------------------------------
4
##
5
## Copyright (C) 2019 by the adcc authors
6
##
7
## This file is part of adcc.
8
##
9
## adcc is free software: you can redistribute it and/or modify
10
## it under the terms of the GNU General Public License as published
11
## by the Free Software Foundation, either version 3 of the License, or
12
## (at your option) any later version.
13
##
14
## adcc is distributed in the hope that it will be useful,
15
## but WITHOUT ANY WARRANTY; without even the implied warranty of
16
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
## GNU General Public License for more details.
18
##
19
## You should have received a copy of the GNU General Public License
20
## along with adcc. If not, see <http://www.gnu.org/licenses/>.
21
##
22
## ---------------------------------------------------------------------
23
import sys
2✔
24
import warnings
2✔
25
import numpy as np
2✔
26

27
from .SolverStateBase import EigenSolverStateBase
2✔
28
from .explicit_symmetrisation import IndexSymmetrisation
2✔
29

30
import scipy.linalg as la
2✔
31

32

33
class PowerMethodState(EigenSolverStateBase):
2✔
34
    def __init__(self, A):
2✔
35
        super().__init__(A)
2✔
36
        self.residuals = None
2✔
37
        self.algorithm = "power_method"
2✔
38

39

40
def default_print(state, identifier, file=sys.stdout):
2✔
41
    """
42
    A default print function for the power_method callback
43
    """
44
    from adcc.timings import strtime, strtime_short
2✔
45

46
    if identifier == "start" and state.n_iter == 0:
2✔
47
        print("Niter residual  time  Ritz value", file=file)
2✔
48
    elif identifier == "next_iter":
2✔
49
        time_iter = state.timer.current("power_method/iteration")
2✔
50
        fmt = "{n_iter:3d}  {residual:12.5g}  {tstr:5s}"
2✔
51
        print(fmt.format(n_iter=state.n_iter, tstr=strtime_short(time_iter),
2✔
52
                         residual=np.max(state.residual_norms)),
53
              "", state.eigenvalues[:7], file=file)
54
    elif identifier == "is_converged":
2!
55
        soltime = state.timer.total("power_method/iteration")
2✔
56
        print("=== Converged ===", file=file)
2✔
57
        print("    Number of matrix applies:   ", state.n_applies)
2✔
58
        print("    Total solver time:          ", strtime(soltime))
2✔
59

60

61
def power_method(A, guess, conv_tol=1e-9, max_iter=70, callback=None,
2✔
62
                 explicit_symmetrisation=IndexSymmetrisation):
63
    """Use the power iteration to solve for the largest eigenpair of A.
64

65
    The power method is a very simple diagonalisation method, which solves
66
    for the (by magnitude) largest eigenvalue of the matrix `A`.
67

68
    Parameters
69
    ----------
70
    A
71
        Matrix object. Only the `@` operator needs to be implemented.
72
    guess
73
        Matrix used as a guess
74
    conv_tol : float
75
        Convergence tolerance on the l2 norm of residuals to consider
76
        them converged.
77
    max_iter : int
78
        Maximal numer of iterations
79
    callback
80
        Callback function called after each iteration
81
    explicit_symmetrisation
82
        Explicit symmetrisation to perform during iteration to ensure
83
        obtaining an eigenvector with matching symmetry criteria.
84
    """
85
    if callback is None:
2!
86
        def callback(state, identifier):
×
87
            pass
×
88

89
    if explicit_symmetrisation is not None and \
2!
90
            isinstance(explicit_symmetrisation, type):
91
        explicit_symmetrisation = explicit_symmetrisation(A)
×
92

93
    x = guess / np.sqrt(guess @ guess)
2✔
94
    state = PowerMethodState(A)
2✔
95

96
    def is_converged(state):
2✔
97
        return state.residual_norms[0] < conv_tol
2✔
98

99
    callback(state, "start")
2✔
100
    state.timer.restart("power_method/iteration")
2✔
101
    for i in range(max_iter):
2!
102
        state.n_iter += 1
2✔
103
        Ax = A @ x
2✔
104
        state.n_applies += 1
2✔
105

106
        eigval = x @ (Ax)
2✔
107
        residual = Ax - eigval * x
2✔
108
        residual_norm = np.sqrt(residual @ residual)
2✔
109
        state.eigenvalues = np.array([eigval])
2✔
110
        state.eigenvectors = np.array([x])
2✔
111
        state.residual_norms = np.array([residual_norm])
2✔
112

113
        callback(state, "next_iter")
2✔
114
        state.timer.restart("power_method/iteration")
2✔
115
        if is_converged(state):
2✔
116
            state.converged = True
2✔
117
            callback(state, "is_converged")
2✔
118
            state.timer.stop("power_method/iteration")
2✔
119
            return state
2✔
120

121
        if explicit_symmetrisation:
2✔
122
            x = explicit_symmetrisation.symmetrise(Ax)
2✔
123
        else:
124
            x = Ax
2✔
125
        x = x / np.sqrt(x @ x)
2✔
126

127
    warnings.warn(la.LinAlgWarning(
×
128
        "Power method not converged. Returning intermediate results."))
129
    return state
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc