{{위키데이터 속성 추적}}
{{Infobox programming language
| title = Q#
| logo = Q mini.png
| released = {{시작 날짜|2017|12|11}}
| developer = [[마이크로소프트]]
| designer = [[마이크로소프트 리서치]](QuArC)
| influenced by = [[C 샤프|C#]], [[F 샤프|F#]], [[파이썬]]
| File extensions = .qs
| platform = [[공통 언어 기반]]
| paradigm = 양자, 함수형, 명령형
| typing = 정적, 스트롱
| license = [[MIT 라이선스]]<ref>{{웹 인용|title=Introduction to Q# |url=https://courses.cs.washington.edu/courses/cse490q/20au/hws/qsharp-intro.pdf |publisher=[[워싱턴 대학교|University of Washington]]}}</ref>
| website = {{URL|https://docs.microsoft.com/en-us/quantum}}
| repo = {{URL|[https://github.com/Microsoft/Quantum}}
}}

'''Q 샤프'''(Q#)는 [[양자 알고리즘]]을 표현하기 위해 사용되는 [[도메인 특화 언어]]이다.<ref name=":1">{{웹 인용|url=https://docs.microsoft.com/en-us/quantum/quantum-qr-intro?view=qsharp-preview|title=The Q# Programming Language|last=QuantumWriter|website=docs.microsoft.com|language=en-us|access-date=2017-12-11}}</ref> 양자 개발 키트의 일부로서 [[마이크로소프트]]가 처음 공개하였다.<ref name=":0">{{뉴스 인용|url=https://cloudblogs.microsoft.com/quantum/2017/12/11/announcing-microsoft-quantum-development-kit/|title=Announcing the Microsoft Quantum Development Kit|access-date=2017-12-11|language=en-US}}</ref>

== 예시 ==
다음의 소스 코드는 공식 마이크로소프트 Q# 라이브러리 저장소에서 가져온 [[멀티플렉서]]이다.

<syntaxhighlight lang="c#">
// 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) - 2, "Unexpected number of auxiliary qubits");
            let controls1 = ctrlRegister[0..0] + auxRegister;
            let controls2 = Rest(ctrlRegister);
            let targets = auxRegister + [target];
            ApplyToEachA(ApplyAnd, Zipped3(controls1, controls2, targets));
        }
    }
}
</syntaxhighlight>

== 각주 ==
{{각주}}

== 외부 링크 ==
*{{공식 웹사이트}}
*{{GitHub|microsoft|qsharp-language}}

{{마이크로소프트 자유-오픈 소스 소프트웨어}}
{{마이크로소프트 개발 도구}}

[[분류:자유-오픈 소스 소프트웨어]]
[[분류:마이크로소프트의 자유 소프트웨어]]
[[분류:MIT 라이선스 소프트웨어]]
[[분류:마이크로소프트의 프로그래밍 언어]]