fix: address review findings for diverse seed population (#638)
- evolve.sh: fix fail-in-subshell bug — run seed-gen-cli as a direct command so its exit code is checked by the parent shell and fail() aborts the script correctly; redirect stderr to log file instead of discarding it with 2>/dev/null - seed-generator.ts: reorder enumerateVariants() to put STAKED_THRESHOLDS outermost (192 entries/block) so that selectVariants(6) with stride=192 covers all 6 staked% thresholds; remove false doc claim about "first variant is current seed config"; add comments explaining CI=0n is intentional in all presets - seed-gen-cli.ts: emit a stderr diagnostic when count exceeds the 1152-variant cap so the cap is visible rather than silently producing fewer files than requested - test: strengthen n=6 test to assert all STAKED_THRESHOLDS values are represented in the selected variants Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
850131b74f
commit
89a2734bff
4 changed files with 51 additions and 15 deletions
|
|
@ -279,15 +279,22 @@ if [ "$DIVERSE_SEEDS" = "true" ]; then
|
|||
# --- Diverse-seeds mode: use seed-gen-cli to produce parametric variants ---
|
||||
# Generate up to POPULATION variants; any shortfall is filled by mutating the seed.
|
||||
SEED_VARIANTS_DIR="$WORK_DIR/seed_variants"
|
||||
SEED_VARIANTS_LIST="$WORK_DIR/seed_variants_list.txt"
|
||||
VARIANT_IDX=0
|
||||
|
||||
# Run seed-gen-cli as a direct command (not inside <(...)) so its exit code is
|
||||
# checked by the parent shell and fail() aborts the entire script on error.
|
||||
# Stderr goes to the log file for diagnostics rather than being discarded.
|
||||
run_seed_gen_cli --count "$POPULATION" --output-dir "$SEED_VARIANTS_DIR" \
|
||||
> "$SEED_VARIANTS_LIST" 2>>"$LOG" \
|
||||
|| fail "seed-gen-cli.ts failed to generate variants"
|
||||
|
||||
while IFS= read -r VARIANT_FILE && [ "$VARIANT_IDX" -lt "$POPULATION" ]; do
|
||||
CAND_FILE="$GEN_DIR/candidate_$(printf '%03d' $VARIANT_IDX).push3"
|
||||
cp "$VARIANT_FILE" "$CAND_FILE"
|
||||
printf '0\n' > "${CAND_FILE%.push3}.ops"
|
||||
VARIANT_IDX=$((VARIANT_IDX + 1))
|
||||
done < <(run_seed_gen_cli --count "$POPULATION" --output-dir "$SEED_VARIANTS_DIR" 2>/dev/null \
|
||||
|| fail "seed-gen-cli.ts failed to generate variants")
|
||||
done < "$SEED_VARIANTS_LIST"
|
||||
|
||||
# Fill any remaining slots with mutations of the seed (fallback)
|
||||
while [ "$VARIANT_IDX" -lt "$POPULATION" ]; do
|
||||
|
|
|
|||
|
|
@ -54,6 +54,14 @@ if (!outputDir) {
|
|||
mkdirSync(outputDir, { recursive: true });
|
||||
|
||||
const variants = selectVariants(count);
|
||||
if (variants.length < count) {
|
||||
process.stderr.write(
|
||||
`[seed-gen] Note: --count ${count} exceeds the 1152-variant parameter space;` +
|
||||
` generating ${variants.length} variants. The remaining ${count - variants.length}` +
|
||||
` slots in evolve.sh will be filled by mutating the seed.\n`,
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < variants.length; i++) {
|
||||
const text = generateSeedVariant(variants[i]!);
|
||||
const filename = `variant_${String(i).padStart(3, '0')}.push3`;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,13 @@ export const STAKED_THRESHOLDS: readonly number[] = [80, 85, 88, 91, 94, 97];
|
|||
/** Penalty thresholds: penalty < N → bull; else → bear. */
|
||||
export const PENALTY_THRESHOLDS: readonly number[] = [30, 50, 70, 100];
|
||||
|
||||
/** Bull output parameter variants (higher confidence / tighter ranges). */
|
||||
/**
|
||||
* Bull output parameter variants (higher confidence / tighter ranges).
|
||||
*
|
||||
* capitalInefficiency is intentionally fixed at 0 across all variants — the
|
||||
* current seed (optimizer_v3.push3) uses CI=0 in all branches, and varying it
|
||||
* is left to the mutation operators once evolution starts.
|
||||
*/
|
||||
export const BULL_VARIANTS: readonly BullBearParams[] = [
|
||||
// Aggressive bull (current seed): maximum confidence, tight anchor
|
||||
{ capitalInefficiency: 0n, anchorShare: ONE_E18, anchorWidth: 20, discoveryDepth: ONE_E18 },
|
||||
|
|
@ -53,7 +59,11 @@ export const BULL_VARIANTS: readonly BullBearParams[] = [
|
|||
{ capitalInefficiency: 0n, anchorShare: 700_000_000_000_000_000n, anchorWidth: 50, discoveryDepth: 700_000_000_000_000_000n },
|
||||
];
|
||||
|
||||
/** Bear output parameter variants (defensive / wide ranges). */
|
||||
/**
|
||||
* Bear output parameter variants (defensive / wide ranges).
|
||||
*
|
||||
* capitalInefficiency is intentionally fixed at 0 for the same reason as BULL_VARIANTS.
|
||||
*/
|
||||
export const BEAR_VARIANTS: readonly BullBearParams[] = [
|
||||
// Standard bear (current seed)
|
||||
{ capitalInefficiency: 0n, anchorShare: 300_000_000_000_000_000n, anchorWidth: 100, discoveryDepth: 300_000_000_000_000_000n },
|
||||
|
|
@ -249,17 +259,21 @@ export function generateSeedVariant(params: SeedVariantParams): string {
|
|||
/**
|
||||
* Enumerate all parameter combinations in a deterministic order.
|
||||
*
|
||||
* STAKED_THRESHOLDS is the outermost loop so that even-stride sampling in
|
||||
* selectVariants(n) naturally covers all staked% values: each block of
|
||||
* (4 penalty × 4 bull × 4 bear × 3 tax) = 192 entries maps to one threshold.
|
||||
*
|
||||
* Total = |STAKED_THRESHOLDS| × |PENALTY_THRESHOLDS| × |BULL_VARIANTS|
|
||||
* × |BEAR_VARIANTS| × |TAX_DISTRIBUTIONS|
|
||||
* = 6 × 4 × 4 × 4 × 3 = 1152
|
||||
*/
|
||||
export function enumerateVariants(): SeedVariantParams[] {
|
||||
const result: SeedVariantParams[] = [];
|
||||
for (const taxDistribution of TAX_DISTRIBUTIONS) {
|
||||
for (const stakedThreshold of STAKED_THRESHOLDS) {
|
||||
for (const penaltyThreshold of PENALTY_THRESHOLDS) {
|
||||
for (const bull of BULL_VARIANTS) {
|
||||
for (const bear of BEAR_VARIANTS) {
|
||||
for (const stakedThreshold of STAKED_THRESHOLDS) {
|
||||
for (const penaltyThreshold of PENALTY_THRESHOLDS) {
|
||||
for (const bull of BULL_VARIANTS) {
|
||||
for (const bear of BEAR_VARIANTS) {
|
||||
for (const taxDistribution of TAX_DISTRIBUTIONS) {
|
||||
result.push({
|
||||
stakedThreshold,
|
||||
penaltyThreshold,
|
||||
|
|
@ -278,11 +292,12 @@ export function enumerateVariants(): SeedVariantParams[] {
|
|||
/**
|
||||
* Select `n` diverse variants from the full parameter space.
|
||||
*
|
||||
* When n ≤ total combinations (1152), samples evenly so each axis of variation
|
||||
* is represented. When n > total, returns all combinations.
|
||||
* When n ≤ total combinations (1152), samples evenly across the enumeration so
|
||||
* each axis of variation is represented. Because STAKED_THRESHOLDS is the
|
||||
* outermost loop, selectVariants(6) picks one representative per staked%
|
||||
* threshold (stride = 1152/6 = 192, one block per threshold value).
|
||||
*
|
||||
* The first variant is always the current seed configuration
|
||||
* (stakedThreshold=91, penaltyThreshold=50, bull/bear=defaults, exponential).
|
||||
* When n > total, returns all 1152 combinations.
|
||||
*/
|
||||
export function selectVariants(n: number): SeedVariantParams[] {
|
||||
if (n < 1) throw new RangeError('n must be at least 1');
|
||||
|
|
|
|||
|
|
@ -243,10 +243,16 @@ describe('selectVariants', () => {
|
|||
});
|
||||
|
||||
it('n=6 covers all staked thresholds via even stride', () => {
|
||||
// 1152 / 6 = stride of 192; the 6 selected entries span the full combination space
|
||||
// enumerateVariants puts STAKED_THRESHOLDS outermost (192 entries per threshold).
|
||||
// stride = 1152/6 = 192 → one representative per staked% value.
|
||||
const variants = selectVariants(6);
|
||||
expect(variants).toHaveLength(6);
|
||||
// Each variant is valid
|
||||
const stakedValues = new Set(variants.map(v => v.stakedThreshold));
|
||||
expect(stakedValues.size).toBe(STAKED_THRESHOLDS.length);
|
||||
for (const st of STAKED_THRESHOLDS) {
|
||||
expect(stakedValues.has(st)).toBe(true);
|
||||
}
|
||||
// Each representative is a valid Push3 program
|
||||
for (const v of variants) {
|
||||
expect(parseAndValidate(generateSeedVariant(v))).toBe(true);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue