kevin-tracy / qpax

Differentiable QP solver in JAX
MIT License
71 stars 6 forks source link

QPTEST problem z, z_box answer #9

Closed lvjonok closed 1 month ago

lvjonok commented 1 month ago

Hello! Great fix of https://github.com/kevin-tracy/qpax/issues/4 . Now the answer is indeed matches expected, but I found some differences in expected z, z_box variables after solve. Do you think this issue is introduced with clipping?

I am trying to pass the QPTEST to pass all the tests https://github.com/qpsolvers/qpsolvers/pull/304

The expected answer for the problem is the following:

solution = Solution(problem)
solution.found = True
solution.x = np.array([0.7625, 0.475])
solution.z = np.array([0.0, 4.275])
solution.z_box = np.array([0.0, 0.0])

However after all the required transformations I obtain the following from qpax:

z = Array([1.1745805e-08, 4.2749934e+00], dtype=float32)
z_box = Array([-6.6837237e-07,  2.2565496e+01], dtype=float32))

Looks like the same issue is now with https://github.com/kevin-tracy/qpax/issues/5 where the answer is correct but resulting linear and box multipliers do not match the expected result.

I doubt getting some transformations wrong, so ask for the help in investigation to speed up integration process.

Best Regards, Lev Kozlov

stephane-caron commented 1 month ago

On some problems the dual multipliers may not be unique. When that's the case, they should still satisfy optimality conditions, i.e. all residuals below some tolerance.

With a qpsolvers.Solution object you can call is_optimal(tol), or check each of the three residuals one by one. You can use this test to check whether these z, z_box returned by qpax here are valid.

lvjonok commented 1 month ago

On some problems the dual multipliers may not be unique. When that's the case, they should still satisfy optimality conditions, i.e. all residuals below some tolerance.

With a qpsolvers.Solution object you can call is_optimal(tol), or check each of the three residuals one by one. You can use this test to check whether these z, z_box returned by qpax here are valid.

Thanks for the idea! I will look into it and share the results.

stephane-caron commented 1 month ago

I will be to blame if it turns out there is redundancy in dual multipliers for this problem :sweat_smile:, as the unit test does:

            self.assertLess(norm(result.z - solution.z), tolerance)
            self.assertLess(norm(result.z_box - solution.z_box), tolerance)

However since all other solvers return the same multipliers it is likely they are unique on this problem.

Here are the problem matrices for reference:

    P = np.array([[8.0, 2.0], [2.0, 10.0]])
    q = np.array([1.5, -2.0])
    G = np.array([[-1.0, 2.0], [-2.0, -1.0]])
    h = np.array([6.0, -2.0])
    lb = np.array([0.0, 0.0])
    ub = np.array([20.0, np.inf])
lvjonok commented 1 month ago

I've run several checks with the latest 0.0.9 version of qpax and the is_optimal method, and everything seems to be working well! Thanks so much, @kevin-tracy , for the quick fixes!

kevin-tracy commented 1 month ago

Thank you!