Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 44 additions & 6 deletions source/compiler/qsc/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use qdk_simulators::noise_config::NoiseConfig;
use qsc_circuit::{
Circuit, CircuitTracer, TracerConfig,
operations::{entry_expr_for_qubit_operation, qubit_param_info},
rir_to_circuit::rir_to_circuit,
rir_to_circuit::rir_to_circuit_with_noise,
};
use qsc_codegen::qir::{
fir_to_qir, fir_to_qir_from_callable, fir_to_rir, fir_to_rir_from_callable,
Expand Down Expand Up @@ -1319,6 +1319,23 @@ impl Interpreter {
entry: CircuitEntryPoint,
method: CircuitGenerationMethod,
tracer_config: TracerConfig,
) -> std::result::Result<Circuit, Vec<Error>> {
self.circuit_with_noise(
entry,
method,
tracer_config,
None,
qsc_circuit::ErrorDisplayConfig::default(),
)
}

pub fn circuit_with_noise(
&mut self,
entry: CircuitEntryPoint,
method: CircuitGenerationMethod,
tracer_config: TracerConfig,
noise_config: Option<&NoiseConfig<f64, f64>>,
error_display: qsc_circuit::ErrorDisplayConfig,
) -> std::result::Result<Circuit, Vec<Error>> {
let (entry_expr, qubit_params, invoke_params) = match entry {
CircuitEntryPoint::Operation(operation_expr) => {
Expand Down Expand Up @@ -1395,9 +1412,20 @@ impl Interpreter {
}
CircuitGenerationMethod::Static => {
if let Some((callable, args)) = invoke_params {
return self.static_circuit_from_callable(&callable, args, tracer_config);
return self.static_circuit_from_callable(
&callable,
args,
tracer_config,
noise_config,
error_display,
);
}
return self.static_circuit(entry_expr.as_deref(), tracer_config);
return self.static_circuit(
entry_expr.as_deref(),
tracer_config,
noise_config,
error_display,
);
}
}
let circuit = tracer.finish(&(self.compiler.package_store(), &self.fir_store));
Expand All @@ -1408,17 +1436,21 @@ impl Interpreter {
&mut self,
entry_expr: Option<&str>,
tracer_config: TracerConfig,
noise_config: Option<&NoiseConfig<f64, f64>>,
error_display: qsc_circuit::ErrorDisplayConfig,
) -> std::result::Result<Circuit, Vec<Error>> {
if self.capabilities > Profile::AdaptiveRIF.into() {
return Err(vec![Error::UnsupportedRuntimeCapabilities]);
}

let (program, fir_store) = self.compile_to_rir_with_debug_metadata(entry_expr)?;
rir_to_circuit(
rir_to_circuit_with_noise(
&program,
tracer_config,
&[self.package, self.source_package],
&(self.compiler.package_store(), &fir_store),
noise_config,
error_display,
)
.map_err(|e| vec![e.into()])
}
Expand All @@ -1428,6 +1460,8 @@ impl Interpreter {
callable: &Value,
args: Value,
tracer_config: TracerConfig,
noise_config: Option<&NoiseConfig<f64, f64>>,
error_display: qsc_circuit::ErrorDisplayConfig,
) -> std::result::Result<Circuit, Vec<Error>> {
if self.capabilities > Profile::AdaptiveRIF.into() {
return Err(vec![Error::UnsupportedRuntimeCapabilities]);
Expand Down Expand Up @@ -1462,11 +1496,13 @@ impl Interpreter {
)
.map_err(|e| self.partial_evaluation_error(e))?;

rir_to_circuit(
rir_to_circuit_with_noise(
&transformed,
tracer_config,
&[self.package, self.source_package],
&(self.compiler.package_store(), &fir_store),
noise_config,
error_display,
)
.map_err(|e| vec![e.into()])
}
Expand All @@ -1489,11 +1525,13 @@ impl Interpreter {
)
.map_err(|e| self.partial_evaluation_error(e))?;

rir_to_circuit(
rir_to_circuit_with_noise(
&transformed,
tracer_config,
&[self.package, self.source_package],
&(self.compiler.package_store(), &fir_store),
noise_config,
error_display,
)
.map_err(|e| vec![e.into()])
}
Expand Down
2 changes: 1 addition & 1 deletion source/compiler/qsc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub use qsc_doc_gen::{display, generate_docs};

pub mod circuit {
pub use qsc_circuit::{
CURRENT_VERSION, Circuit, CircuitGroup, TracerConfig,
CURRENT_VERSION, Circuit, CircuitGroup, ErrorDisplayConfig, GateErrorMode, TracerConfig,
circuit_to_qsharp::{circuit_to_standalone_qsharp, circuits_to_qsharp},
json_to_circuit::json_to_circuits,
operations::*,
Expand Down
1 change: 1 addition & 0 deletions source/compiler/qsc_circuit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ log = { workspace = true }
miette = { workspace = true }
num-bigint = { workspace = true }
num-complex = { workspace = true }
qdk_simulators = { path = "../../simulators", default-features = false }
qsc_codegen = { path = "../qsc_codegen" }
qsc_eval = { path = "../qsc_eval" }
qsc_data_structures = { path = "../qsc_data_structures" }
Expand Down
11 changes: 10 additions & 1 deletion source/compiler/qsc_circuit/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl Tracer for CircuitTracer {
classical_controls: &[],
},
display_args,
None,
called_at,
);
}
Expand Down Expand Up @@ -156,6 +157,7 @@ impl Tracer for CircuitTracer {
} else {
vec![classical_args]
},
None,
LogicalStack::from_evaluator_trace(stack),
);
}
Expand Down Expand Up @@ -1244,6 +1246,7 @@ impl OperationOrGroup {
targets: &[QubitWire],
controls: Vec<ControlRegister>,
args: Vec<String>,
error: Option<crate::circuit::GateErrorInfo>,
) -> Self {
Self::new_single(Operation::Unitary(Unitary {
gate: name.to_string(),
Expand All @@ -1260,6 +1263,7 @@ impl OperationOrGroup {
is_adjoint,
is_conditional: false,
metadata: None,
error,
}))
}

Expand Down Expand Up @@ -1414,6 +1418,7 @@ impl OperationOrGroup {
is_adjoint: false,
metadata,
is_conditional: false,
error: None,
}),
location: None,
}
Expand Down Expand Up @@ -1644,13 +1649,15 @@ pub(crate) struct ClassicalControlInput {
/// Trait representing a receiver of circuit operations that can accept
/// gates, measurements, and resets into an internal operation list.
pub(crate) trait OperationReceiver {
#[allow(clippy::too_many_arguments)]
fn gate(
&mut self,
wire_map: &WireMap,
name: &str,
is_adjoint: bool,
inputs: &GateInputs,
args: Vec<String>,
error: Option<crate::circuit::GateErrorInfo>,
call_stack: LogicalStack,
);

Expand All @@ -1667,13 +1674,15 @@ pub(crate) trait OperationReceiver {
}

impl OperationReceiver for OperationListBuilder {
#[allow(clippy::too_many_arguments)]
fn gate(
&mut self,
wire_map: &WireMap,
name: &str,
is_adjoint: bool,
inputs: &GateInputs,
args: Vec<String>,
error: Option<crate::circuit::GateErrorInfo>,
call_stack: LogicalStack,
) {
let targets = inputs
Expand All @@ -1697,7 +1706,7 @@ impl OperationReceiver for OperationListBuilder {
}))
.collect::<Vec<_>>();
self.push_op(
OperationOrGroup::new_unitary(name, is_adjoint, &targets, controls, args),
OperationOrGroup::new_unitary(name, is_adjoint, &targets, controls, args, error),
call_stack,
wire_map,
);
Expand Down
17 changes: 17 additions & 0 deletions source/compiler/qsc_circuit/src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,23 @@ pub struct Unitary {
pub is_conditional: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<GateErrorInfo>,
}

#[derive(Clone, Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct GateErrorInfo {
// Error associated with the entire gate.
// For example, probability of gate failure.
pub gate_error: f64,

// Errors associated with registers the gates acts on.
// These will be displayed on circuit after gate application.
// For example, these can be a probability that qubit is lost
// after this gate application.
// Registers refenced here must be among `targets` or `controls`.
pub output_errors: Vec<(Register, f64)>,
}

#[derive(Clone, Deserialize, Debug, Eq, PartialEq)]
Expand Down
6 changes: 6 additions & 0 deletions source/compiler/qsc_circuit/src/circuit/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ fn unitary(gate: &str, targets: Vec<Register>) -> Operation {
children: vec![],
metadata: None,
is_conditional: false,
error: None,
})
}

Expand All @@ -80,6 +81,7 @@ fn ctl_unitary(gate: &str, targets: Vec<Register>, controls: Vec<Register>) -> O
children: vec![],
metadata: None,
is_conditional: false,
error: None,
})
}

