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.
- package/dist/browser.d.ts +2 -2
- package/dist/compiler/compiler.d.ts +3 -1
- package/dist/compiler/compiler.js +5 -1
- package/dist/samples.generated.js +1 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +22 -8
- package/docs/Microsoft.Quantum.Core/Length.md +1 -1
- package/docs/Microsoft.Quantum.Core/Repeated.md +1 -1
- package/docs/Microsoft.Quantum.Core/index.md +1 -1
- package/docs/Std.Arithmetic/AddLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfEqualL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfEqualLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfGreaterOrEqualLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessLE.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessOrEqualL.md +1 -1
- package/docs/Std.Arithmetic/ApplyIfLessOrEqualLE.md +1 -1
- package/docs/Std.Arithmetic/FourierTDIncByLE.md +1 -1
- package/docs/Std.Arithmetic/IncByI.md +1 -1
- package/docs/Std.Arithmetic/IncByIUsingIncByLE.md +1 -1
- package/docs/Std.Arithmetic/IncByL.md +1 -1
- package/docs/Std.Arithmetic/IncByLE.md +1 -1
- package/docs/Std.Arithmetic/IncByLEUsingAddLE.md +1 -1
- package/docs/Std.Arithmetic/IncByLUsingIncByLE.md +1 -1
- package/docs/Std.Arithmetic/LookAheadDKRSAddLE.md +1 -1
- package/docs/Std.Arithmetic/MAJ.md +1 -1
- package/docs/Std.Arithmetic/ReflectAboutInteger.md +1 -1
- package/docs/Std.Arithmetic/RippleCarryCGAddLE.md +1 -1
- package/docs/Std.Arithmetic/RippleCarryCGIncByLE.md +1 -1
- package/docs/Std.Arithmetic/RippleCarryTTKIncByLE.md +1 -1
- package/docs/Std.Arithmetic/index.md +1 -1
- package/docs/Std.Arrays/All.md +1 -1
- package/docs/Std.Arrays/Any.md +1 -1
- package/docs/Std.Arrays/Chunks.md +1 -1
- package/docs/Std.Arrays/CircularlyShifted.md +1 -1
- package/docs/Std.Arrays/ColumnAt.md +1 -1
- package/docs/Std.Arrays/Count.md +1 -1
- package/docs/Std.Arrays/Diagonal.md +1 -1
- package/docs/Std.Arrays/DrawMany.md +1 -1
- package/docs/Std.Arrays/Enumerated.md +1 -1
- package/docs/Std.Arrays/Excluding.md +1 -1
- package/docs/Std.Arrays/Filtered.md +1 -1
- package/docs/Std.Arrays/FlatMapped.md +1 -1
- package/docs/Std.Arrays/Flattened.md +1 -1
- package/docs/Std.Arrays/Fold.md +1 -1
- package/docs/Std.Arrays/ForEach.md +1 -1
- package/docs/Std.Arrays/Head.md +1 -1
- package/docs/Std.Arrays/HeadAndRest.md +1 -1
- package/docs/Std.Arrays/IndexOf.md +1 -1
- package/docs/Std.Arrays/IndexRange.md +1 -1
- package/docs/Std.Arrays/Interleaved.md +1 -1
- package/docs/Std.Arrays/IsEmpty.md +1 -1
- package/docs/Std.Arrays/IsRectangularArray.md +1 -1
- package/docs/Std.Arrays/IsSorted.md +1 -1
- package/docs/Std.Arrays/IsSquareArray.md +1 -1
- package/docs/Std.Arrays/Mapped.md +1 -1
- package/docs/Std.Arrays/MappedByIndex.md +1 -1
- package/docs/Std.Arrays/MappedOverRange.md +1 -1
- package/docs/Std.Arrays/Most.md +1 -1
- package/docs/Std.Arrays/MostAndTail.md +1 -1
- package/docs/Std.Arrays/Padded.md +1 -1
- package/docs/Std.Arrays/Partitioned.md +1 -1
- package/docs/Std.Arrays/Rest.md +1 -1
- package/docs/Std.Arrays/Reversed.md +1 -1
- package/docs/Std.Arrays/SequenceI.md +1 -1
- package/docs/Std.Arrays/SequenceL.md +1 -1
- package/docs/Std.Arrays/Sorted.md +1 -1
- package/docs/Std.Arrays/Subarray.md +1 -1
- package/docs/Std.Arrays/Swapped.md +1 -1
- package/docs/Std.Arrays/Tail.md +1 -1
- package/docs/Std.Arrays/Transposed.md +1 -1
- package/docs/Std.Arrays/Unzipped.md +1 -1
- package/docs/Std.Arrays/Where.md +1 -1
- package/docs/Std.Arrays/Windows.md +1 -1
- package/docs/Std.Arrays/Zipped.md +1 -1
- package/docs/Std.Arrays/index.md +1 -1
- package/docs/Std.Canon/ApplyCNOTChain.md +1 -1
- package/docs/Std.Canon/ApplyControlledOnBitString.md +1 -1
- package/docs/Std.Canon/ApplyControlledOnInt.md +1 -1
- package/docs/Std.Canon/ApplyOperationPowerA.md +1 -1
- package/docs/Std.Canon/ApplyP.md +1 -1
- package/docs/Std.Canon/ApplyPauli.md +1 -1
- package/docs/Std.Canon/ApplyPauliFromBitString.md +1 -1
- package/docs/Std.Canon/ApplyPauliFromInt.md +1 -1
- package/docs/Std.Canon/ApplyQFT.md +1 -1
- package/docs/Std.Canon/ApplyToEach.md +1 -1
- package/docs/Std.Canon/ApplyToEachA.md +1 -1
- package/docs/Std.Canon/ApplyToEachC.md +1 -1
- package/docs/Std.Canon/ApplyToEachCA.md +1 -1
- package/docs/Std.Canon/ApplyXorInPlace.md +1 -1
- package/docs/Std.Canon/ApplyXorInPlaceL.md +1 -1
- package/docs/Std.Canon/CX.md +1 -1
- package/docs/Std.Canon/CY.md +1 -1
- package/docs/Std.Canon/CZ.md +1 -1
- package/docs/Std.Canon/Fst.md +1 -1
- package/docs/Std.Canon/Relabel.md +1 -1
- package/docs/Std.Canon/Snd.md +1 -1
- package/docs/Std.Canon/SwapReverseRegister.md +1 -1
- package/docs/Std.Canon/index.md +1 -1
- package/docs/Std.Convert/BigIntAsBoolArray.md +1 -1
- package/docs/Std.Convert/BigIntAsInt.md +1 -1
- package/docs/Std.Convert/BoolArrayAsBigInt.md +1 -1
- package/docs/Std.Convert/BoolArrayAsInt.md +1 -1
- package/docs/Std.Convert/BoolArrayAsResultArray.md +1 -1
- package/docs/Std.Convert/BoolAsResult.md +1 -1
- package/docs/Std.Convert/ComplexAsComplexPolar.md +1 -1
- package/docs/Std.Convert/ComplexPolarAsComplex.md +1 -1
- package/docs/Std.Convert/DoubleAsStringWithPrecision.md +1 -1
- package/docs/Std.Convert/IntAsBigInt.md +1 -1
- package/docs/Std.Convert/IntAsBoolArray.md +1 -1
- package/docs/Std.Convert/IntAsDouble.md +1 -1
- package/docs/Std.Convert/ResultArrayAsBoolArray.md +1 -1
- package/docs/Std.Convert/ResultArrayAsInt.md +1 -1
- package/docs/Std.Convert/ResultAsBool.md +1 -1
- package/docs/Std.Convert/index.md +1 -1
- package/docs/Std.Core/Length.md +1 -1
- package/docs/Std.Core/Repeated.md +1 -1
- package/docs/Std.Core/index.md +1 -1
- package/docs/Std.Diagnostics/ApplyIdleNoise.md +1 -1
- package/docs/Std.Diagnostics/BitFlipNoise.md +1 -1
- package/docs/Std.Diagnostics/CheckAllZero.md +1 -1
- package/docs/Std.Diagnostics/CheckOperationsAreEqual.md +1 -1
- package/docs/Std.Diagnostics/CheckZero.md +1 -1
- package/docs/Std.Diagnostics/ConfigurePauliNoise.md +1 -1
- package/docs/Std.Diagnostics/DepolarizingNoise.md +1 -1
- package/docs/Std.Diagnostics/DumpMachine.md +1 -1
- package/docs/Std.Diagnostics/DumpOperation.md +1 -1
- package/docs/Std.Diagnostics/DumpRegister.md +1 -1
- package/docs/Std.Diagnostics/Fact.md +1 -1
- package/docs/Std.Diagnostics/NoNoise.md +1 -1
- package/docs/Std.Diagnostics/PhaseFlipNoise.md +1 -1
- package/docs/Std.Diagnostics/StartCountingFunction.md +1 -1
- package/docs/Std.Diagnostics/StartCountingOperation.md +1 -1
- package/docs/Std.Diagnostics/StartCountingQubits.md +1 -1
- package/docs/Std.Diagnostics/StopCountingFunction.md +1 -1
- package/docs/Std.Diagnostics/StopCountingOperation.md +1 -1
- package/docs/Std.Diagnostics/StopCountingQubits.md +1 -1
- package/docs/Std.Diagnostics/index.md +1 -1
- package/docs/Std.Intrinsic/AND.md +1 -1
- package/docs/Std.Intrinsic/ApplyUnitary.md +1 -1
- package/docs/Std.Intrinsic/CCNOT.md +1 -1
- package/docs/Std.Intrinsic/CNOT.md +1 -1
- package/docs/Std.Intrinsic/Exp.md +1 -1
- package/docs/Std.Intrinsic/H.md +1 -1
- package/docs/Std.Intrinsic/I.md +1 -1
- package/docs/Std.Intrinsic/M.md +1 -1
- package/docs/Std.Intrinsic/Measure.md +1 -1
- package/docs/Std.Intrinsic/Message.md +1 -1
- package/docs/Std.Intrinsic/R.md +1 -1
- package/docs/Std.Intrinsic/R1.md +1 -1
- package/docs/Std.Intrinsic/R1Frac.md +1 -1
- package/docs/Std.Intrinsic/RFrac.md +1 -1
- package/docs/Std.Intrinsic/Reset.md +1 -1
- package/docs/Std.Intrinsic/ResetAll.md +1 -1
- package/docs/Std.Intrinsic/Rx.md +1 -1
- package/docs/Std.Intrinsic/Rxx.md +1 -1
- package/docs/Std.Intrinsic/Ry.md +1 -1
- package/docs/Std.Intrinsic/Ryy.md +1 -1
- package/docs/Std.Intrinsic/Rz.md +1 -1
- package/docs/Std.Intrinsic/Rzz.md +1 -1
- package/docs/Std.Intrinsic/S.md +1 -1
- package/docs/Std.Intrinsic/SWAP.md +1 -1
- package/docs/Std.Intrinsic/SX.md +38 -0
- package/docs/Std.Intrinsic/T.md +1 -1
- package/docs/Std.Intrinsic/X.md +1 -1
- package/docs/Std.Intrinsic/Y.md +1 -1
- package/docs/Std.Intrinsic/Z.md +1 -1
- package/docs/Std.Intrinsic/index.md +2 -1
- package/docs/Std.Logical/Xor.md +1 -1
- package/docs/Std.Logical/index.md +1 -1
- package/docs/Std.Math/AbsComplex.md +1 -1
- package/docs/Std.Math/AbsComplexPolar.md +1 -1
- package/docs/Std.Math/AbsD.md +1 -1
- package/docs/Std.Math/AbsI.md +1 -1
- package/docs/Std.Math/AbsL.md +1 -1
- package/docs/Std.Math/AbsSquaredComplex.md +1 -1
- package/docs/Std.Math/AbsSquaredComplexPolar.md +1 -1
- package/docs/Std.Math/ApproximateFactorial.md +1 -1
- package/docs/Std.Math/ArcCos.md +1 -1
- package/docs/Std.Math/ArcCosh.md +1 -1
- package/docs/Std.Math/ArcSin.md +1 -1
- package/docs/Std.Math/ArcSinh.md +1 -1
- package/docs/Std.Math/ArcTan.md +1 -1
- package/docs/Std.Math/ArcTan2.md +1 -1
- package/docs/Std.Math/ArcTanh.md +1 -1
- package/docs/Std.Math/ArgComplex.md +1 -1
- package/docs/Std.Math/ArgComplexPolar.md +1 -1
- package/docs/Std.Math/Binom.md +1 -1
- package/docs/Std.Math/BitSizeI.md +1 -1
- package/docs/Std.Math/BitSizeL.md +1 -1
- package/docs/Std.Math/Ceiling.md +1 -1
- package/docs/Std.Math/Complex.md +1 -1
- package/docs/Std.Math/ComplexPolar.md +1 -1
- package/docs/Std.Math/ContinuedFractionConvergentI.md +1 -1
- package/docs/Std.Math/ContinuedFractionConvergentL.md +1 -1
- package/docs/Std.Math/Cos.md +1 -1
- package/docs/Std.Math/Cosh.md +1 -1
- package/docs/Std.Math/DivRemI.md +1 -1
- package/docs/Std.Math/DivRemL.md +1 -1
- package/docs/Std.Math/DividedByC.md +1 -1
- package/docs/Std.Math/DividedByCP.md +1 -1
- package/docs/Std.Math/E.md +1 -1
- package/docs/Std.Math/ExpModI.md +1 -1
- package/docs/Std.Math/ExpModL.md +1 -1
- package/docs/Std.Math/ExtendedGreatestCommonDivisorI.md +1 -1
- package/docs/Std.Math/ExtendedGreatestCommonDivisorL.md +1 -1
- package/docs/Std.Math/FactorialI.md +1 -1
- package/docs/Std.Math/FactorialL.md +1 -1
- package/docs/Std.Math/Floor.md +1 -1
- package/docs/Std.Math/GreatestCommonDivisorI.md +1 -1
- package/docs/Std.Math/GreatestCommonDivisorL.md +1 -1
- package/docs/Std.Math/HammingWeightI.md +1 -1
- package/docs/Std.Math/InverseModI.md +1 -1
- package/docs/Std.Math/InverseModL.md +1 -1
- package/docs/Std.Math/IsCoprimeI.md +1 -1
- package/docs/Std.Math/IsCoprimeL.md +1 -1
- package/docs/Std.Math/IsInfinite.md +1 -1
- package/docs/Std.Math/IsNaN.md +1 -1
- package/docs/Std.Math/LargestFixedPoint.md +1 -1
- package/docs/Std.Math/Lg.md +1 -1
- package/docs/Std.Math/Log.md +1 -1
- package/docs/Std.Math/Log10.md +1 -1
- package/docs/Std.Math/LogFactorialD.md +1 -1
- package/docs/Std.Math/LogGammaD.md +1 -1
- package/docs/Std.Math/LogOf2.md +1 -1
- package/docs/Std.Math/Max.md +1 -1
- package/docs/Std.Math/MaxD.md +1 -1
- package/docs/Std.Math/MaxI.md +1 -1
- package/docs/Std.Math/MaxL.md +1 -1
- package/docs/Std.Math/Min.md +1 -1
- package/docs/Std.Math/MinD.md +1 -1
- package/docs/Std.Math/MinI.md +1 -1
- package/docs/Std.Math/MinL.md +1 -1
- package/docs/Std.Math/MinusC.md +1 -1
- package/docs/Std.Math/MinusCP.md +1 -1
- package/docs/Std.Math/ModulusI.md +1 -1
- package/docs/Std.Math/ModulusL.md +1 -1
- package/docs/Std.Math/NegationC.md +1 -1
- package/docs/Std.Math/NegationCP.md +1 -1
- package/docs/Std.Math/PI.md +1 -1
- package/docs/Std.Math/PNorm.md +1 -1
- package/docs/Std.Math/PNormalized.md +1 -1
- package/docs/Std.Math/PlusC.md +1 -1
- package/docs/Std.Math/PlusCP.md +1 -1
- package/docs/Std.Math/PowC.md +1 -1
- package/docs/Std.Math/PowCP.md +1 -1
- package/docs/Std.Math/RealMod.md +1 -1
- package/docs/Std.Math/Round.md +1 -1
- package/docs/Std.Math/RoundHalfAwayFromZero.md +1 -1
- package/docs/Std.Math/SignD.md +1 -1
- package/docs/Std.Math/SignI.md +1 -1
- package/docs/Std.Math/SignL.md +1 -1
- package/docs/Std.Math/Sin.md +1 -1
- package/docs/Std.Math/Sinh.md +1 -1
- package/docs/Std.Math/SmallestFixedPoint.md +1 -1
- package/docs/Std.Math/Sqrt.md +1 -1
- package/docs/Std.Math/SquaredNorm.md +1 -1
- package/docs/Std.Math/Tan.md +1 -1
- package/docs/Std.Math/Tanh.md +1 -1
- package/docs/Std.Math/TimesC.md +1 -1
- package/docs/Std.Math/TimesCP.md +1 -1
- package/docs/Std.Math/TrailingZeroCountI.md +1 -1
- package/docs/Std.Math/TrailingZeroCountL.md +1 -1
- package/docs/Std.Math/Truncate.md +1 -1
- package/docs/Std.Math/index.md +1 -1
- package/docs/Std.Measurement/MResetEachZ.md +1 -1
- package/docs/Std.Measurement/MResetX.md +1 -1
- package/docs/Std.Measurement/MResetY.md +1 -1
- package/docs/Std.Measurement/MResetZ.md +1 -1
- package/docs/Std.Measurement/MeasureAllZ.md +1 -1
- package/docs/Std.Measurement/MeasureEachZ.md +1 -1
- package/docs/Std.Measurement/MeasureInteger.md +1 -1
- package/docs/Std.Measurement/index.md +1 -1
- package/docs/Std.Random/DrawRandomBool.md +1 -1
- package/docs/Std.Random/DrawRandomDouble.md +1 -1
- package/docs/Std.Random/DrawRandomInt.md +1 -1
- package/docs/Std.Random/index.md +1 -1
- package/docs/Std.Range/IsRangeEmpty.md +1 -1
- package/docs/Std.Range/RangeEnd.md +1 -1
- package/docs/Std.Range/RangeReverse.md +1 -1
- package/docs/Std.Range/RangeStart.md +1 -1
- package/docs/Std.Range/RangeStep.md +1 -1
- package/docs/Std.Range/index.md +1 -1
- package/docs/Std.ResourceEstimation/AccountForEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/AuxQubitCount.md +1 -1
- package/docs/Std.ResourceEstimation/BeginEstimateCaching.md +1 -1
- package/docs/Std.ResourceEstimation/BeginRepeatEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/CczCount.md +1 -1
- package/docs/Std.ResourceEstimation/EndEstimateCaching.md +1 -1
- package/docs/Std.ResourceEstimation/EndRepeatEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/MeasurementCount.md +1 -1
- package/docs/Std.ResourceEstimation/PSSPCLayout.md +1 -1
- package/docs/Std.ResourceEstimation/RepeatEstimates.md +1 -1
- package/docs/Std.ResourceEstimation/RotationCount.md +1 -1
- package/docs/Std.ResourceEstimation/RotationDepth.md +1 -1
- package/docs/Std.ResourceEstimation/SingleVariant.md +1 -1
- package/docs/Std.ResourceEstimation/TCount.md +1 -1
- package/docs/Std.ResourceEstimation/index.md +1 -1
- package/docs/Std.StatePreparation/ApproximatelyPreparePureStateCP.md +1 -1
- package/docs/Std.StatePreparation/PreparePureStateD.md +1 -1
- package/docs/Std.StatePreparation/PrepareUniformSuperposition.md +1 -1
- package/docs/Std.StatePreparation/index.md +1 -1
- package/docs/Std.TableLookup/Select.md +1 -1
- package/docs/Std.TableLookup/index.md +1 -1
- package/docs/index.md +1 -1
- package/docs/toc.yml +1 -0
- package/lib/node/qsc_wasm.cjs +22 -4
- package/lib/node/qsc_wasm.d.cts +10 -0
- package/lib/node/qsc_wasm_bg.wasm +0 -0
- package/lib/web/qsc_wasm.d.ts +11 -0
- package/lib/web/qsc_wasm.js +21 -4
- package/lib/web/qsc_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/ux/circuit-vis/circuitManipulation.ts +145 -48
- package/ux/circuit-vis/contextMenu.ts +1 -1
- package/ux/circuit-vis/draggable.ts +288 -112
- package/ux/circuit-vis/events.ts +433 -199
- package/ux/circuit-vis/formatters/inputFormatter.ts +9 -4
- package/ux/circuit-vis/panel.ts +37 -34
- package/ux/circuit-vis/process.ts +1 -1
- package/ux/circuit-vis/sqore.ts +2 -2
- package/ux/circuit-vis/utils.ts +17 -1
- package/ux/qsharp-circuit.css +2 -35
package/ux/circuit-vis/events.ts
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
this.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
167
|
-
this.
|
|
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
|
-
|
|
274
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
-
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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
|
-
|
|
464
|
-
|
|
465
|
-
|
|
525
|
+
// Assign the arguments to the selected operation
|
|
526
|
+
this.selectedOperation.args = args;
|
|
527
|
+
}
|
|
466
528
|
|
|
467
|
-
|
|
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
|
-
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
-
|
|
502
|
-
|
|
503
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
*
|
|
524
|
-
*
|
|
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
|
-
|
|
529
|
-
|
|
530
|
-
const
|
|
531
|
-
|
|
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
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
);
|