및 .NET 프로그램을 사용하여 Q# 개발

Q# 프로그래밍 언어는 C# 및 F#과 같은 .NET 언어와 잘 작동하도록 빌드되었습니다. 이 가이드에서는 .NET 언어로 작성된 호스트 프로그램과 함께 사용하는 Q# 방법을 보여 줍니다.

먼저 Q# 애플리케이션과 .NET 호스트를 만들고, 호스트에서 Q#을 호출합니다.

필수 조건

설정의 단계에 따라 Microsoft Quantum Development Kit 를 사용하여 .NET 환경을 설정합니다 Quantum Development Kit.

Q# 라이브러리 및 .NET 호스트 만들기

첫 번째 단계에서는 Q# 라이브러리용 프로젝트 및 Q# 라이브러리에 정의된 작업 및 함수를 호출할 .NET 호스트를 만듭니다.

사용하는 개발 환경에 해당하는 탭의 지침을 따릅니다. Visual Studio 또는 VS Code 이외의 편집기를 사용하는 경우 간단하게 명령 프로그램 단계를 따르면 됩니다.

  • QDK 템플릿 패키지 설치

    dotnet new -i Microsoft.Quantum.ProjectTemplates
    
  • 새 Q# 라이브러리 만들기

    dotnet new classlib -lang Q# -o quantum
    
  • 새 C# 또는 F# 콘솔 프로젝트 만들기

    dotnet new console -lang C# -o host  
    
  • Q# 라이브러리를 호스트 프로그램에서 참조로 추가

    cd host
    dotnet add reference ../quantum/quantum.csproj
    
  • [선택 사항] 두 프로젝트 모두에 대한 솔루션 만들기

    dotnet new sln -n quantum-dotnet
    dotnet sln quantum-dotnet.sln add ./quantum/quantum.csproj
    dotnet sln quantum-dotnet.sln add ./host/host.csproj
    

.NET에서 Q# 호출

위의 지침에 따라 프로젝트를 설정한 후에는 .NET 콘솔 애플리케이션에서 Q#을 호출할 수 있습니다. Q# 컴파일러는 시뮬레이터에서 퀀텀 프로그램을 실행할 수 있도록 각 Q# 작업 및 함수에 대해 .NET 클래스를 생성합니다.

예를 들어 .NET 상호 운용성 샘플에는 다음과 같은 Q# 연산 예제가 포함되어 있습니다.

namespace Microsoft.Quantum.Samples {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Arrays;
    open Microsoft.Quantum.Measurement;

    /// # Summary
    /// A quantum oracle which implements the following function:
    /// f(x₀, …, xₙ₋₁) = Σᵢ (rᵢ xᵢ + (1 - rᵢ)(1 - xᵢ)) modulo 2 for a given bit vector r = (r₀, …, rₙ₋₁).
    ///
    /// # Input
    /// ## r
    /// A bit vector of length N
    /// ## x
    /// N qubits in arbitrary state |x⟩ (input register)
    /// ## y
    /// A qubit in arbitrary state |y⟩ (output qubit)
    operation ApplyProductWithNegationFunction (vector : Bool[], controls : Qubit[], target : Qubit)
    : Unit is Adj {
        for (bit, control) in Zipped(vector, controls) {
            ControlledOnInt(bit ? 1 | 0, X)([control], target);
        }
    }

    /// # Summary
    /// Reconstructs the parameters of the oracle in a single query
    ///
    /// # Input
    /// ## N
    /// The number of qubits in the input register N for the function f
    /// ## oracle
    /// A quantum operation which implements the oracle |x⟩|y⟩ -> |x⟩|y ⊕ f(x)⟩, where
    /// x is an N-qubit input register, y is a 1-qubit answer register, and f is a Boolean function.
    /// The function f implemented by the oracle can be represented as
    /// f(x₀, …, xₙ₋₁) = Σᵢ (rᵢ xᵢ + (1 - rᵢ)(1 - xᵢ)) modulo 2 for some bit vector r = (r₀, …, rₙ₋₁).
    ///
    /// # Output
    /// A bit vector r which generates the same oracle as the given one
    /// Note that this doesn't have to be the same bit vector as the one used to initialize the oracle!
    operation ReconstructOracleParameters(N : Int, oracle : ((Qubit[], Qubit) => Unit)) : Bool[] {
        use x = Qubit[N];
        use y = Qubit();

        // apply oracle to qubits in all 0 state
        oracle(x, y);

        // f(x) = Σᵢ (rᵢ xᵢ + (1 - rᵢ)(1 - xᵢ)) = 2 Σᵢ rᵢ xᵢ + Σᵢ rᵢ + Σᵢ xᵢ + N = Σᵢ rᵢ + N
        // remove the N from the expression
        if (N % 2 == 1) {
            X(y);
        }

        // now y = Σᵢ rᵢ

        // measure the output register
        let m = MResetZ(y);

        // before releasing the qubits make sure they are all in |0⟩ state
        ResetAll(x);
        return m == One
                ? ConstantArray(N, false) w/ 0 <- true
                | ConstantArray(N, false);
    }

    /// # Summary
    /// Instantiates the oracle and runs the parameter restoration algorithm.
    operation RunAlgorithm(bits : Bool[]) : Bool[] {
        Message("Hello, quantum world!");
        // construct an oracle using the input array
        let oracle = ApplyProductWithNegationFunction(bits, _, _);
        // run the algorithm on this oracle and return the result
        return ReconstructOracleParameters(Length(bits), oracle);
    }
}

퀀텀 시뮬레이터의 .NET에서 이 작업을 호출하려면 Q# 컴파일러에서 생성된 RunAlgorithm .NET 클래스의 Run 메서드를 사용하면 됩니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static System.Diagnostics.Debug;

using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;

namespace Microsoft.Quantum.Samples
{
    static class Program
    {
        static async Task Main(string[] args)
        {
            var bits = new[] { false, true, false };
            using var sim = new QuantumSimulator();

            Console.WriteLine($"Input: {bits.ToDelimitedString()}");

            var restored = await RunAlgorithm.Run(sim, new QArray<bool>(bits));
            Console.WriteLine($"Output: {restored.ToDelimitedString()}");

            Assert(bits.Parity() == restored.Parity());
        }

        static bool Parity(this IEnumerable<bool> bitVector) =>
            bitVector.Aggregate(
                (acc, next) => acc ^ next
            );

        static string ToDelimitedString(this IEnumerable<bool> values) =>
            String.Join(", ", values.Select(x => x.ToString()));
    }
}

다음 단계

Quantum Development Kit 이제 애플리케이션과 .NET과의 상호 운용성을 모두 Q# 설정했으므로 첫 번째 양자 프로그램을 작성하고 실행할 수 있습니다.