सामग्री पर जाएँ
DispatchAtlas
खोजें

ट्यूटोरियल

ये ट्यूटोरियल सीखने-उन्मुख, छोर-से-छोर के चलन हैं: प्रत्येक चरण एक चलाने-योग्य स्क्रिप्ट है, दिखाया गया प्रत्येक आउटपुट बंडल किए गए स्मोक डेटा से वास्तविक आउटपुट है, और प्रत्येक रन नियतात्मक है — समान बीज आपकी मशीन पर समान संख्याएँ उत्पन्न करते हैं। पहले इंस्टॉल और त्वरित प्रारंभ पूरा करें, फिर प्रत्येक स्क्रिप्ट को रिपॉज़िटरी चेकआउट से uv run python <file>.py के साथ चलाएँ।

🧭 एक ट्यूटोरियल चुनें

ट्यूटोरियलआप सीखेंगेछुए गए पैकेज
पहले प्रेषण समस्या को मॉडल और हल करेंएक बेंचमार्क इंस्टेंस चुनना, उस पर दो सॉल्वर चलाना, शेड्यूल तुलना करना, और सॉल्वर मेटाडेटा पढ़ना।dispatchatlas.core, dispatchatlas.bench, dispatchatlas.solve
एक छोटा अभियान चलाएँ और उसके परिणाम पढ़ेंएक चेकपॉइंट-युक्त अभियान विन्यस्त करना, उसे एक वर्कस्पेस में निष्पादित करना, और विश्लेषण के लिए परिणाम लोड करना।dispatchatlas.lab, dispatchatlas.analytica

गहरे संदर्भ पथ वहाँ जारी रहते हैं जहाँ ट्यूटोरियल समाप्त होते हैं: डोमेन अनुबंध शेड्यूलिंग मॉडल के लिए, बेंचमार्क मॉडल कैटलॉग जनन के लिए, सॉल्वर प्रणाली पूर्ण रजिस्ट्री के लिए, अभियान इंजन ऑर्केस्ट्रेशन विवरण के लिए, और विश्लेषण निर्यात साक्ष्य बंडलों के लिए। बड़े अभियानों को तत्परता में वर्णित सांख्यिकीय और रिलीज़ द्वारों की आवश्यकता है।

🛠️ Tutorial 1: पहले प्रेषण समस्या को मॉडल और हल करें

त्वरित प्रारंभ ने एक सॉल्वर से एक समस्या हल की। यह ट्यूटोरियल एक स्तर गहरा जाता है: आप एक विशिष्ट बेंचमार्क इंस्टेंस चुनते हैं, उस पर दो प्रेषण आधार-रेखाएँ चलाते हैं, वे जो शेड्यूल बनाती हैं उनकी तुलना करते हैं, और प्रत्येक सॉल्वर को समझाने वाले मेटाडेटा पढ़ते हैं।

1️⃣ देखें कि स्मोक कैटलॉग क्या प्रदान करता है

बंडल किया गया स्मोक कैटलॉग एक एकल मूल बीज से प्रति शेड्यूलिंग परिवार दो छोटे नियतात्मक इंस्टेंस भौतिकीकृत करता है। इसे list_problems.py के रूप में सहेजें और 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)

आउटपुट:

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

प्रत्येक id अपने शेड्यूलिंग परिवार और एक शून्य-आधारित इंस्टेंस सूचकांक को नामित करता है। ट्यूटोरियल का शेष smoke-job-shop-0 उपयोग करता है।

2️⃣ एक इंस्टेंस पर दो सॉल्वर चलाएँ

provider.get_problem एक ProblemId लेता है और एक ValidatedProblem लौटाता है — समस्या विनिर्देश साथ ही उसका सत्यापन मुहर और रिपोर्ट, ताकि एक सॉल्वर कभी एक अ-सत्यापित इंस्टेंस न प्राप्त करे। नीचे दो सॉल्वर नियतात्मक प्रेषण आधार-रेखाएँ हैं: earliest-start कार्यों को सांस्थितिक इनपुट क्रम में शेड्यूल करता है, जबकि shortest-processing-time छोटे कार्यों को प्राथमिकता देता है। इसे 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}"
    )

इसे 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

दोनों शेड्यूल साध्य हैं, और इस इंस्टेंस पर सरल नियम ही जीतता है: earliest-start 353.0 पर समाप्त होता है, जबकि छोटे कार्यों को प्राथमिकता देने वाला shortest-processing-time 433.0 पर। यहाँ ठहरकर सोचना उचित है, क्योंकि shortest-processing-time सामान्यतः एक अच्छा नियम है — जॉब शॉप में यह किसी लंबे कार्य को टाल सकता है जिसकी प्रतीक्षा कोई आगे का कार्य कर रहा हो, और तब पूरा शेड्यूल उसके साथ प्रतीक्षा करता है। किसी नियम की प्रतिष्ठा आपको यह नहीं बताती कि वह आपके इंस्टेंस पर क्या करेगा।

और यही कारण है कि बात संख्या की नहीं, आकार की है। एक इंस्टेंस किसी भी दिशा में कुछ सिद्ध नहीं करता — वही अभियानों और सांख्यिकीय विधियों का उद्देश्य है — पर यहाँ की तुलना (समान सत्यापित समस्या, समान विराम मानदंड, समान व्युत्पन्न बीज) ठीक वही है जैसे बड़ा साक्ष्य निर्मित होता है, और एक अकेला रन ठीक वह नहीं है।

