-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We��ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Routing: Exception in transit callback is silently ignored and gives cost 0 (Python) #3224
Labels
Milestone
Comments
dev note:
SWIGINTERN PyObject *_wrap_RoutingModel_RegisterPositiveTransitCallback(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
operations_research::RoutingModel *arg1 = (operations_research::RoutingModel *) 0 ;
operations_research::RoutingModel::TransitCallback2 arg2 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
int result;
if (!PyArg_UnpackTuple(args, "RoutingModel_RegisterPositiveTransitCallback", 2, 2, &obj0, &obj1)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_operations_research__RoutingModel, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RoutingModel_RegisterPositiveTransitCallback" "', argument " "1"" of type '" "operations_research::RoutingModel *""'");
}
arg1 = reinterpret_cast< operations_research::RoutingModel * >(argp1);
{
SharedPyPtr input(obj1);
arg2 = [input](int64_t i, int64_t j) {
return InvokePythonCallableReturning<int64_t>(input.get(), "LL", i, j);
};
}
{
try {
result = (int)(arg1)->RegisterPositiveTransitCallback(arg2);
}
catch (Swig::DirectorException &e) {
SWIG_fail;
}
}
resultobj = SWIG_From_int(static_cast< int >(result));
return resultobj;
fail:
return NULL;
}
ref |
As a workaround, I created a decorator that can be used to ensure expected behavior: import os
import functools
import traceback
def ortools_callback(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception:
traceback.print_exc()
os._exit(1)
return wrapper @ortools_callback
def distance_callback(from_index, to_index):
"""Returns the distance between the two nodes."""
from_node = manager.IndexToNode(from_index)
to_node = manager.IndexToNode(to_index)
raise RuntimeError()
return dist_matrix[from_node][to_node] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What version of OR-Tools and what language are you using?
Version: 9.1.9490
Language: Python
Which solver are you using (e.g. CP-SAT, Routing Solver, GLOP, BOP, Gurobi)
Routing Solver
What operating system (Linux, Windows, ...) and version?
Linux
What did you do?
Steps to reproduce the behavior:
raise RuntimeError()
somewhere indistance_callback
. Example:routing.GetArcCostForVehicle
will return 0.What did you expect to see
Early termination of the program with a Python stacktrace. Alternatively a C++ crash or even a segmentation fault. Or simply a warning printed from C++.
What did you see instead?
Solution is found and objective value is 0. Similarly, evaluations to
routing.GetArcCostForVehicle
returns 0.Note
This potential bug was discovered in a much more subtle setting:
A dummy node had been added and instead of updating the distance matrix with values, the transit cost was simply handled in the callback as follows:
It worked fine when
from_node
was the dummy node, but whento_node
was the dummy node, it would yield anIndexError
ondist_matrix
that would be silently ignored.My solution was of course to do something like
But I believe there is still some unintended behavior here.
The text was updated successfully, but these errors were encountered: