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 |