Heilbronn's triangle problem
Better configurations for Heilbronn’s triangle problem in the unit square, n = 11–14
| 1 | """Simulated annealing for Heilbronn's problem: maximise the smallest triangle area.""" |
| 2 | import itertools |
| 3 | import math |
| 4 | import random |
| 5 | import sys |
| 6 | |
| 7 | |
| 8 | def min_area(p): |
| 9 | return min(abs((b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1])) / 2 for a, b, c in itertools.combinations(p, 3)) |
| 10 | |
| 11 | |
| 12 | def anneal(n, steps=20000, seed=0): |
| 13 | rng = random.Random(seed) |
| 14 | p = [(rng.random(), rng.random()) for _ in range(n)] |
| 15 | cur = best = min_area(p) |
| 16 | best_p = p[:] |
| 17 | for k in range(steps): |
| 18 | t = 0.01 * (1 - k / steps) + 1e-6 |
| 19 | i = rng.randrange(n) |
| 20 | old = p[i] |
| 21 | p[i] = tuple(min(1, max(0, c + rng.gauss(0, t))) for c in old) |
| 22 | new = min_area(p) |
| 23 | if new >= cur or rng.random() < math.exp((new - cur) / t): |
| 24 | cur = new |
| 25 | if new > best: |
| 26 | best, best_p = new, p[:] |
| 27 | else: |
| 28 | p[i] = old |
| 29 | return best, best_p |
| 30 | |
| 31 | |
| 32 | if __name__ == "__main__": |
| 33 | n = int(sys.argv[1]) |
| 34 | restarts = int(sys.argv[2]) if len(sys.argv) > 2 else 40 |
| 35 | steps = int(sys.argv[3]) if len(sys.argv) > 3 else 20000 |
| 36 | best = max((anneal(n, steps, seed=s) for s in range(restarts)), key=lambda r: r[0]) |
| 37 | print(f"# n={n} min area {best[0]:.6f}") |
| 38 | for x, y in best[1]: |
| 39 | print(f"{x:.6f} {y:.6f}") |