Introduction

This code through explores using the R package qsimulatR for simulating quantum computers by exploring qubits, quantum gates, and their role in quantum cirucuts. “But why would I want to do that!?”, you ask?

Here, let me explain!…

Body

Background on Quantum Information Science and Technology (QIST)

Technologies designed on principles of quantum mechanics have been around for decades such as contemporary staples like lasers, MRI machines, atomic clocks, and transistors. These are considered Quantum 1.0 technologies that exploit the statistical behavior of matter in bulk, such as an particle’s spin (Fortier, 2024). For instance, MRI machines work in part by using magnets to manipulate the body’s collective protons (Merritt Laboratory, n.d.).

We are moving to into what has been called the second quantum or Quantum 2.0 revolution, however, where technologies exploit quantum mechanical principles like superposition and entanglement on an individual systems level (e.g, electrons, neutrons, and protons in the atom) rather than manipulating in bulk like an MRI’s magnetization. Matter at this more individualized scale appears as both a particle and a wave, which means matter can be in multiple points or states simultaneously (superposition), and which can connect across distances (entanglement).

This shifting focus has led to an emerging field of quantum information science and technology (QIST) which combines quantum mechanics, computer science, and information theory. Development in this field can be divided into four categories: quantum computing, quantum simulation, quantum sensing, and quantum networks. Reductively, quantum computers are special purpose computers that use qubits for information transmission and can execute some problems more efficiently than their counterpart. Quantum simulators are either classical technologies that can simulate quantum systems or will be quantum technologies that simulate quantum systems (when technology advances to that point). Quantum sensors are more sensitive sensors (such as those used in biological scans) in comparison to their classical counterparts. Quantum networks will eventually connect networks of quantum computers and also are way information is communicated and secured. While developments in any of these categories are not necessarily exclusive of each other, they do help represent larger trends.

Background on Quantum Algorithms and Simulation

Cross-cutting these technological categories are quantum algorithms that are needed to either (1) run quantum operations on classical technologies or (2) develop quantum technologies themselves. Quantum algorithms are part of a larger piece of the quantum stack (other components of the stack include e.g., hardware and software) that are needed not only to turn theory into tangible materials, but they are also needed to build, scale, and continuously run quantum technologies successfully (TU Delft, 2026). The benefits of quantum algorithms are that while classical algorithms are guided by logic and binary processing and 1s or 0s, which most often leads to predictable and reliable responses, quantum algorithms more or less help establish a probability that a qubit will be a 1 or a 0 once it is measured. While this uncertainty can sound problematic, this probability is key to the charm of quantum algorithms. If we can get a quantum computer to explore multiple possibilities simultaneously, this can ideally speed up the processing of complex data. (See Microsoft’s discussion of the principle of interference for more information about the potential for higher processing speeds (Microsoft Quantum, “Interference”, 2026)).

While eventually quantum computers will run quantum algorithms for optimum conditions, we are currently able to simulate quantum states using quantum algorithms on classical computers. It is important to remember that while there are a variety of categories of quantum algorithms and whose use depends on the task (SpinQ, 2025), there is also no single coding language that must be used to do so (QuEra, 2023). While Python is one of the more popular choices and can currently be used on a functional quantum computer through programs like IBM’s Qiskit, R can also be used.

Thus, back to the beginning, let’s explore one type of quantum algorithm, just to say we did it and shake hands with the future of computing!


Content Overview

From this premise, the purpose of this code-through is to demystify some aspects of QIST and quantum computing. While you will certainly not leave this module knowing the linear algebraic foundations of quantum algorithms (see Microsoft Quantum, “Quantum Math”, 2026), you will see how the codes that people type on their keyboards can actively manipulate qubits. This peek behind the curtain both provides a functional understanding of quantum technology and makes it easier to have meaningful conversations about it and its role in our technological futures (De Jong, 2026). The module will try to make this conversation more accessible by showing distant, but parallel examples to the mathematical concepts behind network analysis in terms of vectors and matrices. The tutorial will use the R package qsimulatR.


Why You Should Care

You should care about this topic because functional quantum computers are less than ten years away, and quantum sensors are already more prolifically on the market now. If you think you’re behind the curve on AI or want to prepare yourself or younger generations for tomorrow’s workforce, developing quantum science and technology literacies is the first step in becoming involved. While it is likely that quantum software programs will be developed where an everyday user does not need a deep technical foundation, a little bit of working knowledge on what quantum computing actually looks like now will be a sensitizing experience for the future that will lead to a greater level of awareness and comfort about these technologies (TU Delft, 2026).


Learning Objectives

Specifically, in this module, you’ll learn what a qubit and a quantum gate looks like and how it connects to a quantum circuit. While the module does not attempt to explain the mathematics behind the algorithms, you can at least get a sense of what quantum algorithms are and how what you are doing can actually simulate a real qubit on a quantum computer. Overall in this module, though, no need to try to work out the math, just enjoy the visual spectacle of manipulating the invisible!



