-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdjikstras.sql
More file actions
84 lines (77 loc) · 2.56 KB
/
djikstras.sql
File metadata and controls
84 lines (77 loc) · 2.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
create table g(source int, target int, weight int);
create table paths(target int, distance int);
create table fringe(val int);
create table nodes (node int, f int, g int, visited int);
create or replace function dijkstra(source int)
returns table(tar int, dis int) as $$
declare
initial int = source;
n nodes%rowtype;
sdash g%rowtype;
s int;
d int;
temp int;
goal int;
dist int;
begin
if (select not exists(select * from nodes where node=initial)) then
return;
end if;
truncate paths;
truncate nodes;
insert into nodes (node,f,g,visited) select g.source as node,0,0,0 from g g union select g.target as node,0,0,0 from g g order by node;
--raise notice 'source: %', initial;
for n in select * from nodes
loop
insert into paths values(n.node,0);
end loop;
for n in select * from nodes
loop
update nodes set f=0,g=0,visited=0;
goal = n.node;
--raise notice 'goal: %', goal;
if initial=goal then
update paths set distance=0 where target=goal;
--raise notice 'Initial=goal';
continue;
end if;
truncate fringe;
insert into fringe values(initial);
loop
if (select not exists(select * from fringe)) then
update paths set distance=null where target=goal;
--raise notice 'No path exists!';
exit;
end if;
select f.val into s from fringe f inner join nodes nod on (nod.node=f.val) where nod.f<=all(select nod.f from nodes nod inner join fringe f on (nod.node=f.val));
--raise notice 'Removing s from fringe: %', s;
update nodes set visited=1 where node=s;
delete from fringe where val=s;
if s=goal then
select f into d from nodes where node=s;
select distance into temp from paths where target=s;
update paths set distance=distance+(select f from nodes where node=goal) where target=s;
--raise notice 's=goal and dist=% + %', temp,d;
exit;
end if;
if (select exists(select * from g g where g.source=s)) then
for sdash in select * from g g where g.source=s
loop
if (select visited from nodes where node=sdash.target)=1 then
continue;
end if;
select g.weight into dist from g g where g.source=s and sdash.target=g.target;
update nodes set g=dist where node=sdash.target;
select f into temp from nodes where node=s;
update nodes set f=temp+dist where node=sdash.target;
insert into fringe values(sdash.target);
--raise notice 'Inserting into fringe: %', sdash.target;
--raise notice 'weight:% + %', temp,dist;
end loop;
end if;
end loop;
end loop;
return query
select target, distance from paths order by target;
end;
$$ language plpgsql;