Esempio n. 1
0
def prox_sum_quantile(expr):
    arg = None
    if (expr.expression_type == Expression.SUM and
        expr.arg[0].expression_type == Expression.MAX_ELEMENTWISE and
        len(expr.arg[0].arg) == 2):

        alpha, x = get_quantile_arg(expr.arg[0].arg[0])
        beta, y  = get_quantile_arg(expr.arg[0].arg[1])
        if (x is not None and y is not None and x == y):
            if (alpha.sign.sign_type == Sign.NEGATIVE and
                beta.sign.sign_type == Sign.POSITIVE):
                alpha, beta = beta, expression.negate(alpha)
                arg = x
            elif (alpha.sign.sign_type == Sign.POSITIVE and
                  beta.sign.sign_type == Sign.NEGATIVE):
                beta = expression.negate(beta)
                arg = x

    if not arg:
        return MatchResult(False)

    alpha = linear.transform_expr(alpha)
    beta = linear.transform_expr(beta)
    diagonal_arg, constrs = convert_diagonal(arg)
    return MatchResult(
        True,
        expression.prox_function(
            create_prox(
                prox_function_type=ProxFunction.SUM_QUANTILE,
                arg_size=[Size(dim=dims(arg))],
                scaled_zone_params=ProxFunction.ScaledZoneParams(
                    alpha_expr=alpha.proto_with_args,
                    beta_expr=beta.proto_with_args)),
            diagonal_arg),
        constrs)
Esempio n. 2
0
def epigraph(expr):
    f_expr, t_expr = get_epigraph(expr)
    if f_expr:
        for rule in BASE_RULES:
            result = rule(f_expr)

            if result.match:
                epi_function = result.prox_expr.prox_function
                epi_function.epigraph = True
                epi_function.arg_size.add().CopyFrom(Size(dim=dims(t_expr)))

                linear_t_expr = linear.transform_expr(t_expr)
                if linear_t_expr.affine_props.scalar:
                    constrs = []
                else:
                    linear_t_expr, constrs = epi_transform(
                        linear_t_expr, "scalar")

                return MatchResult(
                    True,
                    expression.prox_function(
                        epi_function, *(result.prox_expr.arg + [linear_t_expr])),
                    result.raw_exprs + constrs)

        # No epigraph transform found, do conic transformation
        obj, constrs = conic.transform_expr(f_expr)
        return MatchResult(
            True,
            None,
            [expression.leq_constraint(obj, t_expr)] + constrs)

    # Not in epigraph form
    return MatchResult(False)
Esempio n. 3
0
def convert_scalar(expr):
    if not expr.dcp_props.affine:
        return epi_transform(expr, "affine")
    linear_expr = linear.transform_expr(expr)
    if linear_expr.affine_props.scalar:
        return linear_expr, []
    return epi_transform(linear_expr, "scalar")
Esempio n. 4
0
def convert_scalar(expr):
    if not expr.dcp_props.affine:
        return epi_transform(expr, "affine")
    linear_expr = linear.transform_expr(expr)
    if linear_expr.affine_props.scalar:
        return linear_expr, []
    return epi_transform(linear_expr, "scalar")
Esempio n. 5
0
def convert_diagonal(expr):
    if not expr.dcp_props.affine:
        return epi_transform(expr, "affine")
    linear_expr = linear.transform_expr(expr)
    if linear_expr.affine_props.diagonal:
        return linear_expr, []
    return epi_transform(linear_expr, "diagonal")
Esempio n. 6
0
def epigraph(expr):
    f_expr, t_expr = get_epigraph(expr)
    if f_expr:
        for rule in BASE_RULES:
            result = rule(f_expr)

            if result.match:
                epi_function = result.prox_expr.prox_function
                epi_function.epigraph = True
                epi_function.arg_size.add().CopyFrom(Size(dim=dims(t_expr)))

                linear_t_expr = linear.transform_expr(t_expr)
                if linear_t_expr.affine_props.scalar:
                    constrs = []
                else:
                    linear_t_expr, constrs = epi_transform(
                        linear_t_expr, "scalar")

                return MatchResult(
                    True,
                    expression.prox_function(
                        epi_function, *(result.prox_expr.arg + [linear_t_expr])),
                    result.raw_exprs + constrs)

        # No epigraph transform found, do conic transformation
        obj, constrs = conic.transform_expr(f_expr)
        return MatchResult(
            True,
            None,
            [expression.leq_constraint(obj, t_expr)] + constrs)

    # Not in epigraph form
    return MatchResult(False)
Esempio n. 7
0
def convert_diagonal(expr):
    if not expr.dcp_props.affine:
        return epi_transform(expr, "affine")
    linear_expr = linear.transform_expr(expr)
    if linear_expr.affine_props.diagonal:
        return linear_expr, []
    return epi_transform(linear_expr, "diagonal")
Esempio n. 8
0
def prox_constant(expr):
    if expr.dcp_props.constant:
        return MatchResult(
            True,
            expression.prox_function(
                create_prox(prox_function_type=ProxFunction.CONSTANT),
                linear.transform_expr(expr)))
    else:
        return MatchResult(False)