Expand All @@ -93,6 +95,7 @@ fn unitary_with_children(gate: &str, targets: Vec<Register>, children: Component
children,
metadata: None,
is_conditional: false,
error: None,
})
}

Expand All @@ -111,6 +114,7 @@ fn ctl_unitary_with_children(
children,
metadata: None,
is_conditional: false,
error: None,
})
}

Expand Down Expand Up @@ -249,6 +253,7 @@ fn with_args() {
is_conditional: false,
children: vec![],
metadata: None,
error: None,
})]]),
};

Expand All @@ -271,6 +276,7 @@ fn two_targets() {
targets: vec![Register::quantum(0), Register::quantum(2)],
children: vec![],
metadata: None,
error: None,
})]]),
};

Expand Down
2 changes: 2 additions & 0 deletions source/compiler/qsc_circuit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
mod angle_format;
mod builder;
mod circuit;
mod loss;
pub mod operations;

pub use builder::{CircuitTracer, TracerConfig};
pub use circuit::{
CURRENT_VERSION, Circuit, CircuitGroup, ComponentColumn, Operation, operation_list_to_grid,
};
pub use operations::Error;
pub use rir_to_circuit::{ErrorDisplayConfig, GateErrorMode};
pub mod circuit_to_qsharp;
pub mod json_to_circuit;
pub mod rir_to_circuit;
Loading
Loading