diff --git a/src/gates/MultiplyAccumulateGates.js b/src/gates/MultiplyAccumulateGates.js index 1016d9d4..933739b1 100644 --- a/src/gates/MultiplyAccumulateGates.js +++ b/src/gates/MultiplyAccumulateGates.js @@ -154,4 +154,4 @@ MultiplyAccumulateGates.all = [ ...MultiplyAccumulateGates.SquareSubtractInputFamily.all, ]; -export {MultiplyAccumulateGates, BIG_MUL_MOD_SHADER_CODE} +export {MultiplyAccumulateGates, BIG_MUL_MOD_SHADER_CODE, MUL_STEP} diff --git a/src/gates/PhaseGradientGates.js b/src/gates/PhaseGradientGates.js index 23c7e02a..6c1a674e 100644 --- a/src/gates/PhaseGradientGates.js +++ b/src/gates/PhaseGradientGates.js @@ -12,15 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. +import {Config} from "src/Config.js"; import {Gate} from "src/circuit/Gate.js" import {GatePainting} from "src/draw/GatePainting.js" import {ketArgs, ketShaderPhase} from "src/circuit/KetShaderUtil.js" +import {MUL_STEP} from "src/gates/MultiplyAccumulateGates.js" import {WglArg} from "src/webgl/WglArg.js" const PHASE_GRADIENT_SHADER = ketShaderPhase( - 'uniform float factor;', ` - float angle = out_id * factor; + uniform float factor; + + /// Scales an angle by an integer factor. + /// Performs the multiplication gradually, to avoid losing precision. + float angle_mul(float base_angle, float whole_factor) { + float result = 0.0; + for (int k = 0; k < ${Math.ceil(Config.MAX_WIRE_COUNT/MUL_STEP)}; k++) { + result += base_angle * mod(whole_factor, ${1< CircuitDefinition.fromTextDiagram(new Ma ['-', undefined], ['+', undefined], ['|', undefined], - ['/', undefined] + ['/', null] ]), diagram); suite.testUsingWebGL("empty", () => { @@ -117,7 +118,7 @@ suite.testUsingWebGL('incoherent-amplitude-display', () => { suite.testUsingWebGL('coherent-amplitude-display', () => { let c = circuit(`-H-•-a/-- ---X-//-- - -H-------`, ['a', Gates.Displays.AmplitudeDisplayFamily.ofSize(2)]); + -H-------`, ['a', Gates.Displays.AmplitudeDisplayFamily]); let stats = CircuitStats.fromCircuitAtTime(c, 0); assertThat(stats.qubitDensityMatrix(Infinity, 0)).isApproximatelyEqualTo(Matrix.square(0.5, 0, 0, 0.5)); assertThat(stats.qubitDensityMatrix(Infinity, 1)).isApproximatelyEqualTo(Matrix.square(0.5, 0, 0, 0.5)); @@ -141,7 +142,7 @@ suite.testUsingWebGL('conditional-bloch-display', () => { suite.testUsingWebGL('probability-display', () => { let c = circuit(`-H-•-%- - ---X-/-`, ['%', Gates.Displays.ProbabilityDisplayFamily.ofSize(2)]); + ---X-/-`, ['%', Gates.Displays.ProbabilityDisplayFamily]); let stats = CircuitStats.fromCircuitAtTime(c, 0); assertThat(stats.qubitDensityMatrix(Infinity, 0)).isApproximatelyEqualTo(Matrix.square(0.5, 0, 0, 0.5)); assertThat(stats.customStatsForSlot(5, 0)).isApproximatelyEqualTo( @@ -151,7 +152,7 @@ suite.testUsingWebGL('probability-display', () => { suite.testUsingWebGL('controlled-multi-probability-display', () => { let c = circuit(`---◦- -H-%- - ---/-`, ['%', Gates.Displays.ProbabilityDisplayFamily.ofSize(2)]); + ---/-`, ['%', Gates.Displays.ProbabilityDisplayFamily]); let stats = CircuitStats.fromCircuitAtTime(c, 0); assertThat(stats.customStatsForSlot(3, 1)).isApproximatelyEqualTo( Matrix.col(0.5, 0.5, 0, 0)); @@ -159,7 +160,7 @@ suite.testUsingWebGL('controlled-multi-probability-display', () => { suite.testUsingWebGL('density-display', () => { let c = circuit(`-d/- - -//-`, ['d', Gates.Displays.DensityMatrixDisplayFamily.ofSize(2)]); + -//-`, ['d', Gates.Displays.DensityMatrixDisplayFamily]); let stats = CircuitStats.fromCircuitAtTime(c, 0); assertThat(stats.customStatsForSlot(1, 0)).isApproximatelyEqualTo( Matrix.square( @@ -172,7 +173,7 @@ suite.testUsingWebGL('density-display', () => { suite.testUsingWebGL('shifted-density-display', () => { let c = circuit(`---- -d/- - -//-`, ['d', Gates.Displays.DensityMatrixDisplayFamily.ofSize(2)]); + -//-`, ['d', Gates.Displays.DensityMatrixDisplayFamily]); let stats = CircuitStats.fromCircuitAtTime(c, 0); assertThat(stats.customStatsForSlot(1, 1)).isApproximatelyEqualTo( Matrix.square( @@ -262,3 +263,31 @@ suite.testUsingWebGL('survival-rates-controlled-postselection', () => { assertThat(stats.survivalRate(13)).isApproximatelyEqualTo(0.5); assertThat(stats.survivalRate(14)).isApproximatelyEqualTo(0.5); }); + +suite.testUsingWebGL('dynamic-phase-gradient-keeps-qubits-coherent', () => { + let stats = CircuitStats.fromCircuitAtTime( + circuit(`-H-P- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/- + -H-/-`, ['P', Gates.PhaseGradientGates.DynamicPhaseGradientFamily]), + 0.9); + + // Check coherence of each qubit. + for (let i = 0; i < 16; i++) { + let [x, y, z] = stats.qubitDensityMatrix(Infinity, i).qubitDensityMatrixToBlochVector(); + let r = x*x + y*y + z*z; + assertThat(r).withInfo({i, x, y, z}).isApproximatelyEqualTo(1); + } +});