Among the ways to use the calculator are 1) as a stand-alone (e.g.
this one), and 2) as annotation for
an html document (e.g. the manual you are now reading, and
regression tests for the calculator).
There are sets of equations throughout this manual, and clicking on the equations makes the input
equations visible. You can then edit them and see the results. Like in a jupyter notebook,
this encourages learning through experimenting.
Here's how this got started.
When I read IBM's textbook
Now compare them to mine:
Other than the second equation, where I defined CNOT,
my equations
look quite similar to the ones from the textbook. But mine are the output of my calculator.
Click on the equations and you'll see the input. This allows you
to experiment with the equations. Plus there's a subtle but
important difference—where the textbook has
\(X|{-}1\rangle\), my associated equation has \((X \otimes I) |{-}1\rangle \).
I don't know if that was a typo
in the textbook, or if it's a case of "you know what we mean".
What they meant was to apply the X to qubit 1 and not qubit 0.
The calculator demands that you make that explicit, because
it doesn't "know what you mean". Executable equations keep you honest.
Continuing my sales pitch,
below are identities from
section 2.4, More Circuit Identities
of the qiskit textbook.
This shows how well the calculator handles the equations.
section 1. Making a Controlled-Z from a CNOT
section 3. Controlled Rotations
The last four equations demonstrate how the almost-CCX gate
applies an X to the target when the controls are 11,
does nothing when they're 00 or 01, and
applies a Z when 10, which, as the textbook says, "only induces a relative phase".
There are two sections to each calculator. First the textarea for editing equations, then the results rendered with latex.
If only the latex results are visible, click on the results to make the textarea visible.
When the textarea is visible, there are buttons between the textarea and the results.
Here's what they do:
The "parenthesis" radio button selects "keep", "auto", or "all".
See the "parenthesis" section of the math.js manual
for an explanation of the options. "keep" is the default, and I recommend it. "all" is good in an emergency.
I broke "auto" for booleans, so proceed with caution.
The "implicit" radio button selects "hide" or "show".
See the "implicit" section of the math.js manual
for an explanation of the options.
Or maybe you prefer this explanation of the parenthesis and implicit options:
Click on the equations to get the textarea and buttons. Note that the default for parenthesis is "keep", and it's
leaving the equation unchanged from how it's entered in the textarea. Click on "auto" and it removes the
unnecessary parens. Click on "all" and it puts in parentheses everywhere it can. Moving on to implicit,
note that the default is hide, and it's hiding the implicit multiplication. Click on "show" and it
shows the multiplication explicitly.
The "Re-evaluate" button does just that, re-evaluates the equations. It's unnecessary unless you've used the randomAngle or randomState function,
in which case you get new random values.
The "User Manual" button opens the user manual in a new tab. Nice for checking on some function
detail when you're in the middle of entering an equation. Perhaps silly if you're already
in the user manual, like you are now.
A note on not bricking your browser: The calculator can handle computations with matrices
large enough that their latex rendering gets painfully slow. Here are two ways to avoid the problem.
If you want to assign a huge matrix to a variable, you can put a
semicolon at the end of an assignment,
and that tells the calculator not to display the
assignment. I used that on the first line of the following example.
But then you can't see (without looking in the textarea) what the assignment is.
So instead you can put a semicolon as a comment at the end of the line,
and instead of making the whole line invisible, it shows everything
but the result. The second line shows that.
Click here to go to a standalone calculator
There's no difference between the standalone calculator linked to above,
and all the calculators in this manual, other than there's just one in
the standalone, and it has no initial equations in the textarea.
These files can be templates for how to setup calculators for yourself.
math.js is a basic calculation engine with hooks for customizing.
So I customized it, mostly by adding the functions, and one operator, listed in the table of contents, above.
Other than for my customization, see math.js for all documentation.
While I'm doling out credit, mathjax.org renders all the LaTeX.
Also, qiskit was the inspiration for this calculator,
and I use a modified version of the qiskit number pretty-printer.
Maybe I didn't know about it, or I tried it and it was too slow, or it required sacrificing some
functionality that I didn't want to lose, or it wasn't open source. I really wanted to
use Jupyter because I love the Jupyter notebook approach, but using Jupyter meant (you!) having to
install stuff, and it doesn't seem to have a way to hide the inputs (just the outputs), which
would mean this manual would be messier. JupyterLite has hide all inputs, although it replaces
them with elipses. Not too bad. But JupyterLite has some problems, including that it's not an
official project at the time of this writing. Yikes! Anyway, that's the kind of agonizing I
went through when choosing what packages to use.
Probably best just to show examples:
The args are strings (e.g. '01' or "01"). The qubits of the arg are 0's, 1's, +'s, and -'s.
pr makes a measurement of the state (argument one) in the standard or computational basis,
and returns the sum of the probabilities of the states in the rest of the arguments.
bra() pulls a constant out of a state, but math.js leaves the constant in matrix
form, which can then cause a dimension mismatch when you try to use it.
The appropriately-named hack() fixes that.
Probably best just to show them all:
The gates without angles are actually constants rather than functions.
If they were functions you'd have to add "()" to their names.
Nobody wants that.
Probably best just to show examples:
If you're puzzled about what's going on with the angle names,
it turns out math.js turns variables that are names of Greek letters into a latex
rendering of the letter. How cool is that?
I haven't found any mention of it in their manual.
I only discovered it because I was going to add a wrapper
to make that happen, and typed in a test case before coding
it, and discovered it was already working.
qcc() can generate a gate similarly to how one does with the simulator in qiskit.
You're building a result gate with one or more internal gates.
qcc() also lets you specify any number of control qubits for the internal gates.
For example:
The first arg of qcc is the number of qubits. The rest of the args come in pairs,
the first defining the internal gate and the second defining the control and target qubits
for the internal gate. The control and target qubits are specified with a string
(e.g. '01' or "01")
The qubits are either all target qubits, or control qubits and target qubits separated by a '>'.
The number of target qubits must match the number of qubits in the internal gate,
and they must be sequential and ascending. (Yes, I considered allowing
non-consequtive target qubits, and in any order, but I couldn't come up with a clean
way to represent it in the display for qcc().
Use the perm() gate.)
The target qubits are required.
There can be 0 or more control qubits. This limits you to a ten-qubit
result gate. I don't think you want to have more than that.
The gate isn't limited to internal gates without angles, like X. It could be Rx(pi/2),
as you see in the examples. You could also build a gate and put it in a variable
and use that as an internal gate, as you see in the examples.
The display shows each internal gate in a column, with the name of the internal gate in its target row(s),
'c' in its control rows, if there are any, and the rest are '-'.
The qcc display is bracketed by curly brackets. Square brackets make it look too much like a matrix,
and straight brackets (pipes) make it look like a magnitude.
The first two examples show CNOT1 and CNOT2 defined, the two forms of a controlled-X, one
with the control qubit on 0, and the other with the control qubit on 1.
The next two examples show how you can surround each with H's to get the other.
The 3-qubit example compares \(Z \otimes Y \otimes X \) to building it with qcc().
Next, there's an example of using an internal gate with an angle.
Finally, there's surrounding \(Y \otimes X \) with SWAPs to get \(X \otimes Y \).
I messed up. I made qc() multiply the gates from left to right. To make it look like
the circuits in qiskit, it has to multiply from right to left. I left qc() unchanged for
backward compatibility, and added qcc(), which stands for qc-corrected. Take a look:
The first two show the ordering.
Note that it draws qc() and qcc() the same, so you
have to look at the source equations to see that the first line is qc() and the second is qcc().
The perm gate permutes the qubits.
The arg is a string listing qubits in the new order,
so '012' is no change, and '021' leaves one unchanged and swaps the other two.
Here are the equivalences for all the 2-qubit perms:
Here are the equivalences for all the 3-qubit perms:
Here we see that not changing the order of the qubits
is the identity, as is reversing the order twice
and rotating three times:
I added predefined constant names for the Bell states.
The "randomAngle()" function generates a random angle between \(-2\pi\) and \(2\pi\), and the "randomState()" function generates a random
state, normalized so the sum of the squares of the states is 1. I would like
to include symbolic evaluation and simplification, but it's not trivial, so
in the meantime a trivial way to test an equivalence with some level
of assurance is with random values, for example:
Click on the results to make the textarea and buttons visible, then click in the Re-evaluate button to evaluate with
new values for \(\alpha\), \(\omega\), and \(\Psi\), and therefore another test of the equivalences. Not the formal verification you
can get with symbolic evaluation, but, as I said, some level of assurance.
When comparing matrices, the == operator in math.js returns a matrix with a 1 where
they're equal, and 0 where not. That's no fun if all you want is "true" or "false". So the eq() function turns that
into true iff all elements are 1. Further, math.js has some behavior that I didn't
think we want in our context, so I changed that. Finally, math.js may not do
what you want when you say "a==b==c". Use eq(a,b,c). Examples:
In the examples you see how == returns a matrix of element-by-element comparison results.
And you see a comparison of three values. Plus you see the line breaks added to
make a comparison of several elements more readable, like in the introduction at the
beginning of this manual. But if you have more than one eq() in a statement, that pretty
lining up won't work anymore, so it doesn't:
I got tired of typing in the kron() function. I wanted an operator. I repurposed the .* operator, which
had the right precedence, felt kinda like \( \otimes \), and I hoped it wouldn't be missed too much.
So a.*b turns into kron(a,b). Except I didn't like typing two letters, particularly those two.
So you type @ into the textarea equations, that gets turned into .* before parsing, then I intercept the .* function at evaluation
time and substitute kron(). And of course display it as \( \otimes \).
It may seem like a lot of bother, but \( \otimes \) is such an important and frequently-used operator
that I figured it was worth it.
While we're talking about \( \otimes \), I should mention that it's not unusual in others' equations for both * and \( \otimes \) to be implied,
and the way to tell which it's supposed to be is that * doesn't work (dimension mismatch) so it must be \( \otimes \). Yeah, I don't
like that either, so \( \otimes \) has to be explicit in this calculator.
While we're talking about implicit multiplication, I should mention this:
If you try to make the multiplication of st and (3+4) implicit, you'll get an error - "st is not a function".
It's trying to evaluate it as the function call st(3+4). So you make the multiplication explicit and everything is fine.
Each click of the Loop button results in an evaluation with variable Loopvar set to
0, 1, etc. The Loop button is just below the textarea, between the Re-evaluate and
User Manual buttons.
As mentioned above,
if only the latex results are visible, click on the results to make the textarea visible.
For example, click the Loop button eight times in this example:
You get a table of Loopvar values and the last result in the textarea.
To start over, either click Re-evaluate or make any edit in the textarea.
Quantum computing gates often look messy when their values are printed because it's not
unusual to have something like \(\frac{1}{\sqrt{2}}\) as a factor. So results
are "pretty-printed" by looking for common factors like \(\frac{1}{\sqrt{2}}\). Calculations
are not performed symbolicly, so results that "should" be integers can be slightly off.
The pretty-printer rounds to integers when they're within \(10^{-14}\).
(eq() also returns true when numbers are within \(10^{-14}\).)
The pretty-printer also looks for a fraction whose numerator and denominator add to less
than twenty.
When the printer fails to find something "nice", it prints a floating point number with
five digits of precision.
How to Use the Calculator
Go to a Standalone Calculator
It's all built on math.js
Why Didn't I Use [your favorite package]?
Dirac Notation
Measure probabilities with pr
Use hack() to get a constant from bra
Gates with No Angles
Gates with Angles
Gate Generation: qcc
Gate Generation: qc
Gate Generation: perm
Bell States
Random things: randomAngle and randomState
Use eq() instead of ==
The @ operator
Looping
Rounding and Pretty Printing