Maximin method, analyse results harder
dkl9

dkl9 commited on 2025-186 01:56:15
Showing 1 changed files, with 31 additions and 4 deletions.

... ...
@@ -59,17 +59,25 @@ def show_mat(distances: DistTable) -> str:
59 59
         rows.append(row)
60 60
     return "\n".join(rows)
61 61
 
62
+# promising
62 63
 def score_nearest(distances: DistTable, sample: IndSeq) -> float:
63
-    return sum(min(distances[i][j] for j in sample) for i in range(len(distances)))
64
+    return sum(0 if i in sample else min(distances[i][j] for j in sample) for i in range(len(distances)))
64 65
 
66
+# too centred and slow
65 67
 def score_total(distances: DistTable, sample: IndSeq) -> float:
66 68
     return sum(sum(
67 69
         0 if i in sample else distances[i][j] for j in sample
68 70
     ) for i in range(len(distances)))
69 71
 
72
+# promising, needs revision
70 73
 def score_spread(distances: DistTable, sample: IndSeq) -> float:
71 74
     return -sum(sum(distances[sample[i]][j] for j in sample[:i]) for i in range(len(sample)))
72 75
 
76
+def score_sqrt_spread(distances: DistTable, sample: IndSeq) -> float:
77
+    return -sum(sum(
78
+        math.sqrt(distances[sample[i]][j]) for j in sample[:i]
79
+    ) for i in range(len(sample)))
80
+
73 81
 def greedy_min_seq(distances: DistTable, score_func: Func[[DistTable, IndSeq], float]) -> IndSeq:
74 82
     seq = []
75 83
     options = set(range(len(distances)))
... ...
@@ -79,6 +87,23 @@ def greedy_min_seq(distances: DistTable, score_func: Func[[DistTable, IndSeq], f
79 87
         options.remove(best)
80 88
     return seq
81 89
 
90
+def score_maximin(distances: DistTable, sample: IndSeq) -> float:
91
+    return min(min(distances[sample[i]][j] for j in sample[:i]) for i in range(1, len(sample)))
92
+
93
+# promising
94
+def greedy_maximin(distances: DistTable) -> IndSeq:
95
+    seq = []
96
+    options = set(range(len(distances)))
97
+    start = min(options, key=lambda o: score_nearest(distances, [o]))
98
+    seq.append(start)
99
+    options.remove(start)
100
+    while options:
101
+        best = max(options, key=lambda o: score_maximin(distances, seq + [o]))
102
+        seq.append(best)
103
+        options.remove(best)
104
+    return seq
105
+
106
+# too edge-clustery
82 107
 def furthest_nb(distances: DistTable) -> IndSeq:
83 108
     seq = []
84 109
     options = set(range(len(distances)))
... ...
@@ -103,6 +128,7 @@ def distance_hierarchy(distances: DistTable) -> BinaryTree:
103 128
         p = forest[i].merge(forest[j])
104 129
     return p
105 130
 
131
+# promising
106 132
 def scattered_hierarchy(hierarchy: BinaryTree) -> IndSeq:
107 133
     seq = []
108 134
     while hierarchy.usage < hierarchy.weight:
... ...
@@ -131,14 +157,15 @@ t.hideturtle()
131 157
 t.pen(speed=10)
132 158
 dt: DistTable = distance_table(points, math.dist)
133 159
 print(show_mat(dt))
160
+to = time.time()
134 161
 h: BinaryTree = distance_hierarchy(dt)
162
+tf = time.time()
163
+print(f"took {tf - to} s to build hierarchy")
135 164
 print(h)
136 165
 METHODS = [
137 166
     ("graph", lambda: scattered_hierarchy(h)),
138 167
     ("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)),
168
+    ("maximin", lambda: greedy_maximin(dt)),
142 169
 ]
143 170
 input("ready?")
144 171
 for (name, method) in METHODS:
145 172