Quantum circuit simulator implemented in javascript. Smoothly runs 20qubit simulations on laptop. Can run in browser or at server (node.js). No UI: you can use it in your program to run quantum simulations. Circuit can be imported from and exported to OpenQASM. Circuit drawing can be exported to SVG vector image.
About algorithm
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 nonzero probabilities are stored. So, in worst case, size of state map is2^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^n
state vectors at a time). 
Algorithm is parallelizable so it could use GPU, but GPU support is not implemented yet (work in progress).
Using in browser
Simply include quantumcircuit.min.js into your html page (available via unpkg CDN https://unpkg.com/quantumcircuit)
Quantum Circuit Simulator Example
See live example
Using at server with node.js
Install quantumcircuit npm module:
npm install save quantumcircuit
And then import it into your program:
Getting started
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 nonexisting wires
Add singlequbit gates
Call 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:
Result is:
Column 0 Wire 0 ...  Wire 1  H  
Note: if column
is negative integer then gate will be added to the end of the wire
Add multiqubit gates
Call 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  
Note: if column
is negative integer then gate will be added to the end
Implemented gates
Singlequbit gates
h
Hadamard gatex
Pauli X (PI rotation over Xaxis) aka "NOT" gatey
Pauli Y (PI rotation over Yaxis)z
Pauli Z (PI rotation over Zaxis)r2
PI/2 rotation over Zaxis aka "Phase PI/2"r4
PI/4 rotation over Zaxis aka "Phase PI/4"r8
PI/8 rotation over Zaxis aka "Phase PI/8"s
PI/2 rotation over Zaxis (synonym forr2
)t
PI/4 rotation over Zaxis (synonym forr4
)sdg
(PI/2) rotation over Zaxistdg
(PI/4) rotation over Zaxissrn
Square root of NOTmeasure
Measures qubit and stores chance (0 or 1) into classical bit
Twoqubit gates
swap
Swapsrswap
Square root of Swapch
Controlled Hadamard gatecx
Controlled Pauli X (PI rotation over Xaxis) aka "CNOT" gatecy
Controlled Pauli Y (PI rotation over Yaxis)cz
Controlled Pauli Z (PI rotation over Zaxis)cr2
Controlled PI/2 rotation over Zaxis aka "Phase PI/2"cr4
Controlled PI/4 rotation over Zaxis aka "Phase PI/4"cr8
Controlled PI/8 rotation over Zaxis aka "Phase PI/8"cs
Controlled PI/2 rotation over Zaxis (synonym forcr2
)ct
Controlled PI/4 rotation over Zaxis (synonym forcr4
)csdg
Controlled (PI/2) rotation over Zaxisctdg
Controlled (PI/4) rotation over Zaxiscsrn
Controlled Square root of NOT
Threequbit gates
ccx
Toffoli aka "CCNOT" gatecswap
Controlled Swap aka Fredkin gatecsrswap
Controlled Square root of Swap
Run circuit
Simply call run
method.
Initial state
By default, initial state of each qubit is 0>
. You can pass initial values as array of bool (true
or false
) or integers (0
or 1
). This will set first two qubits to 1>
and evaluate circuit:
Measurement
Method measure(wire)
returns chance of being 1 for given qubit:
Example:
Note: method 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)
:
Note:

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
Create register
Classical registers are created automatically if you add measurement gate to the circuit but you can also manually create registers by calling createCreg(name, len)
.
Example: create classical 5bit register named ans
:
Read register
To get register value as integer, call getCregValue(name)
.
Example:
Read single bit
Example: get bit 3 from register named ans
:
console.log(circuit.getCregBit("ans", 3));
Returns integer: 0 or 1
Set single bit
Example: set bit 3 to 1
in register named ans
:
circuit.setCregBit("ans", 3, 1);
View/print final amplitudes
You can get state as string with method stateAsString(onlyPossible)
:
If you want only possible values (only values with probability > 0) then pass true
:
Or, you can print state to javascript console with method print(onlyPossible)
:
If you want to print only possible values (only values with probability > 0) then pass true
:
Export/Import circuit
You can export circuit by calling save
method:
And load previously saved circuit by calling load
method:
Use circuit as a gate in another circuit
You can "compile" any circuit and use it as a gate in another circuit like this:
Decompose circuit
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.
Example:
Export to QASM
Circuit can be exported to OpenQASM with following limitation:
 at the moment, gates not directly supported by QASM and qelib1.inc are exported asis  their definition is not generated. TODO
To export circuit to OpenQASM use exportQASM(comment, decompose)
method:
Example:

comment
 comment to insert at the beginning of the file 
decompose
 if set totrue
and circuit contains custom gates then it will be decomposed to basic gates and then exported. If set tofalse
then custom gates will be exported as user defined gates.
Import from QASM
Circuit can be imported from OpenQASM with following limitations:

import
directive is ignored (but most of gates defined inqelib1.inc
are supported) TODO 
Gates with params like
U(theta, phi, lambda)
are ignored. TODO 
if
statement is ignored. TODO 
barrier
is ignored. TODO 
reset
is ignored. TODO
To import circuit from OpenQASM use importQASM(input)
method:
Example:
input
is string containing QASM source code.
Export to SVG
Vector .svg
image of circuit can be created with exportSVG(embedded)
function with following limitations:

Integer registers are not drawn. TODO

Gate symbols are nonstandard. TODO (BTW, do we have standard?)

Not yet tested well. TODO
Example 1
Show circuit in browser:
var container = document;containerinnerHTML = svg;
Example 2
Generate standalone SVG image at server with node.js:
Export to Quirk
Circuit can be exported to popular opensource draganddrop 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 nonsequentially positioned multiqubit userdefined gates (for example gate on wires [3, 0, 1]) so it's best to export decomposed circuit.
Example:
var quirkURL = "http://algassert.com/quirk#circuit=" + JSON;var quirkLink = document;
API docs
To be written...