use crate::clap::builder::{StringValueParser, TypedValueParser, ValueParser};
use crate::clap::error::{ContextKind, ContextValue, ErrorKind};
use crate::clap::{Parser, Subcommand};
use crate::code_builder;
use crate::noise_model_builder;
use crate::serde::{Deserialize, Serialize};
use crate::serde_json;
use crate::tool;
#[derive(Parser, Clone, Debug)]
#[clap(author = clap::crate_authors!(", "))]
#[clap(version = env!("CARGO_PKG_VERSION"))]
#[clap(about = "Quantum Error Correction Playground")]
#[clap(color = clap::ColorChoice::Auto)]
#[clap(propagate_version = true)]
#[clap(subcommand_required = true)]
#[clap(arg_required_else_help = true)]
pub struct Cli {
#[clap(subcommand)]
pub command: Commands,
}
#[derive(Subcommand, Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum Commands {
Test {
#[clap(subcommand)]
command: TestCommands,
},
Tool {
#[clap(subcommand)]
command: ToolCommands,
},
Server(ServerParameters),
}
#[derive(Subcommand, Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum TestCommands {
DebugTests,
ArchivedDebugTests,
All,
}
#[derive(Subcommand, Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum ToolCommands {
Benchmark(BenchmarkParameters),
}
#[derive(Clone)]
struct VecUsizeParser;
impl TypedValueParser for VecUsizeParser {
type Value = Vec<usize>;
fn parse_ref(
&self,
cmd: &clap::Command,
arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
let inner = StringValueParser::new();
let val = inner.parse_ref(cmd, arg, value)?;
match serde_json::from_str::<Vec<usize>>(&val) {
Ok(vector) => Ok(vector),
Err(error) => {
let mut err = clap::Error::new(ErrorKind::ValueValidation).with_cmd(cmd);
if let Some(arg) = arg {
err.insert(ContextKind::InvalidArg, ContextValue::String(arg.to_string()));
}
err.insert(
ContextKind::InvalidValue,
ContextValue::String(format!("should be like [1,2,3], parse error: {}", error)),
);
Err(err)
}
}
}
}
#[derive(Clone)]
struct VecF64Parser;
impl TypedValueParser for VecF64Parser {
type Value = Vec<f64>;
fn parse_ref(
&self,
cmd: &clap::Command,
arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
let inner = StringValueParser::new();
let val = inner.parse_ref(cmd, arg, value)?;
match serde_json::from_str::<Vec<f64>>(&val) {
Ok(vector) => Ok(vector),
Err(error) => {
let mut err = clap::Error::new(ErrorKind::ValueValidation).with_cmd(cmd);
if let Some(arg) = arg {
err.insert(ContextKind::InvalidArg, ContextValue::String(arg.to_string()));
}
err.insert(
ContextKind::InvalidValue,
ContextValue::String(format!("should be like [0.1,0.2,0.3], parse error: {error}")),
);
Err(err)
}
}
}
}
#[derive(Clone)]
struct SerdeJsonParser;
impl TypedValueParser for SerdeJsonParser {
type Value = serde_json::Value;
fn parse_ref(
&self,
cmd: &clap::Command,
arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
let inner = StringValueParser::new();
let val = inner.parse_ref(cmd, arg, value)?;
match serde_json::from_str::<serde_json::Value>(&val) {
Ok(vector) => Ok(vector),
Err(error) => {
let mut err = clap::Error::new(ErrorKind::ValueValidation).with_cmd(cmd);
if let Some(arg) = arg {
err.insert(ContextKind::InvalidArg, ContextValue::String(arg.to_string()));
}
err.insert(
ContextKind::InvalidValue,
ContextValue::String(format!("should be like {{\"a\":1}}, parse error: {error}")),
);
Err(err)
}
}
}
}
#[derive(Parser, Clone, Serialize, Deserialize, Debug)]
pub struct BenchmarkParameters {
#[clap(value_parser = ValueParser::new(VecUsizeParser))]
pub dis: std::vec::Vec<usize>,
#[clap(long, value_parser = ValueParser::new(VecUsizeParser))]
pub djs: Option<std::vec::Vec<usize>>,
#[clap(value_parser = ValueParser::new(VecUsizeParser))]
pub nms: std::vec::Vec<usize>,
#[clap(value_parser = ValueParser::new(VecF64Parser))]
pub ps: std::vec::Vec<f64>,
#[clap(long, value_parser = ValueParser::new(VecF64Parser))]
pub ps_graph: Option<std::vec::Vec<f64>>,
#[clap(long, value_parser = ValueParser::new(VecF64Parser))]
pub pes: Option<std::vec::Vec<f64>>,
#[clap(long, value_parser = ValueParser::new(VecF64Parser))]
pub pes_graph: Option<std::vec::Vec<f64>>,
#[clap(long, default_value_t = 0.5)]
pub bias_eta: f64,
#[clap(short = 'm', long, default_value_t = 100000000)]
pub max_repeats: usize,
#[clap(short = 'e', long, default_value_t = 10000)]
pub min_failed_cases: usize,
#[clap(short = 'p', long, default_value_t = 1)]
pub parallel: usize,
#[clap(long)]
pub parallel_init: Option<usize>,
#[clap(short = 'c', long, value_enum, default_value_t = code_builder::CodeType::StandardPlanarCode)]
pub code_type: code_builder::CodeType,
#[clap(long, value_enum, default_value_t = tool::BenchmarkDecoder::MWPM)]
pub decoder: tool::BenchmarkDecoder,
#[clap(long, default_value_t = json!({}), value_parser = ValueParser::new(SerdeJsonParser))]
pub decoder_config: serde_json::Value,
#[clap(long, action)]
pub ignore_logical_i: bool,
#[clap(long, action)]
pub ignore_logical_j: bool,
#[clap(long)]
pub debug_print: Option<tool::BenchmarkDebugPrint>,
#[clap(long)]
pub time_budget: Option<f64>,
#[clap(long)]
pub log_runtime_statistics: Option<String>,
#[clap(long, action)]
pub log_error_pattern_when_logical_error: bool,
#[clap(long, alias = "noise-model")]
pub noise_model_builder: Option<noise_model_builder::NoiseModelBuilder>,
#[clap(long, default_value_t = json!({}), value_parser = ValueParser::new(SerdeJsonParser))]
pub noise_model_configuration: serde_json::Value,
#[clap(long, default_value_t = 60.)]
pub thread_timeout: f64,
#[clap(long, action)]
pub use_brief_edge: bool,
#[clap(long, default_value_t = ("").to_string())]
pub label: String,
#[clap(long)]
pub load_noise_model_from_temporary_store: Option<usize>,
#[clap(long)]
pub load_noise_model_from_file: Option<String>,
#[clap(long, action)]
pub enable_visualizer: bool,
#[clap(long, default_value_t = crate::visualize::static_visualize_data_filename())]
pub visualizer_filename: String,
#[clap(long, action)]
pub visualizer_skip_success_cases: bool,
#[clap(long, action)]
pub visualizer_model_graph: bool,
#[clap(long, action)]
pub visualizer_model_hypergraph: bool,
#[clap(long, action)]
pub visualizer_tailored_model_graph: bool,
#[clap(long, default_value_t = ("./tmp/fusion.syndromes").to_string())]
pub fusion_blossom_syndrome_export_filename: String,
#[clap(long, requires = "use_compact_simulator")]
pub simulator_compact_extender_noisy_measurements: Option<usize>,
#[clap(long, action)]
pub use_compact_simulator: bool,
#[clap(long, requires = "use_compact_simulator")]
pub use_compact_simulator_compressed: bool,
#[clap(long)]
pub deterministic_seed: Option<u64>,
#[clap(long, value_parser = ValueParser::new(SerdeJsonParser))]
pub error_pattern: Option<serde_json::Value>,
}
#[derive(Parser, Clone, Debug)]
pub struct ServerParameters {
#[clap(short = 'p', long, default_value_t = 8066)]
pub port: i32,
#[clap(short = 'a', long, default_value_t = ("127.0.0.1").to_string())]
pub addr: String,
#[clap(short = 'r', long, default_value_t = ("/").to_string())]
pub root_url: String,
}