Skip to content
optiprofilerPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

PyCUTEst

OptiProfiler 2.0: See compatibility and release boundaries.

This repository provides an interface for OptiProfiler to access the PyCUTEst problem collection.

It contains adaptation tools allowing OptiProfiler to invoke and work with these problems.

Contents

  • Adaptation Tools: Wrapper scripts and utilities in the root directory that bridge OptiProfiler with the PyCUTEst collection.

Package and Plugin

This adapter uses API-v1 and requires optiprofiler>=2.0.0. OptiProfiler 2.0.0 is not on PyPI until it is released, and this plugin is not published on PyPI either. The 0.1.0 package value is build metadata, not a release announcement.

The Python distribution name is optiprofiler-pycutest. It installs the adapter package optiprofiler_pycutest and registers the problem-library entry point

[project.entry-points."optiprofiler.problem_libraries"]
pycutest = "optiprofiler_pycutest:get_problem_library"

The adapter package name intentionally avoids pycutest, which is reserved for the upstream PyCUTEst runtime module. Installing or discovering this plugin does not import PyCUTEst or compile CUTEst problems. Runtime availability is checked only when OptiProfiler actually selects the pycutest problem library.

Install the adapter at the exact commit recorded in the core's problem_libraries.lock, using normal dependency resolution:

python -m pip install "optiprofiler-pycutest @ git+https://github.com/optiprofiler/pycutest@<sha>"
python -m pip check

Replace <sha> with the full commit pinned in the core's problem_libraries.lock: that is the commit tested with OptiProfiler 2.0.0. A tag is created at the release. Until OptiProfiler 2.0.0 is on PyPI, install that core first from its own wheel or checkout, because pip cannot otherwise satisfy optiprofiler>=2.0.0. Do not work around this with --no-deps: it skips the compatibility check that the requirement expresses. pip keeps an installed adapter of the same version, so uninstall an earlier source build before installing another commit.

This distribution intentionally installs only the OptiProfiler adapter. It does not install or configure PyCUTEst, CUTEst, or MASTSIF. Users who want to run PyCUTEst problems must prepare that runtime independently by following the upstream PyCUTEst installation instructions. OptiProfiler checks runtime availability only when the pycutest library is selected; installing and discovering the adapter remain lightweight.

To remove only this adapter and its OptiProfiler entry point, run:

python -m pip uninstall optiprofiler-pycutest

This does not remove or reconfigure PyCUTEst, CUTEst, MASTSIF, compiled CUTEst problems, or user caches. Those external runtime components remain under their own installation and cleanup procedures.

Discover, Update, and Remove

Discovery reads the installed entry-point metadata without importing the upstream PyCUTEst runtime:

from optiprofiler import list_problem_libraries

assert "pycutest" in list_problem_libraries()

Select the adapter with benchmark(..., plibs=["pycutest"]); an installed plugin needs no filesystem path.

For a source checkout, update it and reinstall the adapter explicitly:

git pull --ff-only
python -m pip install -e .

The OptiProfiler core repository records the tested adapter commit in problem_libraries.lock. Do not assume that an arbitrary newer adapter commit is compatible with an older core checkout.

Running python -m pip uninstall optiprofiler does not uninstall this adapter or its upstream runtime. The adapter remains installed but cannot be used until a compatible OptiProfiler core is installed again. Running python -m pip uninstall optiprofiler-pycutest removes only this adapter and its entry point; the independently managed runtime and caches are preserved as described above.

Configuration

Parallel cache access

On Linux/macOS the adapter serializes each complete upstream pycutest.import_problem call and both adapter cache-clear operations with a process lock in the effective cache root. This prevents workers from creating the same cache directory or importing a module that is still being built. An entry left incomplete by a killed build has no __init__.py, which upstream writes last; the next load clears and rebuilds it under the lock. The lock ends before problem conversion and solver/objective evaluation; benchmark evaluations remain parallel. Warm imports use the same lock, so the cache root must be writable.

The persistent .optiprofiler-import.lock file lives outside pycutest_cache_holder and is not removed when clearing that holder. Its presence does not mean a process holds the lock. Keep the cache environment and working directory stable while loading, and use a filesystem that supports POSIX advisory locks. The existing cache policy is unchanged: PYCUTEST_CACHE takes precedence, otherwise the user cache is used. The adapter puts that root first on sys.path and refuses a pycutest_cache_holder package already imported from another cache, so set PYCUTEST_CACHE before importing PyCUTEst. External callers bypassing this adapter do not participate in its lock. Do not clear a cache while previously loaded native problems are in use. Permission, path, and native build errors still propagate; the adapter does not retry, repair partial entries, or modify upstream PyCUTEst source.

Undefined _ZGV... symbols

Recent gfortran releases vectorize math calls at -O2 through glibc's libmvec, and upstream PyCUTEst does not link that library. On such a toolchain (observed with gfortran 15 and glibc 2.43), about 2% of the problems then fail to import with an undefined symbol such as _ZGVbN2vv_pow, and OptiProfiler reports them as load failures. Preloading the library fixes them without a rebuild:

LD_PRELOAD=libmvec.so.1 python your_benchmark.py

The adapter does not preload libraries or change upstream build flags for you.

Selection

The file config.txt in this directory controls how pycutest_select filters problems (e.g., variable_size and test_feasibility_problems). See the comments in config.txt for a full description of each option.

