Greedy furthest-neighbour path, compare methods
dkl9

dkl9 commited on 2025-185 23:46:05
Showing 1 changed files, with 45 additions and 3 deletions.

... ...
@@ -1,4 +1,7 @@
1
+import itertools
1 2
 import math
3
+import random
4
+import turtle
2 5
 import typing
3 6
 import collections.abc
4 7
 
... ...
@@ -45,6 +48,16 @@ class BinaryTree:
45 48
 def distance_table[T](points: list[T], metric: Func[[T, T], float]) -> DistTable:
46 49
     return [[metric(x, y) for y in points] for x in points]
47 50
 
51
+def show_mat(distances: DistTable) -> str:
52
+    rows = []
53
+    for i in range(len(distances)):
54
+        first, last = i == 0, i == len(distances) - 1
55
+        row = "/" if first else "\\" if last else "|"
56
+        row += " ".join(f"{d:5.2f}" for d in distances[i])
57
+        row += "\\" if first else "/" if last else "|"
58
+        rows.append(row)
59
+    return "\n".join(rows)
60
+
48 61
 def score_nearest(distances: DistTable, sample: IndSeq) -> float:
49 62
     return sum(min(distances[i][j] for j in sample) for i in range(len(distances)))
50 63
 
... ...
@@ -62,6 +75,19 @@ def greedy_min_seq(distances: DistTable, score_func: Func[[DistTable, IndSeq], f
62 75
         options.remove(best)
63 76
     return seq
64 77
 
78
+def furthest_nb(distances: DistTable) -> IndSeq:
79
+    seq = []
80
+    options = set(range(len(distances)))
81
+    start = min(options, key=lambda o: score_nearest(distances, [o]))
82
+    seq.append(start)
83
+    options.remove(start)
84
+    while options:
85
+        dl = distances[seq[-1]]
86
+        best = max(options, key=lambda o: dl[o])
87
+        seq.append(best)
88
+        options.remove(best)
89
+    return seq
90
+
65 91
 def distance_hierarchy(distances: DistTable) -> BinaryTree:
66 92
     n = len(distances)
67 93
     forest = [BinaryTree(i) for i in range(n)]
... ...
@@ -90,8 +116,24 @@ def scattered_hierarchy(hierarchy: BinaryTree) -> IndSeq:
90 116
         seq.append(fb.a)
91 117
     return seq
92 118
 
93
-dt: DistTable = distance_table([(0, 2), (3, 2), (4, 2), (5, 0), (0, 0)], math.dist)
94
-print(greedy_min_seq(dt, score_total))
119
+def with_len(distances: DistTable, seq: IndSeq):
120
+    return (sum(distances[i][j] for (i, j) in itertools.pairwise(seq)), seq)
121
+
122
+points: list[tuple[float, float]] = [(random.randint(0, 10), random.randint(0, 10)) for _ in range(10)]
123
+print(points)
124
+t: turtle.Turtle = turtle.Turtle()
125
+t.hideturtle()
126
+t.pen(speed=10)
127
+for (i, (x, y)) in enumerate(points):
128
+    t.teleport(50 * (x - 5), 50 * (y - 5))
129
+    t.dot()
130
+    t.write(i)
131
+dt: DistTable = distance_table(points, math.dist)
132
+print(show_mat(dt))
95 133
 h: BinaryTree = distance_hierarchy(dt)
96 134
 print(h)
97
-print(scattered_hierarchy(h))
135
+print("by graph", with_len(dt, scattered_hierarchy(h)))
136
+print("by nearest-nb sum", with_len(dt, greedy_min_seq(dt, score_nearest)))
137
+print("by total dist", with_len(dt, greedy_min_seq(dt, score_total)))
138
+print("by furthest-nb", with_len(dt, furthest_nb(dt)))
139
+input("done?")
98 140