qubit

package
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2023 License: MIT Imports: 10 Imported by: 1

Documentation

Overview

Example (BellState)
package main

import (
	"fmt"

	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	q := qubit.Zero(2).Apply(
		gate.H().TensorProduct(gate.I()),
		gate.CNOT(2, 0, 1),
	)

	for _, s := range q.State() {
		fmt.Println(s)
	}

}
Output:

[00][  0]( 0.7071 0.0000i): 0.5000
[11][  3]( 0.7071 0.0000i): 0.5000
Example (ErrorCorrectionBitFlip)
package main

import (
	"fmt"

	"github.com/itsubaki/q/math/matrix"
	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	phi := qubit.New(1, 2)

	// encoding
	phi.TensorProduct(qubit.Zero(2))
	phi.Apply(
		gate.CNOT(3, 0, 1),
		gate.CNOT(3, 0, 2),
	)

	// error: first qubit is flipped
	phi.Apply(matrix.TensorProduct(gate.X(), gate.I(2)))

	// add ancilla qubit
	phi.TensorProduct(qubit.Zero(2))

	// z1z2
	phi.Apply(
		gate.CNOT(5, 0, 3),
		gate.CNOT(5, 1, 3),
	)

	// z2z3
	phi.Apply(
		gate.CNOT(5, 1, 4),
		gate.CNOT(5, 2, 4),
	)

	// measure
	m3 := phi.Measure(3)
	m4 := phi.Measure(4)

	// recover
	if m3.IsOne() && m4.IsZero() {
		phi.Apply(matrix.TensorProduct(gate.X(), gate.I(4)))
	}

	if m3.IsOne() && m4.IsOne() {
		phi.Apply(matrix.TensorProduct(gate.I(), gate.X(), gate.I(3)))
	}

	if m3.IsZero() && m4.IsOne() {
		phi.Apply(matrix.TensorProduct(gate.I(2), gate.X(), gate.I(2)))
	}

	// decoding
	phi.Apply(
		gate.CNOT(5, 0, 2),
		gate.CNOT(5, 0, 1),
	)

	for _, s := range phi.State() {
		fmt.Println(s)
	}

}
Output:

[00010][  2]( 0.4472 0.0000i): 0.2000
[10010][ 18]( 0.8944 0.0000i): 0.8000
Example (ErrorCorrectionPhaseFlip)
package main

import (
	"fmt"

	"github.com/itsubaki/q/math/matrix"
	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	phi := qubit.New(1, 2)

	// encoding
	phi.TensorProduct(qubit.Zero(2))
	phi.Apply(
		gate.CNOT(3, 0, 1),
		gate.CNOT(3, 0, 2),
		gate.H(3),
	)

	// error: first qubit is flipped
	phi.Apply(matrix.TensorProduct(gate.Z(), gate.I(2)))

	// H
	phi.Apply(gate.H(3))

	// add ancilla qubit
	phi.TensorProduct(qubit.Zero(2))

	// x1x2
	phi.Apply(
		gate.CNOT(5, 0, 3),
		gate.CNOT(5, 1, 3),
	)

	// x2x3
	phi.Apply(
		gate.CNOT(5, 1, 4),
		gate.CNOT(5, 2, 4),
	)

	// H
	phi.Apply(matrix.TensorProduct(gate.H(3), gate.I(2)))

	// measure
	m3 := phi.Measure(3)
	m4 := phi.Measure(4)

	// recover
	if m3.IsOne() && m4.IsZero() {
		phi.Apply(matrix.TensorProduct(gate.Z(), gate.I(4)))
	}

	if m3.IsOne() && m4.IsOne() {
		phi.Apply(matrix.TensorProduct(gate.I(), gate.Z(), gate.I(3)))
	}

	if m3.IsZero() && m4.IsOne() {
		phi.Apply(matrix.TensorProduct(gate.I(2), gate.Z(), gate.I(2)))
	}

	// decoding
	phi.Apply(
		matrix.TensorProduct(gate.H(3), gate.I(2)),
		gate.CNOT(5, 0, 2),
		gate.CNOT(5, 0, 1),
	)

	for _, s := range phi.State() {
		fmt.Println(s)
	}

}
Output:

