@@ -62,7 +62,7 @@ def inverse_mod2(matrix):
62
62
return result
63
63
64
64
65
- def gaussian_elimination_mod2 (matrix , type = 'row' , show_pivots = False ):
65
+ def gaussian_elimination_mod2 (matrix , type = 'row' , reduced = False , show_pivots = False ):
66
66
r"""
67
67
Performs Gaussian elimination in the field $F_2$.
68
68
@@ -71,8 +71,11 @@ def gaussian_elimination_mod2(matrix, type='row', show_pivots=False):
71
71
matrix : numpy.array
72
72
A binary matrix.
73
73
type : str, optional
74
- Available aore ``row`` for row echelon form, and ``column`` for column echelon form.
74
+ Available are ``row`` for row echelon form, and ``column`` for column echelon form.
75
75
The default is ``row``.
76
+ reduced : Boolean, optional
77
+ If ``True``, the reduced row (column) echelon form is calculated.
78
+ The default is ``False``.
76
79
show_pivots : Boolean, optional
77
80
If ``True``, the pivot columns (rows) are returned.
78
81
@@ -106,14 +109,22 @@ def gaussian_elimination_mod2(matrix, type='row', show_pivots=False):
106
109
# Swap the current row with the pivot row
107
110
matrix [[row_index , max_row ]] = matrix [[max_row , row_index ]]
108
111
109
- # Eliminate all rows below the pivot
112
+ # Eliminate all rows after the pivot
110
113
for j in range (row_index + 1 , rows ):
111
114
if matrix [j , column_index ] == 1 :
112
115
matrix [j ] = (matrix [j ] + matrix [row_index ]) % 2
113
116
114
117
row_index += 1
115
118
column_index += 1
116
119
120
+ # Backward elimination (optional, for reduced row echelon form)
121
+ if reduced :
122
+ for i in range (min (rows , columns ) - 1 , - 1 , - 1 ):
123
+ for j in range (i - 1 , - 1 , - 1 ):
124
+ if matrix [j , i ] == 1 :
125
+ matrix [j ] = (matrix [j ] + matrix [i ]) % 2
126
+
127
+
117
128
elif type == 'column' :
118
129
while row_index < rows and column_index < columns :
119
130
# Find the pivot column
@@ -128,16 +139,23 @@ def gaussian_elimination_mod2(matrix, type='row', show_pivots=False):
128
139
# Swap the current column with the pivot column
129
140
matrix [:,[column_index , max_column ]] = matrix [:,[max_column , column_index ]]
130
141
131
- # Eliminate all rows below the pivot
142
+ # Eliminate all columns after the pivot
132
143
for j in range (column_index + 1 , columns ):
133
144
if matrix [row_index , j ] == 1 :
134
145
matrix [:,j ] = (matrix [:,j ] + matrix [:,column_index ]) % 2
135
146
136
147
row_index += 1
137
148
column_index += 1
138
149
150
+ # Backward elimination (optional, for column row echelon form)
151
+ if reduced :
152
+ for i in range (min (rows , columns ) - 1 , - 1 , - 1 ):
153
+ for j in range (i - 1 , - 1 , - 1 ):
154
+ if matrix [j , i ] == 1 :
155
+ matrix [:,j ] = (matrix [:,j ] + matrix [:,i ]) % 2
156
+
139
157
if show_pivots :
140
- return matrix , pivots #(pivot_rows,pivot_cols)
158
+ return matrix , pivots
141
159
else :
142
160
return matrix
143
161
@@ -172,7 +190,7 @@ def construct_change_of_basis(S):
172
190
# Step 0: Calculate S_0: Independent columns (i.e., Pauli terms) of S
173
191
####################
174
192
175
- S_reduced , independent_cols = gaussian_elimination_mod2 (S , show_pivots = True )
193
+ S_reduced , independent_cols = gaussian_elimination_mod2 (S , reduced = True , show_pivots = True )
176
194
k = len (independent_cols )
177
195
178
196
S0 = S [:,independent_cols ]
@@ -199,8 +217,9 @@ def construct_change_of_basis(S):
199
217
# Construct permutation achieving that the first k rows in X component of S1 are independent
200
218
perm = np .arange (0 ,n )
201
219
for index1 , index2 in enumerate (independent_rows ):
220
+ curr = perm [index1 ]
202
221
perm [index1 ] = index2
203
- perm [index2 ] = index1
222
+ perm [index2 ] = curr
204
223
205
224
# Apply permutation to rows of S1 for Z and X component
206
225
S1 = np .vstack ((S1 [:n ,:][perm ],S1 [- n :,:][perm ]))
0 commit comments