Skip to content
DispatchAtlas
Search

Publishing Your Work

How DispatchAtlas publishes evidence from its registries to the website — the flow from campaign results to public, disclosure-filtered portal surfaces.

DispatchAtlas auto-publishes from its registries straight to the website's dedicated, viewable sections: a registered solver surfaces in the Solver Recommender, an exported benchmark subset becomes a downloadable bundle, and an exported campaign result is rendered by the Results explorer. Every step uses the installed public API -- no repository-only tooling -- so your own solvers, benchmarks, and results reach the same surfaces the shipped ones do. The runnable examples/publish_to_portal.py walks the whole path end to end in under a second.

Publish a solver

A solver carries registry metadata (a profile). Register it into a SolverRegistry, and a publicly-catalogued profile enters the public catalog the portal renders:

from dispatchatlas.solve import SolverRegistry
 
catalog = SolverRegistry()
catalog.register_instance(your_solver)
published = {metadata.solver_id for metadata in catalog.public_catalog()}

The registry-derived solver bundle the website serves carries every catalogued solver, so a registered public solver reaches the Solver Recommender with no extra step.

Publish a benchmark subset

Project any catalog into a portable, self-describing bundle and a flat CSV table -- the exact artifacts the portal's download center serves a visitor:

from dispatchatlas.bench import (
    build_continuum_catalog,
    catalog_metadata_for_sets,
    catalog_subset_to_bundle,
    catalog_subset_to_csv,
)
 
records = catalog_metadata_for_sets(build_continuum_catalog(root_seed=23))
bundle_bytes = catalog_subset_to_bundle(records)  # a downloadable archive
csv_text = catalog_subset_to_csv(records)  # a flat table of the same rows

Both are the downloadable artifacts the Downloads center offers, and the full continuum catalog is already browsable in the Benchmark Catalog.

build_continuum_catalog materializes a fast three-resource preview -- ideal for portal filtering and a quick look. For research-scale reference benchmarks, swap in build_continuum_full_catalog, which builds each family at its declared scale -- a larger resource pool and task count, where the co-allocation, contention, and placement structure genuinely manifests -- and flows through the very same catalog_metadata_for_sets and catalog_subset_to_bundle export surface:

from dispatchatlas.bench import build_continuum_full_catalog
 
research_records = catalog_metadata_for_sets(
    build_continuum_full_catalog(root_seed=23, problem_count_per_family=4)
)
research_bundle = catalog_subset_to_bundle(research_records)  # research-scale

Publish from an installable package

The sections above register a solver or a generator from inside your own script. For a reusable extension -- one another project installs and picks up without any glue code -- DispatchAtlas reads packaging entry points, so an installed distribution contributes solvers and benchmark generators without touching the in-tree registries. Advertise a zero-argument provider under the matching entry-point group in your package's pyproject.toml:

[project.entry-points."dispatchatlas.solvers"]
my-solvers = "my_package.providers:scheduling_solvers"
 
[project.entry-points."dispatchatlas.benchmark_generators"]
my-generators = "my_package.providers:scheduling_generators"

Each target is a callable that takes no arguments and returns an iterable -- of ProfiledSolver for the solver group, of BenchmarkGenerator for the generator group -- the same shape the shipped providers return. Discovery is never automatic, so the bundled catalogs stay deterministic; a caller opts in explicitly:

from dispatchatlas.bench import GeneratorRegistry, discover_plugin_generators
from dispatchatlas.solve import default_solver_registry, discover_plugin_solvers
 
solvers = default_solver_registry()
discover_plugin_solvers(solvers)  # ids of the third-party solvers registered
 
generators = GeneratorRegistry()
discover_plugin_generators(generators)  # ids of the third-party generators registered

A discovered solver flows through the same register_instance path as the one above, so a publicly-catalogued plugin solver reaches the Solver Recommender with no extra step. Discovery is fail-closed on evidence: a plugin solver that declares no citation reference, or a generator that claims citation-backed status while citing no source, is rejected before it enters a registry -- a third-party extension carries the same citation-backed invariant the shipped catalog does.

Publish results

Run a campaign, then export it through a disclosure policy to the portal-results bundle the site's results explorer renders:

from dispatchatlas.analytica import (
    AnalysisConfig,
    EvidenceTier,
    default_disclosure_policy,
    load_result_dataset,
    write_portal_dataset,
)
 
dataset = load_result_dataset(workspace, "your-campaign-id")
write_portal_dataset(
    dataset,
    default_disclosure_policy(EvidenceTier.CORE),
    target_dir,
    AnalysisConfig(objective_name="makespan"),
)

write_portal_dataset writes a content-hashed portal-results.json filtered to the declared disclosure tier -- the exact bundle the Results explorer renders, so the export is your results published to the portal. The disclosure filter is fail-closed: a result the tier does not permit is never published, so a study cannot over-share by accident.

See it end to end

uv run python examples/publish_to_portal.py

The example registers a solver, confirms it rides the portal solver bundle, exports a benchmark subset to a bundle and a CSV, and runs a campaign whose results export in the portal results-explorer format -- the whole publish path, read straight from the installed public API and the committed portal bundles the site ships.