다음을 통해 공유


특수화 선언

호출 가능한 선언 대한 섹션에서 설명한 것처럼 현재 함수에 대한 특수화를 명시적으로 선언할 이유가 없습니다. 이 항목은 작업에 적용되며 특정 functor를 지원하는 데 필요한 전문화를 선언하는 방법에 대해 자세히 설명합니다.

양자 컴퓨팅에서 지정된 변환과 인접해야 하는 것은 매우 일반적인 문제입니다. 많은 양자 알고리즘은 계산을 수행하려면 연산과 인접한 연산이 모두 필요합니다. Q# 특정 본문 구현에 해당하는 인접 구현을 자동으로 생성할 수 있는 심볼 계산을 사용합니다. 이 세대는 클래식 및 양자 계산을 자유롭게 혼합하는 구현에서도 가능합니다. 그러나 이 경우에 적용되는 몇 가지 제한 사항이 있습니다. 예를 들어 구현에서 변경 가능한 변수를 사용하는 경우 성능상의 이유로 자동 생성이 지원되지 않습니다. 또한 본문 내에서 호출된 각 연산은 Adjoint functor 자체를 지원하는 해당 인접한 요구 사항을 생성합니다.

다중 큐비트 사례에서 측정값을 쉽게 실행 취소할 수는 없지만 적용된 변환이 단위화되도록 측정을 결합할 수 있습니다. 이 경우 본문 구현에 자체적으로 Adjoint functor를 지원하지 않는 측정값이 포함되어 있더라도 본문 전체가 인접할 수 있음을 의미합니다. 그럼에도 불구하고 이 경우 인접한 구현을 자동으로 생성하지 못합니다. 이러한 이유로 구현을 수동으로 지정할 수 있습니다. 컴파일러는 구성같은 일반적인 패턴에 최적화된 구현을 자동으로 생성합니다. 그럼에도 불구하고 명시적 특수화는 보다 최적화된 구현을 직접 정의하는 것이 바람직할 수 있습니다. 구현 하나와 구현 수를 명시적으로 지정할 수 있습니다.

메모

컴파일러는 수동으로 지정한 구현의 정확성을 확인하지 않습니다.

다음 예제에서는 두 큐비트 q1q2상태를 교환하는 작업 SWAP선언은 인접 버전 및 제어된 버전에 대한 명시적 특수화를 선언합니다. 따라서 Adjoint SWAPControlled SWAP 대한 구현은 사용자 정의이지만 컴파일러는 여전히 두 functor(Controlled Adjoint SWAP, Adjoint Controlled SWAP)의 조합에 대한 구현을 생성해야 합니다.

    operation SWAP (q1 : Qubit, q2 : Qubit) : Unit
    is Adj + Ctl { 

        body ... {
            CNOT(q1, q2);
            CNOT(q2, q1);
            CNOT(q1, q2);
        }

        adjoint ... { 
            SWAP(q1, q2);
        }

        controlled (cs, ...) { 
            CNOT(q1, q2);
            Controlled CNOT(cs, (q2, q1));
            CNOT(q1, q2);            
        } 
    }

자동 생성 지시문

특정 특수화를 생성하는 방법을 결정할 때 컴파일러는 사용자 정의 구현의 우선 순위를 지정합니다. 즉, 인접한 특수화가 사용자 정의이고 제어된 특수화가 자동 생성되면 제어된 인접 특수화는 사용자 정의 인접에 따라 생성되고 그 반대의 경우도 마찬가지입니다. 이 경우 두 특수화 모두 사용자 정의입니다. 인접한 구현의 자동 생성에 더 많은 제한이 적용되므로 제어된 인접 특수화는 기본적으로 인접 특수화의 명시적으로 정의된 구현의 제어된 특수화를 생성합니다.

SWAP 구현의 경우 제어 큐비트의 상태에 대한 첫 번째 및 마지막 CNOT 실행을 불필요하게 컨디셔닝하지 않도록 제어된 특수화와 인접하는 것이 더 좋습니다. 적절한 생성 지시문을 지정하는 제어된 인접 버전에 대한 명시적 선언을 추가하면 컴파일러가 제어된 버전의 수동으로 지정된 구현에 따라 제어된 인접 특수화를 생성하도록 강제할 있습니다. 컴파일러에서 생성한 특수화의 명시적 선언은 형식을 사용합니다.

    controlled adjoint invert;

SWAP선언 내에 삽입됩니다. 반면에 선을 삽입합니다.

    controlled adjoint distribute;

는 컴파일러가 정의된(또는 생성된) 인접 특수화를 기반으로 특수화를 생성하도록 합니다. 자세한 내용은 이 부분 특수화 유추 제안을 참조하세요.

작업 SWAP더 나은 옵션이 있습니다. SWAP 자기 인접, 즉, 그것은 자신의 역입니다; 인접의 정의된 구현은 단지 SWAP 본문을 호출하고 지시문으로 표현됩니다.

    adjoint self;

이러한 방식으로 인접 특수화를 선언하면 컴파일러가 자동으로 삽입하는 제어된 인접 특수화가 제어된 특수화만 호출하도록 합니다.

다음 생성 지시문이 존재하며 유효합니다.

전문화 지시문
body 전문화: -
adjoint 전문화: self, invert
controlled 전문화: distribute
controlled adjoint 전문화: self, invert, distribute

모든 세대 지시문이 제어된 인접 특수화에 유효하다는 것은 우연이 아닙니다. functors가 통근하는 한, 펀터 조합에 대한 특수화를 구현하기 위한 유효한 생성 지시문 집합은 항상 각 생성기에 대한 유효한 생성기 집합의 합집합입니다.

이전에 나열된 지시문 외에도 지시문 autobody; 를 제외한 모든 특수화에 유효합니다. 컴파일러가 적절한 생성 지시문을 자동으로 선택해야 했음을 나타냅니다. 선언

    operation DoNothing() : Unit {
        body ... { }
        adjoint auto;
        controlled auto;
        controlled adjoint auto;
    }

에 해당합니다.

    operation DoNothing() : Unit 
    is Adj + Ctl { }

이 예제의 주석 is Adj + Ctl 특정 작업이 지원하는 functor에 대한 정보를 포함하는작업 특성을 지정합니다.

가독성을 위해서는 특성에 대한 완전한 설명으로 각 작업에 주석을 달고, 컴파일러는 명시적으로 선언된 특수화에 따라 주석을 자동으로 삽입하거나 완료하는 것이 좋습니다. 반대로 컴파일러는 명시적으로 선언되지는 않았지만 주석이 추가된 특성에 따라 존재해야 하는 특수화도 생성합니다. 지정된 주석 이러한 특수화에 암시적으로 선언한다고 합니다. 컴파일러는 가능한 경우 필요한 특수화를 자동으로 생성하고 적절한 지시문을 선택합니다. 따라서 Q# (부분) 주석 및 명시적으로 정의된 특수화를 기반으로 작업 특성과 기존 특수화의 유추를 지원합니다.

어떤 의미에서 특수화는 동일한 호출 가능한 개별 오버로드와 유사하며, 선언할 수 있는 오버로드에 특정 제한이 적용된다는 주의를 줍니다.