Further Exposition: The Origins of Quantum Algorithms on R

Using R to write a quantum algorithm is based on the work of Johann Ostmeyer and and Carsten Urbach in their R package “qsimulatR.” qsimulatR is designed to work with up to 24 qubits at a time and simulate control over them (rProject.org, 2023). While conceptualized more as an educational tool because quantum computers are not mainstream technologies, qsimulatR is still a vital tool for getting familiar with quantum programming. Ostmeyerand and Urbach (2020) described the importance of their package by stating, “Exploring quantum algorithms on classical computers is especially useful because this allows interested parties to create and test algorithms both for future use and for understanding the logic of quantum computers and their algorithms.” Their R package is especially ideal for those familiar with R, however, because it does allow users to export circuits to IBM’s Python-based software ‘Qiskit’ that can actually run on IBM’s quantum computer (Urbach, 2020).


Quantum Algorithms: Qubits, Gates, and Circuits

Before beginning, a few key terms are important to discuss. The key components of a quantum algorithm we’ll be exploring are qubit, the quantum gate, and the quantum circuit. (Note that some companies are pursuing research on quantum annealing instead of gate-based models, but annealing is beyond the scope of this tutorial.)

As noted previously, qubits are the fundamental units of quantum information science are used to encode data. They are similar to the classical bit in that we call their different positions 1s and 0s, however, they are fundamentally different and not turned on and off by electrical impulses.

Quantum gates are the basic processes that manipulate qubits. In the math of quantum algorithms, gates are represented by matrices, or grids of numbers, and qubits are represented as vectors, or a single column of complex numbers that help determine the likelihood of measuring 0 or 1. (Remember the qubit is a real physical system.) When you multiple a vector by a matrix multiplies a vector, this calculation transforms the qubit’s state (Microsoft Quantum, “Quantum Math”, 2026). These transformations create superposition, entanglement, and interference, which algorithms use to amplify probabilities of correct answers and cancel out wrong ones.

Quantum circuits coordinate a larger operation and organize gates into sequences, leading qubits through specific steps to execute an algorithm.


A Parallel from Network Analysis

A Basic Example: Vectors

While all of this can be terribly complex, especially without an understanding of linear algebra, the description on a broad level can help with some visual recognition of what happens in a quantum algorithm. One useful way to start this conversation is to start with something more recognizable and then pivot.

Thus, the first step in this code though exercise is to practice creating a vector in R. This is one of the more basic activities that even novice programmers might work with.

As a starting point, consider and create vector types and explore their properties and attributes:

# Vector Types

numeric_vector <- c(1, 2, 3)
logical_vector <- c(TRUE, FALSE, FALSE)
character_vector <- ("Hello")

numeric_vector
## [1] 1 2 3
logical_vector
## [1]  TRUE FALSE FALSE
character_vector
## [1] "Hello"
# Vector Properties: types and length

typeof(numeric_vector)
## [1] "double"
length(numeric_vector)
## [1] 3
typeof(logical_vector)
## [1] "logical"
length(logical_vector)
## [1] 3
typeof(character_vector)
## [1] "character"
length(character_vector)
## [1] 1
# Vector Attributes: names and class

numeric_vector <- c(a = 1, b = 2, c = 3)
names(numeric_vector)      
## [1] "a" "b" "c"
class(numeric_vector)
## [1] "numeric"
logical_vector <- c(a = TRUE, b = FALSE, c = FALSE)
names(logical_vector)
## [1] "a" "b" "c"
class(logical_vector)
## [1] "logical"
character_vector <- c(answer = "Hello")
names(character_vector)
## [1] "answer"
class(character_vector)
## [1] "character"

While these vectors do not directly translate to quantum algorithms, they do help remind us what vectors look like and how they hold information.

Find more information about vectors in R here: https://r4ds.had.co.nz/vectors.html

Network Analysis and Vectors

To offer a slightly more concrete example of vectors, we can think about three people that want to send messages to each other: Alice, Bob, and Charlie.

Alice sends 3 messages. Bob sends 2 messages. Charlie sends 0 message.

In other words, c(Alice = 3, Bob = 2, Charlie = 0)

# Put together, we might do this to create a vector:

messages_sent <- c(Alice = 3, Bob = 2, Charlie = 0)

messages_sent
##   Alice     Bob Charlie 
##       3       2       0

For this vector, we see three named numbers which correspond to the messages that each person sent.


Another Basic Example: Matrices

Now we can move on to making a matrix. Matrices are two dimensional data sets with columns and rows (W3, 2026).

Network Analysis and Matrices

While you might be familiar with how to do this and why, we’ll use an example from network analysis.

