| author | Alan Dipert
<alan@dipert.org> 2025-12-04 04:25:50 UTC |
| committer | Alan Dipert
<alan@dipert.org> 2025-12-04 04:25:50 UTC |
| parent | cec2db1bf141e2110fbe6e9aa3a395e9534ab227 |
| README.md | +1 | -1 |
| main.py | +19 | -8 |
diff --git a/README.md b/README.md index 6af45ca..a8bae54 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Do **not** use the score as a sole hiring gate; treat it as one data point along - No prefix/suffix ordering violations. - Tense/number/gender surfaces remain distinct (no collapses). - JSON output validated against the canonical feature-structure schema (`meta_schema.py`). -- **Regeneration:** `main.py` will retry up to 10 seeds until all properties pass; otherwise it fails loudly. +- **Regeneration:** `main.py` will retry seeds until all properties pass; otherwise it fails loudly. Hardness knobs (`--min-irregular`, `--min-irregular-contrast`, `--min-ditransitive`, `--min-plural`, `--min-adjective`, `--min-fem-plural`, `--min-feature-load`) can be scaled in one go with `--hardness-multiplier` (e.g., `2.0` to roughly double thresholds). All chosen params are recorded in `generation_params` in the JSON and printed in the booklet for reproducibility. ## Proctoring Guidance - Keep the cheat sheet and dictionary visible with the booklet; candidates should not need prior linguistics knowledge. diff --git a/main.py b/main.py index 2632ca5..c145d48 100644 --- a/main.py +++ b/main.py @@ -24,6 +24,12 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--min-adjective", type=int, default=12, help="Minimum adjective-bearing items.") parser.add_argument("--min-fem-plural", type=int, default=6, help="Minimum feminine-plural items.") parser.add_argument("--min-feature-load", type=int, default=1, help="Minimum feature load per item (hardness).") + parser.add_argument( + "--hardness-multiplier", + type=float, + default=1.0, + help="Scale all coverage/complexity thresholds (e.g., 2.0 ~ twice as hard).", + ) return parser.parse_args() @@ -33,16 +39,21 @@ def main() -> None: concepts = get_default_concepts() blueprint = get_default_blueprint() max_attempts = 50 + total_items = sum(s.num_items for s in blueprint.sections) + + def scale(base: int) -> int: + return min(total_items, int(round(base * args.hardness_multiplier))) params = { - "min_irregular": args.min_irregular, - "min_irregular_contrast": args.min_irregular_contrast, - "min_irregular_distractor": max(3, args.min_irregular_contrast), - "min_ditransitive": args.min_ditransitive, - "min_plural": args.min_plural, - "min_adjective": args.min_adjective, - "min_fem_plural": args.min_fem_plural, - "min_feature_load": args.min_feature_load, + "min_irregular": max(1, scale(args.min_irregular)), + "min_irregular_contrast": max(1, scale(args.min_irregular_contrast)), + "min_irregular_distractor": max(3, scale(args.min_irregular_contrast)), + "min_ditransitive": max(1, scale(args.min_ditransitive)), + "min_plural": max(1, scale(args.min_plural)), + "min_adjective": max(1, scale(args.min_adjective)), + "min_fem_plural": max(1, scale(args.min_fem_plural)), + "min_feature_load": max(args.min_feature_load, int(round(args.min_feature_load * args.hardness_multiplier))), + "hardness_multiplier": args.hardness_multiplier, } for attempt in range(max_attempts):