Download api/test_greedyoptim_api.py from Arpit-Bansal/train-schedule-optimization: direct link, hf CLI and curl.
- Browser
- Download file 15.7 kB
-
https://huggingface.co/spaces/Arpit-Bansal/train-schedule-optimization/resolve/main/api/test_greedyoptim_api.py
- Command line
-
hf download hf://spaces/Arpit-Bansal/train-schedule-optimization/api/test_greedyoptim_api.py
-
curl -L -o test_greedyoptim_api.py https://huggingface.co/spaces/Arpit-Bansal/train-schedule-optimization/resolve/main/api/test_greedyoptim_api.py
15.7 kB
| #!/usr/bin/env python3 | |
| """ | |
| Test script for GreedyOptim API | |
| Tests all endpoints with sample data | |
| """ | |
| import requests | |
| import json | |
| from datetime import datetime, timedelta | |
| BASE_URL = "http://localhost:7860" | |
| def test_health(): | |
| """Test health check endpoint""" | |
| print("\n" + "="*70) | |
| print("Testing Health Check") | |
| print("="*70) | |
| response = requests.get(f"{BASE_URL}/health") | |
| print(f"Status: {response.status_code}") | |
| print(f"Response: {json.dumps(response.json(), indent=2)}") | |
| return response.status_code == 200 | |
| def test_methods(): | |
| """Test methods listing endpoint""" | |
| print("\n" + "="*70) | |
| print("Testing Methods Listing") | |
| print("="*70) | |
| response = requests.get(f"{BASE_URL}/methods") | |
| print(f"Status: {response.status_code}") | |
| if response.status_code == 200: | |
| methods = response.json() | |
| print(f"\nAvailable Methods: {len(methods['available_methods'])}") | |
| for method, info in methods['available_methods'].items(): | |
| print(f" {method}: {info['name']}") | |
| return response.status_code == 200 | |
| def test_generate_synthetic(): | |
| """Test synthetic data generation""" | |
| print("\n" + "="*70) | |
| print("Testing Synthetic Data Generation") | |
| print("="*70) | |
| payload = { | |
| "num_trainsets": 25, | |
| "maintenance_rate": 0.1, | |
| "availability_rate": 0.8 | |
| } | |
| response = requests.post(f"{BASE_URL}/generate-synthetic", json=payload) | |
| print(f"Status: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f"\nGenerated Data:") | |
| print(f" Trainsets: {result['metadata']['num_trainsets']}") | |
| print(f" Fitness Certificates: {result['metadata']['num_fitness_certificates']}") | |
| print(f" Job Cards: {result['metadata']['num_job_cards']}") | |
| print(f" Component Health: {result['metadata']['num_component_health']}") | |
| return result['data'] # Return for use in other tests | |
| return None | |
| def test_validate(data): | |
| """Test data validation endpoint""" | |
| print("\n" + "="*70) | |
| print("Testing Data Validation") | |
| print("="*70) | |
| # Create request from synthetic data | |
| request_data = { | |
| "trainset_status": data['trainset_status'], | |
| "fitness_certificates": data['fitness_certificates'], | |
| "job_cards": data['job_cards'], | |
| "component_health": data['component_health'], | |
| "method": "ga" | |
| } | |
| response = requests.post(f"{BASE_URL}/validate", json=request_data) | |
| print(f"Status: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f"\nValidation Result:") | |
| print(f" Valid: {result['valid']}") | |
| if result['valid']: | |
| print(f" Trainsets: {result['num_trainsets']}") | |
| print(f" Certificates: {result['num_certificates']}") | |
| print(f" Job Cards: {result['num_job_cards']}") | |
| print(f" Component Health: {result['num_component_health']}") | |
| else: | |
| print(f" Errors: {len(result.get('validation_errors', []))}") | |
| return response.status_code == 200 | |
| def test_optimize(data): | |
| """Test optimization endpoint""" | |
| print("\n" + "="*70) | |
| print("Testing Schedule Optimization") | |
| print("="*70) | |
| # Create optimization request | |
| request_data = { | |
| "trainset_status": data['trainset_status'], | |
| "fitness_certificates": data['fitness_certificates'], | |
| "job_cards": data['job_cards'], | |
| "component_health": data['component_health'], | |
| "method": "ga", | |
| "config": { | |
| "required_service_trains": 15, | |
| "min_standby": 2, | |
| "population_size": 30, | |
| "generations": 50 | |
| } | |
| } | |
| print(f"Optimizing with method: {request_data['method']}") | |
| print(f"Trainsets: {len(request_data['trainset_status'])}") | |
| response = requests.post(f"{BASE_URL}/optimize", json=request_data) | |
| print(f"Status: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f"\nOptimization Results:") | |
| print(f" Method: {result['method']}") | |
| print(f" Fitness Score: {result['fitness_score']:.4f}") | |
| print(f" Execution Time: {result['execution_time_seconds']:.3f}s") | |
| print(f"\n Schedule Allocation:") | |
| print(f" In Service: {result['num_service']} trains") | |
| print(f" Standby: {result['num_standby']} trains") | |
| print(f" Maintenance: {result['num_maintenance']} trains") | |
| print(f" Unavailable: {result['num_unavailable']} trains") | |
| print(f"\n Detailed Scores:") | |
| print(f" Service: {result['service_score']:.4f}") | |
| print(f" Standby: {result['standby_score']:.4f}") | |
| print(f" Health: {result['health_score']:.4f}") | |
| print(f" Certificate: {result['certificate_score']:.4f}") | |
| print(f"\n Constraints Satisfied: {result['constraints_satisfied']}") | |
| if result.get('warnings'): | |
| print(f" Warnings: {len(result['warnings'])}") | |
| for warning in result['warnings'][:3]: | |
| print(f" - {warning}") | |
| else: | |
| print(f"Error: {response.text}") | |
| return response.status_code == 200 | |
| def test_compare(data): | |
| """Test method comparison endpoint""" | |
| print("\n" + "="*70) | |
| print("Testing Method Comparison") | |
| print("="*70) | |
| # Create comparison request with all trainsets and all methods | |
| request_data = { | |
| "trainset_status": data['trainset_status'], | |
| "fitness_certificates": data['fitness_certificates'], | |
| "job_cards": data.get('job_cards', []), | |
| "component_health": data['component_health'], | |
| "methods": ["ga", "pso", "sa", "cmaes", "nsga2"], | |
| "config": { | |
| "required_service_trains": 15, | |
| "min_standby": 2, | |
| "population_size": 30, | |
| "generations": 50 | |
| } | |
| } | |
| print(f"Comparing methods: {request_data['methods']}") | |
| print(f"Trainsets: {len(request_data['trainset_status'])}") | |
| response = requests.post(f"{BASE_URL}/compare", json=request_data) | |
| print(f"Status: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f"\nComparison Results:") | |
| print(f" Total Execution Time: {result['summary']['total_execution_time']:.3f}s") | |
| print(f" Best Method: {result['summary']['best_method']}") | |
| print(f" Best Score: {result['summary']['best_score']:.4f}") | |
| print(f"\n Individual Results:") | |
| for method, method_result in result['methods'].items(): | |
| print(f" {method.upper()}:") | |
| print(f" Fitness: {method_result['fitness_score']:.4f}") | |
| print(f" Service: {method_result['num_service']} trains") | |
| print(f" Time: {method_result.get('execution_time_seconds', 'N/A')}") | |
| else: | |
| print(f"Error: {response.text}") | |
| return response.status_code == 200 | |
| def test_custom_data(): | |
| """Test with minimal custom data""" | |
| print("\n" + "="*70) | |
| print("Testing with Custom Minimal Data") | |
| print("="*70) | |
| # Create minimal valid data with 25 trainsets | |
| custom_data = { | |
| "trainset_status": [ | |
| {"trainset_id": f"KMRL-{i:02d}", "operational_status": "Available", "total_mileage_km": 50000.0} | |
| for i in range(1, 26) | |
| ], | |
| "fitness_certificates": [ | |
| { | |
| "trainset_id": f"KMRL-{i:02d}", | |
| "department": "Safety", | |
| "status": "Valid", | |
| "expiry_date": (datetime.now() + timedelta(days=365)).isoformat() | |
| } | |
| for i in range(1, 26) | |
| ], | |
| "job_cards": [], # No job cards | |
| "component_health": [ | |
| { | |
| "trainset_id": f"KMRL-{i:02d}", | |
| "component": "Brakes", | |
| "status": "Good", | |
| "wear_level": 20.0 | |
| } | |
| for i in range(1, 26) | |
| ], | |
| "method": "ga", | |
| "config": { | |
| "required_service_trains": 15, | |
| "min_standby": 2, | |
| "population_size": 30, | |
| "generations": 50 | |
| } | |
| } | |
| print(f"Testing with {len(custom_data['trainset_status'])} trainsets") | |
| response = requests.post(f"{BASE_URL}/optimize", json=custom_data) | |
| print(f"Status: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f"\nOptimization successful!") | |
| print(f" Fitness: {result['fitness_score']:.4f}") | |
| print(f" In Service: {result['num_service']}") | |
| print(f" Time: {result['execution_time_seconds']:.3f}s") | |
| else: | |
| print(f"Error: {response.text}") | |
| return response.status_code == 200 | |
| def test_schedule(data): | |
| """Test full schedule generation endpoint""" | |
| print("\n" + "="*70) | |
| print("Testing Full Schedule Generation (/schedule)") | |
| print("="*70) | |
| # Create schedule request | |
| request_data = { | |
| "trainset_status": data['trainset_status'], | |
| "fitness_certificates": data['fitness_certificates'], | |
| "job_cards": data.get('job_cards', []), | |
| "component_health": data['component_health'], | |
| "method": "ga", | |
| "config": { | |
| "required_service_trains": 6, | |
| "min_standby": 2, | |
| "population_size": 30, | |
| "generations": 50 | |
| } | |
| } | |
| print(f"Generating schedule with method: {request_data['method']}") | |
| print(f"Trainsets: {len(request_data['trainset_status'])}") | |
| response = requests.post(f"{BASE_URL}/schedule", json=request_data) | |
| print(f"Status: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f"\nSchedule Generated:") | |
| print(f" Schedule ID: {result['schedule_id']}") | |
| print(f" Valid From: {result['valid_from']}") | |
| print(f" Valid Until: {result['valid_until']}") | |
| print(f" Depot: {result['depot']}") | |
| print(f"\n Fleet Summary:") | |
| fleet = result['fleet_summary'] | |
| print(f" Total Trainsets: {fleet['total_trainsets']}") | |
| print(f" Revenue Service: {fleet['revenue_service']}") | |
| print(f" Standby: {fleet['standby']}") | |
| print(f" Maintenance: {fleet['maintenance']}") | |
| print(f" Availability: {fleet['availability_percent']}%") | |
| print(f"\n Optimization Metrics:") | |
| metrics = result['optimization_metrics'] | |
| print(f" Fitness Score: {metrics['fitness_score']:.4f}") | |
| print(f" Method: {metrics['method']}") | |
| print(f" Total Planned KM: {metrics['total_planned_km']}") | |
| print(f" Runtime: {metrics['optimization_runtime_ms']}ms") | |
| # Show service trainsets with blocks | |
| print(f"\n Service Trainsets with Blocks:") | |
| service_count = 0 | |
| for ts in result['trainsets']: | |
| if ts['status'] == 'REVENUE_SERVICE': | |
| service_count += 1 | |
| blocks = ts.get('service_blocks', []) | |
| print(f" {ts['trainset_id']}: {len(blocks)} blocks, {ts['daily_km_allocation']} km") | |
| if blocks and service_count <= 2: # Show blocks for first 2 service trains | |
| for block in blocks[:3]: | |
| print(f" - {block['block_id']}: {block['departure_time']} {block['origin']} → {block['destination']}") | |
| if len(blocks) > 3: | |
| print(f" ... and {len(blocks) - 3} more blocks") | |
| # Show alerts | |
| if result.get('alerts'): | |
| print(f"\n Alerts: {len(result['alerts'])}") | |
| for alert in result['alerts'][:3]: | |
| print(f" [{alert['severity']}] {alert['trainset_id']}: {alert['message']}") | |
| else: | |
| print(f"Error: {response.text}") | |
| return response.status_code == 200 | |
| def test_schedule_methods(data): | |
| """Test schedule generation with different optimization methods""" | |
| print("\n" + "="*70) | |
| print("Testing Schedule with Different Methods") | |
| print("="*70) | |
| methods = ['ga', 'pso', 'sa', 'nsga2'] | |
| results = {} | |
| for method in methods: | |
| request_data = { | |
| "trainset_status": data['trainset_status'][:15], | |
| "fitness_certificates": [fc for fc in data['fitness_certificates'] | |
| if fc['trainset_id'] in [ts['trainset_id'] for ts in data['trainset_status'][:15]]], | |
| "job_cards": [], | |
| "component_health": [ch for ch in data['component_health'] | |
| if ch['trainset_id'] in [ts['trainset_id'] for ts in data['trainset_status'][:15]]], | |
| "method": method, | |
| "config": { | |
| "required_service_trains": 6, | |
| "min_standby": 2, | |
| "population_size": 20, | |
| "generations": 30 | |
| } | |
| } | |
| response = requests.post(f"{BASE_URL}/schedule", json=request_data) | |
| if response.status_code == 200: | |
| result = response.json() | |
| total_blocks = sum( | |
| len(ts.get('service_blocks', [])) | |
| for ts in result['trainsets'] | |
| if ts['status'] == 'REVENUE_SERVICE' | |
| ) | |
| results[method] = { | |
| 'success': True, | |
| 'blocks': total_blocks, | |
| 'fitness': result['optimization_metrics']['fitness_score'], | |
| 'service': result['fleet_summary']['revenue_service'] | |
| } | |
| print(f" {method.upper()}: ✓ {total_blocks} blocks, {results[method]['service']} service trains") | |
| else: | |
| results[method] = {'success': False} | |
| print(f" {method.upper()}: ✗ Failed") | |
| return all(r['success'] for r in results.values()) | |
| def main(): | |
| """Run all tests""" | |
| print("=" * 70) | |
| print("GREEDYOPTIM API TEST SUITE") | |
| print("=" * 70) | |
| print(f"Testing API at: {BASE_URL}") | |
| print(f"Start Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") | |
| results = {} | |
| # Run tests | |
| results['health'] = test_health() | |
| results['methods'] = test_methods() | |
| # Generate synthetic data for remaining tests | |
| synthetic_data = test_generate_synthetic() | |
| if synthetic_data: | |
| results['validate'] = test_validate(synthetic_data) | |
| results['optimize'] = test_optimize(synthetic_data) | |
| results['schedule'] = test_schedule(synthetic_data) | |
| results['schedule_methods'] = test_schedule_methods(synthetic_data) | |
| results['compare'] = test_compare(synthetic_data) | |
| results['custom'] = test_custom_data() | |
| # Summary | |
| print("\n" + "="*70) | |
| print("TEST SUMMARY") | |
| print("="*70) | |
| passed = sum(1 for v in results.values() if v) | |
| total = len(results) | |
| print(f"\nTests Passed: {passed}/{total}") | |
| for test_name, passed in results.items(): | |
| status = "✓ PASS" if passed else "✗ FAIL" | |
| print(f" {status} - {test_name}") | |
| print("\n" + "="*70) | |
| print(f"End Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") | |
| print("="*70) | |
| if __name__ == "__main__": | |
| try: | |
| main() | |
| except requests.exceptions.ConnectionError: | |
| print("\n✗ ERROR: Could not connect to API") | |
| print(" Make sure the API is running:") | |
| print(" python api/greedyoptim_api.py") | |
| except Exception as e: | |
| print(f"\n✗ ERROR: {str(e)}") | |