Q#で量子演算どうやるのって、

# 前書き:
誰かわかりやすいサンプル用意してください。。

# 参考:
- [Microsoft.Quantum.Arithmetic](https://learn.microsoft.com/ja-jp/qsharp/api/qsharp/microsoft.quantum.arithmetic)
- [Microsoft.Quantum.Arrays](https://learn.microsoft.com/ja-jp/qsharp/api/qsharp/microsoft.quantum.arrays)

# 環境:
 以下の環境下のプロジェクトで行っています。
 - ベースイメージ : ```mcr.microsoft.com/quantum/iqsharp-base:0.28.302812```
 - プロジェクトのテンプレートは以下の```Short Name```の```console```を使用しています。
```bash
 Template Name                   Short Name      Language  Tags
------------------------------  --------------  --------  --------------
Class library                   classlib        Q#        Common/Library
Console Application             console         Q#        Common/Console
Quantum Application Honeywell   azq-honeywell   Q#        Common/Console
Quantum Application IonQ        azq-ionq        Q#        Common/Console
Quantum Application Quantinuum  azq-quantinuum  Q#        Common/Console
xUnit Test Project              xunit           Q#        Test/xUnit
```

# Packageの追加:
nugetで既存のQ#プロジェクトにパッケージを追加します。
算術用パッケージを使用する為に```Microsoft.Quantum.Numerics```をプロジェクトに追加します。
```bash
dotnet add <Project Name> package Microsoft.Quantum.Numerics
```

# 量子算術演算サンプルコード:
算術演算を可能にするパッケージ(```Microsoft.Quantum.Arithmetic```)で定義されている。```LittleEndian```型を使用して算術演算を行うことができるみたいです。

その他にも```BigEndian```や```FixedPoint```なども存在しそれ用の演算等がありますので気になる方は、
[ドキュメント](https://learn.microsoft.com/ja-jp/qsharp/api/qsharp/microsoft.quantum.arithmetic)参照すると良いと思います。


## インクリメント：
インクリメントというよりかは、定数値を追加するイメージの方が良い。

#### サンプルコード
```csharp
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Arithmetic; // LittleEndian
  
    @EntryPoint()
    operation IncrementMain(): Unit {
        let bitSize = 3;
        
        use a = Qubit[bitSize];
        // アダマールゲートを先頭の量子ビットに施す
        H(a[0]);

        // アダマールを施した結果をダンプ
        DumpMachine();
        Message("---");

        let aLEHandler = LittleEndian(a);

        IncrementByInteger(1, aLEHandler);

        // インクリメント(+1)を施した結果をダンプ
        DumpMachine();
        // 量子結果を測定し、LitteleEndianで整数化した結果を取得
        let result = MeasureInteger(aLEHandler);
        // 1か2のいずれかを出力
        Message($"result = {result}");

        ResetAll(a);
    }
```

#### 結果
なんで少しPhaseしているかよくわからないが、 （要調査）
|0>と|1>が|1>と|2>にシフトしているのが分かります。

```bash
|0⟩      0.707107 +  0.000000 i  ==     ***********          [ 0.500000 ]     --- [  0.00000 rad ]
|1⟩      0.707107 +  0.000000 i  ==     ***********          [ 0.500000 ]     --- [  0.00000 rad ]
|2⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|3⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|4⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|5⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|6⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|7⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
---
|0⟩     -0.000000 +  0.000000 i  ==     *                    [ 0.000000 ]  \      [  2.42038 rad ]
|1⟩      0.707107 + -0.000000 i  ==     ***********          [ 0.500000 ]     --- [ -0.00000 rad ]
|2⟩      0.707107 + -0.000000 i  ==     ***********          [ 0.500000 ]     --- [ -0.00000 rad ]
|3⟩      0.000000 + -0.000000 i  ==     *                    [ 0.000000 ]     -\  [ -1.10715 rad ]
|4⟩      0.000000 +  0.000000 i  ==     *                    [ 0.000000 ]     +/  [  1.21984 rad ]
|5⟩     -0.000000 + -0.000000 i  ==     *                    [ 0.000000 ] -/      [ -2.61169 rad ]
|6⟩      0.000000 + -0.000000 i  ==     *                    [ 0.000000 ]     -\  [ -1.21367 rad ]
|7⟩     -0.000000 +  0.000000 i  ==     *                    [ 0.000000 ]  \      [  2.18628 rad ]
result = 2
```
## 2つの量子整数の足し算

量子レジスタ同士の足し算は以下のように行います。
この例では```LittleEndian```型で行っています。
他の型のサンプルはご自身でお願いいたします。

```csharp
    @EntryPoint()
    operation IntegerMain(): Unit{
        let bitSize = 3;
        use a = Qubit[bitSize];
        use b = Qubit[bitSize];

        let aLE = LittleEndian(a);
        let bLE = LittleEndian(b);

        // |1> + |5>
        X(a[0]);
        H(a[2]);

        // |1> + |3>
        X(b[0]);
        H(b[1]);

        DumpRegister((), a);
        Message("===");
        DumpRegister((), b);
        Message("===");

        AddI(bLE, aLE);

        DumpMachine();
        let abLE = LittleEndian(Flattened([a, b]));
        let result = MeasureInteger(abLE);
        Message($"result = {result}");
        ResetAll(Flattened([a, b]));
    }
```
#### 結果

#### 量子レジスタ```a```の状態

```bash
|0⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|1⟩      0.707107 +  0.000000 i  ==     **********           [ 0.500000 ]     --- [  0.00000 rad ]  
|2⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|3⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|4⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|5⟩      0.707107 +  0.000000 i  ==     **********           [ 0.500000 ]     --- [  0.00000 rad ]  
|6⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|7⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
```
#### 量子レジスタ```b```の状態
```bash
|0⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|1⟩      0.707107 +  0.000000 i  ==     **********           [ 0.500000 ]     --- [  0.00000 rad ]  
|2⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|3⟩      0.707107 +  0.000000 i  ==     **********           [ 0.500000 ]     --- [  0.00000 rad ]  
|4⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|5⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|6⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|7⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
```
これらの量子レジスタを加えた結果が以下のようになり、
```10, 14, 24, 28```のいずれかの値が出力されることになります。

#### 量子レジスタA+Bの状態
※出力値が多いので、少し省きました。
```bash
|0⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|1⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|10⟩     0.500000 +  0.000000 i  ==     ******               [ 0.250000 ]     --- [  0.00000 rad ]  
|2⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
...
|9⟩      0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|14⟩     0.500000 +  0.000000 i  ==     ******               [ 0.250000 ]     --- [  0.00000 rad ]  
|33⟩     0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|52⟩     0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|24⟩     0.500000 +  0.000000 i  ==     ******               [ 0.250000 ]     --- [  0.00000 rad ]  
|43⟩     0.000000 +  0.000000 i  ==                          [ 0.000000 ]
...
|56⟩     0.000000 +  0.000000 i  ==                          [ 0.000000 ]
|28⟩     0.500000 +  0.000000 i  ==     ******               [ 0.250000 ]     --- [  0.00000 rad ]  
|47⟩     0.000000 +  0.000000 i  ==                          [ 0.000000 ]
...
```
その時の量子レジスタを読み込んだ結果
```bash
result = 14
```

## 型が違う演算を行いた場合

```Microsoft.Quantum.Arithmetic```にはいくつかのエンディアンが存在します。
通常ビックかリトルしかないと思うのですが、Q#では以下のようなエンディアンの型が存在します。

| name | short name | summary |
|---|---|---|
| BigEndian	 | BE |量子ビットを符号なし整数として扱う為の型。ビッグエンディアン順にエンコードします。 |
| FixedPoint | FxP |量子ビットを固定小数点数として扱う為の型。ビッグエンディアン順にエンコードします。 |
| LittleEndian | LE |量子ビットを符号なし整数として扱う為の型。リトルエンディアン順にエンコードします。 |
| PhaseLittleEndian | PhaseLE |QFT ベースのリトルエンディアン符号なし整数。 |
| SignedLittleEndian | SI |量子ビットを符号付き整数として扱う型。リトルエンディアン順にエンコードします。 |


別の型の操作を実行したい場合は以下のような定義をしている操作を
利用することで実現ができます。

```
Apply<current endian short name>OperationOn<target endian short name><functor option>(op, current endian);
```


先ほどのインクリメントを例にします。
LittleEndian型でPhaseLittleEndian型用のIncrement操作したい場合は以下のようにします。
```csharp

    @EntryPoint()
    operation IncrementMain(): Unit {
        let bitSize = 3;
        
        use a = Qubit[bitSize];
        ...
        let aLEHandler = LittleEndian(a);
        // LittleEndian型をインクリメント(+1)
        ApplyPhaseLEOperationOnLECA(IncrementPhaseByInteger(1, _), aLEHandler);
        ...

```

この例では、```ApplyPhaseLEOperationOnLECA```を使用しています。
Q#になれていない人は、第一引数がどういことが分かりずらいと思うのですが、
簡単に言うとバインドしています。以下のようにクロージャーとして扱うこともできます。
```csharp
let increment = IncrementPhaseByInteger(1, _); // アンダーバー(_)を引数入れて関数呼び出しを行うとクロージャーになります。

use register = Qubit[size];
let aPhaseLE = PhaseLittleEndian(register);
increment(aPhaseLE); //　インクリメント
```


以上です。
間違ってたらごめんね。