AddDisjunction function

1,074 views
Skip to first unread message

Teemu Niemelä

unread,
Jun 3, 2019, 1:58:42 AM6/3/19
to or-tools-discuss
I am wondering how AddDisjunction should work? Just for example I made case:

public long[,] DistanceMatrix = {
            {0, 3, 3, 3, 3, 3},
            {3, 0, 1, 1, 1, 1},
            {3, 1, 0, 1, 1, 1},
            {3, 1, 1, 0, 1, 1},
            {3, 1, 1, 1, 0, 1},
            {3, 1, 1, 1, 1, 0}
        };

Debot is node 0. Every node has demand 1 and we have two vehicles which both have capacity 1. We don't have any other effecting constraints. Now if I set penalty like this:

        for (int i = 1; i < data.DistanceMatrix.GetLength(0); i++)
        {
            long penalty = 8;
            routing.AddDisjunction(
               new long[] { manager.NodeToIndex(i) }, penalty, 4);
        }

From the documentation "If penalty is given, at most max cardinality of the indices can be active, and if less are active, penalty is payed per inactive incidence. If there is less than 4 nodes active we get penalty per node. Currently if all nodes are dropped there is penalty 8 * dropped nodes 5 = total cost 40. If we calculate with two vehicles the cost is: 2 active nodes with distance cost of 6 per node. 12 + (3 * inactive nodes penalty 8) = 36. Still I get all nodes dropped. When I use it with Maxcardinality value 1 it functions like it is described in documentation. Every other value higher than 1 gives all nodes dropped no matter which is the penalty.

Is there some kind of bug with maxcardinality or am I doing something wrong? I am using version 7.1.6720 for C#.
  

blind.line

unread,
Jun 3, 2019, 11:17:46 AM6/3/19
to or-tools...@googlegroups.com
To quote again the docs: “'max_cardinality' of the indices are active”, the key phrase being “of the indices”. 

I’m not a C++ guy, but isn’t the statement 

new long[] { manager.NodeToIndex(i) },

Creating a single element array?  You can’t turn on 4 of one thing

Actually, I think the API should throw when cardinality is more than the size of the input array


James
--
You received this message because you are subscribed to the Google Groups "or-tools-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/or-tools-discuss/05679a63-269a-4ce6-8850-88e51deaaaec%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Teemu Niemelä

unread,
Jun 4, 2019, 1:38:50 AM6/4/19
to or-tools-discuss
Hi,

Thank you again for the fast answer. Yes you are right, I think it should be called only once. But when I change the code to:

long[] p = new long[data.DistanceMatrix.GetLength(0)-1];
        for (int i = 1; i < data.DistanceMatrix.GetLength(0); i++)
        {
            p[i - 1] = manager.NodeToIndex(i);
        }
        long penalty = 9999999;
        routing.AddDisjunction(
           p, penalty, 4);

I still get all the nodes dropped. So it seems like the max cardinality > 1 does not work. Also if I can call AddDisjunction only once, I can't set different penalties per node. It would be more convenient if the penalty was array of long where you could set penalty per nodeindex. 

There is something marked as a bug related to milestone 7.2, but I can't figure it out is the same problem or something else:



maanantai 3. kesäkuuta 2019 18.17.46 UTC+3 blind.line kirjoitti:
To quote again the docs: “'max_cardinality' of the indices are active”, the key phrase being “of the indices”. 

I’m not a C++ guy, but isn’t the statement 

new long[] { manager.NodeToIndex(i) },

Creating a single element array?  You can’t turn on 4 of one thing

Actually, I think the API should throw when cardinality is more than the size of the input array


James

On Jun 2, 2019, at 22:58, Teemu Niemelä <teemu....@gmail.com> wrote:

I am wondering how AddDisjunction should work? Just for example I made case:

public long[,] DistanceMatrix = {
            {0, 3, 3, 3, 3, 3},
            {3, 0, 1, 1, 1, 1},
            {3, 1, 0, 1, 1, 1},
            {3, 1, 1, 0, 1, 1},
            {3, 1, 1, 1, 0, 1},
            {3, 1, 1, 1, 1, 0}
        };

