Some useful skills for quantum computing

If you’re reading this, you’ve probably also read about some of the neat things you can do with Q# and quantum computing, and are eager to try out this whole quantum development thing. Like any other part of computing and development, there’s some skills that can really help you out on your way, so in this post I’ll talk about what some of those skills are and how you can practice the non-quantum stuff that will make your quantum journey a bit easier.

Before that, though, it’s worth mentioning a small bit of a disclaimer. There’s no one right skillset that you need for quantum computing. In my previous post, I talked a bit about my path towards quantum computing, and about how rewarding it can be to work with people that come at things from a different perspective and background. As you go forward with quantum computing, you’ll find your own way to make a difference, your own way to leave both the technology and the community better than how you found it. Thus, my focus here isn’t on what skills you need, but what skills can be useful. You don’t need to be an expert in everything or even any one thing in particular in order to get going with quantum computing.

With that caveat in mind, then, let’s get down to brass tacks and explore some things you may find helpful along your way.


Even though it’s not required, being comfortable with math can be really quite helpful as a quantum developer. Most documentation in quantum programming languages involves at least a bit of math, so being familiar with a few mathematical concepts can help you make the most out of the resources that are already out there. The most fundamental descriptions of quantum computing are expressed using ideas from linear algebra and complex numbers, such that a familiarity with each can help you peel back the layers a bit and see how things work.

That doesn’t mean you’re doing quantum computing on hard mode if you aren’t a PhD-level mathematician, though. Really, this is another way that quantum computing is a lot like other areas of computing. If you try to read about OpenGL, knowing some math will help you get the most out of documentation. Similarly, machine learning involves a fair bit of math, you can also get quite a ways by following along with examples or using high-level libraries.

What’s really exciting, though, is that you can also practice your math skills as you go. In our Q# book, Sarah Kaiser and I write most of our the QuTiP package for Python to handle doing most of the math, so that you can jump right in and see how things work without having to do all of the math yourself.

If you want to preload things a bit, though, refreshing your memory on linear algebra and complex numbers will give you a head start with quantum computing content.

Classical Software Development

As I talked about in my previous post, many of the skills that help me out the most as a quantum developer are classical software development skills. Brushing up on classical languages like Python or C#, unit testing, how to manage projects with Git, how to work with containers, how to write and test code with an IDE, or any number of other skills can help you contribute to open source quantum projects, and can help you to make progress with your own projects.

Thankfully, there’s a lot of good resources to help you out here, itself not the least of them! If you’re already a seasoned software developer, that will help you out as you go forward with quantum computing. On the other hand, if you’re new to software development, welcome! Your original way of looking at and learning about computing will help you make a difference with quantum computing.


There’s no way to underestimate this one. Quantum computing is a big field, bringing together a lot of different ideas and ways of looking at the world. That means that as you progress through your quantum computing journey, you’ll write e-mails, tweets, blog posts, documentation, and many other kinds of things in order to communicate those ideas with your community.

That’s not to say you need to be an amazing novelist, of course (though if you are, awesome! 💖). Rather, my point is that math and prose go hand-in-hand for communicating quantum ideas. Being comfortable with writing isn’t necessary to get started in quantum computing, but it can help you ask questions on StackOverflow that help others on their journey, to file informative and descriptive bug reports, to improve Wikipedia articles that others use to look up quantum concepts, and can help you explain ways of looking at quantum computing that you found useful. As you build your own quantum projects, your writing skills can help you make documentation that lowers barriers instead of raising them.

In my experience, there’s two main parts to getting better at writing. The first? Reading. Spend time on, Twitter, StackExchange, arXiv, and whatever other platforms you find useful for talking about quantum computing. Pay attention to what things other writers do that help you, and what things make it harder for you to learn, so that you can use that in your own writing. The other part of brushing up on writing skills, of course, is to practice. Even if you think it’s crappy, writing a lot can help you find a voice that you can use to make the quantum computing community that much more wonderful.


