PY-100

Compare Runs with One Stated Change

  • Medium–Hard
  • Run Comparison
  • Python

Task

Write compare_runs(baseline, changed, allowed_field).

Each argument is a saved run record with the same shape:

The source identity must match exactly in both runs. The configuration keys must also match exactly. allowed_field names one existing top-level configuration key. Exactly one configuration value must differ, and it must be that allowed field. A missing key, no changed value, two changed values, or a changed field other than allowed_field is invalid. Do not treat a seed alone as proof that the runs did the same work.

Align artifacts by their non-empty, unique relative path, keeping the baseline order. The two records must use the same comparison and tolerance metadata for an aligned artifact. Compare "exact" artifacts with ordinary equality. Compare "close" artifacts recursively with:

abs(changed - baseline) <= atol + rtol * abs(baseline)

Lists and tuples must have the same length and dictionaries the same keys. A non-numeric value must match exactly even under a close comparison. Report one descriptive difference per artifact whose value does not agree. A missing or extra artifact is also a difference. Keep the evidence descriptive: report what the two runs contain, but do not claim that the allowed setting caused the difference or that it will generalize to other runs.

Return:

For invalid input, return "invalid", matches: False, an empty differences list, and one of these errors: "invalid run record", "source identity mismatch", "configuration keys differ", "configuration must change exactly one allowed field", "changed field is not allowed", or "artifact contracts differ". Validate all of these conditions before comparing result values. Do not modify either run, print, or ask for input.

Example

Suppose both runs use source calibrated-v1 and the only configuration change is noise_high from 0.2 to 0.1. If the ordered IDs remain equal but the mean changes from 7.5 to 7.2, return one difference for result/mean and describe it as an observed difference between the baseline and changed run. The result must not say that lowering noise_high caused the change; this small comparison does not establish causation.

Your implementation

Edit solution.py and keep this function signature:

You may import math. This task uses in-memory evidence and does not require NumPy, files, plotting, a random generator, or an external experiment tracker.