Debot is node 0. Every node has demand 1 and we have two vehicles which both have capacity 1. We don't have any other effecting constraints. Now if I set penalty like this:

        for (int i = 1; i < data.DistanceMatrix.GetLength(0); i++)
        {
            long penalty = 8;
            routing.AddDisjunction(
               new long[] { manager.NodeToIndex(i) }, penalty, 4);
        }

From the documentation "If penalty is given, at most max cardinality of the indices can be active, and if less are active, penalty is payed per inactive incidence. If there is less than 4 nodes active we get penalty per node. Currently if all nodes are dropped there is penalty 8 * dropped nodes 5 = total cost 40. If we calculate with two vehicles the cost is: 2 active nodes with distance cost of 6 per node. 12 + (3 * inactive nodes penalty 8) = 36. Still I get all nodes dropped. When I use it with Maxcardinality value 1 it functions like it is described in documentation. Every other value higher than 1 gives all nodes dropped no matter which is the penalty.

Is there some kind of bug with maxcardinality or am I doing something wrong? I am using version 7.1.6720 for C#.
  

--
You received this message because you are subscribed to the Google Groups "or-tools-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools...@googlegroups.com.

Abed

unread,
Jun 4, 2019, 8:32:25 AM6/4/19
to or-tools-discuss
Hi Teema,

I am using this piece of code in C# and it works as it is supposed to considering vehicle capacity:

long penalty = 1000;
        for (int i = 1; i < data.DistanceMatrix.GetLength(0); ++i)
        {
            routing.AddDisjunction(
                new long[] { manager.NodeToIndex(i) }, penalty);
        }

You can also define the penalty as an array for each node and in the AddDisjunction call it as penalty[i]:

long penalty []={penalty values go here per node};
        for (int i = 1; i < data.DistanceMatrix.GetLength(0); ++i)
        {
            routing.AddDisjunction(
                new long[] { manager.NodeToIndex(i) }, penalty[i]);
        }

Teemu Niemelä

unread,
Jun 4, 2019, 8:49:28 AM6/4/19
to or-tools-discuss
Hi,

You are using adddisjunction without max cardinality parameter. So it uses default value 1. If you use it with value > 1, it is not working as expected. I think your last example just sets last penalty to last node? So every call resets the disjunction parameters.

blind.lin...@gmail.com

unread,
Jun 4, 2019, 11:36:24 AM6/4/19
to or-tools...@googlegroups.com
On Mon, Jun 03, 2019 at 10:38:50PM -0700, Teemu Niemelä wrote:
> Hi,
>
> Thank you again for the fast answer. Yes you are right, I think it should
> be called only once. But when I change the code to:

I think that's just a time-zone thing.

>
> long[] p = new long[data.DistanceMatrix.GetLength(0)-1];
> for (int i = 1; i < data.DistanceMatrix.GetLength(0); i++)
> {
> p[i - 1] = manager.NodeToIndex(i);
> }
> long penalty = 9999999;
> routing.AddDisjunction(
> p, penalty, 4);
>
> I still get all the nodes dropped. So it seems like the max cardinality > 1
> does not work. Also if I can call AddDisjunction only once, I can't set
> different penalties per node. It would be more convenient if the penalty
> was array of long where you could set penalty per nodeindex.
>
> There is something marked as a bug related to milestone 7.2, but I can't
> figure it out is the same problem or something else:
>
> https://github.com/google/or-tools/issues/1110
>

My guess/intuition is that the problem is not with the disjunctions
but with something else. The disjunction constraint doesn't force 4
nodes to be active. Rather it requires that exactly 4 are active, or
exactly zero plus penalty. So if all nodes are dropped and you pay
the penalty, then it *is* working correctly.

