2

I am setting up a branch-and-cut algorithm using the generic callback framework through the C API of CPLEX 12.10.

At each node, the separation problem is based on the current node LP and detects locally valid cuts, that if violated are added for every child node of the current node.

To my understanding, the information of a current node LP is not readily available in the generic callbacks. However, I would like to use cuts generated for a parent node, to generate better cuts in the child nodes.

Is it necessary to do book-keeping about which cuts are generated at all the nodes or can this information somehow be passed on using CPLEX functionality? If the only possibility is to keep track of all generated cuts, how can this book-keeping be made thread-safe, if CPLEX calls the callback from different threads and in different nodes?

F. Plein
  • 25
  • 2

1 Answers1

0

There is no way to make CPLEX keep track of this information for you. You have to roll your own.

One way to do this is to implement a dictionary that maps a node's unique id (see CPXCALLBACKINFO_NODEUID) to the information you want to store along with that node. With respect to thread-safety you only have to protect the accesses to that dictionary. To do that, use a lock (pthread_mutex on non-Windows, CRITICAL_SECTION on Windows, for example) and lock and lookup or update operation on that dictionary.

Daniel Junglas
  • 5,830
  • 1
  • 5
  • 22
  • But in this case, is there a way to find out wether a certain node id belongs to a parent node? A local cut (in CPLEX terms) belonging to a non-parent node would not be valid in the separation problem, either. – F. Plein Feb 17 '20 at 16:45
  • No, sorry, there is currently no way to do that. The only way to track parent/child relationships is by creating custom branches and tracking the information there. CPLEX does not expose parent/child relationships on purpose: the design of the generic callback is so that only node-local information is used at a node and users should not make any assumptions about the shape of the tree (unless they explicitly create it using custom branches). – Daniel Junglas Feb 18 '20 at 12:24
  • 1
    I have added a user wish to get this implemented in one of the future versions of CPLEX. Querying a node's parent *after* the node was created seems a reasonable and useful thing that CPLEX should thus support. – Daniel Junglas Feb 19 '20 at 09:54
  • I agree that this could be useful, especially since there is no way to pass data from parent to child except through the global userhandle struct. In the meantime, I have indeed rolled my own. I keep a dictionary mapping nodeid to a node struct (in particular it points to the parent where it was created by CPXXmakebranch), however CPLEX performs a restart at some point. However, now the last node creating branches had id N (creating nodes N+1 and N+2) and the node after restart suddenly has id N+3, which is non-existent in my map. Is there another workaround? – F. Plein Feb 19 '20 at 15:09
  • 1
    When a restart happens you should clear your map. Any node-related information becomes invalid at this point. There are two ways to detect a restart: 1. query the `CPXCALLBACKINFO_RESTARTS` information from the callback and check whether it increased since the last call. 2. Check the depth of the current node. A depth of 0 means either the root node or the root of a restart. – Daniel Junglas Feb 19 '20 at 15:53
  • Is there no parameter to turn off restarts, in general? Given that my model is only a MIP so that I can use the callbacks, but does not really contain any real MIP information, I am not sure if I can benefit from them. – F. Plein Feb 19 '20 at 16:12