microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
source/npm/qsharp/ux/circuit-vis/formatters/inputFormatter.ts
115lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT license. |
| 3 | |
| 4 | import { Qubit, SourceLocation } from "../circuit.js"; |
| 5 | import { RegisterType, RegisterMap, RegisterRenderData } from "../register.js"; |
| 6 | import { |
| 7 | leftPadding, |
| 8 | startY, |
| 9 | registerHeight, |
| 10 | classicalRegHeight, |
| 11 | } from "../constants.js"; |
| 12 | import { createSvgElement, group, text } from "./formatUtils.js"; |
| 13 | import { mathChars } from "../utils.js"; |
| 14 | |
| 15 | /** |
| 16 | * `formatInputs` takes in an array of Qubits and outputs the SVG string of formatted |
| 17 | * qubit wires and a mapping from register IDs to register rendering data. |
| 18 | * |
| 19 | * @param qubits List of declared qubits. |
| 20 | * |
| 21 | * @returns returns the SVG string of formatted qubit wires, a mapping from registers |
| 22 | * to y coord and total SVG height. |
| 23 | */ |
| 24 | const formatInputs = ( |
| 25 | qubits: Qubit[], |
| 26 | renderLocations?: (s: SourceLocation[]) => { title: string; href: string }, |
| 27 | ): { qubitWires: SVGElement; registers: RegisterMap; svgHeight: number } => { |
| 28 | const qubitWires: SVGElement[] = []; |
| 29 | const registers: RegisterMap = {}; |
| 30 | |
| 31 | let currY: number = startY; |
| 32 | qubits.forEach(({ id, numResults, declarations }, wireIndex) => { |
| 33 | const link: { link?: { href: string; title: string } } = {}; |
| 34 | if (renderLocations && declarations && declarations.length > 0) { |
| 35 | link.link = renderLocations(declarations); |
| 36 | } |
| 37 | |
| 38 | // Add qubit wire to list of qubit wires |
| 39 | qubitWires.push(qubitInput(currY, wireIndex, id.toString(), link.link)); |
| 40 | |
| 41 | // Create qubit register |
| 42 | registers[id] = { type: RegisterType.Qubit, y: currY }; |
| 43 | |
| 44 | // If there are no attached classical registers, increment y by fixed register height |
| 45 | if (numResults == null || numResults === 0) { |
| 46 | currY += registerHeight; |
| 47 | return; |
| 48 | } |
| 49 | |
| 50 | // Increment current height by classical register height for attached classical registers |
| 51 | currY += classicalRegHeight; |
| 52 | |
| 53 | // Add classical wires |
| 54 | registers[id].children = Array.from(Array(numResults), () => { |
| 55 | const clsReg: RegisterRenderData = { |
| 56 | type: RegisterType.Classical, |
| 57 | y: currY, |
| 58 | }; |
| 59 | currY += classicalRegHeight; |
| 60 | return clsReg; |
| 61 | }); |
| 62 | }); |
| 63 | |
| 64 | return { |
| 65 | qubitWires: group(qubitWires, { class: "qubit-input-states" }), |
| 66 | registers, |
| 67 | svgHeight: currY, |
| 68 | }; |
| 69 | }; |
| 70 | |
| 71 | /** |
| 72 | * Generate the SVG text component for the input qubit register. |
| 73 | * |
| 74 | * @param y y coord of input wire to render in SVG. |
| 75 | * |
| 76 | * @returns SVG text component for the input register. |
| 77 | */ |
| 78 | const qubitInput = ( |
| 79 | y: number, |
| 80 | wireIndex: number, |
| 81 | subscript?: string, |
| 82 | link?: { href: string; title: string }, |
| 83 | ): SVGElement => { |
| 84 | const el: SVGElement = text("", leftPadding, y, 16); |
| 85 | |
| 86 | const subtext = subscript |
| 87 | ? `<tspan baseline-shift="sub" font-size="65%">${subscript}</tspan>` |
| 88 | : ""; |
| 89 | |
| 90 | el.innerHTML = `|<tspan class="qs-mathtext">${mathChars.psi}</tspan>${subtext}${mathChars.rangle}</tspan>`; |
| 91 | |
| 92 | el.setAttribute("text-anchor", "start"); |
| 93 | el.setAttribute("dominant-baseline", "middle"); |
| 94 | el.setAttribute("data-wire", wireIndex.toString()); |
| 95 | el.classList.add("qs-maintext", "qs-qubit-label"); |
| 96 | |
| 97 | if (link) { |
| 98 | const linkElem = createSvgElement("a", { |
| 99 | href: link.href, |
| 100 | class: "qs-circuit-source-link", |
| 101 | }); |
| 102 | |
| 103 | // Add title as a child <title> element for accessibility and hover tooltip |
| 104 | const titleElem = createSvgElement("title"); |
| 105 | titleElem.textContent = link.title; |
| 106 | linkElem.appendChild(titleElem); |
| 107 | |
| 108 | // Add the gate as a child of the link |
| 109 | linkElem.appendChild(el); |
| 110 | return linkElem; |
| 111 | } |
| 112 | return el; |
| 113 | }; |
| 114 | |
| 115 | export { formatInputs, qubitInput }; |