[00010][  2]( 0.4472 0.0000i): 0.2000
[10010][ 18]( 0.8944 0.0000i): 0.8000
Example (Grover2qubit)
package main

import (
	"fmt"

	"github.com/itsubaki/q/math/matrix"
	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	oracle := gate.CZ(2, 0, 1)
	amp := matrix.Apply(
		gate.H(2),
		gate.X(2),
		gate.CZ(2, 0, 1),
		gate.X(2),
		gate.H(2),
	)

	q := qubit.Zero(2).Apply(
		gate.H(2),
		oracle,
		amp,
	)

	q.Measure(0)
	q.Measure(1)

	for _, s := range q.State() {
		fmt.Println(s)
	}

}
Output:

[11][  3](-1.0000 0.0000i): 1.0000
Example (Grover3qubit)
package main

import (
	"fmt"

	"github.com/itsubaki/q/math/matrix"
	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	oracle := matrix.Apply(
		matrix.TensorProduct(gate.X(), gate.I(3)),
		gate.ControlledNot(4, []int{0, 1, 2}, 3),
		matrix.TensorProduct(gate.X(), gate.I(3)),
	)

	amp := matrix.Apply(
		matrix.TensorProduct(gate.H(3), gate.H()),
		matrix.TensorProduct(gate.X(3), gate.I()),
		matrix.TensorProduct(gate.ControlledZ(3, []int{0, 1}, 2), gate.I()),
		matrix.TensorProduct(gate.X(3), gate.I()),
		matrix.TensorProduct(gate.H(3), gate.I()),
	)

	q := qubit.TensorProduct(
		qubit.Zero(3),
		qubit.One(),
	).Apply(
		gate.H(4),
		oracle,
		amp,
	)

	for _, s := range q.State() {
		fmt.Println(s)
	}

}
Output:

[0001][  1](-0.1768 0.0000i): 0.0313
[0011][  3](-0.1768 0.0000i): 0.0313
[0101][  5](-0.1768 0.0000i): 0.0313
[0111][  7](-0.8839 0.0000i): 0.7813
[1001][  9](-0.1768 0.0000i): 0.0313
[1011][ 11](-0.1768 0.0000i): 0.0313
[1101][ 13](-0.1768 0.0000i): 0.0313
[1111][ 15](-0.1768 0.0000i): 0.0313
Example (POVM)
package main

import (
	"fmt"
	"math"

	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	E1 := gate.New(
		[]complex128{0, 0},
		[]complex128{0, 1},
	).Mul(complex(math.Sqrt(2)/(1.0+math.Sqrt(2)), 0))

	E2 := gate.New(
		[]complex128{1, -1},
		[]complex128{-1, 1},
	).Mul(complex(0.5, 0)).
		Mul(complex(math.Sqrt(2)/(1.0+math.Sqrt(2)), 0))

	E3 := gate.I().Sub(E1).Sub(E2)

	add := E1.Add(E2).Add(E3)
	fmt.Println(add.Equals(gate.I()))

	{
		q0 := qubit.Zero()
		q1 := qubit.Zero()
		q2 := qubit.Zero()

		fmt.Println("zero:")
		fmt.Println(q0.Apply(E1).InnerProduct(q0))
		fmt.Println(q1.Apply(E2).InnerProduct(q1))
		fmt.Println(q2.Apply(E3).InnerProduct(q2))
	}

	{
		q0 := qubit.Zero().Apply(gate.H())
		q1 := qubit.Zero().Apply(gate.H())
		q2 := qubit.Zero().Apply(gate.H())

		fmt.Println("H(zero):")
		fmt.Println(q0.Apply(E1).InnerProduct(q0))
		fmt.Println(q1.Apply(E2).InnerProduct(q1))
		fmt.Println(q2.Apply(E3).InnerProduct(q2))
	}

}
Output:

