Q Sharp

Q#
ParadigmQuantum, functional, imperative
Designed byMicrosoft Research (quantum architectures and computation group; QuArC)
DeveloperMicrosoft
First appearedDecember 11, 2017 (2017-12-11)
Typing disciplineStatic, strong
PlatformCommon Language Infrastructure
LicenseMIT License[1]
Filename extensions.qs
Websitedocs.microsoft.com/en-us/quantum
Influenced by
C#, F#, Python

Q# (pronounced as Q sharp) is a domain-specific programming language used for expressing quantum algorithms.[2] It was initially released to the public by Microsoft as part of the Quantum Development Kit.[3]

History[edit]

Historically, Microsoft Research had two teams interested in quantum computing: the QuArC team based in Redmond[which?],[4] directed by Krysta Svore, that explored the construction of quantum circuitry, and Station Q initially located in Santa Barbara and directed by Michael Freedman, that explored topological quantum computing.[5][6]

During a Microsoft Ignite Keynote on September 26, 2017, Microsoft announced that they were going to release a new programming language geared specifically towards quantum computers.[7] On December 11, 2017, Microsoft released Q# as a part of the Quantum Development Kit.[3]

At Build 2019, Microsoft announced that it would be open-sourcing the Quantum Development Kit, including its Q# compilers and simulators.[8]

Bettina Heim currently leads the Q# language development effort.[9][10]

Usage[edit]

Q# is available as a separately downloaded extension for Visual Studio,[11] but it can also be run as an independent tool from the command line or Visual Studio Code. The Quantum Development Kit ships with a quantum simulator which is capable of running Q#.[12]

In order to invoke the quantum simulator, another .NET programming language, usually C#, is used, which provides the (classical) input data for the simulator and reads the (classical) output data from the simulator.[13]

Features[edit]

A primary feature of Q# is the ability to create and use qubits for algorithms. As a consequence, some of the most prominent features of Q# are the ability to entangle and introduce superpositioning to qubits via Controlled NOT gates and Hadamard gates, respectively, as well as Toffoli Gates, Pauli X, Y, Z Gate, and many more which are used for a variety of operations; see the list at the article on quantum logic gates.[14]

The hardware stack that will eventually come together with Q# is expected to implement Qubits as topological qubits. The quantum simulator that is shipped with the Quantum Development Kit today is capable of processing up to 32 qubits on a user machine and up to 40 qubits on Azure.[15]

Documentation and resources[edit]

Currently, the resources available for Q# are scarce, but the official documentation is published: Microsoft Developer Network: Q#. Microsoft Quantum Github repository is also a large collection of sample programs implementing a variety of Quantum algorithms and their tests.

Microsoft has also hosted a Quantum Coding contest on Codeforces, called Microsoft Q# Coding Contest - Codeforces, and also provided related material to help answer the questions in the blog posts, plus the detailed solutions in the tutorials.

Microsoft hosts a set of learning exercises to help learn Q# on GitHub: microsoft/QuantumKatas with links to resources, and answers to the problems.

Syntax[edit]

Q# is syntactically related to both C# and F# yet also has some significant differences.

Similarities with C#[edit]

  • Uses namespace for code isolation
  • All statements end with a ;
  • Curly braces are used for statements of scope
  • Single line comments are done using //
  • Variable data types such as Int Double String and Bool are similar, although capitalised (and Int is 64-bit)[16]
  • Qubits are allocated and disposed inside a using block.
  • Lambda functions are defined using the => operator.
  • Results are returned using the return keyword.

Similarities with F#[edit]

  • Variables are declared using either let or mutable[2]
  • First-order functions
  • Modules, which are imported using the open keyword
  • The datatype is declared after the variable name
  • The range operator ..
  • for … in loops
  • Every operation/function has a return value, rather than void. Instead of void, an empty Tuple () is returned.
  • Definition of record datatypes (using the newtype keyword, instead of type).

