Quantum 메모리 관리

프로그램은 항상 큐비트 없이 시작됩니다. 즉, Qubit 형식의 값을 진입점 인수로 전달할 수 없습니다. 이 제한은 의도적입니다. Q#의 목적은 프로그램 전체를 표현하고 추론하는 것이기 때문입니다. 대신, 프로그램은 진행되면서 큐비트 또는 양자 메모리를 할당하고 해제합니다. 이와 관련하여 Q#은 양자 컴퓨터를 큐비트 힙으로 모델링합니다.

Q#은 양자 메모리에 대해 별도의 allocaterelease 문을 지원하는 대신 block 문 형태로 양자 메모리 할당을 지원하며, 메모리는 해당 block 문의 범위 내에서만 액세스할 수 있습니다. 문 블록은 현재 범위의 기간 동안 큐비트를 할당할 때 암시적으로 정의할 수 있으며, 자세한 내용은 useborrow 문에 대한 섹션에 설명되어 있습니다. 문이 종료된 후 할당된 큐비트에 액세스하려고 하면 런타임 예외가 발생합니다.

Q#에는 큐비트 값, 큐비트 배열 또는 이들의 조합을 인스턴스화하는 useborrow 문이 있습니다. 이러한 문은 연산 내에서만 사용할 수 있습니다. 이러한 문은 인스턴스화된 큐비트 값을 수집하고 문에 지정된 변수에 바인딩한 다음, 문 블록을 실행합니다. 블록이 끝나면 바인딩된 변수가 범위를 벗어나 더 이상 정의되지 않습니다.

Q#은 clean 큐비트와 dirty 큐비트의 할당을 구분합니다. clean 큐비트는 얽혀 있지 않으며 계산의 다른 부분에 사용되지 않습니다. dirty 큐비트는 상태를 알 수 없으며 양자 프로세서 메모리의 다른 부분과도 얽힐 수 있는 큐비트입니다.

use 문

"clean" 큐비트는 use 문을 통해 할당됩니다.

  • 문은 use 키워드 뒤에 바인딩 및 선택적 문 블록으로 구성됩니다.
  • 문 블록이 있는 경우 큐비트는 해당 블록 내에서만 사용할 수 있습니다. 그렇지 않으면 큐비트는 현재 범위가 끝날 때까지 사용할 수 있습니다.
  • 결합은 단일 기호 또는 기호 튜플, 그 뒤에 등호 =, 단일 튜플 또는 일치하는 이니셜라이저 튜플 중 let 문과 동일한 패턴을 따릅니다.

이니셜라이저는 Qubit()로 표시된 단일 큐비트 또는 큐비트 배열 Qubit[n]에 대해 사용할 수 있습니다. 여기서 nInt 식입니다. 예를 들면 다음과 같습니다.

use qubit = Qubit();
// ...

use (aux, register) = (Qubit(), Qubit[5]);
// ...

use qubit = Qubit() {
    // ...
}

use (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

큐비트는 할당 시 |0⟩ 상태가 보장됩니다. scope 끝에 릴리스되며 릴리스 시 |0⟩ 상태여야 합니다. 이 요구 사항은 매우 비용이 많이 드는 기호 평가가 필요하기 때문에 컴파일러에 의해 적용되지 않습니다. 시뮬레이터에서 실행할 때, 요구 사항을 런타임에 적용할 수 있습니다. 양자 프로세서에서는 요구 사항을 런타임에 적용할 수 없습니다. 측정되지 않은 큐비트는 단일 변환을 통해 |0⟩으로 다시 설정될 수 있습니다. 그렇게 하지 않으면 잘못된 동작이 발생합니다.

use 문은 양자 프로세서의 무료 큐비트 힙에서 큐비트를 할당하고, 큐비트가 바인딩된 범위의 끝보다 늦지 않은 지점에서 이러한 큐비트를 힙으로 반환합니다.

borrow 문

borrow 문은 이미 할당되었지만 현재 사용되지 않는 큐비트에 대한 액세스 권한을 부여합니다. 이러한 큐비트는 임의의 상태일 수 있으며 borrow 문이 종료될 때 다시 동일한 상태에 있어야 합니다. 일부 양자 알고리즘은 큐비트의 정확한 상태에 의존하거나 시스템의 나머지 부분과 얽히지 않을 것을 요구하지 않고, 큐비트를 사용할 수 있습니다. 즉, 일시적으로 추가 큐비트가 필요하지만 해당 큐비트의 상태에 관계없이 원래 상태로 정확하게 반환되도록 할 수 있습니다.

사용 중이지만 서브루틴 동안 건드리지 않은 큐비트가 있는 경우 추가 양자 메모리를 할당하는 대신 이러한 알고리즘에서 사용하기 위해 해당 큐비트를 차용할 수 있습니다. 할당하는 대신 차용하면 알고리즘의 전체 양자 메모리 요구 사항을 크게 줄일 수 있으며 일반적인 시공간 절충의 양자적 예입니다.

borrow 문은 앞에서 use에 대해 설명한 것과 동일한 패턴을 따르며, 동일한 이니셜라이저를 사용할 수 있습니다. 예를 들면 다음과 같습니다.

borrow qubit = Qubit();
// ...

borrow (aux, register) = (Qubit(), Qubit[5]);
// ...

borrow qubit = Qubit() {
    // ...
}

borrow (aux, register) = (Qubit(), Qubit[5]) {
    // ...
}

차용한 큐비트는 알 수 없음 상태이며 문 블록의 끝에서 범위를 벗어납니다. 차용자는 큐비트를 차용했을 때와 동일한 상태로 두기로 약속합니다. 즉, 문 블록의 시작과 끝에 큐비트의 상태가 동일할 것으로 예상됩니다.

borrow 문은 큐비트가 바인딩된 시간부터 해당 큐비트가 마지막으로 사용된 시점까지 프로그램에서 사용하지 않을 것이 보장되었지만 사용 중인 큐비트를 검색합니다. 차용할 수 있는 큐비트가 충분하지 않으면 큐비트가 use 문과 같이 힙에서 할당되고 힙으로 반환됩니다.

참고

dirty 큐비트의 알려진 사용 사례 중에는 매우 적은 큐비트와 증분 구현이 필요한 다중 제어 CNOT 게이트 구현이 있습니다. 큐비트를 사용한 팩터링에 대한 이 문서에서는 차용한 큐비트를 활용하는 알고리즘 예제를 제공합니다.