1use std::path::PathBuf;
18use std::sync::Arc;
19
20use glam::IVec3;
21use thiserror::Error;
22
23mod action;
24mod action_dag;
25mod block;
26mod branch;
27mod cancellation;
28#[doc(hidden)]
29pub mod composition;
30mod gallery;
31#[cfg(feature = "gltf")]
32mod gltf;
33mod graph;
34mod guarded;
35mod height;
36pub use composition::ModuleJoinOptions;
37mod module_view;
38mod parser;
39mod program;
40mod summary;
41pub(crate) mod validate;
42#[cfg(feature = "verify")]
43pub mod verify;
44#[cfg(feature = "verify")]
45pub use verify::feedback::{
46 FeedbackInferenceError, FeedbackOptions, infer_feedback, infer_feedback_with,
47};
48mod zx;
49
50pub use action::{Action, BinaryOp, Expr, FeedbackTarget, MeasureTarget};
51pub use action_dag::{
52 ActionDag, ActionDependency, ActionNode, ActionOwner, MeasurementObservable,
53 ResolveDomainError, ResolveValueDomain,
54};
55pub use block::{
56 Block, BlockError, BlockKind, CubeKind, PatchRotationKind, Pipe, SelectiveKind,
57 WalkingBoundaryKind, WalkingKind, is_valid_tag,
58};
59#[doc(no_inline)]
63pub use bloq_utils::{
64 Basis, Direction, DirectionParseError, Pauli, PauliBasis, PauliError, PauliString,
65 PhasedPauliString, PortRole, RGBA, UDirection,
66};
67pub use branch::{Branch, BranchArm, BranchCut, BranchProjection, BranchRegion};
68pub use cancellation::{CancellationToken, ComputationCancelled};
69pub use gallery::{GalleryCategory, GalleryEntry, GalleryItem};
70#[cfg(feature = "gltf")]
71pub use gltf::{
72 EDITOR_AMBIENT_BRIGHTNESS, EDITOR_DIRECTIONAL_ILLUMINANCE, GltfData, GltfFaceSelector,
73 block_as_gltf_data, block_as_gltf_data_with_pipe_length, block_graph_as_gltf_data,
74 block_graph_as_gltf_data_with_popped_faces, pipe_as_gltf_data,
75 pipe_between_positions_as_gltf_data, stabilizer_as_gltf_data,
76};
77pub use graph::{AnalyzedBranchProjections, BlockGraph, BlockLayerView};
78pub use guarded::{GuardedProjection, GuardedTopology, GuardedVariable, selective_selector_name};
79pub use height::{CubeHeight, MAX_CUBE_HEIGHT_CELLS};
80pub use module_view::{ModuleView, ModuleViewModule, module_color};
81#[cfg(test)]
82pub(crate) use parser::load_graph_with_resolver_and_limits;
83#[cfg(test)]
84pub(crate) use parser::parse_inline_graph;
85pub(crate) use parser::parse_inline_graph_with_limits;
86pub use parser::{
87 ParseError, ast, lower_blog_ast_deferred, lower_blog_ast_lenient,
88 lower_blog_graph_ast_deferred, parse_actions, parse_blog_program_to_ast, parse_blog_to_ast,
89 parse_blog_to_graph, parse_blog_to_graph_with_limits,
90};
91pub use program::{
92 BitBinding, BitOutput, BitRef, InstancePort, LeafModuleCertificate, LinkedModuleDefinition,
93 MaterializedModuleSite, ModuleCertificationError, ModuleCertificationLimits, ModuleError,
94 ModuleInstance, ModuleInterface, ModuleOrientation, ModuleRotation, PortDirection,
95 QuantumConnection, QuantumPort, UnknownCertificationLimit, flatten_module_definition,
96 qualified_name,
97};
98pub use summary::{ModuleSummary, default_module_jobs, map_jobs};
99#[doc(no_inline)]
103pub use rustc_hash::FxHashMap;
104pub use validate::{InvalidActionError, InvalidBlockGraphError};
105pub use zx::{
106 DerivedSurface, FillPortsError, GuardedLocalSurface, GuardedReadoutPlan, GuardedSurface,
107 GuardedSurfaceKind, GuardedSurfaceSpace, LocalPauliSurface, NamedReadout, NodeKind,
108 OutputCorrectionError, OutputCorrectionRow, ReadoutCoordinates, ReadoutPlan, RuntimeBasisError,
109 RuntimeStabilizerBasis, SelectiveFixing, SelectiveFixingTarget, SelectiveFixings, Stabilizer,
110 StabilizerError, StabilizerGenerator, StabilizerGenerators, StabilizerRowKind, SurfaceSupport,
111 SymbolicBasisError, SymbolicFramePair, SymbolicOutputCorrection, SymbolicSite,
112 SymbolicStabilizerBasis, ZXEdge, ZXError, ZXGraph, ZXLayerView, ZXNode, selective_fixings,
113 solve_output_correction_symbolic, solve_output_correction_symbolic_prefix,
114};
115
116pub mod prelude {
120 #[doc(no_inline)]
121 pub use crate::{
122 Block, BlockGraph, BlockGraphError, BlockKind, Branch, BranchArm, CubeHeight, CubeKind,
123 GalleryItem, Pipe, parse_blog_to_graph,
124 };
125 #[doc(no_inline)]
126 pub use bloq_utils::{
127 Basis, Direction, Pauli, PauliBasis, PauliString, PortRole, RGBA, UDirection,
128 };
129}
130
131#[derive(Error, Debug, Clone)]
134#[non_exhaustive]
135pub enum BlockGraphError {
136 #[error("block already exists at position {0}")]
138 BlockExists(IVec3),
139 #[error("block footprint would overlap occupied position {0}")]
141 BlockPositionOccupied(IVec3),
142 #[error("module block footprints conflict at cell {position}: {first}; {second}")]
144 ModuleBlockOverlap {
145 position: IVec3,
147 first: Arc<MaterializedModuleSite>,
149 second: Arc<MaterializedModuleSite>,
151 },
152 #[error("no block found at position {0}")]
154 BlockNotFound(IVec3),
155 #[error(
157 "invalid tag `{tag}`: tags must be non-empty and contain no whitespace, controls, `<`, or `>`"
158 )]
159 InvalidTag {
160 tag: String,
162 },
163 #[error("no pipe found between positions {0} and {1}")]
165 PipeNotFound(IVec3, IVec3),
166 #[error("pipe already exists between positions {0} and {1}")]
168 PipeExists(IVec3, IVec3),
169 #[error("coordinate overflow while adding offset {offset} to position {position}")]
171 CoordinateOverflow {
172 position: IVec3,
174 offset: IVec3,
176 },
177 #[error(
179 "cannot normalize z span {min_z}..={max_z} to start at zero within the i32 coordinate range"
180 )]
181 CoordinateNormalizationOverflow {
182 min_z: i32,
184 max_z: i32,
186 },
187 #[error("rotation of {position} negates unrepresentable {axis} component")]
189 CoordinateRotationOverflow {
190 position: IVec3,
192 axis: UDirection,
194 },
195 #[error("measurement edge from {0} to {1} does not infer a time basis")]
197 MeasurementEdgeMissingTimeBasis(IVec3, IVec3),
198 #[error("{0}")]
200 Invalid(#[from] validate::InvalidBlockGraphError),
201 #[error("{0}")]
203 InvalidAction(#[from] validate::InvalidActionError),
204 #[error("I/O error at {path}: {source}")]
206 Io {
207 path: PathBuf,
209 #[source]
211 source: Arc<std::io::Error>,
212 },
213 #[error("{0}")]
215 Block(#[from] block::BlockError),
216 #[error("{0}")]
218 Parse(#[from] parser::ParseError),
219 #[error("{0}")]
221 ModuleSource(#[source] Arc<ModuleError>),
222 #[error("{operation} requires a flat graph; call BlockGraph::flatten() explicitly first")]
224 HierarchyRequiresFlatten {
225 operation: &'static str,
227 },
228 #[error("{0}")]
230 ModuleMaterialization(#[source] Arc<ModuleCertificationError>),
231 #[error("{0}")]
233 Zx(#[from] zx::ZXError),
234 #[error("{0}")]
236 FillPorts(#[from] zx::FillPortsError),
237 #[error("{0}")]
239 Stabilizer(#[from] zx::StabilizerError),
240 #[cfg(feature = "gltf")]
241 #[error("glTF JSON serialization failed")]
243 GltfSerialize(#[source] Arc<gltf_json::Error>),
244 #[error("T and Selective blocks can only rotate around the time axis")]
246 RotationUnsupportedDynamicBlocks,
247 #[error("block graphs containing Y blocks can only rotate in 180-degree increments")]
249 RotationRequiresHalfTurns,
250 #[error("Walking and PatchRotation blocks can only rotate around the time axis")]
252 RotationWalkingRequiresTimeAxis,
253 #[error("cube blocks with a non-default height can only rotate around the time axis")]
255 RotationCubeHeightRequiresTimeAxis,
256}
257
258impl From<bloq_utils::boolean::BooleanResourceError> for StabilizerError {
259 fn from(error: bloq_utils::boolean::BooleanResourceError) -> Self {
260 Self::ResourceLimited {
261 phase: error.resource,
262 observed: error.observed,
263 limit: error.limit,
264 }
265 }
266}
267
268impl From<bloq_utils::boolean::BooleanResourceError> for BlockGraphError {
269 fn from(error: bloq_utils::boolean::BooleanResourceError) -> Self {
270 StabilizerError::from(error).into()
271 }
272}
273
274impl From<bloq_utils::boolean::BooleanResourceError> for RuntimeBasisError {
275 fn from(error: bloq_utils::boolean::BooleanResourceError) -> Self {
276 StabilizerError::from(error).into()
277 }
278}
279
280impl BlockGraphError {
281 pub fn is_incomplete_action_program(&self) -> bool {
283 matches!(
284 self,
285 Self::InvalidAction(
286 InvalidActionError::UndefinedVariable(_)
287 | InvalidActionError::MissingResolveForSelective { .. }
288 | InvalidActionError::MissingResolveForBranch(_)
289 )
290 )
291 }
292}
293
294pub fn checked_add_position(position: IVec3, offset: IVec3) -> Result<IVec3, BlockGraphError> {
300 let Some(x) = position.x.checked_add(offset.x) else {
301 return Err(BlockGraphError::CoordinateOverflow { position, offset });
302 };
303 let Some(y) = position.y.checked_add(offset.y) else {
304 return Err(BlockGraphError::CoordinateOverflow { position, offset });
305 };
306 let Some(z) = position.z.checked_add(offset.z) else {
307 return Err(BlockGraphError::CoordinateOverflow { position, offset });
308 };
309 Ok(IVec3::new(x, y, z))
310}