

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

# Amazon Braket을 사용하여 양자 작업 빌드
<a name="braket-build"></a>

Braket은 간단하게 시작할 수 있는 완전관리형 Jupyter Notebook 환경을 제공합니다. Braket 노트북에는 Amazon Braket SDK를 비롯한 샘플 알고리즘, 리소스 및 개발자 도구가 사전 설치되어 있습니다. Amazon Braket SDK를 사용하면 양자 알고리즘을 빌드한 다음 단 한 줄의 코드만 변경하여 다양한 양자 컴퓨터 및 시뮬레이터에서 이를 테스트하고 실행할 수 있습니다.

**Topics**
+ [첫 번째 회로 빌드](braket-get-started-run-circuit.md)
+ [전문가 조언 받기](braket-expert-advice.md)
+ [OpenQASM 3.0으로 회로 실행](braket-openqasm.md)
+ [실험 기능 살펴보기](braket-experimental-capabilities.md)
+ [Amazon Braket의 펄스 제어](braket-pulse-control.md)
+ [아날로그 해밀토니안 시뮬레이션](braket-analog-hamiltonian-simulation.md)
+ [AWS Boto3 작업](braket-using-boto3.md)

# 첫 번째 회로 빌드
<a name="braket-get-started-run-circuit"></a>

노트북 인스턴스가 시작되고 나면, 방금 생성한 노트북을 선택하여 표준 Jupyter 인터페이스로 인스턴스를 엽니다.

