Tutorials
qcr:2606.92740.1

Simulating Advanced OpenQASM Programs on Braket

This Amazon Braket notebook is a comprehensive reference for the advanced OpenQASM language features supported by Braket's local simulator, which understands a substantially larger subset of OpenQASM than the cloud devices. OpenQASM is the open intermediate representation used widely across quantum computing, and the local simulator's broad support makes it a powerful environment for developing and testing portable quantum programs. The notebook systematically walks through the supported features with runnable examples: standard and custom gate definitions, classically-controlled and conditional operations, mid-circuit measurement and reset, registers and indexing, control-flow constructs, subroutines, and the various result types that can be requested. For each feature it shows the OpenQASM syntax and the behavior produced by the local simulator, building up a practical catalog that program authors can consult. By exercising the richer language surface the local simulator exposes, the example helps researchers write more expressive quantum programs, prototype features before running on restricted hardware, and understand exactly which OpenQASM constructs Braket interprets. It is an in-depth companion to working with quantum assembly and a valuable reference for OpenQASM portability on Amazon Braket.
Compilation
Qubit
Circuit-based
Uploaded 2 days ago
10
Views
GitHub582
Citing this entry? Use this QCR ID
Uploaded by
QL
QCR Librarian

Overview

amazon-braket/amazon-braket-examples
582261
In [ ]:
# --- Setup cell added by QCR (not part of the original tutorial) ---
# Source: amazon-braket/amazon-braket-examples @ 0c0818f315479aab9deebed7e7ed7533ac581923, Apache License 2.0.
# Installs the example's dependencies. If a later cell still reports a missing
# package, restart the runtime/kernel and run again from the top.
%pip install -q amazon-braket-sdk==1.117.3

Simulating Advanced OpenQASM Programs with the Local Simulator

The LocalSimulator now supports simulating OpenQASM programs and the scope of supported language features is larger than previously offered on Braket!

This notebook serves as a references of all OpenQASM features supported by Braket with the LocalSimulator. For detailed documentation about the language, see the OpenQASM 3.0 specification.

Creating the Device

We create the device using the LocalSimulator class.

In [1]:
from braket.devices import LocalSimulator

device = LocalSimulator()
In [2]:
# to make the output a little neater

import numpy as np

np.set_printoptions(precision=3)

Run a Bell circuit

Let's do a Hello World example where we run a Bell circuit!

In [3]:
from braket.ir.openqasm import Program

qasm_string = """
qubit[2] q;

h q[0];
cnot q[0], q[1];
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
Measurement counts: Counter({'11': 59, '00': 41})

Run a Bell circuit with a result type

Let's run the same circuit, but with no shots, instead getting the state vector.

For more info on supported result types, see the developer guide.

In [4]:
from braket.ir.openqasm import Program

qasm_string = """
qubit[2] q;

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

#pragma braket result state_vector
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program).result()
print(f"State vector result: {result.result_types[0].value}")
State vector result: [0.707+0.j 0.   +0.j 0.   +0.j 0.707+0.j]

Gate Modifiers

You can use the following gate modifiers on any gate: inv, ctrl, negctrl, pow.

For more documentation on gate modifiers, see the OpenQASM specification.

In [5]:
qasm_string = """
qubit[2] q;

h q[0];
ctrl @ x q[0], q[1];
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
Measurement counts: Counter({'00': 51, '11': 49})
In [6]:
qasm_string = """
qubit q;

pow(1/2) @ x q;     // sqrt x
inv @ v q;          // inv of (sqrt x)

