7
7
import scipy .sparse as sp
8
8
from line_profiler import LineProfiler
9
9
import scipy
10
-
10
+ from pyclassify .utils import make_symmetric
11
+ from pyclassify .eigenvalues import EigenSolver , Lanczos_PRO
11
12
12
13
profile = LineProfiler ()
13
14
@@ -301,9 +302,17 @@ def parallel_tridiag_eigen(
301
302
D = np .concatenate ((eigvals_left , eigvals_right ))
302
303
D_size = D .size
303
304
v_vec = np .concatenate ((eigvecs_left [- 1 , :], eigvecs_right [0 , :]))
305
+
304
306
deflated_eigvals , deflated_eigvecs , D_keep , v_keep , P = deflate_eigenpairs_cxx (
305
307
D , v_vec , beta , tol_factor
306
308
)
309
+
310
+ # Pdeflated_eigvals, Pdeflated_eigvecs, PD_keep, Pv_keep, PP = deflate_eigenpairs(
311
+ # D, v_vec, beta, tol_factor
312
+ # )
313
+
314
+
315
+
307
316
D_keep = np .array (D_keep )
308
317
309
318
reduced_dim = len (D_keep )
@@ -313,13 +322,16 @@ def parallel_tridiag_eigen(
313
322
idx_inv = np .arange (0 , reduced_dim )
314
323
idx_inv = idx_inv [idx ]
315
324
325
+ # T= np.diag(D_keep) + beta * np.outer(v_keep, v_keep)
326
+ # lam , _ = np.linalg.eigh(T)
327
+
316
328
lam , changing_position , delta = secular_solver_cxx (
317
- beta , D_keep [idx ], v_keep [idx ], np .arange (reduced_dim )
329
+ beta , D_keep [idx ], v_keep [idx ] , np .arange (reduced_dim )
318
330
)
319
331
lam = np .array (lam )
320
332
delta = np .array (delta )
321
333
changing_position = np .array (changing_position )
322
- # #diff=lam_s-lam
334
+
323
335
else :
324
336
lam = np .array ([])
325
337
@@ -350,9 +362,9 @@ def parallel_tridiag_eigen(
350
362
v_keep = comm .bcast (v_keep , root = 0 )
351
363
my_count = counts [rank ]
352
364
type_lam = comm .bcast (lam .dtype , root = 0 )
353
- # type_D=comm.bcast(D_keep.dtype, root=0)
365
+
354
366
lam_buffer = np .empty (my_count , dtype = type_lam )
355
- # D_buffer=np.empty(my_count, dtype=type_D)
367
+
356
368
P = comm .bcast (P , root = 0 )
357
369
D_size = comm .bcast (D_size )
358
370
changing_position = comm .bcast (changing_position , root = 0 )
@@ -381,11 +393,6 @@ def parallel_tridiag_eigen(
381
393
root = 0
382
394
)
383
395
384
- # # Scatterv with matching MPI datatype
385
- # comm.Scatterv([lam, counts, displs, MPI._typedict[type_lam] ],
386
- # lam_buffer, root=0)
387
- # comm.Scatterv([D_keep, counts, displs, MPI._typedict[type_lam] ],
388
- # D_buffer, root=0)
389
396
390
397
initial_point = displs [rank ]
391
398
@@ -403,8 +410,6 @@ def parallel_tridiag_eigen(
403
410
404
411
for j_rel in range (lam_buffer .size ):
405
412
y = np .zeros (D_size )
406
- # y[:reduced_dim]=v_keep/(lam[j]-D_keep)
407
- # y /= np.linalg.norm(y)
408
413
j = j_rel + initial_point
409
414
diff = lam [j ] - D_keep
410
415
diff [idx_inv [changing_position [j ]]] = delta [j ]
@@ -544,192 +549,6 @@ def parallel_tridiag_eigen(
544
549
545
550
546
551
547
- # for eigval, vec in zip(deflated_eigvals, deflated_eigvecs):
548
- # # vec = Q_block @ vec
549
- # vec = np.concatenate((eigvecs_left @ vec[:n1], eigvecs_right @ vec[n1:]))
550
- # eigenpairs.append((eigval, vec))
551
- # eigenpairs.sort(key=lambda x: x[0])
552
- # final_eigvals = np.array([ev for ev, _ in eigenpairs])
553
- # final_eigvecs = np.column_stack([vec for _, vec in eigenpairs])
554
- # else:
555
- # final_eigvals, final_eigvecs = None, None
556
-
557
- # final_eigvals = comm.bcast(final_eigvals, root=0)
558
- # final_eigvecs = comm.bcast(final_eigvecs, root=0)
559
-
560
- # return final_eigvals, final_eigvecs
561
-
562
-
563
-
564
-
565
-
566
-
567
- # @profile
568
- # def parallel_tridiag_eigen(
569
- # diag,
570
- # off,
571
- # comm=None,
572
- # tol_factor=1e-16,
573
- # min_size=1,
574
- # depth=0,
575
- # profiler=None,
576
- # tol_QR=1e-8,
577
- # max_iterQR=5000,
578
- # ):
579
- # """
580
- # Computes eigenvalues and eigenvectors of a symmetric tridiagonal matrix.
581
- # Input:
582
- # -diag: diagonal part of the tridiagonal matrix
583
- # -off: off diagonal part of the tridiagonal matrix
584
- # -comm: MPI communicator
585
- # -tol_factor: tollerance for the deflating step
586
-
587
- # Output:
588
- # -final_eigvals: return the eigenvalues of the tridiagonal matrix
589
- # -final_eigvecs: return the eigenvectors of the tridiagonal matrix
590
-
591
- # """
592
-
593
- # if comm is None:
594
- # comm = MPI.COMM_WORLD
595
- # rank = comm.Get_rank()
596
- # size = comm.Get_size()
597
- # current_rank = MPI.COMM_WORLD.Get_rank()
598
- # n = len(diag)
599
- # prof_filename = f"Profile_folder/profile.rank{current_rank}.depth{depth}.lprof"
600
-
601
-
602
- # if n <= min_size or size == 1:
603
- # eigvals, eigvecs = QR_algorithm(diag, off, tol_QR, max_iterQR)
604
- # eigvecs = np.array(eigvecs)
605
- # eigvals = np.array(eigvals)
606
-
607
- # index_sort = np.argsort(eigvals)
608
- # eigvecs = eigvecs[:, index_sort]
609
- # eigvals = eigvals[index_sort]
610
- # return eigvals, eigvecs
611
-
612
- # k = n // 2
613
- # diag1, diag2 = diag[:k].copy(), diag[k:].copy()
614
- # off1 = off[: k - 1].copy() if k > 1 else np.array([])
615
- # off2 = off[k:] if k < n - 1 else np.array([])
616
- # beta = off[k - 1].copy()
617
-
618
- # diag1[-1] -= beta
619
- # diag2[0] -= beta
620
-
621
- # # Parallel Recursion
622
- # left_size = size // 2 if size > 1 else 1
623
- # color = 0 if rank < left_size else 1
624
- # subcomm = comm.Split(color=color, key=rank)
625
-
626
- # if color == 0:
627
- # eigvals_left, eigvecs_left = parallel_tridiag_eigen(
628
- # diag1,
629
- # off1,
630
- # comm=subcomm,
631
- # tol_factor=tol_factor,
632
- # min_size=min_size,
633
- # depth=depth + 1,
634
- # profiler=profiler,
635
- # )
636
- # else:
637
- # eigvals_right, eigvecs_right = parallel_tridiag_eigen(
638
- # diag2,
639
- # off2,
640
- # comm=subcomm,
641
- # tol_factor=tol_factor,
642
- # min_size=min_size,
643
- # depth=depth + 1,
644
- # profiler=profiler,
645
- # )
646
-
647
-
648
-
649
-
650
- # if rank == 0:
651
- # eigvals_right = comm.recv(source=left_size, tag=77)
652
- # eigvecs_right = comm.recv(source=left_size, tag=78)
653
- # elif rank == left_size:
654
- # comm.send(eigvals_right, dest=0, tag=77)
655
- # comm.send(eigvecs_right, dest=0, tag=78)
656
-
657
-
658
- # if rank == 0:
659
-
660
- # # Merge Step
661
- # n1 = len(eigvals_left)
662
- # D = np.concatenate((eigvals_left, eigvals_right))
663
- # v_vec = np.concatenate((eigvecs_left[-1, :], eigvecs_right[0, :]))
664
- # deflated_eigvals, deflated_eigvecs, D_keep, v_keep, P = deflate_eigenpairs_cxx(
665
- # D, v_vec, beta, tol_factor
666
- # )
667
- # D_keep=np.array(D_keep)
668
-
669
- # reduced_dim = len(D_keep)
670
-
671
- # if D_keep.size > 0:
672
- # idx = np.argsort(D_keep)
673
- # idx_inv = np.arange(0, reduced_dim)
674
- # idx_inv = idx_inv[idx]
675
-
676
- # lam, changing_position, delta = secular_solver_cxx(
677
- # beta, D_keep[idx], v_keep[idx], np.arange(reduced_dim)
678
- # )
679
- # lam = np.array(lam)
680
- # delta=np.array(delta)
681
- # changing_position=np.array(changing_position)
682
- # # #diff=lam_s-lam
683
- # else:
684
- # lam = np.array([])
685
-
686
-
687
- # for k in range(lam.size):
688
- # numerator = lam - D_keep[k]
689
- # denominator = np.concatenate((D_keep[:k], D_keep[k + 1 :])) - D_keep[k]
690
- # numerator[:-1] = numerator[:-1] / denominator
691
- # v_keep[k] = np.sqrt(np.abs(np.prod(numerator) / beta)) * np.sign(v_keep[k])
692
-
693
- # eigenpairs = []
694
-
695
- # for j in range(lam.size):
696
- # y = np.zeros(D.size)
697
- # # y[:reduced_dim]=v_keep/(lam[j]-D_keep)
698
- # # y /= np.linalg.norm(y)
699
-
700
- # diff = lam[j] - D_keep
701
- # diff[idx_inv[changing_position[j]]] = delta[j]
702
- # y[:reduced_dim] = v_keep / (diff)
703
- # y_norm = np.linalg.norm(y)
704
- # if y_norm > 1e-15:
705
- # y /= y_norm
706
-
707
- # y = P.T @ y
708
- # vec = np.concatenate((eigvecs_left @ y[:n1], eigvecs_right @ y[n1:]))
709
- # vec /= np.linalg.norm(vec)
710
- # eigenpairs.append((lam[j], vec))
711
-
712
- # for eigval, vec in zip(deflated_eigvals, deflated_eigvecs):
713
- # # vec = Q_block @ vec
714
- # vec = np.concatenate((eigvecs_left @ vec[:n1], eigvecs_right @ vec[n1:]))
715
- # eigenpairs.append((eigval, vec))
716
- # eigenpairs.sort(key=lambda x: x[0])
717
- # final_eigvals = np.array([ev for ev, _ in eigenpairs])
718
- # final_eigvecs = np.column_stack([vec for _, vec in eigenpairs])
719
- # else:
720
- # final_eigvals, final_eigvecs = None, None
721
-
722
- # final_eigvals = comm.bcast(final_eigvals, root=0)
723
- # final_eigvecs = comm.bcast(final_eigvecs, root=0)
724
-
725
- # return final_eigvals, final_eigvecs
726
-
727
-
728
-
729
-
730
-
731
-
732
-
733
552
734
553
def parallel_eigen (
735
554
main_diag , off_diag , tol_QR = 1e-15 , max_iterQR = 5000 , tol_deflation = 1e-15
@@ -752,17 +571,19 @@ def parallel_eigen(
752
571
if __name__ == "__main__" :
753
572
comm = MPI .COMM_WORLD
754
573
rank = comm .Get_rank ()
755
- n = 900
574
+ n = 100
756
575
if rank == 0 :
757
576
758
577
# import debugpy
759
578
# port = 5678 + rank # 5678 for rank 0, 5679 for rank 1
760
579
# debugpy.listen(("localhost", port))
761
580
# print(f"Rank {rank} waiting for debugger attach on port {port}")
762
581
# debugpy.wait_for_client()
763
- # np.random.seed(42)
764
- main_diag = np .ones (n , dtype = np .float64 ) * 2.0
765
- off_diag = np .ones (n - 1 , dtype = np .float64 ) * 1.0
582
+ np .random .seed (42 )
583
+ # main_diag = np.ones(n, dtype=np.float64) * 2.0
584
+ # off_diag = np.ones(n - 1, dtype=np.float64) *1.0
585
+ main_diag = (np .random .rand (n ) * 2 ).astype (np .float64 )
586
+ off_diag = (np .random .rand (n - 1 ) * 1 ).astype (np .float64 )
766
587
# eig = np.arange(1, n + 1)
767
588
# A = np.diag(eig)
768
589
# U = scipy.stats.ortho_group.rvs(n)
0 commit comments