AGENTS.md has always said that a skill shipping scripts/ puts its tests in
tests/<name>/, but nothing checked it: 54 of the 100 such skills had no suite
at all, including docx, pptx, xlsx, pdf and scanpy. All 100 now do.
tests/_meta is the guard. It runs the shared structural contract across every
skill in a single process -- safe because it parses scripts with ast and never
imports them -- and fails when a skill ships scripts/ without a suite or
without a [skills.<name>] entry in skill-requirements.toml. It needs no
scientific packages and finishes in seconds, so skill-tests.yml blocks every
pull request on it, plus the packages=[] suites.
tests/_contract holds what the per-skill suites were each reimplementing:
frontmatter conformance, the 500-line limit, no tests or bytecode under
skills/, local links resolving, scripts parsing, no eval/exec/os.system, no
standard-library shadowing, no hardcoded local paths, valid shell scripts. Also
the --help contract, which skips when a skill's packages are absent and runs
for real under --isolated, and shared behaviour for the files docx/pptx/xlsx
and five schematic-shipping skills carry byte-identical copies of, with drift
detection so they cannot diverge silently.
67 new suites, 3325 test functions. The existing suites were retrofitted: 18
no longer pin an exact skill version, so a version bump no longer breaks a
test; 11 duplicated structural methods removed; 19 wired to the --help
contract; and 5 that failed collection without their packages now skip
cleanly. run_all.py in the bare project environment goes from 6 failures to 0.
Writing the tests surfaced 19 defects in the skills, fixed here with version
bumps. The ones that changed scientific output:
- openpiv reported vorticity 0 for a rotating flow, from a sign error in
openpiv's y-up coordinate relabelling; solid-body rotation now gives 2w
exactly, on grids of either orientation
- deepchem returned solubility predictions in z-scored space while labelling
them log(mol/L), because it transformed a y-less dataset instead of
untransforming the output
- neuropixels-analysis had the Allen and IBL ISI thresholds swapped,
contradicting its own references/QUALITY_METRICS.md and inverting the two
standards' relative strictness
- scanpy's summarize() raised TypeError on every AnnData under anndata 0.13,
which reports an unnamed None key on .layers; scanpy convert was broken
- experimental-design's Latin hypercube was never reproducible: pyDOE3 draws
from its own default_rng and ignores numpy's global seed
- primekg shipped a hardcoded path naming a person, which is why
no_personal_paths is now a contract rule
The remainder is upstream API drift, each verified against the installed
package: retired symbols in bioservices 1.16, gget helpers that returned lists
where a string was written, ArviZ 1.x kwargs in pymc, a positional-only
factory in pymoo, ReduceLROnPlateau(verbose=) in torch 2.13, a removed scvelo
parameter, and PyPDF2 in scientific-slides.
Two manifest environments could not build and are pinned: gget, where an
unpinned scanpy walked back to 1.9.8 and pulled llvmlite 0.36 which does not
compile on 3.13, and pymatgen, pinned to the snapshot its own _common.py
enforces rather than loosening that check. deepchem gains torch, without which
no model class exists.
python tests/run_all.py --isolated: 101 passed, 0 failed.
75 lines
2.2 KiB
Python
75 lines
2.2 KiB
Python
"""
|
|
Many-objective optimization example using pymoo.
|
|
|
|
This script demonstrates many-objective optimization (4+ objectives)
|
|
using NSGA-III on the DTLZ2 benchmark problem.
|
|
"""
|
|
|
|
from pymoo.algorithms.moo.nsga3 import NSGA3
|
|
from pymoo.problems import get_problem
|
|
from pymoo.optimize import minimize
|
|
from pymoo.util.ref_dirs import get_reference_directions
|
|
from pymoo.visualization.pcp import PCP
|
|
import numpy as np
|
|
|
|
|
|
def run_many_objective_optimization():
|
|
"""Run many-objective optimization example."""
|
|
|
|
# Define the problem - DTLZ2 with 5 objectives
|
|
n_obj = 5
|
|
problem = get_problem("dtlz2", n_obj=n_obj)
|
|
|
|
# Generate reference directions for NSGA-III
|
|
# Das-Dennis method for uniform distribution.
|
|
# The dimension is positional: the factory's first argument is n_dim, and
|
|
# passing it as n_obj= raises TypeError.
|
|
ref_dirs = get_reference_directions("das-dennis", n_obj, n_partitions=12)
|
|
|
|
print(f"Number of reference directions: {len(ref_dirs)}")
|
|
|
|
# Configure NSGA-III algorithm
|
|
algorithm = NSGA3(
|
|
ref_dirs=ref_dirs,
|
|
eliminate_duplicates=True
|
|
)
|
|
|
|
# Run optimization
|
|
result = minimize(
|
|
problem,
|
|
algorithm,
|
|
('n_gen', 300),
|
|
seed=1,
|
|
verbose=True
|
|
)
|
|
|
|
# Print results summary
|
|
print("\n" + "="*60)
|
|
print("MANY-OBJECTIVE OPTIMIZATION RESULTS")
|
|
print("="*60)
|
|
print(f"Number of objectives: {n_obj}")
|
|
print(f"Number of solutions: {len(result.F)}")
|
|
print(f"Number of generations: {result.algorithm.n_gen}")
|
|
print(f"Number of function evaluations: {result.algorithm.evaluator.n_eval}")
|
|
|
|
# Show objective space statistics
|
|
print("\nObjective space statistics:")
|
|
print(f"Minimum values per objective: {result.F.min(axis=0)}")
|
|
print(f"Maximum values per objective: {result.F.max(axis=0)}")
|
|
print("="*60)
|
|
|
|
# Visualize using Parallel Coordinate Plot
|
|
plot = PCP(
|
|
title=f"DTLZ2 ({n_obj} objectives) - NSGA-III Results",
|
|
labels=[f"f{i+1}" for i in range(n_obj)],
|
|
normalize_each_axis=True
|
|
)
|
|
plot.add(result.F, alpha=0.3, color="blue")
|
|
plot.show()
|
|
|
|
return result
|
|
|
|
|
|
if __name__ == "__main__":
|
|
result = run_many_objective_optimization()
|