qsharp-lang 1.13.1-dev → 1.13.3-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/dist/browser.d.ts +1 -0
  2. package/dist/compiler/compiler.d.ts +3 -3
  3. package/dist/compiler/compiler.js +2 -2
  4. package/dist/debug-service/debug-service.d.ts +1 -1
  5. package/dist/katas-content.generated.js +1 -1
  6. package/dist/katas-content.generated.md.js +1 -1
  7. package/dist/shared/circuit.d.ts +64 -0
  8. package/dist/shared/circuit.js +16 -0
  9. package/dist/shared/register.d.ts +35 -0
  10. package/dist/shared/register.js +10 -0
  11. package/docs/Microsoft.Quantum.Core/Length.md +1 -1
  12. package/docs/Microsoft.Quantum.Core/Repeated.md +1 -1
  13. package/docs/Microsoft.Quantum.Core/index.md +1 -1
  14. package/docs/Std.Arithmetic/AddLE.md +1 -1
  15. package/docs/Std.Arithmetic/ApplyIfEqualL.md +1 -1
  16. package/docs/Std.Arithmetic/ApplyIfEqualLE.md +1 -1
  17. package/docs/Std.Arithmetic/ApplyIfGreaterL.md +1 -1
  18. package/docs/Std.Arithmetic/ApplyIfGreaterLE.md +1 -1
  19. package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualL.md +1 -1
  20. package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualLE.md +1 -1
  21. package/docs/Std.Arithmetic/ApplyIfLessL.md +1 -1
  22. package/docs/Std.Arithmetic/ApplyIfLessLE.md +1 -1
  23. package/docs/Std.Arithmetic/ApplyIfLessOrEqualL.md +1 -1
  24. package/docs/Std.Arithmetic/ApplyIfLessOrEqualLE.md +1 -1
  25. package/docs/Std.Arithmetic/FourierTDIncByLE.md +1 -1
  26. package/docs/Std.Arithmetic/IncByI.md +1 -1
  27. package/docs/Std.Arithmetic/IncByIUsingIncByLE.md +1 -1
  28. package/docs/Std.Arithmetic/IncByL.md +1 -1
  29. package/docs/Std.Arithmetic/IncByLE.md +1 -1
  30. package/docs/Std.Arithmetic/IncByLEUsingAddLE.md +1 -1
  31. package/docs/Std.Arithmetic/IncByLUsingIncByLE.md +1 -1
  32. package/docs/Std.Arithmetic/LookAheadDKRSAddLE.md +1 -1
  33. package/docs/Std.Arithmetic/MAJ.md +1 -1
  34. package/docs/Std.Arithmetic/ReflectAboutInteger.md +1 -1
  35. package/docs/Std.Arithmetic/RippleCarryCGAddLE.md +1 -1
  36. package/docs/Std.Arithmetic/RippleCarryCGIncByLE.md +1 -1
  37. package/docs/Std.Arithmetic/RippleCarryTTKIncByLE.md +1 -1
  38. package/docs/Std.Arithmetic/index.md +1 -1
  39. package/docs/Std.Arrays/All.md +1 -1
  40. package/docs/Std.Arrays/Any.md +1 -1
  41. package/docs/Std.Arrays/Chunks.md +1 -1
  42. package/docs/Std.Arrays/CircularlyShifted.md +1 -1
  43. package/docs/Std.Arrays/ColumnAt.md +1 -1
  44. package/docs/Std.Arrays/Count.md +1 -1
  45. package/docs/Std.Arrays/Diagonal.md +1 -1
  46. package/docs/Std.Arrays/DrawMany.md +1 -1
  47. package/docs/Std.Arrays/Enumerated.md +1 -1
  48. package/docs/Std.Arrays/Excluding.md +1 -1
  49. package/docs/Std.Arrays/Filtered.md +1 -1
  50. package/docs/Std.Arrays/FlatMapped.md +1 -1
  51. package/docs/Std.Arrays/Flattened.md +1 -1
  52. package/docs/Std.Arrays/Fold.md +1 -1
  53. package/docs/Std.Arrays/ForEach.md +1 -1
  54. package/docs/Std.Arrays/Head.md +1 -1
  55. package/docs/Std.Arrays/HeadAndRest.md +1 -1
  56. package/docs/Std.Arrays/IndexOf.md +1 -1
  57. package/docs/Std.Arrays/IndexRange.md +1 -1
  58. package/docs/Std.Arrays/Interleaved.md +1 -1
  59. package/docs/Std.Arrays/IsEmpty.md +1 -1
  60. package/docs/Std.Arrays/IsRectangularArray.md +1 -1
  61. package/docs/Std.Arrays/IsSorted.md +1 -1
  62. package/docs/Std.Arrays/IsSquareArray.md +1 -1
  63. package/docs/Std.Arrays/Mapped.md +1 -1
  64. package/docs/Std.Arrays/MappedByIndex.md +1 -1
  65. package/docs/Std.Arrays/MappedOverRange.md +1 -1
  66. package/docs/Std.Arrays/Most.md +1 -1
  67. package/docs/Std.Arrays/MostAndTail.md +1 -1
  68. package/docs/Std.Arrays/Padded.md +1 -1
  69. package/docs/Std.Arrays/Partitioned.md +1 -1
  70. package/docs/Std.Arrays/Rest.md +1 -1
  71. package/docs/Std.Arrays/Reversed.md +1 -1
  72. package/docs/Std.Arrays/SequenceI.md +1 -1
  73. package/docs/Std.Arrays/SequenceL.md +1 -1
  74. package/docs/Std.Arrays/Sorted.md +1 -1
  75. package/docs/Std.Arrays/Subarray.md +1 -1
  76. package/docs/Std.Arrays/Swapped.md +1 -1
  77. package/docs/Std.Arrays/Tail.md +1 -1
  78. package/docs/Std.Arrays/Transposed.md +1 -1
  79. package/docs/Std.Arrays/Unzipped.md +1 -1
  80. package/docs/Std.Arrays/Where.md +1 -1
  81. package/docs/Std.Arrays/Windows.md +1 -1
  82. package/docs/Std.Arrays/Zipped.md +1 -1
  83. package/docs/Std.Arrays/index.md +1 -1
  84. package/docs/Std.Canon/ApplyCNOTChain.md +1 -1
  85. package/docs/Std.Canon/ApplyControlledOnBitString.md +1 -1
  86. package/docs/Std.Canon/ApplyControlledOnInt.md +1 -1
  87. package/docs/Std.Canon/ApplyP.md +1 -1
  88. package/docs/Std.Canon/ApplyPauli.md +1 -1
  89. package/docs/Std.Canon/ApplyPauliFromBitString.md +1 -1
  90. package/docs/Std.Canon/ApplyPauliFromInt.md +1 -1
  91. package/docs/Std.Canon/ApplyQFT.md +1 -1
  92. package/docs/Std.Canon/ApplyToEach.md +1 -1
  93. package/docs/Std.Canon/ApplyToEachA.md +1 -1
  94. package/docs/Std.Canon/ApplyToEachC.md +1 -1
  95. package/docs/Std.Canon/ApplyToEachCA.md +1 -1
  96. package/docs/Std.Canon/ApplyXorInPlace.md +1 -1
  97. package/docs/Std.Canon/ApplyXorInPlaceL.md +1 -1
  98. package/docs/Std.Canon/CX.md +1 -1
  99. package/docs/Std.Canon/CY.md +1 -1
  100. package/docs/Std.Canon/CZ.md +1 -1
  101. package/docs/Std.Canon/Fst.md +1 -1
  102. package/docs/Std.Canon/Relabel.md +1 -1
  103. package/docs/Std.Canon/Snd.md +1 -1
  104. package/docs/Std.Canon/SwapReverseRegister.md +1 -1
  105. package/docs/Std.Canon/index.md +1 -1
  106. package/docs/Std.Convert/BigIntAsBoolArray.md +1 -1
  107. package/docs/Std.Convert/BoolArrayAsBigInt.md +1 -1
  108. package/docs/Std.Convert/BoolArrayAsInt.md +1 -1
  109. package/docs/Std.Convert/BoolArrayAsResultArray.md +1 -1
  110. package/docs/Std.Convert/BoolAsResult.md +1 -1
  111. package/docs/Std.Convert/ComplexAsComplexPolar.md +1 -1
  112. package/docs/Std.Convert/ComplexPolarAsComplex.md +1 -1
  113. package/docs/Std.Convert/DoubleAsStringWithPrecision.md +1 -1
  114. package/docs/Std.Convert/IntAsBigInt.md +1 -1
  115. package/docs/Std.Convert/IntAsBoolArray.md +1 -1
  116. package/docs/Std.Convert/IntAsDouble.md +1 -1
  117. package/docs/Std.Convert/ResultArrayAsBoolArray.md +1 -1
  118. package/docs/Std.Convert/ResultArrayAsInt.md +1 -1
  119. package/docs/Std.Convert/ResultAsBool.md +1 -1
  120. package/docs/Std.Convert/index.md +1 -1
  121. package/docs/Std.Core/Length.md +1 -1
  122. package/docs/Std.Core/Repeated.md +1 -1
  123. package/docs/Std.Core/index.md +1 -1
  124. package/docs/Std.Diagnostics/ApplyIdleNoise.md +1 -1
  125. package/docs/Std.Diagnostics/BitFlipNoise.md +1 -1
  126. package/docs/Std.Diagnostics/CheckAllZero.md +1 -1
  127. package/docs/Std.Diagnostics/CheckOperationsAreEqual.md +1 -1
  128. package/docs/Std.Diagnostics/CheckZero.md +1 -1
  129. package/docs/Std.Diagnostics/ConfigurePauliNoise.md +1 -1
  130. package/docs/Std.Diagnostics/DepolarizingNoise.md +1 -1
  131. package/docs/Std.Diagnostics/DumpMachine.md +1 -1
  132. package/docs/Std.Diagnostics/DumpOperation.md +1 -1
  133. package/docs/Std.Diagnostics/DumpRegister.md +1 -1
  134. package/docs/Std.Diagnostics/Fact.md +1 -1
  135. package/docs/Std.Diagnostics/NoNoise.md +1 -1
  136. package/docs/Std.Diagnostics/PhaseFlipNoise.md +1 -1
  137. package/docs/Std.Diagnostics/StartCountingFunction.md +1 -1
  138. package/docs/Std.Diagnostics/StartCountingOperation.md +1 -1
  139. package/docs/Std.Diagnostics/StartCountingQubits.md +1 -1
  140. package/docs/Std.Diagnostics/StopCountingFunction.md +1 -1
  141. package/docs/Std.Diagnostics/StopCountingOperation.md +1 -1
  142. package/docs/Std.Diagnostics/StopCountingQubits.md +1 -1
  143. package/docs/Std.Diagnostics/index.md +1 -1
  144. package/docs/Std.Intrinsic/AND.md +1 -1
  145. package/docs/Std.Intrinsic/ApplyUnitary.md +1 -1
  146. package/docs/Std.Intrinsic/CCNOT.md +1 -1
  147. package/docs/Std.Intrinsic/CNOT.md +1 -1
  148. package/docs/Std.Intrinsic/Exp.md +1 -1
  149. package/docs/Std.Intrinsic/H.md +1 -1
  150. package/docs/Std.Intrinsic/I.md +1 -1
  151. package/docs/Std.Intrinsic/M.md +1 -1
  152. package/docs/Std.Intrinsic/Measure.md +1 -1
  153. package/docs/Std.Intrinsic/Message.md +1 -1
  154. package/docs/Std.Intrinsic/R.md +1 -1
  155. package/docs/Std.Intrinsic/R1.md +1 -1
  156. package/docs/Std.Intrinsic/R1Frac.md +1 -1
  157. package/docs/Std.Intrinsic/RFrac.md +1 -1
  158. package/docs/Std.Intrinsic/Reset.md +1 -1
  159. package/docs/Std.Intrinsic/ResetAll.md +1 -1
  160. package/docs/Std.Intrinsic/Rx.md +1 -1
  161. package/docs/Std.Intrinsic/Rxx.md +1 -1
  162. package/docs/Std.Intrinsic/Ry.md +1 -1
  163. package/docs/Std.Intrinsic/Ryy.md +1 -1
  164. package/docs/Std.Intrinsic/Rz.md +1 -1
  165. package/docs/Std.Intrinsic/Rzz.md +1 -1
  166. package/docs/Std.Intrinsic/S.md +1 -1
  167. package/docs/Std.Intrinsic/SWAP.md +1 -1
  168. package/docs/Std.Intrinsic/T.md +1 -1
  169. package/docs/Std.Intrinsic/X.md +1 -1
  170. package/docs/Std.Intrinsic/Y.md +1 -1
  171. package/docs/Std.Intrinsic/Z.md +1 -1
  172. package/docs/Std.Intrinsic/index.md +1 -1
  173. package/docs/Std.Logical/Xor.md +1 -1
  174. package/docs/Std.Logical/index.md +1 -1
  175. package/docs/Std.Math/AbsComplex.md +1 -1
  176. package/docs/Std.Math/AbsComplexPolar.md +1 -1
  177. package/docs/Std.Math/AbsD.md +1 -1
  178. package/docs/Std.Math/AbsI.md +1 -1
  179. package/docs/Std.Math/AbsL.md +1 -1
  180. package/docs/Std.Math/AbsSquaredComplex.md +1 -1
  181. package/docs/Std.Math/AbsSquaredComplexPolar.md +1 -1
  182. package/docs/Std.Math/ApproximateFactorial.md +1 -1
  183. package/docs/Std.Math/ArcCos.md +1 -1
  184. package/docs/Std.Math/ArcCosh.md +1 -1
  185. package/docs/Std.Math/ArcSin.md +1 -1
  186. package/docs/Std.Math/ArcSinh.md +1 -1
  187. package/docs/Std.Math/ArcTan.md +1 -1
  188. package/docs/Std.Math/ArcTan2.md +1 -1
  189. package/docs/Std.Math/ArcTanh.md +1 -1
  190. package/docs/Std.Math/ArgComplex.md +1 -1
  191. package/docs/Std.Math/ArgComplexPolar.md +1 -1
  192. package/docs/Std.Math/Binom.md +1 -1
  193. package/docs/Std.Math/BitSizeI.md +1 -1
  194. package/docs/Std.Math/BitSizeL.md +1 -1
  195. package/docs/Std.Math/Ceiling.md +1 -1
  196. package/docs/Std.Math/Complex.md +1 -1
  197. package/docs/Std.Math/ComplexPolar.md +1 -1
  198. package/docs/Std.Math/ContinuedFractionConvergentI.md +1 -1
  199. package/docs/Std.Math/ContinuedFractionConvergentL.md +1 -1
  200. package/docs/Std.Math/Cos.md +1 -1
  201. package/docs/Std.Math/Cosh.md +1 -1
  202. package/docs/Std.Math/DivRemI.md +1 -1
  203. package/docs/Std.Math/DivRemL.md +1 -1
  204. package/docs/Std.Math/DividedByC.md +1 -1
  205. package/docs/Std.Math/DividedByCP.md +1 -1
  206. package/docs/Std.Math/E.md +1 -1
  207. package/docs/Std.Math/ExpModI.md +1 -1
  208. package/docs/Std.Math/ExpModL.md +1 -1
  209. package/docs/Std.Math/ExtendedGreatestCommonDivisorI.md +1 -1
  210. package/docs/Std.Math/ExtendedGreatestCommonDivisorL.md +1 -1
  211. package/docs/Std.Math/FactorialI.md +1 -1
  212. package/docs/Std.Math/FactorialL.md +1 -1
  213. package/docs/Std.Math/Floor.md +1 -1
  214. package/docs/Std.Math/GreatestCommonDivisorI.md +1 -1
  215. package/docs/Std.Math/GreatestCommonDivisorL.md +1 -1
  216. package/docs/Std.Math/HammingWeightI.md +1 -1
  217. package/docs/Std.Math/InverseModI.md +1 -1
  218. package/docs/Std.Math/InverseModL.md +1 -1
  219. package/docs/Std.Math/IsCoprimeI.md +1 -1
  220. package/docs/Std.Math/IsCoprimeL.md +1 -1
  221. package/docs/Std.Math/IsInfinite.md +1 -1
  222. package/docs/Std.Math/IsNaN.md +1 -1
  223. package/docs/Std.Math/LargestFixedPoint.md +1 -1
  224. package/docs/Std.Math/Lg.md +1 -1
  225. package/docs/Std.Math/Log.md +1 -1
  226. package/docs/Std.Math/Log10.md +1 -1
  227. package/docs/Std.Math/LogFactorialD.md +1 -1
  228. package/docs/Std.Math/LogGammaD.md +1 -1
  229. package/docs/Std.Math/LogOf2.md +1 -1
  230. package/docs/Std.Math/Max.md +1 -1
  231. package/docs/Std.Math/MaxD.md +1 -1
  232. package/docs/Std.Math/MaxI.md +1 -1
  233. package/docs/Std.Math/MaxL.md +1 -1
  234. package/docs/Std.Math/Min.md +1 -1
  235. package/docs/Std.Math/MinD.md +1 -1
  236. package/docs/Std.Math/MinI.md +1 -1
  237. package/docs/Std.Math/MinL.md +1 -1
  238. package/docs/Std.Math/MinusC.md +1 -1
  239. package/docs/Std.Math/MinusCP.md +1 -1
  240. package/docs/Std.Math/ModulusI.md +1 -1
  241. package/docs/Std.Math/ModulusL.md +1 -1
  242. package/docs/Std.Math/NegationC.md +1 -1
  243. package/docs/Std.Math/NegationCP.md +1 -1
  244. package/docs/Std.Math/PI.md +1 -1
  245. package/docs/Std.Math/PNorm.md +1 -1
  246. package/docs/Std.Math/PNormalized.md +1 -1
  247. package/docs/Std.Math/PlusC.md +1 -1
  248. package/docs/Std.Math/PlusCP.md +1 -1
  249. package/docs/Std.Math/PowC.md +1 -1
  250. package/docs/Std.Math/PowCP.md +1 -1
  251. package/docs/Std.Math/RealMod.md +1 -1
  252. package/docs/Std.Math/Round.md +1 -1
  253. package/docs/Std.Math/SignD.md +1 -1
  254. package/docs/Std.Math/SignI.md +1 -1
  255. package/docs/Std.Math/SignL.md +1 -1
  256. package/docs/Std.Math/Sin.md +1 -1
  257. package/docs/Std.Math/Sinh.md +1 -1
  258. package/docs/Std.Math/SmallestFixedPoint.md +1 -1
  259. package/docs/Std.Math/Sqrt.md +1 -1
  260. package/docs/Std.Math/SquaredNorm.md +1 -1
  261. package/docs/Std.Math/Tan.md +1 -1
  262. package/docs/Std.Math/Tanh.md +1 -1
  263. package/docs/Std.Math/TimesC.md +1 -1
  264. package/docs/Std.Math/TimesCP.md +1 -1
  265. package/docs/Std.Math/TrailingZeroCountI.md +1 -1
  266. package/docs/Std.Math/TrailingZeroCountL.md +1 -1
  267. package/docs/Std.Math/Truncate.md +1 -1
  268. package/docs/Std.Math/index.md +1 -1
  269. package/docs/Std.Measurement/MResetEachZ.md +1 -1
  270. package/docs/Std.Measurement/MResetX.md +1 -1
  271. package/docs/Std.Measurement/MResetY.md +1 -1
  272. package/docs/Std.Measurement/MResetZ.md +1 -1
  273. package/docs/Std.Measurement/MeasureAllZ.md +1 -1
  274. package/docs/Std.Measurement/MeasureEachZ.md +1 -1
  275. package/docs/Std.Measurement/MeasureInteger.md +1 -1
  276. package/docs/Std.Measurement/index.md +1 -1
  277. package/docs/Std.Random/DrawRandomBool.md +1 -1
  278. package/docs/Std.Random/DrawRandomDouble.md +1 -1
  279. package/docs/Std.Random/DrawRandomInt.md +1 -1
  280. package/docs/Std.Random/index.md +1 -1
  281. package/docs/Std.Range/IsRangeEmpty.md +1 -1
  282. package/docs/Std.Range/RangeEnd.md +1 -1
  283. package/docs/Std.Range/RangeReverse.md +1 -1
  284. package/docs/Std.Range/RangeStart.md +1 -1
  285. package/docs/Std.Range/RangeStep.md +1 -1
  286. package/docs/Std.Range/index.md +1 -1
  287. package/docs/Std.ResourceEstimation/AccountForEstimates.md +1 -1
  288. package/docs/Std.ResourceEstimation/AuxQubitCount.md +1 -1
  289. package/docs/Std.ResourceEstimation/BeginEstimateCaching.md +1 -1
  290. package/docs/Std.ResourceEstimation/BeginRepeatEstimates.md +1 -1
  291. package/docs/Std.ResourceEstimation/CczCount.md +1 -1
  292. package/docs/Std.ResourceEstimation/EndEstimateCaching.md +1 -1
  293. package/docs/Std.ResourceEstimation/EndRepeatEstimates.md +1 -1
  294. package/docs/Std.ResourceEstimation/MeasurementCount.md +1 -1
  295. package/docs/Std.ResourceEstimation/PSSPCLayout.md +1 -1
  296. package/docs/Std.ResourceEstimation/RepeatEstimates.md +1 -1
  297. package/docs/Std.ResourceEstimation/RotationCount.md +1 -1
  298. package/docs/Std.ResourceEstimation/RotationDepth.md +1 -1
  299. package/docs/Std.ResourceEstimation/SingleVariant.md +1 -1
  300. package/docs/Std.ResourceEstimation/TCount.md +1 -1
  301. package/docs/Std.ResourceEstimation/index.md +1 -1
  302. package/docs/Std.StatePreparation/ApproximatelyPreparePureStateCP.md +1 -1
  303. package/docs/Std.StatePreparation/PreparePureStateD.md +1 -1
  304. package/docs/Std.StatePreparation/index.md +1 -1
  305. package/docs/Std.TableLookup/Select.md +1 -1
  306. package/docs/Std.TableLookup/index.md +1 -1
  307. package/docs/index.md +1 -1
  308. package/lib/node/qsc_wasm.cjs +17 -14
  309. package/lib/node/qsc_wasm.d.cts +3 -6
  310. package/lib/node/qsc_wasm_bg.wasm +0 -0
  311. package/lib/web/qsc_wasm.d.ts +4 -7
  312. package/lib/web/qsc_wasm.js +17 -14
  313. package/lib/web/qsc_wasm_bg.wasm +0 -0
  314. package/package.json +1 -1
  315. package/ux/circuit-vis/README.md +1 -0
  316. package/ux/circuit-vis/circuit.ts +10 -0
  317. package/ux/circuit-vis/constants.ts +39 -0
  318. package/ux/circuit-vis/formatters/formatUtils.ts +220 -0
  319. package/ux/circuit-vis/formatters/gateFormatter.ts +557 -0
  320. package/ux/circuit-vis/formatters/inputFormatter.ts +78 -0
  321. package/ux/circuit-vis/formatters/registerFormatter.ts +118 -0
  322. package/ux/circuit-vis/index.ts +30 -0
  323. package/ux/circuit-vis/metadata.ts +56 -0
  324. package/ux/circuit-vis/process.ts +536 -0
  325. package/ux/circuit-vis/register.ts +9 -0
  326. package/ux/circuit-vis/sqore.ts +376 -0
  327. package/ux/circuit-vis/styles.ts +236 -0
  328. package/ux/circuit-vis/utils.ts +77 -0
  329. package/ux/circuit.tsx +2 -2
  330. package/ux/data.ts +1 -1
