Commit 5a548dbe authored by Jean-Benoist Leger's avatar Jean-Benoist Leger

Very more efficent method to compute CC

parent 7a1b2d90
......@@ -2,10 +2,8 @@
BEGIN;
-- rv_ways
DROP TABLE IF EXISTS rv_ways;
CREATE TABLE rv_ways (id BIGINT, cc BIGINT, ccprov BIGINT);
CREATE TABLE rv_ways (id BIGINT);
ALTER TABLE rv_ways ADD CONSTRAINT pk_rv_ways PRIMARY KEY (id);
CREATE INDEX idx_rv_ways_cc ON rv_ways USING btree (cc);
CREATE INDEX idx_rv_ways_ccprov ON rv_ways USING btree (ccprov) WHERE cc IS NULL;
-- rv_nodes
DROP TABLE IF EXISTS rv_nodes;
......
DROP FUNCTION IF EXISTS propage();
CREATE FUNCTION propage() RETURNS VOID AS $$
DROP FUNCTION IF EXISTS propto();
CREATE FUNCTION propto() RETURNS VOID AS $$
DECLARE
nb BIGINT;
k BIGINT;
BEGIN
nb:=1;
k:=1;
WHILE nb<>0 LOOP
UPDATE rv_ways
SET
ccprov=k+1
FROM
(
SELECT
w2.id AS id
FROM
rv_ways AS w1
INNER JOIN
rv_way_way AS ww ON w1.id=ww.id1
INNER JOIN
rv_ways AS w2 ON w2.id=ww.id2
WHERE
w1.ccprov=k AND w1.cc IS NULL
AND
w2.ccprov IS NULL AND w2.cc IS NULL
) AS sub
WHERE
rv_ways.id=sub.id;
k:=k+1;
GET DIAGNOSTICS nb = ROW_COUNT;
END LOOP;
END;
$$ LANGUAGE plpgsql;
DROP FUNCTION IF EXISTS etiqueter();
CREATE FUNCTION etiqueter() RETURNS BIGINT AS $$
DECLARE
n BIGINT;
ccref BIGINT;
updated BIGINT;
count BIGINT;
BEGIN
ccref:=0;
WITH
mm AS
(
SELECT
DISTINCT ON (wc1.cc_id)
wc1.cc_id AS old_cc_id,
wc2.cc_id AS new_cc_id
FROM
rv_way_cc AS wc1
INNER JOIN
rv_way_way AS ww ON wc1.way_id=ww.id1
INNER JOIN
rv_way_cc AS wc2 ON ww.id2=wc2.way_id
ORDER BY wc1.cc_id,wc2.cc_id
)
UPDATE rv_way_cc
SET
cc_id=sub.new_cc_id
FROM
(
SELECT * FROM mm WHERE NOT old_cc_id=new_cc_id
) AS SUB
WHERE
cc_id=sub.old_cc_id;
SELECT DISTINCT cc FROM rv_ways WHERE NOT cc IS NULL ORDER BY cc DESC LIMIT 1 INTO ccref;
GET DIAGNOSTICS count = ROW_COUNT;
ccref:=ccref+1;
IF count=0 THEN
ccref:=0;
END IF;
n:=ccref;
LOOP
UPDATE rv_ways
SET
ccprov=1
FROM
(
SELECT
id
FROM
rv_ways
WHERE
cc IS NULL
LIMIT 1
) AS sub
WHERE rv_ways.id=sub.id;
PERFORM propage();
UPDATE rv_ways SET cc=n, ccprov=NULL WHERE cc IS NULL AND NOT ccprov IS NULL;
GET DIAGNOSTICS updated = ROW_COUNT;
PERFORM id FROM rv_ways WHERE cc IS NULL;
GET DIAGNOSTICS count = ROW_COUNT;
RAISE INFO 'Connected component % with % ways, % ways left', n, updated, count;
n:=n+1;
EXIT WHEN count=0;
GET DIAGNOSTICS nb = ROW_COUNT;
RAISE INFO '% ways updated', nb;
END LOOP;
RETURN ccref;
END;
$$ LANGUAGE plpgsql;
--
-- modifs
DROP FUNCTION IF EXISTS osmosisUpdate();
CREATE FUNCTION osmosisUpdate() RETURNS VOID AS $$
DECLARE
ccref BIGINT;
DROP FUNCTION IF EXISTS updateRV();
CREATE FUNCTION updateRV() RETURNS VOID AS $$
BEGIN
-- rv_ways
-- on note les cc touchées par la modification des ways
......@@ -66,86 +64,6 @@ BEGIN
)
);
-- update de la table des liens du graph dual, deux ways sont liées si elles
-- partagent un noeud
-- on utilise la methode bourinne, on efface le contenu et on le recrée
CREATE TEMP TABLE rv_way_way (id1 BIGINT, id2 BIGINT) ON COMMIT DROP;
INSERT INTO rv_way_way
(
SELECT DISTINCT
w1.id AS id1,
w2.id AS id2
FROM
rv_ways AS w1
INNER JOIN
way_nodes AS wn1 ON wn1.way_id=w1.id
INNER JOIN
way_nodes AS wn2 ON wn2.node_id=wn1.node_id AND wn2.way_id<>wn1.way_id
INNER JOIN
rv_ways AS w2 ON w2.id=wn2.way_id
);
CREATE INDEX idx_rv_ways_id1 ON rv_way_way USING btree (id1);
-- on note les cc touchées, ce sont les cc qui ont été touchés par l'ajout
-- d'un noeud dans un way, donc il faut propager une fois par rv_way_way
-- pour voir toutes les composantes connexes qui auront été réunies
INSERT INTO actions
(
SELECT
'c' AS data_type,
'M' AS action,
sub.id AS id
FROM
(
(
SELECT DISTINCT
rv_ways.cc AS id
FROM
actions AS a1
INNER JOIN
rv_way_way ON a1.id=rv_way_way.id1
INNER JOIN
rv_ways ON rv_way_way.id2=rv_ways.id
WHERE
a1.data_type='W'
AND
NOT rv_ways.cc IS NULL
)
EXCEPT
(
SELECT
id
FROM
actions
WHERE
data_type='c'
)
) AS sub
);
-- maintenant qu'on a toutes les cc touchées par la modification on mets à
-- NULL la cc de tous les ways pour un calcul de composantes connexe
-- ulterieur
UPDATE rv_ways
SET
cc=NULL
FROM
(
SELECT DISTINCT
id
FROM
actions
WHERE
data_type='c'
) AS sub
WHERE
rv_ways.cc=sub.id;
DELETE FROM actions WHERE data_type='c';
-- on labelise les cc qui ont été placés à NULL
SELECT etiqueter() INTO ccref;
-- rv_edges
-- etape 1 : on effacte tous les edges qui proviennent d'un ways
DELETE FROM rv_edges
......@@ -256,8 +174,46 @@ BEGIN
nodes ON nodes.id=n.id
);
-- etape 4 : on mets à jour les labels de cc à partir de ceux calculés sur
-- computation of connected components
-- puis on mets à jour les labels de cc à partir de ceux calculés sur
-- le graph dual
CREATE TEMP TABLE rv_way_way (id1 BIGINT, id2 BIGINT);
INSERT INTO rv_way_way
(
SELECT DISTINCT
w1.id AS id1,
w2.id AS id2
FROM
rv_ways AS w1
INNER JOIN
way_nodes AS wn1 ON wn1.way_id=w1.id
INNER JOIN
way_nodes AS wn2 ON wn2.node_id=wn1.node_id AND wn2.way_id<>wn1.way_id
INNER JOIN
rv_ways AS w2 ON w2.id=wn2.way_id
);
INSERT INTO rv_way_way
(
SELECT
w.id AS id1,
w.id AS id2
FROM
rv_ways AS w
);
CREATE TEMP TABLE rv_way_cc (way_id BIGINT, cc_id BIGINT);
INSERT INTO rv_way_cc
(
SELECT
w.id AS way_id,
w.id AS cc_id
FROM
rv_ways AS w
);
PERFORM propto();
UPDATE rv_nodes
SET
cc=sub.cc
......@@ -265,15 +221,13 @@ BEGIN
(
SELECT DISTINCT
wn.node_id AS id,
w.cc AS cc
wc.cc_id AS cc
FROM
rv_ways AS w
rv_way_cc AS wc
INNER JOIN
way_nodes AS wn ON wn.way_id=w.id
way_nodes AS wn ON wn.way_id=wc.way_id
INNER JOIN
rv_nodes ON rv_nodes.id=wn.node_id
WHERE
w.cc >= ccref
) AS sub
WHERE
sub.id=rv_nodes.id;
......
--
-- modifs
DROP FUNCTION IF EXISTS osmosisUpdate();
CREATE FUNCTION osmosisUpdate() RETURNS VOID AS $$
BEGIN
PERFORM updateRV();
END;
$$ LANGUAGE plpgsql;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment