QkObs
typedef struct QkObs QkObs데이터를 큐비트-스페어 형식으로 저장하는 폴리 기반에 대한 옵저버블입니다.
수학
이 관측 가능성은 폴리 연산자와 폴리 고유 상태 프로젝터의 문자열에 대한 합을 나타내며, 각 항에 복소수 가중치를 부여합니다. 즉, 전체 관찰 가능 범위는 다음과 같습니다
복소수 및 제한된 알파벳 에서 큐비트 에 작용하는 단일 큐비트 연산자. 의 합은 개별 항의 합이며, 텐서 곱은 연산자 문자열을 생성합니다. 허용되는 단일 큐비트 연산자의 알파벳은 폴리 연산자와 폴리 고유 상태 투영 연산자입니다. 명시적으로는 다음과 같습니다:
연산자 | QkBitTerm | 숫자 값 |
|---|---|---|
| (신원) | 저장되지 않습니다. | 저장되지 않습니다. |
| (폴리 엑스) | QkBitTerm_X | 0b0010 (2) |
| (Pauli Y) | QkBitTerm_Y | 0b0011 (3) |
| (폴리 Z) | QkBitTerm_Z | 0b0001 (1) |
| (X의 양의 고유 상태로 투영) | QkBitTerm_Plus | 0b1010 (10) |
| (X의 음의 고유 상태로 프로젝터) | QkBitTerm_Minus | 0b0110 (6) |
| (Y의 양의 고유 상태로 투영) | QkBitTerm_Right | 0b1011 (11) |
| (Y의 음의 고유 상태로 투영) | QkBitTerm_Left | 0b0111 (7) |
| (Z의 양의 고유 상태로 투영) | QkBitTerm_Zero | 0b1001 (9) |
| (Z의 음의 고유 상태로 투영) | QkBitTerm_One | 0b0101 (5) |
폴리스와 프로젝터를 모두 허용하기 때문에 허용된 알파벳은 연산자 공간의 지나치게 불완전한 기초를 형성합니다. 즉, 주어진 관측값을 나타내는 고유한 합이 없다는 뜻입니다. 따라서 비교에는 추가적인 주의가 필요하며 수학적으로 동등한 두 개의 관측값에 qk_obs_canonicalize 을 사용하면 동일한 표현이 되지 않을 수 있습니다.
QkObs 는 '측정의 효율성'을 '표현의 효율성'과 동등하게 만들기 위해 특별히 불완전한 기반을 사용합니다. 예를 들어, 관측 가능한 은 간단한 측정으로 하드웨어에서 효율적으로 측정할 수 있지만, 폴리스에서는 로만 표현할 수 있으므로 저장된 용어가 필요합니다. QkObs 를 저장하는 데는 단 하나의 용어만 필요합니다. 이 방법의 단점은 임의의 행렬을 사용하여 최상의 QkObs 표현을 찾는 것이 비현실적이라는 것입니다. 일반적으로 QkObs 을 분해하는 대신 직접 구성하는 것이 좋습니다.
표현
QkObs 의 내부 표현은 비신원 큐비트 연산자만 저장합니다. 따라서 ; QkObs 과 같은 관측값을 표현하는 데 훨씬 더 효율적입니다. 용어는 스파스 행렬의 압축 스파스 행 형식과 유사하게 압축되어 저장됩니다. 이 비유에서 합계의 용어는 '행'이고 큐비트 용어는 '열'이며, 없는 항목은 0이 아닌 신원을 나타냅니다. 보다 명확하게 표현하면, 이 표현은 4개의 인접한 배열로 구성됩니다:
액세스 가능한 속성 | 길이 | 설명 |
|---|---|---|
qk_obs_coeffs | 각 용어에 대한 복소 스칼라 승수입니다. | |
qk_obs_bit_terms | 모든 연산자에 대한 비식별 단일 큐비트 용어 각각을 순서대로 나열합니다. 이는 합계 설명에서 비아이덴티티 에 해당하며, 항목은 먼저 이 증가하는 순서로 저장되고 각 용어 내에서 이 증가하는 순서로 저장됩니다. | |
qk_obs_indices | 각 비트 용어에 해당하는 큐비트( )입니다. QkObs 를 사용하려면 이 목록이 용어별로 정렬되어야 하며 알고리즘은 이 불변성이 유지되는지 확인할 수 있습니다. | |
qk_obs_boundaries | 비트 용어와 인덱스를 완전한 용어로 분할하는 인덱스입니다. 용어 번호 의 경우 복소수 계수는 인덱스 i 에 저장되며, 비식별 단일 큐비트 연산자와 해당 큐비트는 비트 용어와 인덱스에서 각각 [boundaries[i], boundaries[i+1]) 범위에 있습니다. 경계는 항상 명시적으로 0을 첫 번째 요소로 사용합니다. |
길이 매개변수 는 합계의 용어 수이며 qk_obs_num_terms 을 사용하여 쿼리할 수 있습니다. 매개변수 는 비식별 단일 큐비트 용어의 총 개수이며 qk_obs_len 를 사용하여 쿼리할 수 있습니다.
예시적인 예로
- 영 연산자의 경우 경계는 길이 1(단일 0)이고 다른 모든 벡터는 비어 있습니다.
- 완전히 단순화된 ID 연산자의 경우 경계는
{0, 0}, 계수에는 단일 항목이 있으며 비트 항과 인덱스는 모두 비어 있습니다. - 연산자 의 경우 경계는
{0, 2, 4}, 코오프는{1.0, -1.0}, 비트 용어는{QkBitTerm_Z, QkBitTerm_Z, QkBitTerm_Y, QkBitTerm_X}, 인덱스는{0, 2, 1, 3}입니다. 운영자는 큐비트 수에 따라 4개 이상의 큐비트에 대해 작업할 수 있습니다(qk_obs_num_qubits참조). 단일 비트 용어와 인덱스는 용어별로 정렬된 순서로 정렬된다는 점에 유의하세요.
이러한 경우는 특별한 경우가 아니며 규칙에 완전히 부합하므로 특별한 처리가 필요하지 않습니다.
정규 순서
주어진 수학적 관측값에 대해 QkObs 로 표현하는 방법에는 여러 가지가 있습니다. 예를 들어, 동일한 단일 비트 용어 집합과 해당 인덱스가 관찰 가능 항목에 여러 번 나타날 수 있습니다. 수학적으로 이것은 모든 계수를 합산한 단일 항만 있는 것과 같습니다. 마찬가지로, QkObs 에서의 합의 조건은 동일한 관측값을 나타내면서 어떤 순서로든 될 수 있습니다(부동소수점 덧셈은 연관성이 없지만 QkObs 은 합산 순서에 대해 보장하지 않습니다).
이러한 두 가지 범주의 표현 퇴화는 연산자 같음( qk_obs_equal)이 동일한 객체를 표현함에도 불구하고 두 관측값이 같지 않다고 주장하게 만들 수 있습니다. 이러한 경우, 관측값을 구조적으로 비교할 수 있는 표준 형식을 정의하는 것이 편리할 수 있습니다. qk_obs_canonicalize 함수를 사용하여 QkObs 을 정식 형식으로 입력할 수 있습니다. 표준 순서의 정확한 용어 순서는 지정되어 있지 않으며, 키스킷 버전에 따라 변경될 수 있습니다. 그러나 동일한 버전의 키스킷 내에서는 두 개의 관측값을 단순화된 형태로 비교하여 구조적으로 비교할 수 있습니다.
비교에서 부동 소수점 허용 오차를 고려하려면 다음과 같은 레시피를 사용하는 것이 가장 안전합니다:
bool equivalent(QkObs *left, QkObs *right, double tol) {
// compare a canonicalized version of left - right to the zero observable
QkObs *neg_right = qk_obs_multiply(right, &(QkComplex64){-1, 0});
QkObs *diff = qk_obs_add(left, neg_right);
QkObs *canonical = qk_obs_canonicalize(diff, tol);
QkObs *zero = qk_obs_zero(qk_obs_num_qubits(left));
bool equiv = qk_obs_equal(diff, zero);
// free all temporary variables
qk_obs_free(neg_right);
qk_obs_free(diff);
qk_obs_free(canonical);
qk_obs_free(zero);
return equiv;
}qk_obs_canonicalize 에서 생성된 표준 형식만으로는 기본 알파벳이 지나치게 완전하기 때문에 동등한 모든 관측값을 보편적으로 감지할 수 없습니다.
색인화
QkObs 의 개별 관측 가능한 합계 조건은 qk_obs_term 을 통해 액세스하고 QkObsTerm 유형의 객체를 반환할 수 있습니다. 이러한 용어에는 용어의 계수, 비트 용어, 인덱스 및 정의된 큐비트 수가 있는 필드가 포함됩니다. 용어 수에 대한 정보와 함께 관찰 가능한 모든 용어를 다음과 같이 반복할 수 있습니다
size_t num_terms = qk_obs_num_terms(obs); // obs is QkObs*
for (size_t i = 0; i < num_terms; i++) {
QkObsTerm term; // allocate term on stack
int exit = qk_obs_term(obs, i, &term); // get the term (exit > 0 upon index errors)
// do something with the term...
}qk_obs_term 을 통해 QkObsTerm 을 채우면 원본 QkObs 의 데이터를 참조하게 됩니다. 비트 용어나 인덱스를 수정하면 관측값이 변경되어 일관성 없는 상태가 될 수 있습니다.
생성
QkObs 는 빈 옵저버블을 초기화( qk_obs_zero)하고 반복적으로 용어를 추가( qk_obs_add_term)하여 구성할 수 있습니다. 또는 모든 내부 데이터가 지정된 경우 '원시' 데이터( qk_obs_new)로 관측값을 구성할 수도 있습니다. 이를 위해서는 데이터의 일관성을 유지하고 유효한 관찰 가능한 결과를 얻을 수 있도록 주의를 기울여야 합니다.
함수 | 요약 |
|---|---|
qk_obs_zero | 주어진 수의 큐비트에 빈 옵저버블을 구축합니다. |
qk_obs_identity | 주어진 큐비트 수에서 관찰 가능한 ID를 구성합니다. |
qk_obs_new | 원시 데이터 배열에서 관찰 가능한 데이터를 구축합니다. |
수학적 조작
QkObs 는 관측값 사이 또는 스칼라를 사용한 기본적인 산술 연산을 지원합니다. 다음과 같은 일을 할 수 있습니다.
- 와 를
qk_obs_add사용하여 두 개의 관측값을 추가하고qk_obs_add_inplace - 복소수를 곱할 때
qk_obs_multiply와qk_obs_multiply_inplace - 를 통해 두 개의 관측값을 작성(곱하기)하고
qk_obs_compose및qk_obs_compose_map - 두 개의 관측량과 복소 스칼라에 대해 다음을
left + scalar * right``qk_obs_scaled_add계산한다:qk_obs_scaled_add_inplace
함수
qk_obs_zero
QkObs *qk_obs_zero(uint32_t num_qubits)
(조건 없이) 영 관측값을 구축합니다.
예
QkObs *zero = qk_obs_zero(100);매개변수
- 숫자_큐비트 - 관측 항목이 정의된 큐비트 수입니다.
리턴
생성된 관찰 가능 항목에 대한 포인터입니다.
qk_obs_identity
QkObs *qk_obs_identity(uint32_t num_qubits)
관찰 가능한 아이덴티티를 구축합니다.
예
QkObs *identity = qk_obs_identity(100);매개변수
- 숫자_큐비트 - 관측 항목이 정의된 큐비트 수입니다.
리턴
생성된 관찰 가능 항목에 대한 포인터입니다.
qk_obs_new
QkObs *qk_obs_new(uint32_t num_qubits, uint64_t num_terms, uint64_t num_bits, QkComplex64 *coeffs, QkBitTerm *bit_terms, uint32_t *indices, size_t *boundaries)
원시 데이터에서 새로운 관측값을 생성합니다.
포인터 인자 중 어느 것이든 해당 길이가 0일 때에만 NULL 해당할 수 있다.
예
// define the raw data for the 100-qubit observable |01><01|_{0, 1} - |+-><+-|_{98, 99}
uint32_t num_qubits = 100;
uint64_t num_terms = 2; // we have 2 terms: |01><01|, -1 * |+-><+-|
uint64_t num_bits = 4; // we have 4 non-identity bits: 0, 1, +, -
QkComplex64 coeffs[] = {{1, 0}, {-1, 0}};
QkBitTerm bits[4] = {QkBitTerm_Zero, QkBitTerm_One, QkBitTerm_Plus, QkBitTerm_Minus};
uint32_t indices[4] = {0, 1, 98, 99}; // <-- e.g. {1, 0, 99, 98} would be invalid
size_t boundaries[3] = {0, 2, 4};
QkObs *obs = qk_obs_new(
num_qubits, num_terms, num_bits, coeffs, bits, indices, boundaries
);
qk_obs_free(obs);안전
다음 조건 중 하나라도 위반하면 동작이 정의되지 않습니다:
coeffs는QkComplex64길이의 배열에 대한 포인터입니다num_termsbit_terms는 길이가 유효한QkBitTerm요소의 배열에 대한 포인터입니다num_bitsindices는 길이num_bits의uint32_t배열에 대한 포인터로, 엄격한 오름차순으로 정렬되며 모든 요소는 다음보다 작습니다num_qubitsboundaries는 오름차순으로 정렬된num_terms + 1길이의size_t배열에 대한 포인터로, 첫 번째 요소는 0이고 마지막 요소는 다음보다 작습니다num_terms
매개변수
- 숫자_큐비트 - 관측 항목이 정의된 큐비트 수입니다.
- num_terms - 학기 수입니다.
- num_bits - 비식별 비트 용어의 총 개수입니다.
- coeffs - 길이가
num_terms인 계수 배열의 첫 번째 요소에 대한 포인터입니다. - bit_terms - 비트 용어 배열의 첫 번째 요소에 대한 포인터로, 길이가
num_bits입니다. - 인덱스 - 길이가
num_bits인 인덱스 배열의 첫 번째 요소에 대한 포인터입니다. 용어별로 점진적으로 정렬해야 한다는 점에 유의하세요. - 경계 - 길이가
num_terms + 1인 경계 배열의 첫 번째 요소에 대한 포인터입니다.
리턴
입력 데이터가 일관되고 구성이 성공적이었다면, 그 결과는 관찰 가능성에 대한 포인터가 됩니다. 그렇지 않으면 널 포인터가 반환됩니다.
qk_obs_free
void qk_obs_free(QkObs *obs)
관찰 가능한 것을 해제하세요.
예
QkObs *obs = qk_obs_zero(100);
qk_obs_free(obs);안전
obs 이 null이 아니거나 QkObs 에 대한 유효한 포인터가 아닌 경우 동작이 정의되지 않습니다.
매개변수
- obs - 관찰할 수 있는 무료에 대한 포인터입니다.
qk_obs_add_term
QkExitCode qk_obs_add_term(QkObs *obs, const QkObsTerm *cterm)
관찰 가능 항목에 용어를 추가합니다.
예
uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);
QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};
QkExitCode exit_code = qk_obs_add_term(obs, &term);안전
다음 중 하나라도 위반하면 동작이 정의되지 않습니다:
obs는 널이 아닌 유효한 포인터입니다QkObscterm는 널이 아닌 유효한 포인터입니다QkObsTerm
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
- 학기 - 추가할 학기에 대한 포인터입니다.
리턴
종료 코드입니다. 용어가 일관성이 없거나 용어 추가에 실패한 경우 >0 입니다.
qk_obs_term
QkExitCode qk_obs_term(QkObs *obs, uint64_t index, QkObsTerm *out)
참조로 관찰 가능한 용어를 가져옵니다.
QkObsTerm 에는 해당 용어의 인덱스와 비트 용어에 대한 포인터가 포함되어 있으며, 이 포인터는 옵저버블의 내부 데이터를 수정하는 데 사용할 수 있습니다. 이렇게 하면 관찰 가능한 내용이 일관성 없는 상태로 남을 수 있으므로 세심한 주의를 기울이지 않는 한 피해야 합니다. 일반적으로 제자리에서 수정을 시도하는 대신 새 관측값을 만드는 것이 더 안전합니다.
예
QkObs *obs = qk_obs_identity(100);
QkObsTerm term;
QkExitCode exit_code = qk_obs_term(obs, 0, &term);
// out-of-bounds indices return an error code
// QkExitCode error = qk_obs_term(obs, 12, &term);안전
다음 중 하나라도 위반하는 경우 동작이 정의되지 않습니다
obs는 널이 아닌 유효한 포인터입니다QkObsout는 널이 아닌 유효한 포인터입니다QkObsTerm
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
- 색인 - 가져올 용어의 색인입니다.
- out - 관찰 가능한 용어를 반환하는 데 사용되는
QkObsTerm포인터입니다.
리턴
종료 코드입니다.
qk_obs_num_terms
size_t qk_obs_num_terms(const QkObs *obs)
관찰 가능한 용어의 개수를 가져옵니다.
예
QkObs *obs = qk_obs_identity(100);
size_t num_terms = qk_obs_num_terms(obs); // num_terms==1안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
관찰 가능한 용어의 수입니다.
qk_obs_num_qubits
uint32_t qk_obs_num_qubits(const QkObs *obs)
옵저버블이 정의된 큐비트 수를 가져옵니다.
예
QkObs *obs = qk_obs_identity(100);
uint32_t num_qubits = qk_obs_num_qubits(obs); // num_qubits==100안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
옵저버블이 정의된 큐비트 수입니다.
qk_obs_len
size_t qk_obs_len(const QkObs *obs)
옵저버블의 비트 텀/인덱스 수를 가져옵니다.
예
QkObs *obs = qk_obs_identity(100);
size_t len = qk_obs_len(obs); // len==0, as there are no non-trivial bit terms안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
관찰 가능한 용어의 수입니다.
qk_obs_coeffs
QkComplex64 *qk_obs_coeffs(QkObs *obs)
계수에 대한 포인터를 가져옵니다.
관측값의 계수를 읽고 수정하는 데 사용할 수 있습니다. 결과 포인터는 QkComplex64 의 qk_obs_num_terms(obs) 요소에 대해 읽을 수 있습니다.
예
QkObs *obs = qk_obs_identity(100);
size_t num_terms = qk_obs_num_terms(obs);
QkComplex64 *coeffs = qk_obs_coeffs(obs);
for (size_t i = 0; i < num_terms; i++) {
printf("%f + i%f\n", coeffs[i].re, coeffs[i].im);
}안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
계수에 대한 포인터입니다.
qk_obs_indices
uint32_t *qk_obs_indices(QkObs *obs)
인덱스에 대한 포인터를 가져옵니다.
옵저버블의 인덱스를 읽고 수정하는 데 사용할 수 있습니다. 결과 포인터는 uint32_t 크기의 qk_obs_len(obs) 요소에 대해 읽을 수 있습니다.
예
uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);
QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t term_indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, term_indices, num_qubits};
qk_obs_add_term(obs, &term);
size_t len = qk_obs_len(obs);
uint32_t *indices = qk_obs_indices(obs);
for (size_t i = 0; i < len; i++) {
printf("index %i: %i\n", i, indices[i]);
}
qk_obs_free(obs);안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
인덱스에 대한 포인터입니다.
qk_obs_boundaries
size_t *qk_obs_boundaries(QkObs *obs)
경계라는 용어에 대한 포인터를 가져옵니다.
옵저버블의 용어 경계를 읽고 수정하는 데 사용할 수 있습니다. 결과 포인터는 size_t 크기의 qk_obs_num_terms(obs) + 1 요소에 대해 읽을 수 있습니다.
예
uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);
QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};
qk_obs_add_term(obs, &term);
size_t num_terms = qk_obs_num_terms(obs);
size_t *boundaries = qk_obs_boundaries(obs);
for (size_t i = 0; i < num_terms + 1; i++) {
printf("boundary %i: %i\n", i, boundaries[i]);
}안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
경계를 가리키는 포인터입니다.
qk_obs_bit_terms
QkBitTerm *qk_obs_bit_terms(QkObs *obs)
비트 용어에 대한 포인터를 가져옵니다.
옵저버블의 비트 용어를 읽고 수정하는 데 사용할 수 있습니다. 결과 포인터는 uint8_t 크기의 qk_obs_len(obs) 요소에 대해 읽을 수 있습니다.
예
uint32_t num_qubits = 100;
QkObs *obs = qk_obs_zero(num_qubits);
QkComplex64 coeff = {1, 0};
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t indices[3] = {0, 1, 2};
QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits};
qk_obs_add_term(obs, &term);
size_t len = qk_obs_len(obs);
QkBitTerm *bits = qk_obs_bit_terms(obs);
for (size_t i = 0; i < len; i++) {
printf("bit term %i: %i\n", i, bits[i]);
}
qk_obs_free(obs);안전
'Behavior is undefined'는 유효하지 obs 않거나 null이 아닌 포인터가 아니거나, 결과 QkBitTerm 포인터에 유효하지 QkObs 않은 값이 기록된 경우입니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
비트 용어에 대한 포인터입니다.
qk_obs_multiply
QkObs *qk_obs_multiply(const QkObs *obs, const QkComplex64 *coeff)
관측 가능 항목에 복소수 계수를 곱합니다.
예
QkObs *obs = qk_obs_identity(100);
QkComplex64 coeff = {2, 0};
QkObs *result = qk_obs_multiply(obs, &coeff);안전
다음 중 하나라도 위반하는 경우 동작이 정의되지 않습니다
obs는 널이 아닌 유효한 포인터입니다QkObscoeff는 널이 아닌 유효한 포인터입니다QkComplex64
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
- coeff - 관측값에 곱할 계수입니다.
리턴
결과에 대한 obs * coeff포인터.
qk_obs_multiply_inplace
void qk_obs_multiply_inplace(QkObs *obs, const QkComplex64 *coeff)
현재 위치의 관측값에 복소수 계수를 곱합니다.
예
QkObs *obs = qk_obs_identity(100);
QkComplex64 coeff = {2, 0};
qk_obs_multiply_inplace(obs, &coeff);안전
다음 중 하나라도 위반하는 경우 동작이 정의되지 않습니다
obs는 널이 아닌 유효한 포인터입니다QkObscoeff는 널이 아닌 유효한 포인터입니다QkComplex64
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
- coeff - 관측값에 곱할 계수입니다.
qk_obs_add
QkObs *qk_obs_add(const QkObs *left, const QkObs *right)
두 개의 관찰 항목을 추가합니다.
예
QkObs *left = qk_obs_identity(100);
QkObs *right = qk_obs_zero(100);
QkObs *result = qk_obs_add(left, right);안전
left 또는 right 이 QkObs\ s에 대한 유효하지 않은 널이 아닌 포인터인 경우 동작이 정의되지 않습니다.
매개변수
- 왼쪽 - 왼쪽 관찰 가능 영역에 대한 포인터입니다.
- 오른쪽 - 오른쪽 관찰 가능 영역에 대한 포인터입니다.
리턴
결과에 대한 포인터 left + right.
qk_obs_add_inplace
void qk_obs_add_inplace(QkObs *left, const QkObs *right)
기존의 observable에 새로운 observable을 추가합니다.
예
QkObs *left = qk_obs_identity(100);
QkObs *right = qk_obs_zero(100);
qk_obs_add_inplace(left, right);안전
left 또는 right 이 QkObs\ s에 대한 유효하지 않은 널이 아닌 포인터인 경우 동작이 정의되지 않습니다.
매개변수
- 왼쪽 - 왼쪽 관찰 가능 영역에 대한 포인터입니다.
- 오른쪽 - 오른쪽 관찰 가능 영역에 대한 포인터입니다.
qk_obs_scaled_add
QkObs *qk_obs_scaled_add(const QkObs *left, const QkObs *right, const QkComplex64 *factor)
두 개의 관측 변수를 추가하고, 오른쪽 관측 변수의 계수를 조정합니다.
예
QkObs *left = qk_obs_zero(100);
QkObs *right = qk_obs_identity(100);
QkComplex64 factor = {2, 0};
QkObs *result = qk_obs_scaled_add(left, right, &factor);안전
left 또는 right 이 QkObs\ s에 대한 유효하지 않은 널이 아닌 포인터인 경우 동작이 정의되지 않습니다.
매개변수
- 왼쪽 - 왼쪽 관찰 가능 영역에 대한 포인터입니다.
- 오른쪽 - 오른쪽 관찰 가능 영역에 대한 포인터입니다.
- 계수 – 계수에 곱할 계수.
리턴
결과를 가리키는 소유 left + factor * right 포인터.
qk_obs_scaled_add_inplace
void qk_obs_scaled_add_inplace(QkObs *left, const QkObs *right, const QkComplex64 *factor)
기존의 관측 가능 객체에 스케일링된 관측 가능 객체를 추가합니다.
예
QkObs *left = qk_obs_zero(100);
QkObs *right = qk_obs_identity(100);
QkComplex64 factor = {2, 0};
qk_obs_scaled_add_inplace(left, right, &factor);안전
left 또는 right 이 QkObs\ s에 대한 유효하지 않은 널이 아닌 포인터인 경우 동작이 정의되지 않습니다.
매개변수
- 왼쪽 - 왼쪽 관찰 가능 영역에 대한 포인터입니다.
- 오른쪽 - 오른쪽 관찰 가능 영역에 대한 포인터입니다.
- 계수 – 계수에 곱할 계수.
qk_obs_compose
QkObs *qk_obs_compose(const QkObs *first, const QkObs *second)
두 개의 관측값을 구성(곱하기)합니다.
예
QkObs *first = qk_obs_zero(100);
QkObs *second = qk_obs_identity(100);
QkObs *result = qk_obs_compose(first, second);안전
first 또는 second 이 QkObs\ s에 대한 유효하지 않은 널이 아닌 포인터인 경우 동작이 정의되지 않습니다.
매개변수
- 첫째 - 하나의 관찰 가능.
- 둘째 - 다른 관찰 가능.
리턴
first.compose(second) 는 행렬 곱셈의 관점에서 관찰 가능한 result = second @ first, @ 과 동일합니다.
qk_obs_compose_map
QkObs *qk_obs_compose_map(const QkObs *first, const QkObs *second, const uint32_t *qargs)
사용자 지정 큐비트 순서에 따라 두 개의 관측값을 구성(곱하기)합니다.
특히, 크기가 다른 두 개의 관측값을 구성할 수 있습니다.
예
QkObs *first = qk_obs_zero(100);
QkObs *second = qk_obs_identity(100);
QkObs *result = qk_obs_compose(first, second);안전
이 함수를 안전하게 호출하려면
first와second는QkObs\ s에 대한 널이 아닌 유효한 포인터여야 합니다qargs는qk_obs_num_qubits(second)요소(second의 큐비트 수를 의미)에 대해 읽을 수 있는uint32_t배열을 가리켜야 합니다
매개변수
- 첫째 - 하나의 관찰 가능.
- 둘째 - 다른 관찰 가능. 큐비트 수는
qargs의 길이와 일치해야 합니다. - qargs -
second의 인덱스와 연결할first의 인덱스를 지정하는 쿼비트 인자입니다.
리턴
first.compose(second) 는 행렬 곱셈의 관점에서 관찰 가능한 result = second @ first, @ 과 동일합니다.
qk_obs_apply_layout
QkExitCode qk_obs_apply_layout(QkObs *obs, const uint32_t *layout, uint32_t num_qubits)
옵저버블에 새 큐비트 레이아웃을 적용합니다.
레이아웃은 새 인덱스의 배열 layout 로 설정되며, 현재 인덱스 i 의 큐비트가 인덱스 layout[i] 로 레이블이 변경되도록 지정합니다. 옵저버블이 작동하는 큐비트 수는 현재 옵저버블보다 큰 num_qubits 을 설정하여 확장할 수 있습니다.
예
이 인터페이스를 사용하면 큐비트 인덱스의 레이블을 다시 지정하고 확장할 수 있습니다:
QkObs *obs = qk_obs_zero(4);
// add a term to the observable
QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z};
uint32_t qubits[3] = {1, 2, 3};
complex double coeff = 1;
QkObsTerm term = {coeff, 3, bit_terms, qubits, 4};
qk_obs_add_term(obs, &term);
uint32_t layout[3] = {0, 10, 9}; // qubit mapping is: 0->0, 1->10, 2->9
uint32_t num_output_qubits = 11;
QkExitCode exit = qk_obs_apply_layout(obs, layout, num_output_qubits);컴파일러 워크플로에서 이 함수는 트랜스파일러 패스에서 얻은 QkTranspileLayout* (다음 예제에서는 transpile_layout )를 적용하는 데 편리하게 사용할 수 있습니다:
// get the number of output qubits
uint32_t num_output_qubits = qk_transpile_layout_num_output_qubits(transpile_layout);
// get the layout including the ancillas (hence the ``false`` in the function call)
uint32_t *layout = malloc(sizeof(uint32_t) * num_output_qubits);
qk_transpile_layout_final_layout(transpile_layout, false, layout);
// apply the layout
QkExitCode exit = qk_obs_apply_layout(obs, layout, num_output_qubits);
// free the layout array
free(layout);안전
obs 가 QkObs 에 대한 유효하고 널이 아닌 포인터가 아니거나 layout 가 qk_obs_num_qubits(obs) 의 연속된 요소 시퀀스에 대한 유효하고 널이 아닌 포인터가 아닌 경우 동작이 정의되지 않습니다 uint32_t.
매개변수
- obs - 관찰 가능 항목에 대한 포인터로, 성공 시 이 관찰 가능 항목이 제자리에서 수정됩니다. 종료 코드를 확인하여 레이아웃이 올바르게 적용되었는지 확인합니다.
- 레이아웃 - 레이아웃에 대한 포인터입니다. 포인터는
uint32_t유형의qk_obs_num_qubits(obs)요소에 대한 배열을 가리켜야 합니다. 각 요소는[0, num_qubits)의 값을 가져야 합니다. - 숫자_큐비트 - 출력 큐비트 수입니다.
리턴
종료 코드입니다.
QkExitCode_Success성공 시QkExitCode_DuplicteIndexError중복 큐비트 인덱스가 발견된 경우QkExitCode_MismatchedQubitsnum_qubits이 관찰 가능한 큐비트 수보다 작으면QkExitCode_IndexError의 유효하지 않은 값과 같은 다른 인덱스 오류를 확인하려면layout.
qk_obs_canonicalize
QkObs *qk_obs_canonicalize(const QkObs *obs, double tol)
관측 가능 영역의 정식 표현을 계산합니다.
예
QkObs *iden = qk_obs_identity(100);
QkObs *two = qk_obs_add(iden, iden);
double tol = 1e-6;
QkObs *canonical = qk_obs_canonicalize(two, tol);안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
- tol - 계수가 0으로 간주되는 허용 오차 범위입니다.
리턴
관측 가능 영역의 정식 표현입니다.
qk_obs_copy
QkObs *qk_obs_copy(const QkObs *obs)
관찰 항목을 복사합니다.
예
QkObs *original = qk_obs_identity(100);
QkObs *copied = qk_obs_copy(original);안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
매개변수
- obs - 관찰 가능 항목에 대한 포인터입니다.
리턴
관찰 가능 항목의 복사본에 대한 포인터입니다.
qk_obs_equal
bool qk_obs_equal(const QkObs *obs, const QkObs *other)
두 관측값의 동일성을 비교합니다.
이는 수학적 동등성을 비교하는 것이 아니라 데이터 동등성을 비교한다는 점에 유의하세요. 즉, 두 관측값은 동일한 관측값을 나타내지만 동일하게 비교할 수는 없습니다.
예
QkObs *observable = qk_obs_identity(100);
QkObs *other = qk_obs_identity(100);
bool are_equal = qk_obs_equal(observable, other);안전
obs 또는 other 이 QkObs\ s에 대한 유효하지 않은 널이 아닌 포인터인 경우 동작이 정의되지 않습니다.
매개변수
- 관찰 - 하나의 관찰 가능 항목에 대한 포인터입니다.
- 기타 - 다른 관찰 가능 항목에 대한 포인터입니다.
리턴
true 관측값이 같으면 false , 그렇지 않으면.
qk_obs_str
char *qk_obs_str(const QkObs *obs)
QkObs 의 문자열 표현을 반환합니다.
예
QkObs *obs = qk_obs_identity(100);
char *string = qk_obs_str(obs);
qk_str_free(string);
qk_obs_free(obs);안전
동작이 정의되지 않았습니다 obs 은 QkObs 에 대한 유효한 널이 아닌 포인터가 아닙니다.
문자열은 일반적인 C 해제로는 해제할 수 없으며 qk_str_free 을 사용하여 문자열이 사용하는 메모리를 해제해야 합니다. qk_str_free 을 호출하지 않으면 메모리 누수가 발생할 수 있습니다.
값을 변경할 수는 있지만 문자열이 반환된 후에는 문자열 내부 어딘가에 널 바이트를 쓰거나 마지막 바이트를 제거하여 문자열의 길이를 변경하지 마세요.
매개변수
- 관찰 - 문자열을 가져올
QkObs에 대한 포인터입니다.
리턴
에 대한 문자열 표현의 널로 끝나는 문자 배열에 대한 포인터입니다 obs
qk_str_free
void qk_str_free(char *string)
문자열 표현을 해제합니다.
안전
str 가 qk_obs_str 또는 qk_obsterm_str 에서 반환하는 포인터가 아닌 경우 동작이 정의되지 않습니다.
매개변수
- 문자열 -
qk_obs_str또는qk_obsterm_str에서 반환된 문자열 표현에 대한 포인터입니다.
qk_obs_to_python
PyObject *qk_obs_to_python(QkObs *obs)
객체의 QkObs 소유권을 Python 에 전달합니다.
이 함수를 호출한 후에는 QkObs 포인터를 사용하는 것이 안전하지 않습니다. 특히, 이를 지우거나 해제하려고 시도해서는 안 됩니다. 호출자는 해당 객체를 소유하고 QkObs있어야 하며, 빌린 참조를 가지고 있어서는 안 됩니다(예를 들어 qk_obs_borrow_from_python , 에서 가져온 QkObs * 객체는 소유권이 없습니다).
안전
호출자는 Python 인터프리터에 연결되어 있어야 합니다. 가 초기화되고 소유권이 있는 에 대한 유효한 비공백 포인터가 QkObs 아닌 obs 경우 동작이 정의되지 않습니다.
매개변수
- obs – 소유된 객체.
리턴
해당 객체에 대한 Python 참조.
qk_obs_borrow_from_python
QkObs *qk_obs_borrow_from_python(PyObject *ob)
Python 객체에서 QkObs 포인터를 가져옵니다.
이 코드는 Python 참조를 가져와, 해당 참조가 올바른 유형일 경우 그 QkObs 포인터를 추출합니다. 반환된 포인터는 해당 ob 포인터에서 빌려온 것입니다. 의 유형이 올바르지 않은 PyObject 경우, 반환 값은 이 NULL 되며 Python 인터프리터의 예외 상태가 설정됩니다.
이 함수를 호출하려면 Python 인터프리터가 연결되어 있어야 합니다.
또한 를 사용할 수도 있습니다 qk_obs_convert_from_python. 이는 논리적으로는 이 함수와 완전히 동일하지만, Python 변환 함수 계열에 PyArg_Parse* 대한 “변환기” 함수로 직접 사용할 수 있습니다.
안전
호출자는 Python 인터프리터에 연결되어 있어야 합니다. 가 Python 객체를 가리키는 유효한 비공백 포인터가 아닌 ob 경우 동작이 정의되지 않습니다.
매개변수
- ob – 차용된 Python 객체.
리턴
네이티브 객체에 대한 포인터이거나, NULLPython 객체의 유형이 올바르지 않은 경우.
qk_obs_convert_from_python
int qk_obs_convert_from_python(PyObject *object, void *address)
Python 객체에서 QkObs 포인터를 가져옵니다.
이 코드는 Python 참조를 가져와, 해당 QkObs 포인터가 올바른 유형인 경우 이를 address``로 추출합니다. 반환된 포인터는 해당 object 포인터에서 빌려온 것입니다. 의 PyObject 유형이 올바르지 않은 경우, 반환 값은 1이 되며, Python 인터프리터의 예외 상태가 설정되고 는 변경되지 address 않습니다.
이 함수를 호출하려면 Python 인터프리터가 연결되어 있어야 합니다.
또한 를 qk_obs_borrow_from_python사용할 수도 있는데, 이는 논리적으로는 이와 완전히 동일하지만 직접 사용할 때 더 자연스러운 시그니처를 갖습니다.
안전
호출자는 Python 인터프리터에 연결되어 있어야 합니다. 가 유효한 null이 아닌 Python 객체 포인터가 object 아니거나, 가 올바른 유형의 쓰기 가능한 address 데이터에 대한 포인터가 아닌 경우 동작이 정의되지 않습니다.
매개변수
- 객체 – 빌려온 Python 객체.
- 주소 – 출력을 기록할 위치.
리턴
성공 시 1, 실패 시 0.