I'd like to define a routing problem using RoutingModel including nodes that are freed from the must-visit constraint, but have an influence on a capacity dimension if visited. Do you have any suggestions how to do this?
You can use disjunction constraints to make your nodes optional. You should add each node to its own disjunction group, each having a single element:
for node in [0, 1, 2, 3, 4]:
routing.AddDisjunction(
nodes=[node],
penalty=1)
Why does this work?
In a disjunction group, the solver will try to include in the solution exactly max_cardinality nodes from that group.
If penalty is negative, this will be treated as a hard constraint, which means that the solver will not return a valid solution if the constraint is not satisfied.
However, if penalty is positive, this will be a soft constraint, meaning that a violation will add a penalty to the global cost variable.
Therefore, in order to minimize the penalties, the solver will attempt to include in the solution as many nodes as possible, while still being allowed to leave some of them out.
Related
I have a list of orders, each consists of a disjunction of pickup and a disjunction of delivery nodes (using AddDisjunction with a positive penalty and max cardinality of 1).
Some of these orders form groups that must be delivered to the same location at the same time by the same vehicle, or not at all.
AddPickupAndDelivery/AddPickupAndDeliverySets cannot be used on the same node/disjunction twice so I cannot merge the delivery disjunctions into one and link all pickup disjunctions to it.
I have tried setting the NextVar of one delivery disjunction to the other delivery disjunction, however the other disjunction was still sometimes reached without the first one (but not vice versa).
I have tried combining the NextVar method with giving penalty for reaching only part of the delivery nodes, in two different ways:
first by using AddSoftSameVehicleConstraint, however it did not give penalty for unperformed nodes,
second by creating a new dimension with positive arc values for reaching all disjunctions other than the first one in the NextVar chain, and a negative arc value for reaching the latter, which is the only one that can be reached only if all the rest of the disjunctions were reached. Combined with SetSpanCostCoefficientForAllVehicles and a big cumul var start value at the start nodes, the idea was that reaching part of the nodes would induce a positive span, while reaching all of them would reset the span back to 0.
However at this point the algorithm stopped reaching any nodes, I presume due to the fact that the local search operators do not include a single addition of multiple nodes, and each addition of a single node induces a higher cost. Is there a way of implementing multiple pickups to a single delivery which abides the constraints I have stated while using the python version of or-tools?
I'm trying to solve a classic Traveling Salesman Problem (TSP). I'm using Google OR Tools default TSP wrapper code. I want some arcs to be forbidden, in the sense that perhaps there is no path between node 10 and node 12. In this instance, I set the value to a large number, like 10^6, but the solver still uses that arc.
I verified that this particular instance has a feasible solution, in the sense that when I run the same code twice or extend the time limit of the solver from 30s to 60s, the solver found a solution that does not use this arc.
The question I have: is there a way to specify a hard constraint that this can't be used, instead of setting the arc cost to ∞? I imagine that in a classic TSP Linear Program, a constraint can be set on the binary decision variable.
You have two options:
Create a routing dimension so you can set a vehicle capacity (i.e. vehicle longest distance allowed). Thus any arc whose transit cost is above this capacity is effectively forbidden (vehicle capacity is an hard constraint).
e.g.
# Add Distance constraint.
dimension_name = 'Distance'
routing.AddDimension(
transit_callback_index, # you can reuse the same callback use in SetArcCost
0, # no slack
42_000, # vehicle maximum travel distance
True, # start cumul to zero
dimension_name)
now every arcs above 42_000 is forbidden.
You can remove some arcs by tweaking the routing.NextArc()
e.g. to remove arc {I,J}
i_index = manager.NodeToIndex(I)
j_index = manager.NodeToIndex(J)
routing.NextVar(i_index).RemoveValue(j_index)
note: you also have the RemoveValues([....]) to suppress a list of outgoing arcs.
I have a problem when I want to optimize the global Cost of the vehicules' route. So for that I register a Cost Dimension for returning the cost associated to each arc. But at the same time I have restrictions in another dimensions such as Time & Distance. How can I achieve this? Maybe I just only have to use AddDimension for each callback, but I don't know how to set the Objective function in RoutingModel.
All in your question: Does restriction aka constraint should be part of the objective cost ? or this is just, well constraints the solver need to fulfill ?
Adding new dimension using AddDimension() is a good start IMHO.
note: You may also add the span or global span of any dimension to the objective cost by setting the corresponding coefficient (zero by default thus dimension won't participate to the objective cost and only add "constraint" to the solution)
ref: https://github.com/google/or-tools/blob/b37d9c786b69128f3505f15beca09e89bf078a89/ortools/constraint_solver/routing.h#L2482-L2496
Can someone please point me to the part in the documentation explaining the difference between nodes and indices? I'm going over code that was written by someone else and it seems to use nodes and indices interchangeably. Also, when I apply NodeToIndex or IndexToNode on a variable, the value does not change.
Please read: https://developers.google.com/optimization/routing
indices are internal object belonging to the solver, nodes are linked to the distance matrix and the user visits.
In the underlying constraint programming model of routing problems, each stop is exactly visited once. Each stop is a index. The routing library allows several vehicles to start and end at a stop. This causes a conflict because a stop may be visited by several vehicles. In ortools this conflict is resolved by creating dummy indices for nodes that are visited by several vehicles. Hence there may be several indicies that are map to the same node. The depot is a typical example.
This page about the auxillary graph helped me: https://acrogenesis.com/or-tools/documentation/user_manual/manual/tsp/model_behind_scenes.html#the-auxiliary-graph
In the known paper Impossibility of Distributed Consensus with one Faulty Process (JACM85), FLP (Fisher, Lynch and Paterson) proved the surprising result that no completely asynchronous consensus protocol can tolerate even a single unannounced process death.
In Lemma 3, after showing that D contains both 0-valent and 1-valent configurations, it says:
Call two configurations neighbors if one results from the other in a single step. By an easy induction, there exist neighbors C₀, C₁ ∈ C such that Dᵢ = e(Cᵢ) is i-valent, i = 0, 1.
I can follow the whole proof except when they claim the existence of such C₀ and C₁. Could you please give me some hints?
D (the set of possible configurations after applying e to elements of C) contains both 0-valent and 1-valent configurations (and is assumed to contain no bivalent configurations).
That is — e maps every element in C to either a 0-valent or a 1-valent configuration. By definition of C, there must be a root element that is connected to all other elements by a series of "neighbour" relationships, so there must be a boundary point where an element in C that leads to a 0-valent configuration after e is neighbours with an element in C that leads to a 1-valent configuration after e.
I once went down the path of reading all these papers only to discover its a complete waste of time.
The result is not surprising at all.
The paper you mention "[Impossibility of Distributed Consensus with One Faulty
Process]" 1
is a long list of complex mathematical proofs that simply equate to:
1) Consensus is a deterministic state
2) one (or more) faulty systems within an environment is a non deterministic environment
3) No deterministic state, action or outcome can ever be reached within a non deterministic environment.
The end. No further thought is required.
This is how it works in the real world outside of acadamia.
If you wish for agents to reach consensus then Synchronous (Timing model) approximation constructs have to be added to make the environment deterministic within a given set of constraints. For example simple constructs like Timeouts, Ack/Nack, Handshake, Witness, or way more complex constructs.
The closer you wish to get to a Synchronous deterministic model the more complex the constructs become. A hypothetical Synchronous model would have infinitely complex constructs. Also bearing in mind that a fully deterministic Synchronous model can never be achieved in a non trivial distributed system. This is because in any non trivial dynamic multi variate system with a variable initial state there exists an infinite number of possible states, actions and outcomes at any point in time. Chaos Theory
Consider the complexity of a construct for detecting a dropped TCP packets because of buffer overflow errors in a router at hop number 21. And the complexity of detecting the same buffer overflow error dropping the detection signal from the construct itself.
Define a mapping f such that f(C) = 0, if e(C) is 0-valent, otherwise, f(C) = 1, if e(C) is 1-valent.
Because e(C) could not be bivalent, if we assume that D has no bivalent configuration, f(C) could only be either 0 or 1.
Arrange accessible configurations from the initial bivalent configuration in a tree, there must be two neighbors C0, C1 in the tree that f(C0) != f(C1). Because, if not, all f(C) are the same, which means that D has only either all 0-valent configurations or all 1-valent configurations.