The last and absolute most important skill that I can suggest practicing is empathy; it may even be the only mandatory skill on this list. Quantum computing, just like every other kind of computing, is a thing that humans do. Listening to those humans — your peers! — can help you understand where they get stuck and might need a little help, where they need your help making the community the best it can be, and where they might be able to help you get unstuck.

Your peers in the quantum community come from all walks of life, not just in terms of skills, but also in terms of who they are as people. The quantum computing community includes people of all genders, sexualities, races, nationalities, and kinds of disabilities. Listening to your peers can help you break down the barriers that they face in any number of small and large ways. By putting empathy into practice, you can ensure that you not only make a difference in the quantum community, but that you make a difference for the better.

If you like this post, vote for it on, or read Learn Quantum Computing with Python and Q#, now available in early access from Manning Publications.

What is a Quantum Developer, Anyway?

Quantum computing has been, to put it mildly, in the news a bit as of late. With so many different announcements about and developments in quantum computing, it can feel a bit daunting to jump in and get started. Sometimes, quantum computing can even pick up an air of mystique about it, given popular analogies such as “two places at once,” “action at a distance,” and other pretty confusing explanations.

While there’s thankfully quite a range of good content out there to help you get started, it can still be hard to get a feeling for what it’s like to actually be a quantum developer. As I talk to people at the bar, in carpools, on Twitter, at conferences, and the like, saying that I work on quantum computing can be a bit of a conversation killer; sure quantum computing is cool, but what do I do? With this post, I’d like help to demystify things a little bit by talking about what quantum development is like for me as I go about my day.


But first because everyone’s path to quantum development looks different, a little bit about myself can provide some helpful context. I’m Chris Granade, a research software development engineer in the Quantum System group at Microsoft. Before that, I did a triple-major at the University of Alaska Fairbanks, a Masters degree at the Perimeter Institute, a PhD at the Institute for Quantum Computing, and a postdoc at the University of Sydney. Needless to say, learning about quantum computing has been a bit of a thing for me throughout much of my life. In my spare time, I’m as liable to be shitposting surreal memes, planning a World of Darkness tabletop campaign, or taking our adorable puppy for a walk to one of Seattle’s surprisingly numerous dog-friendly breweries.

insert pun here

Given that, one might think I spend all day buried in obscure journal papers, nose-deep in a pen-and-paper calculation, or scrawling at a chalkboard. While those are all completely valid and useful ways of working on quantum computing, I’ve tried my hand at them and found that at least for myself, there are other ways I can contribute.

Even before starting in undergrad, for example, I have always found a joy in solving problems using programming. I got my start back with QBASIC and GWBASIC (yes, I am officially an Old; I’m also a Millennial, somehow?), and loved that I could use programming to get answers to things I was curious about. When I wanted to understand population growth and how that affected ecology better, I borrowed my mom’s population dynamics textbook and started programming things up as VBA macros in Excel.

As it turns out, that’s a great approach to working with quantum computing as well. Building a quantum computer is hard, and there’s lots of ways that classical computers help us out on our way there. We can use classical computers to model what we want quantum computers to do, using linear algebra packages to help us out, or we can use classical computers to run statistical inference algorithms on the data we get back from quantum devices to help us understand how to make better ones. Of course, we can go much further as well and use classical computers to write and test the actual programs we want to run on quantum computers; hence the emergence of quantum programming languages like Q#!

So, what do you do?

As soon as you start using classical computers to solve problems of any sort, you get back into the fun issues of building, testing, packaging, deploying, and designing classical software. Recently, as a part of the 2019 Q# Advent Calendar, Andres Paz explained many of the pieces that make up Q# and the Quantum Development Kit. Making Q# work involves writing classical compilers and simulators, integrating with existing languages like C# and Python, making editor integration extensions to help us write quantum programs in the first place, writing documentation for everything, and even making Docker containers to power online-first experiences for Q#. This is a team effort, as designing, building, and maintaining the Quantum Development Kit necessarily involves more kinds of expertise what any one member of the team brings with them.

