Data update

This commit is contained in:
Ingy döt Net 2026-02-01 16:33:20 -08:00
parent 5150844a7d
commit 4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions

View file

@ -1,32 +0,0 @@
private with Ada.Containers.Ordered_Maps;
generic
type t_Vertex is (<>);
package Dijkstra is
type t_Graph is limited private;
-- Defining a graph (since limited private, only way to do this is to use the Build function)
type t_Edge is record
From, To : t_Vertex;
Weight : Positive;
end record;
type t_Edges is array (Integer range <>) of t_Edge;
function Build (Edges : in t_Edges; Oriented : in Boolean := True) return t_Graph;
-- Computing path and distance
type t_Path is array (Integer range <>) of t_Vertex;
function Shortest_Path (Graph : in out t_Graph;
From, To : in t_Vertex) return t_Path;
function Distance (Graph : in out t_Graph;
From, To : in t_Vertex) return Natural;
private
package Neighbor_Lists is new Ada.Containers.Ordered_Maps (Key_Type => t_Vertex, Element_Type => Positive);
type t_Vertex_Data is record
Neighbors : Neighbor_Lists.Map; -- won't be affected after build
-- Updated each time a function is called with a new source
Previous : t_Vertex;
Distance : Natural;
end record;
type t_Graph is array (t_Vertex) of t_Vertex_Data;
end Dijkstra;

View file

