microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.23.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/npm/qsharp/src/data-structures/circuit.ts

288lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT license.
3
4import { isRegister, Register } from "./register.js";
5
6/**
7 * Current format version.
8 */
9export const CURRENT_VERSION = 1;
10
11export interface CircuitGroup {
12 circuits: Circuit[];
13 version: number;
14}
15
16/**
17 * Runtime check: is this a valid CircuitGroup?
18 */
19export function isCircuitGroup(obj: any): obj is CircuitGroup {
20 return (
21 obj &&
22 typeof obj === "object" &&
23 typeof obj.version === "number" &&
24 Array.isArray(obj.circuits) &&
25 obj.circuits.length > 0 &&
26 obj.circuits.every(isCircuit)
27 );
28}
29
30/**
31 * Circuit to be visualized.
32 */
33export interface Circuit {
34 /** Array of qubit resources. */
35 qubits: Qubit[];
36 componentGrid: ComponentGrid;
37}
38
39/**
40 * Runtime check: is this a valid Circuit?
41 */
42export function isCircuit(obj: any): obj is Circuit {
43 return (
44 obj &&
45 typeof obj === "object" &&
46 Array.isArray(obj.qubits) &&
47 obj.qubits.every(isQubit) &&
48 Array.isArray(obj.componentGrid) &&
49 obj.componentGrid.every(isColumn)
50 );
51}
52
53export type ComponentGrid = Column[];
54
55export interface Column {
56 components: Component[];
57}
58
59/**
60 * Runtime check: is this a valid Column?
61 */
62export function isColumn(obj: any): obj is Column {
63 return (
64 obj &&
65 typeof obj === "object" &&
66 Array.isArray(obj.components) &&
67 obj.components.every(isOperation)
68 );
69}
70
71/**
72 * Represents a component of a circuit. Currently, the only component is an operation.
73 * In the future, this may be extended to include other components.
74 */
75export type Component = Operation;
76
77/**
78 * Represents a unique qubit resource bit.
79 */
80export interface Qubit {
81 /** Qubit ID. */
82 id: number;
83 /** Number of measurement results associated to the qubit. */
84 numResults?: number;
85 /** Declaration locations in the source code. */
86 declarations?: SourceLocation[];
87}
88
89/**
90 * Runtime check: is this a valid Qubit?
91 */
92export function isQubit(obj: any): obj is Qubit {
93 return (
94 obj &&
95 typeof obj === "object" &&
96 typeof obj.id === "number" &&
97 // numResults is optional, but if present must be a number
98 (obj.numResults === undefined || typeof obj.numResults === "number")
99 );
100}
101
102/**
103 * Base type for operations.
104 */
105export interface BaseOperation {
106 /** Gate label. */
107 gate: string;
108 /** Formatted gate arguments. */
109 args?: string[];
110 /** The parameters expected for the operation. */
111 params?: Parameter[];
112 /** Nested operations within this operation. */
113 children?: ComponentGrid;
114
115 /** Custom data attributes to attach to gate element.
116 Note that this is never written to file, so it is not part of the circuit schema */
117 dataAttributes?: DataAttributes;
118
119 /** Whether gate is a conditional operation. */
120 isConditional?: boolean;
121 /** Specify conditions on when to render operation. */
122 conditionalRender?: ConditionalRender;
123
124 /** Not written to file */
125 metadata?: Metadata;
126}
127
128/**
129 * Runtime check: is this a valid BaseOperation?
130 */
131function isBaseOperation(obj: any): obj is BaseOperation {
132 return (
133 obj &&
134 typeof obj === "object" &&
135 typeof obj.gate === "string" &&
136 // args is optional, but if present must be an array of strings
137 (obj.args === undefined ||
138 (Array.isArray(obj.args) &&
139 obj.args.every((arg: any) => typeof arg === "string"))) &&
140 // params is optional, but if present must be an array of Parameter
141 (obj.params === undefined ||
142 (Array.isArray(obj.params) && obj.params.every(isParameter))) &&
143 // children is optional, but if present must be a ComponentGrid
144 (obj.children === undefined ||
145 (Array.isArray(obj.children) && obj.children.every(isColumn))) &&
146 // dataAttributes is optional, but if present must be an object with string values
147 (obj.dataAttributes === undefined ||
148 (typeof obj.dataAttributes === "object" &&
149 obj.dataAttributes !== null &&
150 Object.values(obj.dataAttributes).every(
151 (val) => typeof val === "string",
152 ))) &&
153 // isConditional is optional, but if present must be boolean
154 (obj.isConditional === undefined ||
155 typeof obj.isConditional === "boolean") &&
156 // conditionalRender is optional, but if present must be a valid enum value
157 (obj.conditionalRender === undefined ||
158 Object.values(ConditionalRender).includes(obj.conditionalRender))
159 );
160}
161
162/**
163 * Represents a measurement operation and the registers it acts on.
164 */
165export interface Measurement extends BaseOperation {
166 /** Discriminator for the Operation type */
167 kind: "measurement";
168 /** The qubit registers the gate measures. */
169 qubits: Register[];
170 /** The classical registers the gate writes to. */
171 results: Register[];
172}
173
174/**
175 * Represents a unitary operation and the registers it acts on.
176 */
177export interface Unitary extends BaseOperation {
178 /** Discriminator for the Operation type */
179 kind: "unitary";
180 /** Target registers the gate acts on. */
181 targets: Register[];
182 /** Control registers the gate acts on. */
183 controls?: Register[];
184 /** Whether gate is an adjoint operation. */
185 isAdjoint?: boolean;
186}
187
188/**
189 * Represents a gate that sets its targets to a specific state.
190 */
191export interface Ket extends BaseOperation {
192 /** Discriminator for the Operation type */
193 kind: "ket";
194 /** Target registers the gate acts on. */
195 targets: Register[];
196}
197
198/**
199 * Union type for operations.
200 */
201export type Operation = Unitary | Measurement | Ket;
202
203/**
204 * Runtime check: is this a valid Operation?
205 */
206export function isOperation(obj: any): obj is Operation {
207 if (!isBaseOperation(obj)) return false;
208 // Re-cast to any so we can check discriminated fields without narrowing
209 const op: any = obj;
210 if (op.kind === undefined || typeof op.kind !== "string") return false;
211 switch (op.kind) {
212 case "unitary":
213 return (
214 Array.isArray(op.targets) &&
215 op.targets.every(isRegister) &&
216 // controls is optional
217 (op.controls === undefined ||
218 (Array.isArray(op.controls) && op.controls.every(isRegister))) &&
219 // isAdjoint is optional
220 (op.isAdjoint === undefined || typeof op.isAdjoint === "boolean")
221 );
222 case "measurement":
223 return (
224 Array.isArray(op.qubits) &&
225 op.qubits.every(isRegister) &&
226 Array.isArray(op.results) &&
227 op.results.every(isRegister)
228 );
229 case "ket":
230 return Array.isArray(op.targets) && op.targets.every(isRegister);
231 default:
232 return false;
233 }
234}
235
236/**
237 * A parameter for an operation.
238 */
239export interface Parameter {
240 /** Parameter name. */
241 name: string;
242 /** Parameter's Q# type. */
243 type: string;
244}
245
246/**
247 * Runtime check: is this a valid Parameter?
248 */
249export function isParameter(obj: any): obj is Parameter {
250 return (
251 obj &&
252 typeof obj === "object" &&
253 typeof obj.name === "string" &&
254 typeof obj.type === "string"
255 );
256}
257
258/**
259 * Conditions on when to render the given operation.
260 */
261export enum ConditionalRender {
262 /** Always rendered. */
263 Always,
264 /** Render classically-controlled operation when measurement is a zero. */
265 OnZero,
266 /** Render classically-controlled operation when measurement is a one. */
267 OnOne,
268 /** Render operation as a group of its nested operations. */
269 AsGroup,
270}
271
272/**
273 * Custom data attributes (e.g. data-{attr}="{val}")
274 */
275export interface DataAttributes {
276 [attr: string]: string;
277}
278
279export interface SourceLocation {
280 file: string;
281 line: number;
282 column: number;
283}
284
285export interface Metadata {
286 source?: SourceLocation;
287 scopeLocation?: SourceLocation;
288}
289