Пример #1
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]
        n, _ = A.size
        # Requires that A is symmetric.
        obj, constraints = transpose.graph_implementation([A], (n, n))
        # A == A.T
        constraints.append(lu.create_eq(A, obj))
        # SDP constraint.
        t = lu.create_var((1, 1))
        prom_t = lu.promote(t, (n, 1))
        # I*t - A
        expr = lu.sub_expr(A, lu.diag_vec(prom_t))
        return (t, [SDP(expr)] + constraints)
Пример #2
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        t = lu.create_var(size)
        constraints = []
        for obj in arg_objs:
            # Promote obj.
            if obj.size != size:
                obj = lu.promote(obj, size)
            constraints.append(lu.create_leq(obj, t))
        return (t, constraints)
Пример #3
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        x = arg_objs[0]
        t = lu.create_var((1, 1))
        # sum(exp(x - t))
        prom_t = lu.promote(t, x.size)
        expr = lu.sub_expr(x, prom_t)
        obj, constraints = exp.graph_implementation([expr], x.size)
        obj = lu.sum_entries(obj)
        # obj <= 1
        one = lu.create_const(1, (1, 1))
        constraints += [lu.create_leq(obj, one)]
        return (t, constraints)
Пример #4
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Promote scalars.
        for idx, arg in enumerate(arg_objs):
            if arg.size != size:
                arg_objs[idx] = lu.promote(arg, size)
        x = arg_objs[0]
        y = arg_objs[1]
        v = lu.create_var(x.size)
        two = lu.create_const(2, (1, 1))
        # SOC(x + y, [y - x, 2*v])
        constraints = [
            SOC_Elemwise(lu.sum_expr([x, y]),
                         [lu.sub_expr(y, x),
                          lu.mul_expr(two, v, v.size)])
        ]
        # 0 <= x, 0 <= y
        constraints += [lu.create_geq(x), lu.create_geq(y)]
        return (v, constraints)
Пример #5
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        x = arg_objs[0]
        t = lu.create_var((1, 1))
        # sum(exp(x - t))
        prom_t = lu.promote(t, x.size)
        expr = lu.sub_expr(x, prom_t)
        obj, constraints = exp.graph_implementation([expr], x.size)
        obj, constr = sum_entries.graph_implementation([obj], (1, 1))
        # obj <= 1
        one = lu.create_const(1, (1, 1))
        constraints += constr + [lu.create_leq(obj, one)]
        return (t, constraints)
Пример #6
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # min sum_entries(t) + kq
        # s.t. x <= t + q
        #      0 <= t
        x = arg_objs[0]
        k = lu.create_const(data[0], (1, 1))
        q = lu.create_var((1, 1))
        t = lu.create_var(x.size)
        sum_t = lu.sum_entries(t)
        obj = lu.sum_expr([sum_t, lu.mul_expr(k, q, (1, 1))])
        prom_q = lu.promote(q, x.size)
        constr = [lu.create_leq(x, lu.sum_expr([t, prom_q])), lu.create_geq(t)]
        return (obj, constr)
Пример #7
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        axis = data[0]
        if axis is None:
            t = lu.create_var((1, 1))
            promoted_t = lu.promote(t, arg_objs[0].size)
        elif axis == 0:
            t = lu.create_var((1, arg_objs[0].size[1]))
            const_size = (arg_objs[0].size[0], 1)
            ones = lu.create_const(np.ones(const_size), const_size)
            promoted_t = lu.mul_expr(ones, t, arg_objs[0].size)
        else:  # axis == 1
            t = lu.create_var((arg_objs[0].size[0], 1))
            const_size = (1, arg_objs[0].size[1])
            ones = lu.create_const(np.ones(const_size), const_size)
            promoted_t = lu.rmul_expr(t, ones, arg_objs[0].size)

        constraints = [lu.create_leq(arg_objs[0], promoted_t)]
        return (t, constraints)
Пример #8
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]
        n, _ = A.size
        # SDP constraint.
        t = lu.create_var((1, 1))
        prom_t = lu.promote(t, (n, 1))
        # A - I*t
        expr = lu.sub_expr(A, lu.diag_vec(prom_t))
        return (t, [SDP(expr)])
