Nurturing Palpable Magnificence


    1.4.1 • Public • Published

    QQCS - Quick Quantum Circuit Simulation

    Table of Contents


    QQCS is installed with the Node Package Manager. First, install NodeJS. Then, at the command line, enter:

    npm install qqcs

    To run, go to the node_modules directory, and enter:

    node qqcs -or- node qqcs/qdesk.js

    Use the command line switch -h to get help.


    The student new to Quantum Computing immediately confronts the steep hurdle of the mathematics of complex vector spaces needed to understand the basic concepts.

    There are elaborate systems available to aid quantum computations, but they are embedded in other languages, which is just one more thing to learn.

    When working with quantum algorithms expressed as circuits or gate sequences, one wants to know several things that are not immediately available in quantum programming systems.

    * A trace of the quantum state after each circuit gate
    * A display of the gate equivalent at any point in the circuit
    * Simple displays of quantum probabilities
    * Output using the notation of quantum computing

    QQCS contains all these features. It is an educational tool for first and second courses in Quantum Computing.

    QQCS can also be used by the quantum experimentalist. It can test the operation of a quantum circuit step by step, displaying the output of each step as a quantum state, an equivalent gate, or a measure of one or more qubits, and it can quickly run through alternatives.

    Although QQCS is "one more thing to learn", it is designed to be an intuitive character representation of a quantum circuit, using familiar gate names and quantum notation, drawing on existing concepts so that the learning is minimal.


    A quantum circuit simulation is not a quantum computer simulation. It is a mathematical rendering of each step of a quantum algorithm that is described by a sequence of gate operations on an initial quantum state.

    The QQCS software renders the simulation. The system allows a student to quickly construct a circuit using a linear notation motivated by the circuits themselves, and to acquire the information to analyze an algorithm quickly without the need for tedious calculations.

    The following gate sequence [6] may or may not implement a controlled Hadamard gate. How is one to tell?

    equivalent gate sequence for a controlled Hadamard gate

    QQCS answers the question with a single interactive statement. The [ 1] is the line number prompt.

    [ 1] :_H:_Sa:Cx:_H:_T:Cx:_T:_H:_S:_X:S_
    [] _H _Sa Cx _H _T Cx _T _H _S _X S_ [
    0.707+0.707i 0            0         0       
    0            0.707+0.707i 0         0       
    0            0            0.5+0.5i  0.5+0.5i
    0            0            0.5+0.5i -0.5-0.5i]

    Although first two diagonal elements should be 1, it looks like a factor of cos π/4 + isin π/4 would make that so, meaning the circuit could very well be equivalent to a global phase with a controlled Hadamard gate

    QQCS Statement Detail

    Circuit steps syntactically begin with a colon (:) and combine gates, given their standard names, with ungated qubit lines indicated by underscores (_), in sequence from the top to the bottom of the lines in the circuit. The first step in the example, :_H, is a Hadamard gate with an ungated line above it, in a two-line circuit.

    Gates with common adjoint gates use the upper case letter name for the gate, and the lower case letter "a" following the upper case letter as the name for the adjoint gate.

    A controlled gate, such as the CNOT, has a two- or three-digit suffix following the gate name identifying the control line (or lines) followed by the target line, so :C01 is a CNOT with control line 0 and target line 1. :Cx is a common abbreviation for :C01. :C10 is a reverse CNOT, and can be abbreviated Cr.

    Control and target lines are relative to the span of the controlled gate, so "_" prefixes and suffixes do not change the numbering of the controls and target.

    Available Gates

    1-Qubit 2-Qubit
    H Hadamard gate C general CNOT (used with a 2-digit control suffix)
    I Identity gate Cx CNOT with control qubit q and target qubit q+1
    _ ungated lines (implied Identity) Cr reverse CNOT with control qubit q+1 and target qubit q
    Kp(𝜃) Phase gate (universal set) [4] Sw general Swap (used with a 2-digit control suffix)
    Rp(𝜃) Rotation gate (universal set) [4] 3-Qubit
    Rx(𝜃) Pauli X rotation gate Fr general Fredkin gate (used with a 3-digit control suffix)
    Ry(𝜃) Pauli Y rotation gate Tf general Toffoli gate (used with a 3 (or more) digit control suffix)
    Rz(𝜃) Pauli Z rotation gate n-Qubit
    S S gate (π/2 phase gate) Im Mean Inversion (used with 1-digit size suffix)
    Sa S adjoint Qa Inverse Quantum Fourier Transform (used with 1-digit size suffix)
    T π/8 gate (π/4 phase gate) Qf Quantum Fourier Transform (used with 1-digit size suffix)
    Ta T adjoint
    Tp(𝜃) Phase Rotation gate (universal set) [4]
    U(𝜃,𝜙,λ) General one-, two-, or three-parameter rotation gate Other
    X Pauli X gate a... named, reusable, custom gate sequences
    Y Pauli Y gate ct control(c)-target(t) digit control suffix for any 1-qubit gate
    Z Pauli Z gate (π phase gate) M Qubit measurement pseudo-gate

    Rotational Gates

    All the rotational gates specify the angle parameters as factors of π radians, with π implicit. Thus, Rx(.5) is an X-axis rotation of π/2 radians, or 90 degrees. The parameter range for all angles is [0,4).

    The U gate may have 1, 2, or 3 parameters. U(λ) = U(0,0,λ) = Rz(λ), U(𝜙,λ) = U(π/2,𝜙,λ), and U(𝜃,𝜙,λ). The U gate implements the general unitary matrix

    exp(-i(𝜙+λ)/2)cos(𝜃/2)  -exp(-i(𝜙-λ)/2)sin(𝜃/2)
    exp( i(𝜙-λ)/2)sin(𝜃/2)   exp( i(𝜙+λ)/2)cos(𝜃/2)

    The Rx(𝜃) gate is equivalent to U(𝜃,-π/2,π/2).

    The Ry(𝜃) gate is equivalent to U(𝜃,0,0).

    The Rz(λ) gate is equivalent to U(0,0,λ).

    An alternate general unitary definition is available, invoked by the -u command line flag, or the ualt comment flag. The alternate definition differs only by a phase factor from the default definition above, but it can simplify the elements of some rotational gates. The definition is:

    cos(𝜃/2)        -exp(iλ)sin(𝜃/2)
    exp(i𝜙)sin(𝜃/2)  exp(i(𝜙+λ))cos(𝜃/2)

    Permutation Gates

    Permutation gates are matrices with a single 1 in each row and column and 0's in all other elements. The CNOT gate is a typical permutation gate. When applied to a quantum state, permutation gates shift the amplitudes from one basis vector to another

    A permutation gate is specified with the syntax :P(pair, ...)n. Each pair is a real number, but it is interpreted as a pair of integers separated by a period. Thus, 2.6 is the pair 2 -> 6, specifying that the amplitude for basis vector |010> becomes the amplitude for basis vector |110>. The gate :P(2.6,6.2)3 will exchange the amplitudes of those two basis vectors. The CNOT gate specified as a permutation is :P(2.3,3.2)2. The n suffix is the qubit size of the permutation gate.

    A permutation gate starts as an identity gate. The permutation a.b is applied by setting the element (a,a) to 0, then setting the element (a,b) to 1. After the permutations are applied, QQCS will verify that the result is valid. A permutation gate is a unitary matrix. If the gate is symmetric, it is Hermitian and therefore its own adjoint. Otherwise, its adjoint is the reverse permutation.

    The specification of a permutation gate is tedious. The simplest way to use one is to specify it once and assign it to a custom gate, then reuse the custom gate as needed.


    Oracles are available for the well-known algorithms of Deutsch, Deutsch and Jozsa, Bernstein and Vazirani, Simon and Grover.

    The oracles are specified with the syntax :Ox(p)n. The x is d for Deutsch and Deutsch-Jozsa which are, distinguished by their qubit size, b for Bernstein-Vazirani, s for Simon, and g for Grover. The optional parameter p is specific to the oracle and determines whether the oracle will implement a random function or a function determined by the parameter. The n suffix is the qubit size and must be specified. The qubit size includes any ancilla qubits.

    :Od2 is considered the Deutsch oracle, and any larger qubit size is the Deutsch-Jozsa oracle. Both algorithms use a single ancilla qubit, and the random function is either a constant or balanced binary function of domain size n-1. If the optional parameter is specified, a value of 0 generates a constant function whose values are all 0. A value of 1 generates a constant function whose values are all 1. Any other value generates a balanced function.

    :Obn is the Bernstein-Vazirani oracle. The algorithm uses a single ancilla qubit, and the function implements a hidden binary string of size n-1. If the optional parameter is specified, it determines the hidden string and should be a value between 0 and n-1.

    :Osn is the Simon oracle. The algorithm uses n/2 ancilla qubits, and the function implements a binary string of size n/2 representing the "period" [5] of the function, which is discovered by the Simon algorithm. If the optional parameter is specified, it determines the "period" and should be a value between 0 and (n/2)-1.

    :Ogn is the Grover oracle. The oracle negates the phase of one basis vector of the n-qubit input quantum state. If the optional parameter is specified, it determines which basis vector is negated and should be a value between 0 and n-1.

    Gate Positioning and Replication

    Ungated lines (_) have already been mentioned. They may be repeated as many times as needed (subject to maximum qubit restriction) to position a gate on the correct line. For example, :__X__ designates an X-gate on line 2 in a 5-qubit circuit.

    Gates may be repeated across adjacent lines by using a 1-digit suffix replicator. For example, :__X3 designates a circuit step created from the tensor product of 2 Identity gates on lines 0 and 1, and 3 X-gates on lines 2, 3, 4 of a 5-qubit circuit. The replication is only applicable to single-qubit gates, and uses only a single digit. As an alternative, the gate name can be repeated. :HHHH is the same as :H4.

    Non-adjacent gates are handled by infixed underscores (_), such as :_X_X, which puts two X gates on lines 1 and 3 of a 4-qubit circuit.

    Controlled Gate Names

    suffix notation corresponding to CNOT gates in a circuit

    Qubit line numbers on a controlled gate can be relative to the span of the gate, or absolute.

    The span of a gate is the difference between the minimum and maximum control/target lines plus one. Reading left to right, controls occur first, then target, each as a single digit. As an example, the control suffix 02 has a span of 3 (2-0+1=3) lines, and indicates a control on relative line 0 and a target on relative line 2.

    Ungated prefixes and suffixes are used, as in all other gates, to position the gate vertically in the circuit. Lines within the span that are not control or target lines are ungated by implication.

    With an absolute suffix, the control and target digits indicate the actual lines of the circuit. No leading _'s are needed for positioning. Trailing _'s may still be needed.

    Either absolute or relative notation may be used.

    Any single qubit gate can be followed by a control suffix to make it a controlled gate.

    A Toffoli gate may have more than two control qubits.


    The default display is the resulting gate matrix, or a quantum state transposed column vector.

    If the gate sequence was supplied with an initial value (see below), that value is displayed before the gate sequence is executed.

    The ket (-k) flag causes the quantum state display to be in basis vector form.

    The trace (-t) flag causes a display of output at each step in the gate sequence.

    * If there was an initial value, the trace is of each quantum state
    * If no initial value, the trace is the equivalent gate matrix to that point in the circuit


    The M pseudo-gate signifies measurement.

    It is placed and repeated as many times as needed in a circuit. To measure all 5 qubits at the end of a 5-qubit gate sequence, use :MMMMM, or :M5. Use the underscore for any unmeasured lines.

    The measurement display is a probability associated with the selected qubit lines, at the point in the circuit where the M pseudo-gate appears. Measurement output is sequentially numbered to track the different M-pseudo-gates that may be specified in circuit steps.

    Measurement is purely a mathematical display and does not cause state collapse.

    Any subset of the qubit lines can be measured. Use the ungated notation to position M pseudo-gates as needed.

    Initial Values

    A gate sequence execution does not automatically start with a qubit value. This allows the computation and display of an equivalent gate matrix, a sequence of gate matrix products.

    To specify an initial value for a gate sequence, use a linear combination of basis vectors in standard quantum computing ket notation.

    * |0> - single qubit zero ket
    * 0.707|0>+0.707|1> - balanced superposition qubit
    * An i is the imaginary value suffix, and must be preceded by a number, even if the number is 1.  Only + and
      - operators are used. Multiplication is implicit when a complex number is adjacent to a basis ket. There is
      no division, but see factoring below.
    * The initial value is ended by the first colon of the gate sequence

    Initial Value Tensor Products

    Larger initial values can be composed using the tensor product by surrounding a ket expression with parentheses.

    * (|0>)(|0>) is the same as |00>
    * (0.707|0>+0.707|1>)(0.707|0>-0.707|1>) is the tensor product of quantum states also known in the literature
      as |+> and |->.

    If the tensor product is all that is needed, terminate the statement with a return. No gate sequence is necessary.


    A Quantum Fourier Transform circuit [5] can be difficult to recognize without factoring.

    At the end of a gate sequence, the / operator followed by a (possibly complex) number at the end of a gate sequence, will factor out the number before the final display.

    3-qubit Quantum Fourier Transform - No Factor

    0.354  0.354       0.354   0.354      ...
    0.354  0.25+0.25i  0.354i -0.25+0.25i ...
    0.354  0.354i     -0.354  -0.354i     ...
    0.354 -0.25+0.25i -0.354i  0.25+0.25i ...
    0.354 -0.354       0.354  -0.354      ...
    0.354 -0.25-0.25i  0.354i  0.25-0.25i ...
    0.354 -0.354i     -0.354   0.354i     ...
    0.354  0.25-0.25i -0.354i -0.25-0.25i ...

    3-qubit Quantum Fourier Transform, Factoring Sqrt(8)

    1  1             1   1            ...
    1  0.707+0.707i  1i -0.707+0.707i ...
    1  1i           -1  -1i           ...
    1 -0.707+0.707i -1i  0.707+0.707i ...
    1 -1             1  -1            ...
    1 -0.707-0.707i  1i  0.707-0.707i ...
    1 -1i           -1   1i           ...
    1  0.707-0.707i -1i -0.707-0.707i ...

    Custom Gates

    A gate sequence can be named and saved for future use. Simply precede the gate sequence with a name.

    A name should start with a letter, comprise lower and upper case letters. Do not start or end the name with anything that might be mistaken for a gate name. Best practice is to avoid upper case characters as the first character of a custom gate name.

    Once defined, a custom gate is used just like a normal gate. It can be positioned in a circuit with "_" prefixes and suffixes, but control and replicator suffixes cannot be applied to it.

    For example, ss:Sw03:Sw01__:_Sw01_ assigns the 4-qubit custom swap circuit [1] to the name "ss". It can then be used in another circuit as :ss. For example, |0001>:ss determines the effect of the :ss equivalent circuit on the 4-qubit basis |0001>.

    Custom gates allow new gates to be defined. The square root of X (square root NOT [5]) gate can be defined by sn:Rx(.5)/.707-.707i. This statement assigns the custom gate sn a π/2 Rx rotation, after factoring out the global phase exp(-iπ/4). To verify, look at the result :sn:sn. Square root NOT squared is X.


    Comments are introduced by the hash character (#) and continue until the end of the line.

    In interactive mode, it is possible to set switch controls by preceding the switch keyword with a $ in a comment.

    kdisp - display quantum states in ket notation (default is transposed column vector)
    trace - display the resulting quantum state (or equivalent matrix) at each step of the quantum circuit
    ualt - use the alternate definition of a general 1-qubit unitary matrix
    rzeroes - replace zeroe values with periods in matrix displays for readability
    ocache - cache oracles once they are generated
    none - reset all switches, and clear the instruction cache

    When the $name appears in a comment, the switch is toggled.

    Interactive Help

    The keyword $gate[s] immediately following the hash character in an interactive comment will display a short
    help regarding the available gates.  The keyword $help will display a list of comment switches.


    QQCS is a simple linear notation for the simulation of quantum circuits.

    It is an educational tool that can be easily used by students new to Quantum Computing.

    It provides automatic mathematical analysis of circuits by incorporating the matrix mathematics necessary to provide insight to circuit operation, and by displaying the details at each execution step, something not available from quantum computer simulated execution.

    It can be executed in interactive or batch mode.

    Version Notes

    Notes on Version 1.4.1

    * Add the Grover oracle
    * Add the oracle cacheing switch ocache
    * Redesign the configuration processing

    Notes on Version 1.4.0

    * Added extended controls (more than two) to the Toffoli gate 
    * Added permutation gates
    * Added oracles for the Deutsch, Deutsch-Josza, Bernstein-Vazirani, and Simon algorithms
    * Improved compiler-generator for handling tail recursion

    Notes on Version 1.3.0

    * An alternate general unitary matrix definition is available with the -u flag on start-up, or with the $ualt
      interactive comment flag
    * The Fredkin (Fr) gate, controlled swap, has been added
    * The n-qubit Quantum Fourier Transform (Qf) anf Inverse QFT (Qa) gates have been added
    * The gates Kp(𝜙), Rp(𝛽), and Tp(𝛼), which are the universal gate set from [4] have been added
    * The gate suffix notation has been simplified in an upward compatible way
        * actual circuit line numbers can now be used in multiple-qubit gates, instead of relative ones
        * this eliminates the need for leading _'s to indicate identify matrix positioning
        * as an example, the following are equivalent
            * X12 and _X01
            * X24 and __X02
            * Fr123 and _Fr012
        * the number of qubits in the circuit will be taken as the maximum size of the circuit, unless overridden by trailing _'s
    * Control suffixes are allowed on all single qubit gates


    * When a non-zero element of a matrix was set to zero, the sparse matrix structure was corrupted.

    Notes on Version 1.2.0

    Version 1.2.0 introduces several upward incompatibilities in order to expand the set of gates supported and to simplify the syntax:

    * Ungated circuit lines are now represented by the underscore (_) character, not the lower case i
    * The comma syntax for ungated circuit lines between gates has been eliminated.  What used to be specified
      as :X,I,X can now be specified as :X_X
    * The S adjoint gate has been renamed from 's' to 'Sa'.  A similiar change has been made for the T adjoint gate. 
    * In prior versions, factoring at the end of a custom gate assignment was displayed but did not affect the
      assigned gate matrix.  It now does.

    New features in version 1.2.0 include:

    * Rx(𝜃), Ry(𝜃), and Rz(𝜃) rotation gates
    * U(𝜃,𝜙,λ), general rotation gate (U1, U2, and U3) based on a three parameter general 2x2 unitary matrix 

    QQCS Linear Notation Syntax


    ::=       is defined as
    |         alternative
    [ ... ]   zero or more
    e         empty
    'x'       identifies x as a grammar symbol


                  pgm ::= stmt stmt-list eof
            stmt-list ::= eol stmt stmt-list | e
                 stmt ::= ident gate-sequence | initial-value gate-sequence
        initial-value ::= q-state | q-state-list | e
        gate-sequence ::= g-seq-tail g-factor
           g-seq-tail ::= : gates g-seq-tail | e
             g-factor ::= / unop Complex | e
         q-state-list ::= ( q-state ) q-state-list | e
              q-state ::= unop v-comp p-state-tail
         p-state-tail ::= addop v-comp p-state-tail | e
                gates ::= full-gate gates | e
            full-gate ::= gate gate-suffix | ident
          gate-suffix ::= gate-angle gate-repl
           gate-angle ::= ( unop Real reals ) | e
            gate-repl ::= integer | e
                reals ::= , unop Real reals | e
               v-comp ::= coeff ket
                coeff ::= Complex | e
                  ket ::= '|' integer >
              Complex ::= complex | Real
                 Real ::= real | integer
                addop ::= + | -
                 unop ::= - | e


    [1] C. C. Moran (2019) Mastering Quantum Computing with IBM QX,  Birmingham, UK, Packt Publishing.
    [2] G. Nannicini (2018). An Introduction to Quantum Computing, Without the Physics. IBM T.J. Watson, Yorktown Heights, NY. retrieve
    [3] M. A. Nielsen and I. L. Chuang (2010) Quantum Computation and Quantum Information. 10th Anniversary Ed, New York, Cambridge University Press.
    [4] E. Rieffel and W. Polak (2011) Quantum Computing, A Gentle Introduction. MIT Press, Cambridge, Massachusetts; London, England.
    [5] R. S. Sutor (2019) Dancing With Qubits. Birmingham, UK, Packt Publishing.
    [6] A. Cross, L. Bishop, J. Smolin, J. Gambetta (2017). Open Quantum Assembly Language. retrieve
    [7] IBM, the Quantum Experience web site (2019) retrieve
    [8] The QISKit SDK for Quantum Software Development (2019). retrieve
    [9] QPIC (2018) Creating quantum circuit diagrams in TikZ. retrieve


    npm i qqcs

    DownloadsWeekly Downloads






    Unpacked Size

    415 kB

    Total Files


    Last publish


    • danevans