## Circuits and Qubits

Let’s take a look at the core abstractions that, for the most part, serve as immutable containers for various quantum primitives. The top-level primitive is called `Circuit`

. Each circuit can be thought of as a container for one `QubitRegister`

—a group of qubits (`Qubit`

)—and a sequence of quantum operations (`Op`

).

Circuits can be combined sequentially:

```
val newCircuit = Circuit(H(0)).combine(Circuit(CNOT(0, 1))
```

`QubitRegister`

is a collection of qubits. It can be initialized directly with qubits of your choosing:

```
QubitRegister(Qubit.one, Qubit.fiftyFifty, Qubit.zero)
```

You can also use a binary string or an integer to initiate it:

```
QubitRegister("1001")
// is equivalent to
QubitRegister(9)
```

The register uses a little-endian ordering of bits, meaning that the qubit on the right is the first qubit in the circuit (its index is `0`

).

All circuits come with an implicit qubit register where all qubits are initialized at $\lvert0\rangle$. The number of qubits is based on the highest operation index. For example, `Circuit(H(5))`

will be initialized with a register of six qubits (index starts at zero). You can always specify a custom register by applying `withRegister`

to your circuit:

```
Circuit(CNOT(0, 2)).withRegister(QubitRegister(Qubit.one, Qubit.zero, Qubit.zero))
Circuit(CNOT(0, 2)).withRegister(Qubit.one, Qubit.zero, Qubit.zero)
Circuit(CNOT(0, 2)).withRegister("100")
Circuit(CNOT(0, 2)).withRegister(4)
```

Qubits are immutable containers with two `Complex`

numbers describing their quantum state:

$\alpha$ and $\beta$ match `Qubit`

`a`

and `b`

parameters. Since these parameters represent qubit probabilities their squares have to add up to one:

`Complex`

case class is a convenient container to represent real and imaginary components of a complex number. Lots of framework methods and case classes work with `Complex`

numbers. In performance-sensitive places, like the `Superposition`

state and gate computations, `Array[Float]`

is used instead. This is done to optimize for garbage collection and general memory usage during quantum computations.

All qubits in the register have to be accessed by their index in the underlying sequence. For easy access to the actual numerical indexes `Circuit`

has a helper property `indexes`

.

Qubits implement the `Labeled`

trait, which means that you can apply a unique string label to any qubit:

```
val testQubit = Qubit.one("test")
val messageQubit = Qubit(Complex(0.8), Complex(0.6), "message")
```

Labels are useful for when you need to quickly differentiate between qubits and when you look at the final classical register readouts after the measurement.