@ -1,91 +0,0 @@
with Ada.Containers.Ordered_Sets;
package body Dijkstra is
Infinite : constant Natural := Natural'Last;
-- ----- Graph constructor
function Build (Edges : in t_Edges; Oriented : in Boolean := True) return t_Graph is
begin
return Answer : t_Graph := (others => (Neighbors => Neighbor_Lists.Empty_Map,
Previous => t_Vertex'First,
Distance => Natural'Last)) do
for Edge of Edges loop
Answer(Edge.From).Neighbors.Insert (Key => Edge.To, New_Item => Edge.Weight);
if not Oriented then
Answer(Edge.To).Neighbors.Insert (Key => Edge.From, New_Item => Edge.Weight);
end if;
end loop;
end return;
end Build;
-- ----- Paths / distances data updating in case of computation request for a new source
procedure Update_For_Source (Graph : in out t_Graph;
From : in t_Vertex) is
function Nearer (Left, Right : in t_Vertex) return Boolean is
(Graph(Left).Distance < Graph(Right).Distance or else
(Graph(Left).Distance = Graph(Right).Distance and then Left < Right));
package Ordered is new Ada.Containers.Ordered_Sets (Element_Type => t_Vertex, "<" => Nearer);
use Ordered;
Remaining : Set := Empty_Set;
begin
-- First, let's check if vertices data are already computed for this source
if Graph(From).Distance /= 0 then
-- Reset distances and remaining vertices for a new source
for Vertex in Graph'range loop
Graph(Vertex).Distance := (if Vertex = From then 0 else Infinite);
Remaining.Insert (Vertex);
end loop;
-- ----- The Dijkstra algorithm itself
while not Remaining.Is_Empty
-- If some targets are not connected to source, at one point, the remaining
-- distances will all be infinite, hence the folllowing stop condition
and then Graph(Remaining.First_Element).Distance /= Infinite loop
declare
Nearest : constant t_Vertex := Remaining.First_Element;
procedure Update_Neighbor (Position : in Neighbor_Lists.Cursor) is
use Neighbor_Lists;
Neighbor : constant t_Vertex := Key (Position);
In_Remaining : Ordered.Cursor := Remaining.Find (Neighbor);
Try_Distance : constant Natural :=
(if In_Remaining = Ordered.No_Element
then Infinite -- vertex already reached, this distance will fail the update test below
else Graph(Nearest).Distance + Element (Position));
begin
if Try_Distance < Graph(Neighbor).Distance then
-- Update distance/path data and reorder the remaining set
Remaining.Delete (In_Remaining);
Graph(Neighbor).Distance := Try_Distance;
Graph(Neighbor).Previous := Nearest;
Remaining.Insert (Neighbor);
end if;
end Update_Neighbor;
begin
Remaining.Delete_First;
Graph(Nearest).Neighbors.Iterate (Update_Neighbor'Access);
end;
end loop;
end if;
end Update_For_Source;
-- ----- Bodies for the interfaced functions
function Shortest_Path (Graph : in out t_Graph;
From, To : in t_Vertex) return t_Path is
function Recursive_Build (From, To : in t_Vertex) return t_Path is
(if From = To then (1 => From)
else Recursive_Build(From, Graph(To).Previous) & (1 => To));
begin
Update_For_Source (Graph, From);
if Graph(To).Distance = Infinite then
raise Constraint_Error with "No path from " & From'Img & " to " & To'Img;
end if;
return Recursive_Build (From, To);
end Shortest_Path;
function Distance (Graph : in out t_Graph;
From, To : in t_Vertex) return Natural is
begin
Update_For_Source (Graph, From);
return Graph(To).Distance;
end Distance;
end Dijkstra;

View file

@ -1,39 +0,0 @@
with Ada.Text_IO; use Ada.Text_IO;
with Dijkstra;
procedure Test_Dijkstra is
subtype t_Tested_Vertices is Character range 'a'..'f';
package Tested is new Dijkstra (t_Vertex => t_Tested_Vertices);
use Tested;
Graph : t_Graph := Build (Edges => (('a', 'b', 7),
('a', 'c', 9),
('a', 'f', 14),
('b', 'c', 10),
('b', 'd', 15),
('c', 'd', 11),
('c', 'f', 2),
('d', 'e', 6),
('e', 'f', 9)));
procedure Display_Path (From, To : in t_Tested_Vertices) is
function Path_Image (Path : in t_Path; Start : Boolean := True) return String is
((if Start then "["
elsif Path'Length /= 0 then ","
else "") &
(if Path'Length = 0 then "]"
else Path(Path'First) & Path_Image(Path(Path'First+1..Path'Last), Start => False)));
begin
Put ("Path from '" & From & "' to '" & To & "' = ");
Put_Line (Path_Image (Shortest_Path (Graph, From, To))
& " distance =" & Distance (Graph, From, To)'Img);
exception
when others => Put_Line("no path");
end Display_Path;
begin
Display_Path ('a', 'e');
Display_Path ('a', 'f');
New_Line;
for From in t_Tested_Vertices loop
for To in t_Tested_Vertices loop
Display_Path (From, To);
end loop;
end loop;
end Test_Dijkstra;

View file

@ -1,4 +1,4 @@
define :graph [vertices, neighbours][]
define :graph [vertices, neighbours]
initGraph: function [edges][
vs: []
@ -19,7 +19,7 @@ Inf: 1234567890
dijkstraPath: function [gr, fst, lst][
dist: #[]
prev: #[]
result: new []
result: []
notSeen: new gr\vertices
loop gr\vertices 'vertex ->
dist\[vertex]: Inf

View file

@ -1,62 +0,0 @@
(defvar path-list '((a b 7)
(a c 9)
(a f 14)
(b c 10)
(b d 15)
(c d 11)
(c f 2)
(d e 6)
(e f 9)))
(defun calculate-shortest-path (path-list)
(let (shortest-path)
(dolist (path path-list)
(add-to-list 'shortest-path (list (nth 0 path)
(nth 1 path)
nil
(nth 2 path))
't))
(dolist (path path-list)
(dolist (short-path shortest-path)
(when (equal (nth 0 path) (nth 1 short-path))
(let ((test-path (list (nth 0 short-path)
(nth 1 path)
(nth 0 path)
(+ (nth 2 path) (nth 3 short-path))))
is-path-found)
(dolist (short-path1 shortest-path)
(when (equal (seq-take test-path 2)
(seq-take short-path1 2))
(setq is-path-found 't)
(when (> (nth 3 short-path1) (nth 3 test-path))
(setcdr (cdr short-path1) (cddr test-path)))))
(when (not is-path-found)
(add-to-list 'shortest-path test-path 't))))))
shortest-path))
(defun find-shortest-route (from to path-list)
(let ((shortest-path-list (calculate-shortest-path path-list))
point-list matched-path distance)
(add-to-list 'point-list to)
(setq matched-path
(seq-find (lambda (path) (equal (list from to) (seq-take path 2)))
shortest-path-list))
(setq distance (nth 3 matched-path))
(while (nth 2 matched-path)
(add-to-list 'point-list (nth 2 matched-path))
(setq to (nth 2 matched-path))
(setq matched-path
(seq-find (lambda (path) (equal (list from to) (seq-take path 2)))
shortest-path-list)))
(if matched-path
(progn
(add-to-list 'point-list from)
(list 'route point-list 'distance distance))
nil)))
(format "%S" (find-shortest-route 'a 'e path-list))

View file

@ -1,7 +1,6 @@
# Experimental!
# Use table of edge weights.
A ← [[0 7 9 0 0 14] [0 0 10 15 0 0] [0 0 0 11 0 2]
[0 0 0 0 6 0] [0 0 0 0 0 9][0 0 0 0 0 0]]
Ns ← ⍜⊟⍜⍉(▽⊸≡(≠0⊢)):°⊏⊡:A # Neighbours with costs.
P ← &p$"Path: _ with cost _"/$"_->_"+@a°□⊢astar(Ns|0|≍)°⊟
P ← &p$"Path: _ with cost _"/$"_->_"+@a°□⊢path(Ns|≍)°⊟
≡P[0_4 0_5]