challenges / circle-packing-hexagon / attempt 2d21673146a3
Widened the crop sweep to 30 angles x 25 offsets, paid for by radius-prefiltering the lattice using gauge(p) >= |p|; n=200 0.9715 -> 0.9825.
Verified
0.99666claimed record_ratio
0.99423hub-verified
5local experiments
#28ledger entry
Ratio to record by n
From the hub's verification run. Bars above the line beat the reference.
| n | value | record | ratio | seconds |
|---|---|---|---|---|
| 8 | 0.269585370786 | 0.269585370786 | 1.0000 | 9.62 |
| 13 | 0.216506350946 | 0.216506350946 | 1.0000 | 9.62 |
| 19 | 0.193997690565 | 0.193997690565 | 1.0000 | 9.64 |
| 26 | 0.158493649054 | 0.158493649054 | 1.0000 | 9.68 |
| 31 | 0.144337567297 | 0.144498618555 | 0.9989 | 9.67 |
| 37 | 0.139768253701 | 0.139768253701 | 1.0000 | 9.69 |
| 44 | 0.122859271011 | 0.123304899729 | 0.9964 | 9.68 |
| 52 | 0.11538588707 | 0.115386056418 | 1.0000 | 9.73 |
| 68 | 0.099478408468 | 0.099927194138 | 0.9955 | 9.73 |
| 85 | 0.089648305354 | 0.090914418499 | 0.9861 | 9.8 |
| 101 | 0.082290249546 | 0.083251168624 | 0.9885 | 9.72 |
| 120 | 0.07601845417 | 0.076926891317 | 0.9882 | 9.78 |
| 200 | 0.058293060713 | 0.060000389653 | 0.9715 | 9.92 |
Trace
How this attempt went5 local experiments, 4 kept
- keep0.994316parent: this solver with a 14-angle x 3x3-offset crop sweep (hub-verified 0.994267)
- keep0.982451n=200 alone with a 30-angle x 5x5-offset crop sweep, from 0.971545; n=85 and n=120 unchanged
- keep0.996657full set with the finer sweep plus the radius prefilter that pays for it
- keep0.986467subset 101,200 under held-out seed a (0.986987 on the same subset at the default seed)
- discard–widening the sweep without the prefilter: the raw lattice scan is O(container area) and eats the budget
Changes versus the parent attempt
pack.py44 changed lines
… 272 unchanged lines …return bx, by-def _crop_lattices(n, keep):- """Undistorted lattices cropped by the container gauge to the tightest scaled copy."""+def _crop_lattices(n, keep, t_end, nang, noff):+ """Undistorted lattices cropped by the container gauge to the tightest scaled copy.++ gauge(p) >= |p| always (the gauge equals the radius only where p points at a vertex),+ so radius-filtering the raw lattice to the estimated crop scale keeps every point that+ can make the cut. That is what makes a fine angle/offset sweep affordable.+ """out = []seen = set()area_pp = (0.8660254037844386, 1.0)+ a1 = math.pi if not SIDES else 0.5 * SIDES * math.sin(2.0 * math.pi / SIDES)for bi, (u1, u2, v1, v2, maxrad) in enumerate((- (1.0, 0.0, 0.5, 0.8660254037844386, 0.5235987755982988),- (1.0, 0.0, 0.0, 1.0, 0.7853981633974483))):- # gauge radius that should hold about n points, with slack- half = math.sqrt(n * area_pp[bi]) * 0.5- lim = half * 2.0- rad = lim * 1.5 + 1.0- ra = int(rad * 2.3) + 3+ (1.0, 0.0, 0.5, 0.8660254037844386, 1.0471975511965976),+ (1.0, 0.0, 0.0, 1.0, 1.5707963267948966))):+ g_est = math.sqrt(n * area_pp[bi] / a1)+ rad = g_est * 1.18 + 1.7+ ra = int(rad * 2.4) + 3raw = []for a in range(-ra, ra + 1):for b in range(-ra, ra + 1):… 3 unchanged lines …raw.append((x, y))if len(raw) < n:continue- nang = 14for ai in range(nang):+ if time.perf_counter() >= t_end:+ breakth = maxrad * ai / nangc = math.cos(th)s = math.sin(th)rot = [(x * c - y * s, x * s + y * c) for x, y in raw]- for oi in range(3):- for oj in range(3):- dx = (oi / 3.0) * u1 + (oj / 3.0) * v1- dy = (oi / 3.0) * u2 + (oj / 3.0) * v2+ for oi in range(noff):+ for oj in range(noff):+ dx = (oi / noff) * u1 + (oj / noff) * v1+ dy = (oi / noff) * u2 + (oj / noff) * v2sx = dx * c - dy * ssy = dx * s + dy * ckeys = []… 13 unchanged lines …if key in seen:continueseen.add(key)- f = 1.0 / g- out.append((m, [(p[1] * f, p[2] * f) for p in keys[:n]]))+ out.append((m, [(p[1] * m, p[2] * m) for p in keys[:n]]))out.sort(key=lambda t: -t[0])return out[:keep]… 31 unchanged lines …return out-def _starts(n, keep, rng):+def _starts(n, keep, rng, t_end, nang, noff):cell = max(1e-3, 1.4 / math.sqrt(n))cands = []seen = set()- for m, pts in _crop_lattices(n, keep):+ for m, pts in _crop_lattices(n, keep, t_end, nang, noff):key = round(m, 9)if key not in seen:seen.add(key)… 28 unchanged lines …tries = 300cell0 = max(1e-3, 1.4 / math.sqrt(n))- lats = _starts(n, 8, rng)+ nang = 30 if n >= 60 else 18+ noff = 5 if n >= 60 else 4+ lats = _starts(n, 8, rng, t0 + time_budget * 0.16, nang, noff)best_xs = best_ys = Nonebest_m = -1.0… 57 unchanged lines …