In [111]:
    
# Import modules
import sys
import math
import numpy as np
from matplotlib import pyplot as plt
from scipy import linalg
from scipy import sparse
    
for the least squares solution $\bar{x}$ that minimizes the Euclidean length if the residual $r = b -Ax$
In [10]:
    
A = np.array([1, -4, 2, 3, 2, 2]).reshape(3, 2)
b = np.array([-3, 15, 9])
x = linalg.lstsq(A, b)
print(x[0])
    
    
In [3]:
    
A = np.array([1, 1, 1, -1, 1, 1]).reshape(3, 2)
b = np.array([2, 1, 3])
x = linalg.lstsq(A, b)
print(x[0])
    
    
The best line is $y = \frac{7}{4} + \frac{3}{4}t$
In [81]:
    
def classical_gram_schmidt_orthogonalization(A):
    Q = np.zeros(A.size).reshape(A.shape)
    R = np.zeros(A.shape[1] ** 2).reshape(A.shape[1], A.shape[1])
    for j in range(A.shape[1]):
        y = A[:,j]
        for i in range(j):
            R[i][j] = np.matmul(Q[:,i], A[:,j])
            y = y - R[i][j] * Q[:,i]
        R[j][j] = linalg.norm(y, 2)
        Q[:,j] = y / R[j][j]
    return Q, R
    
In [82]:
    
A = np.array([1, -4, 2, 3, 2, 2]).reshape(3, 2)
Q, R = classical_gram_schmidt_orthogonalization(A)
print('Q =')
print(Q)
print('R =')
print(R)
    
    
In [146]:
    
A = np.array([1, -4, 2, 3, 2, 2]).reshape(3, 2)
Q, R = linalg.qr(A)
print('Q =')
print(Q)
print('R =')
print(R)
    
    
In [204]:
    
A = np.array([1, -4, 2, 3, 2, 2]).reshape(3, 2)
b = np.array([-3, 15, 9]).T
Q, R = linalg.qr(A)
lu, piv = linalg.lu_factor(R[:2,:])
x = linalg.lu_solve([lu, piv], np.matmul(Q.T, b).reshape(3, 1)[:2])
print('x = %s' %x.T)
    
    
In [3]:
    
def modified_gram_schmidt_orthogonalization(A):
    Q = np.zeros(A.size).reshape(A.shape)
    R = np.zeros(A.shape[1] ** 2).reshape(A.shape[1], A.shape[1])
    for j in range(A.shape[1]):
        y = A[:,j]
        for i in range(j):
            R[i][j] = np.matmul(Q[:,i], y)
            y = y - R[i][j] * Q[:,i]
        R[j][j] = linalg.norm(y, 2)
        Q[:,j] = y / R[j][j]
    return Q, R
    
In [23]:
    
x = np.array([3, 4]).reshape(2, 1)
w = np.array([5, 0]).reshape(2, 1)
v = w - x
# Projection matrix
P = np.matmul(v, v.T) / np.matmul(v.T, v)
# Householder reflector
H = np.identity(P.shape[0]) - 2 * P
print('H=\n', H)
    
    
In [104]:
    
def householder_reflector(x):
    w = np.zeros(x.size)
    w[0] = linalg.norm(x, 2)
    v = (w - x).reshape(x.size, 1)
    
    # Projection matrix
    P = np.matmul(v, v.T) / np.matmul(v.T, v)
    
    # Householder reflector
    H = np.identity(P.shape[0]) - 2 * P
    
    return H
    
In [106]:
    
A = np.array([3, 1, 4, 3]).reshape(2, 2)
H1 = householder_reflector(A[:,0])
R = np.matmul(H1, A)
Q = H1
print('Q=\n', Q)
print('R=\n', R)
    
    
In [139]:
    
A = np.array([1, -4, 2, 3, 2, 2]).reshape(3, 2)
H1 = householder_reflector(A[:, 0])
TEMP = np.matmul(H1, A)
H2 = householder_reflector(TEMP[1:, 1])
H2_Ext = np.identity(H1.shape[0])
H2_Ext[-H2_TMP.shape[0]:, -H2_TMP.shape[1]:] = H2
R = np.matmul(np.matmul(H2_Ext, H1), A)
Q = np.matmul(H1, H2_Ext)
print('Q=\n', Q)
print('R=\n', R)
    
    
In [110]:
    