#pragma braket result state_vector
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=0).result()
print(f"State vector result: {result.result_types[0].value}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
State vector result: [0.5-0.5j 0.5+0.5j]

OpenQASM Built-in Gates

You can use the built-in OpenQASM quantum directives, the parameterized unitary, U, and the global phase instruction gphase.

For more info on the built-in quantum operations, see the OpenQASM specification.

In [7]:
qasm_string = """
qubit q;

U(π, 0, π) q;

#pragma braket result state_vector
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=0).result()
print(f"State vector result: {result.result_types[0].value}")
State vector result: [6.123e-17+0.j 1.000e+00+0.j]

Classical Variables

The LocalSimulator supports OpenQASM variables and constants of the following types: int, uint, float, bool, bit.

For more info on classical variables in OpenQASM, see the OpenQASM specification.

In [8]:
qasm_string = """
qubit q;

int p1 = 2;
float p2 = .25;

pow(p1) @ pow(p2) @ x q;    // sqrt x
inv @ v q;                  // inv of (sqrt x)

#pragma braket result state_vector
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=0).result()
print(f"State vector result: {result.result_types[0].value}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
State vector result: [ 1.000e+00-3.331e-16j -5.551e-16+2.220e-16j]

Classical Operations

You can use many standard operators on classical variables of different types. There is also a list of built-in functions.

For a full list of supported operations and functions, see the OpenQASM specification for classical operations and built-in functions.

In [9]:
qasm_string = """
qubit q;

int p1 = floor(log(sin(20)));
float p2 = 4 * (π/3);

pow(p1) @ pow(p2) @ x q;

#pragma braket result state_vector
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=0).result()
print(f"State vector result: {result.result_types[0].value}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
State vector result: [0.915-0.279j 0.085+0.279j]

Custom Gates

You can define your own gates using built-in Braket and OpenQASM gates, as well as other custom defined gates.

For more information around defining custom gates, see the OpenQASM specification.

In [10]:
qasm_string = """
qubit[3] q;

gate majority a, b, c {
    // set c to the majority of {a, b, c}
    ctrl @ x c, b;
    ctrl @ x c, a;
    ctrl(2) @ x a, b, c;
}

x q[0:1];
// this should flip q[2] to 1
majority q[0], q[1], q[2];
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
Measurement counts: Counter({'111': 100})

Classical control

The LocalSimulator supports the following classical control directives: if, for, while, as well as simple subroutines (more on that later)

For more info on classical control, see the OpenQASM specification.

In [11]:
qasm_string = """
qubit[2] q;

bit[2] bitstring = "10";

for int i in [0:1] {
    if (bitstring[i]) {
        x q[i];
    }
    else {
        i q[i];
    }
}
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
Measurement counts: Counter({'10': 100})

Input

The LocalSimulator supports parametric circuits using the input directive allowing users to provide a dictionary to the inputs field in the OpenQASM Program object.

For documentation on the input directive, see the OpenQASM specification.

In [12]:
qasm_string = """
input float theta;
qubit q;
rx(theta) q;
"""
qasm_program = Program(source=qasm_string, inputs={"theta": 1.0})

result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
Measurement counts: Counter({'0': 77, '1': 23})

QASM Files

Instead of providing an OpenQASM string, you can provide a filename.

In [13]:
a_in, b_in = 2, 11
inputs = {"a_in": a_in, "b_in": b_in}

program = Program(source="adder.qasm", inputs=inputs)
device = LocalSimulator()

result = device.run(program).result()
probs = np.outer(result.result_types[0].value, result.result_types[1].value).flatten()
answer = np.argmax(probs)
print(f"{a_in} + {b_in} = {answer}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
2 + 11 = 12

Subroutines

The LocalSimulator supports creating subroutines to compartmentalize pieces of your code. They can support both classical and quantum computation. Note that using variables that are in scope during subroutine definition, but not passed as arguments is currently undefined behavior.

For documentation around subroutines, see the OpenQASM specification.

In [14]:
qasm_string = """
const int[8] n = 4;
input bit[n] x;

qubit q;

def parity(bit[n] cin) -> bit {
  bit c = false;
  for int[8] i in [0: n - 1] {
    c ^= cin[i];
  }
  return c;
}

if(parity(x)) {
    x q;
} else {
    i q;
}
"""
qasm_program = Program(source=qasm_string, inputs={"x": "1011"})

result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
Measurement counts: Counter({'1': 100})
In [15]:
qasm_string = """
qubit q;

def sum(const array[int[8], #dim = 1] arr) -> int {
    int size = sizeof(arr);
    int x = 0;
    for int i in [0:size - 1] {
        x += arr[i];
    }
    return x;
}

array[int, 10] arr = {9, 3, 6, 2, 2, 4, 3, 1, 12, 7};
int s = sum(arr);
rx(s*π/4) q;
"""
qasm_program = Program(source=qasm_string)

result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
This program uses OpenQASM language features that may not be supported on QPUs or on-demand simulators.
Measurement counts: Counter({'0': 88, '1': 12})

Simulating Noise

You can simulate noise instructions on the density matrix simulator using Braket noise pragmas.

For more documentation around supported noise operations, see the developer guide.

In [16]:
qasm_string = """
qubit q;

x q;

#pragma braket noise bit_flip(.1) q
"""
qasm_program = Program(source=qasm_string, inputs={"x": "1011"})

device = LocalSimulator("braket_dm")
result = device.run(qasm_program, shots=100).result()
print(f"Measurement counts: {result.measurement_counts}")
Measurement counts: Counter({'1': 92, '0': 8})

Join the Discussion

Comments (0)

No comments yet. Be the first to share your thoughts!

Indexed by QCR Librarian

This entry was created automatically from publicly available records. QCR links to public sources and only stores repository content where the license permits redistribution.

Versions

v1 Latest
Jun 17, 2026
qcr:2606.92740.1

Cite all versions? Use the base QCR ID to always reference the latest version of this entry.

Tools used

Amazon Braket SDK

Keywords

openqasm
local-simulator
braket
format-conversion
language-features

You may also like5