LoginSignup
5
4

More than 5 years have passed since last update.

Microsoft Quantum Development Techniquesを翻訳する(〜2.1)

Last updated at Posted at 2018-01-04

こんにちは。|つじしん〉と申します。
MicrosoftのQuantum Development Techniquesの序盤を翻訳しました。
これはMicrosoft Quantum Development Kit Previewに含まれている節です。Google翻訳をかけまくって違和感のあるところを直したり語調を揃えたりしています。
量子開発技術
1. Q#とファイル構造
1.1 Q#とはなにか? 
1.2 Q#ソースファイルの構造
2. 命令と関数
2.1 新しい演算子の定義
今回はここまで!
2.2 Defining New Functions
2.3 Control Flow
2.4 Operations and Functions as First-Class Values
2.5 Partially Applying Operations and Functions
3. Local variables
4. Q# type model
5. Working with qubits
6. Putting it all together
7. Going further
8. Testing and debugging

$$\newcommand{\bra}[1]{\left\langle #1 \right|}$$$$\newcommand{\ket}[1]{\left|#1 \right\rangle}$$$$\newcommand{\bracket}[2]{\left\langle #1 \middle|#2 \right\rangle}$$

量子開発技術

Quantum Development Techniques
This section details the core concepts used to create quantum programs in Q#, and to interact with those programs from classical .NET applications. This section assumes some knowledge of quantum computing concepts like those described in Quantum computing concepts.

このセクションでは、Q#で量子プログラムを作成し、古典的な.NETアプリケーションからそれらのプログラムと対話するために使用される概念の核心について詳しく説明します。 このセクションでは、量子計算機のコンセプト(英語原文)(@YuichiroMinato さんによって日本語に翻訳されたもの)に記述されているような量子計算の概念に関する知識を前提としています。

Q#とファイル構造

Q#とはなにか?

Q# and file structures --What is Q#?
Q# is a scalable, multi-paradigm, domain-specific programming language for quantum computing. Q# is a quantum programming language in that it be used to describe how instructions are executed on quantum machines. The machines that can be targeted include many different levels of abstraction, ranging from various simulators to actual quantum hardware. Q# is multi-paradigm in that it supports functional and imperative programming styles. Q# is scalable in that it allows to write programs to target machines of various sizes, ranging from small machines with only a few hundred qubits to large machines with millions of qubits. Even though large physical machines might only come into fruition on the future, Q# allows a programmer already now to program complex quantum algorithms and to perform various tasks such as debugging, profiling, resource estimation, and certain special-purpose simulations in a scalable way.

Q#は、量子計算のためのスケーラブル(有拡張性)でマルチパラダイム(複数模範対応)のドメイン固有プログラミング言語です。 Q#は、量子計算機上で命令がどのように実行されるかを記述するために使用される量子プログラミング言語です。 対象とすることができる計算機には、さまざまなシミュレータから実際の量子ハードウェアまで、さまざまな抽象的な階層が含まれます。 Q#は、関数型および命令型プログラミングのスタイルをサポートするという点で、マルチパラダイム(複数模範対応)です。 Q#は、数百キュービットの小型マシンから数百万キュービットの大型マシンまで、様々なサイズのターゲットマシンにプログラムを書き込むことができるという点でスケーラブル(有拡張性)です。 大規模な物理マシンは将来的に実現する可能性があるものの現時点では実現されていませんが、Q#は現時点で既にプログラマが複雑な量子アルゴリズムをプログラミング、デバッグ、プロファイリング、リソース推定、特殊な目的のシミュレーションなどのさまざまなタスクをスケーラブルに実行することを可能にします。

From a technical perspective, a quantum program is a particular set of classical functions which, when called, generate quantum circuits as their side effects. An important consequence of that view is that a program written in Q# does not directly model qubits themselves, but rather describes how a classical control computer interacts with those qubits. By design, Q# thus does not define quantum states or other properties of quantum mechanics directly, but rather does so indirectly through the action of the various subroutines defined in the language. For instance, consider the state $\ket{+} =\frac{\ket{0}+\ket{1}}{\sqrt{2}}$ discussed in the Quantum Computing Concepts guide. To prepare this state in Q#, we use that qubits are initialized in the $\ket{0}$ state, and that $\ket{+}=H\ket{0}$, where $H$ is the Hadamard transform:

技術的な側面から見ると、量子プログラムは、呼び出されたときに副作用として量子回路を生成する特定の一組の古典的関数です。 この見解における重要な点は、Q#で書かれたプログラムが量子ビット自体を直接モデル化するのではなく、古典的な制御コンピュータがそれら量子ビットとどのように相互作用するのかを記述することです。したがって、Q#は、量子状態または量子力学の特性を直接的に定義するのでなく、言語で定義された様々なサブルーチンの作用を通じて間接的に定義します。たとえば、量子計算機のコンセプト(英語原文)(@YuichiroMinato さんによって翻訳されたもの)で説明されている状態 $\ket{+} =\frac{\ket{0}+\ket{1}}{\sqrt{2}}$ を考えてみましょう。
この状態をQ#で準備してみましょう。まず最初量子ビットは$\ket{0}$状態で初期化されています。また、$\ket{+}=H \ket{0}$です。($ H $はアダマール変換)

using (register = Qubit[1]) {
    let qubit = register[0];
    // At this point, qubit is in the state |0〉.
    H(qubit);
    // We've now applied H, such that our qubit is in H|0〉 = |+〉, as we wanted.
}

Importantly, in writing the above program, we did not explicitly refer to the state within Q#, but rather described how the state was transformed by our program. Thus, similar to how a graphics shader program accumulates a description of transformations to each vertex, a quantum program in Q# accumulates transformations to quantum states. This allows us to be entirely agnostic about what a quantum state even is on each target machine, which might have different interpretations depending on the machine.

重要なのは、上記のプログラムを書く際に、Q#内の状態を明示的に参照するのではなく、プログラムによって状態がどのように変化したかを記述していることだ。したがって、グラフィックシェーダプログラムが各頂点への変換の記述を蓄積するのと同様に、Q#の量子プログラムは量子状態の変換を蓄積する。 これにより、各ターゲットマシン上で量子状態がどのようなものであるかについて完全に無関心であることが可能になります。(この各ターゲットマシン上での量子状態は、マシンによって解釈が異なる場合があります。)

From the perspective of a Q# program, a qubit is an entirely opaque reference to the internal structure of a target machine. A Q# program has no ability to introspect into the state of a qubit, its representation on a target machine, or even whether it is the same qubit as any other qubit available to the program. Rather, a program can call operations such as Measure to learn information from a qubit, and call operations such as X and H to act on the state of a qubit. These operations have no intrinsic definition within the language, and are made concrete only by the target machine used to run a particular Q# program. A Q# program recombines these operations as defined by a target machine to create new, higher-level operations to express quantum computation. In this way, Q# makes it easy to express the logic underlying quantum and hybrid quantum-classical algorithms, while also being general with respect to the structure of a target machine or simulator.

Q#プログラムの観点からは、量子ビットはターゲットマシンの内部構造を完全に不透明なものとしています。 Q#プログラムは、量子ビットの状態、ターゲットマシン上でのその表現、またそれがプログラムに利用可能な他の量子ビットと同じ量子ビットであるかどうか、などを調べる能力を持ちません。 むしろ、プログラムは、量子ビットから情報を得るために$Measure$(測定)などの操作を呼び出したり、量子ビットの状態に作用するように$X$や$H$などの操作を呼び出します。 これらの操作は、言語内での本質的な定義を持たず、特定のQ#プログラムを実行するために使用されるターゲットマシンによってのみ具体化されます。 Q#プログラムは、ターゲットコンピュータによって定義されたこれらの操作を再結合して、量子計算を表現するための新しい高水準操作を作成します。 このようにして、Q#は、量子機械およびハイブリッド量子古典的アルゴリズムの基礎となる論理を表現するのを容易にする一方で、ターゲットマシンまたはシミュレータの構造に関しても汎用的です。

Concretely, a Q# program is comprised of one or more operations, one or more functions, and user defined types. Operations are used to describe the transformations of the state of a quantum machine and are the most basic building block of Q# programs. Each operation defined in Q# may then call any number of other operations, including the built-in primitive operations defined by the language and implemented by each target machine. When compiled, each operation is represented as a .NET class type that can be provided to target machines.
In contrast to operations, functions are used to describe purely classical behavior and do not have any effects besides computing classical output values. Q# is a strongly typed language and comes with a set of built-in primitive types as well as support for user defined types.
Throughout the rest of this guide, we will see how to use different language concepts and constructs to help us define complex quantum programs through the basic building blocks of operations, functions, and types.

具体的には、Q#プログラムは、1つ以上の演算、1つ以上の関数、およびユーザ定義型から構成されます。演算は、量子コンピュータの状態の変換を記述するために使用され、Q#プログラムの最も基本的なビルディングブロックです。次に、Q#で定義された各演算は、言語によって定義され、各ターゲットマシンによって実装された組み込みプリミティブ演算を含む任意の数の他の演算を呼び出すことができます。コンパイルされると、各操作は、ターゲットマシンに提供できる.NETクラスタイプとして表記されます。
操作とは対照的に、関数は純粋に古典的な振る舞いを記述するために使用され、古典的な出力値を計算する以外には何の効果もありません。 Q#は強く型付けされた言語であり、組み込みプリミティブ型のセットとユーザー定義型のサポートが付属しています。
このガイドの残りの部分では、さまざまな言語概念と構造を使用して、操作、関数、およびタイプの基本的なビルディングブロックを通じて複雑な量子プログラムを定義する方法を見ていきます。

Q#ソースファイルの構造

Structure of Q# Source Files
Minimally, a Q# source file consists of a namespace declaration, which specifies a .NET namespace which will contain the definitions in the source file. Definitions from other Q# source files and libraries can be included using the open statement. For instance, most of the operations defining fundamental gates are defined in the Microsoft.Quantum.Primitive namespace. To make this available to our code, we simply open that namespace at the top of each file:

最も小さなQ#ソースファイルは、ソースファイル内の定義を含む.NET名前空間を指定する名前空間宣言で構成されています。 open文を使用して、他のQ#ソースファイルやライブラリの定義を組み込むことができます。 たとえば、基本的なゲートを定義する操作のほとんどは、Microsoft.Quantum.Primitive名前空間で定義されています。 これをコードで利用できるようにするために、各ファイルの先頭にその名前空間をopenするだけです。

namespace Example {
    open Microsoft.Quantum.Primitive;

    // ...
}

名前空間内で、各Q#ソースファイルは、操作、関数、およびユーザー定義型の任意の組み合わせを定義できます。 このセクションの残りの部分では、順番にそれぞれを説明し、有用な量子プログラムを作成するためにそれらを実際にどのように使用できるかの例を示します。

命令と関数

Operations and Functions
Q# programs consist of one or more operations which describe side effect which quantum operations can have on quantum data and one or more functions which allow to modify classical data. In contrast to operations, functions are used to describe purely classical behavior and do not have any effects besides computing classical output values.
Each operation defined in Q# may then call any number of other operations, including the built-in primitive operations defined by the language. The particular way in which these primitive operations are defined depends on the target machine. When compiled, each operation is represented as a .NET class type that can be provided to target machines.

Q#プログラムは、量子演算が量子データに対して有することができる副作用と、古典的なデータを修正することを可能にする1つまたは複数の関数を記述する1つまたは複数の演算からなります。 操作とは対照的に、関数は純粋に古典的な振る舞いを記述するために使用され、古典的な出力値を計算する以外には何の効果もありません。

次に、Q#で定義された各演算は、言語によって定義された組み込みプリミティブ演算を含む任意の数の他の演算を呼び出すことができます。 これらのプリミティブ操作が定義される特定の方法は、ターゲットマシンによって異なります。 コンパイルされると、各操作は、ターゲットマシンに提供できる.NETクラスタイプとして表されます。

新しい演算子の定義

Defining New Operations
As described above, the most basic building block of a quantum program written in Q# is an operation, which can either be called from classical .NET applications, e.g., using a simulator, or by other operations within Q#. Each operation takes an input, produces an output, and minimally consists of a body listing one or more instructions. For instance, the following operation takes a single qubit as its input, then calls the built-in X operation on that input:

上述したように、Q#で書かれた量子プログラムの最も基本的なビルディングブロックは、例えば、シミュレータを使用する古典的な.NETアプリケーションから、またはQ#内の他の動作によって呼び出すことができる操作です。 各操作は入力を受け取り、出力を生成し、最小限には1つ以上の指示を列挙する本体で構成されます。 たとえば、次の操作では、単一のキュビットを入力として受け取り、その入力に対して組み込みの$X$操作を呼び出します。

operation BitFlip(target : Qubit) : () {
    body {
        X(target);
    }
}

The keyword operation begins the operation definition, and is followed by the name; here, BitFlip. Next, the type of the input is defined as Qubit, along with a name target for referring to the input within the new operation. Similarly, the () defines that the operation's output is empty. This is used similarly to void in C# and other imperative languages, and is equivalent to unit in F# and other functional languages.

キーワードoperationは演算子(操作)定義を開始し、その後に名前が続きます。 すなわち、 BitFlipです。 次に、入力の型は、新しい操作内の入力を参照するための名前 targetとともに、Qubitとして定義されます。同様に、 ()は操作の出力が空であることを定義します。 これはC#や他の命令型言語の voidと同様に使われ、F#や他の関数型言語のunitと同等です。

!note

We will explore this in more detail below, but each operation in Q# takes exactly one input and returns exactly one output. Multiple inputs and outputs are then represented using tuples, which collect multiple values together into a single value. Informally, we say that Q# is a "tuple-in tuple-out" language. Following this concept, () should then be read as the "empty" tuple.

! ノート
これについては以下で詳しく説明しますが、Q#の各操作はちょうど1つの入力を受け取り、ちょうど1つの出力を返します。 複数の入力と出力はタプルを使用して表現され、タプルは複数の値をまとめて1つの値にします。 非公式には、Q#は「タプルイン・タプル・アウト」言語であると言います。 この概念に従うと、()empty(空の)タプルとして読み込まれます。

Within the new operation, the keyword body is used to declare the sequence of statements that make up the new operation. In the example above, the only statement is to call the $X$ operation built-in to the Q# prelude.
Operations can also return more interesting types than (). For instance, the $M$ operation returns an output of type (Result), representing having performed a measurement. We can either pass the output from an operation to another operation, or can use it with the let keyword to define a new variable.
This allows for representing classical computation that interacts with quantum operations at a low level, such as in superdense coding:

新しい操作(operation)の中で、キーワード bodyは、新しい操作を構成するステートメントのシーケンスを宣言するために使用されます。 上の例では、唯一のステートメントはQ#preludeに組み込まれた$ X $操作を呼び出すことです。
演算は ()よりも面白い型を返すこともできます。 例えば、$ M $演算は、測定を実行したことを表す型 (Result) 'の出力を返します。 操作の出力を別の操作に渡したり、新しい変数を定義するためにlet`キーワードと一緒に使用することができます。
これは、超高密度符号化のような低レベルで量子演算と相互作用する古典的計算を表すことを可能にします。

operation Superdense(here : Qubit, there : Qubit) : (Result, Result) {
    body {
        CNOT(there, here);
        H(there);

        let firstBit = M(there);
        let secondBit = M(here);

        return (firstBit, secondBit);
    }
}

If an operation does not return a value other than (), then it can also specify variants as well as a body, specifying how the operation acts when adjointed or controlled. The adjoint variant of an operation specifies how it acts when run in reverse, while the controlled variant specifies how an operation acts when applied conditioned on the state of a quantum register.

操作が ()以外の値を返さない場合は、variant型と本体を指定して、操作が追加または制御されたときの動作の仕方を指定することもできます。 操作の随伴変形は、逆順で実行されるときの動作を指定し、制御されたvariant型は、量子レジスタの状態を条件として適用されたときの操作(operation)の動作を指定します。

!note
Many operations in Q# represent unitary gates. If $U$ is the unitary gate represented by an operation U, then (Adjoint U) represents the unitary gate $U^†$.

Q#の多くの操作はユニタリーゲートを表します。 $ U $が演算Uによって表されるユニタリーゲートである場合、 (Adjoint U)はユニタリーゲート$ U ^†$を表します。

In both cases, the variant specification immediately follows the end of the body definition:

どちらの場合でも、variant指定はbody定義の終わりに直ちに続きます。

operation PrepareEntangledPair(here : Qubit, there : Qubit) : () {
    body {
        H(here);
        CNOT(here, there);
    }

    adjoint auto
    controlled auto
    controlled adjoint auto
}

Very often, variant specifications will consist of the keyword auto, indicating that the compiler should determine how to generate the variant definition. If the compiler cannot generate a definition automatically, or if a more efficient implementation can be given, then a variant may also be manually defined. We will see examples of this below in Higher-Order Control Flow.
To call a variant of an operation, use the Adjoint or Controlled keywords. For example, the superdense coding example above can be written more compactly by using the adjoint of PrepareEntangledState to transform the entangled state back into an unentangled pair of qubits:

非常に多くの場合、variantの仕様はキーワード autoで構成され、コンパイラがvariant定義の生成方法を決定する必要があることを示します。 コンパイラが定義を自動的に生成できない場合や、より効率的な実装を与えることができる場合は、variantを手動で定義することもできます。 下の例は高次制御フローで見ることができます。
操作の変形を呼び出すには、 AdjointまたはControlledキーワードを使用します。 例えば、上記の超高密度コーディングの例は、PrepareEntangledStateのadjointを使用してエンタングル状態を、エンベロップされていない量子ビットのペアに変換することにより、よりコンパクトに書くことができます。

operation Superdense(here : Qubit, there : Qubit) : (Result, Result) {
    body {
        (Adjoint PrepareEntangledPair)(there, here);

        let firstBit = M(there);
        let secondBit = M(here);

        return (firstBit, secondBit);
    }
}

There are a number of important limitations to consider when designing operations for use with variants. Most critically, an operation which uses the output value of any other operation cannot use the auto keyword to specify variants, as it is ambiguous how to reorder the statements in such an operation to obtain the same effect.

variantで使用する操作を設計する際に考慮すべきいくつかの重要な制限があります。 最も重要なのは、他の操作の出力値を使用する操作では、同じ効果を得るためにそのような操作でどのように命令を並べ替えるのかがあいまいであるため、変数を指定するのに autoキーワードを使用できないということです。

2.2 Defining New Functions に続く....(気力と時間があれば)

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4