Пример #9
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # min sum_entries(t) + kq
        # s.t. x <= t + q
        #      0 <= t
        x = arg_objs[0]
        k = lu.create_const(data[0], (1, 1))
        q = lu.create_var((1, 1))
        t = lu.create_var(x.size)
        sum_t, constr = sum_entries.graph_implementation([t], (1, 1))
        obj = lu.sum_expr([sum_t, lu.mul_expr(k, q, (1, 1))])
        prom_q = lu.promote(q, x.size)
        constr.append( lu.create_leq(x, lu.sum_expr([t, prom_q])) )
        constr.append( lu.create_geq(t) )
        return (obj, constr)
Пример #10
0
    def graph_implementation(arg_objs, shape, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        shape : tuple
            The shape of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        axis = data[0]
        if axis is None:
            t = lu.create_var((1, 1))
            promoted_t = lu.promote(t, arg_objs[0].shape)
        elif axis == 0:
            t = lu.create_var((1, arg_objs[0].shape[1]))
            const_shape = (arg_objs[0].shape[0], 1)
            ones = lu.create_const(np.ones(const_shape), const_shape)
            promoted_t = lu.mul_expr(ones, t, arg_objs[0].shape)
        else:  # axis == 1
            t = lu.create_var((arg_objs[0].shape[0], 1))
            const_shape = (1, arg_objs[0].shape[1])
            ones = lu.create_const(np.ones(const_shape), const_shape)
            promoted_t = lu.rmul_expr(t, ones, arg_objs[0].shape)

        constraints = [lu.create_leq(arg_objs[0], promoted_t)]
        return (t, constraints)
Пример #11
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        t = lu.create_var(size)
        constraints = []
        for obj in arg_objs:
            # Promote obj.
            if obj.size != size:
                obj = lu.promote(obj, size)
            constraints.append(lu.create_leq(obj, t))
        return (t, constraints)
Пример #12
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]
        n, _ = A.size
        # Requires that A is symmetric.
        # A == A.T
        obj, constraints = transpose.graph_implementation([A], (n, n))
        constraints.append(lu.create_eq(A, obj))
        # SDP constraint.
        t = lu.create_var((1, 1))
        prom_t = lu.promote(t, (n, 1))
        # I*t - A
        expr = lu.sub_expr(lu.diag_vec(prom_t), A)
        return (t, [SDP(expr)] + constraints)
Пример #13
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Promote scalars.
        for idx, arg in enumerate(arg_objs):
            if arg.size != size:
                arg_objs[idx] = lu.promote(arg, size)
        x = arg_objs[0]
        y = arg_objs[1]
        v = lu.create_var(x.size)
        two = lu.create_const(2, (1, 1))
        # SOC(x + y, [y - x, 2*v])
        constraints = [
            SOC_Elemwise(lu.sum_expr([x, y]),
                         [lu.sub_expr(y, x),
                          lu.mul_expr(two, v, v.size)])
        ]
        # 0 <= x, 0 <= y
        constraints += [lu.create_geq(x), lu.create_geq(y)]
        return (v, constraints)
Пример #14
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]
        n, _ = A.size
        # SDP constraint.
        t = lu.create_var((1, 1))
        prom_t = lu.promote(t, (n, 1))
        # I*t - A
        expr = lu.sub_expr(lu.diag_vec(prom_t), A)
        return (t, [SDP(expr)])