For myself, I tend to fit into that team effort by designing and maintaining the different Q# libraries that come with the QDK, and by working with domain experts to make those libraries as awesome as they can be. This means that a large part of my day is writing unit tests in Q#, fixing things when builds fail, reading through pull requests, and working on the best way to package things up so that other quantum developers can make use of the code that I help out with. If you’re curious to see more of what I do, follow me on GitHub! Since the Quantum Development Kit is open source, you can follow along as we add new features, fix bugs, introduce new bugs, and otherwise do what you’d expect software developers to do.

Put differently, a large part of the skills that help me as a quantum developer are the same skills that help out in any other software development engineering role. While I do use the skills that I’ve learned throughout my quantum computing training on a daily basis, it’s the traditional software development engineering practices that give me the basis I need to make use of those skills.

There’s a point to all this, right?

As you get involved in quantum computing, you’ll bring your own skills, background, and experience to what you do. There’s no one way to be a quantum developer, or to contribute to the quantum computing community. My hope is that by showing my particular path, I can provide an example of the way I use my particular background to help the community. Your path will look different, and that’s not just OK but wonderful. The breath of different skills and backgrounds that come to bear on quantum computing is one of the most amazing things about this field. You’ll do amazing things here, and you’ll do them your way.

If you like this post, vote for it on, or read Learn Quantum Computing with Python and Q#, now available in early access from Manning Publications.

Reproducible Research with Q#

This post is part of the Q# Advent Calendar 2019. Follow the calendar for other great posts!


Almost three years ago, I wrote here about the importance of reproducible research, and about tools that can be used to make it easier to perform research in a way that makes reproduciblity easy. Making it easy to do research in a reproducible fashion is critical — not just to avoid the gatekeeping that all too often comes along with research, but also because people are much more likely to do the things that we encourage them to do. Though reproducible research is critical throughout science, it’s also near and dear to my own heart given the importance to quantum computing.

Looking back at my post, a lot can change in three years. That’s definitely been true in the quantum computing community. Indeed, three years ago, the quantum computing community was much smaller, and much more heavily focused on more abstract research results. As the community has grown, we’ve seen a huge growth in both the number and variety of tools available to help explore quantum computing through reproducible research. In this post, I’ll take an opportunity to highlight how it’s easier than ever to get started in reproducible quantum computing research.

Let’s start with the punchline, though: the only software you need to get started is a browser.

Reproducible Research with Visual Studio Online

As a member of the team that launched the Quantum Development Kit and the Q# language two years ago, I’m particularly excited for how Q# has helped enable quantum computing research by making it easier to develop and test quantum algorithms, estimate resource costs, and once Azure Quantum launches, even to run quantum programs on hardware. Thanks to the recent launch of Visual Studio Online, you can now do all of that from your browser. To get started with Visual Studio Online, you’ll need two things:

If you don’t already have an Azure subscription, you can get $200 worth of free credits to help you get started. Note that if you’re at a university or other research instutition, they may also have purchased an Azure subscription already.

In either case, I’ve put together a template to help you get started, so let’s go on and get started. Go to, and you should see a button labeled “Use this template.”

When you click that button, you’ll be prompted to make your own GitHub repository to help collect your work and share it with your collaborators. Go on and give your new repository a name, and press “Create repository from template.” It will take a few moments, but then you’ll have a repo all setup with the start of a LaTeX manuscript, some Q# code, and a script that will package everything up for uploading to the arXiv.

Next, let’s go to Visual Studio Online and use your new repository to setup an environment. The template you copied in the previous step comes with instructions that Visual Studio Online can use to install LaTeX, Python, the .NET Core SDK, and other software that’s helpful for doing quantum research.

