Forum Discussion

FICO's avatar
FICO
Community Manager
1 year ago

how to use getcpcuts() and delcpcuts() method in python library?

Hello,

I’m currently implementing a Benders decomposition algorithm using the Xpress Python library. I'm working on a model that exhibits basic characteristics of the Traveling Salesman Problem (TSP) and trying to solve it accordingly.

I am using two callback functions: addcbpreintsol and addcboptnode. In these callbacks, when a subtour is detected, I use the DFJ constraints and eliminate the subtour by adding cuts via the addcuts() method. When the addcbpreintsol callback is triggered and no subtours are found, I solve the Benders Subproblem (BSP), and based on its result, I generate Benders cuts, which are then added using addcuts() as well.

Now, what I would like to do is, inside the addcbpreintsol callback, I want to access the cuts previously added using addcuts() , check them with getcpcuts(), and if any of the cuts are found to be invalid or incorrect, delete them using delcpcuts() .According to the documentation from

https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/python/HTML/chReference.html

and the “Working with the Cut Manager” section, it seems that cuts added with addcuts() should automatically be stored in the cut pool. However, in my code, when I try to access those cuts using getcpcuts() within the addcbpreintsol callback, I don’t get any information or output about the previously added cuts. Do you happen to have any example code that shows how to use getcpcuts() or delcpcuts() properly? Or could you point me to any useful papers or references that provide more insight into this issue?

Thanks so much for taking the time to read this rather long question!

1 Reply

  • FICO's avatar
    FICO
    Community Manager

    Hi,

    There is a TSP example in the online documentation that uses .addcuts() to provide sub-tour elimination constraints within the preintsol callback:

    https://www.fico.com/fico-xpress-optimization/docs/latest/examples/python/GUID-EDE11C09-F189-30C8-8811-763F7F772943.html

    Unfortunately, it doesn't show you how to delete cuts since this example assumes it is unnecessary to remove constraints once they have been added. When cuts are added to a node problem by .addcuts(), they are only applied to the current node and its descendants.

    Could you provide a snippet of code that you use within your preintsol callback? This would help us understand how you are calling these cut management functions.

    You are correct that any cuts added by .addcuts() are automatically and immediately stored within the user cut pool. To retrieve these cuts from the cut pool, you should first call .getcpcutlist()

    https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/python/HTML/problem.getcpcutlist.html

    to retrieve the references to the cuts in the pool. Note that this function will retrieve a subset of your cuts, depending on the 'cuttype', 'interp' and 'delta' arguments. To retrieve all cuts, you would set 'interp = -1' and 'delta = -xpress.infinity`. The function will return a list of cut references, which you can then pass to .getcpcuts() to retrieve the actual cut coefficients.

    You should be aware that adding or deleting cuts from the user cut pool does not have any impact on the active cuts currently loaded into node problems of the branch-and-bound search tree. The pool is only provided as a convenience for accessing user cuts that have been stored previously. Deleting a cut from the pool only means that it is no longer available through .getcpcuts().

    To remove cuts from a node problem and its descendants, you have to call .delcuts().

    https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/python/HTML/problem.delcuts.html

    You can call this function without a list of cut references if you want to e.g. remove all inactive cuts from the current node.

    Best Regards,

    Michael