Esempio n. 9
0
def prox_affine(expr):
    if expr.dcp_props.affine:
        return MatchResult(
            True,
            expression.prox_function(
                create_prox(prox_function_type=ProxFunction.AFFINE),
                linear.transform_expr(expr)))
    else:
        return MatchResult(False)
Esempio n. 10
0
def prox_affine(expr):
    if expr.dcp_props.affine:
        return MatchResult(
            True,
            expression.prox_function(
                create_prox(prox_function_type=ProxFunction.AFFINE),
                linear.transform_expr(expr)))
    else:
        return MatchResult(False)
Esempio n. 11
0
def prox_constant(expr):
    if expr.dcp_props.constant:
        return MatchResult(
            True,
            expression.prox_function(
                create_prox(prox_function_type=ProxFunction.CONSTANT),
                linear.transform_expr(expr)))
    else:
        return MatchResult(False)
Esempio n. 12
0
def prox_sum_quantile(expr):
    arg = None
    if (expr.expression_type == Expression.SUM and
        expr.arg[0].expression_type == Expression.MAX_ELEMENTWISE and
        len(expr.arg[0].arg) == 2):

        alpha, x = get_quantile_arg(expr.arg[0].arg[0])
        beta, y  = get_quantile_arg(expr.arg[0].arg[1])
        if (x is not None and y is not None and x == y):
            if (alpha.sign.sign_type == Sign.NEGATIVE and
                beta.sign.sign_type == Sign.POSITIVE):
                alpha, beta = beta, expression.negate(alpha)
                arg = x
            elif (alpha.sign.sign_type == Sign.POSITIVE and
                  beta.sign.sign_type == Sign.NEGATIVE):
                beta = expression.negate(beta)
                arg = x

    if not arg:
        return MatchResult(False)

    alpha = linear.transform_expr(alpha)
    beta = linear.transform_expr(beta)
    data = alpha.expression_data()
    data.update(beta.expression_data())

    diagonal_arg, constrs = convert_diagonal(arg)
    return MatchResult(
        True,
        expression.prox_function(
            create_prox(
                prox_function_type=ProxFunction.SUM_QUANTILE,
                arg_size=[Size(dim=dims(arg))],
                scaled_zone_params=ProxFunction.ScaledZoneParams(
                    alpha_expr=alpha.proto_with_args,
                    beta_expr=beta.proto_with_args)),
            diagonal_arg,
            data=data),
        constrs)
Esempio n. 13
0
def transform_linear_map(expr, constrs):
    if expr.arg[0].expression_type == Expression.LINEAR_MAP:
        # TODO(mwytock): need more complete logic here, i.e. need to do type
        # inference across the entire chain using something like affine_props
        A = affine.LinearMapType(expr.linear_map)
        B = affine.LinearMapType(expr.arg[0].linear_map)

        if ((A.kronecker_product or B.kronecker_product) and
            not (A*B).kronecker_product):
            t, epi_constrs = epi_transform(expr.arg[0], "split_linear_map")
            constrs += [linear.transform_expr(x) for x in epi_constrs]
            return expression.from_proto(expr.proto, [t], expr.data)

    return expr
Esempio n. 14
0
def add_variable_copy(f, var, graph):
    m, n = dims(var.expr)
    old_var_id = var.expr.variable.variable_id
    new_var_id = "separate:%s:%s" % (old_var_id, f.node_id)

    new_var = graph.add_node(
        expression.variable(m, n, new_var_id), VARIABLE, new_var_id)
    f.expr = replace_var(f.expr, old_var_id, new_var.expr)
    graph.remove_edge(f, var)
    graph.add_edge(f, new_var)

    eq_constr = graph.add_node(linear.transform_expr(
        expression.eq_constraint(new_var.expr, var.expr)), CONSTRAINT)
    graph.add_edge(eq_constr, new_var)
    graph.add_edge(eq_constr, var)
Esempio n. 15
0
def add_variable_copy(f, var, graph):
    m, n = dims(var.expr)
    old_var_id = var.expr.variable.variable_id
    new_var_id = "separate:%s:%s" % (old_var_id, f.node_id)

    new_var = graph.add_node(expression.variable(m, n, new_var_id), VARIABLE,
                             new_var_id)
    f.expr = replace_var(f.expr, old_var_id, new_var.expr)
    graph.remove_edge(f, var)
    graph.add_edge(f, new_var)

    eq_constr = graph.add_node(
        linear.transform_expr(expression.eq_constraint(new_var.expr,
                                                       var.expr)), CONSTRAINT)
    graph.add_edge(eq_constr, new_var)
    graph.add_edge(eq_constr, var)
Esempio n. 16
0
def convert_affine(expr):
    if not expr.dcp_props.affine:
        return epi_transform(expr, "affine")
    return linear.transform_expr(expr), []
Esempio n. 17
0
def convert_affine(expr):
    if not expr.dcp_props.affine:
        return epi_transform(expr, "affine")
    return linear.transform_expr(expr), []