@@ -0,0 +1,536 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+
4
+ import {
5
+ minGateWidth,
6
+ startX,
7
+ gatePadding,
8
+ controlBtnOffset,
9
+ groupBoxPadding,
10
+ } from "./constants";
11
+ import { Operation, ConditionalRender } from "./circuit";
12
+ import { Metadata, GateType } from "./metadata";
13
+ import { Register, RegisterMap, RegisterType } from "./register";
14
+ import { getGateWidth } from "./utils";
15
+
16
+ /**
17
+ * Takes in a list of operations and maps them to `metadata` objects which
18
+ * contains information for formatting the corresponding SVG.
19
+ *
20
+ * @param operations Array of operations.
21
+ * @param registers Mapping from qubit IDs to register metadata.
22
+ *
23
+ * @returns An object containing `metadataList` (Array of Metadata objects) and
24
+ * `svgWidth` which is the width of the entire SVG.
25
+ */
26
+ const processOperations = (
27
+ operations: Operation[],
28
+ registers: RegisterMap,
29
+ ): { metadataList: Metadata[]; svgWidth: number } => {
30
+ if (operations.length === 0) return { metadataList: [], svgWidth: startX };
31
+
32
+ // Group operations based on registers
33
+ const groupedOps: number[][] = _groupOperations(operations, registers);
34
+
35
+ // Align operations on multiple registers
36
+ const alignedOps: (number | null)[][] = _alignOps(groupedOps);
37
+
38
+ // Maintain widths of each column to account for variable-sized gates
39
+ const numColumns: number = Math.max(
40
+ 0,
41
+ ...alignedOps.map((ops) => ops.length),
42
+ );
43
+ const columnsWidths: number[] = new Array(numColumns).fill(minGateWidth);
44
+
45
+ // Get classical registers and their starting column index
46
+ const classicalRegs: [number, Register][] = _getClassicalRegStart(
47
+ operations,
48
+ alignedOps,
49
+ );
50
+
51
+ // Keep track of which ops are already seen to avoid duplicate rendering
52
+ const visited: { [opIdx: number]: boolean } = {};
53
+
54
+ // Map operation index to gate metadata for formatting later
55
+ const opsMetadata: Metadata[][] = alignedOps.map((regOps) =>
56
+ regOps.map((opIdx, col) => {
57
+ let op: Operation | null = null;
58
+
59
+ // eslint-disable-next-line no-prototype-builtins
60
+ if (opIdx != null && !visited.hasOwnProperty(opIdx)) {
61
+ op = operations[opIdx];
62
+ visited[opIdx] = true;
63
+ }
64
+
65
+ const metadata: Metadata = _opToMetadata(op, registers);
66
+
67
+ if (
68
+ op != null &&
69
+ [GateType.Unitary, GateType.ControlledUnitary].includes(metadata.type)
70
+ ) {
71
+ // If gate is a unitary type, split targetsY into groups if there
72
+ // is a classical register between them for rendering
73
+
74
+ // Get y coordinates of classical registers in the same column as this operation
75
+ const classicalRegY: number[] = classicalRegs
76
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
77
+ .filter(([regCol, _]) => regCol <= col)
78
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
79
+ .map(([_, reg]) => {
80
+ if (reg.cId == null)
81
+ throw new Error("Could not find cId for classical register.");
82
+ const { children } = registers[reg.qId];
83
+ if (children == null)
84
+ throw new Error(
85
+ `Failed to find classical registers for qubit ID ${reg.qId}.`,
86
+ );
87
+ return children[reg.cId].y;
88
+ });
89
+
90
+ metadata.targetsY = _splitTargetsY(
91
+ op.targets,
92
+ classicalRegY,
93
+ registers,
94
+ );
95
+ }
96
+
97
+ // Expand column size, if needed
98
+ if (metadata.width > columnsWidths[col]) {
99
+ columnsWidths[col] = metadata.width;
100
+ }
101
+
102
+ return metadata;
103
+ }),
104
+ );
105
+
106
+ // Fill in x coord of each gate
107
+ const endX: number = _fillMetadataX(opsMetadata, columnsWidths);
108
+
109
+ // Flatten operations and filter out invalid gates
110
+ const metadataList: Metadata[] = opsMetadata
111
+ .flat()
112
+ .filter(({ type }) => type != GateType.Invalid);
113
+
114
+ return { metadataList, svgWidth: endX };
115
+ };
116
+
117
+ /**
118
+ * Group gates provided by operations into their respective registers.
119
+ *
120
+ * @param operations Array of operations.
121
+ * @param numRegs Total number of registers.
122
+ *
123
+ * @returns 2D array of indices where `groupedOps[i][j]` is the index of the operations
124
+ * at register `i` and column `j` (not yet aligned/padded).
125
+ */
126
+ const _groupOperations = (
127
+ operations: Operation[],
128
+ registers: RegisterMap,
129
+ ): number[][] => {
130
+ // NOTE: We get the max ID instead of just number of keys because there can be a qubit ID that
131
+ // isn't acted upon and thus does not show up as a key in registers.
132
+ const numRegs: number =
133
+ Math.max(-1, ...Object.keys(registers).map(Number)) + 1;
134
+ const groupedOps: number[][] = Array.from(Array(numRegs), () => new Array(0));
135
+ operations.forEach(({ targets, controls }, instrIdx) => {
136
+ const ctrls: Register[] = controls || [];
137
+ const qRegs: Register[] = [...ctrls, ...targets].filter(
138
+ ({ type }) => (type || RegisterType.Qubit) === RegisterType.Qubit,
139
+ );
140
+ const qRegIdxList: number[] = qRegs.map(({ qId }) => qId);
141
+ const clsControls: Register[] = ctrls.filter(
142
+ ({ type }) => (type || RegisterType.Qubit) === RegisterType.Classical,
143
+ );
144
+ const isClassicallyControlled: boolean = clsControls.length > 0;
145
+ if (!isClassicallyControlled && qRegs.length === 0) return;
146
+ // If operation is classically-controlled, pad all qubit registers. Otherwise, only pad
147
+ // the contiguous range of registers that it covers.
148
+ const minRegIdx: number = isClassicallyControlled
149
+ ? 0
150
+ : Math.min(...qRegIdxList);
151
+ const maxRegIdx: number = isClassicallyControlled
152
+ ? numRegs - 1
153
+ : Math.max(...qRegIdxList);
154
+ // Add operation also to registers that are in-between target registers
155
+ // so that other gates won't render in the middle.
156
+ for (let i = minRegIdx; i <= maxRegIdx; i++) {
157
+ groupedOps[i].push(instrIdx);
158
+ }
159
+ });
160
+ return groupedOps;
161
+ };
162
+
163
+ /**
164
+ * Aligns operations by padding registers with `null`s to make sure that multiqubit
165
+ * gates are in the same column.
166
+ * e.g. ---[x]---[x]--
167
+ * ----------|---
168
+ *
169
+ * @param ops 2D array of operations. Each row represents a register
170
+ * and the operations acting on it (in-order).
171
+ *
172
+ * @returns 2D array of aligned operations padded with `null`s.
173
+ */
174
+ const _alignOps = (ops: number[][]): (number | null)[][] => {
175
+ let maxNumOps: number = Math.max(0, ...ops.map((regOps) => regOps.length));
176
+ let col = 0;
177
+ // Deep copy ops to be returned as paddedOps
178
+ const paddedOps: (number | null)[][] = JSON.parse(JSON.stringify(ops));
179
+ while (col < maxNumOps) {
180
+ for (let regIdx = 0; regIdx < paddedOps.length; regIdx++) {
181
+ const reg: (number | null)[] = paddedOps[regIdx];
182
+ if (reg.length <= col) continue;
183
+
184
+ // Should never be null (nulls are only padded to previous columns)
185
+ const opIdx: number | null = reg[col];
186
+
187
+ // Get position of gate
188
+ const targetsPos: number[] = paddedOps.map((regOps) =>
189
+ regOps.indexOf(opIdx),
190
+ );
191
+ const gatePos: number = Math.max(-1, ...targetsPos);
192
+
193
+ // If current column is not desired gate position, pad with null
194
+ if (col < gatePos) {
195
+ paddedOps[regIdx].splice(col, 0, null);
196
+ maxNumOps = Math.max(maxNumOps, paddedOps[regIdx].length);
197
+ }
198
+ }
199
+ col++;
200
+ }
201
+ return paddedOps;
202
+ };
203
+
204
+ /**
205
+ * Retrieves the starting index of each classical register.
206
+ *
207
+ * @param ops Array of operations.
208
+ * @param idxList 2D array of aligned operation indices.
209
+ *
210
+ * @returns Array of classical register and their starting column indices in the form [[column, register]].
211
+ */
212
+ const _getClassicalRegStart = (
213
+ ops: Operation[],
214
+ idxList: (number | null)[][],
215
+ ): [number, Register][] => {
216
+ const clsRegs: [number, Register][] = [];
217
+ idxList.forEach((reg) => {
218
+ for (let col = 0; col < reg.length; col++) {
219
+ const opIdx: number | null = reg[col];
220
+ if (opIdx != null && ops[opIdx].isMeasurement) {
221
+ const targetClsRegs: Register[] = ops[opIdx].targets.filter(
222
+ (reg) => reg.type === RegisterType.Classical,
223
+ );
224
+ targetClsRegs.forEach((reg) => clsRegs.push([col, reg]));
225
+ }
226
+ }
227
+ });
228
+ return clsRegs;
229
+ };
230
+
231
+ /**
232
+ * Maps operation to metadata (e.g. gate type, position, dimensions, text)
233
+ * required to render the image.
234
+ *
235
+ * @param op Operation to be mapped into metadata format.
236
+ * @param registers Array of registers.
237
+ *
238
+ * @returns Metadata representation of given operation.
239
+ */
240
+ const _opToMetadata = (
241
+ op: Operation | null,
242
+ registers: RegisterMap,
243
+ ): Metadata => {
244
+ const metadata: Metadata = {
245
+ type: GateType.Invalid,
246
+ x: 0,
247
+ controlsY: [],
248
+ targetsY: [],
249
+ label: "",
250
+ width: -1,
251
+ };
252
+
253
+ if (op == null) return metadata;
254
+
255
+ const {
256
+ gate,
257
+ dataAttributes,
258
+ displayArgs,
259
+ isMeasurement,
260
+ isConditional,
261
+ isControlled,
262
+ isAdjoint,
263
+ controls,
264
+ targets,
265
+ children,
266
+ conditionalRender,
267
+ } = op;
268
+
269
+ // Set y coords
270
+ metadata.controlsY = controls?.map((reg) => _getRegY(reg, registers)) || [];
271
+ metadata.targetsY = targets.map((reg) => _getRegY(reg, registers));
272
+
273
+ if (isConditional) {
274
+ // Classically-controlled operations
275
+ if (children == null || children.length == 0)
276
+ throw new Error(
277
+ "No children operations found for classically-controlled operation.",
278
+ );
279
+
280
+ // Gates to display when classical bit is 0.
281
+ const onZeroOps: Operation[] = children.filter(
282
+ (op) => op.conditionalRender !== ConditionalRender.OnOne,
283
+ );
284
+ let childrenInstrs = processOperations(onZeroOps, registers);
285
+ const zeroGates: Metadata[] = childrenInstrs.metadataList;
286
+ const zeroChildWidth: number = childrenInstrs.svgWidth;
287
+
288
+ // Gates to display when classical bit is 1.
289
+ const onOneOps: Operation[] = children.filter(
290
+ (op) => op.conditionalRender !== ConditionalRender.OnZero,
291
+ );
292
+ childrenInstrs = processOperations(onOneOps, registers);
293
+ const oneGates: Metadata[] = childrenInstrs.metadataList;
294
+ const oneChildWidth: number = childrenInstrs.svgWidth;
295
+
296
+ // Subtract startX (left-side) and 2*gatePadding (right-side) from nested child gates width
297
+ const width: number =
298
+ Math.max(zeroChildWidth, oneChildWidth) - startX - gatePadding * 2;
299
+
300
+ metadata.type = GateType.ClassicalControlled;
301
+ metadata.children = [zeroGates, oneGates];
302
+ // Add additional width from control button and inner box padding for dashed box
303
+ metadata.width = width + controlBtnOffset + groupBoxPadding * 2;
304
+
305
+ // Set targets to first and last quantum registers so we can render the surrounding box
306
+ // around all quantum registers.
307
+ const qubitsY: number[] = Object.values(registers).map(({ y }) => y);
308
+ if (qubitsY.length > 0)
309
+ metadata.targetsY = [Math.min(...qubitsY), Math.max(...qubitsY)];
310
+ } else if (
311
+ conditionalRender == ConditionalRender.AsGroup &&
312
+ (children?.length || 0) > 0
313
+ ) {
314
+ const childrenInstrs = processOperations(
315
+ children as Operation[],
316
+ registers,
317
+ );
318
+ metadata.type = GateType.Group;
319
+ metadata.children = childrenInstrs.metadataList;
320
+ // _zoomButton function in gateFormatter.ts relies on
321
+ // 'expanded' attribute to render zoom button
322
+ metadata.dataAttributes = { expanded: "true" };
323
+ // Subtract startX (left-side) and add inner box padding (minus nested gate padding) for dashed box
324
+ metadata.width =
325
+ childrenInstrs.svgWidth - startX + (groupBoxPadding - gatePadding) * 2;
326
+ } else if (isMeasurement) {
327
+ metadata.type = GateType.Measure;
328
+ } else if (gate === "SWAP") {
329
+ metadata.type = GateType.Swap;
330
+ } else if (isControlled) {
331
+ metadata.type = gate === "X" ? GateType.Cnot : GateType.ControlledUnitary;
332
+ metadata.label = gate;
333
+ } else if (gate === "X") {
334
+ metadata.type = GateType.X;
335
+ metadata.label = gate;
336
+ } else {
337
+ // Any other gate treated as a simple unitary gate
338
+ metadata.type = GateType.Unitary;
339
+ metadata.label = gate;
340
+ }
341
+
342
+ // If adjoint, add ' to the end of gate label
343
+ if (isAdjoint && metadata.label.length > 0) metadata.label += "'";
344
+
345
+ // If gate has extra arguments, display them
346
+ if (displayArgs != null) metadata.displayArgs = displayArgs;
347
+
348
+ // Set gate width
349
+ metadata.width = getGateWidth(metadata);
350
+
351
+ // Extend existing data attributes with user-provided data attributes
352
+ if (dataAttributes != null)
353
+ metadata.dataAttributes = { ...metadata.dataAttributes, ...dataAttributes };
354
+
355
+ return metadata;
356
+ };
357
+
358
+ /**
359
+ * Compute the y coord of a given register.
360
+ *
361
+ * @param reg Register to compute y coord of.
362
+ * @param registers Map of qubit IDs to RegisterMetadata.
363
+ *
364
+ * @returns The y coord of give register.
365
+ */
366
+ const _getRegY = (reg: Register, registers: RegisterMap): number => {
367
+ const { type, qId, cId } = reg;
368
+ if (!Object.prototype.hasOwnProperty.call(registers, qId))
369
+ throw new Error(`ERROR: Qubit register with ID ${qId} not found.`);
370
+ const { y, children } = registers[qId];
371
+ switch (type) {
372
+ case undefined:
373
+ case RegisterType.Qubit:
374
+ return y;
375
+ case RegisterType.Classical:
376
+ if (children == null)
377
+ throw new Error(
378
+ `ERROR: No classical registers found for qubit ID ${qId}.`,
379
+ );
380
+ if (cId == null)
381
+ throw new Error(
382
+ `ERROR: No ID defined for classical register associated with qubit ID ${qId}.`,
383
+ );
384
+ if (children.length <= cId)
385
+ throw new Error(
386
+ `ERROR: Classical register ID ${cId} invalid for qubit ID ${qId} with ${children.length} classical register(s).`,
387
+ );
388
+ return children[cId].y;
389
+ default:
390
+ throw new Error(`ERROR: Unknown register type ${type}.`);
391
+ }
392
+ };
393
+
394
+ /**
395
+ * Splits `targets` if non-adjacent or intersected by classical registers.
396
+ *
397
+ * @param targets Target qubit registers.
398
+ * @param classicalRegY y coords of classical registers overlapping current column.
399
+ * @param registers Mapping from register qubit IDs to register metadata.
400
+ *
401
+ * @returns Groups of target qubit y coords.
402
+ */
403
+ const _splitTargetsY = (
404
+ targets: Register[],
405
+ classicalRegY: number[],
406
+ registers: RegisterMap,
407
+ ): number[][] => {
408
+ if (targets.length === 0) return [];
409
+
410
+ // Get qIds sorted by ascending y value
411
+ const orderedQIds: number[] = Object.keys(registers).map(Number);
412
+ orderedQIds.sort((a, b) => registers[a].y - registers[b].y);
413
+ const qIdPosition: { [qId: number]: number } = {};
414
+ orderedQIds.forEach((qId, i) => (qIdPosition[qId] = i));
415
+
416
+ // Sort targets and classicalRegY by ascending y value
417
+ targets = targets.slice();
418
+ targets.sort((a, b) => {
419
+ const posDiff: number = qIdPosition[a.qId] - qIdPosition[b.qId];
420
+ if (posDiff === 0 && a.cId != null && b.cId != null) return a.cId - b.cId;
421
+ else return posDiff;
422
+ });
423
+ classicalRegY = classicalRegY.slice();
424
+ classicalRegY.sort((a, b) => a - b);
425
+
426
+ let prevPos = 0;
427
+ let prevY = 0;
428
+
429
+ return targets.reduce((groups: number[][], target: Register) => {
430
+ const y = _getRegY(target, registers);
431
+ const pos = qIdPosition[target.qId];
432
+
433
+ // Split into new group if one of the following holds:
434
+ // 1. First target register
435
+ // 2. Non-adjacent qubit registers
436
+ // 3. There is a classical register between current and previous register
437
+ if (
438
+ groups.length === 0 ||
439
+ pos > prevPos + 1 ||
440
+ (classicalRegY[0] > prevY && classicalRegY[0] < y)
441
+ )
442
+ groups.push([y]);
443
+ else groups[groups.length - 1].push(y);
444
+
445
+ prevPos = pos;
446
+ prevY = y;
447
+
448
+ // Remove classical registers that are higher than current y
449
+ while (classicalRegY.length > 0 && classicalRegY[0] <= y)
450
+ classicalRegY.shift();
451
+
452
+ return groups;
453
+ }, []);
454
+ };
455
+
456
+ /**
457
+ * Updates the x coord of each metadata in the given 2D array of metadata and returns rightmost x coord.
458
+ *
459
+ * @param opsMetadata 2D array of metadata.
460
+ * @param columnWidths Array of column widths.
461
+ *
462
+ * @returns Rightmost x coord.
463
+ */
464
+ const _fillMetadataX = (
465
+ opsMetadata: Metadata[][],
466
+ columnWidths: number[],
467
+ ): number => {
468
+ let currX: number = startX;
469
+
470
+ const colStartX: number[] = columnWidths.map((width) => {
471
+ const x: number = currX;
472
+ currX += width + gatePadding * 2;
473
+ return x;
474
+ });
475
+
476
+ const endX: number = currX;
477
+
478
+ opsMetadata.forEach((regOps) =>
479
+ regOps.forEach((metadata, col) => {
480
+ const x = colStartX[col];
481
+ switch (metadata.type) {
482
+ case GateType.ClassicalControlled:
483
+ case GateType.Group:
484
+ {
485
+ // Subtract startX offset from nested gates and add offset and padding
486
+ let offset: number = x - startX + groupBoxPadding;
487
+ if (metadata.type === GateType.ClassicalControlled)
488
+ offset += controlBtnOffset;
489
+
490
+ // Offset each x coord in children gates
491
+ _offsetChildrenX(metadata.children, offset);
492
+
493
+ // We don't use the centre x coord because we only care about the rightmost x for
494
+ // rendering the box around the group of nested gates
495
+ metadata.x = x;
496
+ }
497
+ break;
498
+
499
+ default:
500
+ metadata.x = x + columnWidths[col] / 2;
501
+ break;
502
+ }
503
+ }),
504
+ );
505
+
506
+ return endX;
507
+ };
508
+
509
+ /**
510
+ * Offset x coords of nested children operations.
511
+ *
512
+ * @param children 2D array of children metadata.
513
+ * @param offset x coord offset.
514
+ */
515
+ const _offsetChildrenX = (
516
+ children: (Metadata | Metadata[])[] | undefined,
517
+ offset: number,
518
+ ): void => {
519
+ if (children == null) return;
520
+ children.flat().forEach((child) => {
521
+ child.x += offset;
522
+ _offsetChildrenX(child.children, offset);
523
+ });
524
+ };
525
+
526
+ export {
527
+ processOperations,
528
+ _groupOperations,
529
+ _alignOps,
530
+ _getClassicalRegStart,
531
+ _opToMetadata,
532
+ _getRegY,
533
+ _splitTargetsY,
534
+ _fillMetadataX,
535
+ _offsetChildrenX,
536
+ };
@@ -0,0 +1,9 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ export {
5
+ RegisterType,
6
+ type Register,
7
+ type RegisterMap,
8
+ type RegisterMetadata,
9
+ } from "../../src/shared/register";