Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] power related convex functions #297

Open
utotch opened this issue May 25, 2019 · 4 comments
Open

[Feature Request] power related convex functions #297

utotch opened this issue May 25, 2019 · 4 comments

Comments

@utotch
Copy link

utotch commented May 25, 2019

Hi.

CVX supports power-related functions:

These functions are often used for financial problems, like portfolio optimization.

I think these functions are important and useful, but current Convex.jl haven't supported them yet.
https://convexjl.readthedocs.io/en/latest/operations.html

I request to support the functions.

@ericphanson
Copy link
Collaborator

Do you happen to know how they are implemented?

I ask for two reasons: (1) it would help anyone who would be up for implementing them in Convex, and (2) to know if there's any big obstacles to implementing them in Convex.

I was looking at matrix logarithm based functions implemented in https://github.com/hfawzi/cvxquad, and noticed arrays with > 2 dimensions are used frequently in the implementation (although the functions are just for matrices). Convex.jl only supports scalars, vectors, and matrices in its current form, which might make it hard to port CVXQUAD (which, since it doesn't have a license, would also likely require permission of the authors). So if these power-related functions also need arrays with 3+ dimensions, it might be harder to implement them in Convex. I've been toying with ideas for how to rewrite some of Convex to allow general arrays but I'm not sure when I would have time to do so. It would be interesting to see if there is the same or another obstacle to implementing these in the current form of Convex.jl, or if it's just a matter of doing it. If there is another obstacle, maybe it could be tackled at the same time as general arrays.

@utotch
Copy link
Author

utotch commented Jun 27, 2019

Thanks for the comment.

I don't have implementation-level knowledge in this time, but I asked how it is implemented in cvxpy to the author.

Simply speaking, the implementation in cvxpy is a little complicated and NOT using power cone BUT using second-order cone.
(And many solvers don't accept power cone.)

I guess cvxpy canonicalize or factorize positive power to a combination of quadratic forms, but I don't have deep knowledge about it. I'm collecting related paper info now.

@utotch
Copy link
Author

utotch commented Jun 27, 2019

I guess these part of the implementation of cvxpy could be the clue.

https://github.com/cvxgrp/cvxpy/blob/master/cvxpy/atoms/elementwise/power.py
Line 119-128

def __init__(self, x, p, max_denom=1024):
        p_old = p

        # how we convert p to a rational depends on the branch of the function
        if p > 1:
            p, w = pow_high(p, max_denom)
        elif 0 < p < 1:
            p, w = pow_mid(p, max_denom)
        elif p < 0:
            p, w = pow_neg(p, max_denom)

and
https://github.com/cvxgrp/cvxpy/blob/master/cvxpy/utilities/power_tools.py
Line 86-122

def pow_high(p, max_denom=1024):
    """ Return (t,1,x) power tuple
        x <= t^(1/p) 1^(1-1/p)
        user wants the epigraph variable t
    """
    assert p > 1
    p = Fraction(1/Fraction(p)).limit_denominator(max_denom)
    if 1/p == int(1/p):
        return int(1/p), (p, 1-p)
    return 1/p, (p, 1-p)


def pow_mid(p, max_denom=1024):
    """ Return (x,1,t) power tuple
        t <= x^p 1^(1-p)
        user wants the epigraph variable t
    """
    assert 0 < p < 1
    p = Fraction(p).limit_denominator(max_denom)
    return p, (p, 1-p)


def pow_neg(p, max_denom=1024):
    """ Return (x,t,1) power tuple
        1 <= x^(p/(p-1)) t^(-1/(p-1))
        user wants the epigraph variable t
    """
    assert p < 0
    p = Fraction(p)
    p = Fraction(p/(p-1)).limit_denominator(max_denom)
    return p/(p-1), (p, 1-p)

and also is_pow2(num) func can identry 2^4 as (2^2)^2, etc.

I'll show more info if I understand it deeper.

@odow
Copy link
Member

odow commented May 2, 2024

Now that #590 is merged, this issue can be resolved by adding support for atoms that create the various GenericConstraint{MOI.PowerCone} constraints.

See also #90

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants