Lewati ke konten
DispatchAtlas
Cari

Tutorial

Tutorial-tutorial ini adalah pemanduan berorientasi-pembelajaran, ujung-ke-ujung: setiap langkah adalah sebuah skrip yang dapat-dijalankan, setiap keluaran yang ditampilkan adalah keluaran nyata dari data smoke yang dibundel, dan setiap jalannya deterministik — benih yang sama menghasilkan angka yang sama di mesin Anda. Selesaikan dulu instalasi dan mulai cepat, lalu jalankan setiap skrip dari checkout repositori dengan uv run python <file>.py.

🧭 Pilih Sebuah Tutorial

TutorialAnda akan belajarPaket yang disentuh
Memodelkan dan menyelesaikan masalah pendispatchan pertamaMemilih sebuah instans benchmark, menjalankan dua solver padanya, membandingkan jadwal, dan membaca metadata solver.dispatchatlas.core, dispatchatlas.bench, dispatchatlas.solve
Menjalankan kampanye kecil dan membaca hasilnyaMengonfigurasi kampanye ber-checkpoint, mengeksekusinya ke sebuah workspace, dan memuat hasil untuk analisis.dispatchatlas.lab, dispatchatlas.analytica

Jalur referensi lebih dalam berlanjut di tempat tutorial berakhir: kontrak domain untuk model penjadwalan, model benchmark untuk generasi katalog, sistem solver untuk registri lengkap, mesin kampanye untuk detail orkestrasi, dan ekspor analisis untuk bundel bukti. Kampanye lebih besar memerlukan gerbang statistik dan rilis yang dijelaskan di kesiapan.

🛠️ Tutorial 1: Memodelkan Dan Menyelesaikan Masalah Pendispatchan Pertama

Mulai cepat menyelesaikan satu masalah dengan satu solver. Tutorial ini turun satu tingkat lebih dalam: Anda memilih sebuah instans benchmark tertentu, menjalankan dua lini-dasar pendispatchan padanya, membandingkan jadwal yang mereka bangun, dan membaca metadata yang menjelaskan setiap solver.

1️⃣ Lihat apa yang ditawarkan katalog smoke

Katalog smoke yang dibundel mematerialisasi dua instans deterministik kecil per famili penjadwalan dari satu benih akar. Simpan ini sebagai list_problems.py dan jalankan dengan uv run python list_problems.py:

from dispatchatlas.bench import smoke_benchmark_provider
 
provider = smoke_benchmark_provider(root_seed=20260527)
for problem_id in provider.list_problem_ids():
    print(problem_id.value)

Keluaran:

smoke-cloud-edge-0
smoke-cloud-edge-1
smoke-workflow-0
smoke-workflow-1
smoke-machine-scheduling-unrelated-0
smoke-machine-scheduling-unrelated-1
smoke-job-shop-0
smoke-job-shop-1
smoke-flexible-job-shop-0
smoke-flexible-job-shop-1
smoke-permutation-flow-shop-0
smoke-permutation-flow-shop-1
smoke-setup-flow-shop-0
smoke-setup-flow-shop-1
smoke-rcpsp-renewable-0
smoke-rcpsp-renewable-1
smoke-open-shop-0
smoke-open-shop-1
smoke-hybrid-flow-shop-0
smoke-hybrid-flow-shop-1
smoke-distributed-permutation-flow-shop-0
smoke-distributed-permutation-flow-shop-1
smoke-no-wait-flow-shop-0
smoke-no-wait-flow-shop-1
smoke-blocking-flow-shop-0
smoke-blocking-flow-shop-1
smoke-distributed-assembly-flow-shop-0
smoke-distributed-assembly-flow-shop-1
smoke-multi-objective-pfsp-0
smoke-multi-objective-pfsp-1
smoke-rcpsp-max-0
smoke-rcpsp-max-1
smoke-rcpsp-multi-mode-0
smoke-rcpsp-multi-mode-1
smoke-multi-project-rcpsp-0
smoke-multi-project-rcpsp-1
smoke-unrelated-parallel-setup-0
smoke-unrelated-parallel-setup-1
smoke-reentrant-fab-0
smoke-reentrant-fab-1
smoke-distributed-flexible-job-shop-0
smoke-distributed-flexible-job-shop-1
smoke-facility-assignment-0
smoke-facility-assignment-1

Setiap id menamai famili penjadwalannya dan sebuah indeks instans berbasis-nol. Sisa tutorial menggunakan smoke-job-shop-0.

2️⃣ Menjalankan dua solver pada satu instans

provider.get_problem mengambil sebuah ProblemId dan mengembalikan sebuah ValidatedProblem — spesifikasi masalah ditambah cap dan laporan validasinya, sehingga sebuah solver tidak pernah menerima instans tak-tervalidasi. Dua solver di bawah adalah lini-dasar pendispatchan deterministik: earliest-start menjadwalkan tugas dalam urutan masukan topologis, sementara shortest-processing-time memprioritaskan tugas lebih pendek. Simpan ini sebagai compare_solvers.py:

