Sample-spreading method, present better
dkl9

dkl9 commited on 2025-186 00:19:25
Showing 1 changed files, with 28 additions and 12 deletions.

... ...
@@ -1,6 +1,7 @@
1 1
 import itertools
2 2
 import math
3 3
 import random
4
+import time
4 5
 import turtle
5 6
 import typing
6 7
 import collections.abc
... ...
@@ -66,6 +67,9 @@ def score_total(distances: DistTable, sample: IndSeq) -> float:
66 67
         0 if i in sample else distances[i][j] for j in sample
67 68
     ) for i in range(len(distances)))
68 69
 
70
+def score_spread(distances: DistTable, sample: IndSeq) -> float:
71
+    return -sum(sum(distances[sample[i]][j] for j in sample[:i]) for i in range(len(sample)))
72
+
69 73
 def greedy_min_seq(distances: DistTable, score_func: Func[[DistTable, IndSeq], float]) -> IndSeq:
70 74
     seq = []
71 75
     options = set(range(len(distances)))
... ...
@@ -116,24 +120,36 @@ def scattered_hierarchy(hierarchy: BinaryTree) -> IndSeq:
116 120
         seq.append(fb.a)
117 121
     return seq
118 122
 
119
-def with_len(distances: DistTable, seq: IndSeq):
120
-    return (sum(distances[i][j] for (i, j) in itertools.pairwise(seq)), seq)
123
+def total_len(distances: DistTable, seq: IndSeq) -> float:
124
+    return sum(distances[i][j] for (i, j) in itertools.pairwise(seq))
121 125
 
122
-points: list[tuple[float, float]] = [(random.randint(0, 10), random.randint(0, 10)) for _ in range(10)]
126
+N = 100
127
+points: list[tuple[float, float]] = [(random.randint(0, N // 2), random.randint(0, N // 3)) for _ in range(N)]
123 128
 print(points)
124 129
 t: turtle.Turtle = turtle.Turtle()
125 130
 t.hideturtle()
126 131
 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 132
 dt: DistTable = distance_table(points, math.dist)
132 133
 print(show_mat(dt))
133 134
 h: BinaryTree = distance_hierarchy(dt)
134 135
 print(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?")
136
+METHODS = [
137
+    ("graph", lambda: scattered_hierarchy(h)),
138
+    ("nearest-nb sum", lambda: greedy_min_seq(dt, score_nearest)),
139
+    ("all dist sum", lambda: greedy_min_seq(dt, score_total)),
140
+    ("sample spread", lambda: greedy_min_seq(dt, score_spread)),
141
+    ("furthest-nb", lambda: furthest_nb(dt)),
142
+]
143
+input("ready?")
144
+for (name, method) in METHODS:
145
+    to = time.time()
146
+    seq = method()
147
+    tf = time.time()
148
+    l = total_len(dt, seq)
149
+    print(f"{name} method took {tf - to} s to find {seq}, length {l}")
150
+    t.clear()
151
+    for (i, (x, y)) in enumerate(points[k] for k in seq):
152
+        t.teleport(2000 / N * (x - 0.25 * N), 2000 / N * (y - 0.17 * N))
153
+        t.dot(20 / math.sqrt(i + 1))
154
+        t.write(i)
155
+    input("next?")
140 156