true
zero:
(0+0i)
(0.17157287525381+0i)
(0.5857864376269049+0i)
H(zero):
(0.17157287525381+0i)
(0+0i)
(0.5857864376269051+0i)
Example (QuantumTeleportation)
package main

import (
	"fmt"

	"github.com/itsubaki/q/math/matrix"
	"github.com/itsubaki/q/math/rand"
	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	phi := qubit.New(1, 2)
	phi.Rand = rand.Const()

	fmt.Println("before:")
	for _, s := range phi.State() {
		fmt.Println(s)
	}

	bell := qubit.Zero(2).Apply(
		matrix.TensorProduct(gate.H(), gate.I()),
		gate.CNOT(2, 0, 1),
	)
	phi.TensorProduct(bell)

	phi.Apply(
		gate.CNOT(3, 0, 1),
		matrix.TensorProduct(gate.H(), gate.I(2)),
	)

	mz := phi.Measure(0)
	mx := phi.Measure(1)

	if mx.IsOne() {
		phi.Apply(matrix.TensorProduct(gate.I(2), gate.X()))
	}

	if mz.IsOne() {
		phi.Apply(matrix.TensorProduct(gate.I(2), gate.Z()))
	}

	fmt.Println("after:")
	for _, s := range phi.State() {
		fmt.Println(s)
	}

}
Output:

before:
[0][  0]( 0.4472 0.0000i): 0.2000
[1][  1]( 0.8944 0.0000i): 0.8000
after:
[110][  6]( 0.4472 0.0000i): 0.2000
[111][  7]( 0.8944 0.0000i): 0.8000
Example (QuantumTeleportation2)
package main

import (
	"fmt"

	"github.com/itsubaki/q/math/matrix"
	"github.com/itsubaki/q/math/rand"
	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	phi := qubit.New(1, 2)
	phi.Rand = rand.Const()

	fmt.Println("before:")
	for _, s := range phi.State() {
		fmt.Println(s)
	}

	bell := qubit.Zero(2).Apply(
		matrix.TensorProduct(gate.H(), gate.I()),
		gate.CNOT(2, 0, 1),
	)
	phi.TensorProduct(bell)

	phi.Apply(
		gate.CNOT(3, 0, 1),
		matrix.TensorProduct(gate.H(), gate.I(2)),
		gate.CNOT(3, 1, 2),
		gate.CZ(3, 0, 2),
	)

	phi.Measure(0)
	phi.Measure(1)

	fmt.Println("after:")
	for _, s := range phi.State() {
		fmt.Println(s)
	}

}
Output:

before:
[0][  0]( 0.4472 0.0000i): 0.2000
[1][  1]( 0.8944 0.0000i): 0.8000
after:
[110][  6]( 0.4472 0.0000i): 0.2000
[111][  7]( 0.8944 0.0000i): 0.8000

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Equals

func Equals(s, v []State, eps ...float64) bool

Equals returns true if s equals v. If eps is not given, epsilon.E13 is used.

Types

type Qubit

type Qubit struct {
	Rand func() float64 // Random number generator
	// contains filtered or unexported fields
}

Qubit is a qubit.

func New

func New(z ...complex128) *Qubit

New returns a new qubit. z is a vector of complex128.

func One

func One(n ...int) *Qubit

One returns a qubit in the one state. n is the number of qubits.

func TensorProduct

func TensorProduct(qb ...*Qubit) *Qubit

func Zero

func Zero(n ...int) *Qubit

Zero returns a qubit in the zero state. n is the number of qubits.

Example
package main

import (
	"fmt"

	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	z := qubit.Zero()
	fmt.Print("z : ")
	for _, s := range z.State() {
		fmt.Println(s)
	}

	z2 := qubit.Zero(2)
	fmt.Print("z2:")
	for _, s := range z2.State() {
		fmt.Println(s)
	}

}
Output:

z : [0][  0]( 1.0000 0.0000i): 1.0000
z2:[00][  0]( 1.0000 0.0000i): 1.0000

func (*Qubit) Amplitude

func (q *Qubit) Amplitude() []complex128

Amplitude returns the amplitude of q.

func (*Qubit) Apply