from dispatchatlas.bench import smoke_benchmark_provider
from dispatchatlas.core import ProblemId, TerminationPolicy, derive_seed
from dispatchatlas.solve import default_solver_registry
 
provider = smoke_benchmark_provider(root_seed=20260527)
validated = provider.get_problem(ProblemId("smoke-job-shop-0"))
spec = validated.spec
 
print(f"problem: {spec.id.value}")
print(f"tasks: {len(spec.tasks)}  resources: {len(spec.resources)}")
 
registry = default_solver_registry()
for solver_id in ("earliest-start", "shortest-processing-time"):
    metadata = registry.get_metadata(solver_id)
    solver = registry.create(solver_id)
    run = solver.solve(
        problem=validated,
        stop=TerminationPolicy(max_iterations=metadata.default_stop.max_iterations),
        seed=derive_seed(20260610, "docs.tutorial.compare", 0),
    )
    makespan = run.result.objective_values[0]
    print(
        f"{solver_id}: feasible={run.result.feasible} "
        f"{makespan.objective_name}={makespan.value:.1f}"
    )

Jalankan dengan uv run python compare_solvers.py:

problem: smoke-job-shop-0
tasks: 9  resources: 3
earliest-start: feasible=True makespan=353.0
shortest-processing-time: feasible=True makespan=433.0

Kedua jadwal layak, dan pada instans ini aturan yang lebih sederhana justru menang: earliest-start selesai di 353.0 sedangkan shortest-processing-time, yang mendahulukan tugas-tugas pendek, baru selesai di 433.0. Ini layak direnungkan, karena shortest-processing-time adalah aturan yang baik secara umum — di job shop ia bisa menunda satu tugas panjang yang sedang ditunggu tugas berikutnya, dan seluruh jadwal ikut menunggu. Reputasi sebuah aturan tidak memberi tahu Anda apa yang dilakukannya pada instans Anda.

Dan justru itulah pokoknya: bentuknya, bukan angkanya. Satu instans tidak membuktikan apa pun ke arah mana pun — itulah gunanya kampanye dan metode statistik — tetapi perbandingan di sini (masalah tervalidasi yang sama, kriteria henti yang sama, benih turunan yang sama) adalah persis bagaimana bukti lebih besar dibangun, dan satu kali eksekusi justru bukan itu.

3️⃣ Membaca metadata solver

Setiap solver terdaftar membawa metadata sebagai kontrak publiknya: tujuan yang didukung, label kapabilitas, stokastisitas, kriteria henti default, dan sebuah sitasi kanonik. Simpan ini sebagai inspect_metadata.py:

from dispatchatlas.solve import default_solver_registry
 
registry = default_solver_registry()
metadata = registry.get_metadata("shortest-processing-time")
print(f"solver: {metadata.solver_id}")
print(f"stochasticity: {metadata.stochasticity}")
print(f"citation: {metadata.citation.reference}")
print("capabilities:", ", ".join(c.value for c in metadata.capabilities))

Jalankan dengan uv run python inspect_metadata.py:

solver: shortest-processing-time
stochasticity: deterministic
citation: Smith, W. E. (1956). Various optimizers for single-stage production. Naval Research Logistics Quarterly, 3(1-2), 59-66.
capabilities: single-objective, capacity-aware, precedence-aware, constructive, dispatching, deterministic

Metadata ini adalah yang registry.select saring dan dari mana perekomendasi solver menjelaskan. Registri lengkap — lini-dasar, metaheuristik, adaptor eksak, dan famili NDSO — dikatalogkan di algoritma dan sistem solver.

🧪 Tutorial 2: Menjalankan Kampanye Kecil Dan Membaca Hasilnya

Sebuah kampanye adalah himpunan jalannya yang terkonfigurasi — instans benchmark disilangkan dengan solver dan tujuan — dieksekusi dengan benih, anggaran, checkpoint eksplisit, dan sebuah repositori hasil di-disk. Tutorial ini menjalankan bentuk yang sama dengan resep yang dilacak di experiments/configs/smoke-pilot.json: dua instans smoke, dua lini-dasar deterministik, satu tujuan.

1️⃣ Mengonfigurasi dan menjalankan kampanye

Simpan ini sebagai first_campaign.py. Ia mendeklarasikan kampanye, memvalidasinya menjadi sebuah rencana deterministik, mengestimasi biayanya dengan sebuah jalannya-kering, lalu mengeksekusinya ke sebuah workspace lokal my-campaigns/:

from pathlib import Path
 
from dispatchatlas.core import TerminationPolicy
from dispatchatlas.lab import (
    CampaignConfig,
    CampaignKind,
    CampaignStage,
    ExecutionMode,
    OutputPolicy,
    ResourceBudget,
    default_campaign_runner,
)
 
workspace = Path("my-campaigns")
 