Пример #15
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        x = arg_objs[0]
        axis = data[0]
        t = lu.create_var(size)

        # sum(exp(x - t)) <= 1
        if axis is None:
            prom_t = lu.promote(t, x.size)
            expr = lu.sub_expr(x, prom_t)
            obj, constraints = exp.graph_implementation([expr], x.size)
            obj = lu.sum_entries(obj)

        elif axis == 0:
            prom_size = (x.size[0], 1)
            ones = lu.create_const(np.ones(prom_size), prom_size)
            prom_t = lu.mul_expr(ones, t, x.size)
            expr = lu.sub_expr(x, prom_t)
            obj, constraints = exp.graph_implementation([expr], x.size)

            const_size = (1, x.size[0])
            ones = lu.create_const(np.ones(const_size), const_size)
            obj = lu.mul_expr(ones, obj, size)

        else:  # axis == 1
            prom_size = (1, x.size[1])
            ones = lu.create_const(np.ones(prom_size), prom_size)
            prom_t = lu.rmul_expr(t, ones, x.size)
            expr = lu.sub_expr(x, prom_t)
            obj, constraints = exp.graph_implementation([expr], x.size)

            const_size = (x.size[1], 1)
            ones = lu.create_const(np.ones(const_size), const_size)
            obj = lu.rmul_expr(obj, ones, size)

        ones = lu.create_const(np.ones(size), size)
        constraints += [lu.create_leq(obj, ones)]

        return (t, constraints)
Пример #16
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        x = arg_objs[0]
        axis = data[0]
        t = lu.create_var(size)

        # sum(exp(x - t)) <= 1
        if axis is None:
            prom_t = lu.promote(t, x.size)
            expr = lu.sub_expr(x, prom_t)
            obj, constraints = exp.graph_implementation([expr], x.size)
            obj = lu.sum_entries(obj)

        elif axis == 0:
            prom_size = (x.size[0], 1)
            ones = lu.create_const(np.ones(prom_size), prom_size)
            prom_t = lu.mul_expr(ones, t, x.size)
            expr = lu.sub_expr(x, prom_t)
            obj, constraints = exp.graph_implementation([expr], x.size)

            const_size = (1, x.size[0])
            ones = lu.create_const(np.ones(const_size), const_size)
            obj = lu.mul_expr(ones, obj, size)

        else:  # axis == 1
            prom_size = (1, x.size[1])
            ones = lu.create_const(np.ones(prom_size), prom_size)
            prom_t = lu.rmul_expr(t, ones, x.size)
            expr = lu.sub_expr(x, prom_t)
            obj, constraints = exp.graph_implementation([expr], x.size)

            const_size = (x.size[1], 1)
            ones = lu.create_const(np.ones(const_size), const_size)
            obj = lu.rmul_expr(obj, ones, size)

        ones = lu.create_const(np.ones(size), size)
        constraints += [lu.create_leq(obj, ones)]

        return (t, constraints)
Пример #17
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0] # n by m matrix.
        n, m = A.size
        # Create a matrix with Schur complement I*t - (1/t)*A.T*A.
        X = lu.create_var((n+m, n+m))
        t = lu.create_var((1, 1))
        # Expand A.T.
        obj, constraints = transpose.graph_implementation([A], (m, n))
        # Fix X using the fact that A must be affine by the DCP rules.
        # X[0:n, 0:n] == I_n*t
        prom_t = lu.promote(t, (n, 1))
        index.block_eq(X, lu.diag_vec(prom_t), constraints,
                       0, n, 0, n)
        # X[0:n, n:n+m] == A
        index.block_eq(X, A, constraints,
                       0, n, n, n+m)
        # X[n:n+m, 0:n] == obj
        index.block_eq(X, obj, constraints,
                       n, n+m, 0, n)
        # X[n:n+m, n:n+m] == I_m*t
        prom_t = lu.promote(t, (m, 1))
        index.block_eq(X, lu.diag_vec(prom_t), constraints,
                       n, n+m, n, n+m)
        # Add SDP constraint.
        return (t, constraints + [SDP(X)])
Пример #18
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0] # n by m matrix.
        n, m = A.size
        # Create a matrix with Schur complement I*t - (1/t)*A.T*A.
        X = lu.create_var((n+m, n+m))
        t = lu.create_var((1, 1))
        constraints = []
        # Fix X using the fact that A must be affine by the DCP rules.
        # X[0:n, 0:n] == I_n*t
        prom_t = lu.promote(t, (n, 1))
        index.block_eq(X, lu.diag_vec(prom_t), constraints,
                       0, n, 0, n)
        # X[0:n, n:n+m] == A
        index.block_eq(X, A, constraints,
                       0, n, n, n+m)
        # X[n:n+m, n:n+m] == I_m*t
        prom_t = lu.promote(t, (m, 1))
        # prom_t = lu.promote(lu.create_const(1, (1,1)), (m, 1))
        index.block_eq(X, lu.diag_vec(prom_t), constraints,
                       n, n+m, n, n+m)
        # Add SDP constraint.
        return (t, constraints + [SDP(X)])
