qsharp-lang 1.15.4-dev → 1.16.1-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 (326) hide show
  1. package/dist/browser.d.ts +2 -2
  2. package/dist/compiler/compiler.d.ts +3 -1
  3. package/dist/compiler/compiler.js +5 -1
  4. package/dist/samples.generated.js +1 -1
  5. package/dist/utils.d.ts +8 -0
  6. package/dist/utils.js +22 -8
  7. package/docs/Microsoft.Quantum.Core/Length.md +1 -1
  8. package/docs/Microsoft.Quantum.Core/Repeated.md +1 -1
  9. package/docs/Microsoft.Quantum.Core/index.md +1 -1
  10. package/docs/Std.Arithmetic/AddLE.md +1 -1
  11. package/docs/Std.Arithmetic/ApplyIfEqualL.md +1 -1
  12. package/docs/Std.Arithmetic/ApplyIfEqualLE.md +1 -1
  13. package/docs/Std.Arithmetic/ApplyIfGreaterL.md +1 -1
  14. package/docs/Std.Arithmetic/ApplyIfGreaterLE.md +1 -1
  15. package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualL.md +1 -1
  16. package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualLE.md +1 -1
  17. package/docs/Std.Arithmetic/ApplyIfLessL.md +1 -1
  18. package/docs/Std.Arithmetic/ApplyIfLessLE.md +1 -1
  19. package/docs/Std.Arithmetic/ApplyIfLessOrEqualL.md +1 -1
  20. package/docs/Std.Arithmetic/ApplyIfLessOrEqualLE.md +1 -1
  21. package/docs/Std.Arithmetic/FourierTDIncByLE.md +1 -1
  22. package/docs/Std.Arithmetic/IncByI.md +1 -1
  23. package/docs/Std.Arithmetic/IncByIUsingIncByLE.md +1 -1
  24. package/docs/Std.Arithmetic/IncByL.md +1 -1
  25. package/docs/Std.Arithmetic/IncByLE.md +1 -1
  26. package/docs/Std.Arithmetic/IncByLEUsingAddLE.md +1 -1
  27. package/docs/Std.Arithmetic/IncByLUsingIncByLE.md +1 -1
  28. package/docs/Std.Arithmetic/LookAheadDKRSAddLE.md +1 -1
  29. package/docs/Std.Arithmetic/MAJ.md +1 -1
  30. package/docs/Std.Arithmetic/ReflectAboutInteger.md +1 -1
  31. package/docs/Std.Arithmetic/RippleCarryCGAddLE.md +1 -1
  32. package/docs/Std.Arithmetic/RippleCarryCGIncByLE.md +1 -1
  33. package/docs/Std.Arithmetic/RippleCarryTTKIncByLE.md +1 -1
  34. package/docs/Std.Arithmetic/index.md +1 -1
  35. package/docs/Std.Arrays/All.md +1 -1
  36. package/docs/Std.Arrays/Any.md +1 -1
  37. package/docs/Std.Arrays/Chunks.md +1 -1
  38. package/docs/Std.Arrays/CircularlyShifted.md +1 -1
  39. package/docs/Std.Arrays/ColumnAt.md +1 -1
  40. package/docs/Std.Arrays/Count.md +1 -1
  41. package/docs/Std.Arrays/Diagonal.md +1 -1
  42. package/docs/Std.Arrays/DrawMany.md +1 -1
  43. package/docs/Std.Arrays/Enumerated.md +1 -1
  44. package/docs/Std.Arrays/Excluding.md +1 -1
  45. package/docs/Std.Arrays/Filtered.md +1 -1
  46. package/docs/Std.Arrays/FlatMapped.md +1 -1
  47. package/docs/Std.Arrays/Flattened.md +1 -1
  48. package/docs/Std.Arrays/Fold.md +1 -1
  49. package/docs/Std.Arrays/ForEach.md +1 -1
  50. package/docs/Std.Arrays/Head.md +1 -1
  51. package/docs/Std.Arrays/HeadAndRest.md +1 -1
  52. package/docs/Std.Arrays/IndexOf.md +1 -1
  53. package/docs/Std.Arrays/IndexRange.md +1 -1
  54. package/docs/Std.Arrays/Interleaved.md +1 -1
  55. package/docs/Std.Arrays/IsEmpty.md +1 -1
  56. package/docs/Std.Arrays/IsRectangularArray.md +1 -1
  57. package/docs/Std.Arrays/IsSorted.md +1 -1
  58. package/docs/Std.Arrays/IsSquareArray.md +1 -1
  59. package/docs/Std.Arrays/Mapped.md +1 -1
  60. package/docs/Std.Arrays/MappedByIndex.md +1 -1
  61. package/docs/Std.Arrays/MappedOverRange.md +1 -1
  62. package/docs/Std.Arrays/Most.md +1 -1
  63. package/docs/Std.Arrays/MostAndTail.md +1 -1
  64. package/docs/Std.Arrays/Padded.md +1 -1
  65. package/docs/Std.Arrays/Partitioned.md +1 -1
  66. package/docs/Std.Arrays/Rest.md +1 -1
  67. package/docs/Std.Arrays/Reversed.md +1 -1
  68. package/docs/Std.Arrays/SequenceI.md +1 -1
  69. package/docs/Std.Arrays/SequenceL.md +1 -1
  70. package/docs/Std.Arrays/Sorted.md +1 -1
  71. package/docs/Std.Arrays/Subarray.md +1 -1
  72. package/docs/Std.Arrays/Swapped.md +1 -1
  73. package/docs/Std.Arrays/Tail.md +1 -1
  74. package/docs/Std.Arrays/Transposed.md +1 -1
  75. package/docs/Std.Arrays/Unzipped.md +1 -1
  76. package/docs/Std.Arrays/Where.md +1 -1
  77. package/docs/Std.Arrays/Windows.md +1 -1
  78. package/docs/Std.Arrays/Zipped.md +1 -1
  79. package/docs/Std.Arrays/index.md +1 -1
  80. package/docs/Std.Canon/ApplyCNOTChain.md +1 -1
  81. package/docs/Std.Canon/ApplyControlledOnBitString.md +1 -1
  82. package/docs/Std.Canon/ApplyControlledOnInt.md +1 -1
  83. package/docs/Std.Canon/ApplyOperationPowerA.md +1 -1
  84. package/docs/Std.Canon/ApplyP.md +1 -1
  85. package/docs/Std.Canon/ApplyPauli.md +1 -1
  86. package/docs/Std.Canon/ApplyPauliFromBitString.md +1 -1
  87. package/docs/Std.Canon/ApplyPauliFromInt.md +1 -1
  88. package/docs/Std.Canon/ApplyQFT.md +1 -1
  89. package/docs/Std.Canon/ApplyToEach.md +1 -1
  90. package/docs/Std.Canon/ApplyToEachA.md +1 -1
  91. package/docs/Std.Canon/ApplyToEachC.md +1 -1
  92. package/docs/Std.Canon/ApplyToEachCA.md +1 -1
  93. package/docs/Std.Canon/ApplyXorInPlace.md +1 -1
  94. package/docs/Std.Canon/ApplyXorInPlaceL.md +1 -1
  95. package/docs/Std.Canon/CX.md +1 -1
  96. package/docs/Std.Canon/CY.md +1 -1
  97. package/docs/Std.Canon/CZ.md +1 -1
  98. package/docs/Std.Canon/Fst.md +1 -1
  99. package/docs/Std.Canon/Relabel.md +1 -1
  100. package/docs/Std.Canon/Snd.md +1 -1
  101. package/docs/Std.Canon/SwapReverseRegister.md +1 -1
  102. package/docs/Std.Canon/index.md +1 -1
  103. package/docs/Std.Convert/BigIntAsBoolArray.md +1 -1
  104. package/docs/Std.Convert/BigIntAsInt.md +1 -1
  105. package/docs/Std.Convert/BoolArrayAsBigInt.md +1 -1
  106. package/docs/Std.Convert/BoolArrayAsInt.md +1 -1
  107. package/docs/Std.Convert/BoolArrayAsResultArray.md +1 -1
  108. package/docs/Std.Convert/BoolAsResult.md +1 -1
  109. package/docs/Std.Convert/ComplexAsComplexPolar.md +1 -1
  110. package/docs/Std.Convert/ComplexPolarAsComplex.md +1 -1
  111. package/docs/Std.Convert/DoubleAsStringWithPrecision.md +1 -1
  112. package/docs/Std.Convert/IntAsBigInt.md +1 -1
  113. package/docs/Std.Convert/IntAsBoolArray.md +1 -1
  114. package/docs/Std.Convert/IntAsDouble.md +1 -1
  115. package/docs/Std.Convert/ResultArrayAsBoolArray.md +1 -1
  116. package/docs/Std.Convert/ResultArrayAsInt.md +1 -1
  117. package/docs/Std.Convert/ResultAsBool.md +1 -1
  118. package/docs/Std.Convert/index.md +1 -1
  119. package/docs/Std.Core/Length.md +1 -1
  120. package/docs/Std.Core/Repeated.md +1 -1
  121. package/docs/Std.Core/index.md +1 -1
  122. package/docs/Std.Diagnostics/ApplyIdleNoise.md +1 -1
  123. package/docs/Std.Diagnostics/BitFlipNoise.md +1 -1
  124. package/docs/Std.Diagnostics/CheckAllZero.md +1 -1
  125. package/docs/Std.Diagnostics/CheckOperationsAreEqual.md +1 -1
  126. package/docs/Std.Diagnostics/CheckZero.md +1 -1
  127. package/docs/Std.Diagnostics/ConfigurePauliNoise.md +1 -1
  128. package/docs/Std.Diagnostics/DepolarizingNoise.md +1 -1
  129. package/docs/Std.Diagnostics/DumpMachine.md +1 -1
  130. package/docs/Std.Diagnostics/DumpOperation.md +1 -1
  131. package/docs/Std.Diagnostics/DumpRegister.md +1 -1
  132. package/docs/Std.Diagnostics/Fact.md +1 -1
  133. package/docs/Std.Diagnostics/NoNoise.md +1 -1
  134. package/docs/Std.Diagnostics/PhaseFlipNoise.md +1 -1
  135. package/docs/Std.Diagnostics/StartCountingFunction.md +1 -1
  136. package/docs/Std.Diagnostics/StartCountingOperation.md +1 -1
  137. package/docs/Std.Diagnostics/StartCountingQubits.md +1 -1
  138. package/docs/Std.Diagnostics/StopCountingFunction.md +1 -1
  139. package/docs/Std.Diagnostics/StopCountingOperation.md +1 -1
  140. package/docs/Std.Diagnostics/StopCountingQubits.md +1 -1
  141. package/docs/Std.Diagnostics/index.md +1 -1
  142. package/docs/Std.Intrinsic/AND.md +1 -1
  143. package/docs/Std.Intrinsic/ApplyUnitary.md +1 -1
  144. package/docs/Std.Intrinsic/CCNOT.md +1 -1
  145. package/docs/Std.Intrinsic/CNOT.md +1 -1
  146. package/docs/Std.Intrinsic/Exp.md +1 -1
  147. package/docs/Std.Intrinsic/H.md +1 -1
  148. package/docs/Std.Intrinsic/I.md +1 -1
  149. package/docs/Std.Intrinsic/M.md +1 -1
  150. package/docs/Std.Intrinsic/Measure.md +1 -1
  151. package/docs/Std.Intrinsic/Message.md +1 -1
  152. package/docs/Std.Intrinsic/R.md +1 -1
  153. package/docs/Std.Intrinsic/R1.md +1 -1
  154. package/docs/Std.Intrinsic/R1Frac.md +1 -1
  155. package/docs/Std.Intrinsic/RFrac.md +1 -1
  156. package/docs/Std.Intrinsic/Reset.md +1 -1
  157. package/docs/Std.Intrinsic/ResetAll.md +1 -1
  158. package/docs/Std.Intrinsic/Rx.md +1 -1
  159. package/docs/Std.Intrinsic/Rxx.md +1 -1
  160. package/docs/Std.Intrinsic/Ry.md +1 -1
  161. package/docs/Std.Intrinsic/Ryy.md +1 -1
  162. package/docs/Std.Intrinsic/Rz.md +1 -1
  163. package/docs/Std.Intrinsic/Rzz.md +1 -1
  164. package/docs/Std.Intrinsic/S.md +1 -1
  165. package/docs/Std.Intrinsic/SWAP.md +1 -1
  166. package/docs/Std.Intrinsic/SX.md +38 -0
  167. package/docs/Std.Intrinsic/T.md +1 -1
  168. package/docs/Std.Intrinsic/X.md +1 -1
  169. package/docs/Std.Intrinsic/Y.md +1 -1
  170. package/docs/Std.Intrinsic/Z.md +1 -1
  171. package/docs/Std.Intrinsic/index.md +2 -1
  172. package/docs/Std.Logical/Xor.md +1 -1
  173. package/docs/Std.Logical/index.md +1 -1
  174. package/docs/Std.Math/AbsComplex.md +1 -1
  175. package/docs/Std.Math/AbsComplexPolar.md +1 -1
  176. package/docs/Std.Math/AbsD.md +1 -1
  177. package/docs/Std.Math/AbsI.md +1 -1
  178. package/docs/Std.Math/AbsL.md +1 -1
  179. package/docs/Std.Math/AbsSquaredComplex.md +1 -1
  180. package/docs/Std.Math/AbsSquaredComplexPolar.md +1 -1
  181. package/docs/Std.Math/ApproximateFactorial.md +1 -1
  182. package/docs/Std.Math/ArcCos.md +1 -1
  183. package/docs/Std.Math/ArcCosh.md +1 -1
  184. package/docs/Std.Math/ArcSin.md +1 -1
  185. package/docs/Std.Math/ArcSinh.md +1 -1
  186. package/docs/Std.Math/ArcTan.md +1 -1
  187. package/docs/Std.Math/ArcTan2.md +1 -1
  188. package/docs/Std.Math/ArcTanh.md +1 -1
  189. package/docs/Std.Math/ArgComplex.md +1 -1
  190. package/docs/Std.Math/ArgComplexPolar.md +1 -1
  191. package/docs/Std.Math/Binom.md +1 -1
  192. package/docs/Std.Math/BitSizeI.md +1 -1
  193. package/docs/Std.Math/BitSizeL.md +1 -1
  194. package/docs/Std.Math/Ceiling.md +1 -1
  195. package/docs/Std.Math/Complex.md +1 -1
  196. package/docs/Std.Math/ComplexPolar.md +1 -1
  197. package/docs/Std.Math/ContinuedFractionConvergentI.md +1 -1
  198. package/docs/Std.Math/ContinuedFractionConvergentL.md +1 -1
  199. package/docs/Std.Math/Cos.md +1 -1
  200. package/docs/Std.Math/Cosh.md +1 -1
  201. package/docs/Std.Math/DivRemI.md +1 -1
  202. package/docs/Std.Math/DivRemL.md +1 -1
  203. package/docs/Std.Math/DividedByC.md +1 -1
  204. package/docs/Std.Math/DividedByCP.md +1 -1
  205. package/docs/Std.Math/E.md +1 -1
  206. package/docs/Std.Math/ExpModI.md +1 -1
  207. package/docs/Std.Math/ExpModL.md +1 -1
  208. package/docs/Std.Math/ExtendedGreatestCommonDivisorI.md +1 -1
  209. package/docs/Std.Math/ExtendedGreatestCommonDivisorL.md +1 -1
  210. package/docs/Std.Math/FactorialI.md +1 -1
  211. package/docs/Std.Math/FactorialL.md +1 -1
  212. package/docs/Std.Math/Floor.md +1 -1
  213. package/docs/Std.Math/GreatestCommonDivisorI.md +1 -1
  214. package/docs/Std.Math/GreatestCommonDivisorL.md +1 -1
  215. package/docs/Std.Math/HammingWeightI.md +1 -1
  216. package/docs/Std.Math/InverseModI.md +1 -1
  217. package/docs/Std.Math/InverseModL.md +1 -1
  218. package/docs/Std.Math/IsCoprimeI.md +1 -1
  219. package/docs/Std.Math/IsCoprimeL.md +1 -1
  220. package/docs/Std.Math/IsInfinite.md +1 -1
  221. package/docs/Std.Math/IsNaN.md +1 -1
  222. package/docs/Std.Math/LargestFixedPoint.md +1 -1
  223. package/docs/Std.Math/Lg.md +1 -1
  224. package/docs/Std.Math/Log.md +1 -1
  225. package/docs/Std.Math/Log10.md +1 -1
  226. package/docs/Std.Math/LogFactorialD.md +1 -1
  227. package/docs/Std.Math/LogGammaD.md +1 -1
  228. package/docs/Std.Math/LogOf2.md +1 -1
  229. package/docs/Std.Math/Max.md +1 -1
  230. package/docs/Std.Math/MaxD.md +1 -1
  231. package/docs/Std.Math/MaxI.md +1 -1
  232. package/docs/Std.Math/MaxL.md +1 -1
  233. package/docs/Std.Math/Min.md +1 -1
  234. package/docs/Std.Math/MinD.md +1 -1
  235. package/docs/Std.Math/MinI.md +1 -1
  236. package/docs/Std.Math/MinL.md +1 -1
  237. package/docs/Std.Math/MinusC.md +1 -1
  238. package/docs/Std.Math/MinusCP.md +1 -1
  239. package/docs/Std.Math/ModulusI.md +1 -1
  240. package/docs/Std.Math/ModulusL.md +1 -1
  241. package/docs/Std.Math/NegationC.md +1 -1
  242. package/docs/Std.Math/NegationCP.md +1 -1
  243. package/docs/Std.Math/PI.md +1 -1
  244. package/docs/Std.Math/PNorm.md +1 -1
  245. package/docs/Std.Math/PNormalized.md +1 -1
  246. package/docs/Std.Math/PlusC.md +1 -1
  247. package/docs/Std.Math/PlusCP.md +1 -1
  248. package/docs/Std.Math/PowC.md +1 -1
  249. package/docs/Std.Math/PowCP.md +1 -1
  250. package/docs/Std.Math/RealMod.md +1 -1
  251. package/docs/Std.Math/Round.md +1 -1
  252. package/docs/Std.Math/RoundHalfAwayFromZero.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/PrepareUniformSuperposition.md +1 -1
  305. package/docs/Std.StatePreparation/index.md +1 -1
  306. package/docs/Std.TableLookup/Select.md +1 -1
  307. package/docs/Std.TableLookup/index.md +1 -1
  308. package/docs/index.md +1 -1
  309. package/docs/toc.yml +1 -0
  310. package/lib/node/qsc_wasm.cjs +22 -4
  311. package/lib/node/qsc_wasm.d.cts +10 -0
  312. package/lib/node/qsc_wasm_bg.wasm +0 -0
  313. package/lib/web/qsc_wasm.d.ts +11 -0
  314. package/lib/web/qsc_wasm.js +21 -4
  315. package/lib/web/qsc_wasm_bg.wasm +0 -0
  316. package/package.json +1 -1
  317. package/ux/circuit-vis/circuitManipulation.ts +145 -48
  318. package/ux/circuit-vis/contextMenu.ts +1 -1
  319. package/ux/circuit-vis/draggable.ts +288 -112
  320. package/ux/circuit-vis/events.ts +433 -199
  321. package/ux/circuit-vis/formatters/inputFormatter.ts +9 -4
  322. package/ux/circuit-vis/panel.ts +37 -34
  323. package/ux/circuit-vis/process.ts +1 -1
  324. package/ux/circuit-vis/sqore.ts +2 -2
  325. package/ux/circuit-vis/utils.ts +17 -1
  326. package/ux/qsharp-circuit.css +2 -35