![\[InService 및 URL 상태인 amazon-braket-test라는 기존 노트북 인스턴스를 보여주는 노트북 인터페이스입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/console-page.png)


Amazon Braket 노트북 인스턴스에는 Amazon Braket SDK 및 모든 종속성이 사전 설치되어 있습니다. 먼저 `conda_braket` 커널을 사용하여 새 노트북을 생성합니다.

![\[노트북, 콘솔 및 터미널, 텍스트 파일, Markdown 파일, Python 파일과 같은 기타 도구를 위한 시작 관리자 인터페이스로, conda_braket Python 환경이 강조 표시되어 있습니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/jupyter-open.png)


간단한 “Hello, world\$1”로 시작할 수 있습니다. 예. 먼저 벨 상태를 준비하는 회로를 구성한 다음, 다른 디바이스에서 해당 회로를 실행하여 결과를 얻습니다.

먼저 Amazon Braket SDK 모듈을 가져오고 simpleBRAKETlong; SDK 모듈을 정의한 다음 기본 벨 상태 회로를 정의하여' 시작'을 가져와서 시작합니다.

```
import boto3
from braket.aws import AwsDevice
from braket.devices import LocalSimulator
from braket.circuits import Circuit

# Create the circuit
bell = Circuit().h(0).cnot(0, 1)
```

다음 명령을 사용하여 회로를 시각화할 수 있습니다.

```
print(bell)
```

```
T  : │  0  │  1  │
      ┌───┐       
q0 : ─┤ H ├───●───
      └───┘   │   
            ┌─┴─┐ 
q1 : ───────┤ X ├─
            └───┘ 
T  : │  0  │  1  │
```

 **로컬 시뮬레이터에서 회로 실행** 

다음으로, 회로를 실행할 양자 디바이스를 선택합니다. Amazon Braket SDK는 신속한 프로토타이핑 및 테스트를 위한 로컬 시뮬레이터와 함께 제공됩니다. 최대 25qubits(로컬 하드웨어에 따라 다름)까지 지원되는 더 작은 회로에는 로컬 시뮬레이터를 사용하는 것이 좋습니다.

로컬 시뮬레이터를 인스턴스화하려면 다음과 같이 한 다음,

```
# Instantiate the local simulator
local_sim = LocalSimulator()
```

회로를 실행합니다.

```
# Run the circuit
result = local_sim.run(bell, shots=1000).result()
counts = result.measurement_counts
print(counts)
```

다음과 같은 결과가 표시되어야 합니다.

```
Counter({'11': 503, '00': 497})
```

준비한 특정 벨 상태는 예상대로 \$100⟩ 및 \$111⟩의 동등한 중첩이며 측정 결과로서 00 및 11의 분포가 거의 동등(최대 shot 노이즈)합니다.

 **온디맨드 시뮬레이터에서 회로 실행** 

또한 Amazon Braket은 대규모 회로 실행을 위한 온디맨드 고성능 시뮬레이터 SV1에 대한 액세스를 제공합니다. SV1은 최대 34qubits의 양자 회로 시뮬레이션을 허용하는 온디맨드 상태 벡터 시뮬레이터입니다. SV1에 대한 자세한 내용은 [지원되는 디바이스](braket-devices.md) 섹션 및 AWS 콘솔에서 확인할 수 있습니다. SV1(및 TN1 또는 QPU)에서 양자 작업을 실행할 때 양자 작업의 결과는 계정의 S3 버킷에 저장됩니다. 버킷을 지정하지 않으면 Braket SDK가 기본 버킷 `amazon-braket-{region}-{accountID}`를 생성합니다. 자세한 내용은 [Amazon Braket에 대한 액세스 관리](braket-manage-access.md)를 참조하세요.

**참고**  
다음 예제가 `amazon-braket-s3-demo-bucket`을 버킷 이름으로 표시하는 실제 기존 버킷 이름을 입력합니다. Amazon Braket의 버킷 이름은 항상 `amazon-braket-`으로 시작하며 그 뒤에 추가한 다른 식별 문자가 옵니다. S3 버킷을 설정하는 방법에 대한 자세한 내용은 [Amazon S3 시작하기](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html)를 참조하세요.

```
# Get the account ID
aws_account_id = boto3.client("sts").get_caller_identity()["Account"]

# The name of the bucket
my_bucket = "amazon-braket-s3-demo-bucket"

# The name of the folder in the bucket
my_prefix = "simulation-output"
s3_folder = (my_bucket, my_prefix)
```

SV1에서 회로를 실행하려면 이전에 선택한 S3 버킷의 위치를 `.run()` 직접 호출에서 위치 인수로 제공해야 합니다.

```
# Choose the cloud-based on-demand simulator to run your circuit
device = AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")

# Run the circuit
task = device.run(bell, s3_folder, shots=100)

# Display the results
print(task.result().measurement_counts)
```

Amazon Braket 콘솔은 양자 작업에 대한 추가 정보를 제공합니다. 콘솔의 **양자 작업** 탭으로 이동하면 양자 작업이 목록 상단에 있어야 합니다. 아니면, 고유한 양자 작업 ID 또는 기타 기준을 사용하여 양자 작업을 검색할 수 있습니다.

**참고**  
90일이 지나면 Amazon Braket은 양자 작업과 연결된 모든 양자 작업 ID 및 기타 메타데이터를 자동으로 제거합니다. 자세한 내용은 [데이터 보존](https://docs.aws.amazon.com/braket/latest/developerguide/security.html#braket-data-retention)을 참조하세요.

 **QPU에서 실행** 

Amazon Braket을 사용하면 단 한 줄의 코드만 변경하여 물리적 양자 컴퓨터에서 이전 양자 회로 예제를 실행할 수 있습니다. Amazon Braket은 다양한 Quantum 처리 장치(QPU) 디바이스에 대한 액세스를 제공합니다. [지원되는 디바이스](braket-devices.md) 섹션과 AWS 콘솔의 디바이스 탭에서 다양한 **디바이스** 및 가용성 기간에 대한 정보를 찾을 수 있습니다. 다음 예제에서는 IQM 디바이스를 인스턴스화하는 방법을 보여줍니다.

```
# Choose the IQM hardware to run your circuit
device = AwsDevice("arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")
```

또는 이 코드가 있는 IonQ 디바이스를 선택합니다.

```
# Choose the Ionq device to run your circuit
device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1")
```

디바이스를 선택한 후 워크로드를 실행하기 전에, 다음 코드로 디바이스 대기열 깊이를 쿼리하여 양자 작업 또는 하이브리드 작업 수를 확인할 수 있습니다. 또한 고객은 Amazon Braket Management Console의 디바이스 페이지에서 디바이스별 대기열 깊이를 볼 수 있습니다.

```
# Print your queue depth
print(device.queue_depth().quantum_tasks)
# Returns the number of quantum tasks queued on the device
# {<QueueType.NORMAL: 'Normal'>: '0', <QueueType.PRIORITY: 'Priority'>: '0'}

print(device.queue_depth().jobs)
# Returns the number of hybrid jobs queued on the device
# '2'
```

작업을 실행하면 Amazon Braket SDK가 결과를 폴링합니다(기본 시간 초과는 5일). 다음 예제와 같이, `.run()` 명령에서 `poll_timeout_seconds` 파라미터를 수정하여 이 기본값을 변경할 수 있습니다. 폴링 시간 초과가 너무 짧으면 QPU를 사용할 수 없고 로컬 시간 초과 오류가 반환되는 경우와 같이 폴링 시간 내에 결과가 반환되지 않을 수 있다는 점을 유의하세요. `task.result()` 함수를 직접적으로 호출하여 폴링을 다시 시작할 수 있습니다.

```
# Define quantum task with 1 day polling timeout
task = device.run(bell, s3_folder, poll_timeout_seconds=24*60*60)
print(task.result().measurement_counts)
```

또한 양자 작업 또는 하이브리드 작업을 제출한 후 `queue_position()` 함수를 직접적으로 호출하여 대기열 위치를 확인할 수 있습니다.

```
print(task.queue_position().queue_position)
# Return the number of quantum tasks queued ahead of you
# '2'
```

# 첫 번째 양자 알고리즘 빌드
<a name="braket-explore-algorithm-library"></a>

Amazon Braket 알고리즘 라이브러리는 Python으로 작성된 사전 빌드된 양자 알고리즘의 카탈로그입니다. 이러한 알고리즘을 그대로 실행하거나 더 복잡한 알고리즘을 빌드하기 위한 출발점으로 활용할 수 있습니다. Braket 콘솔에서 알고리즘 라이브러리에 액세스할 수 있습니다. 자세한 내용은 [Braket Github 알고리즘 라이브러리](https://github.com/aws-samples/amazon-braket-algorithm-library)를 참조하세요.

![\[간단한 설명과 함께 Berstein Vazirani, Deutsch-Jozsa, Grover 알고리즘 및 Quantum Approximate Optimization Algorithm과 같은 사전 빌드된 양자 알고리즘 목록을 보여주는 Amazon Braket의 알고리즘 라이브러리 페이지입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/AlgorithmLibrary.png)


Braket 콘솔은 알고리즘 라이브러리에서 사용 가능한 각 알고리즘에 대한 설명을 제공합니다. GitHub 링크를 선택하여 각 알고리즘의 세부 정보를 보거나, **노트북 열기**를 선택하여 열거나 사용 가능한 모든 알고리즘이 포함된 노트북을 생성합니다. 노트북 옵션을 선택하면 노트북의 루트 폴더에서 Braket 알고리즘 라이브러리를 찾을 수 있습니다.

# SDK에서 회로 구성
<a name="braket-constructing-circuit"></a>

이 섹션에서는 회로 정의, 사용 가능한 게이트 보기, 회로 확장, 각 디바이스가 지원하는 게이트 보기의 예제를 제공합니다. 또한 qubits를 수동으로 할당하는 방법, 컴파일러가 정의된 대로 정확하게 회로를 실행하도록 지시하는 방법, 노이즈가 있는 시뮬레이터를 사용하여 노이즈가 있는 회로를 빌드하는 방법에 대한 지침도 포함되어 있습니다.

또한 특정 QPU를 사용하여 다양한 게이트에 대해 Braket에서 펄스 수준으로 작업할 수도 있습니다. 자세한 내용은 [Amazon Braket의 펄스 제어](braket-pulse-control.md)를 참조하세요.

**Topics**
+ [게이트 및 회로](#braket-gates)
+ [프로그램 세트](#braket-program-set)
+ [부분 측정](#braket-partial-measurement)
+ [수동 qubit 할당](#manual-qubit-allocation)
+ [축어적 컴파일](#verbatim-compilation)
+ [노이즈 시뮬레이션](#noise-simulation)

## 게이트 및 회로
<a name="braket-gates"></a>

양자 게이트 및 회로는 Amazon Braket Python SDK의 [https://github.com/aws/amazon-braket-sdk-python/blob/main/src/braket/circuits/circuit.py](https://github.com/aws/amazon-braket-sdk-python/blob/main/src/braket/circuits/circuit.py) 클래스에 정의됩니다. SDK에서 `Circuit()`을 직접적으로 호출하여 새 회로 객체를 인스턴스화할 수 있습니다.

 **예: 회로 정의** 

이 예제는 표준, 단일 큐비트 아다마르 게이트 및 2큐비트 CNOT 게이트로 구성된 4qubits(`q0`, `q1`, `q2` 및 `q3`으로 레이블 지정)의 샘플 회로를 정의하는 것으로 시작합니다. 다음 예제와 같이 `print` 함수를 직접적으로 호출하여 이 회로를 시각화할 수 있습니다.

```
# Import the circuit module
from braket.circuits import Circuit

# Define circuit with 4 qubits
my_circuit = Circuit().h(range(4)).cnot(control=0, target=2).cnot(control=1, target=3)
print(my_circuit)
```

```
T  : │  0  │     1     │
      ┌───┐             
q0 : ─┤ H ├───●─────────
      └───┘   │         
      ┌───┐   │         
q1 : ─┤ H ├───┼─────●───
      └───┘   │     │   
      ┌───┐ ┌─┴─┐   │   
q2 : ─┤ H ├─┤ X ├───┼───
      └───┘ └───┘   │   
      ┌───┐       ┌─┴─┐ 
q3 : ─┤ H ├───────┤ X ├─
      └───┘       └───┘ 
T  : │  0  │     1     │
```

 **예: 파라미터화된 회로 정의** 

이 예제에서는 자유 파라미터에 따라 달라지는 게이트가 있는 회로를 정의합니다. 이러한 파라미터의 값을 지정하여 새 회로를 생성하거나, 회로를 제출할 때 특정 디바이스에서 양자 작업으로 실행할 수 있습니다.

```
from braket.circuits import Circuit, FreeParameter

# Define a FreeParameter to represent the angle of a gate
alpha = FreeParameter("alpha")

# Define a circuit with three qubits
my_circuit = Circuit().h(range(3)).cnot(control=0, target=2).rx(0, alpha).rx(1, alpha)
print(my_circuit)
```

다음과 같이 단일 `float`(모든 자유 파라미터가 취하는 값) 또는 각 파라미터의 값을 지정하는 키워드 인수를 회로에 제공하여 파라미터화된 회로에서 파라미터화되지 않은 새 회로를 생성할 수 있습니다.

```
my_fixed_circuit = my_circuit(1.2)
my_fixed_circuit = my_circuit(alpha=1.2)
print(my_fixed_circuit)
```

`my_circuit`은 수정되지 않으므로 이를 사용하여 고정된 파라미터 값으로 많은 새 회로를 인스턴스화할 수 있습니다.

 **예: 회로의 게이트 수정** 

다음 예제에서는 제어 및 전원 한정자를 사용하는 게이트가 있는 회로를 정의합니다. 이러한 수정 사항을 사용하여 제어된 `Ry` 게이트와 같은 새 게이트를 생성할 수 있습니다.

```
from braket.circuits import Circuit

# Create a bell circuit with a controlled x gate
my_circuit = Circuit().h(0).x(control=0, target=1)

# Add a multi-controlled Ry gate of angle .13
my_circuit.ry(angle=.13, target=2, control=(0, 1))

# Add a 1/5 root of X gate
my_circuit.x(0, power=1/5)

print(my_circuit)
```

게이트 한정자는 로컬 시뮬레이터에서만 지원됩니다.

 **예: 사용 가능한 모든 게이트 보기** 

다음 예제에서는 Amazon Braket에서 사용 가능한 모든 게이트를 보는 방법을 보여줍니다.

```
from braket.circuits import Gate
# Print all available gates in Amazon Braket
gate_set = [attr for attr in dir(Gate) if attr[0].isupper()]
print(gate_set)
```

이 코드의 출력에는 모든 게이트가 나열됩니다.

```
['CCNot', 'CNot', 'CPhaseShift', 'CPhaseShift00', 'CPhaseShift01', 'CPhaseShift10', 'CSwap', 'CV', 'CY', 'CZ', 'ECR', 'GPhase', 'GPi', 'GPi2', 'H', 'I', 'ISwap', 'MS', 'PRx', 'PSwap', 'PhaseShift', 'PulseGate', 'Rx', 'Ry', 'Rz', 'S', 'Si', 'Swap', 'T', 'Ti', 'U', 'Unitary', 'V', 'Vi', 'X', 'XX', 'XY', 'Y', 'YY', 'Z', 'ZZ']
```

이러한 게이트는 해당 유형의 회로에 대한 메서드를 직접적으로 호출하여 회로에 추가할 수 있습니다. 예를 들어 `circ.h(0)`를 직접적으로 호출하여 첫 번째 qubit에 아다마르 게이트를 추가합니다.

**참고**  
게이트가 제자리에 추가되며, 다음 예제에서는 이전 예제에 나열된 모든 게이트를 동일한 회로에 추가합니다.

```
circ = Circuit()
# toffoli gate with q0, q1 the control qubits and q2 the target.
circ.ccnot(0, 1, 2)
# cnot gate
circ.cnot(0, 1)
# controlled-phase gate that phases the |11> state, cphaseshift(phi) = diag((1,1,1,exp(1j*phi))), where phi=0.15 in the examples below
circ.cphaseshift(0, 1, 0.15)
# controlled-phase gate that phases the |00> state, cphaseshift00(phi) = diag([exp(1j*phi),1,1,1])
circ.cphaseshift00(0, 1, 0.15)
# controlled-phase gate that phases the |01> state, cphaseshift01(phi) = diag([1,exp(1j*phi),1,1])
circ.cphaseshift01(0, 1, 0.15)
# controlled-phase gate that phases the |10> state, cphaseshift10(phi) = diag([1,1,exp(1j*phi),1])
circ.cphaseshift10(0, 1, 0.15)
# controlled swap gate
circ.cswap(0, 1, 2)
# swap gate
circ.swap(0,1)
# phaseshift(phi)= diag([1,exp(1j*phi)])
circ.phaseshift(0,0.15)
# controlled Y gate
circ.cy(0, 1)
# controlled phase gate
circ.cz(0, 1)
# Echoed cross-resonance gate applied to q0, q1
circ = Circuit().ecr(0,1)
# X rotation with angle 0.15
circ.rx(0, 0.15)
# Y rotation with angle 0.15
circ.ry(0, 0.15)
# Z rotation with angle 0.15
circ.rz(0, 0.15)
# Hadamard gates applied to q0, q1, q2
circ.h(range(3))
# identity gates applied to q0, q1, q2
circ.i([0, 1, 2])
# iswap gate, iswap = [[1,0,0,0],[0,0,1j,0],[0,1j,0,0],[0,0,0,1]]
circ.iswap(0, 1)
# pswap gate, PSWAP(phi) = [[1,0,0,0],[0,0,exp(1j*phi),0],[0,exp(1j*phi),0,0],[0,0,0,1]]
circ.pswap(0, 1, 0.15)
# X gate applied to q1, q2
circ.x([1, 2])
# Y gate applied to q1, q2
circ.y([1, 2])
# Z gate applied to q1, q2
circ.z([1, 2])
# S gate applied to q0, q1, q2
circ.s([0, 1, 2])
# conjugate transpose of S gate applied to q0, q1
circ.si([0, 1])
# T gate applied to q0, q1
circ.t([0, 1])
# conjugate transpose of T gate applied to q0, q1
circ.ti([0, 1])
# square root of not gate applied to q0, q1, q2
circ.v([0, 1, 2])
# conjugate transpose of square root of not gate applied to q0, q1, q2
circ.vi([0, 1, 2])
# exp(-iXX theta/2)
circ.xx(0, 1, 0.15)
# exp(i(XX+YY) theta/4), where theta=0.15 in the examples below
circ.xy(0, 1, 0.15)
# exp(-iYY theta/2)
circ.yy(0, 1, 0.15)
# exp(-iZZ theta/2)
circ.zz(0, 1, 0.15)
# IonQ native gate GPi with angle 0.15 applied to q0
circ.gpi(0, 0.15)
# IonQ native gate GPi2 with angle 0.15 applied to q0
circ.gpi2(0, 0.15)
# IonQ native gate MS with angles 0.15, 0.15, 0.15 applied to q0, q1
circ.ms(0, 1, 0.15, 0.15, 0.15)
```

사전 정의된 게이트 세트 외에도, 자체 정의된 단위 게이트를 회로에 적용할 수도 있습니다. 이는 `targets` 파라미터에 의해 정의된 qubits에 적용되는 단일 큐비트 게이트(다음 소스 코드에 표시됨) 또는 다중 큐비트 게이트일 수 있습니다.

```
import numpy as np

# Apply a general unitary
my_unitary = np.array([[0, 1],[1, 0]])
circ.unitary(matrix=my_unitary, targets=[0])
```

 **예: 기존 회로 확장** 

명령을 추가하여 기존 회로를 확장할 수 있습니다. `Instruction`은 양자 디바이스에서 수행할 양자 작업을 설명하는 양자 지시어입니다. `Instruction` 연산자에는 유형 `Gate`의 객체만 포함됩니다.

```
# Import the Gate and Instruction modules
from braket.circuits import Gate, Instruction

# Add instructions directly.
circ = Circuit([Instruction(Gate.H(), 4), Instruction(Gate.CNot(), [4, 5])])

# Or with add_instruction/add functions
instr = Instruction(Gate.CNot(), [0, 1])
circ.add_instruction(instr)
circ.add(instr)

# Specify where the circuit is appended
circ.add_instruction(instr, target=[3, 4])
circ.add_instruction(instr, target_mapping={0: 3, 1: 4})

# Print the instructions
print(circ.instructions)
# If there are multiple instructions, you can print them in a for loop
for instr in circ.instructions:
     print(instr)

# Instructions can be copied
new_instr = instr.copy()
# Appoint the instruction to target
new_instr = instr.copy(target=[5, 6])
new_instr = instr.copy(target_mapping={0: 5, 1: 6})
```

 **예: 각 디바이스가 지원하는 게이트 보기** 

시뮬레이터는 Braket SDK의 모든 게이트를 지원하지만, QPU 디바이스는 더 작은 부분 집합을 지원합니다. 디바이스 속성에서 디바이스의 지원되는 게이트를 확인할 수 있습니다. 다음은 IonQ 디바이스의 예제입니다.

```
# Import the device module
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1")

# Get device name
device_name = device.name
# Show supportedQuantumOperations (supported gates for a device)
device_operations = device.properties.dict()['action']['braket.ir.openqasm.program']['supportedOperations']
print('Quantum Gates supported by {}:\n {}'.format(device_name, device_operations))
```

```
Quantum Gates supported by Aria 1:
 ['x', 'y', 'z', 'h', 's', 'si', 't', 'ti', 'v', 'vi', 'rx', 'ry', 'rz', 'cnot', 'swap', 'xx', 'yy', 'zz']
```

지원되는 게이트는 양자 하드웨어에서 실행되기 전에 네이티브 게이트로 컴파일해야 할 수 있습니다. 회로를 제출하면 Amazon Braket이 이 컴파일을 자동으로 수행합니다.

 **예: 디바이스에서 지원하는 네이티브 게이트의 충실도를 프로그래밍 방식으로 검색** 

Braket 콘솔의 **디바이스** 페이지에서 충실도 정보를 볼 수 있습니다. 프로그래밍 방식으로 동일한 정보에 액세스하는 것이 도움이 되는 경우도 있습니다. 다음 코드는 QPU의 두 게이트 간에 두 qubit 게이트 충실도를 추출하는 방법을 보여줍니다.

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

# Specify the qubits 
a=10 
b=11
edge_properties_entry = device.properties.standardized.twoQubitProperties['10-11'].twoQubitGateFidelity
gate_name = edge_properties_entry[0].gateName
fidelity = edge_properties_entry[0].fidelity
print(f"Fidelity of the {gate_name} gate between qubits {a} and {b}: {fidelity}")
```

## 프로그램 세트
<a name="braket-program-set"></a>

프로그램 세트는 단일 양자 작업에서 여러 양자 회로를 효율적으로 실행합니다. 해당 작업에서는 최대 100개의 양자 회로 또는 최대 100개의 서로 다른 파라미터 세트가 있는 단일 파라메트릭 회로를 제출할 수 있습니다. 이 연산은 후속 회로 실행 사이의 시간을 최소화하고 양자 작업 처리 오버헤드를 줄여줍니다. 현재 프로그램 세트는 Amazon Braket Local Simulator 및 AQT, IQM 및 Rigetti 디바이스에서 지원됩니다.

**ProgramSet 정의**

다음 첫 번째 코드 예제에서는 파라미터화된 회로와 파라미터가 없는 회로를 모두 사용하여 `ProgramSet`를 빌드하는 방법을 보여줍니다.

```
from braket.aws import AwsDevice
from braket.circuits import Circuit, FreeParameter
from braket.program_sets.circuit_binding import CircuitBinding
from braket.program_sets import ProgramSet

# Initialize the quantum device
device = AwsDevice("arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")

# Define circuits
circ1 = Circuit().h(0).cnot(0, 1)
circ2 = Circuit().rx(0, 0.785).ry(1, 0.393).cnot(1, 0)
circ3 = Circuit().t(0).t(1).cz(0, 1).s(0).cz(1, 2).s(1).s(2)
parameterize_circuit = Circuit().rx(0, FreeParameter("alpha")).cnot(0, 1).ry(1, FreeParameter("beta"))

# Create circuit bindings with different parameters
circuit_binding = CircuitBinding(
    circuit=parameterize_circuit,
    input_sets={
            'alpha': (0.10, 0.11, 0.22, 0.34, 0.45),
            'beta': (1.01, 1.01, 1.03, 1.04, 1.04),
    })

# Creating the program set
program_set_1 = ProgramSet([
    circ1,
    circ2,
    circ3,
    circuit_binding,
])
```

이 프로그램 세트에는 `circ1`, `circ2`, `circ3`, `circuit_binding`의 네 가지 고유한 프로그램이 포함되어 있습니다. `circuit_binding` 프로그램은 5개의 서로 다른 파라미터 바인딩으로 실행되어 5개의 실행 파일을 생성합니다. 다른 3개의 파라미터 없는 프로그램은 각각 하나의 실행 파일을 생성합니다. 그러면 다음 이미지와 같이 총 8개의 실행 파일이 생성됩니다.

![\[4개의 회로가 있는 ProgramSet 구조입니다. 여기서 c4는 5개의 입력 세트를 처리하기 위해 CircuitBinding을 사용합니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/program_set1.png)


다음 두 번째 코드 예제에서는 `product()` 메서드를 사용하여 프로그램 세트의 각 실행 파일에 동일한 관찰 가능 항목 세트를 연결하는 방법을 보여줍니다.

```
from braket.circuits.observables import I, X, Y, Z

observables = [Z(0) @ Z(1), X(0) @ X(1), Z(0) @ X(1), X(0) @ Z(1)]

program_set_2 = ProgramSet.product(
    circuits=[circ1, circ2, circuit_binding],
    observables=observables
)
```

파라미터 없는 프로그램의 경우 각 관찰 가능 항목은 각 회로에 대해 측정됩니다. 파라메트릭 프로그램의 경우 다음 이미지에서와 같이 각 관찰 가능 항목은 각 입력 세트에 대해 측정됩니다.

![\[회로 3개의 병렬 실행을 보여주는 ProgramSet.product로, c3는 CircuitBinding을 사용하여 각각 5개의 관찰 가능 항목이 있는 입력 세트 5개를 처리합니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/program_set2.png)


다음 세 번째 코드 예제에서는 `zip()` 메서드를 사용하여 개별 관찰 가능 항목을 `ProgramSet`의 특정 파라미터 세트와 페어링하는 방법을 보여줍니다.

```
program_set_3 = ProgramSet.zip(
    circuits=circuit_binding,
    observables=observables + [Y(0) @ Y(1)]
)
```

![\[입력 세트별로 개별 관찰 가능 항목이 있는 공유 회로를 사용하여 5개의 병렬 실행을 보여주는 CircuitBinding이 포함된 ProgramSet.zip입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/program_set3.png)


`CircuitBinding()` 대신, 관찰 가능 항목의 목록을 회로 및 입력 세트 목록과 함께 직접 압축할 수 있습니다.

```
program_set_4 = ProgramSet.zip(
    circuits=[circ1, circ2, circ3],
    input_sets=[{}, {}, {}],
    observables=observables[:3]
)
```

![\[해당하는 개별 입력 세트 및 개별 관찰 가능 항목이 있는 회로 7개의 병렬 실행을 보여주는 ProgramSet.zip입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/program_set4.png)


프로그램 세트에 대한 자세한 내용과 예제는 amazon-braket-examples Github의 [프로그램 세트 폴더](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/braket_features/program_sets)를 참조하세요.

**디바이스에서 프로그램 세트 검사 및 실행**

프로그램 세트의 실행 파일 수는 고유한 파라미터 바인딩 회로 수와 같습니다. 다음 코드 예제를 사용하여 회로 실행 파일 및 샷의 총 수를 계산합니다.

```
# Number of shots per executable
shots = 10
num_executables = program_set_1.total_executables

# Calculate total number of shots across all executables
total_num_shots = shots*num_executables
```

**참고**  
프로그램 세트를 사용하면 프로그램 세트의 모든 회로에서 총 샷 수를 기준으로 단일 작업당 요금과 샷당 요금을 지불하게 됩니다.

프로그램 세트를 실행하려면 다음 코드 예제를 사용합니다.

```
# Run the program set
task = device.run(
   program_set_1, shots=total_num_shots,
)
```

Rigetti 디바이스를 사용하는 경우 작업이 부분적으로 완료되고 부분적으로 대기열에 있는 동안 프로그램 세트가 `RUNNING` 상태로 유지될 수 있습니다. 결과를 더 빨리 얻으려면 프로그램 세트를 [하이브리드 작업](braket-jobs-first.md)으로 제출하는 것을 고려하세요.

**결과 분석**

다음 코드를 실행하여 `ProgramSet`에서 실행 파일의 결과를 분석하고 측정합니다.

```
# Get the results from a program set 
result = task.result()

# Get the first executbable
first_program = result[0] 
first_executable = first_program[0]

# Inspect the results of the first executable
measurements_from_first_executable = first_executable.measurements
print(measurements_from_first_executable)
```

## 부분 측정
<a name="braket-partial-measurement"></a>

양자 회로의 모든 큐비트를 측정하는 대신 부분 측정을 사용하여 개별 큐비트 또는 큐비트의 부분 집합을 측정합니다.

**참고**  
중간 회로 측정 및 피드포워드 연산과 같은 추가 기능은 실험 기능으로 사용할 수 있습니다. [IQM 디바이스의 동적 회로에 대한 액세스](braket-experimental-capabilities.md#braket-access-dynamic-circuits)를 참조하세요.

**예: 큐비트의 부분 집합 측정**

다음 코드 예제는 벨 상태 회로에서 큐비트 0만 측정하여 부분 측정을 보여줍니다.

```
from braket.devices import LocalSimulator
from braket.circuits import Circuit

# Use the local state vector simulator
device = LocalSimulator()

# Define an example bell circuit and measure qubit 0
circuit = Circuit().h(0).cnot(0, 1).measure(0)

# Run the circuit
task = device.run(circuit, shots=10)

# Get the results
result = task.result()

# Print the circuit and measured qubits
print(circuit)
print()
print("Measured qubits: ", result.measured_qubits)
```

## 수동 qubit 할당
<a name="manual-qubit-allocation"></a>

Rigetti의 양자 컴퓨터에서 양자 회로를 실행할 때 선택적으로 수동 qubit 할당을 사용하여 알고리즘에 어떤 qubits를 사용할지 제어할 수 있습니다. [Amazon Braket 콘솔](https://console.aws.amazon.com/braket/home)과 [Amazon Braket SDK](https://github.com/aws/amazon-braket-sdk-python)를 사용하면 선택한 QPU 디바이스의 최신 보정 데이터를 검사할 수 있으므로, 실험에 가장 적합한 qubits를 선택할 수 있습니다.

수동 qubit 할당을 사용하면 보다 정확하게 회로를 실행하고 개별 qubit 속성을 조사할 수 있습니다. 연구원과 고급 사용자는 최신 디바이스 보정 데이터를 기반으로 회로 설계를 최적화하고 더 정확한 결과를 얻을 수 있습니다.

다음 예제에서는 명시적으로 qubits를 할당하는 방법을 보여줍니다.

```
# Import the device module
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
circ = Circuit().h(0).cnot(0, 7)  # Indices of actual qubits in the QPU

# Set up S3 bucket (where results are stored)
my_bucket = "amazon-braket-s3-demo-bucket" # The name of the bucket
my_prefix = "your-folder-name" # The name of the folder in the bucket
s3_location = (my_bucket, my_prefix)

my_task = device.run(circ, s3_location, shots=100, disable_qubit_rewiring=True)
```

자세한 내용은 [GitHub의 Amazon Braket 예제](https://github.com/aws/amazon-braket-examples), 또는 특히 이 노트북: [QPU 디바이스에서 큐비트 할당](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Allocating_Qubits_on_QPU_Devices.ipynb)을 참조하세요.

## 축어적 컴파일
<a name="verbatim-compilation"></a>

게이트 기반 양자 컴퓨터에서 양자 회로를 실행할 때 컴파일러가 수정 없이 정의된 대로 정확하게 회로를 실행하도록 지시할 수 있습니다. 축어적 컴파일을 사용하여 전체 회로를 지정된 대로 정확하게 보존하거나 특정 부분만 보존(Rigetti에서만 지원)하도록 지정할 수 있습니다. 하드웨어 벤치마킹 또는 오류 완화 프로토콜을 위한 알고리즘을 개발할 때는 하드웨어에서 실행 중인 게이트 및 회로 레이아웃을 정확하게 지정할 수 있는 옵션이 필요합니다. 축어적 컴파일을 사용하면 특정 최적화 단계를 꺼서 컴파일 프로세스를 직접 제어할 수 있으므로, 회로가 설계된 대로 정확하게 실행됩니다.

축어적 컴파일은 AQT, IQM, 및 Rigetti 디바이스에서 지원되며 IonQ네이티브 게이트를 사용해야 합니다. 축어적 컴파일을 사용하는 경우 디바이스의 토폴로지를 확인하여 게이트가 연결된 qubits에서 직접적으로 호출되고 회로가 하드웨어에서 지원되는 네이티브 게이트를 사용하는지 확인하는 것이 좋습니다. 다음 예제에서는 디바이스에서 지원하는 네이티브 게이트 목록에 프로그래밍 방식으로 액세스하는 방법을 보여줍니다.

```
device.properties.paradigm.nativeGateSet
```

Rigetti의 경우, 축어적 컴파일과 함께 사용할 수 있도록 `disableQubitRewiring=True`를 설정하여 qubit 재배선을 꺼야 합니다. 컴파일에서 축어적 상자를 사용할 때 `disableQubitRewiring=False`가 설정된 경우 양자 회로는 검증에 실패하고 실행되지 않습니다.

축어적 컴파일이 회로에 대해 활성화되어 있고 이를 지원하지 않는 QPU에서 실행되는 경우, 지원되지 않는 연산으로 인해 작업이 실패했음을 나타내는 오류가 생성됩니다. 더 많은 양자 하드웨어가 기본적으로 컴파일러 함수를 지원함에 따라 이 기능은 이러한 디바이스를 포함하도록 확장될 예정입니다. 축어적 컴파일을 지원하는 디바이스에는 다음 코드로 쿼리할 때 지원되는 연산으로 포함됩니다.

```
from braket.aws import AwsDevice
from braket.device_schema.device_action_properties import DeviceActionType
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
device.properties.action[DeviceActionType.OPENQASM].supportedPragmas
```

축어적 컴파일 사용과 관련된 추가 비용은 없습니다. [Amazon Braket 요금](https://aws.amazon.com/braket/pricing/) 페이지에 지정된 현재 요금을 기준으로 Braket QPU 디바이스, 노트북 인스턴스 및 온디맨드 시뮬레이터에서 실행되는 양자 작업에 대해서는 계속 요금이 부과됩니다. 자세한 내용은 [축어적 컴파일](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Verbatim_Compilation.ipynb) 예제 노트북을 참조하세요.

**참고**  
OpenQASM을 사용하여 AQT 및 IonQ 디바이스에 대한 회로를 쓰고 회로를 물리적 쿼비트에 직접 매핑하려는 경우 OpenQASM에서 `disableQubitRewiring` 플래그를 무시`#pragma braket verbatim`하므로를 사용해야 합니다.

## 노이즈 시뮬레이션
<a name="noise-simulation"></a>

로컬 노이즈 시뮬레이터를 인스턴스화하려면 다음과 같이 백엔드를 변경할 수 있습니다.

```
# Import the device module
from braket.aws import AwsDevice

device = LocalSimulator(backend="braket_dm")
```

다음과 같은 두 가지 방법으로 노이즈가 있는 회로를 빌드할 수 있습니다.

1. 노이즈가 있는 회로를 상향식으로 빌드합니다.

1. 기존의 노이즈 없는 회로를 가져와 전체적으로 노이즈를 주입합니다.

다음 예제에서는 탈분극 노이즈가 있는 기본 회로와 사용자 지정 Kraus 채널을 사용하는 접근 방식을 보여줍니다.

```
import scipy.stats
import numpy as np

# Bottom up approach
# Apply depolarizing noise to qubit 0 with probability of 0.1
circ = Circuit().x(0).x(1).depolarizing(0, probability=0.1)

# Create an arbitrary 2-qubit Kraus channel
E0 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.8)
E1 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.2)
K = [E0, E1]

# Apply a two-qubit Kraus channel to qubits 0 and 2
circ = circ.kraus([0, 2], K)
```

```
from braket.circuits import Noise

# Inject noise approach
# Define phase damping noise
noise = Noise.PhaseDamping(gamma=0.1)
# The noise channel is applied to all the X gates in the circuit
circ = Circuit().x(0).y(1).cnot(0, 2).x(1).z(2)
circ_noise = circ.copy()
circ_noise.apply_gate_noise(noise, target_gates=Gate.X)
```

다음 두 예제에서와 같이 회로 실행은 이전과 동일한 사용자 환경입니다.

 **예제 1**.

```
task = device.run(circ, shots=100)
```

또는

 **예제 2**.

```
task = device.run(circ_noise, shots=100)
```

추가 예제는 [Braket 입문용 노이즈 시뮬레이터 예제](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Noise_On_Amazon_Braket.ipynb)를 참조하세요.

# 회로 검사
<a name="braket-inspecting-circut"></a>

Amazon Braket의 양자 회로에는 `Moments`라고 하는 의사 시간 개념이 있습니다. 각 qubit는 `Moment`당 단일 게이트를 경험할 수 있습니다. `Moments`의 목적은 회로와 게이트를 더 쉽게 처리하고 시간 구조를 제공하는 것입니다.

**참고**  
모멘트는 일반적으로 QPU에서 게이트가 실행되는 실제 시간과 일치하지 않습니다.

회로의 깊이는 해당 회로의 총 모멘트 수에 따라 결정됩니다. 다음 예제와 같이 메서드 `circuit.depth`를 직접적으로 호출하는 회로 깊이를 볼 수 있습니다.

```
from braket.circuits import Circuit

# Define a circuit with parametrized gates
circ = Circuit().rx(0, 0.15).ry(1, 0.2).cnot(0, 2).zz(1, 3, 0.15).x(0)
print(circ)
print('Total circuit depth:', circ.depth)
```

```
T  : │     0      │        1         │  2  │
      ┌──────────┐                    ┌───┐ 
q0 : ─┤ Rx(0.15) ├───●────────────────┤ X ├─
      └──────────┘   │                └───┘ 
      ┌──────────┐   │   ┌──────────┐       
q1 : ─┤ Ry(0.20) ├───┼───┤ ZZ(0.15) ├───────
      └──────────┘   │   └────┬─────┘       
                   ┌─┴─┐      │             
q2 : ──────────────┤ X ├──────┼─────────────
                   └───┘      │             
                         ┌────┴─────┐       
q3 : ────────────────────┤ ZZ(0.15) ├───────
                         └──────────┘       
T  : │     0      │        1         │  2  │
Total circuit depth: 3
```

위 회로의 총 회로 깊이는 3입니다(모멘트 `0`, `1` 및 `2`로 표시됨). 각 모멘트의 게이트 연산을 확인할 수 있습니다.

 `Moments`는 *키-값* 쌍의 딕셔너리 역할을 합니다.
+ 키는 의사 시간과 qubit 정보가 포함된 `MomentsKey()`입니다.
+ 값은 `Instructions()` 유형으로 할당됩니다.

```
moments = circ.moments
for key, value in moments.items():
    print(key)
    print(value, "\n")
```

```
MomentsKey(time=0, qubits=QubitSet([Qubit(0)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': Rx('angle': 0.15, 'qubit_count': 1), 'target': QubitSet([Qubit(0)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=0, qubits=QubitSet([Qubit(1)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': Ry('angle': 0.2, 'qubit_count': 1), 'target': QubitSet([Qubit(1)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=1, qubits=QubitSet([Qubit(0), Qubit(2)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': CNot('qubit_count': 2), 'target': QubitSet([Qubit(0), Qubit(2)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=1, qubits=QubitSet([Qubit(1), Qubit(3)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': ZZ('angle': 0.15, 'qubit_count': 2), 'target': QubitSet([Qubit(1), Qubit(3)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=2, qubits=QubitSet([Qubit(0)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': X('qubit_count': 1), 'target': QubitSet([Qubit(0)]), 'control': QubitSet([]), 'control_state': (), 'power': 1)
```

`Moments`를 통해 회로에 게이트를 추가할 수도 있습니다.

```
from braket.circuits import Instruction, Gate

new_circ = Circuit()
instructions = [Instruction(Gate.S(), 0),
                Instruction(Gate.CZ(), [1, 0]),
                Instruction(Gate.H(), 1)
                ]

new_circ.moments.add(instructions)
print(new_circ)
```

```
T  : │  0  │  1  │  2  │
      ┌───┐ ┌───┐       
q0 : ─┤ S ├─┤ Z ├───────
      └───┘ └─┬─┘       
              │   ┌───┐ 
q1 : ─────────●───┤ H ├─
                  └───┘ 
T  : │  0  │  1  │  2  │
```

# 결과 유형 목록
<a name="braket-result-types"></a>

Amazon Braket은 `ResultType`을 사용하여 회로를 측정할 때 다양한 유형의 결과를 반환할 수 있습니다. 회로는 다음과 같은 유형의 결과를 반환할 수 있습니다.
+  `AdjointGradient`는 제공된 관찰 가능 항목의 기대값의 기울기(벡터 미분)를 반환합니다. 이 관찰 가능 항목은 수반 미분법을 사용하여 지정된 파라미터와 관련하여 제공된 대상에 작용합니다. 샷이 0인 경우에만 이 방법을 사용할 수 있습니다.
+  `Amplitude`는 출력 파동 함수에서 지정된 양자 상태의 진폭을 반환합니다. SV1 및 로컬 시뮬레이터에서만 사용할 수 있습니다.
+  `Expectation`은 지정된 관찰 가능 항목의 기대값을 반환하며,이 값은 이 장 뒷부분에 소개되는 `Observable` 클래스로 지정할 수 있습니다. 관찰 가능 항목을 측정하는 데 사용되는 대상 qubits를 지정해야 하며, 지정된 대상의 수는 관찰 가능 항목이 작용하는 qubits의 수와 같아야 합니다. 대상이 지정되지 않은 경우 관찰 가능 항목은 1qubit에서만 작동해야 하며 모든 qubits에 병렬로 적용됩니다.
+  `Probability`는 계산 기저 상태를 측정할 확률을 반환합니다. 대상이 지정되지 않은 경우 `Probability`는 모든 기저 상태를 측정할 확률을 반환합니다. 대상이 지정되면 지정된 qubits에 있는 기저 벡터의 주변 확률만 반환됩니다. 관리형 시뮬레이터 및 QPU는 최대 15큐비트로 제한되며 로컬 시뮬레이터는 시스템의 메모리 크기로 제한됩니다.
+  `Reduced density matrix`는 qubits의 시스템에서 지정된 대상 qubits의 하위 시스템에 대한 밀도 행렬을 반환합니다. 이 결과 유형의 크기를 제한하기 위해 Braket은 대상 qubits의 수를 최대 8개로 제한합니다.
+  `StateVector`는 전체 상태 벡터를 반환합니다. 로컬 시뮬레이터에서 사용할 수 있습니다.
+  `Sample`은 지정된 대상 qubit 세트 및 관찰 가능 항목의 측정 수를 반환합니다. 대상이 지정되지 않은 경우 관찰 가능 항목은 1qubit에서만 작동해야 하며 모든 qubits에 병렬로 적용됩니다. 대상이 지정된 경우 지정된 대상의 수는 관찰 가능 항목이 작용하는 qubits의 수와 같아야 합니다.
+  `Variance`는 지정된 대상 qubit 세트 및 관찰 가능 항목의 분산(`mean([x-mean(x)]2)`)을 요청된 결과 유형으로 반환합니다. 대상이 지정되지 않은 경우 관찰 가능 항목은 1qubit에서만 작동해야 하며 모든 qubits에 병렬로 적용됩니다. 그렇지 않으면 지정된 대상의 수는 관찰 가능 항목이 적용될 수 있는 qubits의 수와 같아야 합니다.

 **다양한 공급자에 대해 지원되는 결과 유형:** 


|  |  |  |  |  |  |  |  |  | 
| --- |--- |--- |--- |--- |--- |--- |--- |--- |
|  |  로컬 sim  |   SV1   |   DM1   |   TN1   |   AQT   |   IonQ   |   IQM   |   Rigetti   | 
|  수반 기울기  |  N  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  진폭  |  Y  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  기대값  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 
|  확률  |  Y  |  Y  |  Y  |  N  |  Y  |  Y  |  Y  |  Y  | 
|  축약 밀도 행렬  |  Y  |  N  |  Y  |  N  |  N  |  N  |  N  |  N  | 
|  상태 벡터  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  샘플  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 
|  분산  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 

다음 예제와 같이 디바이스 속성을 검토하여 지원되는 결과 유형을 확인할 수 있습니다.

```
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")

# Print the result types supported by this device
for iter in device.properties.action['braket.ir.openqasm.program'].supportedResultTypes:
    print(iter)
```

```
name='Sample' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Expectation' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Variance' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Probability' observables=None minShots=10 maxShots=50000
```

`ResultType`을 직접적으로 호출하려면 다음 예제와 같이 회로에 추가합니다.

```
from braket.circuits import Circuit, Observable

circ = Circuit().h(0).cnot(0, 1).amplitude(state=["01", "10"])
circ.probability(target=[0, 1])
circ.probability(target=0)
circ.expectation(observable=Observable.Z(), target=0)
circ.sample(observable=Observable.X(), target=0)
circ.state_vector()
circ.variance(observable=Observable.Z(), target=0)

# Print one of the result types assigned to the circuit
print(circ.result_types[0])
```

**참고**  
다양한 양자 디바이스는 다양한 형식으로 결과를 제공합니다. 예를 들어 Rigetti 디바이스는 측정값을 반환하는 반면 IonQ 디바이스는 확률을 제공합니다. Amazon Braket SDK는 모든 결과에 대한 측정 속성을 제공합니다. 그러나 확률을 반환하는 디바이스의 경우, 샷당 측정값을 사용할 수 없으므로 이러한 측정값은 사후 계산되며 확률을 기반으로 합니다. 결과가 사후 계산되었는지 확인하려면 결과 객체에서 `measurements_copied_from_device`를 확인합니다. 이 연산은 Amazon Braket SDK GitHub 리포지토리의 [gate\$1model\$1quantum\$1task\$1result.py](https://github.com/aws/amazon-braket-sdk-python/blob/ca5b08dada4839ca31c012ff50aa20b656fd1879/src/braket/tasks/gate_model_quantum_task_result.py#L70-L72) 파일에 자세히 설명되어 있습니다.

## 관찰 가능 항목
<a name="braket-result-types-observables"></a>

Amazon Braket의 `Observable` 클래스를 사용하면 특정 관찰 가능 항목을 측정할 수 있습니다.

각 qubit에 하나의 고유한 비동일성 관찰 가능 항목만 적용할 수 있습니다. 동일한 qubit에 두 개 이상의 서로 다른 비동일성 관찰 가능 항목을 지정하는 경우 오류가 발생합니다. 이를 위해 텐서 곱의 각 인자는 개별 관찰 가능 항목으로 간주됩니다. 다시 말해, 해당 qubit에 작용하는 인자가 동일하게 유지되는 한, 동일한 qubit에 대해 여러 텐서 곱을 가질 수 있습니다.

관찰 가능 항목의 규모를 조정하고 다른 관찰 가능 항목을 추가할 수 있습니다(규모 조정 여부에 관계없음). 그러면 `AdjointGradient` 결과 유형에 사용할 수 있는 `Sum`이 생성됩니다.

`Observable` 클래스에는 다음과 같은 관찰 가능 항목이 포함됩니다.

```
import numpy as np

Observable.I()
Observable.H()
Observable.X()
Observable.Y()
Observable.Z()

# Get the eigenvalues of the observable
print("Eigenvalue:", Observable.H().eigenvalues)
# Or rotate the basis to be computational basis
print("Basis rotation gates:", Observable.H().basis_rotation_gates)

# Get the tensor product of the observable for the multi-qubit case
tensor_product = Observable.Y() @ Observable.Z()
# View the matrix form of an observable by using
print("The matrix form of the observable:\n", Observable.Z().to_matrix())
print("The matrix form of the tensor product:\n", tensor_product.to_matrix())

# Factorize an observable in the tensor form
print("Factorize an observable:", tensor_product.factors)

# Self-define observables, given it is a Hermitian
print("Self-defined Hermitian:", Observable.Hermitian(matrix=np.array([[0, 1], [1, 0]])))

print("Sum of other (scaled) observables:", 2.0 * Observable.X() @ Observable.X() + 4.0 * Observable.Z() @ Observable.Z())
```

```
Eigenvalue: [ 1. -1.]
Basis rotation gates: (Ry('angle': -0.7853981633974483, 'qubit_count': 1),)
The matrix form of the observable:
 [[ 1.+0.j  0.+0.j]
 [ 0.+0.j -1.+0.j]]
The matrix form of the tensor product:
 [[ 0.+0.j  0.+0.j  0.-1.j  0.+0.j]
 [ 0.+0.j -0.+0.j  0.+0.j  0.+1.j]
 [ 0.+1.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.-1.j  0.+0.j -0.+0.j]]
Factorize an observable: (Y('qubit_count': 1), Z('qubit_count': 1))
Self-defined Hermitian: Hermitian('qubit_count': 1, 'matrix': [[0.+0.j 1.+0.j], [1.+0.j 0.+0.j]])
Sum of other (scaled) observables: Sum(TensorProduct(X('qubit_count': 1), X('qubit_count': 1)), TensorProduct(Z('qubit_count': 1), Z('qubit_count': 1)))
```

## 파라미터
<a name="braket-result-types-parameters"></a>

회로는 자유 파라미터를 포함할 수 있습니다. 이러한 자유 파라미터는 한 번만 구성하면 여러 번 실행할 수 있으며 기울기를 계산하는 데 사용할 수 있습니다.

각 자유 파라미터는 다음에 사용되는 문자열 인코딩 이름을 사용합니다.
+ 파라미터 값 설정
+ 사용할 파라미터 식별

```
from braket.circuits import Circuit, FreeParameter, observables
from braket.parametric import FreeParameter

theta = FreeParameter("theta")
phi = FreeParameter("phi")
circ = Circuit().h(0).rx(0, phi).ry(0, phi).cnot(0, 1).xx(0, 1, theta)
```

## 수반 기울기
<a name="braket-result-types-adjoint-gradient"></a>

SV1 디바이스는 다항 해밀토니안을 포함한 관찰 가능 항목 기대값의 수반 기울기를 계산합니다. 파라미터를 미분하려면 이름(문자열 형식)을 지정하거나 직접 참조로 지정합니다.

```
from braket.aws import AwsDevice
from braket.devices import Devices

device = AwsDevice(Devices.Amazon.SV1)

circ.adjoint_gradient(observable=3 * Observable.Z(0) @ Observable.Z(1) - 0.5 * observables.X(0), parameters = ["phi", theta])
```

고정된 파라미터 값을 파라미터화된 회로에 인수로 전달하면 자유 파라미터가 제거됩니다. 자유 파라미터가 더 이상 존재하지 않으므로, 이 회로를 `AdjointGradient`로 실행하면 오류가 생성됩니다. 다음 코드 예제에서는 올바른 사용법과 잘못된 사용법을 보여줍니다.

```
# Will error, as no free parameters will be present
#device.run(circ(0.2), shots=0)

# Will succeed
device.run(circ, shots=0, inputs={'phi': 0.2, 'theta': 0.2})
```

# 전문가 조언 받기
<a name="braket-expert-advice"></a>

Braket 관리 콘솔에서 직접 양자 컴퓨팅 전문가와 소통하면서 워크로드에 대한 추가 지침을 받아보세요.

Braket Direct를 통해 전문가 조언 옵션을 찾아보려면 Braket 콘솔을 열고 왼쪽 창에서 **Braket Direct**를 선택한 다음 **전문가 조언** 섹션으로 이동합니다. 다음과 같은 전문가 조언 옵션을 사용할 수 있습니다.
+ **Braket 상담 시간:** Braket 상담 시간은 1:1 세션으로, 선착순이며 매월 진행됩니다. 이용 가능한 각 상담 시간 간격은 30분이며 무료입니다. Braket 전문가와의 상담을 통해 use-case-to-device 적합성을 살펴보고 알고리즘에 최적화된 Braket 활용 옵션을 모색하며 Amazon Braket Hybrid Jobs, Braket Pulse 또는 아날로그 해밀토니안 시뮬레이션 같은 특정 Braket 기능을 사용하는 방법에 대한 권장 사항을 얻어 아이디어 구상부터 실행까지의 과정을 더 빠르게 진행할 수 있습니다.
  + Braket 상담 시간에 등록하려면 **등록**을 선택하고 연락처 정보, 워크로드 세부 정보 및 원하는 논의 주제를 입력합니다.
  + 그러면 다음 가능한 시간대에 대한 일정 초대가 이메일로 발송됩니다.
**참고**  
긴급한 문제 또는 빠른 문제 해결 질문의 경우 [AWS Support](https://console.aws.amazon.com/support/home#/case/create?issueType=technical)에 문의하는 것이 좋습니다. 긴급하지 않은 질문의 경우 [AWS re:Post 포럼](https://repost.aws/tags/questions/TAhMWeHkpfSMSCxIFNqcqYog?view=all) 또는 [Quantum Computing Stack Exchange](https://quantumcomputing.stackexchange.com/questions/ask)를 사용하여 이전에 답변된 질문을 찾아보고 새 질문을 할 수도 있습니다.
+ **양자 하드웨어 공급자 제품:** IonQ, QuEra 및 Rigetti는 각각 AWS Marketplace를 통해 전문 서비스 제품을 제공합니다.
  + 제품을 찾아보려면 **연결**을 선택하고 목록을 찾습니다.
  + 의 전문 서비스 상품에 대한 자세한 내용은 [ 전문 서비스 제품을](https://docs.aws.amazon.com/marketplace/latest/buyerguide/buyer-proserv-products.html) AWS Marketplace참조하세요.
+ **Amazon Quantum Solutions Lab(QSL):** QSL은 양자 컴퓨팅 전문가들로 구성된 공동 연구 및 전문 서비스 팀으로, 양자 컴퓨팅을 효과적으로 탐구하고 이 기술의 현재 성능을 평가하는 데 도움을 줄 수 있습니다.
  + QSL에 연락하려면 **연결**을 선택하고 연락처 정보와 사용 사례 세부 정보를 입력합니다.
  + QSL 팀에서 다음 단계에 대한 안내를 이메일로 보내드립니다.

# 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`이며, 이는 모든 큐비트를 측정해야 하는 것은 아님을 나타냅니다.

# 실험 기능 살펴보기
<a name="braket-experimental-capabilities"></a>

실험 기능을 사용하면 가용성이 제한되고 새로운 소프트웨어 기능이 도입된 하드웨어에 액세스할 수 있습니다. 이러한 기능은 표준 사양을 초과하는 디바이스 성능에 영향을 미칠 수 있습니다. Amazon Braket SDK를 통해 작업별로 실험 소프트웨어 기능을 자동으로 활성화할 수 있습니다.

실험 기능을 사용하려면 양자 작업을 생성할 때 `experimental_capabilities` 파라미터를 지정합니다. 이 파라미터를 로 설정`"ALL"`하여 해당 작업에 사용 가능한 모든 실험 기능을 활성화합니다. 다음 예제에서는 디바이스에서 회로를 실행할 때 실험 기능을 활성화하는 방법을 보여줍니다.

```
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")

task = device.run(
   circuit,
   shots=1000,
   experimental_capabilities="ALL"
)
```

**참고**  
이러한 기능은 실험적이며 예고 없이 변경될 수 있습니다. 디바이스 성능은 게시된 사양과 다를 수 있으며 결과는 표준 작업과 다를 수 있습니다. 각 작업에 대해 실험 기능을 명시적으로 활성화해야 합니다. 이 파라미터가 없는 작업은 표준 디바이스 기능만 사용합니다.

**Topics**
+ [QuEra Aquila에서 로컬 디튜닝에 액세스](#braket-access-local-detuning)
+ [QuEra Aquila에서 높은 기하형상에 액세스](#braket-access-tall-geometries)
+ [QuEra Aquila에서 좁은 기하형상에 액세스](#braket-access-tight-geometries)
+ [IQM 디바이스의 동적 회로](#braket-access-dynamic-circuits)

## QuEra Aquila에서 로컬 디튜닝에 액세스
<a name="braket-access-local-detuning"></a>

로컬 디튜닝(Local Detuning, LD)은 사용자 지정 가능한 공간 패턴이 있는 새로운 시간 종속 제어장입니다. LD장은 사용자 지정 가능한 공간 패턴에 따라 큐비트에 영향을 미치며, 균일한 구동장과 Rydberg-Rydberg 상호 작용이 생성할 수 있는 것 이상으로 서로 다른 큐비트에 대해 서로 다른 해밀토니안을 구현합니다.

**제약 조건**:

로컬 디튜닝장의 공간 패턴은 각 AHS 프로그램에 대해 사용자 지정할 수 있지만, 프로그램이 진행되는 동안 일정합니다. 로컬 디튜닝장의 시계열은 0에서 시작하고 끝나야 하며 모든 값은 0보다 작거나 같아야 합니다. 또한 로컬 디튜닝장의 파라미터는 수치적 제약 조건에 의해 제한되며, 이는 특정 디바이스 속성 섹션 - `aquila_device.properties.paradigm.rydberg.rydbergLocal`의 Braket SDK를 통해 볼 수 있습니다.

**제한 사항:**

로컬 디튜닝장을 사용하는 양자 프로그램을 실행할 때(해밀토니안에서 크기가 상수 0으로 설정된 경우에도) 디바이스는 Aquila 속성의 성능 섹션에 나열된 T2 시간보다 더 빠른 결어긋남을 경험합니다. 불필요한 경우 AHS 프로그램의 해밀토니안에서 로컬 디튜닝장을 생략하는 것이 좋습니다.

![\[스핀 용어로 표현된 아날로그 해밀토니안 시뮬레이션에는 큐비트, 시간 종속 전역 구동장 및 시간 종속 로컬 디튜닝이 있습니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/AHS_spin_terminology.png)


**예제:**

1. **스핀 시스템에서 비균일 종방향 자기장의 효과 시뮬레이션**

   구동장의 진폭과 위상은 스핀에 대한 횡방향 자기장과 동일한 효과를 큐비트에 미치지만, 구동장의 디튜닝과 로컬 디튜닝의 합은 스핀에 대한 종방향 자기장과 동일한 효과를 큐비트에 발생시킵니다. 로컬 디튜닝장을 공간적으로 제어하면 더 복잡한 스핀 시스템을 시뮬레이션할 수 있습니다.

1. **비평형 초기 상태 준비**

   예제 노트북 [Rydberg 원자를 이용한 격자 게이지 이론 시뮬레이션](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/07_Simulating_Lattice_Gauge_Theory_with_Rydberg_Atoms.ipynb)은 9원자 선형 배열의 중심 원자가 Z2 정렬 상으로 시스템을 어닐링할 때 여기되는 것을 억제하는 방법을 보여줍니다. 준비 단계 후에는 로컬 디튜닝장이 감소하고 AHS 프로그램은 이 특정 비평형 상태에서 시작하여 시스템의 시간 변화를 계속 시뮬레이션합니다.

1. **가중치 기반 최적화 문제 해결**

   예제 노트북 [Maximum weight independent set](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/08_Maximum_Weight_Independent_Set.ipynb)(MWIS)는 Aquila에서 MWIS 문제를 해결하는 방법을 보여줍니다. 로컬 디튜닝장은 단위 디스크 그래프의 노드에 대한 가중치를 정의하는 데 사용되며, 엣지는 Rybderg 봉쇄 효과로 구현됩니다. 균일 바닥 상태에서 시작하여 로컬 디튜닝장을 점진적으로 증가시키면 시스템이 MWIS 해밀토니안의 바닥 상태로 전환되어 문제에 대한 해결책을 찾을 수 있습니다.

## QuEra Aquila에서 높은 기하형상에 액세스
<a name="braket-access-tall-geometries"></a>

높은 기하형상 기능을 사용하면 높이가 증가된 기하형상을 지정할 수 있습니다. 이 기능을 사용하면 AHS 프로그램의 원자 배열이 Aquila의 일반 기능을 넘어 y 방향으로 추가 길이를 확장할 수 있습니다.

**제약 조건**:

높은 기하형상의 최대 높이는 0.000128m(128um)입니다.

**제한 사항:**

이 실험 기능이 계정에 대해 활성화되면 디바이스 속성 페이지와 `GetDevice` 직접 호출에 표시되는 기능은 계속해서 높이에 대한 일반 하한을 반영합니다. AHS 프로그램이 일반 기능을 넘어서는 원자 배열을 사용하는 경우 채우기 오류가 증가할 것으로 예상됩니다. 작업 결과의 `pre_sequence` 부분에서 예상치 못한 0의 수가 증가하는 현상을 발견하게 되며, 이는 결과적으로 완벽하게 초기화된 배열을 얻을 가능성을 낮춥니다. 이 효과는 원자가 많은 행에서 가장 강력합니다.

![\[세 개의 점 그래프는 1차원 선, 사다리 및 다중 형태의 높은 기하형상을 보여줍니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/tall-geometry-graphs.PNG)


**예**:

1. **더 큰 1차원 및 준-1차원 배열**

   원자 사슬 및 사다리형 배열은 더 높은 원자 번호로 확장할 수 있습니다. y와 병렬로 긴 방향을 지정하면 이러한 모델의 더 긴 인스턴스를 프로그래밍할 수 있습니다.

1. **작은 기하형상을 가진 작업의 실행을 다중화할 수 있는 더 많은 공간**

   예제 노트북 [Parallel quantum tasks on Aquila](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/03_Parallel_tasks_on_Aquila.ipynb)는 하나의 원자 배열에 해당 기하형상의 다중화된 복사본을 배치하여 사용 가능한 영역을 최대한 활용하는 방법을 보여줍니다. 사용 가능한 영역이 많을수록 더 많은 사본을 배치할 수 있습니다.

## QuEra Aquila에서 좁은 기하형상에 액세스
<a name="braket-access-tight-geometries"></a>

좁은 기하형상 기능을 사용하면 이웃하는 행 사이의 간격이 더 짧은 기하형상을 지정할 수 있습니다. AHS 프로그램에서 원자는 최소 수직 간격으로 구분된 행으로 배열됩니다. 두 원자 위치의 y 좌표는 0(동일한 행)이거나 최소 행 간격(다른 행)보다 크게 차이나야 합니다. 좁은 기하형상 기능을 사용하면 최소 행 간격이 축소되어 더 좁은 원자 배열을 생성할 수 있습니다. 이 확장은 원자 간 최소 유클리드 거리 요구 사항을 변경하지 않지만, 멀리 떨어진 원자들이 서로 더 가까운 이웃하는 행을 차지하는 격자 생성을 허용합니다. 대표적인 예로는 삼각형 격자가 있습니다.

**제약 조건**:

좁은 기하형상의 최소 행 간격은 0.000002m(2um)입니다.

**제한 사항:**

이 실험 기능이 계정에 대해 활성화되면 디바이스 속성 페이지와 `GetDevice` 직접 호출에 표시되는 기능은 계속해서 높이에 대한 일반 하한을 반영합니다. AHS 프로그램이 일반 기능을 넘어서는 원자 배열을 사용하는 경우 채우기 오류가 증가할 것으로 예상됩니다. 고객은 작업 결과의 `pre_sequence` 부분에서 예상치 못한 0의 수가 증가하는 현상을 발견하게 되며, 이는 결과적으로 완벽하게 초기화된 배열을 얻을 가능성을 낮춥니다. 이 효과는 원자가 많은 행에서 가장 강력합니다.

![\[그래프는 왼쪽에 점이 있는 삼각형 격자의 좁은 기하형상을 보여주며 오른쪽 그래프는 점의 육각형 격자입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/tight-geometry-graphs.PNG)


**예**:

1. **작은 격자 상수가 있는 비직교 격자**

   행 간격이 더 좁을수록 일부 원자에 가장 가까운 이웃이 대각선 방향에 위치하는 격자를 생성할 수 있습니다. 대표적인 예로는 삼각형, 육각형, 카고메 격자 및 일부 준결정이 있습니다.

1. **튜닝 가능한 격자 계열**

   AHS 프로그램에서 상호 작용은 원자 쌍 간의 거리를 조정하여 튜닝됩니다. 행 간격이 더 좁을수록 원자 구조를 정의하는 각도와 거리가 최소 행 간격 제약 조건의 제한을 덜 받으므로, 서로 상대적으로 다른 원자 쌍의 상호 작용을 더 자유롭게 조정할 수 있습니다. 대표적인 예로는 결합 길이가 다른 Shastry-Sutherland 격자 계열이 있습니다.

## IQM 디바이스의 동적 회로
<a name="braket-access-dynamic-circuits"></a>

IQM 디바이스의 동적 회로를 사용하면 MCM(중간 회로 측정) 및 피드포워드 연산을 수행할 수 있습니다. 이러한 기능을 통해 양자 연구원과 개발자는 조건부 논리 및 큐비트 재사용 기능을 갖춘 고급 양자 알고리즘을 구현할 수 있습니다. 이 실험 기능은 리소스 효율성이 향상된 양자 알고리즘을 탐구하고 양자 오류 완화 및 오류 정정 방식을 연구하는 데 도움이 됩니다.

**주요 명령:**
+ `measure_ff`: 피드포워드 제어에 대한 측정을 구현하여 큐비트를 측정하고 피드백 키를 사용하여 결과를 저장합니다.
+ `cc_prx`: 지정된 피드백 키와 연결된 결과가 \$11⟩ 상태를 측정하는 경우에만 적용되는 고전적 제어 회전을 구현합니다.

Amazon Braket은 OpenQASM, Amazon Braket SDK 및 Amazon Braket Qiskit Provider를 통해 동적 회로를 지원합니다.

**제약 조건**:

1. `measure_ff` 명령의 피드백 키는 고유해야 합니다.

1. `cc_prx`는 동일한 피드백 키로 `measure_ff` 이후에 발생해야 합니다.

1. 단일 회로에서 큐비트의 피드포워드는 자체적으로 또는 다른 큐비트로만 제어할 수 있습니다. 서로 다른 회로에서는 서로 다른 제어 쌍을 가질 수 있습니다.<a name="lower"></a>

   1. 예를 들어 큐비트 1이 큐비트 2로 제어되는 경우 동일한 회로에서 큐비트 3으로 제어할 수 없습니다. 큐비트 1과 큐비트 2 사이에 제어가 적용되는 횟수에는 제약이 없습니다. 큐비트 2에서 활성 초기화를 수행하지 않는 한, 큐비트 2는 큐비트 3(또는 큐비트 1)으로 제어할 수 있습니다.

1. 제어는 동일한 그룹 내의 큐비트에만 적용할 수 있습니다. IQM Garnet 및 Emerald 디바이스의 큐비트 그룹은 다음 이미지에 있습니다.

1. 이러한 기능이 있는 프로그램은 축어적 프로그램으로 제출해야 합니다. 축어적 프로그램에 대한 자세한 내용은 [OpenQASM 3.0으로 축어적 컴파일](https://docs.aws.amazon.com/braket/latest/developerguide/braket-openqasm-verbatim-compilation.html)을 참조하세요.

**제한 사항:**

MCM은 프로그램에서 피드포워드 제어에만 사용할 수 있습니다. MCM 결과(0 또는 1)는 작업 결과의 일부로 반환되지 않습니다.

![\[왼쪽 이미지는 정사각형 격자 안에 2개의 큐비트 그룹이 있는 IQM Garnet 20큐비트 디바이스이고, 오른쪽 이미지는 정사각형 격자 안에 4개의 큐비트 그룹이 있는 IQM Emerald 54큐비트 디바이스입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/IQM-Garnet-Emerald-qubit-grouping.png)


이러한 이미지는 두 IQM 디바이스 모두에 대한 큐비트 그룹을 표시합니다. Garnet 20큐비트 디바이스에는 2개의 큐비트 그룹이 포함되어 있고, Emerald 54큐비트 디바이스에는 4개의 큐비트 그룹이 포함되어 있습니다.

**예**:

1. **활성 초기화를 통한 큐비트 재사용**

   조건부 초기화 연산을 지원하는 MCM은 단일 회로 실행 내에서 큐비트 재사용을 가능하게 합니다. 따라서 회로 깊이 요구 사항이 줄어들고 양자 디바이스 리소스 사용률이 향상됩니다.

1. **활성 비트 플립 보호**

   동적 회로는 비트 플립 오류를 감지하고 측정 결과에 따라 정정 연산을 적용합니다. 이 구현은 양자 오류 감지 실험 역할을 합니다.

1. **순간이동 실험**

   상태 순간이동은 로컬 양자 연산과 MCM의 고전적 정보를 사용하여 큐비트 상태를 전송합니다. 게이트 순간이동은 직접 양자 연산 없이 큐비트 간에 게이트를 구현합니다. 이러한 실험은 양자 오류 정정, 측정 기반 양자 컴퓨팅, 양자 통신이라는 세 가지 핵심 영역에서 기본적인 서브루틴을 보여줍니다.

1. **개방 양자 시스템 시뮬레이션**

   동적 회로는 데이터 큐비트 및 환경 얽힘과 환경 측정을 통해 양자 시스템의 노이즈를 모델링합니다. 이 접근 방식은 특정 큐비트를 사용하여 데이터 및 환경 요소를 나타냅니다. 노이즈 채널은 환경에 적용되는 게이트 및 측정을 통해 설계될 수 있습니다.

동적 회로 사용에 대한 자세한 내용은 [Amazon Braket 노트북 리포지토리](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/experimental_capabilities/dynamic_circuits)의 추가 예제를 참조하세요.

# Amazon Braket의 펄스 제어
<a name="braket-pulse-control"></a>

펄스는 양자 컴퓨터의 큐비트를 제어하는 아날로그 신호입니다. Amazon Braket의 특정 디바이스를 사용하면 펄스 제어 기능에 액세스하여 펄스를 사용해 회로를 제출할 수 있습니다. OpenQASM 3.0을 사용하여 Braket SDK를 통해 또는 Braket API를 통해 직접 펄스 제어에 액세스할 수 있습니다. 먼저 Braket의 펄스 제어에 대한 몇 가지 주요 개념을 소개합니다.

**Topics**
+ [프레임](#braket-frame)
+ [포트](#braket-port)
+ [파형](#braket-waveform)
+ [Hello Pulse 작업](braket-hello-pulse.md)
+ [펄스를 사용하여 네이티브 게이트에 액세스](braket-native-gate-pulse.md)

## 프레임
<a name="braket-frame"></a>

프레임은 양자 프로그램 내에서 시계 역할과 위상 역할을 모두 수행하는 소프트웨어 추상화입니다. 시계 시간은 각 사용량과 주파수로 정의된 상태 저장 캐리어 신호에 따라 증가합니다. 신호를 큐비트로 전송할 때 프레임은 큐비트의 캐리어 주파수, 위상 오프셋 및 파형 엔벨로프가 방출되는 시간을 결정합니다. Braket Pulse에서 프레임 구성은 디바이스, 주파수 및 위상에 따라 달라집니다. 디바이스에 따라 사전 정의된 프레임을 선택하거나 포트를 제공하여 새 프레임을 인스턴스화할 수 있습니다.

```
from braket.aws import AwsDevice
from braket.pulse import Frame, Port

# Predefined frame from a device
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
drive_frame = device.frames["Transmon_5_charge_tx"]

# Create a custom frame
readout_frame = Frame(frame_id="r0_measure", port=Port("channel_0", dt=1e-9), frequency=5e9, phase=0)
```

## 포트
<a name="braket-port"></a>

포트는 큐비트를 제어하는 모든 입력/출력 하드웨어 구성 요소를 나타내는 소프트웨어 추상화입니다. 이를 통해 하드웨어 공급업체는 사용자가 큐비트를 조작하고 관찰하기 위해 상호 작용할 수 있는 인터페이스를 제공할 수 있습니다. 포트는 커넥터의 이름을 나타내는 단일 문자열로 특성화됩니다. 또한 이 문자열은 파형을 얼마나 세밀하게 정의할 수 있는지를 지정하는 최소 시간 증분을 표시합니다.

```
from braket.pulse import Port

Port0 = Port("channel_0", dt=1e-9)
```

## 파형
<a name="braket-waveform"></a>

파형은 출력 포트에서 신호를 방출하거나 입력 포트를 통해 신호를 캡처하는 데 사용할 수 있는 시간 종속 엔벨로프입니다. 복소수 목록을 통해 또는 하드웨어 공급자로부터 목록을 생성하는 파형 템플릿을 사용하여 직접 파형을 지정할 수 있습니다.

```
from braket.pulse import ArbitraryWaveform, ConstantWaveform
import numpy as np

cst_wfm = ConstantWaveform(length=1e-7, iq=0.1)
arb_wf = ArbitraryWaveform(amplitudes=np.linspace(0, 100))
```

 Braket Pulse는 상수 파형, 가우시안 파형, DRAG(Derivative Removal by Adiabatic Gate) 파형을 포함한 표준 파형 라이브러리를 제공합니다. 다음 예제와 같이 `sample` 함수를 통해 파형 데이터를 검색하여 파형의 모양을 그릴 수 있습니다.

```
from braket.pulse import GaussianWaveform
import numpy as np
import matplotlib.pyplot as plt

zero_at_edge1 = GaussianWaveform(1e-7, 25e-9, 0.1, True)
# or zero_at_edge1 = GaussianWaveform(1e-7, 25e-9, 0.1)
zero_at_edge2 = GaussianWaveform(1e-7, 25e-9, 0.1, False)

times_1 = np.arange(0, zero_at_edge1.length, drive_frame.port.dt)
times_2 = np.arange(0, zero_at_edge2.length, drive_frame.port.dt)

plt.plot(times_1, zero_at_edge1.sample(drive_frame.port.dt))
plt.plot(times_2, zero_at_edge2.sample(drive_frame.port.dt))
```

![\[ZaE = True(하단 곡선) 및 ZaE = False(상단 곡선)의 두 가지 경우에 대해 시간 경과에 따른 진폭을 보여주는 그래프입니다. 곡선은 0.10a. u.의 진폭으로 약 0.5초에 정점을 이루는 종 모양을 갖습니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/gaussianwaveform.png)


위의 이미지는 `GaussianWaveform`에서 생성된 가우시안 파형을 보여줍니다. 펄스 길이 100ns, 너비 25ns, 진폭 0.1(임의 단위)을 선택했습니다. 파형은 펄스 창 중앙에 위치합니다. `GaussianWaveform`은 부울 인수`zero_at_edges`(범례의 ZaE)를 허용합니다. `True`로 설정하면 이 인수는 t=0 및 t=`length`의 점이 0이 되도록 가우시안 파형을 오프셋하고 최대값이 `amplitude` 인수에 해당하도록 진폭의 크기를 재조정합니다.

# Hello Pulse 작업
<a name="braket-hello-pulse"></a>

이 섹션에서는 Rigetti 디바이스에서 펄스를 사용하여 직접 단일 큐비트 게이트를 특성화하고 구성하는 방법을 알아봅니다. 큐비트에 전자기장을 가하면 Rabi 진동이 발생하여 큐비트가 0 상태와 1 상태 사이를 전환합니다. 펄스의 보정된 길이와 위상을 사용하면 Rabi 진동이 단일 큐비트 게이트를 계산할 수 있습니다. 여기서는 보다 복잡한 펄스 시퀀스를 빌드하는 데 사용되는 기본 블록인 pi/2 펄스를 측정하기 위한 최적의 펄스 길이를 결정합니다.

먼저 펄스 시퀀스를 빌드하려면 `PulseSequence` 클래스를 가져옵니다.

```
from braket.aws import AwsDevice
from braket.circuits import FreeParameter
from braket.devices import Devices
from braket.pulse import PulseSequence, GaussianWaveform

import numpy as np
```

그런 다음 QPU의 Amazon Resource Name(ARN)을 사용하여 새 Braket 디바이스를 인스턴스화합니다. 다음 코드 블록은 Rigetti Ankaa-3을 사용합니다.

```
device = AwsDevice(Devices.Rigetti.Ankaa3)
```

다음 펄스 시퀀스에는 파형 재생과 큐비트 측정이라는 두 가지 구성 요소가 포함됩니다. 펄스 시퀀스는 일반적으로 프레임에 적용할 수 있습니다. 장벽 및 지연과 같은 몇 가지 예외를 제외하고, 큐비트에 적용할 수 있습니다. 펄스 시퀀스를 구성하기 전에 사용 가능한 프레임을 검색해야 합니다. 드라이브 프레임은 Rabi 진동에 대한 펄스를 적용하는 데 사용되며, 판독 프레임은 큐비트 상태를 측정하는 데 사용됩니다. 이 예제에서는 큐비트 25의 프레임을 사용합니다.

```
drive_frame = device.frames["Transmon_25_charge_tx"]
readout_frame = device.frames["Transmon_25_readout_rx"]
```

이제 드라이브 프레임에서 재생할 파형을 생성합니다. 목표는 다양한 펄스 길이에 대한 큐비트의 동작을 특성화하는 것입니다. 매번 길이가 다른 파형을 재생합니다. 매번 새 파형을 인스턴스화하는 대신, Braket에서 지원하는 펄스 시퀀스 내 `FreeParameter`를 사용합니다. 자유 파라미터로 파형과 펄스 시퀀스를 한 번 생성한 다음, 다른 입력 값으로 동일한 펄스 시퀀스를 실행할 수 있습니다.

```
waveform = GaussianWaveform(FreeParameter("length"), FreeParameter("length") * 0.25, 0.2, False)
```

마지막으로, 펄스 시퀀스로 결합합니다. 펄스 시퀀스에서 `play`는 드라이브 프레임에서 지정된 파형을 재생하고 `capture_v0`은 판독 프레임에서 상태를 측정합니다.

```
pulse_sequence = (
    PulseSequence()
    .play(drive_frame, waveform)
    .capture_v0(readout_frame)
)
```

다양한 펄스 길이를 스캔하여 QPU에 제출합니다. QPU에서 펄스 시퀀스를 실행하기 전에 자유 파라미터의 값을 바인딩합니다.

```
start_length = 12e-9
end_length = 2e-7
lengths = np.arange(start_length, end_length, 12e-9)
N_shots = 100

tasks = [
    device.run(pulse_sequence(length=length), shots=N_shots)
    for length in lengths
]

probability_of_zero = [
    task.result().measurement_counts['0']/N_shots
    for task in tasks
]
```

큐비트 측정의 통계는 0 상태와 1 상태 사이에서 진동하는 큐비트의 진동 역학을 보여줍니다. 측정 데이터에서 Rabi 주파수를 추출하고 펄스 길이를 미세 조정하여 특정 1큐비트 게이트를 구현할 수 있습니다. 예를 들어 아래 그림의 데이터에서 주기성은 약 154ns입니다. 따라서 pi/2 회전 게이트는 길이=38.5ns인 펄스 시퀀스에 해당합니다.

![\[펄스 지속 시간에 대한 모집단 양을 초 단위로 보여주는 선 그래프입니다. 그래프에는 2개의 최고점과 1개의 최저점이 있습니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/Rabi-frequency.png)


## OpenPulse를 사용한 Hello Pulse
<a name="braket-hello-pulse-openpulse"></a>

 [OpenPulse](https://openqasm.com/language/openpulse.html)는 일반 양자 디바이스의 펄스 수준 제어를 지정하는 언어이며 OpenQASM 3.0 사양의 일부입니다. Amazon Braket은 OpenQASM 3.0 표현을 사용하여 펄스를 직접 프로그래밍할 수 있도록 OpenPulse를 지원합니다.

 Braket은 네이티브 명령에서 펄스를 표현하기 위한 기본 중간 표현으로 OpenPulse를 사용합니다. OpenPulse는 `defcal`(“define calibration”의 줄임말) 선언 형태로 명령 보정 추가를 지원합니다. 이러한 선언을 사용하면 저수준 제어 문법 내에서 게이트 명령의 구현을 지정할 수 있습니다.

다음 명령을 사용하여 Braket `PulseSequence`의 OpenPulse 프로그램을 볼 수 있습니다.

```
print(pulse_sequence.to_ir())
```

OpenPulse 프로그램을 직접 구성할 수도 있습니다.

```
from braket.ir.openqasm import Program
 
openpulse_script = """
OPENQASM 3.0;
cal {
    bit[1] psb;
    waveform my_waveform = gaussian(12.0ns, 3.0ns, 0.2, false);
    play(Transmon_25_charge_tx, my_waveform);
    psb[0] = capture_v0(Transmon_25_readout_rx);
}
"""
```

스크립트로 `Program` 객체를 생성합니다. 그런 다음 프로그램을 QPU에 제출합니다.

```
from braket.aws import AwsDevice
from braket.devices import Devices
from braket.ir.openqasm import Program

program = Program(source=openpulse_script)

device = AwsDevice(Devices.Rigetti.Ankaa3)
task = device.run(program, shots=100)
```

# 펄스를 사용하여 네이티브 게이트에 액세스
<a name="braket-native-gate-pulse"></a>

연구원은 특정 QPU에서 지원하는 *네이티브* 게이트가 어떻게 펄스로 구현되는지 정확히 알아야 하는 경우가 많습니다. 펄스 시퀀스는 하드웨어 공급자에 의해 주의 깊게 보정되지만, 이러한 시퀀스에 대한 액세스를 통해 연구원은 더 나은 게이트를 설계하거나 특정 게이트의 펄스를 확장하여 제로 노이즈 외삽과 같은 오류 완화를 위한 프로토콜을 탐구할 기회를 얻습니다.

Amazon Braket은 Rigetti의 네이티브 게이트에 대한 프로그래밍 방식 액세스를 지원합니다.

```
import math
from braket.aws import AwsDevice
from braket.circuits import Circuit, GateCalibrations, QubitSet
from braket.circuits.gates import Rx

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")

calibrations = device.gate_calibrations
print(f"Downloaded {len(calibrations)} calibrations.")
```

**참고**  
하드웨어 공급자는 종종 하루에 두 번 이상 QPU를 주기적으로 보정합니다. Braket SDK를 사용하면 최신 게이트 보정을 얻을 수 있습니다.

```
device.refresh_gate_calibrations()
```

RX 또는 XY 게이트와 같은 지정된 네이티브 게이트를 검색하려면 `Gate` 객체와 관심 대상 큐비트를 전달해야 합니다. 예를 들어 qubit 0에 적용된 RX(π/2)의 펄스 구현을 검사할 수 있습니다.

```
rx_pi_2_q0 = (Rx(math.pi/2), QubitSet(0))

pulse_sequence_rx_pi_2_q0 = calibrations.pulse_sequences[rx_pi_2_q0]
```

`filter` 함수를 사용하여 필터링된 보정 세트를 생성할 수 있습니다. 게이트 목록 또는 `QubitSet` 목록을 전달합니다. 다음 코드는 RX(π/2) 및 qubit 0에 대한 모든 보정을 포함하는 두 세트를 생성합니다.

```
rx_calibrations = calibrations.filter(gates=[Rx(math.pi/2)])
q0_calibrations = calibrations.filter(qubits=QubitSet([0]))
```

이제 사용자 지정 보정 세트를 연결하여 네이티브 게이트의 작업을 제공하거나 수정할 수 있습니다. 예를 들어 다음 회로를 고려합니다.

```
bell_circuit = (
    Circuit()
    .rx(0, math.pi/2)
    .rx(1, math.pi/2)
    .iswap(0, 1)
    .rx(1, -math.pi/2)
)
```

`PulseSequence` 객체의 딕셔너리를 `gate_definitions` 키워드 인수에 전달하여 `qubit 0`의 `rx` 게이트에 대한 사용자 지정 게이트 보정으로 실행할 수 있습니다. `GateCalibrations` 객체의 속성 `pulse_sequences`에서 딕셔너리를 구성할 수 있습니다. 지정되지 않은 모든 게이트는 양자 하드웨어 공급자의 펄스 보정으로 대체됩니다.

```
nb_shots = 50
custom_calibration = GateCalibrations({rx_pi_2_q0: pulse_sequence_rx_pi_2_q0})
task = device.run(bell_circuit, gate_definitions=custom_calibration.pulse_sequences, shots=nb_shots)
```

# 아날로그 해밀토니안 시뮬레이션
<a name="braket-analog-hamiltonian-simulation"></a>

[아날로그 해밀토니안 시뮬레이션](https://en.wikipedia.org/wiki/Hamiltonian_simulation)(AHS)은 기존 양자 회로 모델과는 현저히 다른 양자 컴퓨팅의 새로운 패러다임입니다. 각 회로가 한 번에 몇 개의 큐비트에서만 작동하는 게이트 시퀀스를 대신합니다. AHS 프로그램은 해당 해밀토니안의 시간 종속 및 공간 종속 파라미터로 정의됩니다. [시스템의 해밀토니안](https://en.wikipedia.org/wiki/Hamiltonian_(quantum_mechanics))은 에너지 준위와 외부 힘의 영향을 인코딩하며, 이는 상태의 시간 변화를 함께 제어합니다. N-큐비트 시스템의 경우 해밀토니안은 복소수의 2NX2N 정방 행렬로 표현할 수 있습니다.

AHS를 수행할 수 있는 양자 디바이스는 내부 제어 파라미터를 신중하게 튜닝하여 사용자 지정 해밀토니안에서 양자 시스템의 시간 변화를 밀접하게 근사화하도록 설계되었습니다. 결맞음 구동장의 진폭 조정 및 파라미터 디튜닝을 예로 들 수 있습니다. AHS 패러다임은 응집 물질 물리학 또는 양자 화학과 같이 상호 작용하는 입자가 많은 양자 시스템의 정적 및 동적 특성을 시뮬레이션하는 데 매우 적합합니다. QuEra의 [Aquila 디바이스](https://aws.amazon.com/braket/quantum-computers/quera/)와 같이 특수 제작된 양자 처리 장치(QPU)는 AHS의 장점을 사용하고 기존의 디지털 양자 컴퓨팅 접근 방식을 넘어 혁신적인 방식으로 문제를 해결하도록 개발되었습니다.

**Topics**
+ [Hello AHS: 첫 번째 아날로그 해밀토니안 시뮬레이션 실행](braket-get-started-hello-ahs.md)
+ [QuEra Aquila를 사용하여 아날로그 프로그램 제출](braket-quera-submitting-analog-program-aquila.md)

# Hello AHS: 첫 번째 아날로그 해밀토니안 시뮬레이션 실행
<a name="braket-get-started-hello-ahs"></a>

이 섹션에서는 첫 번째 아날로그 해밀토니안 시뮬레이션을 실행하는 방법에 대한 정보를 제공합니다.

**Topics**
+ [상호 작용 스핀 체인](#braket-get-started-interacting-spin-chain)
+ [배열](#braket-get-started-arrangement)
+ [상호 작용](#braket-get-started-interaction)
+ [구동장](#braket-get-started-driving-field)
+ [AHS 프로그램](#braket-get-started-ahs-program)
+ [로컬 시뮬레이터에서 실행](#braket-get-started-running-local-simulator)
+ [시뮬레이터 결과 분석](#braket-get-started-analyzing-simulator-results)
+ [QuEra의 Aquila QPU에서 실행](#braket-get-started-running-aquila-qpu)
+ [QPU 결과 분석](#braket-get-started-analyzing-qpu-results)
+ [다음 단계](#braket-get-started-ahs-next)

## 상호 작용 스핀 체인
<a name="braket-get-started-interacting-spin-chain"></a>

상호 작용하는 입자가 많은 시스템의 표준 예제로, 8개의 스핀으로 이루어진 고리를 생각해 보겠습니다(각각 “up” ∣↑⟩ 및 “down” ∣↓⟩ 상태일 수 있음). 이 모델 시스템은 비록 작지만, 이미 자연적으로 발생하는 자성 물질의 몇 가지 흥미로운 현상을 보여줍니다. 이 예제에서는 연속적인 스핀이 반대 방향을 가리키는 소위 반강자성 정렬을 준비하는 방법을 보여줍니다.

![\[위쪽 및 아래쪽 반전 화살표가 포함된 8개의 원 노드를 연결하는 다이어그램입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/AntiFerromagnetic.png)


## 배열
<a name="braket-get-started-arrangement"></a>

각 스핀을 나타내기 위해 하나의 중성 원자를 사용하며, “up” 및 “down” 스핀 상태는 각각 원자의 여기된 Rydberg 상태와 바닥 상태로 인코딩됩니다. 먼저 2차원 배열을 생성합니다. 다음 코드를 사용하여 위의 스핀 고리를 프로그래밍할 수 있습니다.

 **사전 조건**: [Braket SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk)를 pip 설치해야 합니다. (Braket 호스팅 노트북 인스턴스를 사용하는 경우 이 SDK는 노트북과 함께 사전 설치되어 제공됩니다.) 플롯을 재현하려면 shell 명령 `pip install matplotlib`을 사용하여 matplotlib을 별도로 설치해야 합니다.

```
from braket.ahs.atom_arrangement import AtomArrangement
import numpy as np
import matplotlib.pyplot as plt  # Required for plotting

a = 5.7e-6  # Nearest-neighbor separation (in meters)

register = AtomArrangement()
register.add(np.array([0.5, 0.5 + 1/np.sqrt(2)]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([-0.5, 0.5 + 1/np.sqrt(2)]) * a)
```

또한 다음으로 플롯할 수 있습니다.

```
fig, ax = plt.subplots(1, 1, figsize=(7, 7))
xs, ys = [register.coordinate_list(dim) for dim in (0, 1)]
ax.plot(xs, ys, 'r.', ms=15)

for idx, (x, y) in enumerate(zip(xs, ys)):
    ax.text(x, y, f" {idx}", fontsize=12)

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[두 축의 양수 값과 음수 값에 걸쳐 분포된 점을 보여주는 산점도 플롯입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/PlotNeutralAtoms.png)


## 상호 작용
<a name="braket-get-started-interaction"></a>

반강자성 위상을 준비하려면 이웃하는 스핀 간의 상호 작용을 유도해야 합니다. 이를 위해 [van der Waals 상호 작용](https://en.wikipedia.org/wiki/Van_der_Waals_force)을 사용합니다. 이 상호 작용은 기본적으로 중성 원자 디바이스(예: QuEra의 Aquila 디바이스)에 의해 구현됩니다. 스핀 표현을 사용하면 이 상호 작용에 대한 해밀토니안 항을 모든 스핀 쌍(j,k)에 대한 합으로 표현할 수 있습니다.

![\[모든 스핀 쌍(j,k)에 대한 합으로 표현된 이 상호 작용을 보여주는 해밀토니안 상호 작용 방정식입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/HInteraction.png)


여기서 nj​=∣↑j​⟩⟨↑j​∣는 스핀 j가 “up” 상태에 있는 경우에만 1, 그렇지 않으면 0의 값을 취하는 연산자입니다. 강도는 Vj,k​=C6​/(dj,k​)6이며, 여기서 C6은 고정 계수이고 dj,k는 스핀 j와 k 사이의 유클리드 거리입니다. 이 상호 작용 항의 즉각적인 효과는 스핀 j와 스핀 k가 “up”인 모든 상태의 에너지가 (Vj,k 만큼) 증가한다는 것입니다. AHS 프로그램의 나머지 부분을 신중하게 설계함으로써, 이 상호 작용은 이웃한 스핀이 모두 “up” 상태에 있는 것을 방지합니다. 이는 일반적으로 "Rydberg 봉쇄"로 알려진 효과입니다.

## 구동장
<a name="braket-get-started-driving-field"></a>

AHS 프로그램을 시작할 때 모든 스핀은 (기본적으로) “down” 상태에서 시작되며 소위 강자성 위상에 있습니다. 반강자성 위상을 준비한다는 목표를 염두에 두고, 이 상태에서 "up" 상태가 선호되는 다체 상태로 스핀을 원활하게 전환하는 시간 종속 결맞음 구동장을 지정합니다. 해당 해밀토니안은 다음과 같이 쓸 수 있습니다.

![\[해밀토니안 드라이브 함수의 계산을 나타내는 수학 방정식입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/HDrive.png)


여기서 Ω(t),ϕ(t),Δ(t)는 모든 스핀에 균일하게 영향을 미치는 구동장의 시간 종속 전역 진폭([Rabi 주파수](https://en.wikipedia.org/wiki/Rabi_frequency)라고도 함), 위상 및 디튜닝입니다. 여기서 S−,k​=∣↓k​⟩⟨↑k​∣and S\$1,k​​=(S−,k​)†=∣↑k​⟩⟨↓k​∣은 각각 스핀 k의 하강 및 상승 연산자이고, nk​=∣↑k​⟩⟨↑k​∣는 이전과 동일한 연산자입니다. 구동장의 Ω 부분은 모든 스핀의 "down" 상태와 "up" 상태를 동시에 일관되게 결합하고 Δ 부분은 "up" 상태에 대한 에너지 보상을 제어합니다.

강자성 위상에서 반강자성 위상으로의 원활한 전환을 프로그래밍하기 위해 다음 코드로 구동장을 지정합니다.

```
from braket.timings.time_series import TimeSeries
from braket.ahs.driving_field import DrivingField

# Smooth transition from "down" to "up" state
time_max = 4e-6  # seconds
time_ramp = 1e-7  # seconds
omega_max = 6300000.0  # rad / sec
delta_start = -5 * omega_max
delta_end = 5 * omega_max

omega = TimeSeries()
omega.put(0.0, 0.0)
omega.put(time_ramp, omega_max)
omega.put(time_max - time_ramp, omega_max)
omega.put(time_max, 0.0)

delta = TimeSeries()
delta.put(0.0, delta_start)
delta.put(time_ramp, delta_start)
delta.put(time_max - time_ramp, delta_end)
delta.put(time_max, delta_end)

phi = TimeSeries().put(0.0, 0.0).put(time_max, 0.0)

drive = DrivingField(
   amplitude=omega,
   phase=phi,
   detuning=delta
)
```

다음 스크립트를 사용하여 구동장의 시계열을 시각화할 수 있습니다.

```
fig, axes = plt.subplots(3, 1, figsize=(12, 7), sharex=True)

ax = axes[0]
time_series = drive.amplitude.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Omega [rad/s]')

ax = axes[1]
time_series = drive.detuning.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Delta [rad/s]')

ax = axes[2]
time_series = drive.phase.time_series
# Note: time series of phase is understood as a piecewise constant function
ax.step(time_series.times(), time_series.values(), '.-', where='post')
ax.set_ylabel('phi [rad]')
ax.grid()
ax.set_xlabel('time [s]')

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[시간 경과에 따른 phi, delta 및 omega를 보여주는 세 가지 그래프입니다. 상단 서브플롯은 6rad/s를 약간 넘는 수준까지 증가한 후 4초 동안 유지되다가 다시 0으로 떨어지는 모습을 보여줍니다. 중간 서브플롯은 이에 상응하는 미분값의 선형 증가를 나타내며, 하단 서브플롯은 0에 가까운 평평한 선을 보여줍니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/DrivingTimeSeries.png)


## AHS 프로그램
<a name="braket-get-started-ahs-program"></a>

레지스터, 구동장(및 암시적 van der Waals 상호 작용)은 아날로그 해밀토니안 시뮬레이션 프로그램 `ahs_program`을 구성합니다.

```
from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation

ahs_program = AnalogHamiltonianSimulation(
   register=register,
   hamiltonian=drive
)
```

## 로컬 시뮬레이터에서 실행
<a name="braket-get-started-running-local-simulator"></a>

이 예제는 작기 때문에(스핀 수 15회 미만), AHS 호환 QPU에서 실행하기 전에 Braket SDK와 함께 제공되는 로컬 AHS 시뮬레이터에서 실행할 수 있습니다. Braket SDK를 통해 로컬 시뮬레이터를 무료로 사용할 수 있으므로, 이는 코드가 올바르게 실행될 수 있도록 보장하는 모범 사례입니다.

여기서는 로컬 시뮬레이터가 양자 상태의 시간 변화를 추적하고 최종 상태에서 샘플을 추출하므로 샷 수를 높은 값(예: 100만)으로 설정할 수 있습니다. 따라서 샷 수가 늘어나더라도 총 실행 시간은 약간만 증가합니다.

```
from braket.devices import LocalSimulator

device = LocalSimulator("braket_ahs")

result_simulator = device.run(
   ahs_program,
   shots=1_000_000
).result()  # Takes about 5 seconds
```

## 시뮬레이터 결과 분석
<a name="braket-get-started-analyzing-simulator-results"></a>

각 스핀의 상태("down"은 "d", "up"은 "u", 빈 위치는 "e"일 수 있음)를 추론하고 각 구성이 샷 전체에서 발생한 횟수를 계산하는 다음 함수를 사용하여 샷 결과를 집계할 수 있습니다.

```
from collections import Counter


def get_counts(result):
    """Aggregate state counts from AHS shot results

    A count of strings (of length = # of spins) are returned, where
    each character denotes the state of a spin (site):
      e: empty site
      u: up state spin
      d: down state spin

    Args:
      result (braket.tasks.analog_hamiltonian_simulation_quantum_task_result.AnalogHamiltonianSimulationQuantumTaskResult)

    Returns
       dict: number of times each state configuration is measured

    """
    state_counts = Counter()
    states = ['e', 'u', 'd']
    for shot in result.measurements:
        pre = shot.pre_sequence
        post = shot.post_sequence
        state_idx = np.array(pre) * (1 + np.array(post))
        state = "".join(map(lambda s_idx: states[s_idx], state_idx))
        state_counts.update((state,))
    return dict(state_counts)


counts_simulator = get_counts(result_simulator)  # Takes about 5 seconds
print(counts_simulator)
```

```
*[Output]*
{'dddddddd': 5, 'dddddddu': 12, 'ddddddud': 15, ...}
```

다음 `counts`는 샷 전체에서 각 상태 구성이 관찰된 횟수를 계산하는 딕셔너리입니다. 다음 코드로 시각화할 수도 있습니다.

```
from collections import Counter


def has_neighboring_up_states(state):
    if 'uu' in state:
        return True
    if state[0] == 'u' and state[-1] == 'u':
        return True
    return False


def number_of_up_states(state):
    return Counter(state)['u']


def plot_counts(counts):
    non_blockaded = []
    blockaded = []
    for state, count in counts.items():
        if not has_neighboring_up_states(state):
            collection = non_blockaded
        else:
            collection = blockaded
        collection.append((state, count, number_of_up_states(state)))

    blockaded.sort(key=lambda _: _[1], reverse=True)
    non_blockaded.sort(key=lambda _: _[1], reverse=True)

    for configurations, name in zip((non_blockaded,
                                     blockaded),
                                    ('no neighboring "up" states',
                                     'some neighboring "up" states')):
        plt.figure(figsize=(14, 3))
        plt.bar(range(len(configurations)), [item[1] for item in configurations])
        plt.xticks(range(len(configurations)))
        plt.gca().set_xticklabels([item[0] for item in configurations], rotation=90)
        plt.ylabel('shots')
        plt.grid(axis='y')
        plt.title(f'{name} configurations')
        plt.show()


plot_counts(counts_simulator)
```

![\[이웃하는 "up" 상태 구성이 없는 많은 수의 샷을 보여주는 막대 차트입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/AHSCounts1.png)


![\[1.0 샷에 4개의 상태가 있는 일부 이웃하는 "up" 상태 구성의 샷을 보여주는 막대 차트입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/AHSCounts2.png)


플롯에서 다음과 같은 관찰 가능 항목을 읽고 반강자성 위상을 성공적으로 준비했는지 확인할 수 있습니다.

1. 일반적으로, 비차단 상태(두 개의 이웃하는 스핀이 “up” 상태에 있지 않음)는 하나 이상의 이웃하는 스핀 쌍이 모두 “up” 상태에 있는 상태보다 더 일반적입니다.

1. 일반적으로 구성이 차단되지 않는 한 "up" 여기가 더 많은 상태가 선호됩니다.

1. 가장 일반적인 상태는 실제로 완벽한 반강자성 상태 `"dudududu"` 및 `"udududud"`입니다.

1. 두 번째로 일반적인 상태는 연속 분리가 1, 2, 2인 3개의 “up” 여기만 존재하는 상태입니다. 이는 van der Waals 상호 작용이 다음으로 가까운 이웃에도 (비록 훨씬 작지만) 영향을 미친다는 것을 보여줍니다.

## QuEra의 Aquila QPU에서 실행
<a name="braket-get-started-running-aquila-qpu"></a>

 **사전 조건**: Braket [SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk)를 pip 설치하는 것 외에도, Amazon Braket을 처음 사용하는 경우 필요한 [시작하기 단계](https://docs.aws.amazon.com/braket/latest/developerguide/braket-get-started.html)를 완료했는지 확인합니다.

**참고**  
Braket 호스팅 노트북 인스턴스를 사용하는 경우 Braket SDK는 인스턴스와 함께 사전 설치되어 제공됩니다.

모든 종속성이 설치된 상태에서 Aquila QPU에 연결할 수 있습니다.

```
from braket.aws import AwsDevice

aquila_qpu = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")
```

AHS 프로그램을 QuEra 시스템에 적합하게 만들려면 Aquila QPU에서 허용하는 정밀도 수준에 부합하도록 모든 값을 반올림해야 합니다. (이러한 요구 사항은 이름에 “분해능”이 있는 디바이스 파라미터에 의해 관리됩니다. 노트북에서 `aquila_qpu.properties.dict()`를 실행하면 확인할 수 있습니다. Aquila의 기능 및 요구 사항에 대한 자세한 내용은 [Aquila 소개](https://github.com/aws/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/01_Introduction_to_Aquila.ipynb) 노트북을 참조하세요.) `discretize` 메서드를 직접적으로 호출하여 이 작업을 수행할 수 있습니다.

```
discretized_ahs_program = ahs_program.discretize(aquila_qpu)
```

이제 Aquila QPU에서 프로그램(현재는 100회 샷만 실행)을 실행할 수 있습니다.

**참고**  
Aquila 프로세서에서 이 프로그램을 실행하면 비용이 발생합니다. Amazon Braket SDK에는 고객이 비용 한도를 설정하고 거의 실시간으로 비용을 추적할 수 있는 [Cost Tracker](https://aws.amazon.com/blogs/quantum-computing/managing-the-cost-of-your-experiments-in-amazon-braket/)가 포함되어 있습니다.

```
task = aquila_qpu.run(discretized_ahs_program, shots=100)

metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: CREATED
```

양자 작업 실행 시간은 가용성 창과 QPU 사용률에 따라 크게 달라질 수 있으므로, 양자 작업 ARN을 기록해 두는 것이 좋습니다. 그러면 나중에 다음 코드 조각을 사용하여 작업 상태를 확인할 수 있습니다.

```
# Optionally, in a new python session
from braket.aws import AwsQuantumTask

SAVED_TASK_ARN = "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef"

task = AwsQuantumTask(arn=SAVED_TASK_ARN)
metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: COMPLETED
```

상태가 COMPLETED(Amazon Braket [콘솔](https://us-east-1.console.aws.amazon.com/braket/home?region=us-east-1#/tasks)의 양자 작업 페이지에서도 확인할 수 있음)가 되면 다음을 사용하여 결과를 쿼리할 수 있습니다.

```
result_aquila = task.result()
```

## QPU 결과 분석
<a name="braket-get-started-analyzing-qpu-results"></a>

이전과 동일한 `get_counts` 함수를 사용하여 개수를 계산할 수 있습니다.

```
counts_aquila = get_counts(result_aquila)
   print(counts_aquila)
```

```
*[Output]*
{'dddududd': 2, 'dudududu': 18, 'ddududud': 4, ...}
```

그리고 `plot_counts`로 플롯합니다.

```
plot_counts(counts_aquila)
```

![\[이웃하는 "up" 상태 구성이 없는 많은 수의 샷을 보여주는 막대 차트입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/QPUPlotCounts1.png)


![\[1.0 샷에 4개의 상태가 있는 일부 이웃하는 "up" 상태 구성의 샷을 보여주는 막대 차트입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/QPUPlotCounts2.png)


일부 샷에는 빈 위치("e"로 표시)가 있습니다. 이는 Aquila QPU의 원자당 1\$12%에 달하는 준비 결함에 의한 것입니다. 이 외에도, 결과는 적은 샷 수로 인해 예상되는 통계적 변동 내에서 시뮬레이션과 일치합니다.

## 다음 단계
<a name="braket-get-started-ahs-next"></a>

축하합니다, 이제 로컬 AHS 시뮬레이터와 Aquila QPU를 사용하여 Amazon Braket에서 첫 번째 AHS 워크로드를 실행하셨습니다.

Rydberg 물리학, 아날로그 해밀토니안 시뮬레이션 및 Aquila 디바이스에 대해 자세히 알아보려면 [예제 노트북](https://github.com/aws/amazon-braket-examples/tree/main/examples/analog_hamiltonian_simulation)을 참조하세요.

# QuEra Aquila를 사용하여 아날로그 프로그램 제출
<a name="braket-quera-submitting-analog-program-aquila"></a>

이 페이지에서는 QuEra의 Aquila 시스템 기능에 대한 포괄적인 설명서를 제공합니다. 여기서 다루는 세부 정보는 다음과 같습니다.

1. Aquila가 시뮬레이션한 매개변수화된 해밀토니안

1. AHS 프로그램 파라미터

1. AHS 결과 내용

1. Aquila 기능 파라미터

**Topics**
+ [해밀토니안](#braket-quera-aquila-device-hamiltonian)
+ [Braket AHS 프로그램 스키마](#braket-quera-ahs-program-schema)
+ [Braket AHS 작업 결과 스키마](#braket-quera-ahs-task-result-schema)
+ [QuEra 디바이스 속성 스키마](#braket-quera-device-properties-schema)

## 해밀토니안
<a name="braket-quera-aquila-device-hamiltonian"></a>

QuEra의 Aquila 시스템은 기본적으로 다음 (시간 종속) 해밀토니안을 시뮬레이션합니다.

![\[드라이브, 로컬 디튜닝 및 점 간 결합 항을 포함하는 시스템의 해밀토니안을 나타내는 합계가 포함된 수학 방정식입니다.\]](http://docs.aws.amazon.com/ko_kr/braket/latest/developerguide/images/TimeDependentDrivingHamiltonian.png)


**참고**  
로컬 디튜닝에 대한 액세스는 [실험 기능](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html)이며 Braket Direct를 통해 요청하여 사용할 수 있습니다.

where
+ Hdrive,k​(t)=( 1/2 ​Ω(t)eiϕ(t)S−,k​ \$1 1/2 ​Ω(t)e−iϕ(t) S\$1,k​) \$1 (−Δglobal​(t)nk​),
  + Ω(t)는 시간 종속 전역 구동 진폭(Rabi 주파수라고도 함)으로, 단위는 (rad/s)입니다.
  + ϕ(t)는 라디안 단위로 측정되는 시간 종속 전역 위상입니다.
  + S−,k​와 S\$1,k​는 원자 k의 스핀 강하 및 상승 연산자입니다(기저 상태에서 \$1↓⟩=\$1g⟩, \$1↑⟩=\$1r⟩, 이는 S−​=\$1g⟩⟨r\$1, S\$1​=(S−​)†=\$1r⟩⟨g\$1).
  + Δglobal​(t)는 시간 종속 전역 디튜닝입니다.
  + nk는 원자 k의 Rydberg 상태에 대한 사영 연산자입니다(즉, n=\$1r⟩⟨r\$1).
+ Hlocal detuning,k(t)=-Δlocal(t)hknk
  + Δlocal(t)는 (rad/s) 단위로 나타낸 로컬 주파수 이동의 시간 종속 인자입니다.
  + hk는 위치 종속 인자로, 0.0에서 1.0 사이의 무차원수입니다.
+ Vvdw,k,l​=C6​/(dk,l​)6nk​nl​,
  + C6은​van der Waals 계수로, 단위는 (rad / s) \$1 (m)^6입니다.
  + dk,l은 원자 k와 l 사이의 유클리드 거리로, 미터 단위로 측정됩니다.

사용자는 Braket AHS 프로그램 스키마를 통해 다음 파라미터를 제어할 수 있습니다.
+ 2차원 원자 배열(각 원자 k의 xk​ 및 yk​ 좌표, um 단위)로, k,l=1,2,…N으로 쌍별 원자 거리 dk,l​을 제어합니다.
+ Ω(t)는 시간 종속 전역 구동 주파수로, 단위는 (rad/s)입니다.
+ ϕ(t)는 시간 종속 전역 위상으로, 단위는 (rad)입니다.
+ Δglobal​(t)는 시간 종속 전역 디튜닝으로, 단위는 (rad/s)입니다.
+ Δlocal(t)는 로컬 디튜닝 크기의 시간 종속 (전역) 인자로, 단위는 (rad/s)입니다.
+ hk는 로컬 디튜닝 크기의 (정적) 위치 종속 인자로, 0.0에서 1.0 사이의 무차원수입니다.

**참고**  
사용자는 관련된 수준(즉, S−​,S\$1​, n 연산자가 고정됨)이나 Rydberg-Rydberg 상호 작용 계수(C6)의 강도를 제어할 수 없습니다.

## Braket AHS 프로그램 스키마
<a name="braket-quera-ahs-program-schema"></a>

 **braket.ir.ahs.program\$1v1.Program 객체**(예제)

**참고**  
계정에 대해 [로컬 디튜닝](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning) 기능이 활성화되지 않은 경우 다음 예제에서 `localDetuning=[]`을 사용합니다.

```
Program(
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.ir.ahs.program',
        version='1'
    ),
    setup=Setup(
        ahs_register=AtomArrangement(
            sites=[
                [Decimal('0'), Decimal('0')],
                [Decimal('0'), Decimal('4e-6')],
                [Decimal('4e-6'), Decimal('0')]
            ],
            filling=[1, 1, 1]
        )
    ),
    hamiltonian=Hamiltonian(
        drivingFields=[
            DrivingField(
                amplitude=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('15700000.0'), Decimal('15700000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                phase=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                detuning=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('-54000000.0'), Decimal('54000000.0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                )
            )
        ],
        localDetuning=[
            LocalDetuning(
                magnitude=PhysicalField(
                    times_series=TimeSeries(
                        values=[Decimal('0'), Decimal('25000000.0'), Decimal('25000000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern=Pattern([Decimal('0.8'), Decimal('1.0'), Decimal('0.9')])
                )
            )
        ]
    )
)
```

**JSON**(예제)

**참고**  
계정에 대해 [로컬 디튜닝](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning) 기능이 활성화되지 않은 경우 다음 예제에서 `"localDetuning": []`을 사용합니다.

```
{
    "braketSchemaHeader": {
        "name": "braket.ir.ahs.program",
        "version": "1"
    },
    "setup": {
        "ahs_register": {
            "sites": [
                [0E-7, 0E-7], 
                [0E-7, 4E-6],
                [4E-6, 0E-7]
            ],
            "filling": [1, 1, 1]
        }
    },
    "hamiltonian": {
        "drivingFields": [
            {
                "amplitude": {
                    "time_series": {
                        "values": [0.0, 15700000.0, 15700000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "phase": {
                    "time_series": {
                        "values": [0E-7, 0E-7],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "detuning": {
                    "time_series": {
                        "values": [-54000000.0, 54000000.0],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                }
            }
        ],
        "localDetuning": [
            {
                "magnitude": {
                    "time_series": {
                        "values": [0.0, 25000000.0, 25000000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": [0.8, 1.0, 0.9]
                }
            }
        ]
    }
}
```


**기본 필드**  

| 프로그램 필드 | type | description | 
| --- | --- | --- | 
|  setup.ahs\$1register.sites  |  List[List[Decimal]]  |  핀셋이 원자를 포획하는 2차원 좌표 목록  | 
|  setup.ahs\$1register.filling  |  List[int]  |  트랩 위치를 차지하는 원자는 1로, 빈 위치는 0으로 표시  | 
|  hamiltonian.drivingFields[].amplitude.time\$1series.times  |  List[Decimal]  |  구동 진폭의 시점, Omega(t)  | 
|  hamiltonian.drivingFields[].amplitude.time\$1series.values  |  List[Decimal]  |  구동 진폭의 값, Omega(t)  | 
|  hamiltonian.drivingFields[].amplitude.pattern  |  str  |  구동 진폭의 공간 패턴, Omega(t). 'uniform'이어야 함  | 
|  hamiltonian.drivingFields[].phase.time\$1series.times  |  List[Decimal]  |  구동 위상의 시점, phi(t)  | 
|  hamiltonian.drivingFields[].phase.time\$1series.values  |  List[Decimal]  |  구동 위상의 값, phi(t)  | 
|  hamiltonian.drivingFields[].phase.pattern  |  str  |  구동 위상의 공간 패턴, phi(t). 'uniform'이어야 함  | 
|  hamiltonian.drivingFields[].detuning.time\$1series.times  |  List[Decimal]  |  구동 디튜닝의 시점, Delta\$1global(t)  | 
|  hamiltonian.drivingFields[].detuning.time\$1series.values  |  List[Decimal]  |  구동 디튜닝의 값, Delta\$1global(t)  | 
|  hamiltonian.drivingFields[].detuning.pattern  |  str  |  구동 디튜닝의 공간 패턴, Delta\$1global(t). 'uniform'이어야 함  | 
|  hamiltonian.localDetuning[].magnitude.time\$1series.times  |  List[Decimal]  |  로컬 디튜닝 크기의 시간 종속 인자의 시점, Delta\$1local(t)  | 
|  hamiltonian.localDetuning[].magnitude.time\$1series.values  |  List[Decimal]  |  로컬 디튜닝 크기의 시간 종속 인자의 값, Delta\$1local(t)  | 
|  hamiltonian.localDetuning[].magnitude.pattern  |  List[Decimal]  |  로컬 디튜닝 크기의 위치 종속 인자, h\$1k(값은 setup.ahs\$1register.sites의 위치에 해당)  | 


**메타데이터 필드**  

| 프로그램 필드 | type | description | 
| --- | --- | --- | 
|  braketSchemaHeader.name  |  str  |  스키마의 이름. 'braket.ir.ahs.program'이어야 함  | 
|  braketSchemaHeader.version  |  str  |  스키마 버전  | 

## Braket AHS 작업 결과 스키마
<a name="braket-quera-ahs-task-result-schema"></a>

 **braket.tasks.analog\$1hamiltonian\$1simulation\$1quantum\$1task\$1result.AnalogHamiltonianSimulationQuantumTaskResult**(예제)

```
AnalogHamiltonianSimulationQuantumTaskResult(
    task_metadata=TaskMetadata(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.task_result.task_metadata',
            version='1'
        ),
        id='arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef',
        shots=2,
        deviceId='arn:aws:braket:us-east-1::device/qpu/quera/Aquila',
        deviceParameters=None,
        createdAt='2022-10-25T20:59:10.788Z',
        endedAt='2022-10-25T21:00:58.218Z',
        status='COMPLETED',
        failureReason=None
    ),
    measurements=[
        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 1, 1]),
            post_sequence=array([0, 1, 1, 1])
        ),

        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 0, 1]),
            post_sequence=array([1, 0, 0, 0])
        )
    ]
)
```

 **JSON**(예제)

```
{
    "braketSchemaHeader": {
        "name": "braket.task_result.analog_hamiltonian_simulation_task_result",
        "version": "1"
    },
    "taskMetadata": {
        "braketSchemaHeader": {
            "name": "braket.task_result.task_metadata",
            "version": "1"
        },
        "id": "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef",
        "shots": 2,
        "deviceId": "arn:aws:braket:us-east-1::device/qpu/quera/Aquila",

        "createdAt": "2022-10-25T20:59:10.788Z",
        "endedAt": "2022-10-25T21:00:58.218Z",
        "status": "COMPLETED"

    },
    "measurements": [
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 1, 1],
                "postSequence": [0, 1, 1, 1]
            }
        },
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 0, 1],
                "postSequence": [1, 0, 0, 0]
            }
        }
    ],
    "additionalMetadata": {
        "action": {...}
        "queraMetadata": {
            "braketSchemaHeader": {
                "name": "braket.task_result.quera_metadata",
                "version": "1"
            },
            "numSuccessfulShots": 100
        }
    }
}
```


**기본 필드**  

| 작업 결과 필드 | type | description | 
| --- | --- | --- | 
|  measurements[].shotResult.preSequence  |  List[int]  |  각 샷에 대한 사전 시퀀스 측정 비트(각 원자성 위치마다 하나씩): 위치가 비어 있는 경우 0, 위치가 채워진 경우 1, 양자 진화를 실행하는 펄스 시퀀스 전에 측정됨  | 
|  measurements[].shotResult.postSequence  |  List[int]  |  각 샷에 대한 사후 시퀀스 측정 비트: 원자가 Rydberg 상태에 있거나 위치가 비어 있는 경우 0, 원자가 바닥 상태에 있는 경우 1, 양자 진화를 실행하는 펄스 시퀀스 종료 시 측정됨  | 


**메타데이터 필드**  

| 작업 결과 필드 | type | description | 
| --- | --- | --- | 
|  braketSchemaHeader.name  |  str  |  스키마의 이름. 'braket.task\$1result.analog\$1hamiltonian\$1simulation\$1task\$1result'여야 함  | 
|  braketSchemaHeader.version  |  str  |  스키마 버전  | 
|  taskMetadata.braketSchemaHeader.name  |  str  |  스키마의 이름, ‘braket.task\$1result.task\$1metadata'여야 함  | 
|  taskMetadata.braketSchemaHeader.version  |  str  |  스키마 버전  | 
|  taskMetadata.id  |  str  |  양자 작업의 ID입니다. AWS 양자 작업의 경우 양자 작업 ARN입니다.  | 
|  taskMetadata.shots  |  int  |  양자 작업에 대한 샷 수입니다.  | 
|  taskMetadata.shots.deviceId  |  str  |  양자 작업이 실행된 디바이스의 ID입니다. AWS 디바이스의 경우 디바이스 ARN입니다.  | 
|  taskMetadata.shots.createdAt  |  str  |  생성 타임스탬프입니다. 형식은 ISO-8601/RFC3339 문자열 형식 YYYY-MM-DDTHH:mm:ss.sssZ여야 합니다. 기본값은 '없음'입니다.  | 
|  taskMetadata.shots.endedAt  |  str  |  양자 작업이 종료된 시점의 타임스탬프입니다. 형식은 ISO-8601/RFC3339 문자열 형식 YYYY-MM-DDTHH:mm:ss.sssZ여야 합니다. 기본값은 '없음'입니다.  | 
|  taskMetadata.shots.status  |  str  |  양자 작업의 상태(CREATED, QUEUED, RUNNING, COMPLETED, FAILED)입니다. 기본값은 '없음'입니다.  | 
|  taskMetadata.shots.failureReason  |  str  |  양자 작업의 실패 이유입니다. 기본값은 '없음'입니다.  | 
|  additionalMetadata.action  |  braket.ir.ahs.program\$1v1.Program  |  ([Braket AHS program schema](#braket-quera-ahs-program-schema) 섹션 참조)  | 
|  additionalMetadata.action.braketSchemaHeader.queraMetadata.name  |  str  |  스키마의 이름. 'braket.task\$1result.quera\$1metadata'여야 함  | 
|  additionalMetadata.action.braketSchemaHeader.queraMetadata.version  |  str  |  스키마 버전  | 
|  additionalMetadata.action.numSuccessfulShots  |  int  |  완전히 성공한 샷 수. 요청된 샷 수와 같아야 함  | 
|  measurements[].shotMetadata.shotStatus  |  int  |  샷 상태(성공, 부분 성공, 실패). "성공"이어야 함  | 

## QuEra 디바이스 속성 스키마
<a name="braket-quera-device-properties-schema"></a>

 **braket.device\$1schema.quera.quera\$1device\$1capabilities\$1v1.QueraDeviceCapabilities**(예제)

```
QueraDeviceCapabilities(
    service=DeviceServiceProperties(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.device_schema.device_service_properties', 
            version='1'
            ), 
            executionWindows=[
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.MONDAY: 'Monday'>, 
                    windowStartHour=datetime.time(1, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.TUESDAY: 'Tuesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.WEDNESDAY: 'Wednesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.FRIDAY: 'Friday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SATURDAY: 'Saturday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SUNDAY: 'Sunday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                )
            ], 
            shotsRange=(1, 1000), 
            deviceCost=DeviceCost(
                price=0.01, 
                unit='shot'
            ), 
            deviceDocumentation=
                DeviceDocumentation(
                    imageUrl='https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png', 
                    summary='Analog quantum processor based on neutral atom arrays', 
                    externalDocumentationUrl='https://www.quera.com/aquila'
                ), 
                deviceLocation='Boston, USA', 
                updatedAt=datetime.datetime(2024, 1, 22, 12, 0, tzinfo=datetime.timezone.utc), 
                getTaskPollIntervalMillis=None
    ), 
    action={
        <DeviceActionType.AHS: 'braket.ir.ahs.program'>: DeviceActionProperties(
                version=['1'], 
                actionType=<DeviceActionType.AHS: 'braket.ir.ahs.program'>
            )
    }, 
    deviceParameters={}, 
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.device_schema.quera.quera_device_capabilities', 
        version='1'
    ), 
    paradigm=QueraAhsParadigmProperties(
        ...
        # See https://github.com/amazon-braket/amazon-braket-schemas-python/blob/main/src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py
        ...
    )  
)
```

 **JSON**(예제)

```
{
    "service": {
        "braketSchemaHeader": {
            "name": "braket.device_schema.device_service_properties",
            "version": "1"
        },
        "executionWindows": [
            {
                "executionDay": "Monday",
                "windowStartHour": "01:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Tuesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Wednesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Friday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Saturday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Sunday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            }
        ],
        "shotsRange": [
            1,
            1000
        ],
        "deviceCost": {
            "price": 0.01,
            "unit": "shot"
        },
        "deviceDocumentation": {
            "imageUrl": "https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png",
            "summary": "Analog quantum processor based on neutral atom arrays",
            "externalDocumentationUrl": "https://www.quera.com/aquila"
        },
        "deviceLocation": "Boston, USA",
        "updatedAt": "2024-01-22T12:00:00+00:00"
    },
    "action": {
        "braket.ir.ahs.program": {
            "version": [
                "1"
            ],
            "actionType": "braket.ir.ahs.program"
        }
    },
    "deviceParameters": {},
    "braketSchemaHeader": {
        "name": "braket.device_schema.quera.quera_device_capabilities",
        "version": "1"
    },
    "paradigm": {
        ...
        # See Aquila device page > "Calibration" tab > "JSON" page
        ...
    }
}
```


**서비스 속성 필드**  

| 서비스 속성 필드 | type | description | 
| --- | --- | --- | 
|  service.executionWindows[].executionDay  |  ExecutionDay  |  실행 기간의 일 수. '매일', '평일', '주말', '월요일', '화요일', '수요일', 목요일', '금요일', '토요일' 또는 '일요일'이어야 함  | 
|  service.executionWindows[].windowStartHour  |  datetime.time  |  실행 기간이 시작되는 시간의 UTC 24시간 형식  | 
|  service.executionWindows[].windowEndHour  |  datetime.time  |  실행 기간이 종료되는 시간의 UTC 24시간 형식  | 
|  service.qpu\$1capabilities.service.shotsRange  |  Tuple[int, int]  |  디바이스의 최소 및 최대 샷 수  | 
|  service.qpu\$1capabilities.service.deviceCost.price  |  실수  |  미국 달러 기준 디바이스 요금  | 
|  service.qpu\$1capabilities.service.deviceCost.unit  |  str  |  요금 청구 단위, 예: '분', '시간', '샷', '작업'  | 


**메타데이터 필드**  

| 메타데이터 필드 | type | description | 
| --- | --- | --- | 
|  action[].version  |  str  |  AHS 프로그램 스키마 버전  | 
|  action[].actionType  |  ActionType  |  AHS 프로그램 스키마 이름. 'braket.ir.ahs.program'이어야 함  | 
|  service.braketSchemaHeader.name  |  str  |  스키마의 이름. 'braket.device\$1schema.device\$1service\$1properties'여야 함  | 
|  service.braketSchemaHeader.version  |  str  |  스키마 버전  | 
|  service.deviceDocumentation.imageUrl  |  str  |  디바이스 이미지의 URL  | 
|  service.deviceDocumentation.summary  |  str  |  디바이스에 대한 간략한 설명  | 
|  service.deviceDocumentation.externalDocumentationUrl  |  str  |  외부 설명서 URL  | 
|  service.deviceLocation  |  str  |  디바이스의 지리적 위치  | 
|  service.updatedAt  |  datetime  |  디바이스 속성이 마지막으로 업데이트된 시간  | 

# AWS Boto3 작업
<a name="braket-using-boto3"></a>

Boto3는 Python용 AWS SDK입니다. Python 개발자는 Boto3를 사용하여 Amazon Braket과 같은를 생성 AWS 서비스, 구성 및 관리할 수 있습니다. Boto3은 객체 지향 API와 Amazon Braket에 대한 저수준 액세스를 제공합니다.

[Boto3 Quickstart 가이드](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html)의 지침에 따라 Boto3을 설치하고 구성하는 방법을 알아봅니다.

Boto3은 Amazon Braket Python SDK와 함께 작동하면서 양자 작업을 구성하고 실행하는 데 도움이 되는 핵심 기능을 제공합니다. Python 고객은 항상 Boto3을 설치해야 합니다. 이는 핵심 구현이기 때문입니다. 추가 헬퍼 메서드를 사용하려면 Amazon Braket SDK도 설치해야 합니다.

예를 들어 `CreateQuantumTask`를 직접적으로 호출하면 Amazon Braket SDK가 Boto3에 요청을 제출한 다음 AWS API를 직접적으로 호출합니다.

**Topics**
+ [Amazon Braket Boto3 클라이언트 켜기](braket-using-boto3-client.md)
+ [Boto3 및 Braket SDK에 대한 AWS CLI 프로파일 구성](braket-using-boto3-profiles.md)

# Amazon Braket Boto3 클라이언트 켜기
<a name="braket-using-boto3-client"></a>

Amazon Braket에서 Boto3을 사용하려면 Boto3을 가져온 다음 Amazon Braket API에 연결하는 데 사용하는 클라이언트를 정의해야 합니다. 다음 예제에서 Boto3 클라이언트의 이름은 `braket`입니다.

```
import boto3
import botocore

braket = boto3.client("braket")
```

**참고**  
[Braket은 IPv6를 지원합니다](https://docs.aws.amazon.com/vpc/latest/userguide/aws-ipv6-support.html). IPv6 전용 네트워크를 사용하거나 워크로드가 IPv6 트래픽을 사용하도록 하려면 [듀얼 스택 및 FIPS 엔드포인트](https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html) 가이드에 설명된 대로 듀얼 스택 엔드포인트를 사용합니다.

이제 `braket` 클라이언트가 설정되었으므로 Amazon Braket 서비스에서 요청을 하고 응답을 처리할 수 있습니다. [API 참조](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/braket.html)에서 요청 및 응답 데이터에 대한 자세한 내용을 확인할 수 있습니다.

**Topics**
+ [디바이스 검색](#braket-using-boto3-example-search-devices)
+ [디바이스 검색](#braket-using-boto3-example-retrieve-devices)
+ [양자 작업 생성](#braket-using-boto3-example-create-task)
+ [양자 작업 검색](#braket-using-boto3-example-retrieve-task)
+ [양자 작업 검색](#braket-using-boto3-example-search-tasks)
+ [양자 작업 취소](#braket-using-boto3-example-cancel-task)

## 디바이스 검색
<a name="braket-using-boto3-example-search-devices"></a>
+  `search_devices(**kwargs)` 

지정된 필터를 사용하여 디바이스를 검색합니다.

```
# Pass search filters and optional parameters when sending the
# request and capture the response
response = braket.search_devices(filters=[{
    'name': 'deviceArn',
    'values': ['arn:aws:braket:::device/quantum-simulator/amazon/sv1']
}], maxResults=10)

print(f"Found {len(response['devices'])} devices")

for i in range(len(response['devices'])):
    device = response['devices'][i]
    print(device['deviceArn'])
```

## 디바이스 검색
<a name="braket-using-boto3-example-retrieve-devices"></a>
+  `get_device(deviceArn)` 

Amazon Braket에서 사용 가능한 디바이스를 검색합니다.

```
# Pass the device ARN when sending the request and capture the repsonse
response = braket.get_device(deviceArn='arn:aws:braket:::device/quantum-simulator/amazon/sv1')

print(f"Device {response['deviceName']} is {response['deviceStatus']}")
```

## 양자 작업 생성
<a name="braket-using-boto3-example-create-task"></a>
+  `create_quantum_task(**kwargs)` 

양자 작업을 생성합니다.

```
# Create parameters to pass into create_quantum_task()
kwargs = {
    # Create a Bell pair
    'action': '{"braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, "results": [], "basis_rotation_instructions": [], "instructions": [{"type": "h", "target": 0}, {"type": "cnot", "control": 0, "target": 1}]}',
    # Specify the SV1 Device ARN
    'deviceArn': 'arn:aws:braket:::device/quantum-simulator/amazon/sv1',
    # Specify 2 qubits for the Bell pair
    'deviceParameters': '{"braketSchemaHeader": {"name": "braket.device_schema.simulators.gate_model_simulator_device_parameters", "version": "1"}, "paradigmParameters": {"braketSchemaHeader": {"name": "braket.device_schema.gate_model_parameters", "version": "1"}, "qubitCount": 2}}',
    # Specify where results should be placed when the quantum task completes.
    # You must ensure the S3 Bucket exists before calling create_quantum_task()
    'outputS3Bucket': 'amazon-braket-examples',
    'outputS3KeyPrefix': 'boto-examples',
    # Specify number of shots for the quantum task
    'shots': 100
}

# Send the request and capture the response
response = braket.create_quantum_task(**kwargs)

print(f"Quantum task {response['quantumTaskArn']} created")
```

## 양자 작업 검색
<a name="braket-using-boto3-example-retrieve-task"></a>
+  `get_quantum_task(quantumTaskArn)` 

지정된 양자 작업을 검색합니다.

```
# Pass the quantum task ARN when sending the request and capture the response
response = braket.get_quantum_task(quantumTaskArn='arn:aws:braket:us-west-1:123456789012:quantum-task/ce78c429-cef5-45f2-88da-123456789012')

print(response['status'])
```

## 양자 작업 검색
<a name="braket-using-boto3-example-search-tasks"></a>
+  `search_quantum_tasks(**kwargs)` 

지정된 필터 값과 일치하는 양자 작업을 검색합니다.

```
# Pass search filters and optional parameters when sending the
# request and capture the response
response = braket.search_quantum_tasks(filters=[{
    'name': 'deviceArn',
    'operator': 'EQUAL',
    'values': ['arn:aws:braket:::device/quantum-simulator/amazon/sv1']
}], maxResults=25)

print(f"Found {len(response['quantumTasks'])} quantum tasks")

for n in range(len(response['quantumTasks'])):
    task = response['quantumTasks'][n]
    print(f"Quantum task {task['quantumTaskArn']} for {task['deviceArn']} is {task['status']}")
```

## 양자 작업 취소
<a name="braket-using-boto3-example-cancel-task"></a>
+  `cancel_quantum_task(quantumTaskArn)` 

지정된 양자 작업을 취소합니다.

```
# Pass the quantum task ARN when sending the request and capture the response
response = braket.cancel_quantum_task(quantumTaskArn='arn:aws:braket:us-west-1:123456789012:quantum-task/ce78c429-cef5-45f2-88da-123456789012')

print(f"Quantum task {response['quantumTaskArn']} is {response['cancellationStatus']}")
```

# Boto3 및 Braket SDK에 대한 AWS CLI 프로파일 구성
<a name="braket-using-boto3-profiles"></a>

달리 명시적으로 지정하지 않는 한 Amazon Braket SDK는 기본 AWS CLI 자격 증명을 사용합니다. 노트북 인스턴스를 시작할 권한이 있는 IAM 역할을 제공해야 하므로 관리형 Amazon Braket 노트북에서 실행할 때는 기본값을 유지하는 것이 좋습니다.

선택적으로 코드를 로컬(예: Amazon EC2 인스턴스에서)로 실행하는 경우 명명된 AWS CLI 프로파일을 설정할 수 있습니다. 기본 프로파일을 정기적으로 덮어쓰지 않고 각 프로파일에 서로 다른 권한 세트를 부여할 수 있습니다.

이 섹션에서는 이러한 CLI `profile`을 구성하는 방법과 해당 프로파일의 권한을 사용하여 API 직접 호출이 이루어지도록 해당 프로파일을 Amazon Braket에 통합하는 방법을 간략하게 설명합니다.

**Topics**
+ [1단계: 로컬 AWS CLI 구성 `profile`](#braket-using-boto3-profiles-step-1)
+ [2단계: Boto3 세션 객체 설정](#braket-using-boto3-profiles-step-2)
+ [3단계: Boto3 세션을 Braket AwsSession에 통합](#braket-using-boto3-profiles-step-3)

## 1단계: 로컬 AWS CLI 구성 `profile`
<a name="braket-using-boto3-profiles-step-1"></a>

사용자를 생성하는 방법과 비기본 프로파일을 구성하는 방법에 대한 설명은 이 문서의 범위를 벗어납니다. 이 주제에 대한 자세한 내용은 다음을 참조하세요.
+  [시작하기](https://docs.aws.amazon.com/singlesignon/latest/userguide/getting-started.html) 
+  [AWS CLI 를 사용하도록 구성 AWS IAM Identity Center](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html) 

Amazon Braket을 사용하려면 이 사용자와 연결된 CLI `profile`에 필요한 Braket 권한을 제공해야 합니다. 예를 들어 **AmazonBraketFullAccess** 정책을 연결할 수 있습니다.

## 2단계: Boto3 세션 객체 설정
<a name="braket-using-boto3-profiles-step-2"></a>

Boto3 세션 객체를 설정하려면 다음 코드 예제를 활용하세요.

```
from boto3 import Session

# Insert CLI profile name here
boto_sess = Session(profile_name=`profile`)
```

**참고**  
예상 API 직접 호출에 `profile` 기본 리전과 일치하지 않는 리전 기반 제한이 있는 경우 다음 예제와 같이 Boto3 세션에 대한 리전을 지정할 수 있습니다.

```
# Insert CLI profile name _and_ region
boto_sess = Session(profile_name=`profile`, region_name=`region`)
```

로 지정된 인수의 경우 `region`, 등과 같이 Amazon Braket AWS 리전 을 사용할 수 있는 중 하나에 해당하는 값을 대체`us-east-1``us-west-1`합니다.

## 3단계: Boto3 세션을 Braket AwsSession에 통합
<a name="braket-using-boto3-profiles-step-3"></a>

다음 예제에서는 Boto3 Braket 세션을 초기화하고 해당 세션에서 디바이스를 인스턴스화하는 방법을 보여줍니다.

```
from braket.aws import AwsSession, AwsDevice

# Initialize Braket session with Boto3 Session credentials
aws_session = AwsSession(boto_session=boto_sess)

# Instantiate any Braket QPU device with the previously initiated AwsSession
sim_arn = 'arn:aws:braket:::device/quantum-simulator/amazon/sv1'
device = AwsDevice(sim_arn, aws_session=aws_session)
```

이 설정이 완료되면 인스턴스화된 `AwsDevice` 객체에 양자 작업을 제출할 수 있습니다(예: `device.run(…​)` 명령을 직접적으로 호출). 해당 디바이스에서 수행한 모든 API 직접 호출은 이전에 `profile`로 지정한 CLI 프로필과 연결된 IAM 자격 증명을 사용할 수 있습니다.