Go to and click “Get Started.” Sign in with the account you use to get to your Azure subscription, and you’ll be taken to the main Visual Studio Online portal. Note that you may be prompted to create a plan if you haven’t already done so. This tells Visual Studio Online what subscription you want to use with your new environment; handy if you have multiple subscriptions.

In any case, press “Create environment,” give your new environment a name and then put in the name of the repo you created above.

Once you do all that, time to grab a coffee (or, if you’re Chris Ferrie, a couple coffees). By the time you get back, your new environment should be up and running, with everything installed from the template.

You can then write Q# code, run it, and embed the code directly into your paper.

Go on and try it out! Open up src/Operations.qs from the side bar, and replace the definition of HelloQ with the following Q# code:

open Microsoft.Quantum.Measurement;

operation HelloQ() : Unit {
    let randomBit = SampleRandomBit();
    Message($"Got {randomBit}!");

operation SampleRandomBit() : Result {
    using (q = Qubit()) {
        return MResetX(q);

Next, open up your TeX manuscript, and try changing some text. Whenever you save, your manuscript will automatically recompile and import the changes you made to your Q# sources.

Of course, you can run things too. Press Ctrl+` or Command+` to bring up a terminal window, then run the following commands to see what your new Q# program does:

$ cd src
$ dotnet run
Got One!

If you prefer Python, that’s cool too:

$ python
Got 0!

When you’re ready to post to the arXiv, that’s just as straightforward:

$ cd ..
$ pwsh Export-ArXiv.ps1

Taking a step back, you got started writing quantum programs in Q#, included them in your manuscript, and got them ready for publication, all without installing a single piece of software.

Where this really helps with reproducibility, though, is that your collaborators can also make a Visual Studio Online environment from your new repository. That will ensure that they run exactly the same software that you use for your part of the project. When you’re done, you can go on and upload to arXiv using the provided script, making sure that all your source code comes along with your result.

There’s a Lot to Unpack Here

If the above all seems like magic, it isn’t: it’s the power of using the best open-source platforms around to do research. Let’s see how that all comes together by taking a trip through the various technologies that you used in your template above.

Contain Yourself

The first thing to look at is the concept of a container. Using Q# to do reproducible research, your software stack might look a little different than it did three years ago. For example, if you want to use Q# together with great host languages like C# or Python, and then include all of that into a paper written with LaTeX, you may wind up needing a variety of different tools:

  • .NET Core SDK (used to provide the Q# compiler)
  • Python
  • TeX / LaTeX
  • Jupyter Notebook
  • Visual Studio Code
  • Git

While thankfully these tools are all pretty straightforward to install, for reproducible research, that can present a bit of a challenge. The more dependencies you take, the greater the chance one of your collaborators, referees, or readers will have a different version of something than what you used. That can make it difficult to run your code and to verify your results.

This is also a problem for very different reasons in many other areas of computing, so for research purposes, we can borrow a trick or two to help us out. In particular, the past few years have seen an explosion in the use of containers to isolate application dependencies for each other, and to deploy software in a robust way.

We can use that same idea to help out with research! Much like Python’s virtual environments or Anaconda’s conda envs, containers can be used to manage side-by-side software installations, letting you use different versions of software packages for different projects.

The Quantum Development Kit uses this concept, for instance, to package everything you need to use IQ# in Jupyter Notebooks into a single container. The instructions on the IQ# repository tell Docker, a popular container engine, how to build that container by installing different other packages into the IQ# container.

Once you have a container like one built to use IQ# and the Quantum Development Kit, there’s any number of different ways you can use it to do awesome stuff. If you’ve used the zero-install version of the quantum katas, for instance, that uses the IQ# container together with a really neat open-source service called Binder. When you use Binder with a project, that launches a new VM for you, builds a new container from the IQ# container, and forwards the Jupyter Notebook server running in the new container over to you. While that is fairly complicated, it means a really straightforward experience for you when you try out different research, tutorials, or other content hosted on Binder.

Getting a Bit More Remote

It turns out that Visual Studio Code can make use of the same kinds of container technology to help you develop your research. If you noticed, there’s a folder called .devcontainer in the Quantum Development Kit samples, the quantum katas, the Q# libraries, and even in the template you just used above. These folders specify what containers to use when developing on those projects. Once you have the right extension installed, when you open one of those repositories, that builds a new container from the instructions in .devcontainer. Most of Visual Studio Code then runs inside that new container; only the graphical interface is running on your normal operating system.

From the standpoint of reproducibility, that’s great, as it means that all the software you use for a project is specified in one place, irrespective of what you might have installed on your normal OS. Because the Quantum Development Kit is provided as a container, it’s really easy to use with devcontainers as well.

Very Online

What does all this have to do with Visual Studio Online, though? It all comes down to that Visual Studio Code is built on another popular open-source technology, called Electron. Electron works by embedding a version of Chrome to run your different apps. This means that Visual Studio Code is effectively a web app tied to a special-purpose copy of Chrome. You can even press Ctrl+Shift+I or Command+Shift+I to get to the same debugger tools as

Most of Visual Studio Code is written using web platforms like HTML, CSS, and TypeScript, similar to how you might make a traditional web app. This means that the browser-based version of Visual Studio Online can work very similarly to Visual Studio Code, reusing existing technologies.

Phew, What Now?

Research is best when we share it with people, collaborate on new ideas, and expand the communities around us. Reproducible research helps us realize on those goals by making sure that our results are trustworthy and can form the basis for new research, new ideas, and new communitity members.

When we apply this insight to a quickly growing field like quantum computing, that only becomes more urgent. It’s all too easy to put up new walls, jealously guard our research, and close ourselves in. Thankfully, services like Visual Studio Online and open-source platforms like the Quantum Development Kit can use help us make the most of our research and be the best members of the quantum computing community that we can be. In this post, I tried to give a small taste of that, but it definitely doesn’t stop here. Please explore, try things out, and leave the quantum computing research community a better place than you found it! 💕

Quantum Computing: Looking Sharp

Last week, I took a look at what a quantum state is in the context of quantum development, using Q# to get a handle on things. Today, though, I’d like to take a little step back and look at what Q# is in the first place, as well as some things that Q# is not.

Q# is a Programming Langauge

When you get right down to it, quantum programs are classical programs that tell a quantum computer what to do. After all, we want to be able to work with classical data, and to get classical data back out from our quantum computers.

From that perspective, then, it’s really important that Q# is a programming language. For instance, a traditional “hello, world” application looks pretty much how you might expect a “hello, world” application to look:

namespace HelloWorld {
    open Microsoft.Quantum.Intrinsic;

    /// # Summary
    /// Says hello to the world.
    function Hello() : Unit {
        Message("Hello, world!");

As a programming language, Q# builds on the long history of classical programming languages to make it as easy as possible to write quantum programs as well. For example, throughout the history of classical programming, we’ve learned that features like namespaces and API documentation comments help us organizing and understanding our code; we can already see both features on display here in our “Hello, world” Q# program.

Q# is a Domain-Specific Language

Given that Q# is “just” a programming language, one might then ask why it exists at all. We could in principle write our quantum programs in existing classical languages like Python, C#, Java, JavaScript, and so forth. That said, each language we work with in software development is engineered to be good at different tasks, and to focus on different domains.

Q# is distinct from other programming languages in that it is designed from the first step to be great at writing quantum programs. This means that Q# makes some choices as to what features to include and which features to leave out that are unusual for general-purpose classical languages, but that make it really easy to write rich quantum programs.

For example, since quantum mechanics is reversible, one common pattern in quantum programming is to run a subroutine backwards. We may want to write a program that converts some quantum data into a representation where it’s easier to do a particular calculation, do that calculation, then undo our first transformation. In Q#, this is supported by the Adjoint keyword, which represents the inverse of an operation. Just as we can run PrepareEntangledState to entangle the state of some qubits, we can run Adjoint PrepareEntangledState to measure out that entanglement.

In order to support the Adjoint keyword, we need a few things to be true about our quantum programs:

  • Loops can’t exit early, otherwise we couldn’t reverse the direction of a loop.
  • Classical calculations used in a reversible operation need to be deterministic.
  • Classical computations used in a reversible operation can’t have side effects.

To ensure these are all true, for loops work a bit differently in Q#, and there’s a difference between functions (which are always deterministic), and operations (which may have side effects, including sending instructions to a quantum device). These choices made with the design of Q# help make it a perfect fit for what we need a quantum programming language to do.

If you’re interested in learning more about why we need Q#, check out Alan Geller’s post on the Q# dev blog.

Q# Includes Classical Logic

All the above being said, many quantum programs also include a lot of traditional, classical computation that has to work in close tandem with a quantum device. From finding the right rotation angles to describe a quantum simulation task, through to using measurement data from a quantum device to decide the next measurement that you should do, quantum programming is rife with classical computational tasks.

This means that Q# has to not only be great at sending instructions to a quantum computer, but also at the kind of classical computations that need to run alongside a quantum device. As a result, Q# includes a lot of features like user-defined types and functional programming libraries to help you write classical logic in your quantum programs.

Q# is Not a Circuit Language

It’s pretty common when talking about quantum programming to focus on a particular kind of quantum program called a circuit. By analogy to a classical logic circuit, which describes how a bunch of different classical logic gates are connected to each other, a quantum circuit expresses a quantum program as a sequence of quantum gates.

This view has been really useful in quantum computing research for many years, but it has some problems that make it hard to use for developing quantum programs. The most critical problem with thinking in terms of quantum circuits is that it’s really difficult to incorporate classical logic into a circuit diagram. Classical logic circuits and quantum circuits are at best rough analogies to each other, and don’t really mix together. By contrast, classical logic is really easy to write out.

For example, in quantum teleportation (a fancy and whimsical name for a neat way to move quantum data around), we need to apply quantum instructions based on the result of some measurements. This is really easy to write in Q#:

if (MResetZ(msg) == One)      { Z(target); }
if (MResetZ(register) == One) { X(target); }

This works because Q# isn’t a circuit description language, but something much more powerful: a language for expressing quantum algorithms in terms of quantum programs.

You Don’t Need to Know C# to Use Q#

Taking a turn for a moment, you might guess from the fact that “sharp” is right there in the name “Q#” that you need to know C# and .NET development to use Q#. After all, over the 17 years that .NET has been around, “sharp” has become a pretty traditional indicator that something is a part of the .NET ecosystem: F#, SharpDevelop, Resharper, Gtk#, even A#, J#, P#, and X#!

In the case of Q#, though, what that “sharp” tells you is that Q# is built from and plays well with the .NET ecosystem. Just as Q# has learned from the history of classical programming languages, Q# reuses a lot of .NET infrastructure like the NuGet package manager to make it easy easy as possible to write powerful quantum applications. That doesn’t mean, however, you have to use C# or other .NET languages to write Q#.

Indeed, Q# provides interoperability with Python, making it easy to include Q# programs as a part of your data science or research workflow. Q# can even be used entirely on its own from within Jupyter Notebook, thanks to the IQ# kernel for Jupyter.

Even if you want to use Q# with the cross-platform open-source .NET Core SDK, that doesn’t mean you need to be a C# expert. It’s easy to use Q# from F#, Visual Basic .NET, and even PowerShell as well. If you’re new to .NET entirely, the project templates, Visual Studio Code and Visual Studio 2019 extensions, and the Quantum Development Kit samples all make it really easy to use Q# with .NET.

When it comes down to it, Q# is meant to write quantum programs that work well with existing classical platforms. Whether you’re a seasoned C# developer, or a die-hard Pythonista, whether you’re new to programming, or have been at this for a while, I encourage you to give Q# a try.

You Don’t Need to Know Quantum Computing to Get Started with Q#

OK, so you don’t have to be a .NET developer to start writing quantum programs, but surely you have to at least be pretty good at this quantum stuff, right? Not really, as it turns out!

One of the most amazing things that has happened to quantum computing in the past few years is that it has gotten much easier to jump in, and to learn by doing. Five or ten years ago, your best bet for getting involved with quantum computing probably would have started by reading a textbook and writing down a bunch of matrices, and probably even taking some graduate-level classes. That’s still a great way to learn, but there’s a lot of other really good paths to learning quantum computing as well thanks to how much easier it has gotten to write and run quantum programs on your laptop or on the web. Using tools like Q# and the Quantum Development Kit, you can try out your understanding by writing a quantum program, then you can run that program to see if it matched with your understanding.

The ability to quickly get feedback like this has really broadened the set of skills that can help you understand quantum computing. The quantum computing community is bigger now than it ever has been, not just in terms of the number of people, but also in terms of the kinds of backgrounds that people bring with them to the community, the diversity of people in the community, and the ways of thinking about quantum computing.

Given that, if you’re looking to use Q# to learn quantum computing, where should you start? I’m definitely partial to my own book, of course (new chapters coming soon!), but there’s a lot more out there as well. Check out for a great list!

However you decide to learn about quantum computing, though, welcome to the community! 💕 I’m really excited for what you bring to quantum computing.

This is Not a Qubit

The Map is Not The Territory

There’s a classic observation in philosophy that “the map is not the territory.” Though it sounds obvious enough to take entirely for granted, this observation reminds us that there is a difference between the world around us and how we choose to represent that world on a map. Depending on what we want to use the map for, we abstract away many different properties of the real world, such as reducing the amount of detail that we include (we clearly can’t include every object in the real world in our maps). We may even add things to our map that don’t actually exist in the world, but that we find useful at a social level, such as national borders. In all cases, we make these choices so that our model of the world (a map) lets us predict what will happen when walk around the world. We can use those predictions to trade off different possible routes, guess at what might be an interesting place to visit, and so forth.

The lesson learned from separating maps from the world becomes far less obvious, however, when we are working with realities and abstractions that are less familiar to us. It’s quite easy, for instance, for both newcomers and experienced quantum physicists to accidentally conflate a register of qubits with the model we use to predict what that register will do. In particular, if we want to simulate how a quantum program transforms data stored in a register of qubits, we can write down a state vector for that register, then use a simulator to propagate that state vector through the unitary matrices for each instruction in our program.

As an example, we can use tools like Q# and the Quantum Development Kit to understand how a quantum program can cause two qubits in a quantum register to become entangled. Using IQ# with Jupyter Notebook, we might something like the following (run online):

In [1]: open Microsoft.Quantum.Diagnostics;
...     open Microsoft.Quantum.Measurement;
...     operation DemonstrateEntanglement() : (Result, Result) {
...         using ((left, right) = (Qubit(), Qubit())) {
...             H(left);
...             CNOT(left, right);
...             DumpMachine();
...             return (MResetZ(left), MResetZ(right));
...         }
...     }
Out[1]: DemonstrateEntanglement

Here, we’ve defined a new operation that asks for two qubits, then runs the H and CNOT instructions on those qubits. The call to DumpMachine asks the simulator to tell us what information it uses internally to predict what those instructions do, so that when we do the measurements at the end of the program, the simulator knows what it should return. Looking at the output of this dump, we see that the simulator represents left and right by the state $\left(\ket{00} + \ket{11}\right) / \sqrt{2}$:

In [2]: %simulate DemonstrateEntanglement
# wave function for qubits with ids (least to most significant): 0;1
∣0❭:	 0.707107 +  0.000000 i	 == 	***********
    [ 0.500000 ]     --- [  0.00000 rad ]
∣1❭:	 0.000000 +  0.000000 i	 == 	           
    [ 0.000000 ]                   
∣2❭:	 0.000000 +  0.000000 i	 == 	           
    [ 0.000000 ]                   
∣3❭:	 0.707107 +  0.000000 i	 == 	***********
    [ 0.500000 ]     --- [  0.00000 rad ]
Out[2]: (One, One)

It might be then tempting to conclude that left and right are the state $\left(\ket{00} + \ket{11}\right) / \sqrt{2}$, but this runs counter to what we learned from the example of separating maps of the world from the world itself. To resolve this, it helps to think a bit more about what a quantum state is in the context of a quantum program. For starters, if I give you a copy of the state of a quantum register at any point in a quantum program, you can predict what the rest of that quantum program will do. Implicit in the word “copy,” however, is that the state of a quantum register is a classical description of that register. After all, you can’t copy a register of qubits, so the fact that we can copy the state is a dead giveaway that state vectors are a kind of classical model. That classical model is a pretty useful one, to be fair; it not only lets you simulate what a register of qubits will do, but also lets you prepare new qubits in the same way, using techniques like the Shende–Bullock–Markov algorithm (offered in Q# as the Microsoft.Quantum.Preparation.PrepareArbitraryState operation).

Put differently, while the No-Cloning Theorem tells us that we can’t copy the data encoded by a quantum register into a second register, we can definitely copy the set of steps we used to do that encoding, then use that recipe to prepare a second register. Perhaps instead of saying the map is not the territory, then, we should say that the cake is not the recipe! While I can use a recipe to prepare a new cake, and to understand what should happen if I follow a particular set of steps, it’s difficult to eat an abstract concept like a recipe and definitely not very tasty. It’s also pretty difficult to turn one cake into two, but not that hard to bake a second cake following the same recipe.

The Cake is Not a Lie

Thinking of a quantum state as a kind of recipe I can use to prepare qubits, then, what good is a quantum program? To answer that, let’s look at one more example in Q#:

In [3]: open Microsoft.Quantum.Diagnostics;
...     open Microsoft.Quantum.Measurement;
...     open Microsoft.Quantum.Arrays;
...     operation DemonstrateMultiqubitEntanglement() : Result[] {
...         using (register = Qubit[10]) {
...             H(Head(register));
...             ApplyToEach(CNOT(Head(register), _), Rest(register));
...             DumpMachine();
...             return ForEach(MResetZ, register);
...         }
...     }

If we were to run this one, the simulator would dump out a state with $2^{10} = 1,024$ amplitudes, but it’s much easier to read and understand what that program does by looking at the Q# source itself. From that perspective, a quantum program can help us understand a computational task by compressing it down from a description purely in terms of state vectors, focusing back on what we actually want to achieve using a quantum device. The simplest and by far the most effective way to both achieve this compression is to simply write down the instructions we need to send to a quantum device to prepare our qubits in a particular state. Thus, instead of writing $\ket{+}$, for instance, we write down the program H(q). Instead of writing down $\ket{++\cdots+}$, we write down ApplyToEach(H, qs). Instead of writing down a state vector for each individual step in a phase estimation experiment, we write a program that calls EstimateEnergy. This has the massive added advantage that we can optimize our quantum programs; that is, we can write down a sequence of instructions that utilizes what we know about the task we’re trying to achieve to use as few quantum instructions as possible.

Indeed, the cake–recipe distinction is especially important as we consider actual quantum devices. In order to solve interesting computational problems using quantum computers, we want to be able to measure actual qubits, and get useful answers back. At that scale, writing down and thinking only in terms of state vectors simply isn’t possible. We need instead to focus on what we actually want to do with our qubits. Once we do that, we’re in a much better spot to have our cake and eat it, too.

If you liked this post, you’ll love Learn Quantum Computing with Python and Q#, now in early access preview from Manning Publications. Check it out!