import cvxpy as cp
import cvxopt
import numpy as np
from numpy import linalg


def weber_point(A):
    """
    x = weber_point(A)
    Given a matrix A with m rows and n columns, find the point that

    sum_i (a_i^T x - b_i)^2.
    x should be a cvxpy variable and you should return its value.
    """
    x = cp.Variable(A.size[1])
    f = sum([cp.norm(x - A[i,:].T,2) for i in range(A.size[0])])
    cp.Problem(cp.Minimize(f), []).solve()
    return x.value

def least_squares(A,b):
    """
    x = least_squares(A,b)
    Given a mxn matrix A, and an m dimensional vector b, find the
    parameters x that minimize the sum of squared errors
    sum_i (a_i^T x - b_i)^2.
    x should be a cvxpy variable and you should return its value.
    """

    return x.value



def least_abs(A,b):
    """
    x = least_abs(A,b)
    Given a mxn matrix A, and an m dimensional vector b, find the
    parameters x that minimize the sum of absolute errors
    sum_i |a_i^T x - b_i|
    x should be a cvxpy variable and you should return its value.
    """

    return x.value


def linear_program(c,A,b,F,g):
    """
    x = linear_program(c,A,b,F,g)
    Find the x that solve the linear program defined by
    minimize_x   c^T x
    subject to   A*x = b
                 F*x <= g

    x should be a cvxpy variable and you should return its value.
    """

    return x.value


def min_distance_hyperplane(A):
    """
    x,y = min_distance_hyperplane(A)
    Given a matrix A with m rows and n columns, find the hyperplane
    that minimizes the sum of the distances to all the points.  The
    hyperplane is defined by the n dimensional vector x and scalar y,
    and the distance from an n-dimensional point a_i to the hyperplane is
    defined as
    dist^2(a_i,(x,y)) = (a_i^T x + y)^2/norm(x,2)^2
    This may or may not be solvable via a convex program
    """

    return (x,y)
