Modifiers and Custom Gates
Scotty provides two modifiers that can be applied to some gates:
Controlled implements the
ControlGate trait. You can use it by setting the control index and the target gate. The target gate can be a controlled gate or a target gate (but not a swap 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.
Dagger is a modifier that takes the complex conjugate transpose of a single-qubit gate matrix.
You can mix and match modifiers and gates in any way you see fit as long as the final controlled gate is a
Scotty provides two abstractions for custom gates:
DefGate lets you to define single-qubit gates with your own matrix.
Here is how you can define a simple square root of NOT gate:
import scotty.quantum.math.Complex 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)) ).toFloat def SqrtNot(index: Int) = DefGate(matrix, index)
Now you can use
SqrtNot as any other gate:
Complex is a complex number representation provided by the framework. It has two
Float parameters: one for the real part and one for the imaginary part. Gates use a more bare-bones representation of the matrix for performance reasons:
Array[Array[Float]]. It represents complex numbers by putting real and imaginary float components next to each other. You can still define your gates with the
Complex helper but you have to use the implicit
toFloat method to convert your matrix array before passing it to
To define a custom parametric gate use another
DefGate constructor that takes a
MatrixGen (which is a shorthand for type
Seq[Float] => Matrix) and a list of
Double parameters. Here’s an example of a custom phase shift gate:
import scotty.quantum.math.Complex val matrix = (params: Seq[Double]) => Array( Array(Complex(1), Complex(0)), Array(Complex(0), Complex(Math.cos(params(0)), Math.sin(params(0)))) ).toFloat def QuarterPhase(phi: Double, index: Int) = DefGate(matrix, phi / 4, index)
Here’s how you can use it:
Finally, you can define
CompositeGates to describe multi-qubit unitary gates. Some gates in the Scotty simulator use this technique. For example, the
SWAP gate is implemented as a function that takes custom indexes as two parameters and returns a
def SWAP(i0: Int, i1: Int) = CompositeGate(CNOT(i0, i1), CNOT(i1, i0), CNOT(i0, i1))
You can use this approach to define your own gates and unitary operations.