File size: 3,283 Bytes
40607c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# EVOLVE-BLOCK-START
"""Initial search baseline for the AlphaEvolve AC inequality task."""

import time
import numpy as np


def evaluate_sequence(sequence: list[float]) -> float:
    """
    Evaluate coefficient sequence with safety checks.
    Lower is better.
    """
    if not isinstance(sequence, list):
        return float(np.inf)
    if not sequence:
        return float(np.inf)

    clean: list[float] = []
    for x in sequence:
        if isinstance(x, bool) or not isinstance(x, (int, float)):
            return float(np.inf)
        if np.isnan(x) or np.isinf(x):
            return float(np.inf)
        clean.append(float(x))

    clean = [max(0.0, min(1000.0, x)) for x in clean]
    n = len(clean)
    conv = np.convolve(clean, clean)
    max_b = float(np.max(conv))
    sum_a = float(np.sum(clean))
    if sum_a < 0.01:
        return float(np.inf)
    return float(2.0 * n * max_b / (sum_a**2))


def _normalize_scale(seq: np.ndarray) -> np.ndarray:
    """Scale sequence to stable magnitude while keeping nonnegative shape."""
    s = np.asarray(seq, dtype=np.float64)
    s = np.clip(s, 0.0, None)
    total = float(np.sum(s))
    if total <= 1e-12:
        return np.ones_like(s)
    # objective is scale-invariant theoretically, but this keeps numerics stable.
    return s / total * len(s)


def _seed_sequence(rng: np.random.Generator, n: int) -> np.ndarray:
    x = np.linspace(0.0, 1.0, n, endpoint=False)
    base = (
        0.9
        + 0.30 * np.sin(2.0 * np.pi * x)
        + 0.12 * np.sin(6.0 * np.pi * x + rng.uniform(0.0, 2.0 * np.pi))
    )
    noise = rng.normal(0.0, 0.08, n)
    return _normalize_scale(base + noise)


def run(seed: int = 42, budget_s: float = 10.0, **kwargs) -> list[float]:
    """
    Search for a low-value nonnegative sequence.

    Returns:
        list[float]: candidate coefficient sequence
    """
    del kwargs

    rng = np.random.default_rng(seed)
    start = time.time()
    deadline = start + max(0.1, budget_s * 0.98)

    # Multi-start initial pool.
    candidate_lengths = [128, 192, 256, 320, 384]
    best_seq = _seed_sequence(rng, n=256)
    best_val = evaluate_sequence(best_seq.tolist())

    for n in candidate_lengths:
        seq = _seed_sequence(rng, n=n)
        val = evaluate_sequence(seq.tolist())
        if val < best_val:
            best_seq, best_val = seq, val

    # Local stochastic search: block perturbation + smoothing.
    while time.time() < deadline:
        seq = best_seq.copy()
        n = len(seq)

        block = int(rng.integers(max(4, n // 64), max(8, n // 10)))
        idx = rng.choice(n, size=block, replace=False)
        seq[idx] += rng.normal(0.0, 0.10, size=block)

        if rng.random() < 0.35:
            # low-pass smooth
            seq = (
                0.25 * np.roll(seq, 1)
                + 0.50 * seq
                + 0.25 * np.roll(seq, -1)
            )

        if rng.random() < 0.15 and n < 800:
            # upsample once in a while to explore larger dimensions
            seq = np.repeat(seq, 2)[: min(800, 2 * n)]

        seq = _normalize_scale(seq)
        val = evaluate_sequence(seq.tolist())
        if val < best_val:
            best_seq, best_val = seq, val

    return [float(x) for x in best_seq.tolist()]


# EVOLVE-BLOCK-END