独自のQ#シミュレーターを作成する-パート1

シミュレーターは、QDKの特に用途の広い機能です。 Q#プログラムを変更せずに、さまざまなタスクを実行できます。このようなタスクには、完全な状態のシミュレーションリソースの推定、またはトレースのシミュレーションが含まれます。新しいインターフェースIQuantumProcessorにより、独自のシミュレーターを作成し、それらをQ#プロジェクトに統合することが非常に簡単になります。



この投稿は、このインターフェイスに関するシリーズの最初の投稿です。最初の例としてリバーシブルシミュレーターを実装することから始めます。これについては、今後のブログ投稿で詳しく説明します。リバーシブルシミュレータは、古典的な操作からのみ構成された量子プログラムをシミュレートすることができます:XCNOTCCNOT(Toffoliゲート)またはランダムに制御されたX操作。リバーシブルシミュレータは、各キュービットに1つのブール値を割り当てることで量子状態を表すことができるため、数千キュービットの量子プログラムを実行することもできます。このシミュレータは、ブール関数を評価する量子演算をテストするのに非常に役立ちます。







Cでのシミュレーターの実装#



このブログ投稿では、基本的なコードスニペットについて説明しています。完全なソースコードは、MicrosoftQDKサンプルリポジトリにあります。


クラスを拡張して、独自のシミュレーターを作成し始めますQuantumProcessorBase



class ReversibleSimulatorProcessor : QuantumProcessorBase {
    private IDictionary<Qubit, bool> simulationValues = new Dictionary<Qubit, bool>();

    //       (intrinsic operations)...
}


プログラム内の各キュービットの現在のシミュレーション値を格納する辞書は、すでにクラスに追加されています。古典的な量子状態|0⟩と|1⟩は、それぞれブール値falseとtrueとして表されます。シミュレーターは、Q#プログラムで内部操作を定義します。QuantumProcessorBase新しいシミュレータでその動作を定義するためにオーバーライドできる各内部操作のメソッドが含まれています。実装されていないメソッドはデフォルトの例外をスローすることに注意してください。これは、操作をまだ実装する必要がある場合を特定するのに役立ち、インライン操作がシミュレーターでサポートされていないことをシミュレーターユーザーに通知します。たとえば、リバーシブルシミュレータを使用して、HやTなどの非古典的な操作を含む量子プログラムをシミュレートすることはできません。



OnAllocateQubitsメソッドをオーバーライドして、新しく割り当てられたキュービットを誤って初期化することから始めましょう。同様に、キュービットはリリース時に辞書から削除されます。この場合、OnReleaseQubitsが呼び出されます。



public override void OnAllocateQubits(IQArray qubits) {
    foreach (var qubit in qubits) {
        simulationValues[qubit] = false;
    }
}

public override void OnReleaseQubits(IQArray qubits) {
    foreach (var qubit in qubits) {
        simulationValues.Remove(qubit);
    }
}


これらの2つの操作により、操作が一部のキュービットに適用されたときにシミュレーション値が使用可能であり、現在の領域にないキュービットのシミュレーション値が辞書に残っていないことが保証されます。



次のステップとして、従来の操作アクションを実装しましょう。この場合、2つのメソッドで十分です。X操作がシミュレートされるときにXメソッドが呼び出され、X操作がシミュレートされるときにControlledXメソッドが呼び出されます。これには、CNOTとCCNOTも含まれます。 X操作は、キュービットのシミュレーション値を反転しますが、任意に制御されたX操作の場合、すべての制御キュービットがtrueに設定されている場合にのみ、ターゲットキュービットが反転されます。



public override void X(Qubit qubit) {
    simulationValues[qubit] = !simulationValues[qubit];
}

public override void ControlledX(IQArray controls, Qubit qubit) {
    simulationValues[qubit] ^= And(controls);
}


最後に、Q#プログラムでキュービットを測定すると、結果(1またはゼロ)が返されます。これは、キュービットの現在のシミュレーション値に基づいて計算できます。また、Q#プログラムでリセット操作が呼び出されたときに呼び出されるResetメソッドを実装します。後者は現在の領域からキュービットを削除しませんが、シミュレーション値を初期値にリセットします。これはfalseです。



public override Result M(Qubit qubit) {
    return simulationValues[qubit] ? Result.One : Result.Zero;
}

public override void Reset(Qubit qubit) {
    simulationValues[qubit] = false;
}


ReversibleSimulatorProcessorは、QuantumProcessorDispatcherをインスタンス化することでシミュレーターとして使用できます。推奨される設計スタイルは、シミュレーターにカスタムクラスを提供することです。



public class ReversibleSimulator : QuantumProcessorDispatcher {
    public ReversibleSimulator() : base(new ReversibleSimulatorProcessor()) {}
}


新しいシミュレーターの使用



次のQ#操作で新しいシミュレーターを試してみましょう。



operation ApplyMajority(a : Qubit, b : Qubit, c : Qubit, f : Qubit) : Unit {
    within {
        CNOT(b, a);
        CNOT(b, c);
    } apply {
        CCNOT(a, c, f);
        CNOT(b, f);
    }
}


また、3つのブール入力を提供することにより、多数決操作を実行する操作を記述します。



operation RunMajority(a : Bool, b : Bool, c : Bool) : Bool {
    using ((qa, qb, qc, f) = (Qubit(), Qubit(), Qubit(), Qubit())) {
        within {
            ApplyPauliFromBitString(PauliX, true, [a, b, c], [qa, qb, qc]);
        } apply {
            ApplyMajority(qa, qb, qc, f);
        }
        return MResetZ(f) == One;
    }
}


最後に、C#ホストプログラムの新しいシミュレーターでQ#操作を呼び出すことにより、すべてをまとめることができます。次の例では、すべての異なる入力先のメイン操作を評価し、すべてのシミュレーション結果を表示します。



public static void Main(string[] args) {
    var sim = new ReversibleSimulator();
    var bits = new[] {false, true};

    foreach (var a in bits) {
        foreach (var b in bits) {
            foreach (var c in bits) {
                var f = RunMajority.Run(sim, a, b, c).Result;
                Console.WriteLine($"Majority({a,5}, {b,5}, {c,5})  =  {f,5}");
            }
        }
    }
}


独自のシミュレーターを作成する準備はできましたか?



この投稿が、独自のシミュレーターを作成するきっかけになることを願っています。次のステップでは、現在の実装のパフォーマンスを向上させる方法(たとえば、シミュレーション値を格納するために辞書を使用しないことによって)、スタンドアロンのQ#プロジェクトに変換する方法、非組み込み操作にカスタムアクションを提供する方法、および診断操作を提供する方法について説明します。デバッグに役立ちます。



All Articles