def solve_qr_b_givens(a, b):
    gMatrixArray = qr_fact_givens.qr_fact_givens(a)

    q = numpy.asmatrix(gMatrixArray[0])
    r = numpy.asmatrix(gMatrixArray[1])

    d = common.mult_mat(numpy.transpose(q), b)

    rSize = r.shape[0]

    x = "0"

    for i in range(0, (rSize - 1)):
        x += "; 0"

    x = numpy.matrix(x, dtype=float)

    # back substitution, i = row num, j = col num
    # r = upper triangular matrix, so it starts at bottom right corner and works its way up
    # gets each x value, from x4 to x1
    # [x1+x2+x3+x4]
    # [   x2+x3+x4]
    # [      x3+x4]
    # [         x4]
    for i in range(rSize - 1, -1, -1):
        for j in range(rSize - 1, -1, -1):
            if j >= i:
                # if not at position pertaining to current x (i.e. a diagonal entry)
                if i != j:
                    d[i] = d[i] - (r[i, j] * d[j])
                elif i == j:
                    x[i] = d[i] / r[i, j]

    return (x, common.error(common.mult_mat(a, x), b))
def solve_33_iter(B, AsubB, x0, b, tol, max_iter):
    """Iteratively solve Ax = b for a 3x3 system of equations, within a given tolerance using a given decomposition of A.

    Args:
        B (matrix): 3x3 primary part of A.
        AsubB (matrix): 3x3 secondary part of A.
        x0 (matrix): 3x1 starting vector.
        b (matrix): 3x1 b for the system of equations.
        tol (float): Tolerance for the approximate solution.
        max_iter (int): Maximum number of attempted iterations.

    Returns:
        tuple(matrix, int): 3x1 approximate solution of system and number of iterations performed;

    Raises:
        ValueError: If any inputs are not expected type.
        DimensionError: If A or AsubB are not 3x3 or x0 or b are not 3x1.
        ConvergenceError: If system does not converge on a solution before max_iter iterations.
    """

    if (type(B) is not numpy.matrixlib.defmatrix.matrix) or (type(AsubB) is not numpy.matrixlib.defmatrix.matrix) or (type(x0) is not numpy.matrixlib.defmatrix.matrix) or (type(b) is not numpy.matrixlib.defmatrix.matrix) or (type(tol) is not float) or (type(max_iter) is not int):
        raise TypeError('Expected matrix, matrix, matrix, matrix, float, and int, got ' + str(type(B)) + ', ' + str(type(AsubB)) + ', ' + str(type(x0)) + ', ' + str(type(b)) + ', ' + str(type(tol)), ', and ' + str(type(max_iter)))

    if B.shape != (3, 3):
        raise common.DimensionError('Expected 3x3 matrix for B, got ' + str(B.shape))

    if AsubB.shape != (3, 3):
        raise common.DimensionError('Expected 3x3 matrix for AsubB, got ' + str(AsubB.shape))

    if x0.shape != (3, 1):
        raise common.DimensionError('Expected 3x1 matrix for x0, got ' + str(x0.shape))

    if b.shape != (3, 1):
        raise common.DimensionError('Expected 3x1 matrix for b, got ' + str(b.shape))

    Bi = common.inv_33_lower_tri(B)

    curx = x0
    itr = 0;

    while itr < max_iter:
        nextx = common.mult_mat(Bi, (b - common.mult_mat(AsubB, curx)))

        if common.error(nextx, curx) <= tol:
            return (nextx, itr)

        curx = nextx
        itr += 1

    raise common.ConvergenceError("System did not converge before " + str(max_iter) + " iterations")
def solve_lu_b(a, b) :
	matrixArray = lu_fact.lu_fact(a)

	l = numpy.asmatrix(matrixArray[0])
	u = numpy.asmatrix(matrixArray[1])
	d = numpy.matrix(b, dtype=float)

	size = u.shape[0]

	y = "0"

	for i in range(0,(size-1)) :
		y += "; 0"

	y = numpy.matrix(y, dtype = float)

	for i in range(0, size) :
		for j in range(0, size) :
			if (j <= i) :
				if (i != j) :
					if ((l[i,j] * d[j]) < 0) :
						d[i] = d[i] + (0 - (l[i,j] * d[j]))
					elif ((l[i,j] * d[j]) > 0) :
						d[i] = d[i] - (l[i,j] * d[j])
				elif (i == j) :
					if l[i,j] != 0 :
						y[i] = d[i] / l[i,j]
					else :
						y[i] = d[i]
						
	x = "0"

	for i in range(0,(size-1)) :
		x += "; 0"

	x = numpy.matrix(x, dtype = float)

	for i in range(size - 1, -1, -1) :
		for j in range(size - 1, -1, -1) :
			if (j >= i) :
				if (i != j) :
					if ( (u[i,j] * y[j]) < 0) :
						y[i] = y[i] + (0 - (u[i,j] * y[j]))
					elif ((u[i,j] * y[j]) > 0) :
						y[i] = y[i] - (u[i,j] * y[j])
				elif (i == j) :
					if l[i,j] != 0 :
						x[i] = y[i] / u[i,j]
					else :
						x[i] = y[i]
					


	return (x, common.error(common.mult_mat(a, x), b))
