

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# OpenQASM 3.0으로 회로 실행
<a name="braket-openqasm"></a>

 Amazon Braket은 이제 게이트 기반 양자 디바이스 및 시뮬레이터에 대해 [OpenQASM 3.0](https://openqasm.com/)을 지원합니다. 이 사용자 가이드는 Braket에서 지원하는 OpenQASM 3.0의 부분 집합에 대한 정보를 제공합니다. Braket 고객은 이제 [SDK](braket-constructing-circuit.md)를 사용하여 Braket 회로를 제출하거나 [Amazon Braket API](https://docs.aws.amazon.com/braket/latest/APIReference/Welcome.html) 및 [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python)를 사용하여 모든 게이트 기반 디바이스에 OpenQASM 3.0 문자열을 직접 제공할 수 있습니다.

이 가이드의 주제에서는 다음 양자 작업을 완료하는 방법에 대한 다양한 예제를 안내합니다.
+  [다양한 Braket 디바이스에서 OpenQASM 양자 작업 생성 및 제출](braket-openqasm-create-submit-task.md) 
+  [지원되는 연산 및 결과 유형에 액세스](braket-openqasm-device-support.md#braket-openqasm-supported-operations-results-result-types) 
+  [OpenQASM으로 노이즈 시뮬레이션](braket-openqasm-noise-simulation.md) 
+  [OpenQASM으로 축어적 컴파일 사용](braket-openqasm-verbatim-compilation.md) 
+  [OpenQASM 문제 해결](https://docs.aws.amazon.com/braket/latest/developerguide/braket-troubleshooting-openqasm.html) 

또한 이 가이드에서는 Braket의 OpenQASM 3.0으로 구현할 수 있는 특정 하드웨어별 기능과 추가 리소스에 대한 링크를 소개합니다.

**Topics**
+ [OpenQASM 3.0이란 무엇입니까?](#braket-openqasm-what-is)
+ [OpenQASM 3.0을 사용해야 하는 시기](#braket-openqasm-when-to-use)
+ [OpenQASM 3.0 작동 방식](#braket-openqasm-how-it-works)
+ [사전 조건](#braket-openqasm-prerequisites)
+ [Braket은 어떤 OpenQASM 기능을 지원하나요?](braket-openqasm-supported-features.md)
+ [예제 OpenQASM 3.0 양자 작업 생성 및 제출](braket-openqasm-create-submit-task.md)
+ [다양한 Braket 디바이스에서의 OpenQASM에 대한 지원](braket-openqasm-device-support.md)
+ [OpenQASM 3.0으로 노이즈 시뮬레이션](braket-openqasm-noise-simulation.md)
+ [OpenQASM 3.0을 사용한 Qubit 재배선](braket-openqasm-rewire-qubits.md)
+ [OpenQASM 3.0을 사용한 축어적 컴파일](braket-openqasm-verbatim-compilation.md)
+ [Braket 콘솔](#braket-openqasm-braket-console)
+ [추가 리소스](#braket-openqasm-more-resources)
+ [OpenQASM 3.0을 사용한 기울기 계산](braket-openqasm-computing-gradients.md)
+ [OpenQASM 3.0을 사용한 특정 큐비트 측정](braket-openqasm-measure-qubits.md)

## OpenQASM 3.0이란 무엇입니까?
<a name="braket-openqasm-what-is"></a>

Open Quantum Assembly Language(OpenQASM)는 양자 명령을 위한 [중간 표현](https://en.wikipedia.org/wiki/Intermediate_representation)입니다. OpenQASM은 오픈 소스 프레임워크이며 게이트 기반 디바이스의 양자 프로그램 사양에 널리 사용됩니다. OpenQASM을 통해 사용자는 양자 계산의 구성 요소를 형성하는 양자 게이트 및 측정 연산을 프로그래밍할 수 있습니다. OpenQASM의 이전 버전(2.0)은 여러 양자 프로그래밍 라이브러리에서 기본 프로그램을 설명하는 데 사용되었습니다.

새 버전의 OpenQASM(3.0)은 이전 버전을 확장하여 최종 사용자 인터페이스와 하드웨어 설명 언어 간의 격차를 해소하기 위해 펄스 수준 제어, 게이트 타이밍, 고전적 제어 흐름과 같은 더 많은 기능을 포함합니다. 현재 버전 3.0에 대한 세부 정보 및 사양은 GitHub [OpenQASM 3.x Live Specification](https://github.com/openqasm/openqasm)에서 확인할 수 있습니다. OpenQASM의 향후 개발은 OpenQASM 3.0 [기술 운영 위원회](https://aws.amazon.com/blogs/quantum-computing/aws-joins-the-openqasm-3-0-technical-steering-committee/)에서 관리하며,이 위원회 AWS 는 IBM, Microsoft 및 University of Innsbruck과 함께 회원입니다.

## OpenQASM 3.0을 사용해야 하는 시기
<a name="braket-openqasm-when-to-use"></a>

OpenQASM은 아키텍처에 구애받지 않는 저수준 제어 기능을 통해 양자 프로그램을 지정하는 표현적 프레임워크를 제공하므로, 여러 게이트 기반 디바이스에 걸쳐 표현 수단으로 적합합니다. OpenQASM에 대한 Braket 지원은 게이트 기반 양자 알고리즘 개발을 위한 일관된 접근 방식으로의 채택을 촉진하여 사용자가 여러 프레임워크에서 라이브러리를 학습하고 유지할 필요성을 줄여줍니다.

OpenQASM 3.0에 기존 프로그램 라이브러리가 있는 경우 이러한 회로를 완전히 다시 쓰는 대신 Braket에서 사용하도록 조정할 수 있습니다. 또한 연구원과 개발자는 OpenQASM 기반 알고리즘 개발을 지원하는 타사 라이브러리를 점점 더 많이 활용할 수 있게 되는 이점을 누릴 수 있습니다.

## OpenQASM 3.0 작동 방식
<a name="braket-openqasm-how-it-works"></a>

Braket의 OpenQASM 3.0 지원은 현재 중간 표현과 기능 패리티를 제공합니다. 즉, Braket API를 사용하여 하드웨어 디바이스 및 온디맨드 시뮬레이터에서 현재 수행할 수 있는 모든 작업을 Braket을 통해 OpenQASM으로 수행할 수 있습니다. 현재 Braket의 디바이스에 회로가 제공되는 방식과 유사한 방식으로 모든 게이트 기반 디바이스에 OpenQASM 문자열을 직접 제공하여 OpenQASM 3.0 프로그램을 실행할 수 있습니다. Braket 사용자는 OpenQASM 3.0을 지원하는 타사 라이브러리를 통합할 수도 있습니다. 이 가이드의 나머지 부분에서는 Braket에서 사용할 OpenQASM 표현을 개발하는 방법을 자세히 설명합니다.

## 사전 조건
<a name="braket-openqasm-prerequisites"></a>

Amazon Braket에서 OpenQASM 3.0을 사용하려면 [Amazon Braket Python Schema](https://github.com/aws/amazon-braket-schemas-python) 버전 v1.8.0과 [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) 버전 v1.17.0 이상이 있어야 합니다.

Amazon Braket을 처음 사용하는 경우 Amazon Braket을 활성화해야 합니다. 지침은 [Amazon Braket 활성화](https://docs.aws.amazon.com/braket/latest/developerguide/braket-enable-overview.html)를 참조하세요.

# Braket은 어떤 OpenQASM 기능을 지원하나요?
<a name="braket-openqasm-supported-features"></a>

다음 섹션에는 Braket에서 지원하는 OpenQASM 3.0 데이터 유형, 문 및 pragma 명령이 나열되어 있습니다.

**Topics**
+ [지원되는 OpenQASM 데이터 유형](#braket-openqasm-supported-features-datatypes)
+ [지원되는 OpenQASM 문](#braket-openqasm-supported-features-statements)
+ [Braket OpenQASM pragma](#braket-openqasm-supported-features-pragmas)
+ [로컬 시뮬레이터에서의 OpenQASM에 대한 고급 기능 지원](#braket-openqasm-supported-features-advanced-feature-local-simulator)
+ [OpenPulse에서 지원되는 연산 및 문법](#braket-openpulse-supported-operations-grammar)

## 지원되는 OpenQASM 데이터 유형
<a name="braket-openqasm-supported-features-datatypes"></a>

Amazon Braket은 다음과 같은 OpenQASM 데이터 유형을 지원합니다.
+ (가상 및 물리적) 큐비트 인덱스에는 음이 아닌 정수가 사용됩니다.
  +  `cnot q[0], q[1];` 
  +  `h $0;` 
+ 게이트 회전 각도에는 부동 소수점 숫자 또는 상수를 사용할 수 있습니다.
  +  `rx(-0.314) $0;` 
  +  `rx(pi/4) $0;` 

**참고**  
pi는 OpenQASM의 기본 제공 상수이며 파라미터 이름으로 사용할 수 없습니다.
+ 복소수 배열(허수부에 대한 OpenQASM `im` 표기법 사용)은 일반적인 에르미트 관찰 가능 항목을 정의하기 위한 결과 유형 pragma와 단위 pragma에서 허용됩니다.
  +  `#pragma braket unitary [[0, -1im], [1im, 0]] q[0]` 
  +  `#pragma braket result expectation hermitian([[0, -1im], [1im, 0]]) q[0]` 

## 지원되는 OpenQASM 문
<a name="braket-openqasm-supported-features-statements"></a>

Amazon Braket은 다음과 같은 OpenQASM 문을 지원합니다.
+  `Header: OPENQASM 3;` 
+ 클래식 비트 선언:
  +  `bit b1;`(동등하게, `creg b1;`)
  +  `bit[10] b2;`(동등하게, `creg b2[10];`)
+ 큐비트 선언:
  +  `qubit b1;`(동등하게, `qreg b1;`)
  +  `qubit[10] b2;`(동등하게, `qreg b2[10];`)
+ 배열 내 인덱싱: `q[0]` 
+ 입력: `input float alpha;` 
+ 물리적 qubits의 사양: `$0` 
+ 디바이스에서 지원되는 게이트 및 연산:
  +  `h $0;` 
  +  `iswap q[0], q[1];` 

**참고**  
디바이스의 지원되는 게이트는 OpenQASM 작업에 대한 디바이스 속성에서 확인할 수 있습니다. 이러한 게이트를 사용하는 데 게이트 정의가 필요하지 않습니다.
+ 축어적 상자 문. 현재, 상자 기간 표기법은 지원되지 않습니다. 축어적 상자에는 네이티브 게이트와 물리적 qubits가 필요합니다.

```
#pragma braket verbatim
box{
    rx(0.314) $0;
}
```
+ qubits 또는 전체 qubit 레지스터에 대한 측정 및 측정 할당입니다.
  +  `measure $0;` 
  +  `measure q;` 
  +  `measure q[0];` 
  +  `b = measure q;` 
  +  `measure q → b;` 
+ 장벽 문은 장벽 경계에서 게이트 재정렬 및 최적화를 방지하여 회로 컴파일 및 실행을 명시적으로 제어할 수 있습니다. 또한 실행 중에 엄격한 시간 순서를 적용하여 후속 작업이 시작되기 전에 모든 작업이 완료되도록 합니다.
  +  `barrier;` 
  +  `barrier q[0], q[1];` 
  +  `barrier $3, $6;` 

## Braket OpenQASM pragma
<a name="braket-openqasm-supported-features-pragmas"></a>

Amazon Braket은 다음과 같은 OpenQASM pragma 명령을 지원합니다.
+ 노이즈 pragma
  +  `#pragma braket noise bit_flip(0.2) q[0]` 
  +  `#pragma braket noise phase_flip(0.1) q[0]` 
  +  `#pragma braket noise pauli_channel` 
+ 축어적 pragma
  +  `#pragma braket verbatim` 
+ 결과 유형 pragma
  + 기저 불변 결과 유형:
    + 상태 벡터: `#pragma braket result state_vector` 
    + 밀도 행렬: `#pragma braket result density_matrix` 
  + 기울기 계산 pragma:
    + 수반 기울기: `#pragma braket result adjoint_gradient expectation(2.2 * x[0] @ x[1]) all` 
  + Z 기저 결과 유형:
    + 진폭: `#pragma braket result amplitude "01"` 
    + 확률: `#pragma braket result probability q[0], q[1]` 
  + 기저 회전 결과 유형
    + 기대값: `#pragma braket result expectation x(q[0]) @ y([q1])` 
    + 분산: `#pragma braket result variance hermitian([[0, -1im], [1im, 0]]) $0` 
    + 샘플: `#pragma braket result sample h($1)` 

**참고**  
OpenQASM 3.0은 OpenQASM 2.0과 역호환되므로 2.0을 사용하여 작성된 프로그램은 Braket에서 실행할 수 있습니다. 그러나 Braket에서 지원하는 OpenQASM 3.0의 기능은 `qreg` vs `creg` 및 `qubit` vs `bit`와 같이 약간의 구문 차이가 있습니다. 측정 구문에도 차이가 있으므로 올바른 구문으로 뒷받침되어야 합니다.

## 로컬 시뮬레이터에서의 OpenQASM에 대한 고급 기능 지원
<a name="braket-openqasm-supported-features-advanced-feature-local-simulator"></a>

`LocalSimulator`는 Braket의 QPU 또는 온디맨드 시뮬레이터의 일부로 제공되지 않는 고급 OpenQASM 기능을 지원합니다. 다음 기능 목록은 `LocalSimulator`에서만 지원됩니다.
+ 게이트 한정자
+ OpenQASM 기본 제공 게이트
+ 고전적 변수
+ 고전적 연산
+ 사용자 지정 게이트
+ 고전적 제어
+ QASM 파일
+ 서브루틴

각 고급 기능의 예제는 이 [샘플 노트북](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Advanced_OpenQASM_Programs_with_the_Local_Simulator.ipynb)을 참조하세요. 전체 OpenQASM 사양은 [OpenQASM 웹 사이트](https://openqasm.com/language/index.html)를 참조하세요.

## OpenPulse에서 지원되는 연산 및 문법
<a name="braket-openpulse-supported-operations-grammar"></a>

 **지원되는 OpenPulse 데이터 유형** 

Cal 블록:

```
cal {
    ...
}
```

Defcal 블록:

```
// 1 qubit
defcal x $0 {
...
}

// 1 qubit w. input parameters as constants
defcal my_rx(pi) $0 {
...
}

// 1 qubit w. input parameters as free parameters
defcal my_rz(angle theta) $0 {
...
}

// 2 qubit (above gate args are also valid)
defcal cz $1, $0 {
...
}
```

프레임:

```
frame my_frame = newframe(port_0, 4.5e9, 0.0);
```

파형:

```
// prebuilt
waveform my_waveform_1 = constant(1e-6, 1.0);

//arbitrary
waveform my_waveform_2 = {0.1 + 0.1im, 0.1 + 0.1im, 0.1, 0.1};
```

 **사용자 지정 게이트 보정 예제:** 

```
cal {
    waveform wf1 = constant(1e-6, 0.25);
}

defcal my_x $0 {
   play(wf1, q0_rf_frame);
}

defcal my_cz $1, $0 {
    barrier q0_q1_cz_frame, q0_rf_frame;
    play(q0_q1_cz_frame, wf1);
    delay[300ns] q0_rf_frame
    shift_phase(q0_rf_frame, 4.366186381749424);
    delay[300ns] q0_rf_frame;
    shift_phase(q0_rf_frame.phase, 5.916747563126659);
    barrier q0_q1_cz_frame, q0_rf_frame;
    shift_phase(q0_q1_cz_frame, 2.183093190874712);
}

bit[2] ro;
my_x $0;
my_cz $1,$0;
c[0] = measure $0;
```

 **임의 펄스 예제:** 

```
bit[2] ro;
cal {
    waveform wf1 = {0.1 + 0.1im, 0.1 + 0.1im, 0.1, 0.1};
    barrier q0_drive, q0_q1_cross_resonance;
    play(q0_q1_cross_resonance, wf1);
    delay[300ns] q0_drive;
    shift_phase(q0_drive, 4.366186381749424);
    delay[300dt] q0_drive;
   barrier q0_drive, q0_q1_cross_resonance;
   play(q0_q1_cross_resonance, wf1);
    ro[0] = capture_v0(r0_measure);
    ro[1] = capture_v0(r1_measure);
}
```

# 예제 OpenQASM 3.0 양자 작업 생성 및 제출
<a name="braket-openqasm-create-submit-task"></a>

Amazon Braket Python SDK, Boto3 또는를 사용하여 Amazon Braket 디바이스 AWS CLI 에 OpenQASM 3.0 양자 작업을 제출할 수 있습니다.

**Topics**
+ [OpenQASM 3.0 프로그램 예제](#braket-openqasm-example-program)
+ [Python SDK를 사용하여 OpenQASM 3.0 양자 작업 생성](#braket-openqasm-create-tasks-with-python-sdk)
+ [Boto3을 사용하여 OpenQASM 3.0 양자 작업 생성](#braket-openqasm-create-tasks-with-boto3)
+ [AWS CLI 를 사용하여 OpenQASM 3.0 작업 생성](#braket-openqasm-create-tasks-with-aws-cli)

## OpenQASM 3.0 프로그램 예제
<a name="braket-openqasm-example-program"></a>

OpenQASM 3.0 작업을 생성하려면, 다음 예제와 같이 [GHZ 상태](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state)를 준비하는 기본 OpenQASM 3.0 프로그램(ghz.qasm)으로 시작할 수 있습니다.

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

qubit[3] q;
bit[3] c;

h q[0];
cnot q[0], q[1];
cnot q[1], q[2];

c = measure q;
```

## Python SDK를 사용하여 OpenQASM 3.0 양자 작업 생성
<a name="braket-openqasm-create-tasks-with-python-sdk"></a>

[Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python)를 사용하여 다음 코드로 이 프로그램을 Amazon Braket 디바이스에 제출할 수 있습니다. 예제 Amazon S3 버킷 위치 “amzn-s3-demo-bucket”을 자체 Amazon S3 버킷 이름으로 바꿔야 합니다.

```
with open("ghz.qasm", "r") as ghz:
    ghz_qasm_string = ghz.read()

# Import the device module
from braket.aws import AwsDevice
# Choose the Rigetti device
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
from braket.ir.openqasm import Program

program = Program(source=ghz_qasm_string)
my_task = device.run(program)

# Specify an optional s3 bucket location and number of shots
s3_location = ("amzn-s3-demo-bucket", "openqasm-tasks")
my_task = device.run(
    program,
    s3_location,
    shots=100,
)
```

## Boto3을 사용하여 OpenQASM 3.0 양자 작업 생성
<a name="braket-openqasm-create-tasks-with-boto3"></a>

다음 예제와 같이 [AWS Python SDK for Braket(Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/braket.html)을 사용하여 OpenQASM 3.0 문자열을 이용해 양자 작업을 생성할 수도 있습니다. 다음 코드 조각은 위에서와 같이 [GHZ 상태](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state)를 준비하는 ghz.qasm을 참조합니다.

```
import boto3
import json

my_bucket = "amzn-s3-demo-bucket"
s3_prefix = "openqasm-tasks"

with open("ghz.qasm") as f:
    source = f.read()

action = {
    "braketSchemaHeader": {
        "name": "braket.ir.openqasm.program",
        "version": "1"
    },
    "source": source
}
device_parameters = {}
device_arn = "arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3"
shots = 100

braket_client = boto3.client('braket', region_name='us-west-1')
rsp = braket_client.create_quantum_task(
    action=json.dumps(
        action
    ),
    deviceParameters=json.dumps(
        device_parameters
    ),
    deviceArn=device_arn,
    shots=shots,
    outputS3Bucket=my_bucket,
    outputS3KeyPrefix=s3_prefix,
)
```

## AWS CLI 를 사용하여 OpenQASM 3.0 작업 생성
<a name="braket-openqasm-create-tasks-with-aws-cli"></a>

다음 예제와 같이 [AWS Command Line Interface (CLI)](https://aws.amazon.com/cli/)를 사용하여 OpenQASM 3.0 프로그램을 제출할 수도 있습니다.

```
aws braket create-quantum-task \
    --region "us-west-1" \
    --device-arn "arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3" \
    --shots 100 \
    --output-s3-bucket "amzn-s3-demo-bucket" \
    --output-s3-key-prefix "openqasm-tasks" \
    --action '{
        "braketSchemaHeader": {
            "name": "braket.ir.openqasm.program",
            "version": "1"
        },
        "source": $(cat ghz.qasm)
    }'
```

# 다양한 Braket 디바이스에서의 OpenQASM에 대한 지원
<a name="braket-openqasm-device-support"></a>

OpenQASM 3.0을 지원하는 디바이스의 경우 `action` 필드는 Rigetti 및 IonQ 디바이스에 대한 다음 예제와 같이 `GetDevice` 응답을 통해 새 작업을 지원합니다.

```
//OpenQASM as available with the Rigetti device capabilities
{
    "braketSchemaHeader": {
        "name": "braket.device_schema.rigetti.rigetti_device_capabilities",
        "version": "1"
    },
    "service": {...},
    "action": {
        "braket.ir.jaqcd.program": {...},
        "braket.ir.openqasm.program": {
            "actionType": "braket.ir.openqasm.program",
            "version": [
                "1"
            ],
            ….
        }
    }
}

//OpenQASM as available with the IonQ device capabilities
{
    "braketSchemaHeader": {
        "name": "braket.device_schema.ionq.ionq_device_capabilities",
        "version": "1"
    },
    "service": {...},
    "action": {
        "braket.ir.jaqcd.program": {...},
        "braket.ir.openqasm.program": {
            "actionType": "braket.ir.openqasm.program",
            "version": [
                "1"
            ],
            ….
        }
    }
}
```

펄스 제어를 지원하는 디바이스의 경우 `pulse` 필드가 `GetDevice` 응답에 표시됩니다. 다음 예제에서는 Rigetti 디바이스에 대한 이 `pulse` 필드를 보여줍니다.

```
// Rigetti
{
  "pulse": {
    "braketSchemaHeader": {
      "name": "braket.device_schema.pulse.pulse_device_action_properties",
      "version": "1"
    },
    "supportedQhpTemplateWaveforms": {
      "constant": {
        "functionName": "constant",
        "arguments": [
          {
            "name": "length",
            "type": "float",
            "optional": false
          },
          {
            "name": "iq",
            "type": "complex",
            "optional": false
          }
        ]
      },
      ...
    },
    "ports": {
      "q0_ff": {
        "portId": "q0_ff",
        "direction": "tx",
        "portType": "ff",
        "dt": 1e-9,
        "centerFrequencies": [
          375000000
        ]
      },
      ...
    },
    "supportedFunctions": {
      "shift_phase": {
        "functionName": "shift_phase",
        "arguments": [
          {
            "name": "frame",
            "type": "frame",
            "optional": false
          },
          {
            "name": "phase",
            "type": "float",
            "optional": false
          }
        ]
      },
     ...
    },
    "frames": {
      "q0_q1_cphase_frame": {
        "frameId": "q0_q1_cphase_frame",
        "portId": "q0_ff",
        "frequency": 462475694.24460185,
        "centerFrequency": 375000000,
        "phase": 0,
        "associatedGate": "cphase",
        "qubitMappings": [
          0,
          1
        ]
      },
      ...
    },
    "supportsLocalPulseElements": false,
    "supportsDynamicFrames": false,
    "supportsNonNativeGatesWithPulses": false,
    "validationParameters": {
      "MAX_SCALE": 4,
      "MAX_AMPLITUDE": 1,
      "PERMITTED_FREQUENCY_DIFFERENCE": 400000000
    }
  }
}
```

앞서 언급된 필드는 다음을 상세히 설명합니다.

 **포트:** 

QPU에 선언된 사전 제작 외부(`extern`) 디바이스 포트와 지정된 포트의 관련 속성을 설명합니다. 이 구조에 나열된 모든 포트는 사용자가 제출한 `OpenQASM 3.0` 프로그램 내에서 유효한 식별자로 사전 선언됩니다. 포트의 추가 속성은 다음과 같습니다.
+ 포트 ID(portId)
  + OpenQASM 3.0에서 식별자로 선언된 포트 이름입니다.
+ 방향(direction)
  + 포트의 방향입니다. 드라이브 포트는 펄스(direction “tx”)를 전송하는 반면, 측정 포트는 펄스(direction “rx”)를 수신합니다.
+ 포트 유형(portType)
  + 이 포트가 담당하는 작업의 유형(예: 드라이브, 캡처 또는 ff - fast-flux)입니다.
+ Dt(dt)
  + 지정된 포트에서 단일 샘플 시간 단계를 나타내는 초 단위 시간입니다.
+ 큐비트 매핑(qubitMappings)
  + 지정된 포트와 연결된 큐비트입니다.
+ 중심 주파수(centerFrequencies)
  + 포트에서 사전 선언되거나 사용자 정의된 모든 프레임에 대한 연관 중심 주파수의 목록입니다. 자세한 내용은 프레임을 참조하세요.
+ QHP 특정 속성(qhpSpecificProperties)
  + QHP 전용 포트에 대한 기존 속성을 자세히 설명하는 선택적 맵입니다.

 **프레임:** 

QPU에서 선언된 사전 제작 외부 프레임과 해당 프레임에 대한 관련 속성을 설명합니다. 이 구조에 나열된 모든 프레임은 사용자가 제출한 `OpenQASM 3.0` 프로그램 내에서 유효한 식별자로 사전 선언됩니다. 프레임의 추가 속성은 다음과 같습니다.
+ 프레임 ID(frameId)
  + OpenQASM 3.0에서 식별자로 선언된 프레임 이름입니다.
+ 포트 ID(portId)
  + 프레임에 연결된 하드웨어 포트입니다.
+ 주파수(frequency)
  + 프레임의 기본 초기 주파수입니다.
+ 중심 주파수(centerFrequency)
  + 프레임의 주파수 대역폭 중심입니다. 일반적으로 프레임은 중심 주파수 주변의 특정 대역폭으로만 조정할 수 있습니다. 따라서 주파수 조정은 중심 주파수의 지정된 델타 범위 내에서 이루어져야 합니다. 대역폭 값은 검증 파라미터에서 확인할 수 있습니다.
+ 위상(phase)
  + 프레임의 기본 초기 위상입니다.
+ 연결된 게이트(associatedGate)
  + 지정된 프레임과 연결된 게이트입니다.
+ 큐비트 매핑(qubitMappings)
  + 지정된 프레임과 연결된 큐비트입니다.
+ QHP 특정 속성(qhpSpecificProperties)
  + QHP 전용 프레임에 대한 기존 속성을 자세히 설명하는 선택적 맵입니다.

 **SupportsDynamicFrames:** 

OpenPulse `newframe` 함수를 통해 프레임을 `cal` 또는 `defcal` 블록에서 선언할 수 있는지 여부를 설명합니다. false인 경우 프레임 구조에 나열된 프레임만 프로그램 내에서 사용할 수 있습니다.

 **SupportedFunctions:** 

지정된 함수에 대해 연결된 인수, 인수 유형 및 반환 유형 외에도 디바이스에 대해 지원되는 OpenPulse 함수를 설명합니다. OpenPulse 함수의 사용 예제를 보려면 [OpenPulse 사양](https://openqasm.com/language/openpulse.html)을 참조하세요. 현재 Braket은 다음을 지원합니다.
+ shift\$1phase
  + 프레임의 위상을 지정된 값만큼 이동합니다.
+ set\$1phase
  + 프레임의 위상을 지정된 값으로 설정합니다.
+ swap\$1phases
  + 두 프레임 간에 위상을 바꿉니다.
+ shift\$1frequency
  + 프레임의 주파수를 지정된 값만큼 이동합니다.
+ set\$1frequency
  + 프레임의 주파수를 지정된 값으로 설정합니다.
+ play
  + 파형을 예약합니다.
+ capture\$1v0
  + 캡처 프레임의 값을 비트 레지스터로 반환합니다.

 **SupportedQhpTemplateWaveforms:** 

디바이스에서 사용할 수 있는 사전 빌드된 파형 함수와 관련 인수 및 유형을 설명합니다. 기본적으로 Braket Pulse는 모든 디바이스에서 다음과 같은 사전 빌드된 파형 루틴을 제공합니다.

 ** *상수* ** 

![\[파라미터 t, tau 및 iq를 갖는 상수 함수를 보여주는 수학 방정식으로, 출력은 항상 iq와 같습니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/ConstantFunction.png)


 `τ`는 파형의 길이이고 `iq`는 복소수입니다.

```
def constant(length, iq)
```

 ** *가우시안* ** 

![\[파라미터 t, tau, 시그마, A=1, ZaE=0을 갖는 가우시안 함수를 보여주는 수학 방정식입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/GaussianFunction.png)


 `τ`는 파형의 길이이고, `σ`는 가우시안의 너비이며 `A`는 진폭입니다. `ZaE`를 `True`로 설정하면 가우시안은 파형의 시작과 끝에서 0이 되도록 오프셋 및 재조정되며 최대값에서 `A`에 도달합니다.

```
def gaussian(length, sigma, amplitude=1, zero_at_edges=False)
```

 ** *DRAG 가우시안* ** 

![\[파라미터 t, tau, 시그마, 베타, A=1, ZaE=0을 갖는 DRAG 가우시안 분포에 대한 수학 방정식입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/DRAGGaussianFunction.png)


 `τ`는 파형의 길이, `σ`는 가우시안의 너비, `β`는 자유 파라미터, `A`는 진폭입니다. `ZaE`를 `True`로 설정하면 DRAG(Derivative Removal by Adiabatic Gate) 가우시안은 파형의 시작과 끝에서 0이 되도록 오프셋 및 재조정되며 실수부는 최대값에서 `A`에 도달합니다. DRAG 파형에 대한 자세한 내용은 백서 [약한 비선형 큐비트에서 누출 제거를 위한 단순 펄스](https://doi.org/10.1103/PhysRevLett.103.110501)를 참조하세요.

```
def drag_gaussian(length, sigma, beta, amplitude=1, zero_at_edges=False)
```

 ** *Erf 제곱* ** 

![\[파라미터 t, 길이, 너비, 시그마, A=1, ZaE=0을 갖는 Erf 제곱 분포에 대한 수학 방정식입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/ErfSquareFunction.PNG)


여기서 `L`은 길이이고 `W`는 파형의 너비이며 `σ`는 엣지의 상승 및 하강 속도를 정의하고 `t1​=(L−W)/2` 및 `t22=(L+W)/2`, `A`는 진폭입니다. `ZaE`를 `True`로 설정하면 가우시안은 파형의 시작과 끝에서 0이 되도록 오프셋 및 재조정되며 최대값에서 `A`에 도달합니다. 다음 방정식은 파형의 재조정된 버전입니다.

![\[파라미터 ZaE=1을 갖는 재조정된 Erf 제곱 분포에 대한 수학 방정식입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/RescaledErfSquareFunction.PNG)


여기서 `a=erf(W/2σ)` 및 `b=erf(-t1​/σ)/2+erf(t2​/σ)/2`입니다.

```
def erf_square(length, width, sigma, amplitude=1, zero_at_edges=False)
```

 **SupportsLocalPulseElements:** 

포트, 프레임 및 파형과 같은 펄스 요소를 `defcal` 블록에서 로컬로 정의할 수 있는지 여부를 설명합니다. 값이 `false`인 경우 요소를 `cal` 블록에서 정의해야 합니다.

 **SupportsNonNativeGatesWithPulses:** 

비네이티브 게이트를 펄스 프로그램과 함께 사용할 수 있는지 여부를 설명합니다. 예를 들어 사용된 큐비트에 대해 `defcal`을 통해 게이트를 먼저 정의하지 않으면 프로그램의 `H` 게이트와 같은 비네이티브 게이트를 사용할 수 없습니다. 디바이스 기능에서 네이티브 게이트 `nativeGateSet` 키 목록을 확인할 수 있습니다.

 **ValidationParameters:** 

다음을 포함하여 펄스 요소 검증 경계를 설명합니다.
+ 파형(임의 및 사전 빌드됨)의 최대 규모/최대 진폭 값
+ 제공된 중심 주파수의 최대 주파수 대역폭을 Hz 단위로 표시
+ 초 단위의 최소 펄스 길이/지속 시간
+ 초 단위의 최대 펄스 길이/지속 시간

## OpenQASM으로 지원되는 연산, 결과 및 결과 유형
<a name="braket-openqasm-supported-operations-results-result-types"></a>

각 디바이스에서 지원하는 OpenQASM 3.0 기능을 확인하려면 디바이스 기능 출력의 `action` 필드에서 `braket.ir.openqasm.program` 키를 참조하세요. 예를 들어 다음은 Braket 상태 벡터 시뮬레이터 SV1에 사용할 수 있는 지원되는 연산 및 결과 유형입니다.

```
...
  "action": {
    "braket.ir.jaqcd.program": {
      ...
    },
 "braket.ir.openqasm.program": {
      "version": [
        "1.0"
      ],
      "actionType": "braket.ir.openqasm.program",
      "supportedOperations": [
        "ccnot",
        "cnot",
        "cphaseshift",
        "cphaseshift00",
        "cphaseshift01",
        "cphaseshift10",
        "cswap",
        "cy",
        "cz",
        "h",
        "i",
        "iswap",
        "pswap",
        "phaseshift",
        "rx",
        "ry",
        "rz",
        "s",
        "si",
        "swap",
        "t",
        "ti",
        "v",
        "vi",
        "x",
        "xx",
        "xy",
        "y",
        "yy",
        "z",
        "zz"
      ],
      "supportedPragmas": [
        "braket_unitary_matrix"
      ],
      "forbiddenPragmas": [],
      "maximumQubitArrays": 1,
      "maximumClassicalArrays": 1,
      "forbiddenArrayOperations": [
        "concatenation",
        "negativeIndex",
        "range",
        "rangeWithStep",
        "slicing",
        "selection"
      ],
      "requiresAllQubitsMeasurement": true,
      "supportsPhysicalQubits": false,
      "requiresContiguousQubitIndices": true,
      "disabledQubitRewiringSupported": false,
      "supportedResultTypes": [
        {
          "name": "Sample",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 1,
          "maxShots": 100000
        },
        {
          "name": "Expectation",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 0,
          "maxShots": 100000
        },
        {
          "name": "Variance",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 0,
          "maxShots": 100000
        },
        {
          "name": "Probability",
          "minShots": 1,
          "maxShots": 100000
        },
        {
          "name": "Amplitude",
          "minShots": 0,
          "maxShots": 0
        }
        {
          "name": "AdjointGradient",
          "minShots": 0,
          "maxShots": 0
        }
      ]
    }
  },
...
```

# OpenQASM 3.0으로 노이즈 시뮬레이션
<a name="braket-openqasm-noise-simulation"></a>

OpenQASM3으로 노이즈를 시뮬레이션하려면 *pragma* 명령을 사용하여 노이즈 연산자를 추가합니다. 예를 들어 이전에 제공된 [GHZ 프로그램](braket-openqasm-create-submit-task.md#braket-openqasm-example-program)의 노이즈 있는 버전을 시뮬레이션하려면 다음 OpenQASM 프로그램을 제출할 수 있습니다.

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

qubit[3] q;
bit[3] c;

h q[0];
#pragma braket noise depolarizing(0.75) q[0] cnot q[0], q[1];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1] cnot q[1], q[2];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1]

c = measure q;
```

지원되는 모든 pragma 노이즈 연산자에 대한 사양은 다음 목록에 나와 있습니다.

```
#pragma braket noise bit_flip(<float in [0,1/2]>) <qubit>
#pragma braket noise phase_flip(<float in [0,1/2]>) <qubit>
#pragma braket noise pauli_channel(<float>, <float>, <float>)  <qubit>
#pragma braket noise depolarizing(<float in [0,3/4]>) <qubit>
#pragma braket noise two_qubit_depolarizing(<float in [0,15/16]>) <qubit>, <qubit>
#pragma braket noise two_qubit_dephasing(<float in [0,3/4]>) <qubit>, <qubit>
#pragma braket noise amplitude_damping(<float in [0,1]>) <qubit>
#pragma braket noise generalized_amplitude_damping(<float in [0,1]> <float in [0,1]>)  <qubit>
#pragma braket noise phase_damping(<float in [0,1]>) <qubit>
#pragma braket noise kraus([[<complex m0_00>, ], ...], [[<complex m1_00>, ], ...], ...) <qubit>[, <qubit>]     // maximum of 2 qubits and maximum of 4 matrices for 1 qubit, 16 for 2
```

## Kraus 연산자
<a name="braket-openqasm-kraus-operator"></a>

Kraus 연산자를 생성하려면 행렬 목록을 반복하여 행렬의 각 요소를 복소수 표현식으로 출력하면 됩니다.

Kraus 연산자를 사용할 때는 다음 사항에 유의하세요.
+ qubits의 수는 2를 초과할 수 없습니다. [스키마의 현재 정의](https://github.com/aws/amazon-braket-sdk-python/blob/0d28a8fa89263daf5d88bc706e79200d8dc091a8/src/braket/circuits/noises.py#L811-L814))는 이 제한을 설정합니다.
+ 인수 목록의 길이는 8의 배수여야 합니다. 즉, 2x2 행렬로만 구성되어야 합니다.
+ 총 길이는 22\$1num\$1qubits 행렬을 초과하지 않습니다. 즉, 1qubit의 경우 행렬이 4개이고 2qubits의 경우 행렬이 16개입니다.
+ 제공된 모든 행렬은 [완전 양성 트레이스 보존(Completely Positive Trace Preserving, CPTP)](https://github.com/aws/amazon-braket-sdk-python/blob/0d28a8fa89263daf5d88bc706e79200d8dc091a8/src/braket/circuits/quantum_operator_helpers.py#L94-L108)입니다.
+ Kraus 연산자와 그 전치 켤레의 곱은 단위 행렬에 합산되어야 합니다.

# OpenQASM 3.0을 사용한 Qubit 재배선
<a name="braket-openqasm-rewire-qubits"></a>

Amazon Braket은 Rigetti 디바이스의 OpenQASM 내에서 물리적 qubit 표기법을 지원합니다(자세한 내용은 이 [페이지](https://github.com/openqasm/openqasm/blob/main/source/language/types.rst) 참조). [나이브 재배선 전략](https://pyquil-docs.rigetti.com/en/v2.28.1/compiler.html#naive)과 함께 물리적 qubits를 사용하는 경우 qubits가 선택한 디바이스에 연결되어 있는지 확인합니다. 또는 qubit 레지스터를 대신 사용하는 경우 Rigetti 디바이스에서 PARTIAL 재배선 전략이 기본적으로 활성화됩니다.

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

h $0;
cnot $0, $1;
cnot $1, $2;

measure $0;
measure $1;
measure $2;
```

# OpenQASM 3.0을 사용한 축어적 컴파일
<a name="braket-openqasm-verbatim-compilation"></a>

Rigetti 및 IonQ와 같은 공급자가 제공하는 양자 컴퓨터에서 양자 회로를 실행할 때 컴파일러가 수정 없이 정의된 대로 정확하게 회로를 실행하도록 지시할 수 있습니다. 이 기능을 *축어적 컴파일*이라고 합니다. Rigetti 디바이스를 사용하면 전체 회로 또는 특정 부분만 보존되는 항목을 정확하게 지정할 수 있습니다. 회로의 특정 부분만 보존하려면 보존된 리전 내에서 네이티브 게이트를 사용해야 합니다. 현재, IonQ는 전체 회로에 대해 축어적 컴파일만 지원하므로 회로의 모든 명령을 축어적 상자에 포함시켜야 합니다.

OpenQASM을 사용하면 코드 상자 주위에 축어적 pragma를 명시적으로 지정할 수 있습니다. 그러면 코드 상자는 하드웨어의 저수준 컴파일 루틴에 의해 변경되지 않고 최적화되지 않은 상태로 유지됩니다. 다음 코드 예제에서는 `#pragma braket verbatim` 지시어를 사용하여 이를 달성하는 방법을 보여줍니다.

```
OPENQASM 3;

bit[2] c;

#pragma braket verbatim
box{
    rx(0.314159) $0;
    rz(0.628318) $0, $1;
    cz $0, $1;
}

c[0] = measure $0;
c[1] = measure $1;
```

예제 및 모범 사례를 포함하여 축어적 컴파일 프로세스에 대한 자세한 내용은 amazon-braket-examples github 리포지토리에서 제공되는 [축어적 컴파일](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Verbatim_Compilation.ipynb) 샘플 노트북을 참조하세요.

## Braket 콘솔
<a name="braket-openqasm-braket-console"></a>

OpenQASM 3.0 작업은 Amazon Braket 콘솔에서 사용하고 관리할 수 있습니다. 콘솔에서 OpenQASM 3.0으로 양자 작업을 제출하는 경험은 기존 양자 작업을 제출할 때와 동일합니다.

## 추가 리소스
<a name="braket-openqasm-more-resources"></a>

OpenQASM은 모든 Amazon Braket 리전에서 사용할 수 있습니다.

Amazon Braket에서 OpenQASM을 시작하기 위한 예제 노트북은 [Braket 자습서 GitHub](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Getting_Started_with_OpenQASM_on_Braket.ipynb)를 참조하세요.

# OpenQASM 3.0을 사용한 기울기 계산
<a name="braket-openqasm-computing-gradients"></a>

Amazon Braket은 `shots=0` (정확) 모드에서 실행할 때 온디맨드 시뮬레이터와 로컬 시뮬레이터 모두에서 기울기 계산을 지원합니다. 이는 수반 미분법을 사용하여 달성됩니다. 계산하려는 기울기를 지정하려면 다음 예제의 코드에 설명된 대로 적절한 pragma를 제공할 수 있습니다.

```
OPENQASM 3.0;
input float alpha;

bit[2] b;
qubit[2] q;

h q[0];
h q[1];
rx(alpha) q[0];
rx(alpha) q[1];
b[0] = measure q[0];
b[1] = measure q[1];

#pragma braket result adjoint_gradient h(q[0]) @ i(q[1]) alpha
```

모든 개별 파라미터를 명시적으로 나열하는 대신, pragma 내에서 `all` 키워드를 지정할 수도 있습니다. 이렇게 하면 나열된 모든 `input` 파라미터에 대한 기울기가 계산되므로, 파라미터 수가 매우 클 때 편리한 옵션이 될 수 있습니다. 이 경우 pragma는 다음 예제의 코드와 유사합니다.

```
#pragma braket result adjoint_gradient h(q[0]) @ i(q[1]) all
```

Amazon Braket의 OpenQASM 3.0 구현에서는 개별 연산자, 텐서 곱, 에르미트 관찰 가능 항목, `Sum` 관찰 가능 항목 등 모든 관찰 가능 항목 유형이 지원됩니다. 기울기를 계산할 때 사용할 특정 연산자는 `expectation()` 함수 내에 래핑되어야 하며, 관찰 가능 항목의 각 항이 작용하는 큐비트는 명시적으로 지정되어야 합니다.

# OpenQASM 3.0을 사용한 특정 큐비트 측정
<a name="braket-openqasm-measure-qubits"></a>

Amazon Braket에서 제공하는 로컬 상태 벡터 시뮬레이터 및 로컬 밀도 행렬 시뮬레이터는 회로 큐비트의 부분 집합을 선택적으로 측정할 수 있는 OpenQASM 프로그램 제출을 지원합니다. 흔히 부분 측정이라고 하는 이 기능을 사용하면 보다 표적화되고 효율적인 양자 계산이 가능합니다. 예를 들어 다음 코드 조각에서는 2큐비트 회로를 생성하고 첫 번째 큐비트만 측정하도록 선택할 수 있으며, 두 번째 큐비트를 측정하지 않은 상태로 둘 수 있습니다.

```
partial_measure_qasm = """
OPENQASM 3.0;
bit[1] b;
qubit[2] q;
h q[0];
cnot q[0], q[1];
b[0] = measure q[0];
"""
```

이 예제에서는 `q[0]`과 `q[1]`이라는 2개의 큐비트가 있는 양자 회로가 있지만 첫 번째 큐비트의 상태만 측정하는 데 관심이 있습니다. 이는 큐비트[0]의 상태를 측정하고 그 결과를 고전적 비트 b[0]으로 저장하는 라인 `b[0] = measure q[0]`에 의해 달성됩니다. 이 부분 측정 시나리오를 실행하려면 Amazon Braket에서 제공하는 로컬 상태 벡터 시뮬레이터에서 다음 코드를 실행할 수 있습니다.

```
from braket.devices import LocalSimulator

local_sim = LocalSimulator()
partial_measure_local_sim_task = local_sim.run(OpenQASMProgram(source=partial_measure_qasm), shots = 10)
partial_measure_local_sim_result = partial_measure_local_sim_task.result()
print(partial_measure_local_sim_result.measurement_counts)
print("Measured qubits: ", partial_measure_local_sim_result.measured_qubits)
```

작업 속성에서 `requiresAllQubitsMeasurement` 필드를 검사하여 디바이스가 부분 측정을 지원하는지 확인할 수 있습니다. `False`인 경우 부분 측정이 지원됩니다.

```
from braket.devices import Devices
            
AwsDevice(Devices.Rigetti.Ankaa3).properties.action['braket.ir.openqasm.program'].requiresAllQubitsMeasurement
```

여기서 `requiresAllQubitsMeasurement`은 `False`이며, 이는 모든 큐비트를 측정해야 하는 것은 아님을 나타냅니다.