Пример #19
0
    def graph_implementation(arg_objs, shape, data=None):
        """Promote scalar to vector/matrix

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        shape : tuple
            The shape of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        return (lu.promote(arg_objs[0], shape), [])
Пример #20
0
    def _promote(arg, shape):
        """Promotes the lin op if necessary.

        Parameters
        ----------
        arg : LinOp
            LinOp to promote.
        shape : tuple
            The shape desired.

        Returns
        -------
        tuple
            Promoted LinOp.
        """
        if arg.shape != shape:
            return lu.promote(arg, shape)
        else:
            return arg
Пример #21
0
    def _promote(arg, size):
        """Promotes the lin op if necessary.

        Parameters
        ----------
        arg : LinOp
            LinOp to promote.
        size : tuple
            The size desired.

        Returns
        -------
        tuple
            Promoted LinOp.
        """
        if arg.size != size:
            return lu.promote(arg, size)
        else:
            return arg
Пример #22
0
    def graph_implementation(arg_objs,size,data=None):
        x = arg_objs[0]
        beta,x0 = data[0],data[1]
        beta_val,x0_val = beta.value,x0.value

        if isinstance(beta,Parameter):
            beta = lu.create_param(beta,(1,1))
        else:
            beta = lu.create_const(beta.value,(1,1))
        if isinstance(x0,Parameter):
            x0 = lu.create_param(x0,(1,1))
        else:
            x0 = lu.create_const(x0.value,(1,1))

        xi,psi = lu.create_var(size),lu.create_var(size)
        one = lu.create_const(1,(1,1))
        one_over_beta = lu.create_const(1/beta_val,(1,1))
        k = np.exp(-beta_val*x0_val)
        k = lu.create_const(k,(1,1))

        # 1/beta * (1 - exp(-beta*(xi+x0)))
        xi_plus_x0 = lu.sum_expr([xi,x0])
        minus_beta_times_xi_plus_x0  = lu.neg_expr(lu.mul_expr(beta,xi_plus_x0,size))
        exp_xi,constr_exp = exp.graph_implementation([minus_beta_times_xi_plus_x0],size)
        minus_exp_minus_etc = lu.neg_expr(exp_xi)
        left_branch = lu.mul_expr(one_over_beta, lu.sum_expr([one,minus_exp_minus_etc]),size)

        # psi*exp(-beta*r0)
        right_branch = lu.mul_expr(k,psi,size)

        obj = lu.sum_expr([left_branch,right_branch])

        #x-x0 == xi + psi, xi >= 0, psi <= 0
        zero = lu.create_const(0,size)
        constraints = constr_exp
        prom_x0 = lu.promote(x0, size)
        constraints.append(lu.create_eq(x,lu.sum_expr([prom_x0,xi,psi])))
        constraints.append(lu.create_geq(xi,zero))
        constraints.append(lu.create_leq(psi,zero))

        return (obj, constraints)
Пример #23
0
    def graph_implementation(arg_objs, size, data=None):
        """Sum the linear expressions.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        for i, arg in enumerate(arg_objs):
            if arg.size != size:
                arg_objs[i] = lu.promote(arg, size)
        return (lu.sum_expr(arg_objs), [])
Пример #24
0
    def graph_implementation(arg_objs, size, data=None):
        """Sum the linear expressions.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        for i, arg in enumerate(arg_objs):
            if arg.size != size:
                arg_objs[i] = lu.promote(arg, size)
        return (lu.sum_expr(arg_objs), [])
Пример #25
0
    def graph_implementation(arg_objs, size, data=None):
        """Multiply the linear expressions.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Promote the right hand side to a diagonal matrix if necessary.
        if size[1] != 1 and arg_objs[1].size == (1, 1):
            arg = lu.promote(arg_objs[1], (size[1], 1))
            arg_objs[1] = lu.diag_vec(arg)
        return (lu.mul_expr(arg_objs[0], arg_objs[1], size), [])
