Source code:
Q-Qubit.js
Perfect pairs
A qubit
is just a pair of numbers.
That’s it—two
shiny happy number values,
holding hands.
Let’s call the first number
“alpha
”
and the second number
“beta
.”
Look at this handsome couple:
alpha
, beta
We can package
alpha
and
beta
together
by storing them in a very small
matrix
that is only one unit wide
and two units tall—and
because this matrix is only one unit wide
it is not merely a matrix, it’s also a
vector.
(What’s a matrix?
What’s a vector?
See the Matrix
page
for quick refreshers on both.)
So when you think of a qubit you can imagine it as
a 1 × 2 matrix
containing its
alpha
value on the top
and its
beta
value on the bottom,
like so:
alpha |
beta |
Now that we know a qubit is a matrix, we also know that we can perform addition with qubits, perform multiplication with qubits, and so on—just as one can do with any matrix. (That will become rather important when we eventually introduce the idea of quantum gates, which are also matrices.)
Predictable couples
The thing that makes this pair of numbers special
is their relationship to each other,
which we can define as follows:
alpha
multiplied by
alpha
,
added to
beta
multiplied by
beta
,
must always equal one.
We can express this as an equation:
The parentheses in the equation above
are not strictly necessary
as the
“order of operations” rules
dictate that these multiplications
must be carried out prior to
the additions—but emphasis can often be more helpful than brevity when learning something new.
And now that we understand this relationship
we can express it more compactly
using exponents rather than multiplications:
alpha
squared
added to
beta
squared
must always equal one.
A bit further below we’ll add one small wrinkle to this equation, but otherwise this is what defines a qubit. That’s it. It’s that easy.
Named couples
Let’s start plugging in values for
alpha
and
beta
.
Each different value combination makes a different sort of qubit.
The most frequently used qubit value combinations
have names
and belong to a set of named vectors called
Jones vectors.
We’ll begin with the two simplest qubits.
This first qubit is named
Horizontal
and the second is named
Vertical.
Both are composed from a zero and a one
and we can see that this
satisfies our qubit definition above.
alpha = 1 |
beta = 0 |
alpha = 0 |
beta = 1 |
What does it mean to be named
Horizontal or
Vertical?
Where do these orientation-based names come from?
Are there more orientation-based names?
To understand, let’s plot these two qubit vectors on a graph.
We’ll use the
alpha
value
as our x coordinate
and the
beta
value
as our y coordinate:
alpha |
beta |
alpha
, beta
)
Plotting
alpha
and
beta
as x and y
yields (1, 0) for a
Horizontal qubit
and (0, 1) for a
Vertical qubit.
We can see that the values from a Horizontal qubit, when plotted as x and y, form a horizontal line from the origin (0, 0) out to (1, 0). Meanwhile, when we plot the values of a Vertical qubit as x and y, it forms a vertical line from the origin (0, 0) up to (0, 1). Before we introduce more named Jones vectors let’s take what we’ve learned about qubit values and generalize it for vectors with more than two elements so we can better understand what these qubit values truly mean.
State vectors
Did it seem strange to read that
the qubit we refer to as “0
” begins with an
alpha
value of 1?
(Or that the qubit we refer to as “1
” begins with an
alpha
value of 0?)
Does that mean we refer to qubits
by their beta
values?
Is that some sort of quantum computing convention?
alpha = 1 |
beta = 0 |
The short answer is “No.”
To understand why,
we must recognize that
a qubit is the simplest example of a
quantum state vector—a
list of all possible states
for a quantum system to exist in,
with each possible state accompanied by the probability
that the system is indeed in that state.
When a single qubit is measured
there are only two possible states
for it to be in:
0
or 1
.
This is why a qubit is represented by a two-element vector;
one element per possible outcome.
On this very short list of possible outcomes,
0
is the first possible outcome
and 1
is the second possible outcome.
When we say that a Horizontal qubit is “0
”
we’re not referring to the qubit’s
beta
value at all.
We’re instead highlighting the fact that
the 1
in this (1, 0) pair
happens to be in the “zeroth” slot—the
alpha
slot
of this
(alpha
,
beta
) pair.
We’re saying that
for the possible outcome “0
”
our qubit is voting 1, or TRUE
.
At the same time we’re saying that
for the possible outcome “1
”,
our qubit is voting 0, or FALSE
.
Outcome will be 0 :
TRUE (1 )
|
Outcome will be 1 :
FALSE (0 )
|
For good measure let’s look at the converse example.
Outcome will be 0 :
FALSE (0 )
|
Outcome will be 1 :
TRUE (1 )
|
To further clarify—and
to hint at how a quantum circuit
functions—let’s look at a state vector
for a quantum system composed of two qubits.
With one qubit there were two possible outcomes:
0
and 1
.
(And because there are only two elements of a qubit vector we named them
alpha
and
beta
to make referring to them more convenient.)
For two qubits there are four possible outcomes:
00
,
01
,
10
, and
11
.
(We won’t bother to name elements of state vectors larger than two.
It would get unwieldy rather quickly.)
Which of those four possible outcomes
might the following state vector represent?
0 |
0 |
1 |
0 |
two qubits.
The above vector represents four possible outcomes
and we see that
three out of those four possible outcomes
are FALSE
(0
).
Meanwhile, the third of those four possible outcomes
is TRUE
(1
).
Because the result value of the third possible outcome is
10
we see that this two qubit vector state
is telling us it represents a result of
10
.
Let’s break this down the same way we did
with
Horizontal
and
Vertical
qubits.
Outcome will be 00 :
FALSE (0 )
|
Outcome will be 01 :
FALSE (0 )
|
Outcome will be 10 :
TRUE (1 )
|
Outcome will be 11 :
FALSE (0 )
|
two qubits.
We’ve learned that a single qubit is the simplest example of a quantum state vector. It is a list of the votes per each possible outcome—and for a single qubit there are only two possible outcomes. We’ve also seen that we can represent the state of a multi-qubit system where there are more than two possible outcomes.
Ket notation
Paul Dirac’s “bra-ket” notation offers us a more compact means of describing quantum state vectors—and by extension, qubits. (While “bra-ket” offers us two named elements—“bra” and “ket”—for our purposes we need only focus on the latter.) Kets represent the result value that our quantum vector state represents. They are expressed as values enclosed between a vertical bar and a rightward angle bracket. The following is pronounced “ket zero.”
We began
by stating that
a Horizontal qubit
represents “0
”,
and later explained why this was so.
Kets provide us a convenient way
to refer to this result state directly
as in-line text
rather than a clunky matrix.
1 |
0 |
Similarly, we defined a
Vertical qubit
as representing “1
”
and illustrated this as well.
We can now also express this column vector as a ket.
0 |
1 |
The convenience of ket notation becomes more apparent as we represent state vectors that are larger than a single qubit. (For n qubits we must use a state vector that has 2n elements. Meanwhile our ket values are still just n digits long.) Here we express four possible states of a two qubit system as both state vectors and their equivalent kets.
1 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
1 |
Superposition
You’ve probably heard the term
“superposition”—and along with that
you’ve likely been spoonfed some measure of mysticism;
pizza-bagels and whatnot.
In the real, physical world, superposition is indeed weird magic.
But mathematically it’s dead simple:
Superposition is any qubit state
where the
alpha
and
beta
values are anything other than
exactly 0 or exactly 1.
Up until now we’ve thought of
alpha
and
beta
values as being either
TRUE
(1) or FALSE
(0)
but each is actually capable of expressing an entire spectrum between
TRUE
(1) and FALSE
(0).
Let’s investigate that idea by building on what we’ve already learned.
Given the constraint
alpha
2 +
beta
2 = 1, if we plot all of the possible
alpha
and
beta
values on a graph
as x and y respectively,
the outcome is a circle with a radius of 1 centered at the origin (0, 0);
ie. a unit circle.
All possible combinations of
alpha
and
beta
lay on the perimeter of this circle.
To illustrate this, here’s a plot of named
Jones vectors
as well as their conjugates.
1 |
√ 2 |
1 |
√ 2 |
-1 |
√ 2 |
1 |
√ 2 |
-1 |
√ 2 |
-1 |
√ 2 |
1 |
√ 2 |
-1 |
√ 2 |
What the
alpha
and
beta
values represent are the individual
probability amplitudes
for each outcome; that a qubit
when measured will be in either a
0
or a
1
state.
Measurement itself causes a qubit’s
probability wave to collapse,
bringing an end to its superposition.
The probability that upon measurement a qubit’s
probability amplitude
will
collapse to
0
is alpha
2,
while the probability that it will
collapse to
1
is beta
2.
We already know that a Horizontal qubit exists in a state of 0 (“ket zero”) and therefore has a 100% chance of being measured as 0.
1 |
0 |
Similarly, we also know that a Vertical qubit exists in a state of 1 (“ket one”) and therefore has a 100% chance of being measured as 1.
0 |
1 |
Meanwhile, a Diagonal qubit exists in a state of superposition as + (“ket plus”). It is a state which does not have a definite result value prior to measurement but it does of course have a definite state vector and that state vector has a positive orientation. (Recall our unit circle diagram above to see how this value lays in a positive quadrant of the graph.) There is a 50% chance of it being measured as 0 (“ket zero”) and a 50% chance of it being measured as 1 (“ket one”).
1 |
1 |
1 |
√ 2 |
1 ÷ √ 2 |
1 ÷ √ 2 |
alpha 2 + beta 2
|
1 |
(1 ÷ √ 2)2 + (1 ÷ √ 2)2 | 1 |
(1 ÷ 2) + (1 ÷ 2) | 1 |
0.5 + 0.5 | 1 |
1 | 1 ✓ |
And finally, an Anti-diagonal qubit also exists in a state of superposition, but as - (“ket minus”). Like the Diagonal qubit it has a 50% chance of being measured as 0 (“ket zero”) and a 50% chance of being measured as 1 (“ket one”).
1 |
-1 |
1 |
√ 2 |
1 ÷ √ 2 |
-1 ÷ √ 2 |
alpha 2 + beta 2
|
1 |
(1 ÷ √ 2)2 + (-1 ÷ √ 2)2 | 1 |
(1 ÷ 2) + (1 ÷ 2) | 1 |
0.5 + 0.5 | 1 |
1 | 1 ✓ |
What does it mean that a Diagonal qubit state and an Anti-diagonal qubit state collapse with the same probabilies? What about their conjugates which also behave in this same fashion? These questions begin to hint at the quirks of quantum circuits; the aspects of quantum computing that quantum algorithms are engineered to take advantage of.
Complex couples
We’ve spent the majority of this primer
describing qubits as containing
alpha
and
beta
values ranging from 0 up to 1.
The unit circle above
illustrates that these values can also range from
0 down to -1.
While all of this remains true,
the story is slightly more complex.
Qubits are actually made of
complex number pairs,
meaning there is an imaginary component.
(See the ComplexNumber
page for a quick refresher on
real,
imaginary, and
complex numbers.)
This means one qubit is actually made of four parts:
The alpha
value
has a ① real
component and an ②
imaginary
one.
The beta
value
also has a ③ real
component and an ④
imaginary
one.
To account for this we must slightly evolve
our definition of a qubit;
specifically the relationship between its
alpha
and
beta
values.
Rather than simply adding their squares together,
we must instead add the squares of their
absolute values.
Our evolved equation,
which indicates absolute values
by enclosing numbers between vertical bars,
now looks like this:
By taking the absolute values
of
alpha
and
beta
before squaring them,
we continue to ensure that our sum of squares
will equal exactly 1; that it continues to equal a simple,
real number
rather than an
imaginary or
complex number.
The Bloch sphere
And that’s really it. That’s what makes a mathematical qubit. But with that last-minute addition of complex numbers above, we can no longer visualize a qubit as a two-dimensional unit circle. Instead we must map our two complex values onto a three dimensional graph known as a Bloch sphere. Select one of the following qubit states to observe its graph on the Bloch sphere. Tap and drag the sphere itself to rotate it.
1 |
0 |
1 |
-i |
1 |
√ 2 |
—˚
polar angle θ (theta)
—˚
azimuth angle ϕ (phi)
Constructor
Qubit
Function([ Q.Matrix* ][
alpha: Number or Q.ComplexNumber,
beta: Number or Q.ComplexNumber [,
label: String [, name: String ]]]) => Q.Qubit
Qubit
extends Q.Matrix
and therefore inherits its
static and
prototypal properties.
The Qubit
constructor
can accept as a single argument a
Q.Matrix
instance,
or anything that inherits from
Q.Matrix
—such as
a Q.Qubit
instance—and will
return a new qubit constructed from the passed object’s values.
Alternatively, the constructor
expects two arguments that are each either
instances of Number
or
Q.ComplexNumber
which will will then correspond to the qubit’s
alpha
and
beta
values.
Further, an optional third argument may be supplied for
label
—expected
in the form of a single character String
—to be
used as a tiny label for the qubit when represented in diagram or graphic form.
Even further, an optional fourth argument may be supplied for
name
—expected
as a String
—to be
used as a more descriptive name for the qubit.
If arguments for
label
or
name
are not supplied then
the constructor checks against the list of existing
constants
and if a qubit with matching
alpha
and
beta
values is found then the corresponding
label
and / or
name
will be copied to this new instance.
When a new qubit is created it internally invokes the
Q.Matrix
constructor,
such that new Q.Qubit(
alpha,
beta
)
is similar to
new Q.Matrix([
alpha ],
[ beta
])
.
If the two supplied values do not satisfy the assertion that
|alpha
|2 +
|beta
|2 = 1
then an error is thrown.
var fox = new Q.Qubit( 1, 0 )
-
- alpha
Q.ComplexNumber
The first of two values that identify the state of a qubit. -
- beta
Q.ComplexNumber
The second of two values that identify the state of a qubit. -
- label
String
Single character representing this qubit state, for example ‘H’ for horizontal. This can be passed to the constructor as an optional third argument or automatically assigned based on existingQ.Qubit.constants
If no match is found among existings constants the ‘?’ character is assigned. -
- name
String
The name of the qubit state, assigned based on existingQ.Qubit.constants
. If no match is found among existings constants the name is left empty. -
- index
Number
An identification number assigned to the instance based on the auto-incrementing static numberQ.Qubit.index
. Used for minding the total number of instances created.
Static properties
Because Q.Qubit
extends Q.Matrix
,
the following append or replace the latter’s existing
static properties.
-
- help
Function ⇒ String
Calls and returns the value ofQ.help
, passingQ.Qubit
as the argument. -
- index
Number
The number of instances created so far.
Constants and constant creation
-
- constants
Object
Constants are appended directly to theQ.Qubit
object. For convenience they are also appended to thisQ.Qubit
.constants object to make looking up constants in the JavaScript console trivial, and to make iterating across all constants convenient via functions likeObject.entries
,Object.keys
,Object.values
, and so on. The intention that a property act as a constant is signaled by its labelling in all-uppercase. -
- createConstant
Function( key: String, value: * )
Appends a property named bykey
with a value ofvalue
to both theQ.Qubit
object and itsconstants
property. -
- createConstants
Function( … )
Expects an even number of arguments. Will use each pair in the sequence of arguments to callcreateConstant
.
Constants — Jones Vectors
Q.Qubit
provides the following built-in Jones vectors.
-
- HORIZONTAL
Q.Qubit
Initialized asnew Q.Qubit( 1, 0, 'H', 'Horizontal' )
. Commonly thought of as “zero” or “off.” Described by the following matrix:
1 0 -
- VERTICAL
Q.Qubit
Initialized asnew Q.Qubit( 0, 1, 'V', 'Vertical' )
. Commonly thought of as “one” or “on.” Described by the following matrix:
0 1 -
- DIAGONAL
Q.Qubit
Initialized asnew Q.Qubit( Math.SQRT1_2, Math.SQRT1_2, 'D', 'Diagonal' )
. Described by the following matrix:
1 1 1 √ 2 -
- ANTI_DIAGONAL
Q.Qubit
Initialized asnew Q.Qubit( Math.SQRT1_2, -Math.SQRT1_2, 'A', 'Anti-diagonal' )
. Described by the following matrix:
1 -1 1 √ 2 -
- RIGHT_HAND_CIRCULAR_POLARIZED
Q.Qubit
Initialized asnew Q.Qubit( Math.SQRT1_2, new Q.ComplexNumber( 0, -Math.SQRT1_2 ), 'R', 'Right-hand Circular Polarized' )
. Described by the following matrix:
1 -i 1 √ 2 -
- LEFT_HAND_CIRCULAR_POLARIZED
Q.Qubit
Initialized asnew Q.Qubit( Math.SQRT1_2, new Q.ComplexNumber( 0, Math.SQRT1_2 ), 'L', 'Left-hand Circular Polarized' )
. Described by the following matrix:
1 i 1 √ 2
Inspection
-
- collapse
Function( Q.Qubit ) ⇒ Q.Qubit
Returns a newQ.Qubit
randomly chosen to be eithernew Q.Qubit( 1, 0 )
— TheHORIZONTAL
constant — ornew Q.Qubit( 0, 1 )
— TheVERTICAL
constant — based on the probability of the supplied qubit argument. -
- applyGate
Function( Q.Qubit ) ⇒ Q.Qubit
Description TK. -
- areEqual
Function( a: Q.Qubit, b: Q.Qubit ) ⇒ Boolean
If thealpha
of each are withinQ.EPSILON
and thebeta
of each are withinQ.EPSILON
then returnstrue
, otherwisefalse
. -
- toBlochSphere
Function( Q.Qubit ) ⇒ Object
Returns the following object for a given qubit’s probability state, useful for rendering a Bloch Sphere representation.{ theta, // Polar angle θ. phi, // Azimuth angle ϕ. // Bloch vector, // the surface point on a Bloch Sphere. vector: { x, y, z }, // Bloch vector “corrected” // for Y-up coordinate systems. position: { x: vector.y,// Note this Y here. y: vector.z,// Note this Z here. z: vector.x // Note this X here. } }
-
- toText
Function( Q.Qubit ) ⇒ Q.Qubit
Description TK. -
- findByBeta
Function( Q.Qubit ) ⇒ Q.Qubit
Description TK.
Prototype properties
Because Q.Qubit
extends Q.Matrix
,
the following append or replace the latter’s existing prototype properties.
Non-destructive methods
-
- clone
Function ⇒ Q.Qubit
Returns a new instance with the values foralpha
andbeta
copied from this instance. -
- collapse
Function ⇒ Q.Qubit
Calls and returns the result of thecollapse
static method, passing the calling instance as an argument. -
- applyGate
Function( gate: Q.Gate ) ⇒ Q.Qubit
Description TK. -
- isEqualTo
Function( otherQubit: Q.Qubit ) ⇒ Boolean
Calls and returns the result of theareEqual
static method, passing the calling instance andotherQubit
as arguments. Will not return aQ.Qubit
instance, and therefore halts “Fluent interface” method chaining along this prototype. -
- toBlochSphere
Function ⇒ Object
Calls and returns the result of static methodQ.Qubit.toBlochSphere( this )
. Will not return aQ.Qubit
instance, and therefore halts “Fluent interface” method chaining along this prototype. -
- toText
Function ⇒ String
Description TK. Will not return aQ.Qubit
instance, and therefore halts “Fluent interface” method chaining along this prototype.
Destructive methods
-
- copy$
Function( otherQubit: Q.Qubit ) ⇒ Q.Qubit
Overwrites this instances’srows Array
with that ofotherQubit
. -
- collapse$
Function ⇒ Q.Qubit
Expects no arguments. Calls the non-destructivecollapse
method, then usescopy$
to overwrite this qubit’s values. -
- applyGate$
Function( gate: Q.Gate ) ⇒ Q.Qubit
Description TK.