I've used disjunctions quite successfully all the time. Invariably
when I have a mysterious fail, it is due to the fact that a time
window or some other constraint *cannot* be met. So in those cases,
the solver can't find "max_cardinality" valid node visits, because,
say, only N-1 are possible given the other constraints, so it must
drop all of them.

Re-reading your older post, you posted a simple distance matrix, and said:

> > Depot is node 0. Every node has demand 1 and we have two vehicles which
> > both have capacity 1. We don't have any other effecting constraints.

So, if every node has a demand of 1, then when a vehicle visits a
node, it is full. If no nodes have negative demand (simulating a drop
off), then each vehicle can visit *at most* one node. The solver is
doing exactly what it should---each vehicle can only visit one node
due to capacity constraints, but you are asking it to visit exactly 4
or 0 with the disjunction constraint.

If I'm missing something, post your full program for the simple
failing case.

James

>
> maanantai 3. kesäkuuta 2019 18.17.46 UTC+3 blind.line kirjoitti:
> >
> > To quote again the docs: “'max_cardinality' of the indices are active”,
> > the key phrase being “of the indices”.
> >
> > I’m not a C++ guy, but isn’t the statement
> >
> > new long[] { manager.NodeToIndex(i) },
> >
> > Creating a single element array? You can’t turn on 4 of one thing
> >
> > Actually, I think the API should throw when cardinality is more than the
> > size of the input array
> >
> >
> > James
> >
> > On Jun 2, 2019, at 22:58, Teemu Niemelä <teemu....@gmail.com <javascript:>>
> > email to or-tools...@googlegroups.com <javascript:>.
> > <https://groups.google.com/d/msgid/or-tools-discuss/05679a63-269a-4ce6-8850-88e51deaaaec%40googlegroups.com?utm_medium=email&utm_source=footer>
> > .
> > For more options, visit https://groups.google.com/d/optout.
> >
> >
>
> --
> You received this message because you are subscribed to the Google Groups "or-tools-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discu...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/or-tools-discuss/76e94e37-b5f3-49a8-a565-f86b360d7bdb%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.


--

James E. Marca
signature.asc

Teemu Niemelä

unread,
Jun 5, 2019, 9:10:18 AM6/5/19
to or-tools-discuss
Hi James,

See my attached code. There is case when I am trying to create case where I would select cheapest option for two different trucks with options truck/truck with trailer. I have cost for truck 1 and truck with trailer 5. Capacity to truck 1 and truck with trailer 3. Then I set penalty so that it is bigger than driving the order with just a truck. (debot->any order->debot , 3 + 3) Penalty is 7 so in example it should select the vehicles without the trailer. But I get all nodes dropped. Maxcardinality in this example is 4/2 = 2. Like mentioned earlier, documentation says:

"If a penalty is given, at most 'max_cardinality' of the indices can be active, and if less are active, 'penalty' is payed per inactive index"

If all nodes are dropped then there is 0 indices active, so there should penalty for 5 nodes? So why all nodes are dropped?

for (int i = 1; i < data.DistanceMatrix.GetLength(0); i++)
        {
            long penalty = 6+data.VehicleCosts[1]+1;
            routing.AddDisjunction(
               new long[] { manager.NodeToIndex(i) }, penalty, data.VehicleNumber/2);
        }

I also tried to setting AddDisjunction calling one with one array:

        long[] p = new long[data.DistanceMatrix.GetLength(0)-1];
        for (int i = 1; i < data.DistanceMatrix.GetLength(0); i++)
        {
            p[i - 1] = manager.NodeToIndex(i);
        }
        long penalty = 6 + data.VehicleCosts[1] + 1;
        routing.AddDisjunction(p, penalty, data.VehicleNumber / 2);

but still getting the same result.

So probably I am not understanding the penalty concept how it should work and how to calculate suitable value for it for my case. In all the examples it is always set to very high value so I cannot compare them to my problem. If I set it to high value, I will get always truck with trailer selected because it has higher capacity.

Thank you before hand for investigating this.

