import numpy as np
import easynn as nn

# Create a numpy array of 10 rows and 5 columns.
# Set the element at row i and column j to be i+j.
def Q1():
    array = np.zeros((10, 5))

    for i in range(10):
        for j in range(5):
            array[i, j] = i+j

    return array

# Add two numpy arrays together.
def Q2(a, b):
    return a + b

# Multiply two 2D numpy arrays using matrix multiplication.
def Q3(a, b):
    return np.matmul(a, b)

# For each row of a 2D numpy array, find the column index
# with the maximum element. Return all these column indices.
def Q4(a):
    return [ np.argmax(row) for row in a ]

# Solve Ax = b.
def Q5(A, b):
    return np.linalg.solve(A, b)

# Return an EasyNN expression for a+b.
def Q6():
    a = nn.Input('a')
    b = nn.Input('b')
    c = a+b
    return c

# Return an EasyNN expression for a+b*c.
def Q7():
    a = nn.Input('a')
    b = nn.Input('b')
    c = nn.Input('c')
    d = a+b*c
    return d

# Given A and b, return an EasyNN expression for Ax+b.
def Q8(A, b):
    A_const = nn.Const(A)
    b_const = nn.Const(b)
    x_input = nn.Input("x")

    expr = ((A_const*x_input) + b_const)

    return expr


# Given n, return an EasyNN expression for x**n.
def Q9(n):
    x = nn.Input("x")
    n_const = nn.Const(n)

    expr = x
    for _ in range(n - 1):
        expr = expr * x

    return expr

# the element-wise absolute value |x|.
def Q10():
    x = nn.Input("x")
    zero = nn.Const(0)
    max = nn.ReLU()(x)
    min = x - max
    abs = max - min
    return abs