@@ -14,22 +14,28 @@ import {
14
14
  locationStringToIndexes,
15
15
  findParentArray,
16
16
  deepEqual,
17
+ getQubitLabelElems,
17
18
  } from "./utils";
18
19
  import { addContextMenuToHostElem, promptForArguments } from "./contextMenu";
19
20
  import {
21
+ removeTrailingUnusedQubits,
20
22
  addControl,
21
23
  addOperation,
22
24
  findAndRemoveOperations,
23
25
  moveOperation,
24
26
  removeControl,
25
27
  removeOperation,
28
+ resolveOverlappingOperations,
26
29
  } from "./circuitManipulation";
27
30
  import {
28
- createGhostElement,
31
+ createGateGhost,
32
+ createQubitLabelGhost,
29
33
  createWireDropzone,
34
+ getColumnOffsetsAndWidths,
35
+ makeDropzoneBox,
30
36
  removeAllWireDropzones,
31
37
  } from "./draggable";
32
- import { getMinMaxRegIdx } from "../../src/utils";
38
+ import { getMinMaxRegIdx, getOperationRegisters } from "../../src/utils";
33
39
 
34
40
  let events: CircuitEvents | null = null;
35
41
 
@@ -54,9 +60,13 @@ class CircuitEvents {
54
60
  renderFn: () => void;
55
61
  componentGrid: ComponentGrid;
56
62
  qubits: Qubit[];
63
+ qubitUseCounts: number[];
57
64
  private circuitSvg: SVGElement;
58
65
  private dropzoneLayer: SVGGElement;
66
+ private ghostQubitLayer: SVGGElement;
67
+ private temporaryDropzones: SVGElement[] = [];
59
68
  private wireData: number[];
69
+ private columnXData: { xOffset: number; colWidth: number }[];
60
70
  private selectedOperation: Operation | null = null;
61
71
  private selectedWire: number | null = null;
62
72
  private movingControl: boolean = false;
@@ -75,11 +85,26 @@ class CircuitEvents {
75
85
  this.dropzoneLayer = container.querySelector(
76
86
  ".dropzone-layer",
77
87
  ) as SVGGElement;
88
+ this.ghostQubitLayer = container.querySelector(
89
+ ".ghost-qubit-layer",
90
+ ) as SVGGElement;
78
91
 
79
92
  this.componentGrid = sqore.circuit.componentGrid;
80
93
  this.qubits = sqore.circuit.qubits;
94
+ this.qubitUseCounts = new Array(this.qubits.length).fill(0);
95
+ for (const column of this.componentGrid) {
96
+ for (const op of column.components) {
97
+ this.incrementQubitUseCountForOp(op);
98
+ }
99
+ }
81
100
 
82
101
  this.wireData = getWireData(this.container);
102
+ this.columnXData = getColumnOffsetsAndWidths(this.container);
103
+ removeTrailingUnusedQubits(this);
104
+
105
+ if (this.qubits.length === 0) {
106
+ this.ghostQubitLayer.style.display = "block";
107
+ }
83
108
 
84
109
  this._addContextMenuEvent();
85
110
  this._addDropzoneLayerEvents();
@@ -87,7 +112,7 @@ class CircuitEvents {
87
112
  this._addGateElementsEvents();
88
113
  this._addToolboxElementsEvents();
89
114
  this._addDropzoneElementsEvents();
90
- this._addQubitLineControlEvents();
115
+ this._addQubitLineEvents();
91
116
  this._addDocumentEvents();
92
117
  }
93
118
 
@@ -130,44 +155,59 @@ class CircuitEvents {
130
155
  documentMouseupHandler = (ev: MouseEvent) => {
131
156
  const copying = ev.ctrlKey;
132
157
  this.container.classList.remove("moving", "copying");
133
- if (this.container) {
134
- const ghostElem = this.container.querySelector(".ghost");
135
- if (ghostElem) {
136
- this.container.removeChild(ghostElem);
137
- }
138
-
139
- // Handle deleting operations that have been dragged outside the circuit
140
- if (!this.mouseUpOnCircuit && this.dragging && !copying) {
141
- const selectedLocation = this.selectedOperation
142
- ? getGateLocationString(this.selectedOperation)
143
- : null;
144
- if (this.selectedOperation != null && selectedLocation != null) {
145
- // We are dragging a gate with a location (not from toolbox) outside the circuit
146
- // If we are moving a control, remove it from the selectedOperation
147
- if (
148
- this.movingControl &&
149
- this.selectedOperation.kind === "unitary" &&
150
- this.selectedOperation.controls != null &&
151
- this.selectedWire != null
152
- ) {
153
- const controlIndex = this.selectedOperation.controls.findIndex(
154
- (control) => control.qubit === this.selectedWire,
155
- );
156
- if (controlIndex !== -1)
157
- this.selectedOperation.controls.splice(controlIndex, 1);
158
- } else {
159
- // Otherwise, remove the selectedOperation
160
- removeOperation(this, selectedLocation);
161
- }
162
- this.renderFn();
158
+ // Handle deleting operations that have been dragged outside the circuit
159
+ if (!this.mouseUpOnCircuit && this.dragging && !copying) {
160
+ const selectedLocation = this.selectedOperation
161
+ ? getGateLocationString(this.selectedOperation)
162
+ : null;
163
+ if (this.selectedOperation != null && selectedLocation != null) {
164
+ // We are dragging a gate with a location (not from toolbox) outside the circuit
165
+ // If we are moving a control, remove it from the selectedOperation
166
+ if (
167
+ this.movingControl &&
168
+ this.selectedOperation.kind === "unitary" &&
169
+ this.selectedOperation.controls != null &&
170
+ this.selectedWire != null
171
+ ) {
172
+ const controlIndex = this.selectedOperation.controls.findIndex(
173
+ (control) => control.qubit === this.selectedWire,
174
+ );
175
+ if (controlIndex !== -1)
176
+ this.selectedOperation.controls.splice(controlIndex, 1);
177
+ } else {
178
+ // Otherwise, remove the selectedOperation
179
+ removeOperation(this, selectedLocation);
163
180
  }
181
+ this.renderFn();
182
+ } else if (this.selectedWire != null) {
183
+ // If we are dragging a qubit line, remove it
184
+ this.removeQubitLineWithConfirmation(this.selectedWire);
164
185
  }
165
186
  }
166
- this.dragging = false;
167
- this.disableLeftAutoScroll = false;
187
+
188
+ this._resetState();
189
+ };
190
+
191
+ /**
192
+ * Resets the internal state of the CircuitEvents instance after a drag or interaction.
193
+ * Clears selection, flags, and removes any temporary dropzones from the DOM.
194
+ * Note that this does not clear the selectedOperation as that is needed to be persistent
195
+ * for context-menu selections.
196
+ */
197
+ _resetState() {
198
+ this.selectedWire = null;
168
199
  this.movingControl = false;
169
200
  this.mouseUpOnCircuit = false;
170
- };
201
+ this.dragging = false;
202
+ this.disableLeftAutoScroll = false;
203
+
204
+ for (const dropzone of this.temporaryDropzones) {
205
+ if (dropzone.parentNode) {
206
+ dropzone.parentNode.removeChild(dropzone);
207
+ }
208
+ }
209
+ this.temporaryDropzones = [];
210
+ }
171
211
 
172
212
  /**
173
213
  * Enable auto-scrolling when dragging near the edges of the container
@@ -269,10 +309,12 @@ class CircuitEvents {
269
309
  * Add events specifically for dropzoneLayer
270
310
  */
271
311
  _addDropzoneLayerEvents() {
272
- this.container.addEventListener(
273
- "mouseup",
274
- () => (this.dropzoneLayer.style.display = "none"),
275
- );
312
+ this.container.addEventListener("mouseup", () => {
313
+ if (this.qubits.length !== 0) {
314
+ this.ghostQubitLayer.style.display = "none";
315
+ }
316
+ this.dropzoneLayer.style.display = "none";
317
+ });
276
318
 
277
319
  this.circuitSvg.addEventListener("mouseup", () => {
278
320
  this.mouseUpOnCircuit = true;
@@ -316,11 +358,11 @@ class CircuitEvents {
316
358
  elems.forEach((elem) => {
317
359
  elem?.addEventListener("mousedown", (ev: MouseEvent) => {
318
360
  // Allow dragging even when initiated on the arg-button
319
- if ((ev.target as HTMLElement).classList.contains("arg-button")) {
361
+ const argButtonElem = (ev.target as HTMLElement).closest(".arg-button");
362
+ if (argButtonElem) {
320
363
  // Find the sibling element with the data-wire attribute
321
- const siblingWithWire = (
322
- ev.target as HTMLElement
323
- ).parentElement?.querySelector("[data-wire]");
364
+ const siblingWithWire =
365
+ argButtonElem.parentElement?.querySelector("[data-wire]");
324
366
  if (siblingWithWire) {
325
367
  const selectedWireStr = siblingWithWire.getAttribute("data-wire");
326
368
  this.selectedWire =
@@ -339,7 +381,34 @@ class CircuitEvents {
339
381
  if (ev.button !== 0) return;
340
382
  ev.stopPropagation();
341
383
  removeAllWireDropzones(this.circuitSvg);
342
- if (this.selectedOperation == null || !selectedLocation) return;
384
+ if (
385
+ this.selectedOperation === null ||
386
+ this.selectedWire === null ||
387
+ !selectedLocation
388
+ )
389
+ return;
390
+
391
+ // Add temporary dropzones specific to this operation
392
+ const [minTarget, maxTarget] = getMinMaxRegIdx(
393
+ this.selectedOperation,
394
+ this.wireData.length,
395
+ );
396
+ for (let wire = minTarget; wire <= maxTarget; wire++) {
397
+ if (wire === this.selectedWire) continue;
398
+ const indexes = locationStringToIndexes(selectedLocation);
399
+ const [colIndex, opIndex] = indexes[indexes.length - 1];
400
+ const dropzone = makeDropzoneBox(
401
+ colIndex,
402
+ opIndex,
403
+ this.columnXData,
404
+ this.wireData,
405
+ wire,
406
+ false,
407
+ );
408
+ dropzone.addEventListener("mouseup", this.dropzoneMouseupHandler);
409
+ this.temporaryDropzones.push(dropzone);
410
+ this.dropzoneLayer.appendChild(dropzone);
411
+ }
343
412
 
344
413
  this._createGhostElement(ev);
345
414
 
@@ -353,6 +422,7 @@ class CircuitEvents {
353
422
  }
354
423
 
355
424
  this.container.classList.add("moving");
425
+ this.ghostQubitLayer.style.display = "block";
356
426
  this.dropzoneLayer.style.display = "block";
357
427
  });
358
428
 
@@ -381,6 +451,7 @@ class CircuitEvents {
381
451
  toolboxMousedownHandler = (ev: MouseEvent) => {
382
452
  if (ev.button !== 0) return;
383
453
  this.container.classList.add("moving");
454
+ this.ghostQubitLayer.style.display = "block";
384
455
  this.dropzoneLayer.style.display = "block";
385
456
  const elem = ev.currentTarget as HTMLElement;
386
457
  const type = elem.getAttribute("data-type");
@@ -410,61 +481,73 @@ class CircuitEvents {
410
481
  });
411
482
  }
412
483
 
413
- /**
414
- * Add events for dropzone elements
415
- */
416
- _addDropzoneElementsEvents() {
417
- const dropzoneElems =
418
- this.dropzoneLayer.querySelectorAll<SVGRectElement>(".dropzone");
419
- dropzoneElems.forEach((dropzoneElem) => {
420
- dropzoneElem.addEventListener("mouseup", async (ev: MouseEvent) => {
421
- const copying = ev.ctrlKey;
422
- // Create a deep copy of the component grid
423
- const originalGrid = JSON.parse(
424
- JSON.stringify(this.componentGrid),
425
- ) as ComponentGrid;
426
- const targetLoc = dropzoneElem.getAttribute("data-dropzone-location");
427
- const insertNewColumn =
428
- dropzoneElem.getAttribute("data-dropzone-inter-column") == "true" ||
429
- false;
430
- const targetWireStr = dropzoneElem.getAttribute("data-dropzone-wire");
431
- const targetWire =
432
- targetWireStr != null ? parseInt(targetWireStr) : null;
484
+ dropzoneMouseupHandler = async (ev: MouseEvent) => {
485
+ const dropzoneElem = ev.currentTarget as SVGRectElement;
486
+ const copying = ev.ctrlKey;
487
+ // Create a deep copy of the component grid
488
+ const originalGrid = JSON.parse(
489
+ JSON.stringify(this.componentGrid),
490
+ ) as ComponentGrid;
491
+ const targetLoc = dropzoneElem.getAttribute("data-dropzone-location");
492
+ const insertNewColumn =
493
+ dropzoneElem.getAttribute("data-dropzone-inter-column") == "true" ||
494
+ false;
495
+ const targetWireStr = dropzoneElem.getAttribute("data-dropzone-wire");
496
+ const targetWire = targetWireStr != null ? parseInt(targetWireStr) : null;
433
497
 
434
- if (
435
- targetLoc == null ||
436
- targetWire == null ||
437
- this.selectedOperation == null
438
- )
498
+ if (
499
+ targetLoc == null ||
500
+ targetWire == null ||
501
+ this.selectedOperation == null
502
+ )
503
+ return;
504
+ const sourceLocation = getGateLocationString(this.selectedOperation);
505
+
506
+ if (sourceLocation == null) {
507
+ if (
508
+ this.selectedOperation.params != undefined &&
509
+ (this.selectedOperation.args === undefined ||
510
+ this.selectedOperation.args.length === 0)
511
+ ) {
512
+ // Prompt for arguments and wait for user input
513
+ const args = await promptForArguments(this.selectedOperation.params);
514
+ if (!args || args.length === 0) {
515
+ // User canceled the prompt, exit early
439
516
  return;
440
- const sourceLocation = getGateLocationString(this.selectedOperation);
441
-
442
- if (sourceLocation == null) {
443
- if (
444
- this.selectedOperation.params != undefined &&
445
- (this.selectedOperation.args === undefined ||
446
- this.selectedOperation.args.length === 0)
447
- ) {
448
- // Prompt for arguments and wait for user input
449
- const args = await promptForArguments(
450
- this.selectedOperation.params,
451
- );
452
- if (!args || args.length === 0) {
453
- // User canceled the prompt, exit early
454
- return;
455
- }
517
+ }
456
518
 
457
- // Create a deep copy of the source operation
458
- this.selectedOperation = JSON.parse(
459
- JSON.stringify(this.selectedOperation),
460
- );
461
- if (this.selectedOperation == null) return;
519
+ // Create a deep copy of the source operation
520
+ this.selectedOperation = JSON.parse(
521
+ JSON.stringify(this.selectedOperation),
522
+ );
523
+ if (this.selectedOperation == null) return;
462
524
 
463
- // Assign the arguments to the selected operation
464
- this.selectedOperation.args = args;
465
- }
525
+ // Assign the arguments to the selected operation
526
+ this.selectedOperation.args = args;
527
+ }
466
528
 
467
- // Add a new operation from the toolbox
529
+ // Add a new operation from the toolbox
530
+ addOperation(
531
+ this,
532
+ this.selectedOperation,
533
+ targetLoc,
534
+ targetWire,
535
+ insertNewColumn,
536
+ );
537
+ } else if (sourceLocation && this.selectedWire != null) {
538
+ if (copying) {
539
+ if (this.movingControl && this.selectedOperation.kind === "unitary") {
540
+ addControl(this, this.selectedOperation, targetWire);
541
+ moveOperation(
542
+ this,
543
+ sourceLocation,
544
+ targetLoc,
545
+ this.selectedWire,
546
+ targetWire,
547
+ this.movingControl,
548
+ insertNewColumn,
549
+ );
550
+ } else {
468
551
  addOperation(
469
552
  this,
470
553
  this.selectedOperation,
@@ -472,126 +555,232 @@ class CircuitEvents {
472
555
  targetWire,
473
556
  insertNewColumn,
474
557
  );
475
- } else if (sourceLocation && this.selectedWire != null) {
476
- if (copying) {
477
- if (
478
- this.movingControl &&
479
- this.selectedOperation.kind === "unitary"
558
+ }
559
+ } else {
560
+ moveOperation(
561
+ this,
562
+ sourceLocation,
563
+ targetLoc,
564
+ this.selectedWire,
565
+ targetWire,
566
+ this.movingControl,
567
+ insertNewColumn,
568
+ );
569
+ }
570
+ }
571
+
572
+ this.selectedOperation = null;
573
+ this._resetState();
574
+
575
+ if (!deepEqual(originalGrid, this.componentGrid)) this.renderFn();
576
+ };
577
+
578
+ /**
579
+ * Add events for dropzone elements
580
+ */
581
+ _addDropzoneElementsEvents() {
582
+ const dropzoneElems =
583
+ this.dropzoneLayer.querySelectorAll<SVGRectElement>(".dropzone");
584
+ dropzoneElems.forEach((dropzoneElem) => {
585
+ dropzoneElem.addEventListener("mouseup", this.dropzoneMouseupHandler);
586
+ });
587
+ }
588
+
589
+ /**
590
+ * Handler for mouseup on qubit line dropzones.
591
+ * @param sourceWire The index of the source wire (being dragged).
592
+ * @param targetWire The index of the target wire (drop location).
593
+ * @param isBetween If true, creates a dropzone between wires.
594
+ */
595
+ qubitDropzoneMouseupHandler = (
596
+ sourceWire: number,
597
+ targetWire: number,
598
+ isBetween: boolean,
599
+ ) => {
600
+ if (sourceWire === targetWire || sourceWire == null || targetWire == null)
601
+ return;
602
+
603
+ // Helper to move an array element
604
+ function moveArrayElement<T>(arr: T[], from: number, to: number) {
605
+ const el = arr.splice(from, 1)[0];
606
+ arr.splice(to, 0, el);
607
+ }
608
+
609
+ // Update qubits array
610
+ if (isBetween) {
611
+ // Moving sourceWire to just before targetWire
612
+ let insertAt = targetWire;
613
+ // If moving down and passing over itself, adjust index
614
+ if (sourceWire < insertAt) insertAt--;
615
+ moveArrayElement(this.qubits, sourceWire, insertAt);
616
+ moveArrayElement(this.qubitUseCounts, sourceWire, insertAt);
617
+ } else {
618
+ // Swap sourceWire and targetWire
619
+ [this.qubits[sourceWire], this.qubits[targetWire]] = [
620
+ this.qubits[targetWire],
621
+ this.qubits[sourceWire],
622
+ ];
623
+ [this.qubitUseCounts[sourceWire], this.qubitUseCounts[targetWire]] = [
624
+ this.qubitUseCounts[targetWire],
625
+ this.qubitUseCounts[sourceWire],
626
+ ];
627
+ }
628
+
629
+ // Update qubit ids to match their new positions
630
+ this.qubits.forEach((q, idx) => {
631
+ q.id = idx;
632
+ });
633
+
634
+ // Update all operations in componentGrid to reflect new qubit order
635
+ for (const column of this.componentGrid) {
636
+ for (const op of column.components) {
637
+ getOperationRegisters(op).forEach((reg) => {
638
+ if (isBetween) {
639
+ // Move: update qubit indices
640
+ if (reg.qubit === sourceWire) {
641
+ reg.qubit = sourceWire < targetWire ? targetWire - 1 : targetWire;
642
+ } else if (
643
+ sourceWire < targetWire &&
644
+ reg.qubit > sourceWire &&
645
+ reg.qubit < targetWire
480
646
  ) {
481
- addControl(this.selectedOperation, targetWire);
482
- moveOperation(
483
- this,
484
- sourceLocation,
485
- targetLoc,
486
- this.selectedWire,
487
- targetWire,
488
- this.movingControl,
489
- insertNewColumn,
490
- );
491
- } else {
492
- addOperation(
493
- this,
494
- this.selectedOperation,
495
- targetLoc,
496
- targetWire,
497
- insertNewColumn,
498
- );
647
+ reg.qubit -= 1;
648
+ } else if (
649
+ sourceWire > targetWire &&
650
+ reg.qubit >= targetWire &&
651
+ reg.qubit < sourceWire
652
+ ) {
653
+ reg.qubit += 1;
499
654
  }
500
655
  } else {
501
- moveOperation(
502
- this,
503
- sourceLocation,
504
- targetLoc,
505
- this.selectedWire,
506
- targetWire,
507
- this.movingControl,
508
- insertNewColumn,
509
- );
656
+ // Swap: swap indices
657
+ if (reg.qubit === sourceWire) reg.qubit = targetWire;
658
+ else if (reg.qubit === targetWire) reg.qubit = sourceWire;
510
659
  }
511
- }
660
+ });
661
+ }
662
+ // Sort operations in this column by their lowest-numbered register
663
+ column.components.sort((a, b) => {
664
+ const aRegs = getOperationRegisters(a);
665
+ const bRegs = getOperationRegisters(b);
666
+ const aMin = Math.min(...aRegs.map((r) => r.qubit));
667
+ const bMin = Math.min(...bRegs.map((r) => r.qubit));
668
+ return aMin - bMin;
669
+ });
670
+ }
671
+
672
+ // Resolve overlapping operations into their own columns
673
+ resolveOverlappingOperations(this.componentGrid);
674
+ removeTrailingUnusedQubits(this);
675
+ this.renderFn();
676
+ };
512
677
 
513
- this.selectedWire = null;
678
+ /**
679
+ * Add events for qubit line labels
680
+ */
681
+ _addQubitLineEvents() {
682
+ const elems = getQubitLabelElems(this.container);
683
+ elems.forEach((elem) => {
684
+ elem.addEventListener("mousedown", (ev: MouseEvent) => {
685
+ ev.stopPropagation();
514
686
  this.selectedOperation = null;
515
- this.movingControl = false;
687
+ this._createQubitLabelGhost(ev, elem);
688
+
689
+ const sourceIndexStr = elem.getAttribute("data-wire");
690
+ const sourceWire =
691
+ sourceIndexStr != null ? parseInt(sourceIndexStr) : null;
692
+ if (sourceWire == null) return;
693
+ this.selectedWire = sourceWire;
694
+
695
+ // Dropzones ON each wire (skip self)
696
+ // Exclude ghost qubit line (last wire)
697
+ for (
698
+ let targetWire = 0;
699
+ targetWire < this.wireData.length - 1; // Exclude ghost
700
+ targetWire++
701
+ ) {
702
+ if (targetWire === sourceWire) continue;
703
+ const dropzone = createWireDropzone(
704
+ this.circuitSvg,
705
+ this.wireData,
706
+ targetWire,
707
+ );
708
+ dropzone.addEventListener("mouseup", () =>
709
+ this.qubitDropzoneMouseupHandler(sourceWire, targetWire, false),
710
+ );
711
+ this.temporaryDropzones.push(dropzone);
712
+ this.circuitSvg.appendChild(dropzone);
713
+ }
516
714
 
517
- if (!deepEqual(originalGrid, this.componentGrid)) this.renderFn();
715
+ // Dropzones BETWEEN wires (including before first and after last)
716
+ // Exclude after ghost qubit line
717
+ for (let i = 0; i <= this.wireData.length - 1; i++) {
718
+ // Optionally, skip if dropping "between" at the source wire's own position
719
+ if (i === sourceWire || i === sourceWire + 1) continue;
720
+ const dropzone = createWireDropzone(
721
+ this.circuitSvg,
722
+ this.wireData,
723
+ i,
724
+ true,
725
+ );
726
+ dropzone.addEventListener("mouseup", () =>
727
+ this.qubitDropzoneMouseupHandler(sourceWire, i, true),
728
+ );
729
+ this.temporaryDropzones.push(dropzone);
730
+ this.circuitSvg.appendChild(dropzone);
731
+ }
518
732
  });
733
+ elem.style.pointerEvents = "all";
519
734
  });
520
735
  }
521
736
 
522
737
  /**
523
- * Add event listeners for the buttons to add or remove qubit lines.
524
- * The add button will append a new qubit line to the circuit.
525
- * The remove button will remove the last qubit line from the circuit,
526
- * along with any operations associated with it.
738
+ * Removes a qubit line by index, with confirmation if it has associated operations.
739
+ * @param qubitIdx The index of the qubit to remove.
527
740
  */
528
- _addQubitLineControlEvents() {
529
- const addQubitLineButton = this.container.querySelector(".add-qubit-line");
530
- const removeQubitLineButton =
531
- this.container.querySelector(".remove-qubit-line");
741
+ removeQubitLineWithConfirmation(qubitIdx: number) {
742
+ // Count number of operations associated with the qubit line
743
+ const numOperations = this.qubitUseCounts[qubitIdx];
744
+
745
+ const doRemove = () => {
746
+ // Remove the qubit
747
+ this.qubits.splice(qubitIdx, 1);
748
+ this.qubitUseCounts.splice(qubitIdx, 1);
749
+ this.wireData.splice(qubitIdx, 1);
750
+ removeTrailingUnusedQubits(this);
751
+
752
+ // Update all remaining operation references
753
+ for (const column of this.componentGrid) {
754
+ for (const op of column.components) {
755
+ getOperationRegisters(op).forEach((reg) => {
756
+ if (reg.qubit > qubitIdx) reg.qubit -= 1;
757
+ });
758
+ }
759
+ }
532
760
 
533
- if (
534
- addQubitLineButton &&
535
- !addQubitLineButton.hasAttribute("data-event-added")
536
- ) {
537
- addQubitLineButton.addEventListener("click", () => {
538
- this.qubits.push({ id: this.qubits.length });
539
- this.renderFn();
761
+ // Update qubit ids to match their new positions
762
+ this.qubits.forEach((q, idx) => {
763
+ q.id = idx;
540
764
  });
541
- addQubitLineButton.setAttribute("data-event-added", "true");
542
- }
543
765
 
544
- if (
545
- removeQubitLineButton &&
546
- !removeQubitLineButton.hasAttribute("data-event-added")
547
- ) {
548
- removeQubitLineButton.addEventListener("click", () => {
549
- // Determines if the operation is associated with the last qubit line
550
- const check = (op: Operation) => {
551
- const targets = op.kind === "measurement" ? op.results : op.targets;
552
- if (targets.some((reg) => reg.qubit == this.qubits.length - 1)) {
553
- return true;
554
- }
555
- const controls =
556
- op.kind === "measurement"
557
- ? op.qubits
558
- : op.kind === "ket"
559
- ? []
560
- : op.controls;
561
- if (
562
- controls &&
563
- controls.some((reg) => reg.qubit == this.qubits.length - 1)
564
- ) {
565
- return true;
566
- }
567
- return false;
568
- };
569
-
570
- // Count number of operations associated with the last qubit line
571
- const numOperations = this.componentGrid.reduce(
572
- (acc, column) =>
573
- acc + column.components.filter((op) => check(op)).length,
574
- 0,
575
- );
576
- if (numOperations === 0) {
577
- this.qubits.pop();
578
- this.renderFn();
579
- } else {
580
- const message =
581
- numOperations === 1
582
- ? `There is ${numOperations} operation associated with the last qubit line. Do you want to remove it?`
583
- : `There are ${numOperations} operations associated with the last qubit line. Do you want to remove them?`;
584
- _createConfirmPrompt(message, (confirmed) => {
585
- if (confirmed) {
586
- // Remove all operations associated with the last qubit line
587
- findAndRemoveOperations(this.componentGrid, check);
588
- this.qubits.pop();
589
- this.renderFn();
590
- }
591
- });
766
+ this.renderFn();
767
+ };
768
+
769
+ if (numOperations === 0) {
770
+ doRemove();
771
+ } else {
772
+ const message =
773
+ numOperations === 1
774
+ ? `There is 1 operation associated with this qubit line. Do you want to remove it?`
775
+ : `There are ${numOperations} operations associated with this qubit line. Do you want to remove them?`;
776
+ _createConfirmPrompt(message, (confirmed) => {
777
+ if (confirmed) {
778
+ findAndRemoveOperations(this, (op: Operation) =>
779
+ getOperationRegisters(op).some((reg) => reg.qubit == qubitIdx),
780
+ );
781
+ doRemove();
592
782
  }
593
783
  });
594
- removeQubitLineButton.setAttribute("data-event-added", "true");
595
784
  }
596
785
  }
597
786
 
@@ -599,6 +788,38 @@ class CircuitEvents {
599
788
  * Misc. *
600
789
  *****************/
601
790
 
791
+ /**
792
+ * Increment the use count for qubits used by the operation.
793
+ * @param op The operation to increment use counts for.
794
+ */
795
+ incrementQubitUseCountForOp(op: Operation) {
796
+ getOperationRegisters(op).forEach((reg) => {
797
+ if (
798
+ reg.result === undefined &&
799
+ reg.qubit >= 0 &&
800
+ reg.qubit < this.qubitUseCounts.length
801
+ ) {
802
+ this.qubitUseCounts[reg.qubit]++;
803
+ }
804
+ });
805
+ }
806
+
807
+ /**
808
+ * Decrement the use count for qubits used by the operation.
809
+ * @param op The operation to decrement the use count for.
810
+ */
811
+ decrementQubitUseCountForOp(op: Operation) {
812
+ getOperationRegisters(op).forEach((reg) => {
813
+ if (
814
+ reg.result === undefined &&
815
+ reg.qubit >= 0 &&
816
+ reg.qubit < this.qubitUseCounts.length
817
+ ) {
818
+ this.qubitUseCounts[reg.qubit]--;
819
+ }
820
+ });
821
+ }
822
+
602
823
  /**
603
824
  * Creates a ghost element for visual feedback during dragging.
604
825
  * This function initializes the dragging state, enables auto-scrolling,
@@ -610,7 +831,7 @@ class CircuitEvents {
610
831
  if (this.selectedOperation == null) return;
611
832
  this.dragging = true;
612
833
  this._enableAutoScroll();
613
- createGhostElement(
834
+ createGateGhost(
614
835
  ev,
615
836
  this.container,
616
837
  this.selectedOperation,
@@ -618,6 +839,12 @@ class CircuitEvents {
618
839
  );
619
840
  }
620
841
 
842
+ _createQubitLabelGhost(ev: MouseEvent, elem: SVGTextElement) {
843
+ this.dragging = true;
844
+ this._enableAutoScroll();
845
+ createQubitLabelGhost(ev, this.container, elem);
846
+ }
847
+
621
848
  /**
622
849
  * Start the process of adding a control to the selected operation.
623
850
  * This function creates dropzones for each wire that isn't already a target or control.
@@ -628,6 +855,7 @@ class CircuitEvents {
628
855
  _startAddingControl(selectedOperation: Unitary, selectedLocation: string) {
629
856
  this.selectedOperation = selectedOperation;
630
857
  this.container.classList.add("adding-control");
858
+ this.ghostQubitLayer.style.display = "block";
631
859
 
632
860
  // Create dropzones for each wire that isn't already a target or control
633
861
  for (let wireIndex = 0; wireIndex < this.wireData.length; wireIndex++) {
@@ -652,9 +880,14 @@ class CircuitEvents {
652
880
  this.selectedOperation != null &&
653
881
  this.selectedOperation.kind === "unitary"
654
882
  ) {
655
- const successful = addControl(this.selectedOperation, wireIndex);
883
+ const successful = addControl(
884
+ this,
885
+ this.selectedOperation,
886
+ wireIndex,
887
+ );
656
888
  this.selectedOperation = null;
657
889
  this.container.classList.remove("adding-control");
890
+ this.ghostQubitLayer.style.display = "none";
658
891
  if (successful) {
659
892
  const indexes = locationStringToIndexes(selectedLocation);
660
893
  const [columnIndex, position] = indexes[indexes.length - 1];
@@ -738,6 +971,7 @@ class CircuitEvents {
738
971
  this.selectedOperation.kind === "unitary"
739
972
  ) {
740
973
  const successful = removeControl(
974
+ this,
741
975
  this.selectedOperation,
742
976
  control.qubit,
743
977
  );