Forum Discussion
FICO
9 months agoCommunity Manager
Are preintsol callbacks threadsafe?
The optimizer documentation states "When the MIP callbacks are called they are MUTEX protected to allow non threadsafe user callbacks." In my Java code for one-tree Benders, if I specify a single thread for the master problem via master.controls().setThreads(1), the problem solves. If I remove that line, allowing multiple threads, I get a series of 1056 errors:
?1056 Error: Object passed as parameter 'prob' of function XPRSgetintattrib is currently being used by the optimizer - you should only use this object when the solver is not using this object or within a callbackEventually, the solver crashes (apparently while attempting to print a cut, according to the stack trace). This all takes place in a preintsol callback. The function preIntsol is declared as synchronized, which apparently does not help.
Can I use a preintsol callback with multiple threads and, if so, how?
Thanks.
3 Replies
- FICOCommunity Manager
Callbacks are in general thread safe. The error message suggests that you are using the wrong problem reference when interacting with Xpress during a callback.
When interacting with Xpress during a callback, you should use the problem reference that is passed into the callback. The error message you are seeing suggests that you are instead using the global problem instance, i.e., the one on which you called optimize.
The problem reference passed into a callback is a thread-local problem reference. As long as you only use that reference in the callback, your callback is thread-safe with respect to Xpress.
Your single-threaded code works because with only one thread, the problem reference passed into the callback is the global problem.
- FICOCommunity Manager
I've narrowed the bug down to a print statement. When I create my master MIP (instance of XpressProblem), I create 15 binary variables (stored in Variable[] use) and one continuous variable (stored in Variable flowCost). Inside the callback, I create an instance of LinExpression using the use variables, then add a cut based on that expression and the flowCost. That seems to be fine, even with multiple threads. The exception occurs (sometimes, not always) when I try to print the cut and/or the value of flowCost.
Just now I tried to replace the original variables with those associated with the prob argument. Since I could not find a direct way to reference them, I tried prob.variableForIndex(i) as a replacement for use. That earned me a null pointer exception because "this.variableHandler" is null.
I fixed the problem by adapting your code (in your answer to another of my questions) for accessing the original names of the cut variables. This seems to work with multiple threads. Thanks for that code! It does seem to me to be unnecessarily clunky in this context. If a LinExpression instance inside a callback can use the original variables and produce correct cuts (throwing no exceptions), it seems that the toString method of that LinExpression should also work.
- FICOCommunity Manager
I agree that the toString() function should work. Unfortunately, at the moment it does not and at the moment this is the expected behavior (for the technical reasons described above). I have filed an internal request for improvement. Obviously, printing out a cut for debugging reasons is a very valid use case that should work out of the box.
You get this NullPointerException from XpressProblem.getVariables() because the problem passed into the callback is in presolved state and thus has no Variable instances: interaction with a model in presolved state requires indices rather than Variable instances to reference columns.
So everything boils down to the known limitation that LinExpression.toString() does not work from inside a callback.
Related Content
Related Content
How to make cuts added in a preIntsol callback globally valid (root node) instead of local to the current subtree?
I'm using the Xpress Optimizer Java API (com.dashoptimization, Xpress 9.4) to solve a MIP with lazy constraints that are generated dynamically. My constraints are all globally valid — they are not lo...2 months agoPlace FICO® Xpress Optimization ForumFICO® Xpress Optimization Forum2 unread comments2 unread3Views0likes2CommentsVariable names in callback (Java API)
I construct a cut in a preintsol callback using variables from the model containing the callback. When constructing the model, I give the variables names (using withName(...)) and store them in a vec...9 months agoPlace FICO® Xpress Optimization ForumFICO® Xpress Optimization Forum4 unread comments4 unread1View0likes4CommentsVariable object mapping issue in Python Callbacks with Presolve enabled
Hi, I am implementing a Branch-and-Cut algorithm using the Xpress Python interface. I have structured my code as a class where I create variables (using xp.var) and store them in a dictionary attrib...8 months agoPlace FICO® Xpress Optimization ForumFICO® Xpress Optimization Forum6 unread comments6 unread0Views0likes6Comments