11package density
22
33import (
4- "fmt"
54 "iter"
65 "math"
76 "strings"
@@ -13,24 +12,6 @@ import (
1312 "github.com/itsubaki/q/quantum/qubit"
1413)
1514
16- // Qubit is a quantum bit.
17- type Qubit int
18-
19- // Index returns the index of qubit.
20- func (q Qubit ) Index () int {
21- return int (q )
22- }
23-
24- // Index returns the indices of the given qubits.
25- func Index (qb ... Qubit ) []int {
26- idx := make ([]int , len (qb ))
27- for i , q := range qb {
28- idx [i ] = q .Index ()
29- }
30-
31- return idx
32- }
33-
3415// Matrix is a density matrix.
3516type Matrix struct {
3617 rho * matrix.Matrix
@@ -67,29 +48,6 @@ func NewZeroState(n ...int) *Matrix {
6748 return NewPureState (qubit .Zero (n ... ))
6849}
6950
70- // Qubits returns the qubits of the density matrix.
71- func (m * Matrix ) Qubits () []Qubit {
72- n := m .NumQubits ()
73-
74- qubits := make ([]Qubit , n )
75- for i := range n {
76- qubits [i ] = Qubit (i )
77- }
78-
79- return qubits
80- }
81-
82- func (m * Matrix ) ComputationalBasis () []* qubit.Qubit {
83- n := m .NumQubits ()
84-
85- basis := make ([]* qubit.Qubit , 1 << n )
86- for i := range 1 << n {
87- basis [i ] = qubit .From (fmt .Sprintf ("%0*b" , n , i ))
88- }
89-
90- return basis
91- }
92-
9351// At returns a value of matrix at (i,j).
9452func (m * Matrix ) At (i , j int ) complex128 {
9553 return m .rho .At (i , j )
@@ -185,17 +143,17 @@ func (m *Matrix) TensorProduct(n *Matrix) *Matrix {
185143// PartialTrace returns the partial trace of the density matrix.
186144// The length of index must be less than or equal to n - 1,
187145// where n is the number of qubits in the matrix.
188- func (m * Matrix ) PartialTrace (idx ... Qubit ) * Matrix {
146+ func (m * Matrix ) PartialTrace (qb ... int ) * Matrix {
189147 n := m .NumQubits ()
190- d := number .Pow (2 , n - len (idx ))
148+ d := number .Pow (2 , n - len (qb ))
191149 p , q := m .Dim ()
192150
193151 rho := matrix .Zero (d , d )
194152 for i := range p {
195- k , kr := take (n , i , idx )
153+ k , kr := take (n , i , qb )
196154
197155 for j := range q {
198- l , lr := take (n , j , idx )
156+ l , lr := take (n , j , qb )
199157
200158 if k != l {
201159 continue
@@ -228,10 +186,10 @@ func (m *Matrix) PartialTrace(idx ...Qubit) *Matrix {
228186// Depolarizing returns the depolarizing channel.
229187// It applies the identity with probability (1 - p),
230188// and applies each of the Pauli gates X, Y, and Z with probability p/3.
231- func (m * Matrix ) Depolarizing (p float64 , qb Qubit ) * Matrix {
189+ func (m * Matrix ) Depolarizing (p float64 , qb int ) * Matrix {
232190 n := m .NumQubits ()
233191
234- idx := Index ( qb )
192+ idx := [] int { qb }
235193 id := m .rho .Mul (complex (1 - p , 0 ))
236194 xg := gate .TensorProduct (gate .X (), n , idx )
237195 yg := gate .TensorProduct (gate .Y (), n , idx )
@@ -248,14 +206,14 @@ func (m *Matrix) Depolarizing(p float64, qb Qubit) *Matrix {
248206
249207// ApplyChannel applies a channel to the density matrix.
250208// It applies the identity with probability 1-p, and applies the gate g with probability p.
251- func (m * Matrix ) ApplyChannel (p float64 , u * matrix.Matrix , qb ... Qubit ) * Matrix {
252- n , idx := m .NumQubits (), Index ( qb ... )
209+ func (m * Matrix ) ApplyChannel (p float64 , u * matrix.Matrix , qb ... int ) * Matrix {
210+ n := m .NumQubits ()
253211
254212 e0 := gate .I ().Mul (complex (math .Sqrt (1 - p ), 0 ))
255213 e1 := u .Mul (complex (math .Sqrt (p ), 0 ))
256214
257- k0 := gate .TensorProduct (e0 , n , idx )
258- k1 := gate .TensorProduct (e1 , n , idx )
215+ k0 := gate .TensorProduct (e0 , n , qb )
216+ k1 := gate .TensorProduct (e1 , n , qb )
259217
260218 rho := matrix .ZeroLike (m .rho )
261219 rho = rho .Add (matrix .MatMul (k0 , m .rho , k0 .Dagger ()))
@@ -267,24 +225,24 @@ func (m *Matrix) ApplyChannel(p float64, u *matrix.Matrix, qb ...Qubit) *Matrix
267225}
268226
269227// BitFlip applies a bit flip channel to the density matrix.
270- func (m * Matrix ) BitFlip (p float64 , qb Qubit ) * Matrix {
228+ func (m * Matrix ) BitFlip (p float64 , qb int ) * Matrix {
271229 return m .ApplyChannel (p , gate .X (), qb )
272230}
273231
274232// BitPhaseFlip applies a bit-phase flip channel to the density matrix.
275- func (m * Matrix ) BitPhaseFlip (p float64 , qb Qubit ) * Matrix {
233+ func (m * Matrix ) BitPhaseFlip (p float64 , qb int ) * Matrix {
276234 return m .ApplyChannel (p , gate .Y (), qb )
277235}
278236
279237// PhaseFlip applies a phase flip channel to the density matrix.
280- func (m * Matrix ) PhaseFlip (p float64 , qb Qubit ) * Matrix {
238+ func (m * Matrix ) PhaseFlip (p float64 , qb int ) * Matrix {
281239 return m .ApplyChannel (p , gate .Z (), qb )
282240}
283241
284- func take (n , i int , idx []Qubit ) (string , string ) {
285- target := make (map [int ]struct {}, len (idx ))
286- for _ , j := range idx {
287- target [j . Index () ] = struct {}{}
242+ func take (n , i int , qb []int ) (string , string ) {
243+ target := make (map [int ]struct {}, len (qb ))
244+ for _ , j := range qb {
245+ target [j ] = struct {}{}
288246 }
289247
290248 var out , remain strings.Builder
0 commit comments