Skip to content

Commit

Permalink
Testing more cases of AmplitudesDisplay
Browse files Browse the repository at this point in the history
- Fixed reference vector comparison in several ways
  • Loading branch information
Strilanc committed Mar 24, 2019
1 parent 5cdbbaa commit 58f5719
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 47 deletions.
38 changes: 15 additions & 23 deletions src/gates/AmplitudeDisplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,31 +82,31 @@ function amplitudeDisplayStatTextures(stateKet, controls, controlsTexture, range

// Compute the dot product of the largest vector against every other vector.
trader.shadeAndTrade(
small_input => POINTWISE_CMUL_SHADER(small_input, ketJustAfterCycle),
small_input => POINTWISE_CMUL_CONJ_SHADER(small_input, ketJustAfterCycle),
WglTexturePool.takeVec2Tex(involvedQubits));
ketJustAfterCycle.deallocByDepositingInPool("ketJustAfterCycle in makeAmplitudeSpanPipeline");
for (let k = 0; k < broadcastQubits; k++) {
trader.shadeHalveAndTrade(Shaders.sumFoldVec2);
for (let k = 0; k < rangeLength; k++) {
trader.shadeHalveAndTrade(Shaders.sumFoldVec2Adjacents);
}

// Sum up the magnitudes of the dot products to get a quality metric for how well the largest vector worked.
trader.shadeAndTrade(AMPS_TO_ABS_MAGS_SHADER, WglTexturePool.takeVecFloatTex(rangeLength));
for (let k = 0; k < rangeLength; k++) {
trader.shadeAndTrade(AMPS_TO_SQUARED_MAGS_SHADER, WglTexturePool.takeVecFloatTex(broadcastQubits));
for (let k = 0; k < broadcastQubits; k++) {
trader.shadeHalveAndTrade(Shaders.sumFoldFloat);
}

if (currentShaderCoder().float.needRearrangingToBeInVec4Format) {
trader.shadeHalveAndTrade(Shaders.packFloatIntoVec4);
}
let quality = trader.currentTexture;
let denormalizedQuality = trader.currentTexture;

trader.currentTexture = rawKet;
if (currentShaderCoder().vec2.needRearrangingToBeInVec4Format) {
trader.shadeHalveAndTrade(Shaders.packVec2IntoVec4);
}
let ket = trader.currentTexture;

return [ket, quality, incoherentKet];
return [ket, denormalizedQuality, incoherentKet];
}

/**
Expand All @@ -117,7 +117,7 @@ function amplitudeDisplayStatTextures(stateKet, controls, controlsTexture, range
*/
function processOutputs(span, pixelGroups, circuitDefinition) {
let [ketPixels, qualityPixels, rawIncoherentKetPixels] = pixelGroups;
let quality = qualityPixels[0];
let denormalizedQuality = qualityPixels[0];
let n = 1 << span;
let w = n === 2 ? 2 : 1 << Math.floor(Math.round(Math.log2(n))/2);
let h = n/w;
Expand All @@ -127,13 +127,14 @@ function processOutputs(span, pixelGroups, circuitDefinition) {
for (let e of ketPixels) {
unity += e*e;
}
let quality = denormalizedQuality / unity;
let incoherentKetPixels = new Float32Array(w * h * 2);
let incoherentUnity = 0;
for (let i = 0; i < n; i++) {
incoherentUnity += rawIncoherentKetPixels[i];
incoherentKetPixels[i << 1] = Math.sqrt(rawIncoherentKetPixels[i]);
}
if (isNaN(unity) || unity < 0.000001) {
if (isNaN(incoherentUnity) || incoherentUnity < 0.000001) {
return {
quality: 0.0,
ket: Matrix.zero(w, h).times(NaN),
Expand Down Expand Up @@ -191,14 +192,6 @@ const AMPS_TO_SQUARED_MAGS_SHADER = makePseudoShaderWithInputsAndOutputAndCode(
return dot(ri, ri);
}`);

const AMPS_TO_ABS_MAGS_SHADER = makePseudoShaderWithInputsAndOutputAndCode(
[Inputs.vec2('input')],
Outputs.float(),
`float outputFor(float k) {
vec2 ri = read_input(k);
return sqrt(dot(ri, ri));
}`);

const MAGS_TO_INDEXED_MAGS_SHADER = makePseudoShaderWithInputsAndOutputAndCode(
[Inputs.float('input')],
Outputs.vec2(),
Expand All @@ -222,17 +215,17 @@ const LOOKUP_KET_AT_INDEXED_MAG_SHADER = makePseudoShaderWithInputsAndOutputAndC
return read_input(k + read_indexed_mag(0.0).x * len_output());
}`);

const POINTWISE_CMUL_SHADER = makePseudoShaderWithInputsAndOutputAndCode(
const POINTWISE_CMUL_CONJ_SHADER = makePseudoShaderWithInputsAndOutputAndCode(
[Inputs.vec2('small_input'), Inputs.vec2('large_input')],
Outputs.vec2(),
`
vec2 cmul(vec2 c1, vec2 c2) {
return mat2(c1.x, c1.y, -c1.y, c1.x) * c2;
vec2 cmul_conj(vec2 c1, vec2 c2) {
return mat2(c1.x, -c1.y, c1.y, c1.x) * c2;
}
vec2 outputFor(float k) {
vec2 in1 = read_small_input(floor(mod(k + 0.5, len_small_input())));
vec2 in2 = read_large_input(k);
return cmul(in1, in2);
return cmul_conj(in1, in2);
}
`);

Expand Down Expand Up @@ -367,10 +360,9 @@ let AmplitudeDisplayFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
export {
AmplitudeDisplayFamily,
AMPS_TO_SQUARED_MAGS_SHADER,
AMPS_TO_ABS_MAGS_SHADER,
MAGS_TO_INDEXED_MAGS_SHADER,
FOLD_MAX_INDEXED_MAG_SHADER,
LOOKUP_KET_AT_INDEXED_MAG_SHADER,
POINTWISE_CMUL_SHADER,
POINTWISE_CMUL_CONJ_SHADER,
amplitudeDisplayStatTextures,
};
12 changes: 12 additions & 0 deletions src/webgl/Shaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,18 @@ Shaders.sumFoldVec2 = makePseudoShaderWithInputsAndOutputAndCode(
return read_input(k) + read_input(k + len_output());
}`);

/**
* Adds the odd half of its input to the even half of its input.
* @param {!WglTexture} inp
* @returns {!WglConfiguredShader}
*/
Shaders.sumFoldVec2Adjacents = makePseudoShaderWithInputsAndOutputAndCode(
[Inputs.vec2('input')],
Outputs.vec2(),
`vec2 outputFor(float k) {
return read_input(k*2.0) + read_input(k*2.0 + 1.0);
}`);

/**
* Adds the second half of its input into the first half.
* @param {!WglTexture} inp
Expand Down
104 changes: 80 additions & 24 deletions test/gates/AmplitudeDisplay.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ import {Suite, assertThat} from "test/TestUtil.js"
import {
amplitudeDisplayStatTextures,
AMPS_TO_SQUARED_MAGS_SHADER,
AMPS_TO_ABS_MAGS_SHADER,
MAGS_TO_INDEXED_MAGS_SHADER,
FOLD_MAX_INDEXED_MAG_SHADER,
LOOKUP_KET_AT_INDEXED_MAG_SHADER,
POINTWISE_CMUL_SHADER,
POINTWISE_CMUL_CONJ_SHADER,
} from "src/gates/AmplitudeDisplay.js"

import {Complex} from "src/math/Complex.js"
import {Controls} from "src/circuit/Controls.js"
import {CircuitDefinition} from "src/circuit/CircuitDefinition.js"
import {CircuitStats} from "src/circuit/CircuitStats.js"
import {CircuitShaders} from "src/circuit/CircuitShaders.js"
import {Serializer} from "src/circuit/Serializer.js"
import {seq} from "src/base/Seq.js"
import {Shaders} from "src/webgl/Shaders.js"
import {currentShaderCoder} from "src/webgl/ShaderCoders.js"
Expand All @@ -48,22 +50,6 @@ suite.testUsingWebGL("AMPS_TO_SQUARED_MAGS_SHADER", () => {
input.deallocByDepositingInPool();
});

suite.testUsingWebGL("AMPS_TO_ABS_MAGS_SHADER", () => {
let input = Shaders.vec2Data(new Float32Array([
1,0,
3,4,
-1,1,
0,0.5
])).toVec2Texture(2);
assertThat(AMPS_TO_ABS_MAGS_SHADER(input).readVecFloatOutputs(2)).isApproximatelyEqualTo(new Float32Array([
1,
5,
Math.sqrt(2),
0.5,
]), 0.001);
input.deallocByDepositingInPool();
});

suite.testUsingWebGL("MAGS_TO_INDEXED_MAGS_SHADER", () => {
let input = Shaders.floatData(new Float32Array([
2,
Expand Down Expand Up @@ -111,7 +97,7 @@ suite.testUsingWebGL("LOOKUP_KET_AT_INDEXED_MAG_SHADER", () => {
input.deallocByDepositingInPool();
});

suite.testUsingWebGL("POINTWISE_CMUL_SHADER", () => {
suite.testUsingWebGL("POINTWISE_CMUL_CONJ_SHADER", () => {
let small_input = Shaders.vec2Data(new Float32Array([
1, 2,
])).toVec2Texture(0);
Expand All @@ -121,11 +107,11 @@ suite.testUsingWebGL("POINTWISE_CMUL_SHADER", () => {
0, 1, 4, 9, 16, 25, 36, 49,
1, 2, 4, 8, 16, 32, 64, 128,
])).toVec2Texture(4);
assertThat(POINTWISE_CMUL_SHADER(small_input, large_input).readVec2Outputs(4)).isApproximatelyEqualTo(new Float32Array([
-2, 1, -4, 7, -6, 13, -8, 19,
-4, 7, -9, 17, -15, 35, -21, 53,
-2, 1, -14, 17, -34, 57, -62, 121,
-3, 4, -12, 16, -48, 64, -192, 256
assertThat(POINTWISE_CMUL_CONJ_SHADER(small_input, large_input).readVec2Outputs(4)).isApproximatelyEqualTo(new Float32Array([
2, 1, 8, -1, 14, -3, 20, -5,
8, -1, 19, -3, 37, -9, 55, -15,
2, 1, 22, 1, 66, -7, 134, -23,
5, 0, 20, 0, 80, 0, 320, 0
]), 0.001);
small_input.deallocByDepositingInPool();
large_input.deallocByDepositingInPool();
Expand Down Expand Up @@ -159,3 +145,73 @@ suite.testUsingWebGL("makeAmplitudeSpanPipeline_coherent", () => {
qualityData.deallocByDepositingInPool();
incoherentKetData.deallocByDepositingInPool();
});

suite.testUsingWebGL("AmplitudesDisplayWithOtherQubit_Minus", () => {
let stats = CircuitStats.fromCircuitAtTime(
Serializer.fromJson(CircuitDefinition, {cols:[["Amps2"]],init:[0,0,"-"]}),
0);
let out = stats.toReadableJson();
assertThat(out.displays[0].data.ket).isApproximatelyEqualTo([
{real: 1, imag: 0},
{real: 0, imag: 0},
{real: 0, imag: 0},
{real: 0, imag: 0},
]);
assertThat(out.displays[0].data.coherence_measure).isApproximatelyEqualTo(1);
});

suite.testUsingWebGL("AmplitudesDisplayWithOtherQubit_i", () => {
let stats = CircuitStats.fromCircuitAtTime(
Serializer.fromJson(CircuitDefinition, {cols:[["Amps2"]],init:[0,0,"i"]}),
0);
let out = stats.toReadableJson();
assertThat(out.displays[0].data.ket).isApproximatelyEqualTo([
{real: 1, imag: 0},
{real: 0, imag: 0},
{real: 0, imag: 0},
{real: 0, imag: 0},
]);
assertThat(out.displays[0].data.coherence_measure).isApproximatelyEqualTo(1);
});

suite.testUsingWebGL("AmplitudesDisplayWithOtherQubit_own_i", () => {
let stats = CircuitStats.fromCircuitAtTime(
Serializer.fromJson(CircuitDefinition, {cols:[["Amps2"]],init:["i",0,1]}),
0);
let out = stats.toReadableJson();
assertThat(out.displays[0].data.ket).isApproximatelyEqualTo([
{real: Math.sqrt(0.5), imag: 0},
{real: 0, imag: Math.sqrt(0.5)},
{real: 0, imag: 0},
{real: 0, imag: 0},
]);
assertThat(out.displays[0].data.coherence_measure).isApproximatelyEqualTo(1);
});

suite.testUsingWebGL("AmplitudesDisplayIncoherent_sqrt_x", () => {
let stats = CircuitStats.fromCircuitAtTime(
Serializer.fromJson(CircuitDefinition, {cols:[[1,"•","X^½"], ["Amps2"]],init:[0,"+",1]}),
0);
let out = stats.toReadableJson();
assertThat(out.displays[0].data.incoherentKet).isApproximatelyEqualTo([
Math.sqrt(0.5),
0,
Math.sqrt(0.5),
0,
]);
assertThat(out.displays[0].data.coherence_measure).isLessThan(0.85);
});

suite.testUsingWebGL("AmplitudesDisplayIncoherent_hadamard", () => {
let stats = CircuitStats.fromCircuitAtTime(
Serializer.fromJson(CircuitDefinition, {cols:[[1,"•","H"], ["Amps2"]],init:[0,"+",1]}),
0);
let out = stats.toReadableJson();
assertThat(out.displays[0].data.incoherentKet).isApproximatelyEqualTo([
Math.sqrt(0.5),
0,
Math.sqrt(0.5),
0,
]);
assertThat(out.displays[0].data.coherence_measure).isLessThan(0.85);
});
6 changes: 6 additions & 0 deletions test/webgl/Shaders.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ suite.testUsingWebGL("sumFold", () => {
0,4,
2,4
]));
assertThat(Shaders.sumFoldVec2Adjacents(coords).readVec2Outputs(2)).isEqualTo(new Float32Array([
1,0,
1,2,
1,4,
1,6,
]));
coords.deallocByDepositingInPool();

let solid = makePseudoShaderWithInputsAndOutputAndCode([], Outputs.vec4(), `
Expand Down

0 comments on commit 58f5719

Please sign in to comment.