Nurturing Palpable Magnificence

# npm

## qqcs

1.4.1 • Public • Published

# QQCS - Quick Quantum Circuit Simulation

## Installation

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.

## Overview

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.

## Introduction

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?

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)
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

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

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.

## Display

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
``````

## Measurement

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.

## Factoring

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

``````:H__:S10_:T20:_H_:_S10:__H:Sw02
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)

``````:H__:S10_:T20:_H_:_S10:__H:Sw02/0.35355
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.
``````

## Conclusion

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 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
``````

#### Fixes

``````* 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

### Meta-symbols

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

### Grammar

``````              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
unop ::= - | e
``````

## References

``````[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 https://arxiv.org/pdf/1708.03684v3.pdf.
[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 https://arxiv.org/pdf/1707.03429.pdf.
[7] IBM, the Quantum Experience web site (2019) retrieve https://quantumexperience.ng.bluemix.net/.
[8] The QISKit SDK for Quantum Software Development (2019). retrieve https://github.com/QISKit.
[9] QPIC (2018) Creating quantum circuit diagrams in TikZ. retrieve https://github.com/qpic/qpic.
``````

## Keywords

### Install

`npm i qqcs`

### Repository

github.com/dde/qqcs

17

1.4.1

BSD-3-Clause

415 kB

17