Best regards, Teemu
> To unsubscribe from this group and stop receiving emails from it, send an email to or-tools...@googlegroups.com.
TspDistanceMatrix.zip

J. E. Marca

unread,
Jun 7, 2019, 1:20:03 PM6/7/19
to or-tools-discuss
I've not made much progress with this, but have only uncovered more mysteries.

Trying to reduce to a minimal program that reproduces the issue.  First up, disjunction_okay.py, which *does not* solve your initial problem, but which works.

If you run this program with no command line arguments, it solves the 5 demand node case with two vehicles, both with capacity of 3:

python disjunction_okay.py  
The Objective Value is 75
...
Total distance of all routes: 75m
Total load of all routes: 5

I set up command line parameters to increase and decrease the size of the problem, and to set up disjunctions.  If you turn on disjuctions with a minimal penalty, no nodes are served:

 python disjunction_okay.py  -d True --singlepenalty 10
single node disjunction penalty is 10
added 5 disjunctions, one per node
The Objective Value is 50
...
Total distance of all routes: 0m
Total load of all routes: 0

So that is good.  If you bump up the penalty to 18, the nodes are no longer dropped, and the solution returns to the original solution.

python disjunction_okay.py  -d True --singlepenalty 18
single node disjunction penalty is 18
added 5 disjunctions, one per node
The Objective Value is 75
...
Total distance of all routes: 75m
Total load of all routes: 5

Disjunctions are important when you bump the problem up to seven nodes (command line --seven True) because then of course the solver *must* drop one node or there is no solution.

In any event, all works as expected with the program disjunction_okay.py

The problem comes when I return to the original problem.  Consider disjunction_fail.py.  The only real difference is that now there are 4 vehicles instead of two, AND there is that constraint in there requiring that only one of a pair of vehicles is used.  Code:

```
    data['vehicle_capacities'] = [3, 1, 3, 1]
    data['vehicle_costs'] = [5, 1, 5, 1]
...
    for veh_pair in range(0, num_veh//2):
        # buggy dead reckoning, but truck-trailer is first, truck single unit second
        combo = veh_pair*2
        single = veh_pair*2 + 1
        index_combo = routing.End(combo)
        index_single = routing.End(single)

        end_time_combo = time_dimension.CumulVar(index_combo)
        end_time_single = time_dimension.CumulVar(index_single)

        combo_on = end_time_combo > 0
        single_on = end_time_single > 0

        # constrain solver to preven both being on
        # truth table
        #
        # combo_on     single_on   multiply  descr
        #   0             0           0      both unused; okay
        #   1             0           0      combo on only; okay
        #   0             1           0      single on only; okay
        #   1             1           1      both on; prevent
        #
        solver.Add(combo_on * single_on == 0)
```

Running the program with no command line arguments uses a demand matrix with 5 pickup nodes, and the solution is to use two combo trucks, one with 3 loads, one with 2:

 python disjunction_fail.py
The Objective Value is 75
Truck 0 travel time
     combo: 40
     single: 0
Truck 1 travel time
     combo: 35
     single: 0
Route for vehicle 0:

If you set the --four True command line parameter, it uses a four node problem, in which the ideal solution is to choose one combo, one single unit:

python disjunction_fail.py --four True
The Objective Value is 46
Truck 0 travel time
     combo: 0
     single: 6
Truck 1 travel time
     combo: 40
     single: 0
Route for vehicle 0:

So that's great, the constraint is doing its job and the solver is picking the best vehicle.  But turning on the disjuctions (for example to solve the --seven True case), the solver acts very strangely

With disjunctions low (5), all nodes are dropped:

python disjunction_fail.py  -d True --singlepenalty 5
single node disjunction penalty is 5
added 5 disjunctions, one per node
The Objective Value is 25
Truck 0 travel time
     combo: 0
     single: 0
Truck 1 travel time
     combo: 0
     single: 0

With disjuction at 6, you get a weird case where one vehicle is used, so ignore that and bump to penalty of 7

