import numpy as np

v = np.array([1, 1])
v2 = np.array([[1], [1]])
u = np.array([0, -1, 2, 3, -0.3])
r = np.zeros(5)
r2 = np.zeros((5, 1))

print(v)
print(v2)
print(u)
print(r)
print(r2)

print(u[3])
u2 = u[:3]
print(u2)
u3 = u[3:]
print(u3)

def norm(x):    
    sum = 0
    for val in x:
        sum = sum + val**2
    return np.sqrt(sum)  

v = np.array([3, -1, 0, 1, 2, -1]) 
v_norm = norm(v) 
print(v_norm)


def dot_product(x, y):
    sum = 0
    for i in range(len(x)):
        sum = sum + x[i]*y[i]
    return sum 

v = np.array([3, -1, 0, 1, 2, -1]) 
u = np.array([1, 2, 3, -4, 0.2, 1]) 
print(dot_product(u, v))

v = np.array([1, -1, 3])
print(norm(v))

print(dot_product(v, v))

print(np.sqrt(dot_product(v, v)))

X = np.array([[0, 1], [1, 0]])
print(X)

Y = np.array([[1, 3, 1], [0, -0.4, 5]])
print(Y)

Z = np.array([[2, -1, 2, 7],[-1.1, 3.3, 4, 0.7],[9, -8, 2, 0]])
print(Z)

print(np.shape(Y))


def mult(A, B):
    
    C = np.zeros((np.shape(A)[0], np.shape(B)[1]))
    
    if np.shape(A)[1] == np.shape(B)[0]:
        for i in range(np.shape(A)[0]):
            row = A[i, :]
            for j in range(np.shape(B)[1]):
                col = B[:, j]
                C[i, j] = dot_product(row, col)
    else:
        raise ValueError("dimensions do not match!") 
    
    return C

X = np.array([[0, 1, 3], [2, 4, 8]])
Y = np.array([[0], [2], [-5]])
print(mult(X, Y))

def equal(A, B):
    
    if np.shape(A)[0] != np.shape(B)[0]:
        return False
    
    if np.shape(A)[1] != np.shape(B)[1]:
        return False
    
    for i in range(np.shape(A)[0]):
        for j in range(np.shape(A)[1]):
            if A[i, j] != B[i, j]:
                return False
    
    return True

print(equal(X, X))

def transpose(A):
    A_T = np.zeros((np.shape(A)[1], np.shape(A)[0]), dtype=np.complex128)

    for i in range(np.shape(A)[0]):
        for j in range(np.shape(A)[1]): 
            A_T[j, i] = A[i, j]
    
    return A_T

print(transpose(np.array([[1, 3, 0], [-1, 2, 4]], dtype=np.complex128)))

def conjugate(A):
    A_C = np.zeros_like(A, dtype=np.complex128)
    
    for i in range(np.shape(A)[0]):
        for j in range(np.shape(A)[1]):
            A_C[i, j] = np.conjugate(A[i, j])
    return A_C

A = np.array([[1, 3j, 0], [-1j + 1, 2, 4]], dtype=np.complex128)
print(conjugate(transpose(A)))

def is_hermitian(A):
    A_TC = conjugate(transpose(A))
    return equal(A, A_TC)

print(is_hermitian(A))

B = np.array([[2, 1 + 1j], [1 - 1j, 3]])
print(is_hermitian(B))