func (q *Qubit) Apply(m ...matrix.Matrix) *Qubit

Apply returns a qubit that is applied m.

func (*Qubit) BinaryString

func (q *Qubit) BinaryString() string

BinaryString returns the binary string representation of q.

func (*Qubit) Clone

func (q *Qubit) Clone() *Qubit

Clone returns a clone of q.

func (*Qubit) Dimension

func (q *Qubit) Dimension() int

Dimension returns the dimension of q.

func (*Qubit) Equals

func (q *Qubit) Equals(qb *Qubit, eps ...float64) bool

Equals returns true if q and qb are equal.

func (*Qubit) Fidelity

func (q *Qubit) Fidelity(qb *Qubit) float64

Fidelity returns the fidelity of q and qb.

func (*Qubit) InnerProduct

func (q *Qubit) InnerProduct(qb *Qubit) complex128

InnerProduct returns the inner product of q and qb.

func (*Qubit) Int

func (q *Qubit) Int() int64

Int returns the integer representation of q.

func (*Qubit) IsOne

func (q *Qubit) IsOne(eps ...float64) bool

IsOne returns true if q is one qubit.

func (*Qubit) IsZero

func (q *Qubit) IsZero(eps ...float64) bool

IsZero returns true if q is zero qubit.

func (*Qubit) Measure

func (q *Qubit) Measure(index int) *Qubit

Measure returns a measured qubit.

func (*Qubit) Normalize

func (q *Qubit) Normalize() *Qubit

Normalize returns a normalized qubit.

func (*Qubit) NumberOfBit

func (q *Qubit) NumberOfBit() int

NumberOfBit returns the number of qubits.

func (*Qubit) OuterProduct

func (q *Qubit) OuterProduct(qb *Qubit) matrix.Matrix

OuterProduct returns the outer product of q and qb.

Example
package main

import (
	"fmt"

	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	v := qubit.New(1, 0)
	op := v.OuterProduct(v)
	fmt.Println(op)

}
Output:

[[(1+0i) (0+0i)] [(0+0i) (0+0i)]]
Example (OperatorSum)
package main

import (
	"fmt"

	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	v := qubit.New(1, 0)
	q := v.OuterProduct(v)
	e := gate.X().Dagger().Apply(q.Apply(gate.X()))

	fmt.Println(e)

}
Output:

[[(0+0i) (0+0i)] [(0+0i) (1+0i)]]

func (*Qubit) Probability

func (q *Qubit) Probability() []float64

Probability returns the probability of q.

func (*Qubit) State

func (q *Qubit) State(index ...[]int) []State

State returns the state of q with index.

Example
package main

import (
	"fmt"

	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	v := qubit.Zero(4).Apply(gate.H(4))

	for _, s := range v.State([]int{0, 1, 2, 3}) {
		fmt.Println(s)
	}

}
Output:

[0000][  0]( 0.2500 0.0000i): 0.0625
[0001][  1]( 0.2500 0.0000i): 0.0625
[0010][  2]( 0.2500 0.0000i): 0.0625
[0011][  3]( 0.2500 0.0000i): 0.0625
[0100][  4]( 0.2500 0.0000i): 0.0625
[0101][  5]( 0.2500 0.0000i): 0.0625
[0110][  6]( 0.2500 0.0000i): 0.0625
[0111][  7]( 0.2500 0.0000i): 0.0625
[1000][  8]( 0.2500 0.0000i): 0.0625
[1001][  9]( 0.2500 0.0000i): 0.0625
[1010][ 10]( 0.2500 0.0000i): 0.0625
[1011][ 11]( 0.2500 0.0000i): 0.0625
[1100][ 12]( 0.2500 0.0000i): 0.0625
[1101][ 13]( 0.2500 0.0000i): 0.0625
[1110][ 14]( 0.2500 0.0000i): 0.0625
[1111][ 15]( 0.2500 0.0000i): 0.0625
Example (Order)
package main