Here is the next premise:

Alice is friends with Bob but not Charlie. Bob is friends with Alice and Charlie. Charlie doesn’t like anyone.

To set this up in a matrix, we can think of each person occupying a row of a 3 x 3 table. In the case of this table, we can imagine that a 1 means the row/column pair are friends, and zero is entered in the diagonal where the row value (e.g. Alice) meets the column value (e.g, Alice).

Consider Alice’s row: A B C Alice 0 1 0 (Here, Alice is not considered a friend to herself (0) or Charlie (0), but is friends with Bob (1)).

Consider Bob’s row: A B C Bob 1 0 1 (Here, Bob is listed as friends with Alice (1) and Charlie (1) but not considered a friend to himself (0).

Consider Charlie’s row: A B C Charlie 0 0 0

(Here, Charlie doesn’t like anyone ALice (0) and Bob(0), and his self-friendship is not considered (0).

What does this look like in R?

# Here we create a vector with the names of people
people <- c("Alice", "Bob", "Charlie")

# Then, we can make an empty 3x3 matrix before entering the actual information
friends <- matrix(0, nrow = 3, ncol = 3, 
                  dimnames = list(people, people))

# Then we apply our rules
# This says that Alice is friends with Bob but not Charlie because he is not included, and not himself because self-friendship is not counted

friends["Alice", "Bob"] <- 1

# Bob is friends with Alice and Charlie and not himself because self-friendship is not counted
friends["Bob", "Alice"] <- 1
friends["Bob", "Charlie"] <- 1

# Because Charlie doesn't like anyone, so we can leave this empty as it returns 0s

#Now we can look at our table

friends
##         Alice Bob Charlie
## Alice       0   1       0
## Bob         1   0       1
## Charlie     0   0       0


Here, we have made a matrix, or a two dimensional data set with columns and rows that convey information. It is two dimensional because we have to look at two places to get the information that we need.

While a network analysis may not wholly correspond to the type of information that a quantum algorithm might convey, we are encouraged to think about the relationships between the individuals and the possible connections between the people/points.

See more about matrices in R here: https://www.w3schools.com/r/r_matrices.asp (W3Schools.com, 2026)

Putting Vectors and Matrices Together for Network Analysis

Switching now to quantum, this network analysis example allows us to think in terms of the data represented by a vector (e.g., Alice, Bob, and Charlie) and a matrix (e.g., their friendships).

Quantum algorithms do not have anything to do with network analysis, but they do have a lot to do with vectors and matrices. Whereas network analysis conveys the connections between people and points, vectors in quantum algorithms convey the current state of a qubit, and matrices convey the operations that can change this state.


In this premise, we will take this converation a little bit further.


Recall, our vector reflected this:

Alice sends 3 messages. Bob sends 2 messages. Charlie sends 0 messages.

c(Alice = 3, Bob = 2, Charlie = 0)

Alice Bob Charlie 3 2 0


Recall that our matrix also reflected this:

Alice is friends with Bob but not Charlie. Bob is friends with Alice and Charlie. Charlie doesn’t like anyone.

Alice Bob Charlie Alice 0 1 0 Bob 1 0 1 Charlie 0 0 0


Now suppose that we want to know who received messages and how many were received, knowing that the messages are only sent between friends. In this scenario, we would need to multiply the vector of messages by the relationship as friends. These calculations can help us understand who may have received the messages. This calculation looks like this:

#Calculating who received the messages

messages_sent <- c(Alice = 3, Bob = 2, Charlie = 0)

messages_received <- messages_sent %*% friends
messages_received
##      Alice Bob Charlie
## [1,]     2   3       2

From this calculation, we see the possibilities of the distribution of messages and how many messages that each person would get if any friend receive copies of all messages sent. (Bob’s 2 messages are counted twice because he is friends with both Alice and Bob.)

While not the same as quantum algorithms which use matrices to calculate probability, these vector and matrix examples from network analysis provide at least a potentially more familiar parallel about some of the mathematical moves that quantum algorithms attempt. We needed to know what was in the vector, and we needed to know what was in the matrix, and we needed to multiply both together to understand the the answer. We need to multiply both by each other to arrive at these calculation.

##Advanced Examples - Qubits as Vectors

This is the same scenario as quantum algorithms. We need to multiply a matrix by a vector to understand the state of the qubit after it goes through this gate.

The thing is with quantum algorithms, though, and the qsimularR package, the numbers get much more complex than the small network example, and the beauty of the package is that it helps execute these calculations through the package.

We can start off with what we can see, however, and look at a qubit as a vector.

As noted above, qubits can be represented as quantum vectors as 0, 1, and 0/1. This might look like this in R:

# |0> state
q0 <- qstate(1, coefs = c(1, 0))
q0
##    ( 1 ) * |0>
# |1> state  
q1 <- qstate(1, coefs = c(0, 1))
q1
##    ( 1 ) * |1>
# Superposition state - # |+> state: 
qplus <- qstate(1, coefs = c(1/sqrt(2), 1/sqrt(2)))
qplus
##    ( 0.7071068 ) * |0> 
##  + ( 0.7071068 ) * |1>
#[DISCLAIMER: This code adapted from the r-bloggers and verified by using Llama 4. Use your own discretion to check the code's veracity.]

See https://www.r-bloggers.com/2023/07/quantum-computing-with-qsimulatr/ (R-bloggers, 2023) for more information.


Advanced Example: Quantum Gates as Matrices

Related to this, then, the vector is multiplied by a matrix, which is essentially a gate that helps to manipulate the state of the qubit. We need to look at the current state of the cubit represented in the vector to understand how its multiplication by the matrix might change its position.

While earlier we saw what a matrix looked like for a small social network, the matrices/gates used by quantum algorithms often come from standard, textbook varieties of gates, such as the Pauli-X gate, the Pauli-Y, the Pauli-Z Gate, or the Hadamard Gate (Gupta, 2025).

As demonstrated by R-bloggers (2023), you can see here what one of these gates, the Hadamard Gate which creats a uniform superposition, might look like when using the qSimulatR package in R:

#This applies the Hadamard gate, which creates a uniform superposition, to 0

# H|0> = |+>
H(1) * qstate(1)
##    ( 0.7071068 ) * |0> 
##  + ( 0.7071068 ) * |1>
# H applied twice: H * H|0> = |0> to make sure the math is correct
H(1) * (H(1) * qstate(1))
##    ( 1 ) * |0>
#Looking around part 1

# Look at H gate structure
str(H(1))
## Formal class 'sqgate' [package "qsimulatR"] with 3 slots
##   ..@ bit : int 1
##   ..@ M   : cplx [1:2, 1:2] 0.707+0i 0.707+0i 0.707+0i ...
##   ..@ type: chr "H"
# Looking around part 2 - and you can see the matrix!
# View the H matrix
H(1)@M
##              [,1]          [,2]
## [1,] 0.7071068+0i  0.7071068+0i
## [2,] 0.7071068+0i -0.7071068+0i
# Looking a bet at application
#The Hadamard operation on a few qubit state vectors 

# H|0> = |+>
H(1) * qstate(1)
##    ( 0.7071068 ) * |0> 
##  + ( 0.7071068 ) * |1>
# H|1> = |->
H(1) * (X(1) * qstate(1))
##    ( 0.7071068 ) * |0> 
##  + ( -0.7071068 )    * |1>
# H|+> = H * H|0> = |0>
H(1) * (H(1) * qstate(1))
##    ( 1 ) * |0>
# H|-> = H * H|1> = |1>
H(1) * (H(1) * (X(1) * qstate(1)))
##    ( 1 ) * |1>
# Plotted representation of this uniform superposition gate
x <- qstate(1)        # |0> state
x <- H(1) * x         # H|0> = |+>
qsimulatR::plot(x, qubitnames = c("|0>"))

Finally, the result of the code returns this is seen through this final statement:

H(1)*qstate(1)
##    ( 0.7071068 ) * |0> 
##  + ( 0.7071068 ) * |1>

As R-bloggers (2023) describe, what this prompt and answer shows is that “the result of this uniform superposition of |0> with the H gate can be labeled as “|+>” (the plus state) quantum state vector” and further, “We say that the H(1) operation is used to exchange between the z-axis basis ({|0>, |1>}) and the x-axis basis {|+>, |->} in the Bloch sphere.”


Full disclosure, you likely didn’t understand this if you are not an expert, and this might not make sense. But you did it! You played around with a quantum simulator, and you applied a gate to a qubit! That is our win for today.


Conclusion

Even if this tutorial hasn’t resonated with you, you tried! And again, a solid grip on quantum algorithms was not the goal of this tutorial. Most notably, and returning back to the purpose of this code through articulated at the beginning of this module, the purpose of this code through was to help demystify quantum technologies by showing their mundane (albeit complicated) roots. Quantum computing is not something inexplicable or at the whims of nature. Instead, it is a calculated process executed step by step like other algorithms, just a little different. You can even lead a qubit.

With this in mind, I hope you understand qubits, quantum gates, and the quantum circuits that order the process a little bit better. Please return to your daily lives but also pay attention a little more to quantum technologies and the potential that they hold for the future. While today you might have shook hands a bit with quantum algorithms and learned what they were about, you will likely see a lot more of quantum tech in the future.



Further Resources

Learn more about quantum computing and the quantum computing stack:

Learn more about the qsimulatR R package:


Full Works Cited

This code through references and cites the following sources: