Skip to content

Commit

Permalink
Add circuit writer, combine A and M specification (#185)
Browse files Browse the repository at this point in the history
Address action items from this week's meeting #182

---------

Co-authored-by: rryoung98 <32727721+rryoung98@users.noreply.github.com>
Co-authored-by: rryoung98 <ritsukiyoung98@gmail.com>
  • Loading branch information
3 people authored Mar 12, 2024
1 parent 3bfd54b commit 82c09ff
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 26 deletions.
17 changes: 14 additions & 3 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"react-redux": "^9.1.0",
"react-scripts": "5.0.1",
"redux": "^5.0.1",
"sprintf-js": "^1.1.3",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
142 changes: 142 additions & 0 deletions frontend/src/plaquettes/CircuitWriter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable no-shadow */
/* eslint-disable no-plusplus */
/* eslint-disable camelcase */

import qubitLabels from '../qubits/Qubit';

const { sprintf } = require('sprintf-js');

export const CircuitForm = Object.freeze({
CNOT: Symbol('CNOT'),
UNIV: Symbol('UNIV'),
});

const FMT_STR = '%10s';

/**
* Create the circuit as ASCII art.
*
* Two forms of circuits are possible:
*
* [] "cnot"
* - Hadamard on the data qubits
* - only CNOT as 2q gates
* - every CNOT is controlled by a data qubit and targets the ancilla
*
* [] "univ"
* - Hadamard on the ancilla qubit
* - both CNOT and CZ as 2q gates
* - every CNOT/CZ is controlled by the ancilla and targets a data qubit
* @function createCircuitAsciiArt
* @param {Array} data_qubits - The data qubits.
* @param {Object} anc_qubit - The ancilla qubit.
* @param {boolean} [withTime=false]
* @param {CircuitForm} [inputForm=CircuitForm.UNIV]
*/
export function createCircuitAsciiArt(
data_qubits,
anc_qubit,
withTime = false,
inputForm = CircuitForm.UNIV
) {
const { CNOT, UNIV } = CircuitForm;
const { cx, cz } = qubitLabels;
let form = inputForm;
if (form !== CNOT) {
form = UNIV;
}
const lines = [];
// Add lines for every data qubit.
let idx = 0;
data_qubits.forEach((qubit) => {
let line = sprintf('f: ----'.replace('f', FMT_STR), qubit.name.replace('Qubit', 'Q'));
// Local change of basis
if (form === CNOT) {
if (qubit.label === cx) line += '-H--';
if (qubit.label === cz) line += '----';
} else if (form === UNIV) {
line += '----';
}
// Previous CNOTs
for (let i = 0; i < idx; i++) {
line += '-|--';
}
// Current CNOT
if (form === CNOT) {
line += '-*--';
} else if (form === UNIV) {
if (qubit.label === cx) line += '-X--';
if (qubit.label === cz) line += '-*--';
}
// Next CNOTs
for (let i = idx + 1; i < data_qubits.length; i++) {
line += '----';
}
// Change of basis
if (form === CNOT) {
if (qubit.label === cx) line += '-H--';
if (qubit.label === cz) line += '----';
} else if (form === UNIV) {
line += '----';
}
// End
line += '----';
lines.push(line);

// Empty line with only vertical bars.
// Q(__,__): ----
line = ' ';
line += ' ';
// Previous CNOTs and current one
for (let i = 0; i < idx + 1; i++) {
line += ' | ';
}
// Next CNOTs
for (let i = idx + 1; i < data_qubits.length; i++) {
line += ' ';
}
line += ' ';
lines.push(line);
idx += 1;
});
// Add line for the ancilla qubit.
let line = sprintf('f: |0>'.replace('f', FMT_STR), anc_qubit.name.replace('Qubit', 'Q'));
if (form === CNOT) {
line += '----'; // During the change of basis
} else if (form === UNIV) {
line += '-H--';
}
for (let i = 0; i < data_qubits.length; i++) {
if (form === CNOT) {
line += '-X--';
} else if (form === UNIV) {
line += '-*--';
}
}
if (form === CNOT) {
line += '---- D~ ';
} else if (form === UNIV) {
line += '-H-- D~ ';
}
lines.push(line);
// Add time ruler.
if (withTime) {
// Q(__,__):
line = ' ';
let line2 = 'time ruler';
for (let i = 0; i < data_qubits.length + 4; i++) {
line += '___ ';
line2 += ` ${i} `;
}
lines.push(line);
lines.push(line2);
}
// Create the message
let art = '';
lines.slice(0, -1).forEach((line) => {
art = `${art + line}\n`;
});
art += lines[lines.length - 1];
return art;
}
43 changes: 20 additions & 23 deletions frontend/src/plaquettes/Plaquette.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/* eslint-disable import/named */
/* eslint-disable no-param-reassign */
import {
Graphics, Container, Color, RoundedRectangle
} from 'pixi.js';
import Button from '../components/Button';
import notification from '../components/notification';
import { CircuitLabels } from '../qubits/Qubit';
import createCircuitAsciiArt from './circuit';
import { createCircuitAsciiArt, CircuitForm } from './CircuitWriter';

export const PlaquetteColors = {
export const PlaquetteColors = Object.freeze({
purple: new Color('purple'),
yellow: new Color('yellow'),
};
});

export default class Plaquette extends Graphics {
constructor(qubits, workspace, app, template, color = PlaquetteColors.purple) {
Expand Down Expand Up @@ -84,7 +85,7 @@ export default class Plaquette extends Graphics {
this.specifyCircuitButton = new Button('Specify canonical circuit', 200, 725, 'black');
this.controlPanel.addChild(this.specifyCircuitButton);
this.specifyCircuitButton.on('click', () => {
notification(this.app, 'Step 1: Specify ancilla qubit');
notification(this.app, 'Step 1: Specify ancilla/measure qubit');
app.view.addEventListener('click', this.selectAncillaQubit);
this.qubits.forEach((allQubit) => {
allQubit.zIndex = 2;
Expand Down Expand Up @@ -132,29 +133,20 @@ export default class Plaquette extends Graphics {
selectAncillaQubit = (e) => {
const { relativeX, relativeY } = this.getRelativeXY(e);
const qubit = this.getQubit(relativeX, relativeY);
if (!qubit) return;
if (!qubit) {
return;
}
qubit.setCircuitLabel(CircuitLabels.ancilla);
qubit.showLabelText();
this.app.view.removeEventListener('click', this.selectAncillaQubit);
notification(this.app, 'Step 2: Specify measure qubit');
this.app.view.addEventListener('click', this.selectMeasureQubit);
};

selectMeasureQubit = (e) => {
const { relativeX, relativeY } = this.getRelativeXY(e);
const qubit = this.getQubit(relativeX, relativeY);
if (!qubit) return;
qubit.setCircuitLabel(CircuitLabels.measure);
qubit.showLabelText();
this.app.view.removeEventListener('click', this.selectMeasureQubit);
notification(this.app, 'Step 3: Specify CX qubits');
notification(this.app, 'Step 2: Specify CX qubits');
this.app.view.addEventListener('click', this.selectCXQubit);
this.cxDoneButton = new Button('CX Done', 200, 125, 'black');
this.controlPanel.addChild(this.cxDoneButton);
this.cxDoneButton.on('click', () => {
this.controlPanel.removeChild(this.cxDoneButton);
this.app.view.removeEventListener('click', this.selectCXQubit);
notification(this.app, 'Step 4: Specify CZ qubits');
notification(this.app, 'Step 3: Specify CZ qubits');
this.app.view.addEventListener('click', this.selectCZQubit);
this.czDoneButton = new Button('CZ Done', 200, 125, 'black');
this.controlPanel.addChild(this.czDoneButton);
Expand All @@ -169,26 +161,31 @@ export default class Plaquette extends Graphics {
(_qubit) => _qubit.label === CircuitLabels.cx || _qubit.label === CircuitLabels.cz
);
const ancillaQubit = this.qubits.find((_qubit) => _qubit.label === CircuitLabels.ancilla);
const circuit = createCircuitAsciiArt(dataQubits, ancillaQubit, true, 'cnot');
this.circuitASCIIRectangle = this.circuitASCIIRect(circuit);
// eslint-disable-next-line max-len
const circuit = createCircuitAsciiArt(dataQubits, ancillaQubit, false, CircuitForm.CNOT);
// eslint-disable-next-line no-console
console.log(circuit);
// this.workspace.addChild(this.circuitASCIIRectangle);
this.circuitASCII = circuit;
});
});
};

selectCXQubit = (e) => {
const { relativeX, relativeY } = this.getRelativeXY(e);
const qubit = this.getQubit(relativeX, relativeY);
if (!qubit) return;
if (!qubit) {
return;
}
qubit.setCircuitLabel(CircuitLabels.cx);
qubit.showLabelText();
};

selectCZQubit = (e) => {
const { relativeX, relativeY } = this.getRelativeXY(e);
const qubit = this.getQubit(relativeX, relativeY);
if (!qubit) return;
if (!qubit) {
return;
}
qubit.setCircuitLabel(CircuitLabels.cz);
qubit.showLabelText();
};
Expand Down
Empty file removed frontend/src/plaquettes/circuit.js
Empty file.

0 comments on commit 82c09ff

Please sign in to comment.