Memory usage: up to
2 * (2^numQubits) * sizeOfComplexNumber
Naive implementation stores entire state vector in an array of size
2^numQubits. We are storing state in a "map", and only amplitudes with non-zero probabilities are stored. So, in worst case, size of state map is
2^n, but it's less most of the time because we don't store zeroes.
Naive implementation creates transformation matrix and multiplies it with state vector. We are not creating and not storing entire transformation matrix in memory. Instead, elements of transformation matrix are calculated one by one and state is multiplied and stored in new state map on the fly. This way, memory usage is minimal (in worst case we have two
2^nstate vectors at a time).
Algorithm is parallelizable so it could use GPU, but GPU support is not implemented yet (work in progress).
Quantum Circuit Simulator Example
See live example
Install quantum-circuit npm module:
npm install --save quantum-circuit
And then import it into your program:
Create instance of
QuantumCircuit class passing number of qubits (wires) to constructor:
Note: number of qubits is optional argument - circuit will expand automatically if you add gates to non-existing wires
addGate method passing gate name, column index and qubit (wire) index:
For example, to add Hadamard gate as a first gate (column 0) at second qubit (wire 1) type:
Column 0 Wire 0 ----...---- |---| Wire 1 ---| H |--- |---|
column is negative integer then gate will be added to the end of the wire
addGate method passing gate name, column index and array of connected qubits (wires):
For example, to add CNOT as a second gate (column 1) controlled by second qubit (wire 1) at third qubit as target (wire 2) do:
Column 0 Column 1 Wire 0 ----...---------...----- Wire 1 ----...----------o------ | |-----| Wire 2 ----...-------| CX |--- |-----|
column is negative integer then gate will be added to the end
xPauli X (PI rotation over X-axis) aka "NOT" gate
yPauli Y (PI rotation over Y-axis)
zPauli Z (PI rotation over Z-axis)
r2PI/2 rotation over Z-axis aka "Phase PI/2"
r4PI/4 rotation over Z-axis aka "Phase PI/4"
r8PI/8 rotation over Z-axis aka "Phase PI/8"
sPI/2 rotation over Z-axis (synonym for
tPI/4 rotation over Z-axis (synonym for
sdg(-PI/2) rotation over Z-axis
tdg(-PI/4) rotation over Z-axis
srnSquare root of NOT
measureMeasures qubit and stores chance (0 or 1) into classical bit
srswapSquare root of Swap
chControlled Hadamard gate
cxControlled Pauli X (PI rotation over X-axis) aka "CNOT" gate
cyControlled Pauli Y (PI rotation over Y-axis)
czControlled Pauli Z (PI rotation over Z-axis)
cr2Controlled PI/2 rotation over Z-axis aka "Phase PI/2"
cr4Controlled PI/4 rotation over Z-axis aka "Phase PI/4"
cr8Controlled PI/8 rotation over Z-axis aka "Phase PI/8"
csControlled PI/2 rotation over Z-axis (synonym for
ctControlled PI/4 rotation over Z-axis (synonym for
csdgControlled (-PI/2) rotation over Z-axis
ctdgControlled (-PI/4) rotation over Z-axis
csrnControlled Square root of NOT
ccxToffoli aka "CCNOT" gate
cswapControlled Swap aka Fredkin gate
csrswapControlled Square root of Swap
By default, initial state of each qubit is
|0>. You can pass initial values as array of bool (
false) or integers (
1). This will set first two qubits to
|1> and evaluate circuit:
measure(wire) returns chance of being 1 for given qubit:
measure will return real number betwen 0 and 1.
You can store measurement into classical register. For example, to measure first qubit (wire 0) and store result into classical register named
c as fourth bit (bit 3):
Also, you can add
measure gate to circuit and then measurement will be done automatically and result will be stored into classical register:
Short form of writing this is
addMeasure(wire, creg, cbit):
If specified classical register doesn't exists - it will be created automatically.
Equal probability (0.5) will be stored as random 0 or 1
Classical registers are created automatically if you add measurement gate to the circuit but you can also manually create registers by calling
Example: create classical 5-bit register named
To get register value as integer, call
Read single bit
Example: get bit 3 from register named
Returns integer: 0 or 1
Set single bit
Example: set bit 3 to
1 in register named
circuit.setCregBit("ans", 3, 1);
You can get state as string with method
If you want only possible values (only values with probability > 0) then pass
If you want to print only possible values (only values with probability > 0) then pass
You can export circuit by calling
And load previously saved circuit by calling
You can "compile" any circuit and use it as a gate in another circuit like this:
If your circuit contains custom gates (created from another circuit), you can decompose it into equivalent circuit containing only basic gates.
If you pass
true as argument to function
save, you'll get decomposed circuit.
Circuit can be exported to OpenQASM with following limitation:
- at the moment, gates not directly supported by QASM and qelib1.inc are exported as-is - their definition is not generated. TODO
To export circuit to OpenQASM use
exportQASM(comment, decompose) method:
comment- comment to insert at the beginning of the file
decompose- if set to
trueand circuit contains custom gates then it will be decomposed to basic gates and then exported. If set to
falsethen custom gates will be exported as user defined gates.
Circuit can be imported from OpenQASM with following limitations:
importdirective is ignored (but most of gates defined in
qelib1.incare supported) TODO
Gates with params like
U(theta, phi, lambda)are ignored. TODO
ifstatement is ignored. TODO
barrieris ignored. TODO
resetis ignored. TODO
To import circuit from OpenQASM use
inputis string containing QASM source code.
.svg image of circuit can be created with
exportSVG(embedded) function with following limitations:
Integer registers are not drawn. TODO
Gate symbols are non-standard. TODO (BTW, do we have standard?)
Not yet tested well. TODO
Show circuit in browser:
var container = document;containerinnerHTML = svg;
Generate standalone SVG image at server with node.js:
Circuit can be exported to popular open-source drag-and-drop quantum circuit simulator Quirk with following limitations:
Quirk doesn't support more than 16 qubits.
Quirk can possibly incorrectly interpret circuit if we have multiple controlled gates in the same column.
Quirk doesn't support non-sequentially positioned multi-qubit user-defined gates (for example gate on wires [3, 0, 1]) so it's best to export decomposed circuit.
var quirkURL = "" + JSON;var quirkLink = document;
To be written...