Skip to content

Commit 1d226f3

Browse files
committed
Fixed stats being collected after un-setup shaders, breaking X/Y-axis controlled displays
1 parent 5e2b66c commit 1d226f3

2 files changed

Lines changed: 43 additions & 39 deletions

File tree

src/circuit/CircuitComputeUtil.js

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@ function advanceStateWithCircuit(args, circuitDefinition, collectStats) {
6060
let controls = args.controls.and(circuitDefinition.colControls(col).shift(args.row));
6161
let controlTex = KetTextureUtil.control(args.wireCount, controls);
6262

63+
let statsCallback = statArgs => {
64+
if (!collectStats) {
65+
return;
66+
}
67+
68+
let {qubitDensities, customGateStats} = _extractStateStatsNeededByCircuitColumn(
69+
statArgs,
70+
circuitDefinition,
71+
col);
72+
colQubitDensities.push(qubitDensities);
73+
for (let {row, stat} of customGateStats) {
74+
//noinspection JSUnusedAssignment
75+
customStatsMap.push({col, row, out: customStats.length});
76+
//noinspection JSUnusedAssignment
77+
customStats.push(stat);
78+
}
79+
};
80+
6381
let nextState = _advanceStateWithCircuitDefinitionColumn(
6482
args,
6583
new CircuitEvalArgs(
@@ -71,28 +89,8 @@ function advanceStateWithCircuit(args, circuitDefinition, collectStats) {
7189
inputState,
7290
args.customContextFromGates),
7391
circuitDefinition,
74-
col);
75-
76-
if (collectStats) {
77-
let {qubitDensities, customGateStats} = _extractStateStatsNeededByCircuitColumn(
78-
nextState, // We want to show stats after post-selection, so we use 'next' instead of 'input'.
79-
circuitDefinition,
80-
col,
81-
controls,
82-
controlTex,
83-
args.time);
84-
colQubitDensities.push(qubitDensities);
85-
for (let {row, stat} of customGateStats) {
86-
//noinspection JSUnusedAssignment
87-
customStatsMap.push({
88-
col,
89-
row,
90-
out: customStats.length
91-
});
92-
//noinspection JSUnusedAssignment
93-
customStats.push(stat);
94-
}
95-
}
92+
col,
93+
statsCallback);
9694

9795
KetTextureUtil.doneWithTexture(controlTex, "controlTex in advanceStateWithCircuit");
9896
return nextState;
@@ -107,42 +105,36 @@ function advanceStateWithCircuit(args, circuitDefinition, collectStats) {
107105
}
108106

109107
/**
110-
* @param {!WglTexture} state
108+
* @param {!CircuitEvalArgs} args
111109
* @param {!CircuitDefinition} circuitDefinition
112110
* @param {!int} col
113-
* @param {!Controls} controls
114-
* @param {!WglTexture} controlTex
115-
* @param {!number} time
116111
* @private
117112
* @returns {!{qubitDensities:!WglTexture, customGateStats:!Array.<!{row:!int,stat:!WglTexture}>}}
118113
*/
119114
function _extractStateStatsNeededByCircuitColumn(
120-
state,
115+
args,
121116
circuitDefinition,
122-
col,
123-
controls,
124-
controlTex,
125-
time) {
117+
col) {
126118
// Compute custom stats used by display gates.
127119
let customGateStats = [];
128120
for (let row of circuitDefinition.customStatRowsInCol(col)) {
129121
let statArgs = new CircuitEvalArgs(
130-
time,
122+
args.time,
131123
row,
132124
circuitDefinition.numWires,
133-
controls,
134-
controlTex,
135-
state,
125+
args.controls,
126+
args.controlsTexture,
127+
args.stateTexture,
136128
circuitDefinition.colCustomContextFromGates(col, row));
137129
let pipeline = circuitDefinition.columns[col].gates[row].customStatPipelineMaker(statArgs);
138-
let stat = KetTextureUtil.evaluatePipelineWithIntermediateCleanup(state, pipeline);
130+
let stat = KetTextureUtil.evaluatePipelineWithIntermediateCleanup(args.stateTexture, pipeline);
139131
customGateStats.push({row, stat});
140132
}
141133

142134
// Compute individual qubit densities, where needed.
143135
let qubitDensities = KetTextureUtil.superpositionToQubitDensities(
144-
state,
145-
controls,
136+
args.stateTexture,
137+
args.controls,
146138
circuitDefinition.colHasSingleQubitDisplayMask(col));
147139

148140
return {qubitDensities, customGateStats};
@@ -153,14 +145,16 @@ function _extractStateStatsNeededByCircuitColumn(
153145
* @param {!CircuitEvalArgs} args
154146
* @param {!CircuitDefinition} circuitDefinition
155147
* @param {!int} col
148+
* @param {!function(!CircuitEvalArgs)} statsCallback
156149
* @returns {!WglTexture}
157150
* @private
158151
*/
159152
function _advanceStateWithCircuitDefinitionColumn(
160153
outerContextArgs,
161154
args,
162155
circuitDefinition,
163-
col) {
156+
col,
157+
statsCallback) {
164158

165159
let colContext = Util.mergeMaps(
166160
args.customContextFromGates,
@@ -199,6 +193,8 @@ function _advanceStateWithCircuitDefinitionColumn(
199193
circuitDefinition.textureTransformsInColAt(col, outerContextArgs.row),
200194
(v, f) => f(colArgsTemplate.withStateTexture(v)));
201195

196+
statsCallback(colArgsTemplate.withStateTexture(almostAlmostNextState));
197+
202198
// Apply 'after column' un-setup shaders.
203199
let nextState = KetTextureUtil.aggregateWithReuse(
204200
almostAlmostNextState,

test/circuit/CircuitStats.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,11 @@ suite.webGlTest("nested-addition-gate", () => {
5858
assertThat(stats.qubitDensityMatrix(1, Infinity)).isEqualTo(on);
5959
assertThat(stats.qubitDensityMatrix(2, Infinity)).isEqualTo(off);
6060
});
61+
62+
suite.webGlTest('controlled-displays', () => {
63+
let c = circuit(`-H-•-@@-
64+
---X-⊕•-`);
65+
let stats = CircuitStats.fromCircuitAtTime(c, 0);
66+
assertThat(stats.qubitDensityMatrix(0, 5)).isApproximatelyEqualTo(Matrix.square(0.5, 0.5, 0.5, 0.5));
67+
assertThat(stats.qubitDensityMatrix(0, 6)).isApproximatelyEqualTo(Matrix.square(0, 0, 0, 1));
68+
});

0 commit comments

Comments
 (0)