config = CampaignConfig(
    campaign_id="first-campaign",
    benchmark_ids=("smoke-job-shop-0", "smoke-workflow-0"),
    solver_ids=("earliest-start", "shortest-processing-time"),
    objectives=("makespan",),
    root_seed=20260610,
    seed_namespace="docs.tutorial.first-campaign",
    stop=TerminationPolicy(max_iterations=5),
    output=OutputPolicy(root_dir=str(workspace)),
    stage=CampaignStage.SMOKE,
    kind=CampaignKind.PILOT,
    resources=ResourceBudget(
        max_workers=2,
        max_concurrent_runs=2,
        estimated_seconds_per_run=0.5,
    ),
    execution_mode=ExecutionMode.SEQUENTIAL,
)
 
runner = default_campaign_runner(workspace)
plan = runner.validate(config)
budget = runner.dry_run(plan)
print(f"planned runs: {len(plan.runs)}")
print(f"estimated wall time: {budget.estimated_wall_time_seconds:.1f}s")
 
index = runner.run(plan)
print(f"completed runs: {index.run_count}")
print(f"failed attempts: {len(index.failures)}")

Jalankan dengan uv run python first_campaign.py:

planned runs: 4
estimated wall time: 2.0s
completed runs: 4
failed attempts: 0

Empat jalannya persis hasil-silang: 2 instans benchmark × 2 solver × 1 tujuan, dengan satu jalannya per sel karena kedua solver deterministik. Benih setiap jalannya turun dari root_seed dan posisi jalannya, sehingga menjalankan-ulang skrip mereproduksi rekaman yang sama; checkpoint membiarkan sebuah kampanye terinterupsi melanjutkan tanpa mengulang pekerjaan yang selesai.

2️⃣ Memeriksa apa yang mendarat di disk

Runner menulis sebuah workspace dengan tata letak yang sama dengan workspace eksperimen yang dilacak:

my-campaigns/
  .checkpoints/first-campaign.json
  ENVIRONMENT.md
  logs/first-campaign_<timestamp>.log
  results/first-campaign/
    plan.json
    environment.json
    earliest-start/smoke-job-shop-0/run_0.json
    earliest-start/smoke-workflow-0/run_0.json
    shortest-processing-time/smoke-job-shop-0/run_0.json
    shortest-processing-time/smoke-workflow-0/run_0.json

Satu rekaman JSON per jalannya, dialamatkan menurut kampanye, solver, benchmark, dan indeks replika — jalur itu sendiri adalah indeksnya. Setiap rekaman di-hash-konten atas muatan deterministiknya, yang itulah yang diverifikasi mode replay.

3️⃣ Memuat hasil untuk analisis

dispatchatlas.analytica membaca direktori kampanye yang selesai tanpa mengimpor runtime kampanye. Simpan ini sebagai read_results.py:

from pathlib import Path
 
from dispatchatlas.analytica import load_result_dataset, summarize_dataset
 
dataset = load_result_dataset(Path("my-campaigns"), "first-campaign")
print(f"campaign: {dataset.campaign_id}")
print(f"completed runs: {len(dataset.completed)}")
 
summary = summarize_dataset(dataset)
for solver in summary.solver_summaries:
    print(
        f"{solver.solver_id}: runs={solver.count} "
        f"feasible={solver.feasible_count} "
        f"mean {solver.objective_name}={solver.mean:.1f}"
    )

Jalankan dengan uv run python read_results.py:

campaign: first-campaign
completed runs: 4
earliest-start: runs=2 feasible=2 mean makespan=182.1
shortest-processing-time: runs=2 feasible=2 mean makespan=222.1

summarize_dataset menghitung statistik deskriptif per solver dan tujuan. Dengan hanya dua jalannya per solver metode inferensial (uji signifikansi, interval kepercayaan) merute ke permukaan keterbatasan alih-alih menghasilkan hasil ber-daya-rendah — lantai daya-statistik 30 jalannya independen per sel stokastik solver-instans dijelaskan di ekspor analisis.

4️⃣ Mengekspor bundel bukti (opsional)

Direktori kampanye yang sama memberi-makan perintah ekspor, yang menulis sebuah bundel bukti tersaring-pengungkapan dari tabel, gambar, dan suplemen:

uv run dispatchatlas export `
  --campaign-dir .\my-campaigns\results\first-campaign `
  --target-dir .\exports\first-campaign `
  --authorized-output-root .\exports `
  --tier core

Bundel mendarat di exports/first-campaign/evidence-bundles/first-campaign-core/. Halaman bundel bukti menjelaskan empat tingkat dan isi bundel.

🎓 Ke mana ini mengarah

  • Resep yang dilacak experiments/scripts/run_smoke_pilot.py menjalankan bentuk yang sama ini ke workspace eksperimen dan menserialkan konfigurasinya untuk antarmuka baris-perintah dispatchatlas-lab.
  • Halaman mesin kampanye mencakup mode eksekusi, kebijakan coba-ulang, pelanjutan, verifikasi replay, protokol henti ganda, dan jaminan perbandingan-adil.
  • Kampanye tahap-penuh tetap terblokir sampai persetujuan desain statistik direkam — lihat kesiapan rilis.