Skip to content
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

Providing callback functions rather than fixed matrices #62

Open
iedmrc opened this issue Aug 16, 2022 · 11 comments
Open

Providing callback functions rather than fixed matrices #62

iedmrc opened this issue Aug 16, 2022 · 11 comments

Comments

@iedmrc
Copy link

iedmrc commented Aug 16, 2022

Hi all,

Could we add a new future such:

Providing callback functions rather than fixed matrices. With this feature, we would be able to produce custom costs, durations etc.. on the air by looking at some parameters, for example, the onway duration may vary according to traffic at that specific time. Or we would like to punish moving forward from one specific place to another if it's coming from another, etc..

Edit: Miss-click to enter button, sorry :)

@iedmrc iedmrc changed the title Providing Callback functions rather than Providing callback functions rather than fixed matrices Aug 16, 2022
@jcoupey
Copy link
Contributor

jcoupey commented Aug 29, 2022

I guess having this matrix-adjusting logic live in the same place as the python bindings could be handy. But since you have to maintain that on top of the bindings, maybe it would be easier in the long run to have it as an isolated component?

Also another question raised here is that it would define something different from the upstream API while the primary goal for this repo was to provide python bindings that are real close to the upstream C++ API.

@jonathf since you wrote the python bindings, what's your take on this?

@jonathf
Copy link
Collaborator

jonathf commented Aug 30, 2022

Having the code on the pyvroom side of things is posible, but I feel it would be hacky, as I would need to circumvent a lot of the C++ infrastructure, and I don't see any reason why it should be a Python-only feature.

I think that the way to go here is to have the functionality on the C++ side, like you are indicating. Perhaps a new routing class that accepts a std::function<Cost(Location, Location)> as an arg to the constructor. If that existed, it would be trivial to link up such functionality in python with two-three lines of glue code in pyvroom.

@jcoupey
Copy link
Contributor

jcoupey commented Aug 30, 2022

I don't see any reason why it should be a Python-only feature.

Good point, it's probably better to keep features in line in the bindings.

On the other hand I don't think it would be a good idea to bloat the C++ API with a new (complex) way to adjust cost matrices. We already provide a low-level way to pass in custom matrices and optimize based on those. Of course it means users have to build their own cost logic outside VROOM if they want to, but this provides a good modularity.

@iedmrc
Copy link
Author

iedmrc commented Aug 30, 2022

Actually, I also don't see any reason why it should be a Python-only feature. But to have a quick solution, I say why not :)

And also at this point:

On the other hand I don't think it would be a good idea to bloat the C++ API with a new (complex) way to adjust cost matrices. We already provide a low-level way to pass in custom matrices and optimize based on those.

I think such functionality would improve VROOM much. With this functionality, it would be more extensible. At least through bindings or a library version of it. Google's OR-tools can be a good example here.

@jcoupey
Copy link
Contributor

jcoupey commented Aug 30, 2022

Using VROOM as a library is already a thing, see this example of defining a custom matrix directly from C++.

You can already add any custom cost logic to compute matrices, then call the low-level set_durations_matrix function. Having clear and separate roles for different software components is usually considered a good practice.

Baking your matrix-building logic inside VROOM ties you with this software component, whereas if you build your own logic outside you could re-use that part with other engines if need be, or easily switch to a different logic without having to touch VROOM at all.

@iedmrc
Copy link
Author

iedmrc commented Aug 31, 2022

I opened this ticket here because I agree with you @jcoupey here:

Baking your matrix-building logic inside VROOM ties you with this software component, whereas if you build your own logic outside you could re-use that part with other engines if need be, or easily switch to a different logic without having to touch VROOM at all.

And also I actually know VROOM has a library version too.
But making the development in such a project is hard because:

  • The problem in itself is hard. Having a clear understanding of such problems (VRP optimizer) is not easy.
  • C++ is a relatively low-level programming language which makes it powerful but hard to dive into it.

But to make 3rd party bindings easy to implement such "callback function rather than static matrix" feature, seems like we need a development at VROOM part. So I think we should consider it.

@jonathf
Copy link
Collaborator

jonathf commented Aug 31, 2022

The high-level approach to what you want can be done outside of VROOM I think. Like:

import numpy
import vroom

jobs = [vroom.Job(1414, location=0), vroom.Job(1515, location=1),
        vroom.Job(1616, location=2), vroom.Job(1717, location=3)]

def callback(int: loc1, int: loc2) -> int:
    # logic for callculating distance/cost between locations

# Part that you want built into pyvroom:
matrix = numpy.zeros((len(jobs), len(jobs)), dtype=int)
for i in range(len(jobs)):
    for j in range(i + 1, len(jobs)):
      matrix[i, j] = matrix[j, i] = callback(i, j)

# Define problem to be solved:
problem_instance = vroom.Input()
problem_instance.set_duration_matrix(matrix)
problem_instance.add_job(jobs)
...

In other words, you won't gain much code wise from such a logic. From a code implementation point of view, a lot of interception has to be done to do this properly on the Python end. So I think this snippet is your best bet for now.

@iedmrc
Copy link
Author

iedmrc commented Aug 31, 2022

Hey @jonathf, thank you for the offer. I think it's a good approach but doesn't work much as you mentioned because the callback function needs some parameters to be passed to it such as what is the current route, what is the current cost etc..

I understand for both pyvroom and vroom this is not a case that wanted to be placed in the roadmap. But in my opinion, it would be a powerful feature for the vroom. You can assume this as a feature request for a long-term roadmap :). Hence maybe some other parties who need such a feature can find this issue and place their thoughts.

@SkyTik
Copy link

SkyTik commented Aug 28, 2024

Hi, I came to this issue since I had the same problem as @iedmrc. Are there any updates on this issue?
My use case is that I need to define a cost matrix for different types of vehicles. I can easily achieve it with OR-Tools like this.

for i in range(len(vehicles_list)):
    cost_callback = arc_cost_callbacks[i]
    transit_callback_index = routing.RegisterTransitCallback(cost_callback)
    routing.SetArcCostEvaluatorOfVehicle(transit_callback_index, i)

@jonathf
Copy link
Collaborator

jonathf commented Aug 29, 2024

No, sorry. Not on the horizon for planned features.

As for different cost matrixes for different types of vehicles, that is already supported. Just make multiple profiles. See the example in the root README.rst

@jonathf
Copy link
Collaborator

jonathf commented Aug 29, 2024

When you have multiple profiles, you will need to explicitly define the profile for each Vehicle with the profile arg:

car  = vroom.Vehicle(..., profile="car")
truck = vroom.Vehicle(..., profile="truck")
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants