# ## MIT License

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

# In[1]:
import numpy as np
import numpy.linalg as la
# In the Bauer-Fike eigenvalue sensitivity bound, an important observation is that, given a diagonalized matrix
# $$X^{- 1} A X = D$$
# that is perturbed by an additive perturbation $E$
# $$X^{- 1} (A + E) X = D + F,$$
# and if we suppose that $\mu$ is an eigenvalue of $A+E$ (and $D+F$), we have
# $$\|(\mu I - D)^{- 1}\|^{- 1} = | \mu - \lambda _k |,$$
# where $\lambda_k$ is the eigenvalue of $A$ (diagonal entry of $D$) closest to $\mu$.
#
# This notebook illustrates this latter fact. To that end, let the following be $D$:
# In[2]:
D = np.diag(np.arange(6))
D
# In[3]:
mu = 2.1
# In[4]:
mu * np.eye(6) - D
# In[5]:
la.inv(mu * np.eye(6) - D).round(3)
# In[6]:
la.norm(la.inv(mu * np.eye(6) - D), 2)
# For all $p$-norms, the norm of a diagonal matrix is the biggest (abs. value) diagonal entry, so we can also use, say, the $\infty$ norm:
# In[7]:
la.norm(la.inv(mu * np.eye(6) - D), np.inf)
# In[8]:
1/ la.norm(la.inv(mu * np.eye(6) - D), 2)
# Note that this matches the distance between $\mu$ and the closest entry of $D$.
# In[ ]: