I have an ILP, formulated in cvxpy, where I search for a feasible solution. Phrasing it as a simple feasibility problem usually did not yield a solution. Hence, I wrote it as optimisation problem, included a timeout and check the final solution, whether it satisfies my constraints.
However, this usually takes the full timeout, even though the solution is found much earlier. Therefore, I want to include a callback, that checks for feasibility in between, and stops if a feasible solution is found.
I found the following links from Mosek but I don't know how this translates to cvxpy.
My (M)WE is the following. After 10 seconds I found a maximal value 18, but I want to stop, when I find a feasible solution of value 10.
import cvxpy as cvx
import mosek
import numpy as np
m,n = 320,160
np.random.seed(0)
A = np.random.randint(10, size = (m,n))
b = np.random.randint(10, size = m) + 100
c = np.random.randint(10, size = n)
def stop_criterion(data):
if data.sum() >= 10: break
x = cvx.Variable(n, integer = True)
prob = cvx.Problem(cvx.Maximize(c @ x), [A @ x <= b, x >= 0])
prob.solve(solver = cvx.MOSEK, mosek_params={mosek.dparam.optimizer_max_time: 10}, verbose = True)
My questions now are:
stop_criterion
in mosek_params
?stop_criterion
receive?I have an ILP, formulated in cvxpy, where I search for a feasible solution. Phrasing it as a simple feasibility problem usually did not yield a solution. Hence, I wrote it as optimisation problem, included a timeout and check the final solution, whether it satisfies my constraints.
However, this usually takes the full timeout, even though the solution is found much earlier. Therefore, I want to include a callback, that checks for feasibility in between, and stops if a feasible solution is found.
I found the following links from Mosek but I don't know how this translates to cvxpy.
My (M)WE is the following. After 10 seconds I found a maximal value 18, but I want to stop, when I find a feasible solution of value 10.
import cvxpy as cvx
import mosek
import numpy as np
m,n = 320,160
np.random.seed(0)
A = np.random.randint(10, size = (m,n))
b = np.random.randint(10, size = m) + 100
c = np.random.randint(10, size = n)
def stop_criterion(data):
if data.sum() >= 10: break
x = cvx.Variable(n, integer = True)
prob = cvx.Problem(cvx.Maximize(c @ x), [A @ x <= b, x >= 0])
prob.solve(solver = cvx.MOSEK, mosek_params={mosek.dparam.optimizer_max_time: 10}, verbose = True)
My questions now are:
stop_criterion
in mosek_params
?stop_criterion
receive?I think you can use
https://docs.mosek/10.2/pythonapi/parameters.html#mosek.dparam.lower_obj_cut https://docs.mosek/10.2/pythonapi/parameters.html#mosek.dparam.upper_obj_cut
to make Mosek terminate when a feasible solution with a certain objective value is obtained.
I doubt you can set callbacks to Mosek Cvxpy. I suggest to post the question about that at
https://github/cvxpy/cvxpy/discussions
to get an authoritative answer.
Adding MOSEK callbacks from CVXPY is certainly not possible, unless you make your own hack in CVXPY. Use MOSEK directly if you need that.
It is not quite clear what is going on, by the way. First you say that a feasibility problem did not yield a solution. In what sense? Too much time, infeasible, other issues?
Then you say you fixed it by adding an objective. While it can happen that adding an objective can help guide the solver, so a problem with an objective might solve faster than a pure feasibility problem, it is not all that typical. It is not clear if that happens for you here, or if you just formulated a different problem.
If you want you can make the solver exit after finding the first (or second, or...) feasible point by setting https://docs.mosek/latest/pythonapi/parameters.html#mosek.iparam.mio_max_num_solutions
It is not clear from your description what the data
is, for which you get values 10,18. If it is a linear expression you could just add it to the problem as a new constraint.