import (
	"fmt"

	"github.com/itsubaki/q/quantum/gate"
	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	v := qubit.Zero(4).Apply(gate.H(4))

	for _, s := range v.State([]int{0}, []int{1, 2, 3}) {
		fmt.Println(s)
	}

	for _, s := range v.State([]int{1, 2, 3}, []int{0}) {
		fmt.Println(s)
	}

}
Output:

[0 000][  0   0]( 0.2500 0.0000i): 0.0625
[0 001][  0   1]( 0.2500 0.0000i): 0.0625
[0 010][  0   2]( 0.2500 0.0000i): 0.0625
[0 011][  0   3]( 0.2500 0.0000i): 0.0625
[0 100][  0   4]( 0.2500 0.0000i): 0.0625
[0 101][  0   5]( 0.2500 0.0000i): 0.0625
[0 110][  0   6]( 0.2500 0.0000i): 0.0625
[0 111][  0   7]( 0.2500 0.0000i): 0.0625
[1 000][  1   0]( 0.2500 0.0000i): 0.0625
[1 001][  1   1]( 0.2500 0.0000i): 0.0625
[1 010][  1   2]( 0.2500 0.0000i): 0.0625
[1 011][  1   3]( 0.2500 0.0000i): 0.0625
[1 100][  1   4]( 0.2500 0.0000i): 0.0625
[1 101][  1   5]( 0.2500 0.0000i): 0.0625
[1 110][  1   6]( 0.2500 0.0000i): 0.0625
[1 111][  1   7]( 0.2500 0.0000i): 0.0625
[000 0][  0   0]( 0.2500 0.0000i): 0.0625
[001 0][  1   0]( 0.2500 0.0000i): 0.0625
[010 0][  2   0]( 0.2500 0.0000i): 0.0625
[011 0][  3   0]( 0.2500 0.0000i): 0.0625
[100 0][  4   0]( 0.2500 0.0000i): 0.0625
[101 0][  5   0]( 0.2500 0.0000i): 0.0625
[110 0][  6   0]( 0.2500 0.0000i): 0.0625
[111 0][  7   0]( 0.2500 0.0000i): 0.0625
[000 1][  0   1]( 0.2500 0.0000i): 0.0625
[001 1][  1   1]( 0.2500 0.0000i): 0.0625
[010 1][  2   1]( 0.2500 0.0000i): 0.0625
[011 1][  3   1]( 0.2500 0.0000i): 0.0625
[100 1][  4   1]( 0.2500 0.0000i): 0.0625
[101 1][  5   1]( 0.2500 0.0000i): 0.0625
[110 1][  6   1]( 0.2500 0.0000i): 0.0625
[111 1][  7   1]( 0.2500 0.0000i): 0.0625

func (*Qubit) String

func (q *Qubit) String() string

String returns the string representation of q.

func (*Qubit) TensorProduct

func (q *Qubit) TensorProduct(qb *Qubit) *Qubit

TensorProduct returns the tensor product of q and qb.

func (*Qubit) TraceDistance

func (q *Qubit) TraceDistance(qb *Qubit) float64

TraceDistance returns the trace distance of q and qb.

type State

type State struct {
	Amplitude    complex128
	Probability  float64
	Int          []int64
	BinaryString []string
}

State is a quantum state.

Example
package main

import (
	"fmt"

	"github.com/itsubaki/q/quantum/qubit"
)

func main() {
	s := qubit.State{
		Amplitude:    1,
		Probability:  1,
		Int:          []int64{4, 10, 8},
		BinaryString: []string{"0100", "1010", "1000"},
	}

	fmt.Println(s.Value())
	fmt.Println(s.Value(0))
	fmt.Println(s.Value(1))
	fmt.Println(s.Value(2))
	fmt.Println(s.String())

}
Output:

4 0100
4 0100
10 1010
8 1000
[0100 1010 1000][  4  10   8]( 1.0000 0.0000i): 1.0000

func (*State) Add

func (s *State) Add(binary string)

func (State) Equals

func (s State) Equals(v State, eps ...float64) bool

Equals returns true if s equals v. If eps is not given, epsilon.E13 is used.

func (State) String

func (s State) String() string

func (State) Value

func (s State) Value(index ...int) (int64, string)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL