# Quantum Circuits

## QBit

``````import spire.math._

import axle.quantumcircuit._
import axle.syntax.kolmogorov._
import axle.algebra.RegionEq

val sqrtHalf = Complex(Real(1) / sqrt(Real(2)), Real(0))

val qEven = QBit[Real](sqrtHalf, sqrtHalf)

val distribution = qEven.cpt``````
``````distribution.P(RegionEq(CBit0))
// res0: Real = Inexact(
//   f = spire.math.Real\$\$Lambda\$8953/0x00000008029b6580@5a0cf27f
// )

distribution.P(RegionEq(CBit1))
// res1: Real = Inexact(
//   f = spire.math.Real\$\$Lambda\$8953/0x00000008029b6580@5dc3868e
// )``````

## Dirac Vector Notation

``````import axle.quantumcircuit._
import axle.algebra.Binary``````
``````|("00").>().unindex
// res3: Vector[Binary] = Vector(
//   axle.algebra.B1\$@6dd81677,
//   axle.algebra.B0\$@75ceea9c,
//   axle.algebra.B0\$@75ceea9c,
//   axle.algebra.B0\$@75ceea9c
// )

Vector[Binary](1, 0) ⊗ Vector[Binary](1, 0)
// res4: Vector[Binary] = Vector(
//   axle.algebra.B1\$@6dd81677,
//   axle.algebra.B0\$@75ceea9c,
//   axle.algebra.B0\$@75ceea9c,
//   axle.algebra.B0\$@75ceea9c
// )``````

## CNOT

``````import axle.quantumcircuit._
import axle.quantumcircuit.QBit._
import spire.algebra.Field
import spire.math.Real

implicit val fieldReal: Field[Real] = new spire.math.RealAlgebra()
val QBit0 = constant0[Real]
val QBit1 = constant1[Real]``````
``````QBit2.cnot(QBit2(QBit0.unindex ⊗ QBit0.unindex)).unindex
// res6: Vector[spire.math.Complex[Real]] = Vector(
//   Complex(real = Exact(n = 1), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0))
// )

QBit2.cnot(QBit2(QBit0.unindex ⊗ QBit1.unindex)).unindex
// res7: Vector[spire.math.Complex[Real]] = Vector(
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 1), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0))
// )

QBit2.cnot(QBit2(QBit1.unindex ⊗ QBit0.unindex)).unindex
// res8: Vector[spire.math.Complex[Real]] = Vector(
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 1), imag = Exact(n = 0))
// )

QBit2.cnot(QBit2(QBit1.unindex ⊗ QBit1.unindex)).unindex
// res9: Vector[spire.math.Complex[Real]] = Vector(
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 1), imag = Exact(n = 0)),
//   Complex(real = Exact(n = 0), imag = Exact(n = 0))
// )``````

## Future Work

• `QBit2.factor`
• Fix and enable `DeutschOracleSpec`
• QBit CCNot

### Later

• Shor's algorithm
• Property test reversibility (& own inverse)
• Typeclass for "negate" (etc), Binary, CBit
• Typeclass for unindex
• Deutsch-Jozsa algorithm (D.O. for n-bits) (Oracle separation between EQP and P)
• Simon's periodicity problem (oracle separation between BQP and BPP)
• Grover's algorithm
• Quantum cryptographic key exchange