python disjunction_fail.py  -d True --singlepenalty 7
single node disjunction penalty is 7
added 5 disjunctions, one per node
The Objective Value is 33
Truck 0 travel time
     combo: 0
     single: 6
Truck 1 travel time
     combo: 0
     single: 6
Route for vehicle 0:
   ...

So that's correct.  Using both single unit trucks for a cost of 6 each is cheaper than dropping those two nodes.

But when the disjunction penalty is bumped up so as to force the use of the combo trucks, things get weird.

python disjunction_fail.py  -l True -d True --singlepenalty 22
single node disjunction penalty is 22
added 5 disjunctions, one per node
The Objective Value is 78
Truck 0 travel time
     combo: 0
     single: 6
Truck 1 travel time
     combo: 0
     single: 6
Route for vehicle 0:

So notice.  Without per-node disjunctions on, the solver computes a solution using two combo trucks, for a total cost of 75.  Now with disjunctions on, and with a penalty of 22, the solver chooses to drop 3 nodes and use just the two single-unit trucks for a total cost of 78---higher than 75.

Turning on logging, I see:

**With disjunctions**
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0607 17:10:29.849189   340 routing.cc:2833] All Unperformed Solution (110, time = 1 ms, memory used = 42.73 MB)
I0607 17:10:29.849252   340 search.cc:252] Start search (memory used = 42.73 MB)
I0607 17:10:29.849391   340 search.cc:252] Root node processed (time = 0 ms, constraints = 125, memory used = 42.73 MB)
I0607 17:10:29.849684   340 search.cc:252] Solution #0 (118, time = 0 ms, branches = 38, failures = 0, depth = 33, memory used = 42.77 MB)
I0607 17:10:29.849941   340 search.cc:252] Solution #1 (94, objective maximum = 118, time = 0 ms, branches = 41, failures = 2, depth = 33, Relocate<1>, neighbors = 1, filtered neighbors = 1, accepted neighbors = 1, memory used = 42.77 MB)
I0607 17:10:29.850567   340 search.cc:252] Solution #2 (78, objective maximum = 118, time = 1 ms, branches = 45, failures = 4, depth = 33, MakeActiveOperator, neighbors = 19, filtered neighbors = 2, accepted neighbors = 2, memory used = 42.77 MB)
I0607 17:10:29.857329   340 search.cc:252] Finished search tree (time = 8 ms, branches = 423, failures = 327, neighbors = 180, filtered neighbors = 96, accepted neigbors = 2, memory used = 42.77 MB)
I0607 17:10:29.857430   340 search.cc:252] End search (time = 8 ms, branches = 423, failures = 327, memory used = 42.77 MB, speed = 52875 branches/s)
The Objective Value is 78


**Without disjunctions**
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0607 17:13:08.286882   341 search.cc:252] Start search (memory used = 42.73 MB)
I0607 17:13:08.287050   341 search.cc:252] Root node processed (time = 0 ms, constraints = 110, memory used = 42.73 MB)
I0607 17:13:08.287578   341 search.cc:252] Solution #0 (75, time = 0 ms, branches = 52, failures = 8, depth = 33, memory used = 42.73 MB)
I0607 17:13:08.317746   341 search.cc:252] Finished search tree (time = 30 ms, branches = 2599, failures = 1518, neighbors = 338, filtered neighbors = 133, accepted neigbors = 0, memory used = 42.73 MB)
I0607 17:13:08.317854   341 search.cc:252] End search (time = 30 ms, branches = 2599, failures = 1518, memory used = 42.73 MB, speed = 86633 branches/s)
The Objective Value is 75

Even stranger, if you bump the penalty a lot higher, the solver will eventually pick one combo unit, but never both:

