[pgrouting-dev] New TSP algorithm and refactoring - take 2

Stephen Woodbridge woodbri at swoodbridge.com
Sun Mar 31 07:18:25 PDT 2013


So, here is another look at this problem, by looking at the data the 
needs to flow through the problem.

I am ambivalent about using the ARRAY objects but they are convenient 
for representing ordered collections of objects and specifically the 
dmatrix data.


Solve TSP based on Euclidean distances:

1. list of N points to optimize using TSP
    REC(seq, x, y) or ARRAY[P1, P2, P3, ..., PN]
2. compute euclidean  dmatrix from points
    ARRAY[
        ARRAY[0.0, d2, d3, d4, ..., dN],
        ARRAY[d1, 0.0, d3, d4, ..., dN],
        ARRAY[d1, d2, 0.0, d4, ..., dN],
        ARRAY[d1, d2, d3, 0.0, ..., dN],
        ...,
        ARRAY[d1, d2, d3, d4, ..., 0.0]
    ]
3. solve TSP and get order list of dmatrix indices
    ARRAY[i1, i2, i3, i4, ..., iN]
4. return ordered list of edge pairs
    REC(1, n1, n2, LINESTRING(P[i1], P[i2]))
    REC(2, n2, n3, LINESTRING(P[i2], P[i3]))
    REC(3, n3, n4, LINESTRING(P[i3], P[i4]))
    REC(4, n4, n5, LINESTRING(P[i4], P[i5]))
    ...
    REC(N, nN, n1, LINESTRING(P[iN], P[i1]))

The above is the simple case. We don't need to compute routes. This 
would also have application of solving non-routing optimization problems 
where you have a distance/cost matrix and need to optimize the path 
through it.


Solve TSP based on Driving Distance:

1. list of N points to optimize using TSP
    REC(seq, x, y) or ARRAY[P1, P2, P3, ..., PN]
2. map points to list of N node_ids
    ARRAY[N1, N2, N3, ..., NN]
3. compute dmatrix by routing between nodes
    this step needs to keep more information like the list of edges for
    for each route in the matrix, so we can reconstitute the optimized
    route in the final step. This needs some error handling to deal with
    duplicate nodes, unreachable nodes (ie: failure to route to or from
    a node).
    ARRAY[
        ARRAY[0.0, d2, d3, d4, ..., dN],
        ARRAY[d1, 0.0, d3, d4, ..., dN],
        ARRAY[d1, d2, 0.0, d4, ..., dN],
        ARRAY[d1, d2, d3, 0.0, ..., dN],
        ...,
        ARRAY[d1, d2, d3, d4, ..., 0.0]
    ]
4. solve TSP and get order list of matrix indices
    ARRAY[i1, i2, i3, i4, ..., iN]
5. return ordered list of routes
    REC(1, n1, n2, route_from_dmatrix(n1, n2))
    REC(1, n2, n3, route_from_dmatrix(n2, n3))
    REC(1, n3, n4, route_from_dmatrix(n3, n4))
    REC(1, n4, n5, route_from_dmatrix(n4, n5))
    ...
    REC(1, nN, n1, route_from_dmatrix(nN, n1))

For this we need to cache the computed routes so we don't compute them 
twice. I think that this can get done using a WITH clause to cache the 
routes in a temp table and use a aggregate to assemble the dmatrix. 
Something like:

WITH distances (i, j, dist, route[]) as
  select * from compute_routes(node_ids[], ...)
select * from TSP(make_dmatrix_symmetric(i, j, dist));

There are also some optimizations that can be done if we are working 
with symmetric case vs a non-symmetric case.

Anyway, this is as far as I have gotten try to look at how the data 
needs to flow between the various sub processes to generate a result.

Thoughts,
   -Steve


More information about the pgrouting-dev mailing list