pythoncvxpy

cvxpy print constraint equation post optimization


I probably have a very easy question, but I couldn't find an answer online. I have an optimization problem with many constraints. Hence, when the solution is infeasible, I loop through each of the constraints to explore what could have gone wrong. One of the things I would need to do is simply print the actual equation of each constraint. For example:

x1 = cvx.Variable(5)
        y1 = cvx.Variable(5)
        
        ones_vector = np.ones((5))*1.0
        zeros_vect = np.zeros((5))
        cons1 = x1 >= (ones_vector-zeros_vect ) 
        cons2 = y1 >= ones_vector 
        k = np.ones((5))*(-4)
        cons3 = (x1 + y1) <= k
        list_cons = [cons1, cons2, cons3]
        
        
        obj_func = ones_vector.T @ (x1+y1)
        
        prob = cvx.Problem(cvx.Minimize(obj_func), list_cons )
        p.solve()
        for cons in list_cons:
            print(cons)

The final loop prints the constraints to stdout. When printing cons1, my expectation (need) is to see: "x1 >= (ones_vector-zeros_vect ) ". However, it prints the following "[1. 1. 1. 1. 1.] <= var2186". This is clearly a simplistic example, with the right hand side of constraint1 being a vector of ones minus a vector of zeros. In my actual problem, those expressions are way bigger and more complex, hence displaying the actual values is useless on my end. Does anybody know how I could print the actual expression syntax "x1 >= (ones_vector-zeros_vect ) "? Thanks


Solution

  • You would have to indicate the expression structure to CVXPY before you subtract the arrays. I did:

    import cvxpy as cvx
    import numpy as np
    
    x1 = cvx.Variable(5)
    y1 = cvx.Variable(5)
    
    ones_vector = np.ones((5))*1.0
    zeros_vect = np.zeros((5))
    cons1 = x1 >= (cvx.Constant(ones_vector)-cvx.Constant(zeros_vect) )
    
    print(cons1)
    

    and got

    [1. 1. 1. 1. 1.] + -[0. 0. 0. 0. 0.] <= var0
    

    I don't know if can be reduced further to avoid printing the values. It can be done with parameters because they, like variables, can be named:

    import cvxpy as cvx
    import numpy as np
    
    x1 = cvx.Variable(100, name="xx")
    y1 = cvx.Variable(100)
    
    p1 = cvx.Parameter(100, name="pp")
    p2 = cvx.Parameter(100, name="qq")
    
    p1.value =  np.ones((100))*1.0
    p2.value = np.zeros((100))
    cons1 = x1 >= (p1-p2 )
    
    print(cons1)
    

    prints:

    pp + -qq <= xx
    

    Also note that most solvers have some option that allows printing the problem they actually receive in some more or less standard text format.