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
| Tutorial | Anda akan belajar | Paket yang disentuh |
|---|---|---|
| Memodelkan dan menyelesaikan masalah pendispatchan pertama | Memilih sebuah instans benchmark, menjalankan dua solver padanya, membandingkan jadwal, dan membaca metadata solver. | dispatchatlas.core, dispatchatlas.bench, dispatchatlas.solve |
| Menjalankan kampanye kecil dan membaca hasilnya | Mengonfigurasi 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-1Setiap 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.0Kedua 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, deterministicMetadata 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: 0Empat 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.jsonSatu 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.1summarize_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 coreBundel 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.pymenjalankan bentuk yang sama ini ke workspace eksperimen dan menserialkan konfigurasinya untuk antarmuka baris-perintahdispatchatlas-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.