import numpy as np

# Defining essential functions
def infimum_element(x, y):
    return x if x[0] <= y[0] else y

def supremum_element(x, y):
    return x if x[0] >= y[0] else y

def matrix_multiplication(A, B):
    row_A, column_A, membership, _ = A.shape
    row_B, column_B, _, _ = B.shape

    assert column_A == row_B, "Multiplication is not possible for the entered matrices"

    answer = np.empty((row_A, column_B, membership, 2), dtype = float)

    for i in range(row_A):
        for j in range(column_B):
            elements = []
            for membership in range(6):
                if membership in [0, 1]:
                    # Positive truth and positive indeterminacy memberships
                    infimum_list = [infimum_element(A[i, k, membership], B[k, j, membership]) for k in range(column_A)]
                    supremum_result = infimum_list[0]
                    for value in infimum_list[1:]:
                        supremum_result = supremum_element(supremum_result, value)
                    elements.append(supremum_result)

                elif membership == 2:
                    # Positive falsity membership
                    supremum_list = [supremum_element(A[i, k, membership], B[k, j, membership]) for k in range(column_A)]
                    infimum_result = supremum_list[0]
                    for value in supremum_list[1:]:
                        infimum_result = infimum_element(infimum_result, value)
                    elements.append(infimum_result)

                elif membership in [3, 4]:
                    # Negative truth and indeterminacy memberships
                    supremum_list = [supremum_element(A[i, k, membership], B[k, j, membership]) for k in range(column_A)]
                    infimum_result = supremum_list[0]
                    for value in supremum_list[1:]:
                        infimum_result = infimum_element(infimum_result, value)
                    elements.append(infimum_result)

                elif membership == 5:
                    # Negative falsity membership
                    infimum_list = [infimum_element(A[i, k, membership], B[k, j, membership]) for k in range(column_A)]
                    supremum_result = infimum_list[0]
                    for value in infimum_list[1:]:
                        supremum_result = supremum_element(supremum_result, value)
                    elements.append(supremum_result)

            answer[i, j] = np.array(elements)

    return answer

def print_answer(matrix):
    row, column, membership, _ = matrix.shape
    for i in range(row):
        print("[")
        for j in range(column):
            element = matrix[i, j]
            format = ", ".join([f"{amplitude:.2f}e^{{i.{angle:.2f}}}" for amplitude, angle in element])
            print(f"<{format}>")
        print("]")

# Entering example matrices
A = np.array([
    [
        [(0.9, 0.8), (0.1, np.pi/4), (0.8, np.pi/3), (-0.4, -np.pi/2), (-0.4, -np.pi/3), (-0.3, -0.9)],
        [(0.7, 0.9), (0.2, np.pi/6), (0.9, 0.7), (-0.7, -np.pi/6), (-0.3, -np.pi/2), (-0.6, -0.2)],
        [(0.6, 0.9), (0.8, np.pi/4), (0.9, 0.8), (-0.4, -np.pi/3), (-0.6, -np.pi/6), (-0.5, -0.3)]
    ],
    [
        [(0.8, 0.6), (0.7, 2*np.pi), (0.7, np.pi/2), (-0.9, -np.pi/4), (-0.2, -np.pi/4), (-0.8, -0.3)],
        [(0.8, 0.7), (0.5, np.pi/2), (0.8, 0.4), (-0.6, -np.pi/6), (-0.3, -np.pi/6), (-0.4, 0.2)],
        [(0.5, 0.2), (0.1, np.pi/3), (0.4, 0.1), (-0.7, -np.pi/3), (-0.4, -np.pi/2), (-0.7, -0.4)]
    ],
    [
        [(0.5, 0.1), (0.8, np.pi), (0.7, 0.9), (-0.2, -np.pi/2), (-0.2, -3*np.pi/4), (-0.2, -0.9)],
        [(0.8, 0.5), (0.4, np.pi/6), (0.6, 0.4), (-0.8, -np.pi/6), (-0.1, -np.pi/3), (-0.7, 2)],
        [(0.5, 0.4), (0.7, np.pi/2), (0.6, 0.7), (-0.2, -np.pi/3), (-0.1, -np.pi/6), (-0.3, -2.1)]
    ]
])

B = np.array([
    [
        [(0.9, 0.8), (0.7, np.pi), (0.4, np.pi), (-0.9, -np.pi/3), (-0.5, -np.pi/4), (-0.8, -0.3)],
        [(0.6, 0.5), (0.9, np.pi/2), (0.8, 0.6), (-0.6, -np.pi/4), (-0.3, -np.pi/2), (-0.5, -0.2)],
        [(0.5, 0.4), (0.7, np.pi/3), (0.3, 0.5), (-0.5, -np.pi/6), (-0.2, -np.pi/4), (-0.6, -0.1)]
    ],
[
        [(0.4, 0.7), (0.5, np.pi), (0.5, 0.3), (-0.6, -np.pi/3), (-0.8, -np.pi/4), (-0.3, -0.9)],
        [(0.4, 0.8), (0.2, np.pi/6), (0.4, 0.1), (-0.5, -np.pi/2), (-0.6, -np.pi/4), (-0.4, -0.2)],
        [(0.2, 0.4), (0.3, np.pi/4), (0.4, 0.7), (-0.8, -np.pi/6), (-0.2, -np.pi/4), (-0.2, -0.9)]
    ],
    [
        [(0.5, 0.8), (0.5, np.pi/4), (0.2, np.pi), (-0.2, -np.pi/3), (-0.9, -np.pi/2), (-0.2, 0)],
        [(0.7, 0.6), (0.6, np.pi/2), (0.6, 0.7), (-0.7, -np.pi/2), (-0.5, -np.pi/3), (-0.4, -0.1)],
        [(0.8, 0.7), (0.4, np.pi/3), (0.5, 0.5), (-0.3, -np.pi/4), (-0.6, -np.pi/6), (-0.3, -0.2)]
    ]
])
# Calling matrix_multiplication and print the answer
C = matrix_multiplication(A, B)
print("Matrix multiplication of the entered matrices is")
print_answer(C)


