Ejemplo n.º 1
0
def huber(x, M=1):
    """The Huber function

    Huber(x, M) = 2M|x|-M^2 for |x| >= |M|
                  |x|^2 for |x| <= |M|
    M defaults to 1.

    Parameters
    ----------
    x : Expression
        A CVXPY expression.
    M : int/float
    """
    # TODO require that M is positive?
    return square(M)*huber_pos(abs(x)/abs(M))
Ejemplo n.º 2
0
def huber(x, M=1):
    """The Huber function

    Huber(x, M) = 2M|x|-M^2 for |x| >= |M|
                  |x|^2 for |x| <= |M|
    M defaults to 1.

    Parameters
    ----------
    x : Expression
        A CVXPY expression.
    M : int/float
    """
    # TODO require that M is positive?
    return square(M) * huber_pos(abs(x) / abs(M))
Ejemplo n.º 3
0
def norm1_canon(expr, args):
    x = args[0]
    axis = expr.axis

    # we need an absolute value constraint for the symmetric convex branches
    # (p >= 1)
    constraints = []
    # TODO(akshayka): Express this more naturally (recursively), in terms
    # of the other atoms
    abs_expr = abs(x)
    abs_x, abs_constraints = abs_canon(abs_expr, abs_expr.args)
    constraints += abs_constraints
    return sum(abs_x, axis=axis), constraints
Ejemplo n.º 4
0
def pnorm_canon(expr, args):
    x = args[0]
    p = expr.p
    axis = expr.axis
    shape = expr.shape
    t = Variable(shape)

    if p == 2:
        if axis is None:
            assert shape == tuple()
            return t, [SOC(t, vec(x))]
        else:
            return t, [SOC(vec(t), x, axis)]

    # we need an absolute value constraint for the symmetric convex branches
    # (p > 1)
    constraints = []
    if p > 1:
        # TODO(akshayka): Express this more naturally (recursively), in terms
        # of the other atoms
        abs_expr = abs(x)
        abs_x, abs_constraints = abs_canon(abs_expr, abs_expr.args)
        x = abs_x
        constraints += abs_constraints

    # now, we take care of the remaining convex and concave branches
    # to create the rational powers, we need a new variable, r, and
    # the constraint sum(r) == t
    r = Variable(x.shape)
    constraints += [sum(r) == t]

    # todo: no need to run gm_constr to form the tree each time.
    # we only need to form the tree once
    promoted_t = Constant(np.ones(x.shape)) * t
    p = Fraction(p)
    if p < 0:
        constraints += gm_constrs(promoted_t, [x, r],
                                  (-p / (1 - p), 1 / (1 - p)))
    if 0 < p < 1:
        constraints += gm_constrs(r, [x, promoted_t], (p, 1 - p))
    if p > 1:
        constraints += gm_constrs(x, [r, promoted_t], (1 / p, 1 - 1 / p))

    return t, constraints
Ejemplo n.º 5
0
def huber_canon(expr, args):
    M = expr.M
    x = args[0]
    shape = expr.shape
    n = Variable(shape)
    s = Variable(shape)

    # n**2 + 2*M*|s|
    # TODO(akshayka): Make use of recursion inherent to canonicalization
    # process and just return a power / abs expressions for readability sake
    power_expr = power(n, 2)
    n2, constr_sq = power_canon(power_expr, power_expr.args)
    abs_expr = abs(s)
    abs_s, constr_abs = abs_canon(abs_expr, abs_expr.args)
    obj = n2 + 2 * M * abs_s

    constraints = constr_sq + constr_abs
    constraints.append(x == s + n)

    return obj, constraints