File indexing completed on 2026-08-12 08:24:55
0001
0002 """Integration example: Schedulers + Workflows + Configurations.
0003
0004 Shows how JobLibScheduler integrates with workflow configs and objectives.
0005 This is a preview of Step 4 (Extend FullConfig with workflows).
0006
0007 Run: python3 scheduler_workflow_integration_example.py
0008 """
0009
0010 from aid2e.schedulers import (
0011 JobLibScheduler,
0012 get_scheduler,
0013 )
0014 from aid2e.utilities.configurations.workflow_config import (
0015 WorkflowDefinition,
0016 BranchDefinition,
0017 StageDefinition,
0018 JobDefinition,
0019 JobFactory,
0020 ParallelismPolicy,
0021 ArtifactSpec,
0022 )
0023 from aid2e.utilities.configurations.objectives import (
0024 ObjectiveDefinition,
0025 ObjectiveDirection,
0026 ObjectiveComputationSpec,
0027 ScriptObjective,
0028 )
0029 from aid2e.utilities.configurations.scheduler_config import (
0030 SchedulerConfiguration,
0031 JobLibRunnerConfig,
0032 )
0033
0034
0035 def example_basic_scheduler():
0036 """Example 1: Using JobLibScheduler directly."""
0037 print("=" * 70)
0038 print("Example 1: Basic JobLibScheduler Usage")
0039 print("=" * 70)
0040
0041 scheduler = JobLibScheduler()
0042
0043
0044 jobs = [
0045 {
0046 'name': 'evaluate_1',
0047 'command': 'python -c "print(\'f1=1.0, f2=2.0\')"',
0048 'payload': {'design_id': 1},
0049 'outputs': []
0050 },
0051 {
0052 'name': 'evaluate_2',
0053 'command': 'python -c "print(\'f1=1.5, f2=2.5\')"',
0054 'payload': {'design_id': 2},
0055 'outputs': []
0056 },
0057 ]
0058
0059
0060 result = scheduler.run_stage(
0061 stage_name='evaluate',
0062 job_definitions=jobs,
0063 parallelism_policy={'max_concurrent': 2}
0064 )
0065
0066 print(f"Stage: {result.stage_name}")
0067 print(f"Success: {result.success}")
0068 print(f"Jobs completed: {len(result.job_statuses)}")
0069 for status in result.job_statuses:
0070 print(f" {status.job_id}: {status.status} (exit code: {status.return_code})")
0071
0072
0073 def example_with_registry():
0074 """Example 2: Using scheduler registry to lookup schedulers."""
0075 print("\n" + "=" * 70)
0076 print("Example 2: Using Scheduler Registry")
0077 print("=" * 70)
0078
0079
0080 SchedulerClass = get_scheduler('joblib')
0081 print(f"Retrieved scheduler class: {SchedulerClass.__name__}")
0082
0083
0084 config = JobLibRunnerConfig(n_jobs=2, backend='threading')
0085 scheduler = SchedulerClass(config=config)
0086
0087 jobs = [
0088 {'name': 'job_1', 'command': 'echo "Processing job 1"', 'payload': {}, 'outputs': []},
0089 {'name': 'job_2', 'command': 'echo "Processing job 2"', 'payload': {}, 'outputs': []},
0090 ]
0091
0092 result = scheduler.run_stage('process', job_definitions=jobs)
0093 print(f"Result: {result.success} ({len(result.job_statuses)} jobs)")
0094
0095
0096 def example_workflow_with_scheduler():
0097 """Example 3: Workflow + Scheduler integration."""
0098 print("\n" + "=" * 70)
0099 print("Example 3: Workflow + Scheduler Integration")
0100 print("=" * 70)
0101
0102
0103 workflow = WorkflowDefinition(
0104 name='dtlz2_eval',
0105 description='Evaluate design point using DTLZ2',
0106 branches=[
0107 BranchDefinition(
0108 name='main',
0109 stages=[
0110 StageDefinition(
0111 name='evaluate',
0112 jobs=[
0113 JobDefinition(
0114 name='dtlz2_evaluate',
0115 command='python scripts/dtlz2_problem.py',
0116 payload={'design_id': 1},
0117 outputs=[ArtifactSpec(path='objectives.json', format='json')]
0118 )
0119 ],
0120 job_factory=JobFactory(type='range', params={'n': 1}),
0121 parallelism=ParallelismPolicy(max_concurrent=1, retry_max=2, timeout_sec=300),
0122 ),
0123 StageDefinition(
0124 name='aggregate',
0125 jobs=[
0126 JobDefinition(
0127 name='aggregate',
0128 command='echo "Aggregating results"',
0129 payload={},
0130 outputs=[]
0131 )
0132 ],
0133 )
0134 ]
0135 )
0136 ],
0137 objectives=[
0138 ObjectiveDefinition(
0139 name='f1',
0140 direction=ObjectiveDirection.MINIMIZE,
0141 computation=ObjectiveComputationSpec(
0142 script=ScriptObjective(
0143 path='scripts/dtlz2_problem.py',
0144 output_file='objectives.json',
0145 timeout_sec=600
0146 )
0147 )
0148 ),
0149 ObjectiveDefinition(
0150 name='f2',
0151 direction=ObjectiveDirection.MINIMIZE,
0152 ),
0153 ]
0154 )
0155
0156 print(f"Workflow: {workflow.name}")
0157 print(f" Description: {workflow.description}")
0158 print(f" Branches: {len(workflow.branches)}")
0159 for branch in workflow.branches:
0160 print(f" Branch '{branch.name}': {len(branch.stages)} stages")
0161 for stage in branch.stages:
0162 print(f" Stage '{stage.name}': {len(stage.jobs)} jobs")
0163 print(f" Objectives: {len(workflow.objectives)}")
0164 for obj in workflow.objectives:
0165 print(f" {obj.name} ({obj.direction})")
0166
0167
0168 def example_scheduler_config():
0169 """Example 4: SchedulerConfiguration and JobLibRunnerConfig."""
0170 print("\n" + "=" * 70)
0171 print("Example 4: SchedulerConfiguration Models")
0172 print("=" * 70)
0173
0174
0175 joblib_config = JobLibRunnerConfig(
0176 n_jobs=4,
0177 backend='loky',
0178 timeout=600,
0179 verbose=1
0180 )
0181
0182 scheduler_config = SchedulerConfiguration(
0183 runner_type='JobLibRunner',
0184 joblib=joblib_config,
0185 max_retries=3,
0186 monitor_interval=30,
0187 )
0188
0189 print(f"Scheduler type: {scheduler_config.runner_type}")
0190 print(f" JobLib jobs: {scheduler_config.joblib.n_jobs}")
0191 print(f" Backend: {scheduler_config.joblib.backend}")
0192 print(f" Timeout: {scheduler_config.joblib.timeout}s")
0193 print(f"Global max retries: {scheduler_config.max_retries}")
0194 print(f"Monitor interval: {scheduler_config.monitor_interval}s")
0195
0196
0197 def example_stage_execution():
0198 """Example 5: Execute a realistic workflow stage."""
0199 print("\n" + "=" * 70)
0200 print("Example 5: Realistic Stage Execution")
0201 print("=" * 70)
0202
0203 scheduler = JobLibScheduler(
0204 config=JobLibRunnerConfig(n_jobs=3, backend='threading')
0205 )
0206
0207
0208 jobs = [
0209 {
0210 'name': f'design_{i}',
0211 'command': f'python -c "import json; print(json.dumps({{"f1": {1.0 + i*0.1}, "f2": {2.0 + i*0.2}}})"',
0212 'payload': {'design_id': i},
0213 'outputs': []
0214 }
0215 for i in range(3)
0216 ]
0217
0218 result = scheduler.run_stage(
0219 stage_name='evaluate_designs',
0220 job_definitions=jobs,
0221 parallelism_policy={'max_concurrent': 3, 'retry_max': 2, 'timeout_sec': 60},
0222 )
0223
0224 print(f"Stage: {result.stage_name}")
0225 print(f"Success: {result.success}")
0226 print(f"Total jobs: {len(result.job_statuses)}")
0227 print(f"Completed jobs: {sum(1 for s in result.job_statuses if s.status == 'completed')}")
0228 print(f"Failed jobs: {sum(1 for s in result.job_statuses if s.status == 'failed')}")
0229
0230 print("\nJob Results:")
0231 for status in result.job_statuses:
0232 print(f" {status.job_id}: {status.status} (exit: {status.return_code})")
0233
0234
0235 if __name__ == '__main__':
0236 example_basic_scheduler()
0237 example_with_registry()
0238 example_workflow_with_scheduler()
0239 example_scheduler_config()
0240 example_stage_execution()
0241
0242 print("\n" + "=" * 70)
0243 print("✓ All integration examples completed successfully!")
0244 print("=" * 70)