Пример #26
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        x = arg_objs[0]
        t = lu.create_var((1, 1))
        promoted_t = lu.promote(t, x.size)
        constraints = [lu.create_leq(promoted_t, x)]
        return (t, constraints)
Пример #27
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        x = arg_objs[0]
        t = lu.create_var((1, 1))
        promoted_t = lu.promote(t, x.size)
        constraints = [lu.create_leq(x, promoted_t)]
        return (t, constraints)
Пример #28
0
    def graph_implementation(arg_objs, size, data=None):
        """Multiply the linear expressions.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Promote the left hand side to a diagonal matrix if necessary.
        if size[0] != 1 and arg_objs[0].size == (1, 1):
            arg = lu.promote(arg_objs[0], (size[0], 1))
            arg_objs[0] = lu.diag_vec(arg)
        return (lu.rmul_expr(arg_objs[0], arg_objs[1], size), [])
Пример #29
0
    def graph_implementation(arg_objs, size, data=None):
        """Multiply the expressions elementwise.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Promote arguments if necessary.
        for i, arg in enumerate(arg_objs):
            if arg.size != size:
                arg_objs[i] = lu.promote(arg, size)

        return (lu.mul_elemwise(arg_objs[0], arg_objs[1]), [])
Пример #30
0
    def graph_implementation(arg_objs, size, data=None):
        """Multiply the expressions elementwise.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Promote arguments if necessary.
        for i, arg in enumerate(arg_objs):
            if arg.size != size:
                arg_objs[i] = lu.promote(arg, size)

        return (lu.mul_elemwise(arg_objs[0], arg_objs[1]), [])
Пример #31
0
    def graph_implementation(self,
                             arg_objs,
                             shape: Tuple[int, ...],
                             data=None) -> Tuple[lo.LinOp, List[Constraint]]:
        """Sum the linear expressions.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        shape : tuple
            The shape of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        for i, arg in enumerate(arg_objs):
            if arg.shape != shape and lu.is_scalar(arg):
                arg_objs[i] = lu.promote(arg, shape)
        return (lu.sum_expr(arg_objs), [])
Пример #32
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        t = lu.create_var(size)
        for i, obj in enumerate(arg_objs):
            # Promote obj.
            if obj.size != size:
                arg_objs[i] = lu.promote(obj, size)

        return (t, [SOC_Elemwise(t, arg_objs)])
Пример #33
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        t = lu.create_var(size)
        for i, obj in enumerate(arg_objs):
            # Promote obj.
            if obj.size != size:
                arg_objs[i] = lu.promote(obj, size)

        return (t, [SOC_Elemwise(t, arg_objs)])
Пример #34
0
    def graph_implementation(arg_objs, size, data=None):
        r"""Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)

        Notes
        -----

        Implementation notes.

        For general ``p``, the p-norm is equivalent to the following convex inequalities:

        .. math::

            x_i &\leq r_i\\
            -x_i &\leq r_i\\
            r_i &\leq s_i^{1/p} t^{1 - 1/p}\\
            \sum_i s_i &\leq t,

        where :math:`p \geq 1`.

        These inequalities are also correct for :math:`p = +\infty` if we interpret :math:`1/\infty` as :math:`0`.


        Although the inequalities above are correct, for a few special cases, we can represent the p-norm
        more efficiently and with fewer variables and inequalities.

        - For :math:`p = 1`, we use the representation

            .. math::

                x_i &\leq r_i\\
                -x_i &\leq r_i\\
                \sum_i r_i &\leq t

        - For :math:`p = \infty`, we use the representation

            .. math::

                x_i &\leq t\\
                -x_i &\leq t

          Note that we don't need the :math:`s` variables or the sum inequality.

        - For :math:`p = 2`, we use the natural second-order cone representation

            .. math::

                \|x\|_2 \leq t

          Note that we could have used the set of inequalities given above if we wanted an alternate decomposition
          of a large second-order cone into into several smaller inequalities.

        """
        p, w = data
        x = arg_objs[0]
        t = None  # dummy value so linter won't complain about initialization
        if p != 1:
            t = lu.create_var((1, 1))

        if p == 2:
            return t, [SOC(t, [x])]

        if p == np.inf:
            r = lu.promote(t, x.size)
        else:
            r = lu.create_var(x.size)

        constraints = [lu.create_geq(lu.sum_expr([x, r])),
                       lu.create_leq(x, r)]

        if p == 1:
            return lu.sum_entries(r), constraints

        if p == np.inf:
            return t, constraints

        # otherwise do case of general p
        s = lu.create_var(x.size)
        # todo: no need to run gm_constr to form the tree each time. we only need to form the tree once
        constraints += gm_constrs(r, [s, lu.promote(t, x.size)], w)
        constraints += [lu.create_leq(lu.sum_entries(s), t)]
        return t, constraints
