## Scotty 0.6.0 Released

### Performance Improvements

This is a very important update that focuses on the simulator performance. In addition to the state vector memory allocation optimizations we rewrote the gate application algorithm from scratch. The new algorithm is **three orders of magnitude** faster than what we had before. In practical terms, it means that users can run much larger circuits in a fraction of the time required before. For example, a 15-qubit circuit with 1,000 gates now runs in under one second on a 4.2 GHz Intel Core i7 box. A 20-qubit circuit with 1,000 gates runs in about 20 seconds. Users can realistically run shallower circuits of up to 27 qubits with the max of 29 qubits.

In order to optimize for memory usage, we replaced the double-precision (`Double`

) complex number representation with regular `Float`

s. This cut our memory usage in half. Now, every complex number takes up 64 bits instead of 128. It means that `Vector`

and `Matrix`

types were redefined as:

```
type Vector = Array[Float]
type Matrix = Array[Array[Float]]
```

### Multi-Trial Experiment Changes

The `runAndMeasure`

version of the method that ran multiple trials of the same circuit was renamed to `runExperiment`

to avoid confusion with the single shot `runAndMeasure`

.

We also removed parallelism support for multiple trials since it doesn’t make sense to run experiments in parallel given that state initialization, gate application, and probability calculations are already parallelized.

### Gate Changes

Single-qubit gate implementations now live at the framework level. Some are implemented with matrices and some are expressed through other gates.

`CircuitConnector`

was removed in favor of `CompositeGate`

. You can define `CompositeGate`

s to describe multi-qubit unitary gates and operations. Some gates in the Scotty simulator now use this technique. For example, the `SWAP`

gate is implemented as a function that takes custom indexes as two parameters and returns a `CompositeGate`

:

```
def SWAP(i0: Int, i1: Int) = CompositeGate(CNOT(i0, i1), CNOT(i1, i0), CNOT(i0, i1))
```

Performance improvements forced us to introduce limitations to how `Dagger`

and `Controlled`

modifiers work. Now, `Dagger`

can only be applied to single-qubit gates and `Controlled`

can either be applied to other `Controlled`

gates or single-qubit gates. This behavior might change in the future.

### Register Changes

`QubitRegister`

can now be initialized from a binary string or an integer:

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

`Circuit`

also received a couple of helper methods for quick register initialization. Here are all the different ways you can set a custom register:

```
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)
```