User Guide¶
This guide covers all features of the Enhanced Quantum Backend Selector.
How It Works¶
The library provides intelligent backend selection through transpilation-based error analysis:
- Transpiles your circuit to each backend's native gate set
- Calculates the total expected error from all gates and qubits used
- Averages over multiple transpilation runs for stability (default: 3)
- Ranks backends by their actual expected error
Basic Usage¶
from enhanced_quantum_backend_selector import BackendSelector
from qiskit import QuantumCircuit
selector = BackendSelector(backends)
rec = selector.select_backend(circuit)
backend = rec.backend
Understanding Scores¶
The score is based on transpilation-based error estimation:
rec = selector.select_backend(qc)
print(f"Backend: {rec.backend.name}")
print(f"Score: {rec.score_data.score:.3f}") # Negative error sum
print(f"Expected error: {-rec.score_data.score:.2%}")
# Human-readable reasons
for reason in rec.score_data.reasons:
print(f" • {reason}")
Score interpretation:
- Score is the negative sum of all errors:
score = -total_error - Higher scores are better (less negative = lower error)
-0.01(1% error) is better than-0.05(5% error)
Advanced Features¶
Get Full Rankings¶
# Get all backends ranked
all_rankings = selector.rank_backends(qc)
for rec in all_rankings:
print(f"{rec.rank}. {rec.backend.name}: {rec.score_data.score:.3f}")
# Get only top N
top_3 = selector.rank_backends(qc, top_n=3)
Minimum Score Filtering¶
# Require max 10% total error
try:
rec = selector.select_backend(qc, min_score=-0.1)
except RuntimeError as e:
print(f"No backends met threshold: {e}")
Compatibility Filtering¶
# Strict mode (default) - only compatible backends
rec = selector.select_backend(qc, require_compatible=True)
# Lenient mode - include incompatible backends in ranking
rec = selector.select_backend(qc, require_compatible=False)
Configuring Transpilation Runs¶
# Default: 3 runs (balanced)
selector = BackendSelector(backends)
# Fast: 1 run
selector_fast = BackendSelector(backends, transpilation_runs=1)
# Accurate: 5 runs
selector_accurate = BackendSelector(backends, transpilation_runs=5)
Fractional Gates for Chemistry¶
For chemistry and VQE circuits, fractional gates can improve results:
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
# Include both versions to compare
backends = [
service.backend('ibm_torino'),
service.backend('ibm_torino', use_fractional_gates=True),
]
selector = BackendSelector(backends)
rec = selector.select_backend(chemistry_circuit)
Performance¶
Caching¶
Backend analyzers are cached per-selector instance:
# First call creates analyzer
rec1 = selector.select_backend(qc1)
# Second call reuses cached analyzer
rec2 = selector.select_backend(qc2)
# Clear cache to force fresh analysis
selector.clear_cache()
Parallel Processing¶
Multiple backends are scored in parallel (up to 10 workers) automatically.
Best Practices¶
1. Handle Exceptions¶
try:
rec = selector.select_backend(qc)
except ValueError as e:
print(f"Selection failed: {e}")
# Fallback logic
2. Validate Recommendations¶
rec = selector.select_backend(qc)
# Check error rate
error_pct = -rec.score_data.score * 100
if error_pct > 10:
print(f"Warning: {error_pct:.1f}% expected error")
3. Compare Multiple Backends¶
top_5 = selector.rank_backends(qc, top_n=5)
for rec in top_5:
error_pct = -rec.score_data.score * 100
print(f"#{rec.rank}: {rec.backend.name} - {error_pct:.2f}% error")
Example: Production Backend Selection¶
def select_production_backend(circuit, backends):
"""Select backend with error handling."""
selector = BackendSelector(backends)
try:
rec = selector.select_backend(circuit, require_compatible=True)
error_pct = -rec.score_data.score * 100
if error_pct < 10:
return rec.backend, "optimal"
else:
return rec.backend, "acceptable"
except ValueError:
# Fallback to first available
rankings = selector.rank_backends(circuit)
return rankings[0].backend, "fallback"
Next Steps¶
- Examples - More code examples
- API Reference - Complete API documentation
- Architecture - System design details