> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qbraid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Transforms

> Adapt quantum programs to specific hardware requirements.

In the qBraid-SDK, a "transpile" action refers to converting a quantum program from one type to another,
such as from Qiskit to Amazon Braket. In contrast, a "transform" action involves modifying a quantum program to meet specific
requirements dictated by the target device or API through which the program will be executed.

Let's delve into the various "transforms" employed to prepare a quantum program for execution on an IonQ backend.

We begin by constructing a simple Qiskit circuit that executes a controlled Y rotation:

```python theme={null}
import numpy as np
from qiskit import QuantumCircuit

circuit = QuantumCircuit(2, 2)

circuit.cry(np.pi/4, 0, 1)

circuit.measure_all()
```

We then connect to the `IonQProvider` and retrieve the specifications for the IonQ Harmony device:

```python theme={null}
from qbraid.runtime import IonQProvider

provider = IonQProvider()

device = provider.get_device("qpu.harmony")

device.profile.get("program_spec")
# <ProgramSpec('openqasm3', openqasm3.ast.Program)>

device.profile.get("basis_gates")
# { "x","y","z","rx","ry","rz","h","cx","s","sdg","t","tdg","sx","sxdg","swap" }
```

By reviewing the device's `TargetProfile`, we understand that in order to run a program on IonQ Harmony,
qBraid runtime requires that it be expressed as an `openqasm3.ast.Program` and utilize only the gates from
its defined basis gate set. Consequently, our first step is to transpile our `qiskit` program to the `openqasm3`
program type:

```python theme={null}
from qbraid import transpile

qasm3_program = transpile(circuit, 'openqasm3')

type(qasm3_program)
# openqasm3.ast.Program
```

Next, we load the program into a qBraid `QuantumProgram` object and examine its string representation:

<CodeGroup>
  ```python Input theme={null}
  from qbraid import load_program

  qprogram = load_program(qasm3_program)

  print(qprogram.program)
  ```

  ```qasm Output theme={null}
  OPENQASM 3.0;
  include "stdgates.inc";
  bit[2] c;
  bit[2] meas;
  qubit[2] q;
  cry(pi / 4) q[0], q[1];
  barrier q[0], q[1];
  meas[0] = measure q[0];
  meas[1] = measure q[1];
  ```
</CodeGroup>

We can now apply a "transform" to this program, using our device object as argument,
ensuring it is represented exclusively in terms of gates supported by IonQ Harmony:

<CodeGroup>
  ```python Input theme={null}
  program.transform(device)

  print(program.program)
  ```

  ```qasm Output theme={null}
  OPENQASM 3.0;
  bit[2] b;
  qubit[2] q;
  ry(0.39269908169872414) q[1];
  cx q[0], q[1];
  ry(-0.39269908169872414) q[1];
  cx q[0], q[1];
  b[0] = measure q[0];
  b[1] = measure q[1];
  ```
</CodeGroup>

Device-specific transforms are a crucial component of the qBraid runtime framework, applied as the final step
before a program is executed on a quantum backend.

We've just demonstrated how one can utilize these transforms independently, outside of a runtime protocol, which
may be beneficial for testing or local simulations. However, for qBraid runtime end-users, these steps are automatically
performed behind the scenes whenever the `QuantumDevice.run` method is invoked.
