use crate::{QvmScheduler, QvmError, Result};
use crate::circuit_ir::QuantumCircuit;
use crate::topology::{Topology, TopologyBuilder};
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
use std::path::Path;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CliConfig {
pub input_files: Vec<String>,
pub output_file: String,
pub topology: TopologyConfig,
pub buffer_zones: usize,
pub strategy: SchedulingStrategy,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TopologyConfig {
Grid { width: usize, height: usize },
Linear { size: usize },
Custom { file: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SchedulingStrategy {
FirstFitDecreasing,
BestFit,
WorstFit,
}
impl Default for CliConfig {
fn default() -> Self {
Self {
input_files: vec![],
output_file: "output.qasm".to_string(),
topology: TopologyConfig::Grid { width: 5, height: 5 },
buffer_zones: 1,
strategy: SchedulingStrategy::FirstFitDecreasing,
}
}
}
impl CliConfig {
pub fn create_topology(&self) -> Result<Topology> {
match &self.topology {
TopologyConfig::Grid { width, height } => {
Ok(TopologyBuilder::grid(*width, *height))
}
TopologyConfig::Linear { size } => {
Ok(TopologyBuilder::linear(*size))
}
TopologyConfig::Custom { file: _ } => {
Err(QvmError::config_error("Custom topologies not yet implemented"))
}
}
}
#[cfg(feature = "std")]
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
let content = std::fs::read_to_string(path)?;
let config: CliConfig = serde_json::from_str(&content)?;
Ok(config)
}
#[cfg(feature = "std")]
pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let content = serde_json::to_string_pretty(self)?;
std::fs::write(path, content)?;
Ok(())
}
}
pub struct CliRunner {
config: CliConfig,
scheduler: QvmScheduler,
}
impl CliRunner {
pub fn new(config: CliConfig) -> Result<Self> {
let topology = config.create_topology()?;
let scheduler = QvmScheduler::new(topology);
Ok(Self { config, scheduler })
}
#[cfg(feature = "std")]
pub async fn run(&mut self) -> Result<()> {
let mut circuits = Vec::new();
for input_file in &self.config.input_files {
let circuit = self.load_circuit(input_file)?;
circuits.push(circuit);
}
let composite = self.scheduler.schedule_circuits(circuits).await?;
self.save_output(&composite).await?;
println!("Successfully scheduled {} circuits", composite.circuits().len());
println!("Output saved to: {}", self.config.output_file);
Ok(())
}
#[cfg(feature = "std")]
fn load_circuit(&self, file_path: &str) -> Result<QuantumCircuit> {
let content = std::fs::read_to_string(file_path)?;
QuantumCircuit::from_qasm(&content)
}
#[cfg(feature = "std")]
async fn save_output(&self, composite: &crate::CompositeCircuit) -> Result<()> {
let qasm_output = composite.to_qasm()?;
std::fs::write(&self.config.output_file, qasm_output)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = CliConfig::default();
assert_eq!(config.buffer_zones, 1);
assert!(config.input_files.is_empty());
}
#[test]
fn test_topology_creation() {
let config = CliConfig {
topology: TopologyConfig::Grid { width: 3, height: 3 },
..Default::default()
};
let topology = config.create_topology().unwrap();
assert_eq!(topology.qubit_count(), 9);
}
}