특수화 선언
호출 가능한 선언에 대한 섹션에서 설명한 것처럼 현재 함수에 대한 특수화를 명시적으로 선언할 이유가 없습니다. 이 항목은 연산에 적용되며 특정 펀터를 지원하는 데 필요한 특수화를 선언하는 방법에 대해 자세히 설명합니다.
지정된 변환의 수반 행렬을 요구하는 것은 양자 컴퓨팅에서 아주 일반적인 문제입니다. 많은 양자 알고리즘은 연산을 수행하기 위해 연산 및 해당 수반 행렬이 모두 필요합니다.
Q#은 특정 본문 구현에 해당하는 수반 행렬 구현을 자동으로 생성할 수 있는 기호 계산을 사용합니다. 이 세대는 클래식 계산과 양자 계산을 자유롭게 혼합하는 구현에서도 가능합니다. 그러나 이 경우 적용되는 몇 가지 제한 사항이 있습니다. 예를 들어 구현에서 변경 가능한 변수를 사용하는 경우 성능상의 이유로 자동 생성이 지원되지 않습니다. 또한 본문 내에서 호출되는 각 연산은 Adjoint
펀터 자체를 지원하기 위해 해당하는 수반 행렬을 생성합니다.
다중 큐비트의 경우 측정을 쉽게 취소할 수 없지만 적용된 변환이 단일하도록 측정을 결합하는 것은 가능합니다. 이 경우 본문 구현에 자체적으로 Adjoint
펀터를 지원하지 않는 측정이 포함되어 있더라도 본문 전체가 수반할 수 있음을 의미합니다. 그럼에도 불구하고 이 경우 수반 행렬 구현 자동 생성은 실패합니다. 이러한 이유로 구현을 수동으로 지정할 수 있습니다.
컴파일러는 접합과 같은 일반적인 패턴에 대해 최적화된 구현을 자동으로 생성합니다.
그럼에도 불구하고 더 최적화된 구현을 직접 정의하려면 명시적 특수화가 바람직할 수 있습니다. 하나의 구현과 원하는 수의 구현을 명시적으로 지정할 수 있습니다.
참고
이러한 수동으로 지정된 구현의 정확성은 컴파일러에서 확인되지 않습니다.
다음 예에서 두 큐비트 q1
및 q2
의 상태를 교환하는 연산 SWAP
에 대한 선언은 수반 행렬 버전 및 제어 버전에 대한 명시적 특수화를 선언합니다. 따라서 Adjoint SWAP
및 Controlled SWAP
에 대한 구현은 사용자 정의되지만 컴파일러는 여전히 두 펀터(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 |
모든 생성 지시문이 제어된 수반 행렬 특수화에 대해 유효하다는 것은 우연이 아닙니다. 펀터가 왕복 이동하는 한, 펀터 조합에 대한 특수화를 구현하기 위한 유효한 생성 지시문 집합은 항상 각 펀터에 대한 유효한 생성기 집합의 합집합입니다.
이전에 나열된 지시문 외에도 지시문 auto
은 를 제외한 body
모든 특수화에 유효합니다. 컴파일러가 적절한 생성 지시문을 자동으로 선택해야 했음을 나타냅니다.
선언
operation DoNothing() : Unit {
body ... { }
adjoint auto;
controlled auto;
controlled adjoint auto;
}
위의 식은 아래의 식과 동일합니다.
operation DoNothing() : Unit
is Adj + Ctl { }
이 예에서 주석 is Adj + Ctl
은 특정 연산이 지원하는 펀터에 대한 정보가 포함된 연산 특성을 지정합니다.
가독성을 위해 각 연산에 특성에 대한 완전한 설명을 추가하는 것이 좋습니다. 컴파일러는 명시적으로 선언된 특수화를 기반으로 주석을 자동으로 삽입하거나 완료합니다. 반대로 컴파일러는 명시적으로 선언되지 않았지만 주석이 달린 특성을 기반으로 존재해야 하는 특수화도 생성합니다. 지정된 주석이 이러한 특수화를 암시적으로 선언했다고 말합니다. 컴파일러는 가능한 경우 적절한 지시문을 선택하여 필요한 특수화를 자동으로 생성합니다. 따라서 Q#은 부분 주석 및 명시적으로 정의된 특수화를 기반으로 연산 특성과 기존 특수화 모두의 유추를 지원합니다.
어떤 의미에서 특수화는 선언할 수 있는 오버로드에 특정 제한이 적용된다는 경고와 함께 동일한 호출 가능 항목에 대한 개별 오버로드와 유사합니다.