Limit the number of orders per address per day

Hi,
I am looking to use Graphhopper Route Optimization to solve a VRP in a healthcare context. We have a multidisciplinary team of therapists that visits patients in their home. Eventually I want to schedule visits weekly such that all patients are visited according to their therapy plans’ while minimizing the time spent driving by the therapists.

What I am currently struggling with are the following constrains:

  • No patient should be visited more than once a day
  • No patient should be visited less than twice a week
  • No patient should be visited more than three times a week

Do you have an idea how to add these constraints? Thank you for your help!

PS: My sample problem is defined as:

{
“vehicle_types”:[
{
“type_id”: “car_type”,
“profile”: “car”
}
],
“vehicles”: [
{
“vehicle_id”: “therapist-1”,
“type_id”: “car_type”,
“shifts”: [
{
“shift_id”: “monday”,
“start_address”: {
“location_id”: “home_therapist_1”,
“lon”: 11.994504729425763,
“lat”: 50.32102865914283
},
“earliest_start”: 28800,
“latest_end”: 61200
},
{
“shift_id”: “tuesday”,
“start_address”: {
“location_id”: “home_therapist_1”,
“lon”: 11.994504729425763,
“lat”: 50.32102865914283
},
“earliest_start”: 115200,
“latest_end”: 147600
},
{
“shift_id”: “wednesday”,
“start_address”: {
“location_id”: “home_therapist_1”,
“lon”: 11.994504729425763,
“lat”: 50.32102865914283
},
“earliest_start”: 201600,
“latest_end”: 234000
},
{
“shift_id”: “thursday”,
“start_address”: {
“location_id”: “home_therapist_1”,
“lon”: 11.994504729425763,
“lat”: 50.32102865914283
},
“earliest_start”: 288000,
“latest_end”: 320400
},
{
“shift_id”: “friday”,
“start_address”: {
“location_id”: “home_therapist_1”,
“lon”: 11.994504729425763,
“lat”: 50.32102865914283
},
“earliest_start”: 374400,
“latest_end”: 406800
}
],
“skills”: [“physiotherapy”]
},
{
“vehicle_id”: “therapist-2”,
“type_id”: “car_type”,
“shifts”: [
{
“shift_id”: “monday”,
“start_address”: {
“location_id”: “home_therapist_2”,
“lon”: 12.031127130967292,
“lat”: 50.25143411526754
},
“earliest_start”: 28800,
“latest_end”: 61200
},
{
“shift_id”: “tuesday”,
“start_address”: {
“location_id”: “home_therapist_2”,
“lon”: 12.031127130967292,
“lat”: 50.25143411526754
},
“earliest_start”: 115200,
“latest_end”: 147600
},
{
“shift_id”: “wednesday”,
“start_address”: {
“location_id”: “home_therapist_2”,
“lon”: 12.031127130967292,
“lat”: 50.25143411526754
},
“earliest_start”: 201600,
“latest_end”: 234000
},
{
“shift_id”: “thursday”,
“start_address”: {
“location_id”: “home_therapist_2”,
“lon”: 12.031127130967292,
“lat”: 50.25143411526754
},
“earliest_start”: 288000,
“latest_end”: 320400
},
{
“shift_id”: “friday”,
“start_address”: {
“location_id”: “home_therapist_2”,
“lon”: 12.031127130967292,
“lat”: 50.25143411526754
},
“earliest_start”: 374400,
“latest_end”: 406800
}
],
“skills”: [“ergotherapy”]
},
{
“vehicle_id”: “therapist-3”,
“type_id”: “car_type”,
“shifts”: [
{
“shift_id”: “monday”,
“start_address”: {
“location_id”: “home_therapist_3”,
“lon”: 11.849268889689748,
“lat”: 50.270939503033574
},
“earliest_start”: 28800,
“latest_end”: 61200
},
{
“shift_id”: “tuesday”,
“start_address”: {
“location_id”: “home_therapist_3”,
“lon”: 11.849268889689748,
“lat”: 50.270939503033574
},
“earliest_start”: 115200,
“latest_end”: 147600
},
{
“shift_id”: “wednesday”,
“start_address”: {
“location_id”: “home_therapist_3”,
“lon”: 11.849268889689748,
“lat”: 50.270939503033574
},
“earliest_start”: 201600,
“latest_end”: 234000
},
{
“shift_id”: “thursday”,
“start_address”: {
“location_id”: “home_therapist_3”,
“lon”: 11.849268889689748,
“lat”: 50.270939503033574
},
“earliest_start”: 288000,
“latest_end”: 320400
},
{
“shift_id”: “friday”,
“start_address”: {
“location_id”: “home_therapist_3”,
“lon”: 11.849268889689748,
“lat”: 50.270939503033574
},
“earliest_start”: 374400,
“latest_end”: 406800
}
],
“skills”: [“logopedics”]
}
],
“services”: [
{
“id”: “patient_1_visit_1”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_1”,
“lon”: 11.89422123955258,
“lat”: 50.302331865365346
},
“duration”: 4050,
“required_skills”: [“physiotherapy”]
},
{
“id”: “patient_1_visit_2”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_1”,
“lon”: 11.89422123955258,
“lat”: 50.302331865365346
},
“duration”: 4050,
“required_skills”: [“ergotherapy”]
},
{
“id”: “patient_1_visit_3”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_1”,
“lon”: 11.89422123955258,
“lat”: 50.302331865365346
},
“duration”: 4050,
“required_skills”: [“logopedics”]
},
{
“id”: “patient_2_visit_1”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_2”,
“lon”: 11.906218559363055,
“lat”: 50.30121414816818
},
“duration”: 4050,
“required_skills”: [“physiotherapy”]
},
{
“id”: “patient_2_visit_2”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_2”,
“lon”: 11.906218559363055,
“lat”: 50.30121414816818
},
“duration”: 4050,
“required_skills”: [“ergotherapy”]
},
{
“id”: “patient_2_visit_3”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_2”,
“lon”: 11.906218559363055,
“lat”: 50.30121414816818
},
“duration”: 4050,
“required_skills”: [“logopedics”]
},
{
“id”: “patient_3_visit_1”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_3”,
“lon”: 11.905982140027389,
“lat”: 50.30348786244936
},
“duration”: 4050,
“required_skills”: [“physiotherapy”]
},
{
“id”: “patient_3_visit_2”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_3”,
“lon”: 11.905982140027389,
“lat”: 50.30348786244936
},
“duration”: 4050,
“required_skills”: [“ergotherapy”]
},
{
“id”: “patient_3_visit_3”,
“name”: “visit pharmacy”,
“address”: {
“location_id”: “patient_3”,
“lon”: 11.905982140027389,
“lat”: 50.30348786244936
},
“duration”: 4050,
“required_skills”: [“logopedics”]
}
],
“objectives” : [
{
“type”: “min”,
“value”: “completion_time”
}
]
}

Unfortunately I couldn’t find an edit-button.

I realized that the only constraint I can’t solve myself is:

  • No patient is visited more than once a day

Hope this makes answering my question easier. Any pointers?

Thanks for this question. And unfortunately this is not possible, I think.

You could use vehicles instead of shifts and then use “relations” to control how the services behave to each other. But I fear you would need a special relation like “not_in_same_route” to achieve what you want and this is not available at the moment but an interesting feature and use case.

Near the reply button there are three dots where there should be an edit button.