python disjunction_fail.py  -l True -d True --singlepenalty 30
single node disjunction penalty is 30
added 5 disjunctions, one per node
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0607 17:15:57.426460   347 routing.cc:2833] All Unperformed Solution (150, time = 0 ms, memory used = 42.73 MB)
I0607 17:15:57.426518   347 search.cc:252] Start search (memory used = 42.73 MB)
I0607 17:15:57.426826   347 search.cc:252] Root node processed (time = 0 ms, constraints = 125, memory used = 42.73 MB)
I0607 17:15:57.427151   347 search.cc:252] Solution #0 (150, time = 0 ms, branches = 38, failures = 0, depth = 33, memory used = 42.77 MB)
I0607 17:15:57.427507   347 search.cc:252] Solution #1 (126, objective maximum = 150, time = 0 ms, branches = 41, failures = 2, depth = 33, Relocate<1>, neighbors = 1, filtered neighbors = 1, accepted neighbors = 1, memory used = 42.77 MB)
I0607 17:15:57.428037   347 search.cc:252] Solution #2 (102, objective maximum = 150, time = 1 ms, branches = 45, failures = 4, depth = 33, MakeActiveOperator, neighbors = 19, filtered neighbors = 2, accepted neighbors = 2, memory used = 42.77 MB)
I0607 17:15:57.434772   347 search.cc:252] Finished search tree (time = 8 ms, branches = 423, failures = 327, neighbors = 180, filtered neighbors = 96, accepted neigbors = 2, memory used = 42.77 MB)
I0607 17:15:57.434851   347 search.cc:252] End search (time = 8 ms, branches = 423, failures = 327, memory used = 42.77 MB, speed = 52875 branches/s)
The Objective Value is 102
Truck 0 travel time
     combo: 0
     single: 6
Truck 1 travel time
     combo: 0
     single: 6

But at a penalty of 31:

python disjunction_fail.py  -l True -d True --singlepenalty 31
single node disjunction penalty is 31
added 5 disjunctions, one per node
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0607 17:16:23.665720   348 routing.cc:2833] All Unperformed Solution (155, time = 0 ms, memory used = 42.73 MB)
I0607 17:16:23.665779   348 search.cc:252] Start search (memory used = 42.73 MB)
I0607 17:16:23.665977   348 search.cc:252] Root node processed (time = 0 ms, constraints = 125, memory used = 42.73 MB)
I0607 17:16:23.666378   348 search.cc:252] Solution #0 (154, time = 0 ms, branches = 38, failures = 0, depth = 33, memory used = 42.77 MB)
I0607 17:16:23.666610   348 search.cc:252] Solution #1 (130, objective maximum = 154, time = 0 ms, branches = 41, failures = 2, depth = 33, Relocate<1>, neighbors = 1, filtered neighbors = 1, accepted neighbors = 1, memory used = 42.77 MB)
I0607 17:16:23.667462   348 search.cc:252] Solution #2 (129, objective maximum = 154, time = 1 ms, branches = 45, failures = 5, depth = 33, MakeActiveOperator, neighbors = 18, filtered neighbors = 3, accepted neighbors = 2, memory used = 42.77 MB)
I0607 17:16:23.667804   348 search.cc:252] Solution #3 (103, objective maximum = 154, time = 1 ms, branches = 48, failures = 7, depth = 33, MakeActiveOperator, neighbors = 19, filtered neighbors = 4, accepted neighbors = 3, memory used = 42.77 MB)
I0607 17:16:23.668157   348 search.cc:252] Solution #4 (77, objective maximum = 154, time = 2 ms, branches = 53, failures = 9, depth = 33, MakeActiveOperator, neighbors = 20, filtered neighbors = 5, accepted neighbors = 4, memory used = 42.77 MB)
I0607 17:16:23.684505   348 search.cc:252] Finished search tree (time = 18 ms, branches = 871, failures = 644, neighbors = 300, filtered neighbors = 147, accepted neigbors = 4, memory used = 42.77 MB)
I0607 17:16:23.684626   348 search.cc:252] End search (time = 18 ms, branches = 871, failures = 644, memory used = 42.77 MB, speed = 48388 branches/s)
The Objective Value is 77
Truck 0 travel time
     combo: 0
     single: 6
Truck 1 travel time
     combo: 40
     single: 0