A = np.array([1, 1, 0, 0, 1, 0, 1, 1, 1]).reshape(3, 3)
b = np.array([1, 0, 0]).reshape(3, 1)
x0 = np.zeros(3).reshape(3, 1)
x, info = sparse.linalg.gmres(A, b, x0)
print('x = %s' %x)
    
    
In [29]:
    
A = np.arange(1, 10).reshape(3, 3)
D = np.diag(A.diagonal())
print(D)
print(linalg.inv(D))
    
    
Consider the three circles in the plane with centers $(x_1,y_1) = (-1,0)$,$(x_2,y_2) = (1,1/2)$,$(x_3,y_3) = (1,-1/2)$ 
and radii $R_1 = 1,R_2 = 1/2,R3 = 1/2$,respectively. 
Use the Gauss-Newton Method to find the point for which the sum of the squared distances to the three circles is miniminzed.
In [43]:
    
def R_xy(x, y):
    A = np.zeros(3)
    f = lambda xf, yf, R : math.sqrt(pow(x - xf, 2) + pow(y - yf, 2)) - R
    A[0] = f(-1,   0, 1)
    A[1] = f( 1, 0.5, 0.5)
    A[2] = f( 1,-0.5, 0.5)
    return A
def DR_xy(x, y):
    A = np.zeros(6).reshape(3, 2)
    fx = lambda xf, yf : (x - xf) / math.sqrt(pow(x - xf, 2) + pow(y - yf, 2))
    fy = lambda xf, yf : (y - yf) / math.sqrt(pow(x - xf, 2) + pow(y - yf, 2))
    A[0][0] = fx(-1, 0)
    A[0][1] = fy(-1, 0)
    A[1][0] = fx(1, 0.5)
    A[1][1] = fy(1, 0.5)
    A[2][0] = fx(1, -0.5)
    A[2][1] = fy(1, -0.5)
    return A
def gauss_newton_method(x0, y0, k):
    
    xk = np.array([x0, y0])
    
    for _ in range(k):
        x = xk[0]
        y = xk[1]
        A = DR_xy(x, y)
        r = R_xy(x, y)
        v = np.matmul(linalg.inv(np.matmul(A.T, A)), -np.matmul(A.T, r))
        xk = xk + v
        
    return xk
    
In [44]:
    
x = gauss_newton_method(0, 0, 8)
print('x = %s' %x)
    
    
In [75]:
    
def R_xy(c):
    c1 = c[0]
    c2 = c[1]
    c3 = c[2]
    
    r = np.zeros(5)
    f = lambda t, y : c1 * math.exp( -c2 * pow(t - c3, 2) ) - y
    
    r[0] = f(1, 3)
    r[1] = f(2, 5)
    r[2] = f(2, 7)
    r[3] = f(3, 5)
    r[4] = f(4, 1)
    
    return r
def DR_xy(data, c):
    c1 = c[0]
    c2 = c[1]
    c3 = c[2]
    
    DR = np.zeros(15).reshape(5, 3)
    
    f0 = lambda t : math.exp( -c2 * pow(t - c3, 2) )
    f1 = lambda t : -c1 * pow(t - c3, 2) * math.exp( -c2 * pow(t - c3, 2) )
    f2 = lambda t : 2 * c1 * c2 * (t - c3) * math.exp( -c2 * pow(t - c3, 2) )
    
    for i in range(5):
        t = data[i][0]
        DR[i][0] = f0(t)
        DR[i][1] = f1(t)
        DR[i][2] = f2(t)
    
    return DR
def levenberg_marquardt_method(data, c, la, k):
    ck = c
    for _ in range(k):
        A = DR_xy(data, ck)
        r = R_xy(ck)
        mAr = -np.matmul(A.T, r)
        invA = np.linalg.inv(np.matmul(A.T, A) + la * np.diag(np.matmul(A.T, A).diagonal()))
        v = np.matmul(invA, mAr)
        ck = ck + v
    return ck
    
In [168]:
    
data = np.array([(1, 3), (2, 5), (2, 7), (3, 5), (4, 1)])
c = np.array([1, 1, 1])
c = levenberg_marquardt_method(data, c, 50, 1200)
f = lambda t, c1, c2, c3 : c1 * np.exp( -c2 * np.power(t - c3, 2) )
X = np.linspace(0, 5, 100)
Y = f(X, *c)
plt.plot(X, Y, color='cyan')
plt.plot(data[:,0], data[:,1], linestyle='', markersize=8, marker='.', color='blue')
plt.show()