def lu_fact(matrix):
    matrixCopy = numpy.matrix(matrix, dtype=float);
    columns = matrix.shape[1]
    rows = matrix.shape[0]
    identity = matlib.identity(rows);
    #for each non-trivial pivot
    for m in range (0, rows-1):
        #for each row under pivot
        for n in range (m+1, rows):
            #Subtract leading/pivot times pivot row from current row
            subRow = matrixCopy[m,:]/float(matrixCopy[m,m])*matrixCopy[m,n]
            matrixCopy[n] = matrixCopy[n] - subRow
            #Put leading/pivot in corresponding location in identity
            identity[n,m] = matrixCopy[m,n]/float(matrixCopy[m,m])
    #return L, U, and error
    return (identity, matrixCopy, common.error(common.mult_mat(identity, matrixCopy), matrix))
def qr_fact_househ(matrix):

	#sets up various things that are necessary
	uSetUp = ""
	size = matrix.shape
	colSize = size[0]
	rowSize = size[1]
	cont = True
	i = 0
	normalize = 0
	houseHolder = matrix
	tempHouseHolder = houseHolder
	count = 0

	#nested for loop that creates uSetUp
	#uSetUp = contains string of numbers (end of each row signified with ;) that will make u
	for i in range(0, colSize) :
		count = 1
		uSetUp = ""
		normalize = 0
		for j in range(i, rowSize) :
			if j != i :
				if uSetUp != "" :
					uSetUp += ";"

				uSetUp += "%f" % (houseHolder[j,i])

				#added to u1 to get full u 
				normalize += houseHolder[j,i] ** 2
				#only "counts" if houseHolder[i,j] is nonzero
				if houseHolder[j,i] != 0 :
					count += 1
			
		#if "count is greater than 1"
		if count > 1 :
			#gets normalized x and adds it to u1 and prepares to add it to the string of numbers
			afterNormalize = math.sqrt(normalize + (houseHolder[i,i]**2))
			normalizedU = houseHolder[i,i] + afterNormalize
			newValStore = "%f;" % (normalizedU)

			#actually adds it to the string of numbers
			uSetUp = newValStore + uSetUp
			#fairly obvious

			u = numpy.matrix(uSetUp)
			uT = numpy.transpose(u)
			identMatrix = numpy.identity(u.shape[0])

			#creates (2uuT)/(magnitude(u)^2)
			numerator = numpy.multiply(2,common.mult_mat(u, uT))
			normalize += (houseHolder[i,i] + afterNormalize) ** 2
			numerator = numpy.divide(numerator, normalize)

			#creates H(n)
			tempHouseHolder = identMatrix - numerator

			#resizes various matrices to make it easier in the long run
			numColSize = numerator.shape[0]
			numRowSize = numerator.shape[1]
			rowSizeDiff = rowSize - numRowSize
			colSizeDiff = colSize - numColSize			
			temp = tempHouseHolder
			tempHouseHolder = numpy.identity(colSize)

			for i in range(0, colSize) :
				for j in range(0, rowSize) :
					if j >= (rowSizeDiff) and i >= (colSizeDiff) :
						tempHouseHolder[i,j] = temp[i - rowSizeDiff, j - colSizeDiff]

			#gets new H from H multiplied H(n) or original matrix
			if (houseHolder == matrix).all() :
				q = numpy.transpose(tempHouseHolder)
				houseHolder = common.mult_mat(numpy.matrixlib.defmatrix.matrix(tempHouseHolder), matrix)
			else :
				q = common.mult_mat(numpy.matrixlib.defmatrix.matrix(q),numpy.transpose(numpy.matrixlib.defmatrix.matrix(tempHouseHolder)))
				houseHolder = common.mult_mat(numpy.matrixlib.defmatrix.matrix(tempHouseHolder), numpy.matrixlib.defmatrix.matrix(houseHolder))

	error = common.error(common.mult_mat(numpy.matrixlib.defmatrix.matrix(q),numpy.matrixlib.defmatrix.matrix(houseHolder)),matrix)

	return (q, houseHolder, error)