def transform_matrix_frac(expr): assert len(expr.arg) == 2 x, P = expr.arg n = dim(P, 0) M = epi_var(expr, "matrix_frac_M", size=(n+1,n+1)) t = epi_var(expr, "matrix_frac") return t, [ expression.eq_constraint(expression.index(M, 0, n, 0, n), P), expression.eq_constraint(expression.index(M, 0, n, n, n+1), x), expression.eq_constraint(expression.index(M, n, n+1, n, n+1), t), expression.semidefinite(M)]
def transform_sigma_max(expr): X = only_arg(expr) m, n = dims(X) S = epi_var(expr, "sigma_max_S", size=(m+n, m+n)) t = epi_var(expr, "sigma_max") t_In = expression.diag_vec(expression.multiply(expression.ones(n, 1), t)) t_Im = expression.diag_vec(expression.multiply(expression.ones(m, 1), t)) return t, [ expression.eq_constraint(expression.index(S, 0, n, 0, n), t_In), expression.eq_constraint(expression.index(S, n, n+m, 0, n), X), expression.eq_constraint(expression.index(S, n, n+m, n, n+m), t_Im), expression.semidefinite(S)]
def transform_matrix_frac(expr): assert len(expr.arg) == 2 x, P = expr.arg n = dim(P, 0) M = epi_var(expr, "matrix_frac_M", size=(n + 1, n + 1)) t = epi_var(expr, "matrix_frac") return t, [ expression.eq_constraint(expression.index(M, 0, n, 0, n), P), expression.eq_constraint(expression.index(M, 0, n, n, n + 1), x), expression.eq_constraint(expression.index(M, n, n + 1, n, n + 1), t), expression.semidefinite(M) ]
def transform_sigma_max(expr): X = only_arg(expr) m, n = dims(X) S = epi_var(expr, "sigma_max_S", size=(m + n, m + n)) t = epi_var(expr, "sigma_max") t_In = expression.diag_vec(expression.multiply(expression.ones(n, 1), t)) t_Im = expression.diag_vec(expression.multiply(expression.ones(m, 1), t)) return t, [ expression.eq_constraint(expression.index(S, 0, n, 0, n), t_In), expression.eq_constraint(expression.index(S, n, n + m, 0, n), X), expression.eq_constraint(expression.index(S, n, n + m, n, n + m), t_Im), expression.semidefinite(S) ]
def transform_norm_p(expr): p = expr.p x = only_arg(expr) t = epi_var(expr, "norm_p", size=(1,1)) 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: 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_nuc(expr): X = only_arg(expr) m, n = dims(X) T = epi_var(expr, "norm_nuc", size=(m+n, m+n)) obj = expression.multiply( expression.scalar_constant(0.5), expression.trace(T)) return obj, [ expression.semidefinite(T), expression.eq_constraint(expression.index(T, 0, m, m, m+n), X)]
def transform_norm_nuc(expr): X = only_arg(expr) m, n = dims(X) T = epi_var(expr, "norm_nuc", size=(m + n, m + n)) obj = expression.multiply(expression.scalar_constant(0.5), expression.trace(T)) return obj, [ expression.semidefinite(T), expression.eq_constraint(expression.index(T, 0, m, m, m + n), X) ]
def transform_huber(expr): n = epi_var(expr, "huber_n") s = epi_var(expr, "huber_s") # n**2 + 2*M*|s| t, constr = transform_expr( expression.add( expression.power(n, 2), expression.multiply(expression.scalar_constant(2 * expr.M), expression.abs_val(s)))) # x == s + n x = only_arg(expr) constr.append(expression.eq_constraint(x, expression.add(s, n))) return t, constr
def transform_huber(expr): n = epi_var(expr, "huber_n") s = epi_var(expr, "huber_s") # n**2 + 2*M*|s| t, constr = transform_expr( expression.add( expression.power(n, 2), expression.multiply( expression.scalar_constant(2*expr.M), expression.abs_val(s)))) # x == s + n x = only_arg(expr) constr.append(expression.eq_constraint(x, expression.add(s, n))) return t, constr
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)
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)
def epi(f_expr, t_expr): """An expression for an epigraph constraint. The constraint depends on the curvature of f: - f convex, I(f(x) <= t) - f concave, I(f(x) >= t) - f affine, I(f(x) == t) """ f_curvature = f_expr.dcp_props.curvature.curvature_type if f_curvature == Curvature.CONVEX: return expression.leq_constraint(f_expr, t_expr) elif f_curvature == Curvature.CONCAVE: return expression.leq_constraint(negate(f_expr), negate(t_expr)) elif f_curvature == Curvature.AFFINE: return expression.eq_constraint(f_expr, t_expr); raise TransformError("Unknown curvature", f_expr)
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 epi(f_expr, t_expr): """An expression for an epigraph constraint. The constraint depends on the curvature of f: - f convex, I(f(x) <= t) - f concave, I(f(x) >= t) - f affine, I(f(x) == t) """ f_curvature = f_expr.dcp_props.curvature.curvature_type if f_curvature == Curvature.CONVEX: return expression.leq_constraint(f_expr, t_expr) elif f_curvature == Curvature.CONCAVE: return expression.leq_constraint(expression.negate(f_expr), expression.negate(t_expr)) elif f_curvature == Curvature.AFFINE: return expression.eq_constraint(f_expr, t_expr) raise TransformError( "Unknown curvature: %s" % Curvature.Type.Name(f_curvature), f_expr)
def convert_constraint(constraint): if isinstance(constraint, EqConstraint): return expression.eq_constraint(convert_expression(constraint.args[0]), convert_expression(constraint.args[1])) elif isinstance(constraint, PSDConstraint): return expression.psd_constraint( convert_expression(constraint.args[0]), convert_expression(constraint.args[1])) elif isinstance(constraint, LeqConstraint): return expression.leq_constraint( convert_expression(constraint.args[0]), convert_expression(constraint.args[1])) elif isinstance(constraint, SOC_Elemwise): return expression.soc_elemwise_constraint( convert_expression(constraint.t), *[convert_expression(x) for x in constraint.x_elems]) elif isinstance(constraint, SOC): return expression.soc_contraint( convert_expression(constraint.t), expression.vstack( *[convert_expression(x) for x in constraint.x_elems])) raise RuntimeError("Unknown constraint: %s" % type(constraint))
def convert_constraint(constraint): if isinstance(constraint, EqConstraint): return expression.eq_constraint( convert_expression(constraint.args[0]), convert_expression(constraint.args[1])) elif isinstance(constraint, PSDConstraint): return expression.psd_constraint( convert_expression(constraint.args[0]), convert_expression(constraint.args[1])) elif isinstance(constraint, LeqConstraint): return expression.leq_constraint( convert_expression(constraint.args[0]), convert_expression(constraint.args[1])) elif isinstance(constraint, SOC_Elemwise): return expression.soc_elemwise_constraint( convert_expression(constraint.t), *[convert_expression(x) for x in constraint.x_elems]) elif isinstance(constraint, SOC): return expression.soc_contraint( convert_expression(constraint.t), expression.vstack( *[convert_expression(x) for x in constraint.x_elems])) raise RuntimeError("Unknown constraint: %s" % type(constraint))