Пример #35
0
    def graph_implementation(arg_objs, size, data=None):
        r"""Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)

        Notes
        -----

        Implementation notes.

        - For general :math:`p \geq 1`, the inequality :math:`\|x\|_p \leq t`
          is equivalent to the following convex inequalities:

          .. math::

              |x_i| &\leq r_i^{1/p} t^{1 - 1/p}\\
              \sum_i r_i &= t.

          These inequalities happen to also be correct for :math:`p = +\infty`,
          if we interpret :math:`1/\infty` as :math:`0`.

        - For general :math:`0 < p < 1`, the inequality :math:`\|x\|_p \geq t`
          is equivalent to the following convex inequalities:

          .. math::

              r_i &\leq x_i^{p} t^{1 - p}\\
              \sum_i r_i &= t.

        - For general :math:`p < 0`, the inequality :math:`\|x\|_p \geq t`
          is equivalent to the following convex inequalities:

          .. math::

              t &\leq x_i^{-p/(1-p)} r_i^{1/(1 - p)}\\
              \sum_i r_i &= t.




        Although the inequalities above are correct, for a few special cases, we can represent the p-norm
        more efficiently and with fewer variables and inequalities.

        - For :math:`p = 1`, we use the representation

            .. math::

                x_i &\leq r_i\\
                -x_i &\leq r_i\\
                \sum_i r_i &= t

        - For :math:`p = \infty`, we use the representation

            .. math::

                x_i &\leq t\\
                -x_i &\leq t

          Note that we don't need the :math:`r` variable or the sum inequality.

        - For :math:`p = 2`, we use the natural second-order cone representation

            .. math::

                \|x\|_2 \leq t

          Note that we could have used the set of inequalities given above if we wanted an alternate decomposition
          of a large second-order cone into into several smaller inequalities.

        """
        p = data[0]
        x = arg_objs[0]
        t = lu.create_var((1, 1))
        constraints = []

        # first, take care of the special cases of p = 2, inf, and 1
        if p == 2:
            return t, [SOC(t, [x])]

        if p == np.inf:
            t_ = lu.promote(t, x.size)
            return t, [lu.create_leq(x, t_), lu.create_geq(lu.sum_expr([x, t_]))]

        # we need an absolute value constraint for the symmetric convex branches (p >= 1)
        # we alias |x| as x from this point forward to make the code pretty :)
        if p >= 1:
            absx = lu.create_var(x.size)
            constraints += [lu.create_leq(x, absx), lu.create_geq(lu.sum_expr([x, absx]))]
            x = absx

        if p == 1:
            return lu.sum_entries(x), 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 = lu.create_var(x.size)
        t_ = lu.promote(t, x.size)
        constraints += [lu.create_eq(lu.sum_entries(r), t)]

        # make p a fraction so that the input weight to gm_constrs
        # is a nice tuple of fractions.
        p = Fraction(p)
        if p < 0:
            constraints += gm_constrs(t_, [x, r], (-p / (1 - p), 1 / (1 - p)))
        if 0 < p < 1:
            constraints += gm_constrs(r, [x, t_], (p, 1 - p))
        if p > 1:
            constraints += gm_constrs(x, [r, t_], (1 / p, 1 - 1 / p))

        return t, constraints