Boosting the penalty to any larger value fails to turn on the second combo truck.

python disjunction_fail.py  -l True -d True --singlepenalty 1000000000000000000
single node disjunction penalty is 1000000000000000000
added 5 disjunctions, one per node
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0607 17:17:21.113255   352 routing.cc:2833] All Unperformed Solution (5000000000000000000, time = 0 ms, memory used = 42.73 MB)
I0607 17:17:21.113317   352 search.cc:252] Start search (memory used = 42.73 MB)
I0607 17:17:21.113423   352 search.cc:252] Root node processed (time = 0 ms, constraints = 125, memory used = 42.73 MB)
I0607 17:17:21.113732   352 search.cc:252] Solution #0 (4000000000000000030, time = 0 ms, branches = 38, failures = 0, depth = 33, memory used = 42.77 MB)
I0607 17:17:21.114017   352 search.cc:252] Solution #1 (4000000000000000006, objective maximum = 4000000000000000030, time = 0 ms, branches = 41, failures = 2, depth = 33, Relocate<1>, neighbors = 1, filtered neighbors = 1, accepted neighbors = 1, memory used = 42.77 MB)
I0607 17:17:21.114799   352 search.cc:252] Solution #2 (3000000000000000036, objective maximum = 4000000000000000030, time = 1 ms, branches = 45, failures = 5, depth = 33, MakeActiveOperator, neighbors = 18, filtered neighbors = 3, accepted neighbors = 2, memory used = 42.77 MB)
I0607 17:17:21.115105   352 search.cc:252] Solution #3 (2000000000000000041, objective maximum = 4000000000000000030, time = 1 ms, branches = 48, failures = 7, depth = 33, MakeActiveOperator, neighbors = 19, filtered neighbors = 4, accepted neighbors = 3, memory used = 42.77 MB)
I0607 17:17:21.115414   352 search.cc:252] Solution #4 (1000000000000000046, objective maximum = 4000000000000000030, time = 2 ms, branches = 53, failures = 9, depth = 33, MakeActiveOperator, neighbors = 20, filtered neighbors = 5, accepted neighbors = 4, memory used = 42.77 MB)
I0607 17:17:21.131691   352 search.cc:252] Finished search tree (time = 18 ms, branches = 827, failures = 622, neighbors = 300, filtered neighbors = 147, accepted neigbors = 4, memory used = 42.77 MB)
I0607 17:17:21.131822   352 search.cc:252] End search (time = 18 ms, branches = 827, failures = 622, memory used = 42.77 MB, speed = 45944 branches/s)
The Objective Value is 1000000000000000046
Truck 0 travel time
     combo: 0
     single: 6
Truck 1 travel time
     combo: 40
     single: 0
Route for vehicle 0:
 0 Load(0) Cost(0) ->  0 Load(0) Cost(0)
Distance of the route: 0m
Load of the route: 0

There's got to be a bug or a missed search branch somewhere perhaps?  It seems that the binary case of using one vehicle or the other is pushing the search into a local minimum that it cannot get out of, no matter what.  Or maybe this is just a case that OR Tools cannot handle.  I will open an issue on github if the devs on this list think it is worth pursuing.

Regards,
James
disjunction_okay.py
disjunction_fail.py

Teemu Niemelä

unread,
Jun 9, 2019, 4:18:38 PM6/9/19
to or-tools...@googlegroups.com
Hi,

Thank you again for investigating this. Let know if you need any help for testing when you have fix for this.

Best regards, Teemu

To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/or-tools-discuss/07839c41-9cea-44bf-9765-d2c717c2e4f2%40googlegroups.com.

blind.line

unread,
Jun 12, 2019, 7:18:32 PM6/12/19
to or-tools...@googlegroups.com
Can one of the devs have a look at the issue Teemu opened on github please?  https://github.com/google/or-tools/issues/1348

I copied my python code and linked to my repo. Anything else I can do to help this?  (Besides relearn c++ that is). 

James
Reply all
Reply to author
Forward
0 new messages