Modifiers and Custom Gates

Gate Modifiers

Scotty provides two standard modifiers that can be applied to any Gate: Controlled and Dagger.

Controlled implements the ControlGate trait. You can use it by setting a control index and a target gate. The target gate can be a controlled gate or a target gate. The simulator allows for as many qubits in between control and target qubit indexes as you want. You can also have qubits set in any order. The controlled matrix generator is flexible enough to accommodate for that.

Dagger is a modifier that takes the conjugate conjugate of the gate matrix.

You can mix and match modifiers and gates in any way you see fit:

Controlled(0, Dagger(Y(1))

Custom Gates

Scotty provides a special TargetGate implementation called DefGate. It allows you to define static target gates with your own matrix or parametric gates.

Here is how you can define a simple square root of NOT gate:

val matrix = Array(
  Array(Complex(0.5, 0.5), Complex(0.5, -0.5)),
  Array(Complex(0.5, -0.5), Complex(0.5, 0.5))

def SqrtNot(index: Int) = DefGate(matrix, index)

Now you can use SqrtNot as any other gate:

QuantumSimulator().run(Circuit(X(1), SqrtNot(1)))

Complex is a complex number representation provided by the framework. It has two Double parameters: one for the real part and one for the imaginary part. Scotty provides two implicit conversions for custom matricies of complex numbers: Double to Complex and Int to Complex.

To define a custom parametric gate use another DefGate constructor that takes a GateGen (which is shorthand for type Seq[Double] => Matrix) and a list of Double parameters. Here’s an example of a custom phase shift gate:

val matrix = (params: Seq[Double]) => Array(
  Array(Complex(1), Complex(0)),
  Array(Complex(0), Complex(Math.cos(params(0)), Math.sin(params(0))))

def QuarterPhase(phi: Double, index: Int) = DefGate(matrix, phi / 4, index)

Here’s how you can use it:

QuarterPhase(Math.PI, 0)