3️⃣ सॉल्वर मेटाडेटा पढ़ें

प्रत्येक पंजीकृत सॉल्वर अपने सार्वजनिक अनुबंध के रूप में मेटाडेटा धारण करता है: समर्थित उद्देश्य, क्षमता टैग, प्रसंभाव्यता, डिफ़ॉल्ट विराम मानदंड, और एक प्रामाणिक उद्धरण। इसे 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))

इसे 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

यह मेटाडेटा वही है जिस पर registry.select फ़िल्टर करता है और जिससे सॉल्वर अनुशंसक समझाता है। पूर्ण रजिस्ट्री — आधार-रेखाएँ, मेटाह्यूरिस्टिक्स, सटीक एडाप्टर, और NDSO परिवार — एल्गोरिथम और सॉल्वर प्रणाली में कैटलॉग की गई है।

🧪 Tutorial 2: एक छोटा अभियान चलाएँ और उसके परिणाम पढ़ें

एक अभियान रनों का एक विन्यस्त समुच्चय है — बेंचमार्क इंस्टेंस सॉल्वरों और उद्देश्यों के साथ क्रॉस किए गए — स्पष्ट बीजों, बजटों, चेकपॉइंटों, और एक डिस्क-पर परिणाम रिपॉज़िटरी के साथ निष्पादित। यह ट्यूटोरियल experiments/configs/smoke-pilot.json पर ट्रैक की गई रेसिपी के समान आकार चलाता है: दो स्मोक इंस्टेंस, दो नियतात्मक आधार-रेखाएँ, एक उद्देश्य।

1️⃣ अभियान विन्यस्त और चलाएँ

इसे first_campaign.py के रूप में सहेजें। यह अभियान घोषित करता है, उसे एक नियतात्मक योजना में सत्यापित करता है, एक सूखे-रन से उसकी लागत आकलित करता है, फिर उसे एक स्थानीय 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)}")

इसे uv run python first_campaign.py के साथ चलाएँ:

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

चार रन ठीक क्रॉस गुणनफल है: 2 बेंचमार्क इंस्टेंस × 2 सॉल्वर × 1 उद्देश्य, प्रति कोष्ठिका एक रन क्योंकि दोनों सॉल्वर नियतात्मक हैं। प्रत्येक रन का बीज root_seed और रन की स्थिति से व्युत्पन्न होता है, अतः स्क्रिप्ट को पुनः-चलाना समान रिकॉर्ड पुनरुत्पादित करता है; चेकपॉइंट एक बाधित अभियान को पूर्ण किए गए कार्य को दोहराए बिना पुनः-आरंभ करने देता है।

2️⃣ जाँचें कि डिस्क पर क्या उतरा

runner ने ट्रैक किए गए प्रयोग वर्कस्पेस के समान लेआउट वाला एक वर्कस्पेस लिखा:

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

प्रति रन एक JSON रिकॉर्ड, अभियान, सॉल्वर, बेंचमार्क, और प्रतिकृति सूचकांक द्वारा संबोधित — पथ स्वयं सूचकांक है। प्रत्येक रिकॉर्ड अपने नियतात्मक पेलोड पर सामग्री-हैश किया जाता है, जो वही है जिसके विरुद्ध replay मोड सत्यापित करता है।

3️⃣ विश्लेषण के लिए परिणाम लोड करें

dispatchatlas.analytica अभियान रनटाइम आयात किए बिना पूर्ण किए गए अभियान निर्देशिकाएँ पढ़ता है। इसे 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}"
    )

इसे 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 प्रति सॉल्वर और उद्देश्य वर्णनात्मक सांख्यिकी संगणित करता है। प्रति सॉल्वर केवल दो रनों के साथ अनुमानिक विधियाँ (सार्थकता परीक्षण, विश्वास अंतराल) अल्प-शक्ति परिणाम उत्पन्न करने के बजाय सीमा सतह को रूट होती हैं — प्रति प्रसंभाव्य सॉल्वर-इंस्टेंस कोष्ठिका 30 स्वतंत्र रनों की सांख्यिकीय-शक्ति न्यूनतम विश्लेषण निर्यात में वर्णित है।

4️⃣ एक साक्ष्य बंडल निर्यात करें (वैकल्पिक)

वही अभियान निर्देशिका निर्यात कमांड को आहार देती है, जो तालिकाओं, आकृतियों, और अनुपूरक का एक प्रकटीकरण-फ़िल्टर साक्ष्य बंडल लिखती है:

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

बंडल exports/first-campaign/evidence-bundles/first-campaign-core/ पर उतरता है। साक्ष्य बंडल पृष्ठ चार स्तरों और बंडल सामग्री को समझाता है।

🎓 यह कहाँ ले जाता है

  • ट्रैक की गई रेसिपी experiments/scripts/run_smoke_pilot.py इस समान आकार को प्रयोग वर्कस्पेस में चलाती है और इसके विन्यास को dispatchatlas-lab कमांड-लाइन इंटरफ़ेस के लिए सीरियलाइज़ करती है।
  • अभियान इंजन पृष्ठ निष्पादन मोड, पुनः-प्रयास नीति, पुनः-आरंभ, replay सत्यापन, दोहरे विराम प्रोटोकॉल, और निष्पक्ष-तुलना गारंटियों को कवर करता है।
  • पूर्ण-चरण अभियान तब तक अवरुद्ध रहते हैं जब तक सांख्यिकीय डिज़ाइन अनुमोदन दर्ज न हो जाए — रिलीज़ तत्परता देखें।