Closed jcasanov closed 9 years ago
I have also a segmentation fault on the tsp algorithm.
cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=10.10 DISTRIB_CODENAME=maverick DISTRIB_DESCRIPTION="Ubuntu 10.10" dpkg -l | grep postgre ii postgresql 8.4.8-0ubuntu0.10.10 object-relational SQL database (supported version) ii postgresql-8.4 8.4.8-0ubuntu0.10.10 object-relational SQL database, version 8.4 server ii postgresql-8.4-pgrouting 1.05-1~maverick2 routing functionality support for PostgreSQL 8.4 ii postgresql-8.4-pgrouting-dd 1.05-1~maverick2 routing functionality support for PostgreSQL 8.4 ii postgresql-8.4-pgrouting-tsp 1.05-1~maverick2 routing functionality support for PostgreSQL 8.4 ii postgresql-8.4-postgis 1.5.1-5 geographic objects support for PostgreSQL 8.4 ii postgresql-client-8.4 8.4.8-0ubuntu0.10.10 front-end programs for PostgreSQL 8.4 ii postgresql-client-common 111 manager for multiple PostgreSQL client versions ii postgresql-common 111 PostgreSQL database-cluster manager dpkg -l | grep pgrou
ii osm2pgrouting 0.1-5 Tool to import OpenStreetMap data into a pgRouting database. ii postgresql-8.4-pgrouting 1.05-1~maverick2 routing functionality support for PostgreSQL 8.4 ii postgresql-8.4-pgrouting-dd 1.05-1~maverick2 routing functionality support for PostgreSQL 8.4 ii postgresql-8.4-pgrouting-tsp 1.05-1~maverick2 routing functionality support for PostgreSQL 8.4
Here is my log trying with a simple and stupid example: 2011-05-25 13:39:44 CEST STATEMENT: select * from tsp('select 1 as source_id, 2 as x, 3 as y', '1, 2, 3', 4); 2011-05-25 13:39:56 CEST LOG: server process (PID 14474) was terminated by signal 11: Segmentation fault 2011-05-25 13:39:56 CEST LOG: terminating any other active server processes 2011-05-25 13:39:56 CEST WARNING: terminating connection because of crash of another server process 2011-05-25 13:39:56 CEST DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory. 2011-05-25 13:39:56 CEST HINT: In a moment you should be able to reconnect to the database and repeat your command. 2011-05-25 13:39:56 CEST LOG: all server processes terminated; reinitializing 2011-05-25 13:39:56 CEST LOG: database system was interrupted; last known up at 2011-05-25 13:39:19 CEST 2011-05-25 13:39:56 CEST LOG: database system was not properly shut down; automatic recovery in progress 2011-05-25 13:39:56 CEST LOG: redo starts at 0/1197648 2011-05-25 13:39:56 CEST LOG: record with zero length at 0/1387298 2011-05-25 13:39:56 CEST LOG: redo done at 0/1387268 2011-05-25 13:39:56 CEST LOG: last completed transaction was at log time 2011-05-25 13:39:56.285473+02 2011-05-25 13:39:56 CEST LOG: database system is ready to accept connections 2011-05-25 13:39:56 CEST LOG: autovacuum launcher started
Looking at the code I think that the problem might be that s can be not initialized. I don't understand how does the genetic algorithm works, but probably we need a default choice in case the source_id is not on the cromosomes.
boolean tsp_seed(population *pop, entity *adam)
{
int i,s,tmp;
int *data;
data = (int *)adam->chromosome[0];
for (i=0; ilen_chromosomes; i++)
{
data[i] = i;
}
//Maybe s = 0 here?
for (i=0; ilen_chromosomes; i++)
{
if(ids[data[i]] == source_id)
s = i;
}
tmp = data[0];
data[0] = data[s]; // this line is the one with the problem
data[s] = tmp;
return TRUE;
}
In case someone else arrives here and needs a travelling salesman algorithm, I have written a simple script which can skip this problem. It is a brute-force travelling salesman implementation using dijkstra or shooting_star (see issue #31).
It is not very good, but can be handy for further implementations.
DROP FUNCTION IF EXISTS gofleet_tsp(TEXT, TEXT, TEXT, INTEGER);
DROP FUNCTION IF EXISTS gofleet_tsp_next(TEXT, TEXT, TEXT, INTEGER);
DROP TYPE IF EXISTS gofleet_tsp_res_table;
CREATE TYPE gofleet_tsp_res_table as (
id BIGINT,
edge INTEGER,
the_geom GEOMETRY,
cost DOUBLE PRECISION
);
CREATE FUNCTION gofleet_tsp_next(rtable TEXT, ptable TEXT, gid TEXT, source INTEGER)
RETURNS INTEGER AS
$BODY$
DECLARE
answer INTEGER;
r RECORD;
BEGIN
RAISE INFO 'gofleet_tsp_next(%, %, %, %)', rtable, ptable, gid, source;
EXECUTE 'DROP TABLE IF EXISTS routing_next';
EXECUTE 'CREATE TEMPORARY TABLE routing_next
(
id BIGSERIAL NOT NULL,
edge INTEGER NOT NULL,
cost DOUBLE PRECISION NOT NULL,
CONSTRAINT routing_next_pk PRIMARY KEY (id)
)';
BEGIN
FOR r IN EXECUTE 'SELECT DISTINCT id FROM ' || ptable || ' as p WHERE p.id <> ' || source ||
' AND NOT EXISTS (SELECT 1 FROM routing_res as re where p.id =re.edge)' LOOP
RAISE DEBUG 'Calculado hacia %', r.id;
BEGIN
INSERT INTO routing_next
(edge, "cost")
(select r.id, sum(cost) from
shortest_path_shooting_star('SELECT ' || gid || ' as id,
source,
target,
st_length(the_geom) as cost,
st_length(the_geom) as reverse_cost,
x1,
y1,
x2,
y2,
rule,
to_cost FROM ' || rtable, source, r.id :: integer, true, true));
EXCEPTION
WHEN internal_error THEN
RAISE WARNING 'Error calculating route from % to %', source, r.id;
END;
END LOOP;
RAISE DEBUG 'Calculado para %', source;
FOR r IN SELECT DISTINCT edge, cost FROM routing_next ORDER BY cost ASC LOOP
RAISE DEBUG 'Resultados cost % edge %', r.cost, r.edge;
END LOOP;
SELECT edge INTO answer FROM routing_next WHERE edge <> -1 ORDER BY cost ASC LIMIT 1;
RAISE INFO 'Going to EDGE %', answer;
EXCEPTION
WHEN internal_error THEN
RAISE WARNING 'Error calculating next from edge %',source;
END;
RETURN answer;
END;
$BODY$
LANGUAGE 'plpgsql';
--Routing table, Stops table, ID column name, ID source
--The points table contains IDs from the routing table
--where we need to stop
--Routing table contains all the pgrouting data
CREATE FUNCTION gofleet_tsp(rtable TEXT, ptable TEXT, gid TEXT, source INTEGER)
RETURNS setof gofleet_tsp_res_table AS
$BODY$
DECLARE
target INTEGER;
done INTEGER;
max INTEGER;
r RECORD;
BEGIN
RAISE INFO 'gofleet_tsp(%, %, %, %)', rtable, ptable, gid, source;
EXECUTE 'DROP TABLE IF EXISTS routing_res';
EXECUTE 'CREATE TEMPORARY TABLE routing_res
(
id BIGSERIAL NOT NULL,
edge INTEGER NOT NULL,
the_geom GEOMETRY,
cost DOUBLE PRECISION NOT NULL,
CONSTRAINT routing_res_pk PRIMARY KEY (id)
)';
RAISE DEBUG 'Table routing_res created.';
BEGIN
SELECT COUNT(1) INTO done FROM routing_res as re WHERE
EXISTS (SELECT 1 FROM puntos p WHERE p.id = re.edge);
SELECT COUNT(1) INTO max FROM puntos p;
WHILE done < max LOOP
SELECT * INTO target FROM gofleet_tsp_next(rtable, ptable, gid, source);
INSERT INTO routing_res
(edge, "cost")
(select edge_id, cost from
shortest_path_shooting_star('SELECT ' || gid || ' as id,
source,
target,
st_length(the_geom) as cost,
st_length(the_geom) as reverse_cost,
x1,
y1,
x2,
y2,
rule,
to_cost FROM ' || rtable, source, target, true, true));
SELECT target INTO source;
SELECT COUNT(1) INTO done FROM routing_res as re WHERE
EXISTS (SELECT 1 FROM puntos p WHERE p.id = re.edge);
FOR r in SELECT * FROM routing_res LOOP
RAISE INFO '%', r;
END LOOP;
END LOOP;
EXCEPTION
WHEN internal_error THEN
RAISE WARNING 'Error calculating route from % to %',source, target;
END;
EXECUTE 'UPDATE routing_res SET the_geom = (SELECT the_geom from ways where routing_res.edge = ways.gid)';
RETURN QUERY EXECUTE 'SELECT * FROM routing_res ORDER BY id ASC';
END;
$BODY$
LANGUAGE 'plpgsql';
About the tsp_seed, it seems logical... not sure if is the right fix but it still fixes the problem. About the gofleet_tsp() function, is that doing the same as tsp_astar_directed()?
I have changed the script because it failed on dijkstra and now I only use shooting_star. To use dijkstra you just have to change the function called (shortest_path...) and use vertex instead of edges.
And yes, it works more or less like a directed shooting star, but I cannot warrantee you that it will work well in all cases. The script begins on the source edge and looks for the nearest stop edge (where the salesman needs to stop). After calculating the nearest path to the nearest edge, it saves this path and goes to the next one, using the last stop edge as the new source edge.
I am using the length function as cost and reverse cost, but you can change the sql-texted-queries on the script to use cost and reverse cost columns.
A real application should look for the nearest edges of the points where the salesman needs to stop, put them on a table, and then call gofleet_tsp with the parameters described on the code.
And, again, this was a fast-written script, I wouldn't rely on it unless you yourself make some tests.
Cool! i will check it as soon as possible... thanks It could be terrific if some of the pgRouting developers look at this issue, if they don't fix it maybe they can incorporate your function (of course, if you agree and they prove it to be good)
Hi Delawen,
This script seems to not compile in Postgres 8.4. Do you know how to modify it to work in Postgres 8.4 !? Thank you.
I do not have a Postgres 8.4 here, what is the exact error?
Anyway, you may want to take a look at this: https://github.com/Emergya/GoFleetLSServer/tree/master/src/main/database
It contains an updated and evolutioned version of that script.
Maybe it is because of the "DROP......IF EXISTS" of the first lines? You can skip that lines if it causes you troubles.
The updated script works in Postgres 8.4. Thank you.
Dear Delawen,
The 'routingTable' parameter of function gls_tsp may be a subquery such as 'SELECT *,the_geom as geometry FROM roads'. But the script in 'gofleet_tsp.sql' seems not to take that into consideration. I tried to modify the script myself. Following is my modification for the script:
And another question. function 'gls_tsp' return 'text []' instead of 'table'. How can I convert 'text[]' to 'table' !? Thank you.
ps. sorry for my poor English
back to the original problem statement:
simply overwrite the wrapper function, replacing "tsp_test" with " ' || quote_ident(geom_table) || ' "
thanks gubuntu for your comment. i did that and now i still see a crash, this is the initial backtrace:
Core was generated by `postgres: postgres db [local] SELECT '. Program terminated with signal 11, Segmentation fault.
fit=0x7fff89d10be8, err_msg=<value optimized out>) at /usr/src/debug/pgrouting-1.05/extra/tsp/src/tsp_solver.cpp:299
299 if(score < ga_get_entity_from_rank(pop,0)->fitness)
as you can see this is failing at tsp_solver line 299 which is an "if " statement and the only think i can see as a possible problem is the function ga_get_entity_from_rank() which comes from GAUL.
just added a pull request with the simplest of the fixes, not sure if it's the right (tm) fix though
Thanks for looking into that! Do you mean this Pull request: https://github.com/pgRouting/pgrouting/pull/84 ? (just to have a reference here)
El 22/03/2013 10:36, "Daniel Kastl" notifications@github.com escribió:
Thanks for looking into that! Do you mean this Pull request: #84 ? (just to have a reference here)
exactly that. i'm not sure is THE solution but at least looks like a sensible check to avoid the crash
Jaime Casanova 2ndQuadrant: Your PostgreSQL partner
Fixed this in sew-devel-2_0, leaving it tagged as 1.x
Closing - Wont fix.
I installed pgrouting 1.05 with tsp on a centos 5.5 machine with postgres 8.4.7 and postgis 1.3.6. When i tried to run this query:
i get this message "ERROR: relation "tsp_test" does not exist at character 328" which is because the function tsp_astar_directed() in routing_tsp_wrappers.sql has an UNION ALL that takes values from that table (that obviously doesn't really exist)... i workaround that problem creating a dummy tsp_test table...
then when i try the same select i get "segmentation fault", this is the backtrace:
which points at this: