@@ -60,6 +60,7 @@ def kchainbasis(h,k):
6060 - Hypergraph node uids must be sortable.
6161
6262 """
63+
6364 import itertools as it
6465 kchains = set ()
6566 for e in h .edges ():
@@ -70,6 +71,7 @@ def kchainbasis(h,k):
7071 return sorted (list (kchains ))
7172
7273def interpret (Ck ,arr ):
74+
7375 """
7476 Returns the data as represented in Ck associated with the arr
7577
@@ -86,6 +88,7 @@ def interpret(Ck,arr):
8688 list of k-cells referenced by data in Ck
8789
8890 """
91+
8992 output = list ()
9093 for vec in arr :
9194 if len (Ck ) != len (vec ):
@@ -301,6 +304,7 @@ def matmulreduce(arr,reverse=False,mod=2):
301304 P : np.array
302305 Product of matrices in the list
303306 """
307+
304308 if reverse :
305309 items = range (len (arr )- 1 ,- 1 ,- 1 )
306310 else :
@@ -333,6 +337,7 @@ def matsumreduce(arr,mod=2):
333337
334338## Convenience methods for computing Smith Normal Form
335339## All of these operations have themselves as inverses
340+
336341def _sr (i ,j ,M ,L ):
337342 return swap_rows (i ,j ,M ,L )
338343
@@ -409,6 +414,7 @@ def smith_normal_form_mod2(M,track=False):
409414 where $L = L[s]L[s-1]...L[1]L[0]$ and $R = R[0]R[1]...R[t]$.
410415
411416 """
417+
412418 S = copy .copy (M )
413419 dimL ,dimR = M .shape
414420 mod = 2
@@ -420,15 +426,15 @@ def smith_normal_form_mod2(M,track=False):
420426 L = np .eye (dimL ,dtype = int )
421427 R = np .eye (dimR ,dtype = int )
422428
423- Linv = [IL ] ## keep track of transformations to compute inverses at the end
424- Rinv = [IR ]
429+ Linv = np .eye (dimL ,dtype = int )
425430
426431 if track :
427432 print (L ,'L\n ' )
428433 print (M ,'M\n ' )
429434 print (R ,'R\n ' )
430435
431436 for s in range (min (dimL ,dimR )):
437+ print ('.' ),
432438 if track :
433439 print (f'\n s={ s } \n ' )
434440 ## Find index pair (rdx,cdx) with value 1 in submatrix M[s:,s:]
@@ -442,42 +448,27 @@ def smith_normal_form_mod2(M,track=False):
442448 ## Swap rows and columns as needed so that 1 is in the s,s position
443449 if rdx > s :
444450 S ,L = _sr (s ,rdx ,S ,L )
445- # This is equivalent to
446- # S = swap_rows(s,rdx,S)[0]
447- # L = swap_rows(s,rdx,L)[0]
448- Linv .append (swap_rows (s ,rdx ,IL )[0 ]) ## keep track of transformations on the left to reverse them for the inverse
451+ Linv = swap_columns (s ,rdx ,Linv )[0 ]
449452 if track :
450453 print (L ,f'L\n ' ,S ,'S\n ' ,)
451- assert (np .all (S == matmulreduce ([L ,M ,R ],mod = mod )))
452454 if cdx > s :
453455 S ,R = _sc (s ,cdx ,S ,R )
454- Rinv .append (swap_columns (s ,cdx ,IR )[0 ])
455456 if track :
456457 print (S ,'S\n ' ,R ,f'R\n ' )
457- assert (np .all (S == matmulreduce ([L ,M ,R ],mod = mod )))
458458
459459 # add sth row to every row with 1 in sth column & sth column to every column with 1 in sth row
460- row_indices = [idx for idx in range (dimL ) if idx != s and S [idx ][s ] == 1 ]
460+ row_indices = [idx for idx in range (s + 1 , dimL ) if S [idx ][s ] == 1 ]
461461 for rdx in row_indices :
462462 S ,L = _ar (rdx ,s ,S ,L ,mod = mod )
463- temp = add_to_row (IL ,rdx ,s ,mod = mod )
464- Linv .append (temp )
463+ Linv = add_to_column (Linv ,s ,rdx ,mod = mod )
465464 if track :
466465 print (L ,f'L\n ' ,S ,'S\n ' ,)
467- assert (np .all (S == matmulreduce ([L ,M ,R ],mod = mod )))
468- column_indices = [jdx for jdx in range (dimR ) if jdx != s and S [s ][jdx ] == 1 ]
466+ column_indices = [jdx for jdx in range (s + 1 ,dimR ) if S [s ][jdx ] == 1 ]
469467 for jdx ,cdx in enumerate (column_indices ):
470468 S ,R = _ac (cdx ,s ,S ,R )
471- temp = add_to_column (IR ,cdx ,s ,mod = mod )
472- Rinv .append (temp )
473469 if track :
474470 print (R ,f'R\n ' ,S ,'S\n ' ,)
475- assert (np .all (S == matmulreduce ([L ,M ,R ],mod = mod )))
476- Linv = matmulreduce (Linv ,mod = mod )
477- Rinv = matmulreduce (Rinv ,reverse = True ,mod = mod )
478- assert (np .all (IL == matmulreduce ([L ,Linv ],mod = mod )))
479- assert (np .all (IR == matmulreduce ([R ,Rinv ],mod = mod )))
480- return L ,R ,S ,Linv ,Rinv
471+ return L ,R ,S ,Linv
481472
482473
483474def reduced_row_echelon_form_mod2 (M ,track = False ,mod = 2 ):
@@ -511,14 +502,15 @@ def reduced_row_echelon_form_mod2(M,track=False,mod=2):
511502 verify the product:
512503 L[s]L[s-1]...L[0] M = S .
513504 """
505+
514506 S = copy .copy (M )
515507 dimL ,dimR = M .shape
516508 mod = 2
517509
518510 ## method with numpy
519511 IL = np .eye (dimL ,dtype = int )
520512
521- Linv = [ np .eye (dimL ,dtype = int )]
513+ Linv = np .eye (dimL ,dtype = int )
522514 L = np .eye (dimL ,dtype = int )
523515
524516 if track :
@@ -540,22 +532,17 @@ def reduced_row_echelon_form_mod2(M,track=False,mod=2):
540532 continue
541533 if rdx > s1 :
542534 S ,L = _sr (s1 ,rdx ,S ,L )
543- Linv . append ( swap_rows ( s1 , rdx ,IL )[0 ]) ## keep track of transformations on the left to reverse them for the inverse
535+ Linv = swap_columns ( rdx ,s1 , Linv )[0 ]
544536 if track :
545537 print (L ,f'L\n ' ,S ,'S\n ' ,)
546- assert (np .all (S == matmulreduce ([L ,M ],mod = mod )))
547-
548538 # add sth row to every nonzero row
549539 row_indices = [idx for idx in range (dimL ) if idx != s1 and S [idx ][cdx ] == 1 ]
550540 for idx in row_indices :
551541 S ,L = _ar (idx ,s1 ,S ,L ,mod = mod )
552- temp = add_to_row (IL ,idx ,s1 ,mod = mod )
553- Linv .append (temp )
542+ Linv = add_to_column (Linv ,s1 ,idx ,mod = mod )
554543 if track :
555544 print (L ,f'L\n ' ,S ,'S\n ' ,)
556- assert (np .all (S == matmulreduce ([L ,M ],mod = mod )))
557- Linv = matmulreduce (Linv ,mod = mod )
558- assert (np .all (IL == matmulreduce ([L ,Linv ],mod = mod )))
545+
559546 return L ,S ,Linv
560547
561548## Private
@@ -674,8 +661,8 @@ def homology_basis(bd,k,C=None,shortest=False):
674661 k-chains
675662 if shortest then returns a dictionary of shortest cycles for each coset.
676663 """
677- L1 ,R1 ,S1 ,L1inv , R1inv = smith_normal_form_mod2 (bd [k ])
678- L2 ,R2 ,S2 ,L2inv , R2inv = smith_normal_form_mod2 (bd [k + 1 ])
664+ L1 ,R1 ,S1 ,L1inv = smith_normal_form_mod2 (bd [k ])
665+ L2 ,R2 ,S2 ,L2inv = smith_normal_form_mod2 (bd [k + 1 ])
679666
680667 rank1 = np .sum (S1 ); print (f"rank{ k } = { rank1 } " )
681668 rank2 = np .sum (S2 ); print (f"rank{ k + 1 } = { rank2 } " )
@@ -686,9 +673,9 @@ def homology_basis(bd,k,C=None,shortest=False):
686673 ker1 = R1 [:,rank1 :]
687674 im2 = L2inv [:,:rank2 ]
688675 cokernel2 = L2inv [:,rank2 :]
676+ cokproj2 = L2 [rank2 :,:]
689677
690- proj = matmulreduce ([L2 ,ker1 ])[rank2 :,:]
691- proj = matmulreduce ([L2inv [:,rank2 :],proj ]).transpose ()
678+ proj = matmulreduce ([cokernel2 ,cokproj2 ,ker1 ]).transpose ()
692679 _ ,proj ,_ = reduced_row_echelon_form_mod2 (proj )
693680 proj = np .array ([row for row in proj if np .sum (row )> 0 ])
694681 print ('hom basis reps\n ' ,proj )
0 commit comments