For a reproducible OptiProfiler experiment, pass the options explicitly for this run:

from optiprofiler import benchmark

benchmark(
    solvers,
    plibs=['pycutest'],
    plib_options={
        'pycutest': {
            'variable_size': 'all',
            'test_feasibility_problems': 2,
        },
    },
)

OptiProfiler stores the validated effective mapping with the experiment. For a process-level default shared by subsequent calls, the compatibility API remains available:

from optiprofiler import set_plib_config, get_plib_config

# View the current effective configuration
print(get_plib_config('pycutest'))

# Override subsequent calls in the current Python process
set_plib_config('pycutest', variable_size='all', test_feasibility_problems=2)

The precedence is per-run plib_options, process-level set_plib_config, environment variables, config.txt, then built-in defaults. You can also set PYCUTEST_VARIABLE_SIZE and PYCUTEST_TEST_FEASIBILITY_PROBLEMS directly. The adapter merges these layers first and validates the final mapping once, so an explicit valid per-run value can replace an invalid lower-priority value. Inspecting these options does not import PyCUTEst or require a working CUTEst installation. Runtime availability is checked only when this library is selected for a benchmark.

Stable variable-size instances

PyCUTEst and MASTSIF are external runtimes, and an upstream SIF file can change which parameter values are active by default. The adapter therefore records the reviewed default SIF parameters for every variable-size problem in sif_defaults_pycutest.json. Loading a bare variable-size name applies those parameters explicitly; loading an encoded name such as OSCIPATH_N_25_RHO_1 applies the parameters encoded in that identity.

After loading a reviewed instance, the adapter checks its dimension and its bound, linear-constraint, nonlinear-constraint, and total-constraint counts against probinfo_pycutest.csv. A mismatch fails with a runtime/metadata-drift error instead of benchmarking a different instance from the one selected. Explicit custom SIF parameter mappings remain supported, but configurations not present in the reviewed metadata do not claim a recorded shape.

Testing

Loading fails closed when native constraint bounds have invalid shapes or NaN entries, or when required linear constraint values/Jacobians cannot be read. The adapter does not replace failed linear constraints with empty matrices. Purely nonlinear problems do not need a Jacobian probe during loading. The regression suite includes injected failures through the actual loader, real CUTEst U/B/L/N controls, and linear offset/sign checks.

The CI workflow runs daily and on pushes on Linux. It installs CUTEst/PyCUTEst, checks the OptiProfiler adapter layer, and keeps the sample intentionally small:

  • load ROSENBR through pycutest_load and evaluate fun, cub, and ceq;
  • select small problems through pycutest_select;
  • check variable_size and test_feasibility_problems environment overrides;
  • audit all 341 variable-size SIF parameter definitions and all 2,588 recorded nondefault configurations against the committed metadata;
  • verify that OSCIPATH selected in the dimension range 8--10 loads the reviewed 10-dimensional instance by passing its SIF parameters explicitly;
  • check the installed entry-point factory without importing PyCUTEst;
  • sample a few additional small problems each day with at most two numerical-library threads.

Runtime-dependent tests need an installed PyCUTEst/CUTEst environment; mocked adapter conversion tests do not. From this repository:

python -m unittest discover -s tests -p 'test_*.py'

Maintenance

The manual Collect Problem Info workflow regenerates the metadata used by pycutest_select. It is heavier than the smoke CI because it installs the stable compatibility baseline from .github/actions/collect_info/runtime-versions.env and scans the problem list in blocks. Its artifact includes both probinfo_pycutest.csv and the reviewed sif_defaults_pycutest.json; it does not update the adapter automatically. Maintainers can verify the committed defaults against an installed copy of the pinned runtime with:

python scripts/collect_sif_defaults.py --check

Check Runtime Upstream compares that baseline with the latest PyCUTEst, CUTEst, SIFDecode, ARCHDefs, and MASTSIF tags. A newer tag creates or updates an upstream-update issue, but the adapter neither installs it for users nor changes the CI baseline without maintainer review.

The currently reviewed runtime matrix is:

Component Version Commit
PyCUTEst 1.8.2 65fb333f6886386cd38eb0ecdfaff9f536e931de
ARCHDefs v2.2.3 d1bf9f0225a97981aac1b6fddb85c07d8e9676a4
SIFDecode v2.1.3 c0e654b76d925cb59accc03c75f65e6ac6654e32
CUTEst v2.0.42 00999c3e215a4dffd57f5a888fc4c4ada2567940
MASTSIF v0.5 04280876fc4c7cae9a06ab34e0d5887bee4d8960

The same matrix is machine-readable in .github/actions/collect_info/runtime-versions.env and sif_defaults_pycutest.json. Upstream notifications are review inputs, not automatic deployment instructions.

Before promoting a newer runtime matrix, maintainers must also run the adapter regression suite against that candidate runtime. This catches upstream changes such as a different bare SIF default without changing the reviewed instance used by pycutest_select and pycutest_load.

Provenance and License

The OptiProfiler adapter code and generated metadata in this repository are licensed under the BSD 3-Clause License. The built distribution does not include PyCUTEst, CUTEst, or MASTSIF source code or compiled libraries.

PyCUTEst is an optional external runtime dependency licensed under GPL-3.0-or-later. CUTEst and MASTSIF are installed separately and retain their own upstream provenance, citation, and license requirements. See THIRD_PARTY_NOTICES.md for the component boundaries and upstream links.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages