def prox_second_order_cone(expr): args = [] if (expr.expression_type == Expression.INDICATOR and expr.cone.cone_type == Cone.SECOND_ORDER): args = expr.arg else: f_expr, t_expr = get_epigraph(expr) if (f_expr and f_expr.expression_type == Expression.NORM_P and f_expr.p == 2): args = [t_expr, f_expr.arg[0]] # make second argument a row vector args[1] = expression.reshape(args[1], 1, dim(args[1])) if not args: return MatchResult(False) scalar_arg0, constrs0 = convert_scalar(args[0]) scalar_arg1, constrs1 = convert_scalar(args[1]) return MatchResult( True, expression.prox_function( create_prox( prox_function_type=ProxFunction.SECOND_ORDER_CONE, arg_size=[ Size(dim=dims(args[0])), Size(dim=dims(args[1]))]), scalar_arg0, scalar_arg1), constrs0 + constrs1)
def transform_norm_p(expr): p = expr.p x = only_arg(expr) t = epi_var(expr, "norm_p") if p == float("inf"): return t, [ expression.leq_constraint(x, t), expression.leq_constraint(expression.negate(x), t) ] if p == 1: return transform_expr(expression.sum_entries(expression.abs_val(x))) if p == 2: if not expr.has_axis: return t, [ expression.soc_constraint(t, expression.reshape(x, 1, dim(x))) ] if expr.axis == 0: return t, [ expression.soc_constraint(expression.reshape(t, dim(x, 1), 1), expression.transpose(x)) ] if expr.axis == 1: return t, [expression.soc_constraint(t, x)] r = epi_var(expr, "norm_p_r", size=dims(x)) t1 = expression.multiply(expression.ones(*dims(x)), t) if p < 0: p, _ = power_tools.pow_neg(p) p = Fraction(p) constrs = gm_constrs(t1, [x, r], (-p / (1 - p), 1 / (1 - p))) elif 0 < p < 1: p, _ = power_tools.pow_mid(p) p = Fraction(p) constrs = gm_constrs(r, [x, t1], (p, 1 - p)) elif p > 1: abs_x, constrs = transform_expr(expression.abs_val(x)) p, _ = power_tools.pow_high(p) p = Fraction(p) constrs += gm_constrs(abs_x, [r, t1], (1 / p, 1 - 1 / p)) constrs.append(expression.eq_constraint(expression.sum_entries(r), t)) return t, constrs
def transform_norm_p(expr): p = expr.p x = only_arg(expr) t = epi_var(expr, "norm_p") if p == float("inf"): return t, [expression.leq_constraint(x, t), expression.leq_constraint(expression.negate(x), t)] if p == 1: return transform_expr(expression.sum_entries(expression.abs_val(x))) if p == 2: if not expr.has_axis: return t, [expression.soc_constraint( t, expression.reshape(x, 1, dim(x)))] if expr.axis == 0: return t, [expression.soc_constraint( expression.reshape(t, dim(x, 1), 1), expression.transpose(x))] if expr.axis == 1: return t, [expression.soc_constraint(t, x)] r = epi_var(expr, "norm_p_r", size=dims(x)) t1 = expression.multiply(expression.ones(*dims(x)), t) if p < 0: p, _ = power_tools.pow_neg(p) p = Fraction(p) constrs = gm_constrs(t1, [x, r], (-p/(1-p), 1/(1-p))) elif 0 < p < 1: p, _ = power_tools.pow_mid(p) p = Fraction(p) constrs = gm_constrs(r, [x, t1], (p, 1-p)) elif p > 1: abs_x, constrs = transform_expr(expression.abs_val(x)) p, _ = power_tools.pow_high(p) p = Fraction(p) constrs += gm_constrs(abs_x, [r, t1], (1/p, 1-1/p)) constrs.append(expression.eq_constraint(expression.sum_entries(r), t)) return t, constrs
def transform_quad_over_lin(expr): assert len(expr.arg) == 2 x, y = expr.arg assert dim(y) == 1 t = epi_var(expr, "qol", size=(1,1)) return t, [ expression.soc_constraint( expression.add(y, t), expression.vstack( expression.add(y, expression.negate(t)), expression.reshape( expression.multiply(expression.scalar_constant(2), x), dim(x), 1))), expression.leq_constraint(expression.scalar_constant(0), y)]
def transform_quad_over_lin(expr): assert len(expr.arg) == 2 x, y = expr.arg assert dim(y) == 1 t = epi_var(expr, "qol", size=(1, 1)) return t, [ expression.soc_constraint( expression.add(y, t), expression.hstack( expression.add(y, expression.negate(t)), expression.reshape( expression.multiply(expression.scalar_constant(2), x), 1, dim(x)))), expression.leq_constraint(expression.scalar_constant(0), y) ]
def transform_constant(expr): return expression.reshape(expr, dim(expr), 1)
def transform_variable(expr): return expression.reshape(expr, dim(expr), 1)