Differences[edit]

  • Functions are declared using the function keyword
  • Operations on the quantum computer are declared using the operation keyword
  • Lack of multiline comments
  • Asserts instead of throwing exceptions
  • Documentation is written in Markdown instead of XML-based documentation tags

Example[edit]

The following source code is a multiplexer from the official Microsoft Q# library repository.

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License.  namespace Microsoft.Quantum.Canon {     open Microsoft.Quantum.Intrinsic;     open Microsoft.Quantum.Arithmetic;     open Microsoft.Quantum.Arrays;     open Microsoft.Quantum.Diagnostics;     open Microsoft.Quantum.Math;      /// # Summary     /// Applies a multiply-controlled unitary operation $U$ that applies a     /// unitary $V_j$ when controlled by n-qubit number state $\ket{j}$.     ///     /// $U = \sum^{N-1}_{j=0}\ket{j}\bra{j}\otimes V_j$.     ///     /// # Input     /// ## unitaryGenerator     /// A tuple where the first element `Int` is the number of unitaries $N$,     /// and the second element `(Int -> ('T => () is Adj + Ctl))`     /// is a function that takes an integer $j$ in $[0,N-1]$ and outputs the unitary     /// operation $V_j$.     ///     /// ## index     /// $n$-qubit control register that encodes number states $\ket{j}$ in     /// little-endian format.     ///     /// ## target     /// Generic qubit register that $V_j$ acts on.     ///     /// # Remarks     /// `coefficients` will be padded with identity elements if     /// fewer than $2^n$ are specified. This implementation uses     /// $n-1$ auxiliary qubits.     ///     /// # References     /// - [ *Andrew M. Childs, Dmitri Maslov, Yunseong Nam, Neil J. Ross, Yuan Su*,     ///      arXiv:1711.10980](https://arxiv.org/abs/1711.10980)     operation MultiplexOperationsFromGenerator<'T>(unitaryGenerator : (Int, (Int -> ('T => Unit is Adj + Ctl))), index: LittleEndian, target: 'T) : Unit is Ctl + Adj {         let (nUnitaries, unitaryFunction) = unitaryGenerator;         let unitaryGeneratorWithOffset = (nUnitaries, 0, unitaryFunction);         if Length(index!) == 0 {             fail "MultiplexOperations failed. Number of index qubits must be greater than 0.";         }         if nUnitaries > 0 {             let auxiliary = [];             Adjoint MultiplexOperationsFromGeneratorImpl(unitaryGeneratorWithOffset, auxiliary, index, target);         }     }      /// # Summary     /// Implementation step of `MultiplexOperationsFromGenerator`.     /// # See Also     /// - Microsoft.Quantum.Canon.MultiplexOperationsFromGenerator     internal operation MultiplexOperationsFromGeneratorImpl<'T>(unitaryGenerator : (Int, Int, (Int -> ('T => Unit is Adj + Ctl))), auxiliary: Qubit[], index: LittleEndian, target: 'T)     : Unit {         body (...) {             let nIndex = Length(index!);             let nStates = 2^nIndex;              let (nUnitaries, unitaryOffset, unitaryFunction) = unitaryGenerator;              let nUnitariesLeft = MinI(nUnitaries, nStates / 2);             let nUnitariesRight = MinI(nUnitaries, nStates);              let leftUnitaries = (nUnitariesLeft, unitaryOffset, unitaryFunction);             let rightUnitaries = (nUnitariesRight - nUnitariesLeft, unitaryOffset + nUnitariesLeft, unitaryFunction);              let newControls = LittleEndian(Most(index!));              if nUnitaries > 0 {                 if Length(auxiliary) == 1 and nIndex == 0 {                     // Termination case                      (Controlled Adjoint (unitaryFunction(unitaryOffset)))(auxiliary, target);                 } elif Length(auxiliary) == 0 and nIndex >= 1 {                     // Start case                     let newauxiliary = Tail(index!);                     if nUnitariesRight > 0 {                         MultiplexOperationsFromGeneratorImpl(rightUnitaries, [newauxiliary], newControls, target);                     }                     within {                         X(newauxiliary);                     } apply {                         MultiplexOperationsFromGeneratorImpl(leftUnitaries, [newauxiliary], newControls, target);                     }                 } else {                     // Recursion that reduces nIndex by 1 and sets Length(auxiliary) to 1.                     let controls = [Tail(index!)] + auxiliary;                     use newauxiliary = Qubit();                     use andauxiliary = Qubit[MaxI(0, Length(controls) - 2)];                     within {                         ApplyAndChain(andauxiliary, controls, newauxiliary);                     } apply {                         if nUnitariesRight > 0 {                             MultiplexOperationsFromGeneratorImpl(rightUnitaries, [newauxiliary], newControls, target);                         }                         within {                             (Controlled X)(auxiliary, newauxiliary);                         } apply {                             MultiplexOperationsFromGeneratorImpl(leftUnitaries, [newauxiliary], newControls, target);                         }                     }                 }             }         }         adjoint auto;         controlled (controlRegister, ...) {             MultiplexOperationsFromGeneratorImpl(unitaryGenerator, auxiliary + controlRegister, index, target);         }         adjoint controlled auto;     }      /// # Summary     /// Applies multiply-controlled unitary operation $U$ that applies a     /// unitary $V_j$ when controlled by n-qubit number state $\ket{j}$.     ///     /// $U = \sum^{N-1}_{j=0}\ket{j}\bra{j}\otimes V_j$.     ///     /// # Input     /// ## unitaryGenerator     /// A tuple where the first element `Int` is the number of unitaries $N$,     /// and the second element `(Int -> ('T => () is Adj + Ctl))`     /// is a function that takes an integer $j$ in $[0,N-1]$ and outputs the unitary     /// operation $V_j$.     ///     /// ## index     /// $n$-qubit control register that encodes number states $\ket{j}$ in     /// little-endian format.     ///     /// ## target     /// Generic qubit register that $V_j$ acts on.     ///     /// # Remarks     /// `coefficients` will be padded with identity elements if     /// fewer than $2^n$ are specified. This version is implemented     /// directly by looping through n-controlled unitary operators.     operation MultiplexOperationsBruteForceFromGenerator<'T>(unitaryGenerator : (Int, (Int -> ('T => Unit is Adj + Ctl))), index: LittleEndian, target: 'T)     : Unit is Adj + Ctl {         let nIndex = Length(index!);         let nStates = 2^nIndex;         let (nUnitaries, unitaryFunction) = unitaryGenerator;         for idxOp in 0..MinI(nStates,nUnitaries) - 1 {             (ControlledOnInt(idxOp, unitaryFunction(idxOp)))(index!, target);         }     }      /// # Summary     /// Returns a multiply-controlled unitary operation $U$ that applies a     /// unitary $V_j$ when controlled by n-qubit number state $\ket{j}$.     ///     /// $U = \sum^{2^n-1}_{j=0}\ket{j}\bra{j}\otimes V_j$.     ///     /// # Input     /// ## unitaryGenerator     /// A tuple where the first element `Int` is the number of unitaries $N$,     /// and the second element `(Int -> ('T => () is Adj + Ctl))`     /// is a function that takes an integer $j$ in $[0,N-1]$ and outputs the unitary     /// operation $V_j$.     ///     /// # Output     /// A multiply-controlled unitary operation $U$ that applies unitaries     /// described by `unitaryGenerator`.     ///     /// # See Also     /// - Microsoft.Quantum.Canon.MultiplexOperationsFromGenerator     function MultiplexerFromGenerator(unitaryGenerator : (Int, (Int -> (Qubit[] => Unit is Adj + Ctl)))) : ((LittleEndian, Qubit[]) => Unit is Adj + Ctl) {         return MultiplexOperationsFromGenerator(unitaryGenerator, _, _);     }      /// # Summary     /// Returns a multiply-controlled unitary operation $U$ that applies a     /// unitary $V_j$ when controlled by n-qubit number state $\ket{j}$.     ///     /// $U = \sum^{2^n-1}_{j=0}\ket{j}\bra{j}\otimes V_j$.     ///     /// # Input     /// ## unitaryGenerator     /// A tuple where the first element `Int` is the number of unitaries $N$,     /// and the second element `(Int -> ('T => () is Adj + Ctl))`     /// is a function that takes an integer $j$ in $[0,N-1]$ and outputs the unitary     /// operation $V_j$.     ///     /// # Output     /// A multiply-controlled unitary operation $U$ that applies unitaries     /// described by `unitaryGenerator`.     ///     /// # See Also     /// - Microsoft.Quantum.Canon.MultiplexOperationsBruteForceFromGenerator     function MultiplexerBruteForceFromGenerator(unitaryGenerator : (Int, (Int -> (Qubit[] => Unit is Adj + Ctl)))) : ((LittleEndian, Qubit[]) => Unit is Adj + Ctl) {         return MultiplexOperationsBruteForceFromGenerator(unitaryGenerator, _, _);     }      /// # Summary     /// Computes a chain of AND gates     ///     /// # Description     /// The auxiliary qubits to compute temporary results must be specified explicitly.     /// The length of that register is `Length(ctrlRegister) - 2`, if there are at least     /// two controls, otherwise the length is 0.     internal operation ApplyAndChain(auxRegister : Qubit[], ctrlRegister : Qubit[], target : Qubit)     : Unit is Adj {         if Length(ctrlRegister) == 0 {             X(target);         } elif Length(ctrlRegister) == 1 {             CNOT(Head(ctrlRegister), target);         } else {             EqualityFactI(Length(auxRegister), Length(ctrlRegister));             let controls1 = ctrlRegister[0..0] + auxRegister;             let controls2 = Rest(ctrlRegister);             let targets = auxRegister + [target];             ApplyToEachA(ApplyAnd, Zipped3(controls1, controls2, targets));         }     } } 


References[edit]

  1. ^ "Introduction to Q#" (PDF). University of Washington.
  2. ^ a b QuantumWriter. "The Q# Programming Language". docs.microsoft.com. Retrieved 2017-12-11.
  3. ^ a b "Announcing the Microsoft Quantum Development Kit". Retrieved 2017-12-11.
  4. ^ "Solving the quantum many-body problem with artificial neural networks". Microsoft Azure Quantum. 15 February 2017.
  5. ^ Scott Aaronson's blog, 2013, 'Microsoft: From QDOS to QMA in less than 35 years', https://scottaaronson.blog/?p=1471
  6. ^ "What are the Q# programming language & QDK? - Azure Quantum". learn.microsoft.com.
  7. ^ "Microsoft announces quantum computing programming language". Retrieved 2017-12-14.
  8. ^ Microsoft is open-sourcing its Quantum Development Kit
  9. ^ "The Women of QuArC". 30 March 2019.
  10. ^ "Intro to Q# - Intro to Quantum Software Development". stem.mitre.org.
  11. ^ QuantumWriter. "Setting up the Q# development environment". docs.microsoft.com. Retrieved 2017-12-14.
  12. ^ Akdogan, Erman (23 October 2022). "Quantum computing is coming for finance & crypto". Medium.
  13. ^ "This Week in Programming: Get Quantum with Q Sharp". The New Stack. 16 December 2017.
  14. ^ "Qubit Gate - an overview". www.sciencedirect.com.
  15. ^ "Microsoft previews quantum computing development kit". CIO.
  16. ^ "Types in Q# - Microsoft Quantum". docs.microsoft.com.

External links[edit]