Skip to content

Commit 6555a9b

Browse files
authored
Rui/update circuit init logic (#115)
* fix bug: `await circuitReady` freezes execution in `quantum-register.js` #87 * update quantum register node test * update classical register node and its test * update with suggested change * simplfy circuit initialisation logic * update tests * Apply suggestions from code review
1 parent 836caef commit 6555a9b

File tree

5 files changed

+46
-107
lines changed

5 files changed

+46
-107
lines changed

nodes/quantum/classical-register/classical-register.js

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ module.exports = function(RED) {
1414
this.name = config.name.trim().toLowerCase().replace(/ /g, '_');
1515
this.classicalBits = config.classicalBits;
1616
const node = this;
17-
17+
1818
logger.trace(this.id, 'Initialised classical register');
19-
2019
this.on('input', async function(msg, send, done) {
2120
logger.trace(node.id, 'Classical register received input');
2221
const state = stateManager.getState(msg.circuitId);
@@ -25,67 +24,40 @@ module.exports = function(RED) {
2524
// Validate the node input msg: check for register object.
2625
// Return corresponding errors or null if no errors.
2726
// Stop the node execution upon an error
27+
logger.trace(node.id, 'Classical register validating');
2828
let error = errors.validateRegisterInput(msg);
2929
if (error) {
3030
logger.error(node.id, error);
3131
done(error);
3232
return;
3333
}
3434

35+
let shouldInitCircuit = msg.shouldInitCircuit;
36+
let registerArr = state.get('registers');
37+
let circuitReadyEvent = state.get('quantumCircuitReadyEvent');
38+
3539
// Add arguments to classical register code
3640
script += util.format(snippets.CLASSICAL_REGISTER,
3741
'_' + node.name,
3842
node.classicalBits.toString() + ', "' + node.name + '"',
3943
);
4044

41-
// Completing the 'quantumCircuit' flow context array
42-
let register = {
43-
registerType: 'classical',
44-
registerName: node.name,
45-
registerVar: 'cr_' + node.name,
46-
};
47-
let quantumCircuit = state.get('quantumCircuit');
48-
quantumCircuit[msg.payload.register.toString()] = register;
49-
50-
// get quantum circuit config and circuit ready event from flow context
51-
let quantumCircuitConfig = state.get('quantumCircuitConfig');
52-
53-
// If the quantum circuit has not yet been initialised by another register
54-
if (typeof(state.get('quantumCircuit')) !== undefined) {
55-
let structure = state.get('quantumCircuit');
56-
57-
// Validating the registers' structure according to the user input in 'Quantum Circuit'
58-
// And counting how many registers were initialised so far.
59-
let [error, count] = errors.validateRegisterStrucutre(structure, msg.payload.structure);
60-
if (error) {
61-
logger.error(node.id, error);
62-
done(error);
63-
return;
64-
}
65-
66-
// If all register initialised & the circuit has not been initialised by another register:
67-
// Initialise the quantum circuit
68-
if (count == structure.length && typeof(state.get('quantumCircuit')) !== undefined) {
69-
// Delete the 'quantumCircuit' variable, not used anymore
70-
state.del('quantumCircuit');
71-
72-
// Add arguments to quantum circuit code
73-
let circuitScript = util.format(snippets.QUANTUM_CIRCUIT, '%s,'.repeat(count));
74-
75-
structure.map((register) => {
76-
circuitScript = util.format(circuitScript, register.registerVar);
77-
});
45+
registerArr.push(`cr_${node.name}`);
7846

79-
script += circuitScript;
80-
}
47+
if (shouldInitCircuit) {
48+
logger.trace(node.id, 'Should execute quantum circuit init command');
49+
script += util.format(snippets.QUANTUM_CIRCUIT, registerArr.join(','));
8150
}
8251

8352
// Run the script in the python shell, and if no error occurs
8453
// then notify the runtime when the node is done.
8554
await shell.execute(script)
8655
.then(() => {
87-
quantumCircuitConfig[node.name] = register;
88-
send(output);
56+
if (shouldInitCircuit) {
57+
logger.trace(node.id, 'Classical register emitted circuit ready event');
58+
circuitReadyEvent.emit('circuitReady', null);
59+
state.del('registers');
60+
}
8961
done();
9062
})
9163
.catch((err) => {

nodes/quantum/quantum-circuit/quantum-circuit.js

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,18 @@ module.exports = function(RED) {
2828

2929
state.setPersistent('quantumCircuitReadyEvent', quantumCircuitReady);
3030

31-
const quantumCircuitProxyHandler = {
32-
set: (obj, prop, value) => {
33-
obj[prop] = value;
34-
if (Object.keys(obj).length == node.outputs) {
35-
process.nextTick(() => quantumCircuitReady.emit('circuitReady', obj));
36-
state.setPersistent('quantumCircuitConfig', new Proxy({}, quantumCircuitProxyHandler));
37-
}
38-
return true;
39-
},
40-
};
41-
42-
let quantumCircuitConfig = new Proxy({}, quantumCircuitProxyHandler);
43-
state.setPersistent('quantumCircuitConfig', quantumCircuitConfig);
44-
4531
state.setPersistent('isCircuitReady', () => {
4632
let event = state.get('quantumCircuitReadyEvent');
4733
return new Promise((res, rej) => {
48-
event.once('circuitReady', (circuitConfig) => {
49-
res(circuitConfig);
34+
event.once('circuitReady', () => {
35+
res();
5036
});
5137
});
5238
});
5339

40+
// create an empty array in state to store register names
41+
state.setPersistent('registers', []);
42+
5443
logger.trace(this.id, 'Initialised quantum circuit');
5544

5645
this.on('input', async function(msg, send, done) {
@@ -95,6 +84,8 @@ module.exports = function(RED) {
9584
},
9685
register: i,
9786
},
87+
// additional message sent to the last output
88+
shouldInitCircuit: i == node.outputs - 1 ? true : false,
9889
};
9990
if (msg.req && msg.res) {
10091
output[i].req = msg.req;
@@ -124,6 +115,8 @@ module.exports = function(RED) {
124115
register: undefined,
125116
qubit: i,
126117
},
118+
// additional message sent to the last output
119+
shouldInitCircuit: i == node.outputs - 1 ? true : false,
127120
};
128121
if (msg.req && msg.res) {
129122
output[i].req = msg.req;

nodes/quantum/quantum-register/quantum-register.js

Lines changed: 20 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ module.exports = function(RED) {
3333
return;
3434
}
3535

36+
let shouldInitCircuit = msg.shouldInitCircuit;
37+
let registerArr = state.get('registers');
38+
let circuitReadyEvent = state.get('quantumCircuitReadyEvent');
39+
let circuitReady = state.get('isCircuitReady');
40+
3641
// Setting node.name to "r0","r1"... if the user did not input a name
3742
if (node.name == '') {
3843
node.name = 'r' + msg.payload.register.toString();
@@ -44,48 +49,7 @@ module.exports = function(RED) {
4449
node.outputs.toString() + ', "' + node.name + '"',
4550
);
4651

47-
// Completing the 'quantumCircuit' flow context array
48-
let register = {
49-
registerType: 'quantum',
50-
registerName: node.name,
51-
registerVar: 'qr' + msg.payload.register.toString(),
52-
};
53-
let quantumCircuit = state.get('quantumCircuit');
54-
quantumCircuit[msg.payload.register.toString()] = register;
55-
56-
// get quantum circuit config and circuit ready event from flow context
57-
let quantumCircuitConfig = state.get('quantumCircuitConfig');
58-
let circuitReady = state.get('isCircuitReady');
59-
60-
// If the quantum circuit has not yet been initialised by another register
61-
if (typeof(state.get('quantumCircuit')) !== undefined) {
62-
let structure = state.get('quantumCircuit');
63-
64-
// Validating the registers' structure according to the user input in 'Quantum Circuit'
65-
// And counting how many registers were initialised so far.
66-
let [error, count] = errors.validateRegisterStrucutre(structure, msg.payload.structure);
67-
if (error) {
68-
logger.error(node.id, error);
69-
done(error);
70-
return;
71-
}
72-
73-
// If all register initialised & the circuit has not been initialised by another register:
74-
// Initialise the quantum circuit
75-
if (count == structure.length && typeof(state.get('quantumCircuit')) !== undefined) {
76-
// Delete the 'quantumCircuit' variable, not used anymore
77-
state.del('quantumCircuit');
78-
79-
// Add arguments to quantum circuit code
80-
let circuitScript = util.format(snippets.QUANTUM_CIRCUIT, '%s,'.repeat(count));
81-
82-
structure.map((register) => {
83-
circuitScript = util.format(circuitScript, register.registerVar);
84-
});
85-
86-
script += circuitScript;
87-
}
88-
}
52+
registerArr.push(`qr${msg.payload.register}`);
8953

9054
// Creating an array of messages to be sent
9155
// Each message represents a different qubit
@@ -106,6 +70,11 @@ module.exports = function(RED) {
10670
}
10771
}
10872

73+
if (shouldInitCircuit) {
74+
logger.trace(node.id, 'Should execute quantum circuit init command');
75+
script += util.format(snippets.QUANTUM_CIRCUIT, registerArr.join(','));
76+
}
77+
10978
// Run the script in the python shell, and if no error occurs
11079
// then send one qubit object per node output
11180
await shell.execute(script)
@@ -123,10 +92,15 @@ module.exports = function(RED) {
12392
return;
12493
}
12594

126-
// wait for quantum circuit to be initialised
127-
logger.trace(node.id, 'Quantum register waiting for circuit to be ready');
128-
quantumCircuitConfig[node.name] = register;
129-
await circuitReady();
95+
if (shouldInitCircuit) {
96+
logger.trace(node.id, 'Quantum register emitted circuit ready event');
97+
circuitReadyEvent.emit('circuitReady', null);
98+
state.del('registers');
99+
} else {
100+
// wait for quantum circuit to be initialised
101+
logger.trace(node.id, 'Quantum register waiting for circuit to be ready');
102+
await circuitReady();
103+
}
130104

131105
let binaryString = state.get('binaryString');
132106
if (binaryString) {

test/nodes/classical-register_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe('ClassicalRegisterNode', function() {
2525

2626
it('execute quantum circuit command if last register is connected', function(done) {
2727
let command = util.format(snippets.CLASSICAL_REGISTER, '_test', '3, "test"');
28-
command += util.format(snippets.QUANTUM_CIRCUIT, 'qr0,cr_test,');
28+
command += util.format(snippets.QUANTUM_CIRCUIT, 'qr0,cr_test');
2929
flow.add('quantum-circuit', 'n0', [['n1'], ['n2']],
3030
{structure: 'registers', outputs: '2', qbitsreg: '1', cbitsreg: '1'});
3131
flow.add('quantum-register', 'n1', [['n3']], {outputs: '1'});

test/nodes/quantum-register_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe('QuantumRegisterNode', function() {
2525

2626
it('execute quantum circuit command if last register is connected', function(done) {
2727
let command = util.format(snippets.QUANTUM_REGISTER, '0', '1, "quantum_register"');
28-
command += util.format(snippets.QUANTUM_CIRCUIT, 'qr0,');
28+
command += util.format(snippets.QUANTUM_CIRCUIT, 'qr0');
2929
flow.add('quantum-circuit', 'n0', [['n1']], {structure: 'registers', outputs: '1', qbitsreg: '1', cbitsreg: '0'});
3030
flow.add('quantum-register', 'n1', [['n2']], {outputs: 1});
3131
flow.addOutput('n2');

0 commit comments

Comments
 (0)