1

I want to solve an optimisation problem using cvxpy. Suppose I want to use log_sum_exp function to build a constraint like this:

m >= log(1 + exp(m+z))

The syntax of cvxpy allows me to create a vector variable x = [z,m] of dimension 2 and apply matrix multiplication to create a vector of expressions 0, z+m:

import cvxpy
x = cvxpy.Variable(2)
coeff = np.array([
    [0,0],
    [1,1]
])
constraints = [ x[1] >= cvxpy.log_sum_exp(coeff * x)]

When coding like this, I lose some part of the logic because I want different names for different parts of my variable array. Is there some way to use the log_sum_exp transform more explicitly, like

z = cvxpy.Variable()
m = cvxpy.Variable()
constraints = [ m >= cvxpy.log_sum_exp([0, m+z]) ]

?

I couldn't find any hints in the official docs. Thanks!

Sergey Dovgal
  • 614
  • 6
  • 21
  • 1
    [vstack?](http://www.cvxpy.org/en/latest/tutorial/functions/#vector-matrix-functions) – sascha Jul 20 '17 at 11:23
  • @sascha True, this can be achieved by typing `cvxpy.log_sum_exp(cvxpy.vstack(0, m+z))`. Should I write a separate answer for this? – Sergey Dovgal Jul 20 '17 at 12:21
  • I couldn't notice this part of manual and googling always threw me to the title page. Thanks for pointing this out. – Sergey Dovgal Jul 20 '17 at 12:23
  • Feel free to add an answer connected to your code! That function-overview is my goto-page when using cvxpy :-). – sascha Jul 20 '17 at 12:28
  • After two years, I was searching for the same question again and surprisingly, found my own post, it helped. – Sergey Dovgal Jul 08 '19 at 12:24

1 Answers1

2

As sascha pointed out, one of the manual pages

Functions in CVXPY

contains the answer. In particular, I can give an example of using log_sum_exp without matrix multiplication. Note that it is not possible to construct a correct problem within DCP (disciplined convex programming) framework using only operators exp and log because you will obtain concave function applied to convex one, which is considered as undefined behaviour. One should use a built-in constructor instead.

If you want to encode the constraint

F0 >= log( exp(F1) + exp(F2) + ... + exp(Fn) )

where F1, F2, ..., Fn are some convex expressions, and F0 is a concave expression, then instead of introducing slack variables, one can type

import cvxpy

... # Define variables and functions

constraints = [
    ...,
    something >= cvxpy.log_sum_exp(
        cvxpy.vstack(
            F1,
            F2,
            ...,
            Fn
        )
    )
]

... # Solve the optimisation problem

Note that vstack can be used both in multiple-argument style:

cvxpy.vstack(z, u)

and in list-style (but not tuples)

cvxpy.vstack([z,u])
Sergey Dovgal
  • 614
  • 6
  • 21