Search code examples
cplex

Why Cplex outputs wrong result for a simple quadratic programming?


The objective function for minimizing of the problem is,

f=x^2+y^2+z^2,

where x,y,z are continuous variables.

The constraints are

x+2y-z=4,

x-y+z=-2.

The optimal soulation is $f=2.8571$, and $x=0.2857, y=1.4286, z=-0.8571$, however Cplex outputs $f=4, x=0, y=2, z=0$.

The source Python code:

import cplex

def solve_and_display(p):
    
    p.solve()

    # solution.get_status() returns an integer code
    print ("Solution status = " , p.solution.get_status(), ":",)
    # the following line prints the corresponding string
    print (p.solution.status[p.solution.get_status()])
    print ("Solution value  = ", p.solution.get_objective_value())

    numrows = p.linear_constraints.get_num()

    for i in range(numrows):
        print ("Row ", i, ":  ",)
        print ("Slack = %10f " %  p.solution.get_linear_slacks(i),)
        print ("Pi = %10f" % p.solution.get_dual_values(i))

    numcols = p.variables.get_num()

    for j in range(numcols):
        print ("Column ", j, ":  ",)
        print ("Value = %10f " % p.solution.get_values(j),)
        print ("Reduced Cost = %10f" % p.solution.get_reduced_costs(j))

import cplex
problem = cplex.Cplex()


problem.variables.add(names=['x', 'y', 'z'])

qmat = [[[0,1,2],[2, 0, 0]],
        [[0,1,2],[0, 2, 0]],
        [[0,1,2],[0, 0, 2]]]
problem.objective.set_quadratic(qmat)

# The solution is also wrong when using set_quadratic_coefficients
# problem.objective.set_quadratic_coefficients([('x', 'x', 1), ('y', 'y', 1), ('z', 'z', 1)])

problem.objective.set_sense(problem.objective.sense.minimize)

problem.linear_constraints.add(
    lin_expr=[[['x', 'y', 'z'], [1, 2, -1]], [['x', 'y', 'z'], [1, -1, 1]]],
    senses=['E', 'E'],
    rhs=[4, -2]
)

problem.solve()

print("Solution:")
print("Objective Value =", problem.solution.get_objective_value())
print("x =", problem.solution.get_values('x'))
print("y =", problem.solution.get_values('y'))
print("z =", problem.solution.get_values('z'))

Python version: 3.9

Cplex version: 22.1.1.2


Solution

  • In your model if you change

    problem.variables.add(names=['x', 'y', 'z'])
    

    into

    problem.variables.add(names=['x', 'y', 'z'],ub=[10,10,10],lb=[-10,-10,-10])
    

    you will get the right result

    By default with cplex python apis, the lower bound is 0!

    With the OPL CPLEX API you get the right result:

    dvar float x;
    dvar float y;
    dvar float z;
    
    minimize x*x+y*y+z*z;
    
    subject to
    {
    
    x+2*y-z==4;
    
    x-y+z==-2;
    }
    

    gives

    x = 0.28571;
    y = 1.4286;
    z = -0.85714;
    

    and the same with docplex

    from docplex.mp.model import Model
    
    mdl = Model(name='mdl')
    
    
    
    
    x = mdl.continuous_var(-10,10,name='x')
    y = mdl.continuous_var(-10,10,name='y')
    z = mdl.continuous_var(-10,10,name='z')
    
    decisionVars=[x,y,z]
    
    mdl.add(x+2*y-z==4)
    
    mdl.add(x-y+z==-2)
    
    mdl.minimize(x*x+y*y+z*z)
    
    mdl.solve()
    
    for v in decisionVars:
        print(v.name," = ",v.solution_value)